Paperclip: Deleting attachments from views

If you use Paperclip to manage your attachments in Rails, you may find it useful to have a “delete this attachment” feature in your views. For instance, if you have a User model with has_attached_file :avatar, this is how to add the delete option:

Model:

class User < ActiveRecord::Base
  attr_accessor :avatar_remove
  has_attached_file :avatar, :styles => { :profile => "190x>", :small => "100x100>" }
  # …
  def avatar_remove=(remove)
    self.avatar = nil if remove == ‘1’
  end
end

In the view, just use “check_box :avatar_remove” - when the user checks the checkbox and you call update_params in the controller, avatar_remove will be set in the model, i.e. avatar_remove=1 will be called and this will set self.avatar to nil and therefore delete the attached avatar file.

How to install TeamSpeak 3 on a FreeBSD 64-bit server

The TeamSpeak 3 server is available for Linux 64 and FreeBSD 32, but not for FreeBSD 64. So if you have a FreeBSD 64-bit server, there are three possibilities:

  • Don’t use TeamSpeak, but the open-source Mumble (recommended) and install it using ports.
  • Install Linux binary compatibility and use the 64-bit Linux version.
  • Install the 32-bit FreeBSD version.

How to install TeamSpeak 3 (32 bit) on FreeBSD (64 bit)

  1. Install the 32-bit base libs (distribution lib32) using sysinstall.
  2. Download the 32-bit libiconv package and put the libiconv.so.* into, for example /opt/teamspeak/lib
  3. Add /opt/teamspeak/lib to your 32-bit library path using ldconfig -32 -m /opt/teamspeak/lib
  4. Download and put teamspeak into /opt/teamspeak/ts3_server
  5. Add /opt/teamspeak/ts3_server to your 32-bit library path (shouldn’t be necessary, but the startup script doesn’t work for me)
  6. Create a teamspeak user without shell, home directory, password
  7. Start Teamspeak with cd /opt/teamspeak/ts3_server; daemon -u teamspeak /opt/teamspeak/ts3_server (you can put this into /etc/rc.local or write a startup script)

Dealing with WPA2, WEP-only devices, Ubuntu and DD-WRT

If you have a WLAN router that runs DD-WRT (or OpenWRT), you probably want to protect your wireless LAN with WPA2. However, there are some devices that only support WEP (for instance, some old wireless NICs that even don’t support WPA or don’t support it with Linux - the D-Link G520+ is such a bad example).

It’s possible to get WPA2 while using WEP for some devices at the same time

First, it’s important to know that you can set your router to support WPA2 and WEP at the same time. If you use DD-WRT, you can go to Wireless / Basic Settings and create two networks - a primary one (it will be used for WPA2), then add a “virtual interface” and set it to another SSID.

Then go to Wireless / Wireless Security and set WPA2 Personal (or whatever you like) for the primary interface, WEP for the virtual interface. Set the passwords as you like. Make sure that the credentials are very different because the WEP keys can be cracked easily.

Now, you have configured:

  1. a secure way to connect (your WPA2 network)
  2. an insecure way to connect that can be cracked easily (WEP network)

Introducing VPN for the WEP network

To secure communication on the WEP network, we will use a VPN. First of all, we define a new subnet for our WEP network:

“Wireless” / “Basic settings” / Virtual interface wl0.1: Choose

  • AP isolation: enabled (this will prevent hackers who cracked the WEP key from hacking into other WEP devices in your network)
  • network configuration: unbridged (otherwise the WEP WLAN would be connected to your default one)
  • multicast forwarding: disabled
  • masquerade / NAT: disabled
  • IP address: your router’s IP address in the new subnet (shouldn’t be an existing address), for instance 192.168.2.1
  • subnet mask: for instance 255.255.255.0 (choose another one only if you know what it is)

Then activate the VPN server: “Services” / “VPN” / “PPTP Server”:

  • PPTP Server: enable
  • Force MPPE encryption (will ensure that the VPN is really encrypted, otherwise it won’t bring any additional security)
  • Server IP: use the IP address of the wl0.1 interface (in our example: 192.168.2.1)
  • Client IPs: use the IP range of your default subnet, but not in the DHCP range. For instance, if your normal network has 192.168.1.* addresses (default) and the DHCP server gives addresses beginning from .100 (default), you could use “192.168.1.20-192.168.1.49” for this setting. This would allow 29 VPN clients in your network and doesn’t collide with DHCP leases.
  • CHAP secrets: Enter at least one line in the format “username * password *” (without ” but with *, replace username and password with your values).

VPN client on your WEP-only device (assuming it’s running Ubuntu Linux 10.04):

  • Connect to the WEP network, but set the IP address for the connection manually (for instance, 192.168.2.2 in our example)
  • In the network manager, create a new VPN connection. Use these settings:
    Gateway: your VPN server’s address (192.168.1.2 in our example)
    User name and password as set in CHAP secrets
    Advanced: Use point-to-point encryption (MPPE) , security: 128-bit (most secure)
  • Then you can connect to the VPN as soon as your are connected to the WEP network.
  • As soon as you are connected to the VPN server, your data can’t be read anymore by anyone using the weakly secured WEP connection!
  • Unfortunately, you can’t use the “Automatically connect” feature for the VPN because of a bug in NetworkManager. You can get a script and place it in the dispatcher directory. For more information, see https://bugs.launchpad.net/ubuntu/+source/network-manager/+bug/280571

Protecting your network from WEP intruders

If somebody hacks the WEP connection, the intruder shouldn’t be able to access the Internet using the WEP network. So, go to “Administration” / “Commands”, enter:

echo "0" > /proc/sys/net/ipv4/conf/wl0.1/forwarding

Click on “Save startup”, then reboot the router (or run this command)

Creating images for HTML emails with GIMP

If you’re designing HTML emails (for instance, newsletters or other mails that are not created with a Mail User Agent), you will know that you have to use HTML 3.2 because of Outlook 2007 and its strange Word 2007 rendering. (By the way, I’d even extend Microsoft’s argument that Word is better for security reasons because it doesn’t understand scripts and suggest using Word 2007 as the default browser for every computer.)

In Word/Outlook 2007 Background images are only accepted in this format:

<body background="URI to image, may be cid: for attached images>

But this is no news. For me, it became really strange when I used GIMP in Linux to create an image that was intended as a background for an HTML email message.

Word is designed for printing. Are emails too?

I created an image with 10.000 px width where the real graphical content was 700 px wide, filled up with white space. Then I wrote:

<body background="cid:img">
<table background="cid:img" cellspacing="0" cellpadding="0">

Sending this to Outlook 2007, it was all OK but the graphical content was much more than 600 px wide.

After playing around, I had the idea that this problem could be related to printing and DPI settings in some way. So I found out that GIMP creates images with 72 dpi per default (you can’t see this except in the images headers because the size in pixels is always the same). For more information about dpi, resolution and when its use makes sense (or not), see this German article: Dpi, Missverständnisse und Erklärung. Then, Outlook tries to render this image on the “printed” screen where the email is displayed (remember, Outlook uses Word and Word is a text processor, not an Internet browser) and so rescales it to get 96 dpi.

The solution: Open GIMP, load the image, set it to 96 dpi and save it again. You won’t note a difference, but Outlook 2007 does — it should work now (as long as users don’t change their default Windows dpi setting, see link above).

Of course, Microsoft, Outlook, Outlook Express, Office, Word, Internet Explorer, and all other trademarks and registered trademarks are properties of their respective owners. GIMP is free software.

Typo3: show login page for protected pages when user not is logged in

The problem: If you have pages which are only accessible for certain FE user groups, some of your users may bookmark these protected pages and return when they are not logged in (or you may send the URLs in a newsletter, etc.). Typo3 handles this case as a “404 Page not found” situation (I don’t know why they think 401/403 and 404 are the same, but I can’t change it).

So if you want to show a login form in this case, but a 404 error page if the page is “really” not there, you have to write a user-defined page-not-found-handling function. I have put it into fileadmin/404.php:

 
define(LOGIN_URL, "http://yourpage/login.0.html");
define(NOTFOUND_URL, "http://yourpage");
 
class user_pageNotFound {
function pageNotFound($param, $ref) {
if (count($param["pageAccessFailureReasons"]["fe_group"])) {
header("HTTP/1.0 403 Forbidden");
$url = LOGIN_URL."?redirect_url=".$param["currentUrl"];
} else
$url = NOTFOUND_URL;
print file_get_contents($url);
}
}

Then set this in your typo3conf/localconf.php:

$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] =
'USER_FUNCTION:fileadmin/404.php:user_pageNotFound->pageNotFound';

Put a felogin content element onto the login page (here: login.0.html) and set the redirect options like to: login,loginGroup,getpost

So, what happens if the user goes to a protected page when (s)he is not logged in?

  1. Typo3 detects that the page is not accessible and calls our page not found handler.
  2. The handler detects that it is not a real 404 error but the page is proected and redirects to login.0.html?redirect_url=<original url>
  3. The user logs on.
  4. Because getpost is set as a redirect option, the user comes back to <original url>.

Important hint: It took me hours to find out that the redirect options don’t work if the login page has front end user group privileges set. It seems to work only if it’s on a public page.

Also make sure that the LOGIN_URL is found on the system, or you will have a recursive loop calling the 404 page.

Typo3: htmlRTE “Zebra” tables (classes for odd/even rows) using TSConfig

It took me some hours and the documentation is not very good, but finally I have found out how to mark up table rows from RTE tables (not elements with content type “table”) with alternating CSS classes. Put this into your page TSConfig:

RTE.classes.zebra-rows {
  name = Zebra table
  alternating.rows {
    startAt = 1
    oddClass = odd
    evenClass = even
  }
}

RTE.default {
  ignoreMainStyleOverride = 0
  inlineStyle.zebra-tables (
    table.zebra-rows { }
    table.zebra-rows tr { background: lime; } /* or whatever color */
    table.zebra-rows tr.odd { background: red; } /* or whatever color */
  )
  classesTable = zebra-rows
  classesTR = odd, even
  proc.allowedClasses := addToList(zebra-rows, odd, even)
)

Then you only have to assign the block style “Zebra table” in the RTE.

It is also be possible to put the styling into a content CSS file. In that case, you have to set ignoreMainStyleOverride=1, contentCSS=path/to/content.css and then omit the inlineStyle lines.

For ideal table processing, put this into your TypoScript setup (not TSConfig):

lib.parseFunc_RTE.externalBlocks = ul,ol,table
lib.parseFunc_RTE.externalBlocks.table.stdWrap.HTMLparser.tags.table.fixAttrib.class.list >
lib.parseFunc_RTE.externalBlocks.table.HTMLtableCells.default.callRecursive = 0
lib.parseFunc_RTE.externalBlocks.table.HTMLtableCells.default.stdWrap.parseFunc {
  makelinks = 1
  makelinks.http.keep = scheme,path,query
  makelinks.mailto.keep = path
  tags {
    link = TEXT
    link {
      current = 1
      typolink.parameter.data = parameters : allParams
    }
  }
}

It makes the table class zebra-rows working and prevents wrapping table cells with <p> etc. while keeping links intact.

Have fun!

IE6: AlphaImageLoader rendering problem when 3D acceleration available

If you ever had the pain to code Web designs with the goal to support IE6, you will know the AlphaImageLoader workaround to “emulate” transparent PNGs. Of course, this workaround brings new problems, for instance the problem that links are not clickable when positioned over a AlphaImageLoader PNG. This can be fixed with position: relative.

You won’t believe it …

However, I discovered a fairly new problem that surprised even me: there’s a bug with ImageAlphaLoader that hides part of Web pages when and only when 3D hardware acceleration is available. You can test this with 2 environments:

  • A Windows XP installation without hardware graphics acceleration available. For instance, use a normal virtual machine (VirtualBox).
  • A Windows XP installation with acceleration available. For instance, use a native WinXP installation with ATI/Nvidia drivers or VirtualBox with the experimental 3D acceleration support.

Sample

I can’t post the full HTML/CSS code because it involves images that don’t belong to me (that’s the reason why the screenshots are blurred) and I don’t want to invest the time and make a proof-of-concept file only for a stupid IE bug. But I have made two screenshots:

  1. Loaded the page in IE6
  2. Maximized
  3. Restored => display bug in action (see screenshot 1)

Page rendered with bug

The second screenshot shows the correctly rendered page using the workaround below:

Correctly rendered page

My workaround

I had the idea to force a redraw by using something like * { zoom: 1; } in the IE6 stylesheet, and to my surprise, it seemed to work.

Typo3 acceleration experience

How to accelerate Typo3 for a page with relative high load?

No statistically significant data but just a few benchmarks (made with ab) for the feeling:

Typo3 (no_cache = 1): ~ 1 rq/s
Typo3 (with cache): ~ 3 rq/s
Typo3 (with cache and eAccelerator): ~ 50 rq/s
Typo3 (with cache, eAccelerator and Squid reverse proxy): ~ 2000 rq/s

Creating an empty Typo3/4.2 installation that supports UTF-8

I always use UTF-8 with my Typo3 installations even if it’s not needed in the first version of the Web site because translation is a requirement often arises at a later time.

The way I create my new, empty Typo3 4.2 installation that fully supports UTF-8:

  • Create the database with
    CREATE DATABASE tt_new_site DEFAULT CHARSET 'UTF-8';
    GRANT ALL ON tt_new_site.* TO 'new_site'@'localhost' IDENTIFIED BY 'password';
  • Unzip the dummy.zip from typo3.org into the new installation’s directory
  • Create correct typo3_src symlink
  • Set permissions correctly (I made a script for this)
  • Create typo3conf/ENABLE_INSTALL_TOOL
  • Do necessary Web server setup
  • Go to http://new_site/
  • Do not use the 1-2-3 setup, but go to the Install Tool directly
  • In “Basic Configuration”, set database name + username, password, host, site name, encryption key, [GFX][gdlib_png], [GFX][TTFdpi]=96
  • In “Update Wizard”, “upgrade” to the newest Typo3 version. This will do nothing other than setting compatibility mode to Typo3 4.2 in localconf.php.
  • In “All Configuration”, set [BE][forceCharset]=utf8, [SYS][no_pconnect]=1.
  • In “Database Analyser”, choose “COMPARE” and let Typo3 create the tables. Because we have specified UTF-8 as the database’s default character set and also set forceCharset correctly, the tables will be created with the UTF-8 character set. Then “Create admin user” (don’t use admin as the user name for security reasons).
  • Log in to the back end, do the things to remove the 3 warnings (comment the $TYPO3_CONF_VARS[‘BE’][‘installToolPassword’] line in typo3conf/localconf.php, remove typo3conf/ENABLE_INSTALL_TOOL and run the reference check).
  • Now you’ve got a fresh Typo3 installation with all basic settings done, including UTF-8 support.

Some extensions have problems with UTF-8. For instance, I run into problems with qcom_html_cleaner, don’t use it until the UTF-8 problems are fixed.

Comparing myisam_suggest with a book’s index

Recently I had an idea how to illustrate how myisam_suggest works by a comparison with a normal printed book’s index:

“AutoSuggest” for a printed book

Image you have a thick book with hundreds of thousands of words in it. Now you want to know all words beginning with “fu” for some reason (= AutoSuggest).

Without the (full-text) index on the book’s last pages, you’d have to read the whole book, remember all words, sort them alphabetically, erase duplicates and then look at the words beginning with “fu”. A very time-intensive process.

However, if an index is available, you can just scroll to the index, scroll further to “f”, then “fu” and read the words there (ignoring the referenced page numbers). Takes almost no time.

AutoSuggest for MyISAM tables

The same process applies to MyISAM tables, too. Without full-text index, all tables would have to be scanned with something like WHERE description LIKE “% fu%” which would take unacceptable time and resources.

But with full-text index, there’s already a sorted list with all words where you can scroll to and then read all entries beginning with “fu” (in this case, ignoring the referenced records instead of the referenced pages). This is exactly what myisam_suggest does.

Image | WordPress Themes