Web Programming, Linux System Administation, and Entrepreneurship in Athens Georgia

Category: Programming (Page 4 of 6)

PHP Performance – isset() versus empty() versus PHP Notices

I’m cleaning up a lot of PHP code and always program with PHP error_reporting set to E_ALL and display_errors turned on so that I make sure to catch any PHP messages that come up. Since starting on this site, I have fixed literally hundreds (maybe thousands) of PHP Notices about using uninitialized variables and non-existent array indexes.

I have been fixing problems like this where $somevar is sometimes undefined:

if ($somevar)

by changing it to:

if (isset($somevar) && $somevar)

This successfully gets rid of the NOTICEs, but adds some overhead because PHP has to perform two checks. After fixing a lot of this in this manner, I’ve noticed that the pages seem to be generated a little slower.

So, to provide some conclusive results to myself, I wrote up a quick benchmarking script – available at php_empty_benchmark.php. It goes through 1,000,000 tests using each of these methods:

  1. if ($a) – This generates a notice if $a is not set
  2. if (isset($a)) – A simple clean way to check if the variable is set (note that it is not equivalent to the one above)
  3. if (isset($a) && ($a) – The one that I have been using which is equivalent to if($a), but doesn’t generate a notice.
  4. if (!empty($a)) – This is functionally equivalent to if($a), but doesn’t generate a notice.

It measures the time to perform 1 million tests using a defined percentage of values that are set.  It then computes the difference as a percentage of the time taken for the original test (the one that generates the notices).   A ‘diff’ of 100 means that the execution time is the same, greater than 100 means that it is faster, and less than 100 means that it is slower. A typical test produced these results:

    With NOTICE: 0.19779300689697
    With isset:  0.19768500328064 / Diff: 100.05463419811
    With both:   0.21704912185669 / Diff: 91.128222590815
    with !empty: 0.19779801368713 / Diff: 99.997468735875

In summary, using the if (isset($a) && $a) syntax is about 8-10% slower than generating the PHP Notice. Using !empty() should be a drop-in replacement that doesn’t generate the notice and has virtually no performance impact. Using ifset() also has no performance impact, but is not exactly the same as ‘if($a)’ since isset() will return true if the variable is set to a false value. I included it here, because it often make the code a little more readable than the !empty($a) syntax. For example:

$myvalue = !empty($_REQUEST['myvalue']) ? $_REQUEST['myvalue'] : '';

Versus

$myvalue = isset($_REQUEST['myvalue']) ? $_REQUEST['myvalue'] : '';

Installing trac with webadmin on CentOS5

I’m not overly familiar with Python applications, so it takes a little while for me to figure it out each time. I need to document it somewhere so I don’t have to reinvent the wheel every time – might as well do it here so that others can find it.

Install the rpmforge repository

wget  https://dag.wieers.com/rpm/packages/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm

rpm -i rpmforge-release-0.3.6-1.el5.rf.i386.rpm

Install trac from the rpmforge repo

apt-get install trac

Install ez_setup

wget https://peak.telecommunity.com/dist/ez_setup.py

python ez_setup.py

And install webadmin with easy_install

easy_install https://svn.edgewall.com/repos/trac/sandbox/webadmin/

My list of essential FireFox plugins

I just got a new laptop, which is a good chance to start over with a clean system configuration.   After trying to use FireFox without any of my normal plugins, I realized how much I’ve come to rely on these plugins:

ColorZilla:  Adds a button the the bottom left of the status bar.  When you click on it, you can then highlight anywhere on the page to get the HTML Color value.

FasterFox:  A couple very handy utilities for timing page loads, and speeding them up in general.  I find myself watching the page load timer all of the time.  It simply displays the amount of time that each page takes to load in the status bar.  It has a few advanced options to preload links on pages, to increase the number of simultaneous HTTP requests to a server that makes your browsing experience faster.

FireBug: Modify HTML and CSS in real time – incredibly handle for HTML development work and debugging

Google Toolbar: My main point in using this is just to see the PageRank of each page.

MeasureIt: Adds an icon to your status bar that, when clicked, turns your cursor into a crosshair so that you can measure the size of any elements on your current web page.

no-referrer: Adds an option on the context menu for links to open the link in the new tab without passing the HTTP Referrer field.   I use this when on any ‘private’ pages like my awstats pages, or blog admin pages, where I don’t want to tell the world about via the HTTP referrer.

ShowIP: Adds an item to the status bar with the IP Address of the server – This is very useful information to have when doing system administration tasks.   May not always be correct when changing DNS entries though.  That is probably Firefox caching though instead of this plugin’s.

Web Developer: Adds all kinds of options for looking at some HTML details.  The main one I use is for looking at the HTTP Response headers.

Block comment spam with bcSpamBlock

A while ago I installed Paul Butler’s JSSpamBlock on my WordPress blog here. His original idea is simple and brilliant: Spambots don’t (yet) execute Javascript. In fact, they usually post directly to the form without even displaying the form first. By having a hidden input field that is populated by javascript, you can verify that users are hitting the page without the user even noticing. For users with JavaScript disabled (are there any of you out there), they simply have to copy/paste a small string into a textbox for verification.

Since implementing a slightly modified version of it on this blog, I have gotten zero spam posts. Now, I wanted some way to implement the same logic on some of my own custom PHP sites to prevent spam on them as well.

While working on a way to re-implement Paul’s WordPress plugin in my own sites, I came up with something pretty clever. Instead of saving a row to a database every time that the form is displayed, you can use a little cryptography to make the client pass all of the data needed to validate the request back to you on its own. The idea is sortof merger between the JSSpamBlock plugin and TCP Syncookies, which use a similar method of having the client store the data for you.

Essentially, how it works, is that the function generates a Random ID. It then encrypts the current timestamp and the random ID using PHP’s crypt() function with some cryptographic salt that is unique to each server. All three of those values (the random ID, the timestamp, and the encrypted value) are then passed to the browser. The timestamp and the encrypted value are stored in hidden <input> fields, while the random ID displayed for the user to verification. If the user has JavaScript enabled, a few lines of JavaScript copy the random ID into another textbox, and then hide that prompt, so that it is never seen by the user. If the user doesn’t have JavaScript enabled, the would have to copy/paste that random ID into the textbox themselves, similar to a captcha.

When the form is submitted, it checks to make sure that the timestamp is not too old, and then re-encrypts the passed in timestamp and random ID using the same salt value to make sure it matches the crypted value passed in from the form. If everything matches, the comment is approved, otherwise an error is displayed to the user.

I wrote this up into a simple include file that can be used for any PHP application. I also implemented a quick WordPress plugin that uses the generic version. More information about it can be found on my new bcSpamBlock home page

Update 2024-10-01:

There are much better spam blocking plugins now, so this has been discontinued.

Fix for CentOS “Can’t do setuid (cannot exec sperl)”

If you are running a Perl script with the setuid bit, it actually runs a slightly modified version of Perl so that it is a bit more cautious. On a CentOS box, you need to install the ‘perl-suidperl’ package to get the necessary files installed. Otherwise you get an error like this:

[root@host bin]# ls -al myscript.pl
-rws--S--- 1 mail mail 1218 Oct  1 13:09 myscript.pl

[root@host bin]# ./myscript.pl
Can't do setuid (cannot exec sperl)

Find the best book buyback prices with BookScouter.com

A few weeks ago I posted about a quick service I put together that compared textbook buyback prices from a few of the top websites.  I’ve been working on expanding that the past few weeks, and am now unveiling a site dedicated to it.

BookScouter.com is the most comprehensive comparison site for quickly searching for textbook sale prices. It currently scrapes prices from 21 other sites – which is all of them that I could find. The website is written in PHP using a custom framework that I’ve developed and use exclusively now. I found an excellent website called opensourcetemplates.org that has website templates available for free. Their ‘Nautilius’ theme is the one I chose for this site.

The backend of the site is written in Perl. It uses a pretty straightforward LWP to fetch the page, and some regular expressions to pull the price from the pages it obtains. Each site was custom coded, but I got it down to a pretty re-usable script where I just customize a few of the things, like the input variable name for the ISBN and the regex that contains the price. A few of the sites were more complicated than the others and required fetching a couple pages to obtain a session ID.

I’m pretty happy with the end result. Please try to look up a few books and see if you have anything of value sitting around. No registration or any personal information is ever required and it is completely free to use.

Perl Interface to the Quantum Random Bit Generator Service

Quantum Random Bit Generator Service

I read about the Quantum Random Bit Generator Service the other day on slashdot. The service is offered for free with a quick registration at https://random.irb.hr/ They provide the source code and Windows and Linux binaries to connect to the service and retrieve some random data.

Earlier that day I was marveling at the availability of a Perl module to interface with just about anything. I thought it seemed like a good opportunity to write one for this new service.   They provided some C source code, so I figured that I should be able to read through it well enough to understand what it was doing.

The interface that they provide is just a raw TCP connection.  You have to send some header information including your username and password as well as the number of bytes of data you are requesting.   It then sends back a bunch of random bits, and then I transform that into whatever type of numbers you want.

It ended up taking me entirely too long to implement, but I had dedicated enough time to it that I felt pretty committed.  I read through the provided C code, and did a bunch of tcpdumps to capture the traffic that their working program sent and made sure that mine matched it bit by bit.  Eventually I got it working.  I’ve packaged into a module that I’m calling Data::Random::QRBGS.  Now, it is simple to get some random data from the service like this:

  use Data::Random::QRBGS;

  $qrbgs = new Data::Random::QRBGS('username', 'password');

  @ints = $qrbgs->get(4);
  print "Got random integers: @intsn";

  @shorts = $qrbgs->get(2, 's');
  print "Got random shorts: @shortsn";

  $bytes = $qrbgs->getraw(1024);

I’ve created a page at https://www.brandonchecketts.com/qrbgs.php that contains a little documentation and a link to download it.

I’d like to see about getting the module made available through CPAN, but it is actually turning out to be quite complicate to do that. I’ve requested an account, and I guess that has to get approved manually. They instructions recommend joining the mailing list and discussing the module for a while before before actually submitting it. I’ll get around to that as I have time I guess.

Compare used book purchase prices quickly

I was reading the blog of a friend of a friend and came across a discussion about selling used books online. It sounded like there are a bunch of different sites that buy used books. Each of them allows you to put in an ISBN number to see what they are willing to buy it for.

To find the best price, you would have to browse all of these sites to see who was offering the most money. Sometimes the a book may sell for a dollar at one site, but nine dollars at another, so it is worth your time to check out all of the sites.

Sounds like a good candidate for automation to me. I am already doing a pretty similar, but more complicated, version of this with GamePriceWatcher.com. It didn’t take me much time to write some scripts to scrape prices from about eight of these sites. I also included the Perl WWW::Scraper::ISBN module to retrieve some of the details about the book and it has turned out pretty well.

I have it working now at https://avazio.com/sellbooks.php, and may move it over to its own domain if it seems like anybody is using it.

PHP 4’s call_user_func passes everything by value

I spent quite a while today debugging a problem where call_user_func was not passing a parameter by reference. I was trying to pass an object into a function whose name is not known until run time.

Passing it by reference means that changes made to $var inside foo() are made to the actual variable instead of to a copy of the value (when passed by value).  However, for some reason, when calling a function with call_user_func(), it passes everything by value, regardless of how the function is defined.

function foo(&$var)
{
  $var++;
}

$bar = 1;
foo($bar);
echo $bar;    // outputs '2'

$function = 'foo';

call_user_func($function, $bar);
echo $bar;  // you'd expect this to output 3 now, but it still outputs 2

$function($bar);
echo $bar;  // outputs 3 now

As the sample code shows, the solution is to avoid the use of the call_user_func() function by using a variable function name. Thanks to Steve Hannah’s blog post at https://www.sjhannah.com/blog/?p=86 for helping me to solve this one.

Credit Card Validation using the mod10 algorithm in PHP

I’m working on a site that will use the Paypal API for submitting merchant account transactions to them. I’d like to validate as much credit card information as possible before passing any information to a 3rd party, since are different kind of credit cards companies and options, so I’ve been reading to find out more about it. I came across the mod10 check that credit cards use and wrote a little PHP function to validate a card number

function sumdigits($number)
{
  $sum = 0;
  for($i = 0; $i <= strlen($number) - 1; $i++) {
    $sum += substr($number, $i, 1);
  }
  return $sum;
}

function mod10check($number)
{
  $sum_number = '';
  for($i = strlen($number) - 1; $i >= 0; $i--) {
    $thisdigit = substr($number, $i, 1);
    $sum_number .= ( $loop %2 == 0) ? $thisdigit : sumdigits($thisdigit * 2);
  }
  return sumdigits($sum_number) % 10 == 0 ? true : false;
}
« Older posts Newer posts »

© 2025 Brandon Checketts

Theme by Anders NorenUp ↑