Author Archive

DD-WRT in Repeater Bridge mode

ddwrt

DD-WRT is a third party developed firmware, released under the terms of the GPL for many ieee802.11a/b/g/h/n wireless routers based on a Broadcom or Atheros chip reference design. — DD-WRT wiki

Today we are discussing DD-WRT and specifically how you can do some cool stuff that you would not be able to do with your current wireless router. Chances are that your home router is compatible with DD-WRT. You can find this out by checking the DD-WRT router database. With DD-WRT firmware loaded, your router is able to do some tricks it might not be able to do before. One of these things might involve the repeater bridge mode, which can improve your WiFi range at home. Since devices are automatically switching between WiFi and 3G, especially since the 3G prices (in the Netherlands) are quite high and/or low data traffic limits apply, this mode is a necessity.

So what is the plan? Let’s assume you have a living room with an (non wireless) Internet modem, a server, a printer and a laptop. In your study you have another three PC’s. You need a Mac, a Windows PC and a Linux computer right? Occasionally you bring your laptop from the living room. Let’s assume your wife (or husband) did not allow you to put a nice fast gigabit cable connection between your living room and the study, because he/she feels the cables do not match the interior design. Obviously there is no arguing and you need to go wireless. The fastest wireless connections you get now follow the N standard with a theoretical maximum of 300 Mbps. In reality you will probably only get a fraction of that, because of the distance you need to cover. In my house I get about 25 Mbit with going one floor up and passing a bathroom. But anyway, this would be the network layout you can build using DD-WRT on you router:

Repeater_Bridge

The funny poles are actually DD-WRT routers and one is configured as the primary. If your modem has wireless and a switch you can just leave that primary router out, since it is just configured as a standard access point. The secondary is actually a DD-WRT router in repeater bridge mode. This means it connects to the access point by wireless and then announces it’s own SSID (e.g. “wifi-study”) whereas the primary announces the “wifi-living”. Now you can use your laptop in the study as well, and connect the PC’s to the router through wired connections. Note that you can replace the antenna with a Yagi antenna and boost the transmission power to get a better reach and a higher wireless speed.

If you run the router in repeater bridge mode, there are a few settings you need to make sure you set correctly:

  1. You must set your encryption to “WPA2 personal” with “AES” encryption.
  2. You must set your wireless channel to a fixed one, so do NOT put it on “auto”.
  3. Please make sure you follow the instructions carefully.

If you do not yet own a DD-WRT capable router you might consider getting one of these new, very fast routers:

  • Netgear WNDR4300
  • ASUS RT-N66U
  • TP-Link TL-WDR4300
  • Cisco Linksys E4200

These very fast routers have awesome specifications and can run DD-WRT perfectly. I have the older, slower Cisco Linksys E2500 and even older and slower Cisco Linksys WRT54GL routers myself, but they also run DD-WRT fine.

@Secure annotation for Symfony 2.3

We created the LswSecureControllerBundle to provide @Secure annotation in Symfony 2.3 to secure actions in controllers by specifying required roles. This functionality was provided by the JMSSecurityExtraBundle, included in Symfony 2.0, 2.1 and 2.2. In  Symfony 2.3 it was removed because of a license incompatibility between Symfony Core and the JMSSecurityExtraBundle. On the official blog Fabien Potencier (author of Symfony) writes:

As the Symfony Standard Edition is under the MIT license, we did not want to have anything else in its deps. That helps people developing GPL projects on top of Symfony. That said, if you are developing your own project, using dependencies under an Apache license should not be a problem at all. So, feel free to add them back. — Fabien Potencier in a response

So, the JMS bundles are no longer included by default and honestly, apart from the license, it is a huge pile of code. Especially as the only feature we use from it, is the @Secure annotation to require roles for executing specific actions in the controllers. Please note that it is not only a beefy bundle, but it also has an impressive set of dependencies:

And don’t get me wrong; I believe the JMSSecurityExtraBundle does a lot of other things that are very valuable and fully justifies its size and its dependencies. I also highly respect Johannes Schmitt for his efforts in the Symfony community and his coding skills. However, if you only need this one feature and want to stay lean (122 lines of code) or if you need a more permissive license, then our bundle is the one for you.

Installation and usage

secure_test
Figure 1: Symfony 2.3 denying access based on a @Secure annotation

Installation of this bundle is just like any other; details can be found in the README. We will show the usage by providing an example based on the standard Symfony 2.3 AcmeDemoBundle. We use the @Secure annotation in the AcmeDemoBundle to secure the “hello world” page requiring the role “ROLE_TEST” to execute.

In “src/Acme/DemoBundle/Controller/SecuredController.php” you should add the following line on top, but under the namespace definition:

use Lsw\SecureControllerBundle\Annotation\Secure;

To require the “ROLE_TEST” for “helloAction” in the “SecuredController” you should add @Secure annotation to the DocBlock of the “helloAction” like this (line 2):

    /**
     * @Secure(roles="ROLE_TEST")
     * @Route("/hello", defaults={"name"="World"}),
     * @Route("/hello/{name}", name="_demo_secured_hello")
     * @Template()
     */
    public function helloAction($name)
    {
        return array('name' => $name);
    }

Note that you can only use the @Secure annotation on actions that are protected by a firewall. You can configure the firewall in the “app/config/security.yml” file.

Credits

Creating the bundle would not have been possible without Matthias Noback’s excellent posts:

Thank you Matthias!

Support

We are committed to support this bundle and, as with all our bundles, you can contact us via the LswSecureControllerBundle Github page if you find a bug or want a feature to be added.

The PHP floating point precision is wrong by default

Let me show you that PHP is bad at Math:

<?php
echo "0.1 + 0.2 = ". ( 0.1 + 0.2 ) ."\n";
$true = 0.1 + 0.2 == 0.3 ? "Equal" : "Not equal";
echo "0.1 + 0.2 = 0.3 => $true\n";

Output:

0.1 + 0.2 = 0.3
0.1 + 0.2 = 0.3 => Not equal

Now, to analyze what is happening here let’s first look at JavaScript:

>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
false

Okay, so JavaScript is also bad at Math, but at least it prints numbers (better) as it internally represents them, making debugging easier. We see that the answer is slightly off and that is why the test is returning false. Before explaining why there are errors, let me give you some more examples of the problem:

0.1 * .1 results in 0.010000000000000002
0.7 + .1 results in 0.7999999999999999
1.1 + .1 results in 1.2000000000000002

As you can see the problem also exists when multiplying. This is because the problem does not lie in the operation, but in the way computers internally store numbers that contain a decimal point. The internal representation is called a “floating point “. This floating point representation has accuracy problems as we have shown above, but it doesn’t only apply to PHP floating points. The reason we have these accuracy problems is described in the floating point guide:

Because internally, computers use a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.

When the code is compiled or interpreted, your “0.1” is already rounded to the nearest number in that format, which results in a small rounding error even before the calculation happens.  – floating point guide

The floating point guide also explains clearly that:

…binary fractions are different from decimal fractions in what numbers they can accurately represent with a given number of digits, and thus also in what numbers result in rounding errors:

Specifically, binary can only represent those numbers as a finite fraction where the denominator is a power of 2. Unfortunately, this does not include most of the numbers that can be represented as finite fraction in base 10, like 0.1.

Fraction Base Positional Notation Rounded to 4 digits Rounded value as fraction Rounding error
1/10 10 0.1 0.1 1/10 0
1/3 10 0.3 0.3333 3333/10000 1/30000
1/2 2 0.1 0.1 1/2 0
1/10 2 0.00011 0.0001 1/16 3/80

And this is how you already get a rounding error when you just write down a number like 0.1 and run it through your interpreter or compiler. It’s not as big as 3/80 and may be invisible because computers cut off after 23 or 52 binary digits rather than 4. But the error is there and will cause problems eventually if you just ignore it. – floating point guide

Now let’s go back to the PHP floating point calculation and evaluate this code:

<?php
ini_set('precision', 17);
echo "0.1 + 0.2 = ". ( 0.1 + 0.2 ) ."\n";
$true = 0.1 + 0.2 == 0.3 ? "Equal" : "Not equal";
echo "0.1 + 0.2 = 0.3 => $true\n";

Output:

0.1 + 0.2 = 0.30000000000000004
0.1 * 0.2 = 0.3 => Not equal

That is more like it. It does not solve the problem, but makes it easier to understand. Note that we have set the “precision” of the representation of floating point numbers to 17 with the “ini_set” PHP command. Gustavo Lopes explains on the php-internals mailing list why other values (like 100) do not make sense:

Given that the implicit precision of a (normal) IEEE 754 double precision number is slightly less than 16 digits [2], this is a serious overkill. Put another way, while the mantissa is composed of 52 bits plus 1 implicit bit, 100 decimal digits can carry up to 100*log2(10) =~ 332 bits of information, around 6 times more.

Given this, I propose changing the default precision to 17 (while the precision is slightly less than 16, a 17th digit is necessary because the first decimal digit carries little information when it is low). — source

So for now, let’s change the precision to from 14 to 17 in “/etc/php5/apache2/php.ini” on our servers and save ourselves some headaches when we are using PHP floating points.

; The number of significant digits displayed in floating point numbers.
; http://php.net/precision
precision = 17

If you want more background on this topic read the excellent article “What Every Computer Scientist Should Know About Floating-Point Arithmetic“.

Symfony 2.3 LTS: Symfony2 with Long Term Support

Symfony 2.3 LTS (Long Term Support) was finally released yesterday (Monday June 3rd 2013). This is a new Symfony2 version that will be supported for next three years. This is significantly longer than the 8 months that normal releases are maintained for. Longer support means less upgrades and can reduce maintenance costs (although the upgrades will be bigger). Also the promise not to break backward compatibility from this version on is an important one. The complete release process (and the release diagram below) can be found on the Symfony2 release process page of the Symfony website.

release-process

Our LeaseWeb Symfony bundles have all received minor version upgrades to support this new Symfony 2.3 release. However, please report any issues you might find with these new versions.

In previous major version upgrades there was an “UPGRADE.md” (for upgrading from 2.0 to 2.1) and “UPGRADE-2.2.md” (for upgrading from 2.1 to 2.2). This release does not have the file included (probably a mistake), but fortunately you can find “UPGRADE-2.3.md” on the official Github repository and also some upgrade instructions on the official blog. Read it carefully to avoid hitting the issues we found (they are described below).

1: Running LTS with stable versions

To run only stable versions of packagist packages make sure “composer.json” contains the following line:

"minimum-stability": "stable",

It would be strange to run an LTS version with development code wouldn’t it? This is set correctly on a fresh Symfony 2.3 installation, but you should check it locally on your own file to be sure it is set correctly.

2: JMS bundles are missing

When you replace the requirements from your composer.json with the required section from the Symfony 2.3 “composer.json” file, you might get the following error when running the “php composer.phar update”:

PHP Fatal error:  Class 'JMS\AopBundle\JMSAopBundle' not found in app/AppKernel.php on line 19

This happens because there are two lines removed from the composer.json compared to the previous versions:

"jms/security-extra-bundle": "1.2.*",
"jms/di-extra-bundle": "1.1.*",

You should add them again, but with different versions:

"jms/security-extra-bundle": "1.5.*",
"jms/di-extra-bundle": "1.3.*@dev",

Note that in the future, you might want to remove the “@dev” suffix from “jms/di-extra-bundle” that allows the package to run a non-stable version.

Update June 8th 2013: There is a new stable version “jms/di-extra-bundle”, but unfortunately this does not work yet:

"jms/security-extra-bundle": "1.5.*",
"jms/di-extra-bundle": "1.4.*",

This caused by the dependencies on “jms/security-extra-bundle” that have not been adjusted to reflect this new stable version. It complains:

jms/security-extra-bundle 1.5.0 requires jms/di-extra-bundle 1.3.* ...

Update June 9th 2013: There is a new stable version “jms/security-extra-bundle” and all dependencies have been fixed. Thank you!

3: “trust_proxy_headers” option unrecognized

You might run into the issue that the “trust_proxy_headers” option that was already deprecated is removed in Symfony 2.3:

[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "trust_proxy_headers" under "framework"

To fix this issue open “app/config/config.yml” and remove the “trust_proxy_headers” option and replace it with an “trusted_proxies” option and specify the list of proxies as described in the FrameworkBundle Configuration documentation.

4: Method “hasFlash” does not exist

You might run into a issue with Flash Messages. Flash Messages are (unrelated to Adobe Flash) the green, blue, yellow or red bars that show up on a page that show the result of the previous page (form) submit. Normally they show messages like “Login successful”, “Error submitting form, please try again” or “Sign-up successful, an email has been sent”.

Method "hasFlash" for object "Symfony\Component\HttpFoundation\Session\Session"
does not exist in ::flash.html.twig at line 1

The “hasFlash” method is deprecated since version 2.1 and removed in 2.3. The book has a good section on how to handle flash messages in different versions. To summarize, if you have this:

{% if app.session.hasFlash('success') %}
  {{ app.session.flash('success') }}
{% endif %}

You need to change that construct into this:

{% for flashMessage in app.session.flashbag.get('success') %}
  {{ flashMessage }}
{% endfor %}

Make sure you also change all “setFlash” calls with the following search/replace action: ”setFlash” -> “getFlashBag()->add”.

5: Method ”bindRequest” does not exist

Make sure you also change all your “bindRequest” calls to “bind” like this:

$form->bind($request); // was: $form->bindRequest($request);

As was well described in the Form Goodness in Symfony 2.1 post.

6: Change Forms (Types) and Validators

In the Type classes add the following use clause:

use Symfony\Component\OptionsResolver\OptionsResolverInterface;

Step 1: Replace the “getDefaultOptions” function like this:

public function getDefaultOptions(array $options)

with:

public function setDefaultOptions(OptionsResolverInterface $resolver)

Step 2: Replace the return value with a call to the resolver “setDefaults” method like this:

return array('validation_constraint' => $collectionConstraint);

with:

$resolver->setDefaults(array('constraints' => $collectionConstraint));

Step 3: Also in your custom validators replace the function “isValid” like this:

public function isValid($value, Constraint $constraint)

with:

public function validate($value, Constraint $constraint)

7: The method “getEntityManager” is deprecated

Replace the deprecated “getEntityManager” method by “getManager” in your controllers like this:

$em = $this->getDoctrine()->getEntityManager();

with:

$em = $this->getDoctrine()->getManager();

As you can also read in the “Persisting Objects to the Database” chapter of the book.

8: The “Min” and “Max” validators are removed

The Min and Max constraints that are deprecated since version 2.1 are removed in Symfony 2.3. You should use Range validator with the “min” and/or “max” option instead.

9: Yours…

If you run into other issues please post them and I’ll add them to this list. For now enjoy this brand new stable Symfony 2.3!

UTF-8 in PHP and MySQL under Ubuntu 12.04

UTF-8 is the de facto standard character set for PHP websites and there are but a few reasons not to use UTF-8 (utf_general_ci) as the default MySQL database collation. However, anyone arguing that UTF-16 is a better standard would probably be right, but because UTF-8 is more popular, nobody cares. Unfortunately, the guys at Ubuntu (or upstream at Debian, PHP and MySQL) still have some strange defaults configured in their software, as follows:

  1. PHP connects explicitly to MySQL with an “Latin 1″ character set unless you send the “set names utf8″ query.
  2. Apache does not specify a character set by default (nor does PHP), letting the browser determine which character set is used.
  3. MySQL sets the “latin1″ as default character set and “latin1_swedish_ci” as default collation (for string comparison).

This is a longstanding issue. The reason for these western/Swedish defaults is that MySQL AB has a Swedish origin. Now that MySQL is the world’s most popular web database, and has been bought by Oracle (based in California/US), it seems like a strange choice. These days you would expect the following defaults:

  1. PHP connects to the server and uses the character set of the server, unless specified.
  2. Apache should assume all text content to be UTF-8 encoded.
  3. MySQL should have UTF-8 as the default character set and “utf_general_ci” as the default collation.

It is easy to make Apache/MySQL/PHP (under Ubuntu 12.04) behave the way you like. First we add the character set to Apache:

sudo echo "AddDefaultCharset utf-8" >  /etc/apache2/conf.d/utf8.conf

Now for MySQL, we open “/etc/mysql/my.cnf” and under the “[mysqld]” section we add the following 3 lines:

[mysqld]
...
character-set-server=utf8
collation-server=utf8_general_ci
init-connect='SET NAMES utf8'

For a default of UTF-8 in the MySQL command line client (optional) you must add the following line in the “/etc/mysql/my.cnf” file under the “[client]” section:

[client]
...
default-character-set=utf8

Now restart the Apache and MySQL servers with the following commands:

sudo service mysql restart
sudo service apache2 restart

This is really all you have to do on a default Ubuntu 12.04. To check whether or not everything works correctly put the following “utf8.php” file on your website:

<?php
mysql_connect('username', 'password', 'localhost');
mysql_select_db('database');
$re = mysql_query('SHOW VARIABLES LIKE "c%";')or die(mysql_error());
while ($r = mysql_fetch_assoc($re))
{ echo $r["Variable_name"].': '.$r["Value"]; echo "<br />";
}

The output should be:

character_set_client: utf8
character_set_connection: utf8
character_set_database: utf8
character_set_filesystem: binary
character_set_results: utf8
character_set_server: utf8
character_set_system: utf8
character_sets_dir: /usr/share/mysql/charsets/
collation_connection: utf8_general_ci
collation_database: utf8_general_ci
collation_server: utf8_general_ci
completion_type: NO_CHAIN
concurrent_insert: AUTO
connect_timeout: 10

Let me know if you still have any trouble making it work. Good luck!