Skip navigation.

Harold's Home

XML version of this site

PHP Scripts

CLI fun
Mail on 404
HB-NS (NewsScript)


APOD to Desktop
Dreamweaver Extensions


Other stuff
Central Grinder

OOOk Default:

VJ stuff
VJ Tools
Sample Movies


All articles in PHP

A to Z links in PHP
Sometimes you want to add a list of A-Z links to anchors on an existing page that is coming from a database. There are several solutions to this, the easiest being just to create all of those links by hand but this is needlessly tedious.

I came across the following code from an old project.

function oldatoz() // old function, pretty braindead, creates A-Z anchor links
for ($i=65; $i<=90; $i++)
$x = chr($i);
echo " | <a href=\"#$x\">$x</a>";

This gives us an orderly list listing all 26 letters of the alphabet. It's clever in that it uses very little code.

However this can become confusing if the page you have doesn't actually contain all these anchors. What if you want to exclude instances like #Z because there are no listings that start with a Z?

The answer is simple: we'll have to look it up and see what we actually need to use. This isn't too hard if you use SELECT DISTINCT LEFT.

function atoz() // new function, looks in the database for which starting letters are actually in use
$query = "SELECT DISTINCT LEFT(titel, 1) AS anchor FROM links ORDER BY anchor ASC";
$result = mysql_query($query);
while($abcd = mysql_fetch_array($result))
$linky = ucfirst($abcd[0]); // be sleek, sexy and a slinky!
echo " | <a href='#$linky'>$linky</a>";

As you can see this creates a list of anchors that excludes certain items because they are not in use. Insert this function after every 10 records or so using something like if ($j % 10 == 0) atoz();

The downside to this method is that it is inefficient but my database is fairly small and unlikely to grow to millions of records so it's an acceptable tradeoff.

Perhaps next time we'll look at creating the anchors automagically.

HB-NS 1.3 released
I'm pleased to say that version 1.3 of my newsscript is now available for download.

There's some exciting new stuff in this release, here's a partial list:
- As of version 1.3 previews of new articles are saved in the case of a browsercrash or accidental closing of the browserwindow, you can use the admin interface to retrieve the text from the preview, remember to use the preview button!
- Comments are moderated as of version 1.3, however if a poster uses a password and a comment by her has already been approved the new one will be approved automatically.
- Added security fixes for comments: comments can only be deleted by admins (log in to admin.php first), if comments are disabled the form is no longer shown if you know the url to the form and comments are no longer saved even if they're posted by a script for example.

If you're upgrading run upgrade_from_1.2_to_1.3.sql through phpMyAdmin, set your database credentials in config.php, upload the files and you're good to go.

As always: if you're running into problems drop me a note from the contact page.

Host your own PHP urldecoder
I just got a request from someone who wanted to put the urldecoder/urlencoder I have here in the PHP section on their own site. Sure, here's the code for all who want it:

$translate = $_REQUEST['translate'];
$actie = $_REQUEST['actie'];

echo "<fieldset><legend>URL decode or encode the following text:</legend>\n";
echo "<form method=\"get\" action=\"$PHP_SELF\">\n";
echo "<input type=\"text\" name=\"translate\" size=\"60\" value=\"$translate\" /><br /><br />\n";
echo "<label for=\"decode\">urldecode</label> <input type=\"radio\" name=\"actie\" value=\"decode\"";
if ((!isset ($actie)) || ($actie == "decode"))
    echo " checked=\"checked\"";
echo " id=\"decode\" />   <label for=\"encode\">urlencode</label> <input type=\"radio\" name=\"actie\" value=\"encode\"";
if ($actie == "encode")
    echo " checked=\"checked\"";
echo " id=\"encode\" /><br />\n";
echo "<input type=\"submit\" />\n";
echo "</form>\n";
echo "</fieldset>\n";
echo "<br /><br />\n";
echo "<table>\n<tr>\n<td>";
if (isset ($translate))
    echo "original:</td><td>$translate</td></tr>\n<tr>\n<td>";
    if ($actie == "decode")
     echo "urldecoded:</td><td>";
     $translate = htmlspecialchars(urldecode($translate));
     echo "<strong>$translate</strong>";
    if ($actie == "encode")
        echo "urlencoded:</td><td>";
        $translate = urlencode($translate);
        echo "<strong>$translate</strong>";
echo "</td></tr>\n</table>\n";


Calendar code
After months of stagnation I finally got around to hacking my newsscript a bit again, due to a request from a client that uses a modified version of the script.

I have implemented a nifty calendar function.
View this site's calendar now.

Getting a calendar working proved not to be too great a deal, but getting the code to more or less validate did. It's virtually impossible to create a calender without resorting to tables so I didn't even try, I found some code on that did almost what I wanted but that left out a few cells at the end of certain months. I found the solution to that in a comment on the PHP manual page for the date() function, this comment seems to have disappeared however.

Adding some database logic to those combined snippets wasn't too hard so this site is now the proud owner of a calendar where you can see how little I actually publish each month. For what it's worth.

I'll test the system out for a few weeks and roll it into the distribution so you can take a peek.

I just got a bugreport for my online urldecoder.

It appears I was a bit careless and people could inject HTML code that would then get executed by the browser. This is now no longer possible, as the output is run through htmlspecialchars() first.

Just goes to prove that even the simplest of tools need a bit of care. The command line version remains unchanged.

Odd code
I'm currently reading someone else's PHP code and it's a disconcerting thing to read code without any comments whatsoever except for the occasional // insert into database here. This code isn't the most elegant around and shows some really weird things like using nl2br() before inserting into a database and then tediously converting <br /> back to newlines again for the update function.

In fact this reminds me a bit of some code I used to write when I first started with PHP, though I only used that on my own site and didn't use this in production or release.

One of the things I was asked to do was tighten up the security of this app, though I haven't found a really big flaw yet. The code seems ungainly (possibly also due to the extremely unhelpful variable names like $blaat, as in the sound a sheep makes, this is code that has to do with a newspage, nothing about cattle in here, move along) and awkward but it is secure as far as I can tell. (I might still find some big gaping hole as I still haven't figured out what a lot of the files are doing (there's a lot of cruft and dead experiments left behind.))

Still: why would anyone use code to split the parameters from a URL to see what to do in certain circumstances? If you got a URL like it's pretty clear you could just grab the $delete and $id variables from the environment like so:
$delete = $_GET['delete'];
$id = $_GET['id'];

Instead the person writing this used a complicated series of list(), split() and explode().
Fifteen lines wasted, 20 minutes wasted trying to figure out what's happening where and why. Still, it's a fun puzzle and it'll be fun to throw it all out and start afresh if that's what is deemed to only way to salvage this site (and I suspect it might be).

Back to my puzzle.

Logging errors with PHP
I thought I had written about this earlier but I can't find it so perhaps I've only thought about it at some time.
Anyway, it can be quite useful to log some info to the apache error log when a PHP script is accessed.

Here's an example of how to do this using the error_log function:
if ($HTTP_REFERER == "") $HTTP_REFERER = "unknown";
error_log("NOTE: $REQUEST_URI accessed, referer: $HTTP_REFERER");

This will print something like:
[Sun Jan 2 15:13:20 2005] [error] NOTE: /stuff/file.php accessed, referer:

Quick and dirty passwords
For a while now I've been using a function to create random passwords in my PHP webapplications. I've been using the following code: Random Pronounceable Password Generator.

This function creates passwords that are more or less readable which is a big bonus, although I still ask my users to change it to something more memorable to them.

Anyhow, sometimes creating a password on the fly, one at a time, in a webapplication is just not enough and you want to create a bunch of them, say one hundred and fifty (as I had to do this week), so you can process them later and fill a csv-file.

Enter the power of the commandline combined with PHP.

Download this file and rename it to create_password.php. Put the file into your personal bin directory: if that's not already there create a folder named bin in your homedirectory. Make the file executable* and call it from the commandline.

If called just like this: create_password.php it will create ten passwords of ten characters each, but you can also tell it how many characters each password should have and how many to create: create_password.php 6 25. This will create 25 passwords of 6 characters each.

For extra fun of course you could pipe the output to other unix tools like sort, more, perl or whatever: create_password.php 6 25 | sort | bbedit.

*) To make a file executable open a Terminal window and type the following: (chmod 755). Put a space after that and drag the file from the Finder into the Terminal window, hit the enter key. After that is done simply drag the file from the Finder into the Terminal and add optional numbers for the length and number of passwords. Confirm with the enter key and you should see some random passwords to use as you see fit.

[oook:~] harold% create_password.php 7 5
vibu8ur †
bece8e3 †
[oook:~] harold%

†) I did say more or less readable.

Mail on 404
The Mail on 404 PHP script has been slightly updated so it now works with installations that have register_globals off for security reasons (which is A-Good-Idea™).

Newsscript 1.1.8 still imminent
Version 1.1.8 of my newsscript is still under development but the good news is that all known outstanding bugs have been squashed. Even better is that some other bugs were also eliminated because I suddenly noticed them.

If you're reading this through an aggregator you will notice that the comments feed now includes the names of the posters and that the regular feed now shows how many comments on a particular item there are. And yes, this means that once again all items will be marked unread, sorry about that.

I have removed the "feature" whereby expired or not yet available items were (still) available through their permanent link. I'm unsure what to do with the comments on these items though. For the moment these are still available (because it fits my needs better, but mostly because it is a lot less coding) but if anyone has a pressing reason why they shouldn't be shown let me know.

NewsScript Version 1.1.8 imminent
In preparation for the imminent release of version 1.1.8 of this here newsscript I've updated my own site's engine to test it out more fully before unleashing it upon the masses.

Here are the most important changes:
  • Permanent links are now of the form index.php?article=n, without the action=list part (provides easier to read url's and will hopefully be easier for search engines to index).
    As a consequence all the iems you've previously read on this site may be marked as unread in your aggregator, sorry about that.
  • ?action=topic now lists the topics alphabetically instead of the order in which they were entered when you added the topics.
  • Comments are now listed chronologically (oldest first) to ease discussion/reading.
  • Enhancements to the code of the commentsystem (border around preview and much less scrolling when previewing, adding and editing comments).

Useless software
Ah, the joy of useless software.

Here's a PHP script that will allow you to grab the current amount of iTunes downloads so you can get ready to grab the 100 millionth song.

$filename = '';
$fp = fopen("$filename",r);
$contents = fread($fp, 1024);
if (preg_match("/([0-9]+)/", "$contents", $match))
    echo number_format($match[0]);
    echo "Unknown.";

Test it here:
For extra goodness run the following applescript:
set theCount to (do shell script "curl -s ¬")
display dialog "Current iTunes Downloads:" & ¬
    return & return & theCount buttons "OK" ¬
    default button "OK"

Here's how the script looks when run.

Note that Dutch readers won't be allowed to take part, in fact almost no-one, just our American, German, French and British friends as they have their own iTunes stores.
Still, an interesting script, if only because of the use of number_format.

Whoever invented magic quotes should be shot!

Two useful PHP tricks
I got a complaint recently that most of my website is turning out to be about Macintosh stuff and that I'm leaving the poor people who are stuck with Windows behind.

So here's a PHP script* I've written that demonstrates two pretty useful principles, both of these are adaptations on code that's floating around the web but that just didn't quite perform up to my standards, that I needed this week. So I modified it a bit and here it is for your enjoyment.

The problem:
How to print the current directorylisting (with links to all the files) in a nicely formatted table.
As an added bonus the files and the directories should be separated from each other.

The solution:

The above link demonstrates the output and includes the code of listing.phps, the source of the listing.
Confused? Just holler in the comments!

*) Yes, I know, there aren't that many people running PHP on Windows (and why should they) so this could probably be construed as yet another non-Windows thingy. Live with it people, the code works on any practically platform that has PHP installed and is tested on Mac OS X and various *nix systems (four to be exact).

NewsScript Version 1.1.6 is online
After almost a year in development (with lots of breaks to be sure) the next version of the newsscript is online.

Changes since the last public beta:

Version 1.1.6
- The javascript for bbCode is no longer included in the file but referenced as an external file due to a bug in some newer PHP installation.
- bbCode can now also be used in comments (bonus feature).

Version 1.1.5
- Removed a duplicate edit link in the comment section that appeared when you've got both an administratorcookie and have a passwordcookie for a comment entry.

Grab the download here.

Feel free to use the comment section to ask questions.

Newsscript update
Version 1.1.5 of my newsscript (you're looking at it now) is in final beta right now. Grab it here:

Here's the changes since version 1.1.4 (the previous beta version):

- Removed a duplicate edit link in the comment section that appeared when you've got both an administratorcookie and have a passwordcookie for a comment entry.

Actually that's all apart from some minor changes in wording in the comments in the configurationfile.

If I don't get any bugreports this version will be released next week.

Newsscript update
Version 1.1.4 of my newsscript (you're looking at it now) is in beta right now. Grab it here:

Here's the changes since version 1.1.2 (the release version):

Version 1.1.4
- Squashed a few bugs when register globals was off.
- Squashed bug where there was a conflict between the latest headlines and/or latest comments and the main script, if the latest ... was put in the layout before the main script.
- Added tooltips to the admin form elements for adding and updating items (using localised title attributes).
- Fixed some annoying problems with slashes in the comments and the admin module.
- Added a link to show all topics in an installation.
- Added general enhancements to allow for better customisition with CSS.
- Added bbCode for abbreviations: HTML.
- bbCode can be used in comments as well, though there is no interface (like in the admin script) for doing so (as of yet).
- Added a passwordfield to comments so people can edit their own comments, also added a cookie for admin users so they can edit ALL comments.

Version 1.1.3 (previous beta)
- Added a comment option.
- Added an RSS feed for the latest comments (the script defaults to showing the last 10 items, overrule in rss_comments.php, line 12 or on a case-by-case basis:, where n is an arbitrary number).
- New lay-out.
- Topic system introduced.
- You can now only show certain topics in your feed: call the rss feed like so:, where x is the topic of choice (you can still add a certain number of items to show by appending the following: &rss_limit=n).

- Install script added for those without phpMyAdmin or commandline access.

I'd be grateful if people would test it and see if there are any showstoppers in here. As always you can mail me your comments or use the commentssystem that comes with this post.


Unscrupulous Bastards
> Att: Harold Bakker
> Codetransit is about to go through a very major upgrade, we're implementing
> a new backend that we've been working on for months. The new backend will
> make the most advanced script portal online.
> This means we will no longer be using our current backend, so we're
> offering you a copy of our current backend for 199.00 USD.
> [...]
> We can also provide a copy of our database for an
> additional $300, this means you could have a fully commercialized script
> portal without lifting a finger.
> If you're interested please let me know.
> [...]
> --
> If you wish to not receive email regarding codetransit please login to your
> account and change your email address to
> username: Harold
> password: kakap0p0

So let me see,

these guys are offering me the option of buying their backend which doesn't encrypt passwords (which I've just changed by the way, so no use trying it) and are offering any fool out there their entire database? Guess who just got an e-mail asking to remove all my details from their database?

I got the following e-mail regarding the sale of codetransit and my request for removal:

> FYI we won't be selling the contact information

> Just the listings

> Regardless your listings will be removed within the hour.

My details have since been removed.

Here's a cool function if you have register_globals off in php.ini but really really need to enable it for one webapplication: extract($_COOKIE);.
(This can be done for other global variables also like $_SERVER or $_REQUEST.)

Of course register_globals is off for a reason but sometimes you've got an old script that's not written by you and you really really need it and don't have the time (or rather the client doesn't have the money) for you to go over all the code and change it into a completely safe thing.

In the thing I'm working on right now I'm able to figure out all the regular post and get variables but the cookies (used to prevent ballot stuffing) gave me headaches until I came across this function.

news: via RSS
Interesting. Yesterday I was thinking about creating a script that would create an RSS feed for a newsgroup.
Today I came across nntp2rss - access usenet newsgroups via RSS. (Found via Library Stuff.)

There are a few issues with this script though (at least on my setup).
The script assumes a few things that it shouldn't. It assumes that short_open_tag = On and that register_globals = On in php.ini.
nntp2rss.php has a short open tag (which my setup prohibits), add php after the opening <? to make sure it works on your system.

As for the register globals thingy, add the following to the top of nntp2rss.php:
$googleLinks = $_REQUEST['googleLinks'];
$googleThreaded = $_REQUEST['googleThreaded'];
$server = $_REQUEST['server'];
$group = $_REQUEST['group'];
$articles = $_REQUEST['articles'];

After making these changes and editing the settings for my provider's newsserver the script works flawlessly, though I'm not sure how useful it will be for high-volume newsgroups.

According to Brent, the author of NetNewsWire:
the more expensive the CMS, the crappier the URLs.

John Udell gives a couple of examples to support this theory.

So how does this reflect on my own newssystem which I'm currently converting to a blogging system (just what the world needs, right?, right?)?

At the moment permanent links (aka permalinks) look like this:

This means there is a PHP script which displays the entry belonging to the id named in the url.
This data is in a MySQL database, and we use PHP to extract it and dynamically create a page. Lovely system but the url's look ugly.
Worse still, they don't convey much meaning and a spider like Google (which provides about 90% of my search engine referrals) doesn't quite know what to do about them, so it just ignores them. Now systems like Blogger create html files which google knows and deals with properly.

Now there could be a couple of solutions to this problem:
  1. I could generate HTML documents and put them on the server, giving each an unambigious name
  2. I could use Apache's mod_rewrite to rewrite the urls to a more pleasing format

  3. I could ignore the problem
  4. I could devise a system whereby a url would become simpler and yet convey more meaning

Objections against these solutions (numbers correspond to the 'solution' above):
  1. I would force my users to give certain areas of their website write-access to the script, a potential security risk
  2. Most users won't have access to do this, besides mod_rewrite is HARD
  3. A good one, wait for Google et al to catch up, problem is will this ever happen?
  4. I did just this, there's a problem though, but it might not be really terrible and even be a bonus

First, here is what a permanent link could look like in my new system: (don't try it, the system isn't in place yet).
It is obvious that ?urlsAreTitlesToo conveys much more meaning than ?action=list&id=57.
What the system does in fact is perform a search for ALL entries that have "urlsAreTitlesToo" as the title. This means that if we have two entries called "urlsAreTitlesToo" we will get two results and the script will display both.
This is a bonus because if a visitor is interested in the topic, as conveyed by the title, she'll probably be interested enough to read both articles.
This is also a problem because the page can still change and thus could confuse a search engine or human reader.

It appears that I may not have solved the problem entirely, but the script has a cool new feature anyway. Now all I need to do is give the permalink choice to the person who installs the script and this should be trivial.

PHP from the Command Line
Found via Daring Fireball: an installer package for the commandline version of PHP for Mac OS X: somebody dial 911.

Easy to install and great fun.
I'm playing around with this at the moment but expect to see a small example later this week (possibly tonight but who knows what might happen, I gotta eat too you know...).

it's here, a commandline php script to urldecode or urlencode a string of text.

Newsscript Version 1.1.2 released
I have just released the newest version of the newsscript. It features minor codeenhancements, some small sample modules (search and a sidebar to include the latest headlines on any php page) and an RSS feed. It is also pretty easy to localise for other languages, English and Dutch are included.

Aside from small bug-fixes this will probably be the last version for a while. I'm thinking of turning the thing into more of a blogging tool than a newsscript. Feel free to mail me your thoughts on this or use the poll on the PHP scripts index page.

Tip of the day: addslashes()
Accesslogs are a wonderful thing.

To the person who wanted to know how to embed apostrophes in mysql:
the function you're looking for is addslashes($variable_name);
I assume you're using PHP here.

404 script
I have added a snippet of PHP code to the PHP section that will send an e-mail to the webmaster every time a page is requested that is no longer there.

Newsscript update
The new version of the newsscript is coming along nicely. I just added an rss feed option to it.
Paste the following url in your favorite RSS reader *:

There's still some tweaking to do on other modules but it's looking good. More news as it happens.

*) A comprehensive guide to available readers can be found here.

Update: This rss stuff is kinda cool. I have added a user configurable limit to the rss script, just call the script with the parameter ?rss_limit=n, where n is the number of items you want to view, it defaults to 6 but if you want to see 10 you can do so easily:

Newsscript update
A new version of the newsscript is coming along nicely. I have squashed a small bug in the currently released version that prevents the display in the admin interface when you have just added a newsitem but selected preview first. The item IS added, it's just the admin interface getting confused.

I have added localisation options which should make it really easy to support additional languages, Dutch and English will be supplied in the distribution.
I am also working on some small modules to enable one to search articles or add a sidebar to any php-based page with extracts from the latest three articles, but some work remains to be done on this.

I hope to release a new version later this month, check back and be sure to tell me which feature you would like me to add first.
If you would like to receive a message when a new version is released just use the form on the contact page.

Newsscript 1.1 available
The newsscript has been updated.
The new version will allow quick insertion of bbCode like bold text, email adresses:, quotes and the like.

Feel free to test the script using the administrative pages.

The script now also has a preview mode, which was often requested.

Here are the full changes:
Version 1.1.1
- Steamlined workflow in newsadmin.php so much less clicking is required when doing maintenance.
- The email a webmaster receives when a newsitem has been updated is much more readable.
- Lots of code modifications and added comments to enhance readability.
- Fixed a bug that could lead to double entries in the database when updating newsitems.
- Made the dateformats for news expiry and queueing a bit more readable.
- The script now correctly deals with apostrophes ( ' ) in text and titles, like in Persons's Home.
- Fixed a problem with the titles of the user interface.
- Added a much needed preview mode so you can freely change, add or remove text, see how it looks and only if you're completely satisfied commit those changes to the database, previously the item would become available immediately allowing visitors to see all your spelling mistakes.
- The script now not only accepts HTML but also a subset of bbcode, you can easily add hyperlinks, images, quotes, bold, italic and monospaced text. I have decided not to include font formatting like: small red serif words as this kind of thing is deprecated in HTML 4, which the script outputs. If you want to add such styles you have a couple of options: modify the code or write html.
- Almost all options to modify the script to your liking have been moved to configuration.php, you will no longer need to add the database specifications to both the index and newsadmin pages.

Newsscript update
Work on the new version of the newsscript is coming along nicely. Here is what I have so far:
Version 1.1.1
- Steamlined workflow in newsadmin.php so much less clicking is required when doing maintenance.
- The email a webmaster receives when a newsitem has been updated is much more readable.
- Minor code modifications to enhance readability.
- Fixed a bug that could lead to double entries in the database when updating newsitems.
- Made the dateformats for news expiry and queueing a bit more readable.

Still to do:
- bbCode (half of those who voted want it)
- Deal with some special characters like ╦ and ╬

I hope to have the new version up by christmas, don't expect it sooner as I'm also trying to have a life.

Where next?
QuickPoll for new functionality in the newsscript
I have added a quick poll to see if you would like me to include some code (like the popular bbCode that's often used in various forums) in HB-NS so you can easily add styled text. Please take a moment to vote.

Thanks, Harold.

Newsscript download fixed
I just found out I made a stupid mistake when I packaged the targzip of newsscript, I forgot to include the readme, which is essentially the same as the one on this page. The stuffit and zip archives are not affected but if you downloaded an incomplete targzip you can download it again by clicking here.

Apologies for the confusion.

Newsscript updated
A new version of the PHP newsscript is available immediately. New features include:
  • mailing submissions to the webmaster
  • better customisation of visitor pages
  • security for the admin script
  • ability to queue news items and have them expire at a certain date

See the readme for more details.

Newsscript update
Work on the next version of the PHP newsscript is coming along nicely, it should be ready in a week or two. I am working on automatic newsexpiry, admin script security and mail functionality for collaborative newspages.

I am still looking for more suggestions though, so feel free to mail me.

Newsscript update
Fixed a minor problem with the php script I released a few days ago. This is from the readme:

Version 1.0.1
This version fixes a small problem where the current pagenumber wasn't shown correctly in the header, ie.:
13 newsitems found. Page 1 of 2.

The page x of y wasn't shown correctly. It is fixed now, silly mistake, if you don't feel like downoading again just look for the commented out line
//$page_num = $cur_page + 1;// page number counter
in index.php and remove the first set of comment markers so the line will read:

$page_num = $cur_page + 1;// page number counter

Sorry for the mistake.

Newsscript released
Woo and jay!

my first PHP script is released, it's a simple newsscript and is (as usual) completely free.
The script is similar to what I use for the news you're reading now on the homepage.
Check it out, there's a demo too, so you can testdrive before you download.

Show all items | Read all items | Show topics

About, copyright, privacy and accessibility | Mail