Archive for the category “Tips”

June 17th, 2008 at 11:58 am

Restore SSH Public Key

Today I did something stupid: I overwrote an SSH public key with a file from a different machine:

CODE:
  1. scp id_rsa.pub user@example.org:~/.ssh

Obviously, I wanted to place the Public Key for the account from one machine on the other one to append it to the authorized_keys file of the target account. Unfortunately, I didn't bear in mind that I already had a public key file (id_rsa.pub) in this directory. So I had to re-create the Public Key file from the Private Key. This is quite easy, it appears that the SSH developers already thought of this situation. The following code will restore the Public Key file from the Private Key (example for an RSA key):

CODE:
  1. cd ~/.ssh; echo "id_rsa" | ssh-keygen -y> id_rsa.pub 2>/dev/null

January 12th, 2008 at 6:23 pm

Looks like document root, but is in a subfolder

Are you using Google Sitemaps, and does your website have very many pages? Then you will usually have a sitemap index file along with a number of sitemap files in your document root. Now, you might want to tidy up and move those sitemap files to a subfolder -- but that doesn't work, as Google requires the sitemap files to be in the document root. What to do? You can use mod_rewrite to solve this:

Create the directory gg_sitemaps and move your sitemaps index as well as all your sitemap files there.

Add the following line to the file .htaccess in your document root (if it doesn't exists, create it):

CODE:
  1. RewriteRule ^(sitemap.*)$ /gg_sitemaps/$1 [L]

(Note: This assumes that your sitemap index and the sitemaps files start with the string sitemap, e.g. your sitemap index file it could be sitemaps.xml, while the sitemaps files could be sitemap0.xml, sitemap1.xml and so on.)

Now your sitemaps are out of the document root, but Google will still see them as if they were in there.

By the way, this also works for the Google sitemaps verification files: If you want to verify your site in Google Webmasters, you need to upload a file to your document root. (You could also add a meta tag, but that's not so good.) Adding a single file isn't a problem, but if you want to allow different people to manage this domain in different Google Webmaster accounts, or if you have multiple domains in the same document root, you will need to upload more than one file. Again, we can solve this with some mod_rewrite magic:

Create the directory gg_verify and move all your verification files there.

Add another line to the file .htaccess in your document root:

CODE:
  1. RewriteRule (^google.*$) /gg_verify/$1 [L]

Again, Google will think, the respective file is in the document root, while actually it is in the designated subfolder.

December 18th, 2007 at 10:07 am

Improve loading speed of webpages by compressing HTML

Here's a simple HTML "compressor" in PHP, which will reduce the size of HTML served to the client by 10 to 20 percent, depending on your indentation style and commenting. If many of your readers have lousy bandwidth, the slight overhead of this method is worth it.

PHP:
  1. <?php
  2.     function compress($content)
  3.     {
  4.         $content = preg_replace('/[\n\t\s]+/s', ' ', $content);
  5.         $content = preg_replace('/<!--.*?-->/s', '', $content);
  6.         return $content;
  7.     }
  8.  
  9.     ob_start();
  10.     require "/var/www/htdocs/somefile.php";
  11.     $content = ob_get_contents();
  12.     ob_end_clean();
  13.  
  14.     echo compress($content);
  15. ?>

By the way, if you have a rather hungry dynamic application (e.g. WordPress with certain plugins) on a rather weak server, consider using a caching solution like 1 Blog Cacher, so you don't have to regenerate the pages everytime somebody retrieves them. And, of course, consider using output gzip compression -- be it via webserver modules such as mod_gzip/mod_deflate or based on your web application.

December 17th, 2007 at 4:31 pm

Copying is expensive, moving is cheap

When you replace a comprehensive file tree via FTP, you will realize that it takes some time to do all the uploading. If your upload is going to replace old content, then one would usually first delete the old content, then upload the new one. (It is not a good idea to let the FTP client overwrite old contents, unless one knows exactly how the client behaves. For example, some clients merge existing trees, not deleting old files that are expunged rather than replaced, thus potentially raising security problems.)

However, the procedure of first deleting and then copying can leave your site naked or uncomplete for a couple of endless minutes. In the worst case, a user retrieves a page from your incomplete site and causes a database corruption or messes up the internal settings (this is not too unlikely with CMS applications). Therefore, the better way is to first upload the new content under a different name and then rename folders.

For example, if your web documents are in /var/www/docroot/, you would usually do the following: You delete everything in that directory and then upload the new content -- which has the above mentioned side effects. Instead, you should better do the following: Upload all new content to /var/www/docroot_new/, rename /var/www/docroot/ to /var/www/docroot_old/, finally rename /var/www/docroot_new/ to /var/www/docroot/. Afterwards, you can delete /var/www/docroot_old/. Renaming is very fast, as only the base directory's name has to be changed in the filesystem.

With this method, your website will only be naked for a few seconds, and there won't be an incomplete installation at any time.

December 12th, 2007 at 12:47 pm

Playing with xgettext

xgettext is a great shell tool to create po files (i.e. Gettext translation templates). It is also able to merge existing translations with new strings. For example, to create a po template from all PHP files in a directory tree and preserve already done translations from the file my_translation-de_DE.po, enter:

CODE:
  1. mv my_translation-de_DE.po messages.po
  2. find . -type f -iname "*.php" | xgettext --keyword=__ --keyword=_e -j -f -
  3. mv messages.po my_translation-de_DE.po

Now you have a new my_translation-de_DE.po, with all the translated and the newly added strings appended to this file. (The --keywords parameter is very useful to specify your translation function(s), because if you do so, xgettext will not extract all the other strings, too.)

Unfortunately, xgettext is not able to expunge strings that are no longer existing. This behaviour is easy to explain: In many cases, you might be doing an incremental update of your translation template (i.e. you only add the strings for a subset of your files). If xgettext would expunge the translations for which no sting wasn't found in your code, you would always have to recreate the po template completely. Anyway, a little option to expunge translations that weren't found in the original, would be nice.

A little trick will at least help to determine the strings that do no longer exist: Open the po file to be merged and delete all #: lines (the regex ^#:.*$ will match them). Then merge the files as usual. In the new file, all messages without a #: marker do no longer exist. You can even modify the above code to do so automatically:

CODE:
  1. grep -v "^#:" my_translation-de_DE.po> messages.po
  2. find . -type f -iname "*.php" | xgettext --keyword=__ --keyword=_e -j -f -
  3. mv messages.po my_translation-de_DE.po

This way, you will preserve your translations, but your references are recreated, and you can easily see which strings do not exist anymore.

Update, 16.04.08: When I wrote this post, I didn't know about the msgmerge tool. Using it is much better than the grep foo above. Use it as follows:

CODE:
  1. echo ''> messages.po # xgettext needs that file, and we need it empty
  2. find . -type f -iname "*.php" | xgettext --keyword=__ --keyword=_e -j -f -
  3. msgmerge -N existing.po messages.po> new.po
  4. mv new.po existing.po
  5. rm messages.po

It looks a bit more complex, but it's the best generic solution I can provide. Note the -N parameter for msgmerge: It suppresses the fuzzy mode, which yields more confusion and extra work than anything else.