HTTP Cookies from VirtualBox are not sent back

VirtualBox is a great virualization solution. I use it to host my website and test it. It helps it me to set up the very same environment as I use in the server.  So I dont have to worry whether recent change in the web application will break it.  If you are a web developer and not using VirtualBox you should start right now.

Today I faced a weird problem. I could not log in to the web application in the vbox. But I could log in the live server. There was no difference between these two. One is physical server and other was virtual. After observing the http headers carefully I found that php session ids sent from virtual box was not preserved. But for live sever they get preserved. Session id is usually saved in cookie. Its the http clients responsibility to save the cookie and send it back along with successive request. I tested it in curl. it was not saving cooking. Google chrome was also not saving cookie. Only Firefox was saving.

At first I though its a problem of Google Chrome. I was almost submiting a bug to Chrome team. But then I tested in curl and it was not working. Two clients can not have same bug. So this should a problem of my host.  I compared all the headers sent by both live server and virtual box server side by side. And guess what I found?  The expires time for a cookie sent by virutal server was in past time. So this cookie was expired when generated.  It means my virtual box servers time was not in sync. I have to synchronize it with time server. The following command is enough for this.

ntpdate pool.ntp.org

After this everything was working smooth.  I always sync the time when i start the vbox server. If you boot your server time will be automatically synchronized. But if you save the state and later resume it you have to synchronise it manually. I never missed synchronizing. Today I forgot it. So I never think about it.  I checked last 30 revision from my svn repository to track down the problem.

My suggestion, Always synchronize the time of a vbox server if you resume it. Use the command above for this.

Now a new question arise. Why Firefox used a expired cookie?  I’ll verify it later.

Google Chrome Unicode normalization and য়, ড়, ঢ় problem

If you are using Google Chrome and writing Bangla, you might have already faced this problem. Every time you send a POST request (it just happens to POST data only) Google Chrome changes normalizes Unicode characters automatically. In Bangla Language Chrome normalizes 3 characters. These are য়, ড় and ঢ়.

What Chrome Actually do?

If you look carefully each of these 3 characters has a dot (.) underneath. Also there are 3 other characters in Bangla which are same like this but without dot. In Bangla there are actually 6 characters, ড, ঢ, য, ড়, ঢ়, য়. Chrome just uses the first 3 and adds a dot underneath to form the last 3. This is called normalization. Each time we send request that contains the last 3 characters, Chrome just converts them to corresponding first 3 characters and then adds a dot.  This happens only for those data that resides in HTTP request body. So, this behaviour is not found for Cookie, Header or in Query string as all of these three data sources reside in HTTP request header. I suspect it also happens with PUT type request.

An Example

Lets say we are going to submit a form with request method is POST.  It has a input field. If you type “গাঢ় সবুজ পেয়াড়া” (a sentence that contains all the problem characters) and submit the form, Chrome will submit “গাঢ় সবুজ পেয়াড়া”. These string may look alike. But they are different! In hex, The red stands for modified characters and green for newly added characters. Spaces are used to align.

before: hex(গাঢ় সবুজ পেয়াড়া)= e0a697e0a6bee0a79d      20e0a6b8e0a6ace0a781e0a69c20e0a6aae0a787e0a79f      e0a6bee0a79c      e0a6be
after:  hex(গাঢ় সবুজ পেয়াড়া)= e0a697e0a6bee0a6a2e0a6bc20e0a6b8e0a6ace0a781e0a69c20e0a6aae0a787e0a6afe0a6bce0a6bee0a6a1e0a6bce0a6be

Key points:

Some key points to be noted.

  • This normalization takes place any data that reside in HTTP Request body. So only POST and  PUT will be affected. Cookie, Header and Query string data will be unaffected.
  • The inconsistency between HTTP request body and header part confirms this as a Chrome bug.
  • Either it should be normalized all over HTTP request or nowhere.

Solution:

As you have already understood the problem you know how to solve it. Just file a bug to Google Chrome team. As long as google does not fix this you can just replace those characters in your web application.  Here is a snipped I have written to fix this in PHP.

class DeNormalOntosteo {
private static $strmap = array('/য/' => 'য়', '/ড/' => 'ড়', '/ঢ/' => 'ঢ়');
public static function replace($data) {
if (is_array($data)) {
$keys = array_keys($data);
$values = array_values($data);
$len = count($values);
while ($len--) {
$values[$len] = preg_replace(array_keys(self::$strmap), array_values(self::$strmap), $values[$len]);
}
return array_combine($keys, $values);
} elseif (is_string($data)) {
return preg_replace(array_keys(self::$strmap), array_values(self::$strmap), $data);
} else {
return false;
}
}
}

Usage

// Denormalizing $_POST array
$_POST = DeNormalOntosteo::replace($_POST);
// Denormalizing a string
$_POST['data'] = DeNormalOntosteo::replace($_POST['data']);

Update 1:

I have created a page where you can see the bug in action. You must use google chrome to browse this page. Just visit and press submit.

Update 2: 

I have filed a bug on chromium team on google code. If you are having same issue please give them a knock here.

Create Next Previous Javascript Bookmarklet for Slideshow Tutorial Ebook sites

Recently I was browsing http://talks.php.net. There were bunch of slideshows about php. I work on PHP most times. So It was good for me.
The problem arise when I saw some slide shows didn’t rendered correctly in html. so there was no next, previous button. I had to change the urls to navigate next, previous pages.
Most urls were in the format http://domain.com/path/slideshow/1, where 1 is the page number. Changing it to 2 led me to the 2nd page of the sildeshow.
I wanted it to make automated. Via javascript obviously ( being a big fan of JS).

So I made two Javascript bookmarklet button. So when you click the Next button, it will go to next page. And same for Prev button.
Following are the buttons. All you have to do is just drag those button to your Browsers Bookmark bar. Thats it!

Next Page

Prev Page

Note: Not all the urls will work. See below to get more idea.

  1. http://domain.com/path/slideshow/1 Will work
  2. http://domain.com/path/slideshow/1.html Will not work
  3. http://domain.com/path/slideshow/1.php. Will not work
  4. http://domain.com/path/slideshow-1. Will work
  5. http://domain.com/path/slide-2/show Will not work
  6. http://domain.com/path/slide-2/show.php Will not work
  7. http://domain.com/path/slide-2 Will not work
  8. http://domain.com/path/slideshow#1 Will work ! !

Sometimes those buttons discussed above may not work, eg, Manual, ebook etc sites. In that case use the following two buttons.
These are quite handy if you are browsing a site where next page cannot be guessed from url.

Next URL

Prev URL

Here is the code

Next Button:

var e=document.getElementsByTagName("link");
var g="getAttribute";
var l=window.location.href;
for(i=0;i<e.length;i++){
    r=e[i][g]("rel").toLowerCase();
    h=e[i][g]("href");
    if(r=="next"){
    l=h;
    break;
    }
}

Previous Button:

var e=document.getElementsByTagName("link");
var g="getAttribute";
var l=window.location.href;
for(i=0;i<e.length;i++){
    r=e[i][g]("rel").toLowerCase();
    h=e[i][g]("href");
    if(r=="prev"){
    l=h;
    break;
    }
}