All Posts in the ‘PHP’ Category

When Can I Reuse This Calendar (dot com)

November 11th, 2009 | By Ian in Development, Hobbies, Made by isnoop, Misc, PHP, Related sites, Sites of Interest | 3 Comments »

My wife dug up a 2008 calendar still in the shrinkwrap and it got me thinking… When can I reuse this calendar? Well, I had a spare hour and $6.99 to register a domain, so I whipped out this little site:

http://whencanireusethiscalendar.com/

Now you can go digging through that chest of crap from the 1990s and pull out your favorite cute puppies calendar. In 2010, you can re-use calendars from 1999, 1993, 1982, 1971, 1965, 1954, 1943, and 1937.

People Use FeedSifter.com?

July 19th, 2009 | By Ian in Development, Made by isnoop, PHP, Related sites | 1 Comment »

rssAs with most of my web toys, FeedSifter.com started off as a tiny tool that served a very simple need I had. Assuming a handful of people might have the same need, I publish most of these utilities and some of them actually manage to become fairly popular.

FeedSifter is a simple service that allows you to filter an RSS or ATOM feed for various keywords. There are many other services out there that do this same thing, but this site is anonymous, uncluttered, and intuitive–exactly what I wanted at the time.

Looking at the traffic stats today, I’ve found that feedsifter.com managed to become fairly popular while nobody was looking. Over the past 8 months, daily traffic has been steadily increasing and it is fast approaching 2,000 requests per hour. That’s a pleasant surprise and a good indication that I should put some effort into finishing those final few features I never got around to implementing years ago.

10 Rules to Protect User Passwords

May 1st, 2009 | By Ian in Development, Misc, Opinion, PHP, Rants, Security | 5 Comments »

loginformMost programmers take a pragmatic approach to security and scale their efforts based on an estimate of the sensitivity of the data they are storing.

The unfortunate truth is that password security is frequently underestimated, making it easy for credentials to be sniffed or stolen.  Users often keep a very small collection of passwords, with many people memorizing a small collection and using them on almost every site and service they use. A password compromise on one site can lead to a compromise on many.

#1 Only store salted password hashes, not the plaintext password itself

The cardinal rule for handling user passwords is to never store the password itself.  You should only store a hash (one-way encrypted representation) of the password, cryptographically salted with a string at least 16 characters long. When you want to check a user’s login, simply re-hash their input with the same salt and compare it to the hash stored in your credentials table. 

#2 Never display a user’s password

There is never a good reason to display a user’s password on a web page.  If they have forgotten their password, send the user through a password reset procedure.  This also includes displaying their password in HTML forms.  Don’t send the user’s password out as the value of a password form field input.  This is almost as bad as displaying it on the page.

#3 Use the password field in forms

On occasion, a site will not use the “password” input field type on a login form.  Any sensitive input acting like a password should be presented as a password input.  This provides basic protections against caching, copying, and prying eyes.  This applies to passwords, PINs, SSNs, and other private authentication data.

#4 SSL encrypt pages where users create new passwords

Prevent packet sniffing password theft by encrypting pages where the users are changing or creating new passwords.

#5 Protect passwords sent over non-encrypted connections

If you can, SSL encrypt any page where a user is sending their password for login.  In places where this may not be an option, consider using javascript to prevent the password from being sent in plaintext.  (More info on this in a later blog post)

#6 Never store passwords in cookies

Many developers don’t consider the fact that cookies are sent by the user’s browser for every request to a domain, including requests for images, CSS, and javascript.  All this traffic makes it extremely easy to sniff passwords stored in cookies. Passwords stored in cookies are also easily found by someone who has access to a computer’s harddrive.

#7 Enforce reasonable password rules

All sites need some basic rules around passwords to keep users from using poor passwords.  However, don’t think you’re doing yourself or your users any favors if you implement rules like setting a maximum password length, requiring users to change their passwords too often, or preventing users from ever re-using a password once they’ve changed it.  

Forcing users into situations like these frequently leads to password post-it notes stuck to monitors or the underside of keyboards.  Sometimes, it even drives site users away (I’m talking about you, sharebuilder.com).

#8 Send confirmation emails when their password is changed

Whenever a user’s password changes, send a confirmation message to their verified email address.  Tangentially, any email address change should trigger confirmation emails to both their new and old addresses.  This behavior helps your users quickly find out when they’ve been compromised, which can limit the damage done by a malicious user.

#9 Never email a user’s password

Many sites feel they are doing their customers a courtesy by emailing them their own password when they change it or sign up.  However, if your email account is ever compromised, a simple search for ‘password’ can reveal a treasure trove of passwords, allowing a malicious person to gain access to many more sites and services used by a user.  The resultant password list may also be used against any other site that hasn’t emailed a user their password, such as their bank, PayPal, or social networking sites.

#10 Use a proper password reset system

When a user forgets their password, generate a random temporary password and email it to their verified email address.  This should not overwrite their old password.  Instead, it should be set to expire within a reasonable amount of time (a few hours) and if it expires, the old password should remain in place.  If the user logs in with the temporary password, they should be required to enter a new password before continuing to the site.  The temporary password should then be expired and unusable on that account.

PHP Changelog RSS Feed

December 9th, 2008 | By Ian in Misc, PHP, Sites of Interest | No Comments »

Thanks to the site Feed43.com, I was able to quickly and easily generate an RSS feed to the PHP5 Changelog, a very large page that doesn’t already have a feed.

Check out the PHP 5 Changelog Feed.

Feed43 beats Yahoo’s Tubes service because if a page is too large, it simply truncates it to a usable length. Tubes will simply fail to process a page that it deems is too big.

Tags:

A New Home for Package Tracking: Boxoh.com

November 25th, 2008 | By Ian in Development, Google, Hobbies, Made by isnoop, PHP, Related sites, Site Features | 7 Comments »

My Google maps making, RSS feed slinging, universal package tracker has moved to greener pastures. Boxoh.com is your new go-to place for tracking UPS, FedEx, USPS, DHL, and Airborne packages.

Backstory: In 2006, I posted a handy new utility I’d cobbled together which was a mashup between package tracking for for multiple services. It quickly became by far the most popular page on this site, with more than 1.4 million tracking requests last month. It gets more than three times the traffic of my movie theater RSS generator and four times the traffic of another spinoff site, FeedSifter, a simple RSS/Atom feed filter.

If you are familiar with MediaTemple’s GridServer service, you’ll know that using up all 1000 GPUs (server work units) for the past several months is not a good thing. Those cycles weren’t just going to waste on poorly written scripts, either. Each hit to the tracker consumed an average of 0.0002 GPU (WordPress uses 8 to 16 times that with each hit). It wasn’t always this way, though. Check back soon for an upcoming post on how I managed to cut down the CPU usage of the package tracker by 90% with some intelligent code analysis and a creative caching solution.

Boxoh.com is now hosted on a screaming VPS server with plenty of spare power. I’m taking full advantage of APC caching and several other behind-the-scenes tweaks one can only get a grip on when they are running a dedicated server.

Thanks to all of the people who have made the service so popular!

Also, thanks to Juplex for a fast and friendly site design!

PHP Closing Tags Stealing Your Cookies?

October 24th, 2008 | By Ian in Development, Opinion, PHP, Rants | 6 Comments »

PHP logoAs a professional PHP developer who enjoys helping others learn about the language, I have noticed several phases of PHP skill development. One of the first phases is when one stops piling all of their code into one file and starts storing their classes and specialized logic into reusable files. For some, this change brings on a wave of problems that may be very difficult to track down.

The Problem

At some point, many PHP developers run into an inexplicable White Page of Death or at least stubborn cookies and headers that won’t change when they should. A common cause is include files with white space after the PHP closing tag. Your web server might send these characters to the browser before you process your header() or setcookie() calls, causing them to fail. PHP allows for a single newline after a PHP closing tag before it starts interpreting characters as output.

Solutions

Omit PHP closing tags
The PHP closing tag is useful when you embed PHP into a page that already contains other content such as an HTML template. However, if you only intend to have PHP logic in a page and nothing else, you can omit the final PHP closing tag:

<?php
$test = new testClass();
$test->helloWorld();
// End of PHP script. No closing tag needed.

This approach does not incur any additional resource penalty to the server.

Output Buffering
If you feel that you need to send output before processing headers and cookies, you should use output buffering. The ob_* class of PHP functions are very useful in these circumstances, but be aware that it comes at the cost of an increased memory footprint and slightly slower processing.

Error Logging
Instead of silently failing or dying with a white page of death, error logging would tell you exactly what is failing and why:

[24-Oct-2008 15:17:31] PHP Warning: Cannot modify header information - headers already sent by (output started at /websites/demo/htdocs/whitespace.php:5) in /websites/demo/htdocs/cookie.php on line 8

I suggest everyone who develops in PHP do so with log_errors enabled. If develop with logging on from the beginning of your project, you will quickly capture potential problems before they grow too great in number and become overwhelming.

I prefer to set my error_reporting level to “E_ALL & E_STRICT” because many standards and best practices are enforced with these messages. (E_STRICT will be included as part of E_ALL in PHP 6)

Once you have logging enabled, you can SSH into your server and “tail” your error log for real-time error output:
[ian@devbox]~ tail -f /tmp/php.log
Using the “-f” flag will follow the log and give continuous output as it appears in the log file.

Please note that logging should be used sparingly (at least at a higher error_reporting level) in production servers. Also, I advise against using PHP’s display_errors in any case, especially production servers. In a production environment, this argument can provide dangerous information to site visitors. You may find it useful in development, but I find that not all errors will be visible or readable when output within your page. However, your log files will never let you down.

A Letter to an Aspiring PHP Programmer

August 6th, 2007 | By Ian in Opinion, PHP, Rants | 5 Comments »

Below is an email I got through Zend’s certified engineer website. The questions posed by the writer below are not uncommon, so I have posted his letter and my response for general consumption.

Hi,

I am an aspiring PHP programmer. I need some advice from the right people like you before taking a plunge into PHP. I know to know what the future holds for PHP in the web development sector. Why is there more demand for ASP.net or Java than PHP when PHP is the best option available for web development. I have heard that PHP professionals are some of the least paid people in the industry, is this true? why should I not go for ASP.NET or Java as compared to PHP? I know it all comes to one’s interest but knowing a stable path for career is also essential. Please help me and my many other colleagues who want to join the PHP community. Your kind help would be highly a appreciated. Please be frank to give your advice.

–Vibhor S.

Vibhor,

Thanks for your email. From my point of view, I am inclined to believe that PHP is actually in higher demand than ASP or Java. However, the latter two are likely to be more common for large companies. I believe this is mostly the result of corporate decision making and the antiquated belief that PHP is not enterprise class. Companies like Facebook, Flickr, and Digg are rapidly dispelling that myth.

The roots of the enterprise class myth also help to explain the question of compensation. PHP started off as a hobbyist’s language. From there, it became the de facto scripting language for low-cost web hosts. As a result, a lot of personal and small business websites sprung up with PHP as a back end. Lacking the project and budget size of medium and large companies, most jobs available to PHP developers were (and perhaps continue to be) for less pay. This is not to say that there are not good paying PHP jobs available. I live in Seattle and am one of a group of 6 PHP developers for a medium sized company. I believe we are competitively compensated compared to the industry at large.

The other part of the compensation problem might have to do with the experience curve of PHP programmers. I have seen many developer resumes and the large majority of people who claim to be PHP experts are in fact novices or even beginners. PHP is a very simple language to learn and become comfortable with, but that comfort is not the same as knowing (and using) best practices, OOP, or even PHP5. Many PHP developers haven’t had any experience working in a collaborative environment and, frankly, may not be suitable for full-time work in a group of developers.

On the question of why one should choose PHP over ASP.NET or Java, I cannot answer. I chose PHP as my language of choice for personal and perhaps arbitrary reasons. I like that it is open source, works best on *NIX systems, is in active development, offers a tool for just about any job, and has a wide and varied user base. It also helps that the language happens to have a sustainable number of companies offering full-time work for PHP developers.

One might just as well choose Java, ASP.NET, Ruby, Python, Perl, C++, or any other popular web language for their own set of reasons. You’ll find ample work with any of these under your belt. Some might have a brighter future than others, but you’ll still find COBOL programmers out there making pretty good money despite the dwindling need for their chosen skills.

I hope this helps. Good luck with your programming.

–Ian

Hello Again, Zend Certified Engineer!

June 12th, 2007 | By Ian in Development, Misc, PHP | No Comments »

Last year, I tested and passed the Zend PHP 4 certification. Once again, I have overcome great adversity and climbed the highest figurative mountains in order to qualify and quantify my bountiful PHP skills.

Ladies and gentlemen, I would like to announce my acceptance of Zend Certified Engineer: PHP 5.

Tune in this time next year for my PHP 6 hat trick.

Tags:

Seattle PHP Programmers: Come to SEAPHP September 12th

August 21st, 2006 | By Ian in Development, Hobbies, PHP, Related sites, Sites of Interest, The Emerald City | 2 Comments »

I’m working to revive the Seattle PHP users’ group. If you’re interested in PHP and live in the Seattle area, come to our next users’ group meeting at the new Seattle Northgate library on September 12th.

Details can be found on the SEAPHP wiki:
http://seaphp.net/

Add it to your calendar:

Offer Alternate Spellings

August 3rd, 2006 | By Ian in Development, PHP | 2 Comments »

If you have a web tool that takes any sort text input for a search, you might find value in intelligently offering alternate spellings.

This technique is best used with an indexed list of proper words where it may be common to misspell based on phonetics. It is not meant to be applied to serial numbers.

First, create a new column in your index table for your alternate spelling key. Then, create a small batch script that fetches every entry from your index and runs the PHP metaphone() function on it. Store the resultant value in the new column you created. Also, make sure you update the code that adds new data to the table to populate your new column.

Now that you have your alternate spelling column populated, simply query the database with a metaphone() of the search term when a search turns up no results. You now have very rudimentary “did you mean” functionality, but it doesn’t stop there.

PHP’s metaphone() is an okay means of getting words similar to one another. In short, it boils the word down to a very basic pronunciation form where “buyh” and “bowwow” are alike. As you can see, metaphone can be far too general. What we need to do next is pick only the most relevant results from the similar words query.

The next step in finding more specific data is to find the words most similar to the one the user originally provided. I use the PHP levenshtein() function which calculates the difference between two strings. Simply ranking the results of the metaphone query by their levenshtein difference will provide you with a reasonable means of emulating the spelling correction/suggestion code used by popular search engines and spell checkers. This final step whittles words similar to “buyh” down to a manageable few, several of which may indeed be what you really meant.

For a demonstration of this type of code in action, check out my Compact Online Dictionary which I built for testing such ideas. The entire application spans only 100 lines of code and includes user-based result relevance ranking.