phpinfo() Phones Home

So I was doing some client work today when I noticed something somewhat disturbing; phpinfo() has a logo that sends data back to php.net. I’m not sure exactly what the data is, but here’s the offending markup.


<img border="0" src="?=PHPE9568F34-D428-11d2-A769-00AA001ACF42" alt="PHP Logo" />

The somewhat more disturbing part is that this image also sets a cookie. The cookie appears to hold both my country and the IP address of the requesting agent.


COUNTRY=USA%2C64.34.176.111

I’ve looked at a few scripts and found that the src of the image file appears to change slightly between installations. I’m sure it’s nothing malicious, but it is a bit odd.

Anyone else know anything about this?

IE continues to suck

As some of you may know I run a small picture hosting site. A user emailed me the other day to say that Internet Explorer was only allowing her to download images at BMP images, despite the image being a JPG or a GIF. Turns out this is a known issue. I figured that had to be a way to turn off caching via the HTTP headers and I think I have a solution. If you’re sending dynamic files via PHP give these headers a try.


<?php

// Your file's extension
$ext = 'jpg';

// Your file's name
$name = 'goofypicture.jpg';

// Your file's location
$src = '/path/to/'.$name;

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: image/".$ext);
header('Content-Disposition: inline; filename="'.$name.'"');
header("Content-Length: ".filesize($src));

?>

Framework 0.0.7 Released

I’ve fixed a minor security hole in my PEAR version of the framework that I created for the ONLamp.com article Understanding MVC in PHP. Everyone who is currently using Framework 0.0.6 or below should update their install immediately.

To upgrade:


$ pear upgrade "http://www.joestump.net/jax/content/source/Framework/Framework-0.0.7.tgz"

To install:


$ pear install "http://www.joestump.net/jax/content/source/Framework/Framework-0.0.7.tgz"

MVC Framework for PHP5

I am currently writing an article about PHP5 and MVC frameworks for web programming for onlamp.com. Part of writing the article required me writing an MVC framework to showcase the theories and ideas behind MVC programming. The result is what I simply call Framework. The following are the installation instructions.


$ pear install "http://www.joestump.net/code/Framework/Framework-0.0.6.tgz"

As new version become available you can also use the above command to upgrade by replacing install with upgrade and the URL for the newly released version. Once it is installed check out /path/to/PEAR/doc/Framework for installation instructions and the article describing how MVC frameworks work.

You will also need Smarty installed in your path as Smarty/Smarty.class.php. Once that is done it should all work fine. Please feel free to email me with questions and concerns, however, this is not supported code at this time and not to be considered stable in any way.

UPDATE: You will want to check out the PEAR category on my site for the latest version of Framework, which is currently 0.1.1

PHP + AJAX + Dictd Interface

Lots of my geek friends have already had a preview of this feature, but we’ve launched it on the live site and now I can tell everyone about eNotes.com‘s new Dictionary/Thesaurus Lookup feature. Below are instructions for looking up a definition or finding synonym’s for any word on any of eNotes.com’s pages.

  1. Go to eNotes.com
  2. Select a word (any word, or even parts of word) with your mouse
  3. Hit SHIFT+D for a definition or SHIFT+T for a list of synonyms from the thesaurus

Being an educational site this is going to be an amazing feature for our users. Considering we have over 50 full books and plays online and over 70,000 pages of premium educational content it’s going to be great for users to be able to look up definitions and synonyms for any word on our web pages with little effort.

I’m sure everyone is wondering how we went about putting together this great feature. Surprisingly, it wasn’t really that hard. When the owners first came to me with this idea I instantly thought of AJAX. I contacted Ian Eure who is my go to Javascript guru. We talked through the options and decided that we needed some Javascript that used XMLHttpRequest to interface with a PHP script that, in turn, would perform the lookups over the TCP/IP enabled dictd. Below is a list of ingredients we used.

  • 1 Javascript guru
  • PEAR’s Net_Dict to interface with our dictd server
  • dictd installed with the WorldNet dictionary and Moby thesaurus
  • Some PHP code to parse the dictd response and convert it into XHTML
  • Some Javascript/XMLHttpRequest magic to capture the selected text and query the PHP dictd interface

We’ve spent a few weeks perfecting the interface and making it pretty, but Ian had the bulk of the prototype code done in a few hours. I’d like to thank Ian for his superb and highly professional coding skills and eNotes.com for letting us do cool stuff like this. In addition to being a great company to work for, eNotes has also agreed to release some of the library code that parses dictd responses into HTML back to the community. I would assume in the coming months HTML_Dict and Net_Dict_Parser will be released either via PEAR or, possibly, an eNotes PEAR channel.

AJAX and Ruby on Rails

Two of the hottest “trends” in web programming right now are AJAX and Ruby on Rails. Why are they so hot? I honestly don’t understand the hype. Both are old and proven technologies wrapped up in pretty packaging. One of them isn’t even a new technology, it’s merely an acronym slapped over something whose original name wasn’t flashy enough.

AJAX is just XMLHttpRequest. That’s it folks. Nothing really to see or talk about here. It’s a pretty name for an awesome technology.

Ruby on Rails is the one that really pisses me off. Everyone is heralding it as the second coming in web development. Guess what? It’s just an MVC framework. Whoa! Don’t everyone jump up and shout for joy at the same time.

I can’t possibly be the only one looking around and saying to myself “So what?”. I’ve been programming within an MVC framework for three years. It’s been running large scale websites since then without issue. It uses crazy things like a controller, a presentation layer and leverages PEAR. To everyone doing cartwheels over AJAX and Ruby on Rails I say, “Welcome to the party. You’re late.”

Ways for Using and Extending FULLTEXT

Well, my presentation on MySQL’s FULLTEXT indexes is all over now. I actually managed to fill the full 45 minutes with information on how to use FULLTEXT indexes. You can check out the source code as well.

I was pretty scared to present once I found out that MySQL UC is a huge conference filled with people that are way smarter than I am. Also, the room where I was presenting was huge. Pretty intimidating for sure, but it all went well for the most part with very few complaints from the audience.

Running Apache/MySQL/PHP on Debian AMD64

I’ve been pulling my hair out for the last few weeks working on migrating enotes.com over to a new server setup. The new setup runs on dual Opteron AMD64’s. AMD64’s are relatively new 64-bit processors that offer lots of processing power for very little money.

There are a few things you should pay attention to when running Apache, MySQL and PHP under these 64-bit processors.

  1. Bugs in MySQL (8555 and 3483) cause INSERT statements to hange indefinitely. A temporary work around is to add skip-concurrent-insert to your my.cnf.
  2. A bug in Apache’s regex.c engine causes problems with mod_rewrite on AMD64 (31858). You can either upgrade to Apache 2.0 or use the patch supplied in the bug to fix Apache 1.3.33. I continued to have problems running our code in 64-bit mode so I chose to run Apache in an i386 chroot using debootstrap (thanks to Jeremy)
  3. A bug in PHP’s strtotime() function (30215) causes the function to return huge numbers instead of -1 on error. This boned Smarty’s date_format on my sites.

Those were the serious problems I had getting things up and running. Other than that things appear to be running smoothly. The following is the work around I submitted to the Smarty mailing list concerning PHP’s strtotime() bug.

Why not put a check into the smarty_make_timestamp() function? It’s predictable in that it returns huge timestamps (3441718022400 is an example). The check could (and should) be removed once PHP fixes what appears to be a fairly simple bug.

So, until then, what do you do? Well, I’ve put together a simple fix. In plugins/shared.make_timestamp.php around line 51 there is something like this:


    $time = strtotime($string);
    if (is_numeric($time) && $time != -1) {
        return $time;
    }

Change that to:


    static $endOfTime;
    if (!isset($endOfTime)) {
        // End of 32-bit UNIX time - 1
        // 19 Jan 2038 at 03:14 and 7
        $endOfTime = mktime(3,14,6,1,19,2038);
    }

    $time = strtotime($string);
    if (is_numeric($time) && $time != -1 && $time < $endOfTime) {
        return $time;
    }

This fixed my problem since the function fails in a predictable format on my Opteron box. Of course, it will break if this code is still running after Jan of 2038.

Works on Apache 2.0.53/PHP 4.3.10 under Debian GNU/Linux (2.6.8-10).

Checking large sites for PHP parse errors

I now work for a large site. It’s not a place I haven’t been before, but I’m definitely getting back into the swing of running a large (we’ll do over 10 million requests during our busy months). We’re in the middle of migrating our websites in house onto larger servers that we’ll manage ourselves. It’s a daunting task because our company runs lots of smaller sites we’ve either picked up or somewhat abandoned along the way. These sites were written in older versions of PHP (probably PHP3) by the owner of the company as he was learning PHP. As a result I’m having to go back and fix include paths, etc. as we migrate to the new server, but how exactly do you automate the task of checking a site with hundreds to tens of thousands of pages for parse errors?

A friend of mine, Ian, who I do a lot of “bouncing off of” had a great idea. Basically, you turn on log_errors in your php.ini file, tail -f /path/to/error.log | grep PHP and then run a garden variety link checker against your site. As the link checker crawls your site it should trigger parse errors that will show up in your error file.

There you have it. A simple and easy way to check a large site for parse errors. Turn your error_reporting to simply be E_ALL to find notices and other problems in your code.

Internet Explorer Reloading/Refreshing Bug

I was handing off a recently created application to a few of my bosses and coworkers when one of them noticed that that page was constantly refreshing/reloading over and over. The page never fully finished loading before the next reload/refresh would occur. I scoured the internet before I found an article about a guy who was experiencing a similar problem only with HTML emails in Outlook. A reply to the article said that Internet Explorer, which Outlook Express uses to render HTML email message, does not properly decompress gzip pages. Sure enough, Internet Explorder has a gzip bug that is both known and has a hotfix for.

For those of you wondering what gzip output is, it allows a systems administrator to send webpages as gzip compressed archives (much like a WinZip file), which are then uncompressed by IE/Mozilla/Firefox and rendered as HTML/images. Well, evidently, IE doesn’t do this properly. So the fix was to comment out output_method=ob_gzhandler in my php.ini file.

Internet Explorer sucks and cost me 2 hours of work today. Thanks Microsoft!