Checking if an option exists in an MySQL enum column

2012
23
January

Although using MySQL enums is often discouraged I sometimes use them for their simplicity. Today however I stumbled upon one of the problems with enums. There is no simple method to determine all possible values of an enum column.

While it was easy enough to extract with a little creative PHP the solution is rather ugly. I'd much prefer to be able to write "SELECT options(enum_column) FROM table_name" which would then result in one row per option.

Until we come to our senses and stop using enums in MySQL I guess we are stuck with hacks like the following:



// First get the result of $query into variable $column using your prefered db abstraction.
// In my environment I use $db->fetch()
// You can user mysqli or pdo or whatever. Ex:
// $result = mysql_query(, $con);
// $column = mysql_fetch_row($result)

$query = "SHOW columns FROM table WHERE Field = 'enum_column'";
$column = $db->fetch($query);

// $column['Type'] will contain the definition for the enum and it will look something like:
// enum('value1', 'value2', 'value3')
// What we want to do is convert this in to an array. We could do this by replacing "enum" with array
// and then run the string through eval(). But since eval is a "dangerous" function we'll do it using json.
// So first, we do a little string replacing so that we end up with a string looking like:
// ["value1", "value2", "value3"]
//  We then pass that string to json_decode so that we get an array.
$options = json_decode(str_replace(
    array("enum(", ")", "'"),
    array("[", "]", '"'),
    $column['Type']
));

// Now that we have all the options in an array it's simple to test if a certain option is present.
if (in_array("foobar", $options))
{
    doSomething();
}

That's all folks!

A VirtualBox and Lighttpd caching quirk

2011
24
March

Being able to setup your own dev environment for the project you work on is a fairly important skill to posses.
Until recently I was of the conviction that every new developer joining a dev team should start by installing and configuring their own environment. That way new developers would understand the underlying structure and dependencies of the project.

While this has worked out for other projects I've been working on I've now learned that in some cases this is a bad idea. Such is the case for a large project that I'm currently working on. The project has gotten so complex that setting up a workstation with a complete dev environment can take 1-2 workdays. The task is also so quirky that it, in almost all cases, requires the assistance of a senior developer. On top of that the dev team has in the last month and a half grown with ~200%. You don't have to be a math professor to realize that this is a huge waste of time.

The solution we applied was to use VirtualBox to run a pre configured environment. This reduced the time it takes for a new developer to get to the point where they can contribute, to a few hours at most.
Great success!

The quirk

We did run in to a minor caching problem with VirtualBox and Lighttpd. When the following conditions were true, lighttpd would sometimes corrupt static files.

  • VirtualBox has a shared folder with the host system
  • Lighttpd (or Apache for that matter) reads files from the shared folder

Fortunately the solution was simple enough, just tell Lighttpd to use 'writev' to read files by adding the following line to lighttpd.conf.


server.network-backend = "writev"

:)

PHP: Capture vs Closures

2011
18
January

A colleague brought up an interesting question today, he asked which was better performance-wise using closures or using capturing with output control (ob_start() / ob_get_clean()). I expected closures would be better since there's a bit more going on behind the scenes when using output buffering, but I wasn't sure so I decided to make a little test.

The not so scientific test

Keeping it simple, the case was creating output data and then echo'ing it. In our project we use output buffering in order to render multiple views, layouts and whatnot, so these tests should be seen as functions that would run from a view script using output buffering. If you just want to send the output directly to the browser then the comparison would be echo vs closures in which case an echo would be quicker since you don't add the overhead of calling a function.

Three scripts were made, one using a closure, 1 using "echo ob_end_clean()" and another using "ob_end_flush()".


// using closure
$time = microtime();

$closure = function()
{
        $a = str_repeat("Hello", 4242);
        echo $a;
};
$closure();
unset($closure);
$endtime = microtime();
echo "\n\n" . ($endtime - $time), ' - ', memory_get_peak_usage(), ' - ', memory_get_usage(), "\n";

// using ob_end_clean()
$time = microtime();

ob_start();

    $a = str_repeat("Hello", 4242);
    echo $a;

echo ob_get_clean();

$endtime = microtime();
echo "\n\n" . ($endtime - $time), ' - ', memory_get_peak_usage(), ' - ', memory_get_usage(), "\n";

// using ob_end_flush()
$time = microtime();

ob_start();

    $a = str_repeat("Hello", 4242);
    echo $a;

ob_end_flush();

$endtime = microtime();
echo "\n\n" . ($endtime - $time), ' - ', memory_get_peak_usage(), ' - ', memory_get_usage(), "\n";

I ran the tests using "php -q filename.php". I know I should have run the scripts through xdebug or something but I was lazy so instead I just measured microtime, memory usage and peak memory usage as reported by PHP. Results will vary naturally vary based on platform and PHP compile settings/flags. I ran the test on my laptop, a mac book pro 2.2 ghz core 2 duo, with the default OS X installation of PHP.

The result

I ran each script 5 times in a row without any PHP cache or similar.
The overall results were pretty much as expected in favor of closures. But in reality only the peak memory usage would be an issue. The difference in rendering time was minimal and I doubt that you'd ever run in to any issues because of it. Even when using ob_end_clean to move the buffer in to a variable before outputting it, the added memory increase was lower than I expected.

time - peak - mem
0.001673 - 709648 - 645984 (capturing #1, ob_end_clean )
0.001406 - 688328 - 645880 (capturing #1, ob_end_flush)
0.001419 - 649288 - 625664 (closures #1)

0.001514 - 709648 - 645984 (capturing #2, ob_end_clean )
0.00149 - 688328 - 645880 (capturing #2, ob_end_flush)
0.001515 - 649288 - 625664 (closures #2)

0.001524 - 709648 - 645984 (capturing #3, ob_end_clean )
0.001217 - 688328 - 645880 (capturing #3, ob_end_flush)
0.001408 - 649288 - 625664 (closures #3)

0.001499 - 709648 - 645984 (capturing #4, ob_end_clean )
0.001502 - 688328 - 645880 (capturing #4, ob_end_flush)
0.001454 - 649288 - 625664 (closures #4)

0.00104 - 709648 - 645984 (capturing #5, ob_end_clean )
0.00148 - 688328 - 645880 (capturing #5, ob_end_flush)
0.001445 - 649288 - 625664 (closures #5)

The conclusion

So judging from this highly non scientific test my conclusion would be that in most cases it probably doesn't matter which you choose. Performance junkies should however use closures to keep memory waste to a minimum. But as with most things PHP, I guess it depends on the use case. If the case is a view script that will be handled by, designers / front-end developers / end users, rather than backend developers then I'd recommend capturing just because syntax is simpler and looks less intimidating for those not confident with PHP.

Securing the web with SSL Client Certificates

2011
5
January

When restricting access to web content or web applications, more often than not, basic username/password authentication is the solution. While this might be enough for a personal blog, sites with sensitive content will probably need a little more work.

A couple of commonly used and recommended options are restricting access by IP, limiting the number of login attempts, using captchas to combat bots, one time passwords etc. An option that is rarely mentioned is SSL Client Certificates.

By using SSL Client Certificates you deny access to all except those clients that have a valid certificate installed in their browser. For obvious reasons this method can not (conveniently) be used on a site where registration is public, for instance social sites like Twitter or Facebook. Intranets and administration tools are typically used only by a select few users that are known to the site administrator, in these cases SSL Client Certificates are a great option.

The first step in getting SSL Client Certificate authentication up and running for your application is getting it working on your dev machine, something I had to do myself the other day. Symantec provides a great SSL guide for Apache. It's quite extensive so I'm going to recap the steps involved in getting a development environment up and running on your local machine.

I'm going to assume that you already have openssl and apache2 installed. I'm also going to assume that you are running a UN*X system since that's what all cool developers do ;)

Creating the SSL Certificates

We'll start by creating the SSL certificates. We need one for the web application, another one for signing our client certificates and then a third for our client. Assuming we only have one client that is. The first certificate is for the server. This is required for basic SSL (https) functionality. In this example we'll create a self signed certificate but for your live servers you should use a certificate signed by a trusted CA (such as Verisign). Read the semantic article series mentioned above to learn more about this.


openssl req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes -keyout ssl/server.key -out ssl/server.crt -subj '/O=Seccure/OU=Seccure Labs/CN=test.local'

The above will create two files, server.key and server.crt. Notice that at the end I add the hostname of the server (or vhost) that we want to create a certificate for. In the example I use test.local, you should change this to whatever you are using. Move server.crt and server.key to a directory called 'ssl' inside your apache configuration folder. If ssl doesn't exist create it. example: /etc/apache2/ssl/

The next two certificates involve a few extra steps. First we need to create a local Certification Authority which basically mean we make a certificate that we'll use to sign other certificates. The second step is creating and signing the client certificate.

We start by jumping to a folder in which we can fool around, I'll use /tmp/ssl/.


#mkdir -p ssl-ca/certs
#mkdir -p ssl-ca/crl
mkdir -p ssl-ca/requests
mkdir -p ssl-ca/private
mkdir -p ssl-ca/newcerts
echo "01" > ssl-ca/serial
touch ssl-ca/index.txt
touch ssl-ca/openssl.cnf
mkdir clients

Now we need to create the openssl configuration, open ssl-ca/openssl.cnf in your favorite editor and add the configuration settings below. Note that you have to change the path to your ssl-ca folder if you don't use the same one I did.


RANDFILE         = /dev/urandom 

[ ca ]
default_ca       = CA_default

[ CA_default ]
dir              = /tmp/ssl/ssl-ca
certs            = $dir/certs
new_certs_dir    = $dir/newcerts
crl_dir          = $dir/crl
database         = $dir/index.txt
private_key      = $dir/private/ca.key
certificate      = $dir/ca.crt
serial           = $dir/serial
crl              = $dir/crl.pem
RANDFILE         = $dir/private/.rand
default_days     = 365
default_crl_days = 30
default_md       = sha1
preserve         = no
policy           = policy_anything
name_opt         = ca_default
cert_opt         = ca_default

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits            = 1024
default_md              = sha1
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
x509_extensions         = v3_ca
string_mask             = nombstr

[ req_distinguished_name ]
countryName             = Country Name (2 letter code)
countryName_min         = 2
countryName_max         = 2
stateOrProvinceName     = State or Province Name (full name)
localityName            = Locality Name (eg, city)
0.organizationName      = Organization Name (eg, company)
organizationalUnitName  = Organizational Unit Name (eg, section)
commonName              = Common Name (eg, YOUR name)
commonName_max          = 64
emailAddress            = Email Address
emailAddress_max        = 64

[ usr_cert ]
basicConstraints        = CA:FALSE

[ ssl_server ]
basicConstraints        = CA:FALSE
nsCertType              = server
keyUsage                = digitalSignature, keyEncipherment 
extendedKeyUsage        = serverAuth, nsSGC, msSGC
nsComment               = "OpenSSL Certificate for SSL Web Server"

[ ssl_client ]
basicConstraints        = CA:FALSE
nsCertType              = client
keyUsage                = digitalSignature, keyEncipherment
extendedKeyUsage        = clientAuth
nsComment               = "OpenSSL Certificate for SSL Client"

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage         = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]
basicConstraints        = critical, CA:true, pathlen:0 
nsCertType              = sslCA
keyUsage                = cRLSign, keyCertSign
extendedKeyUsage        = serverAuth, clientAuth
nsComment               = "OpenSSL CA Certificate"

[ crl_ext ]
basicConstraints        = CA:FALSE
keyUsage                = digitalSignature, keyEncipherment
nsComment               = "OpenSSL generated CRL"

Time to create the CA certificate.


cd ssl-ca
openssl req -config openssl.cnf -new -x509 -days 3652 -sha1 -newkey rsa:1024 -keyout private/ca.key -out ca.crt -subj '/O=Seccure/OU=Seccure Root CA'

Time to create and sign the client certificate.


cd /tmp/ssl/clients/
openssl req -new -sha1 -newkey rsa:1024 -nodes -keyout testuser.key -out testuser.pem -subj '/O=Seccure/OU=Seccure Labs/CN=TestUser'

This time we have to sign the certificate with our CA certificate. Only certificates signed by us will have access to our web application.


mv testuser.pem ../ssl-ca/requests/
cd ../ssl-ca/
openssl ca -config openssl.cnf -policy policy_anything -extensions ssl_client -out requests/signed.pem -infiles requests/testuser.pem

In this step we export the certificate to a format that your browser can use, namely PKCS#12.


mv requests/signed.pem /usr/ssl/clients/testuser.pem
openssl pkcs12 -export -clcerts -in testuser.pem -inkey testuser.key -out testuser.p12

You should now have 3 certificates(files), server.crt, ca.crt and testuser.p12.

Configuring Apache for SSL

Now that our required certificates are created we can put it all together. We start by enabling SSL in Apache. Open up your httpd.conf in you favorite editor and add the following.


Listen 443

AddType application/x-x509-ca-cert .crt
#AddType application/x-pkcs7-crl    .crl

#SSLPassPhraseDialog  builtin
SSLSessionCache        "shmcb:/var/run/ssl_scache(512000)"
SSLSessionCacheTimeout  300
SSLMutex  "file:/var/run/ssl_mutex"
SSLOptions +StrictRequire 

SSLProtocol +all
SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM
SSLCipherSuite HIGH:MEDIUM:EXP:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM:+EXP 

The values for SSLSessionCache and SSLMutex may vary depending on platform. You probably have defaults for them in the file extras/httpd-ssl.conf in your apache configuration folder. Somewhere in httpd.conf you should have a LoadModule directive for mod_ssl.so. Make sure that row is uncommented.


LoadModule ssl_module libexec/apache2/mod_ssl.so

We also have to configure our site to use SSL. In my case I'm setting up the web application as a virtual host.


<VirtualHost test.local:443>
        ServerName test.local
        DocumentRoot "/home/www/test/"

                SSLEngine on 
                SSLCertificateFile /etc/apache2/ssl/server.crt
                SSLCertificateKeyFile /etc/apache2/ssl/server.key
                SSLOptions +ExportCertData
                SSLCACertificateFile /etc/apache2/ssl/ca.crt
                SSLVerifyClient require

    <Directory "/home/www/test/">
         SSLRequireSSL
         Options Indexes FollowSymLinks
         AllowOverride All
         Order allow,deny
         Allow from all
    </Directory>
</VirtualHost>

If you've been paying attention you've noticed that we reference two of our certificates in the configuration above.
The SSLVerifyClient directive tells apache to require a valid SSL Client Certificate while SSLCACertificateFile tells Apache which CA certificate the client certificates should be signed with. We've already moved server.crt and server.key in to the right place. Now lets do the same with ca.crt.


cp /tmp/ssl/ssl-ca/ca.crt /etc/apache2/ssl/

That takes care of our server configuration. Restart Apache and make sure no errors turned up in the logs. If you load up the site in your browser you should now be denied access. The actual error given may vary, in my case it says 'SSL connection error'. To fix this we need to import our client certificate in the browser. The procedure may vary from browser to browser. I'll use Firefox as an example since that's my browser of choice.

Importing the SSL Client certificate into your browser

The final step is telling our browser to use the client certificate. In Firefox this is done by importing the certificate. It's probably just as simple in other browsers.

In "Preferences / Advanced / Encryption" you have a "View Certificates" button. Clicking that opens up a window with a list and a bunch of buttons. At the top you have a menu with the option "Your Certificates". Click that item and then on the "Import" button near the bottom of the window. This will open a file selection dialog. Select the browser prepared certificate (testuser.p12) and click open.

Thats it, you have now completed all the steps and should be able to access your secured web application. To improve it further you could modify your application so that each of your users are tied to a specific client certificate. But I'll save that subject for another blog post.

Stay tuned and happy hacking.

Getting Flattr to play nice with your WordPress 3 setup

2010
20
December

If you are experiencing problems using the Flattr plugin with WordPress then it's very likely that you are using a plugin or a theme that is incompatible with the Flattr plugin. More often than not your issue will be related to excerpts. Because of how WordPress and most other blog engines handles plugins it's difficult to write a plugin that is compatible with all other plugins.

When trying to resolve a conflict between two plugins the answer is usually one of two solutions.
1) Disable one of the plugins. This is the easiest fix but not really the answer since you want the functionality of both.

2) Patch one or both of the plugins with a case specific fix. Example: plugin1 could check for the presence of plugin2 and if found disable or modify the behavior of the conflicting function in itself. This option is highly impractical since there is an endless amount of WordPress plugins out there and maintaining compatibility with them all is futile at best.

So what is the solution then? Well unfortunately there is no easy fix for this, if there is I simply don't know about it. But you don't have to give up. Often you can get the functionality you are after with a little manual labor (read: coding).

The Flattr plugin

In the case of the Flattr plugin the function that people have problems with is the auto injection of the button. If we disable all auto injection we can still render the button by adding a piece of code to the template without the risk of getting conflicts with other plugins.

I know some people will think that it's to difficult or impractical to edit the theme, but it really isn't, in fact It's easy as pie. Most of you will change your theme maybe once a year or perhaps never so you can't say that it's impractical either. And since virtually all WordPress plugins follow the same schematic, learning how to change it in one means you know how to do it in all others as well.

Modifying the theme

WordPress themes consist of a handful of template files. Each template has a specific name and purpose regardless of the theme. This schematic is decided by the makers of WordPress so it's unlikely to change between themes. For our purpose we need to focus on the template single.php.

single.php (or sometimes single-post.php) is used to display a single post and this is, in my opinion, the best place to put your Flattr button. Open the file in your favorite text editor and search for the row containing "the_content();". This function call is what outputs the contents of your post to the browser. So this is also a good place to put the Flattr button. Depending on wether you would like the flattr button to render above or below the content place "the_flattr_permalink()" function call before or after the "the_content();". It should now look something like this . That is all there is to it, you should now have a Flattr button in your post.

Sometimes you might want to put the Flattr button on pages where multiple posts are displayed. There is some inconsistency when it comes to which template file that is used for those pages. But the idea is the same as above. Look for a call to the_content() or the_excerpt() and if you find it then you know where to place the Flattr button code. Depending on your theme, WordPress version the template files to look in could be: index.php, loop.php, loop-index.php or search.php. If you can't seem to find it just search in each file, it's in there somewhere.

For the handy ones theres also the "get_the_flattr_permalink()" call that will return the code of the button instead of outputting it directly. This might be usefull if you want to make changes to the button html before it gets sent to the browser.

Links:
Flattr plugin at WordPress.org
Flattr plugin at GitHub (Not always up to date)