Archive for the ‘Web Apps’ Category

A More Useful WordPress 404

Sunday, November 23rd, 2008
Posted in Web Apps · Tags:

Recently A List Apart had an article by Dean Frickey titled A More Useful 404. It was a good article about making a more useful 404 page that attempts to figure out what went wrong and it will email you some information. I modified the code from Perl to PHP for WordPress and figured I’d save people time from building it themselves by posting it here. Feel free to edit what you need to. The code goes inside your 404.php template.

//based on
//just to break any email addresses or spam that might get spoofed in falsed headers, might just use a regex later
$disallowed_strings = array('@', '\t', '\r', '\n', '\v', '\f', '<', '>');
$clean_server_name = preg_replace('/[^a-zA-Z0-9\-\.]/', '', $_SERVER['SERVER_NAME']);
$clean_http_referer = str_ireplace($disallowed_strings, '', $_SERVER['HTTP_REFERER']);
$clean_request_uri = str_ireplace($disallowed_strings, '', $_SERVER['REQUEST_URI']);
$search_engine_domains = array('', '', '', '', '', '', '', '');//add more if you want
$search_message = '<p>You may want to try searching this site or using our <a href="' . get_bloginfo('url') . '/sitemap/">sitemap</a> to find what you were looking for.</p>';//if you have a sitemap
<p>Sorry, but the page you were trying to get to <!--http:// ,--> does not exist.</p>
if ($_SERVER['HTTP_REFERER'] == '')
<p>It looks like this was the result of either</p>
<li>a mistyped address</li>
<li>or an out-of-date bookmark in your web browser.</li>
echo $search_message;
//make it easier to search referer
$disallowed_url_strings = array('http://', 'https://', 'www.');//filter out https:// anyway
$referer = str_ireplace($disallowed_url_strings, '', $_SERVER['HTTP_REFERER']);
$referer_array = explode('/', $referer);
$referer = $referer_array[0];
$myblog_url = get_bloginfo('url');
$myblog_url = str_ireplace($disallowed_url_strings, '', $myblog_url);
$myblog_url_array = explode('/', $myblog_url);
$myblog_url = $myblog_url_array[0];
if ($referer == $myblog_url)
<p>Apparently, we have a broken link on our page. An e-mail has just been sent to the person who can fix this and it should be corrected shortly. No further action is required on your part.</p>
$email_subject = 'Broken link on my site, ' . $clean_server_name;
$email_message = 'BROKEN LINK ON MY SITE' . "\r\n\r\n" . 'There appears to be a broken link on my page, ' . $clean_http_referer . " \r\n\r\n" . ' Someone was trying to get to ' . $clean_request_uri . ' from that page.';
$email_message .= "\r\n\r\n" . 'Why don\'t you take a look at it and see what\'s wrong?';
mail(get_bloginfo('admin_email'), $email_subject, $email_message, 'FROM:');
//see if it was a search engine
$domains_matched = 0;
$total_domains = count($search_engine_domains);
for ($x = 0; $x < $total_domains; $x++)
if ($referer == $search_engine_domains[$x])
if ($domains_matched != 0)
<p>It looks like the search engine has returned a link to an old page. These old links should eventually be removed from their indexes but since these are automatically generated there is no one to contact to try to correct the problem.</p>
echo $search_message;
<p>Apparently, there is a broken link on the page you just came from. We have been notified and will attempt to contact the owner of that page and let them know about it.</p>
echo $search_message;
$email_subject = 'Broken link on somebody else\'s site.';
$email_message = 'BROKEN LINK ON SOMEBODY ELSE\'S SITE' . "\r\n\r\n" . 'There appears to be a broken link on the page, ' . $clean_http_referer . " \r\n\r\n" . ' Someone was trying to get to ' . $clean_request_uri . ' from that page.';
$email_message .= "\r\n\r\n" . 'Why don\'t you take a look at it and see if you can contact the page owner and let them know about it?';
mail(get_bloginfo('admin_email'), $email_subject, $email_message, 'FROM:');

WordPress Recent Comments Hack

Wednesday, August 27th, 2008
Posted in Web Apps · Tags: ,

I wanted to get the most recent comments in WordPress without having to use the widgets or any plugins. When you use any of the widgets it will override the sidebar.php (although you could put what you needed in a else bracket inside sidebar.php, but I figured I’d put this hack together anyway).

This hack would go in your sidebar.php

$comment_array = $wpdb->get_results("SELECT comment_date_gmt, comment_author, comment_ID, comment_post_ID FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 10");
$comment_total = count($comment_array);
echo '<ul>';
for ($x = 0; $x < $comment_total; $x++)
echo '<li>';
echo $comment_array[$x]->comment_author . ' on ';
echo '<a href="'. get_permalink($comment_array[$x]->comment_post_ID) . '#comment-' . $comment_array[$x]->comment_ID . '">';
echo get_the_title($comment_array[$x]->comment_post_ID);
echo '</a>';
echo '</li>';
echo '</ul>'

A Customizable Tag Cloud For WordPress

Tuesday, August 26th, 2008
Posted in Web Apps · Tags: ,

If you’ve tried using wp_tag_cloud() as an array, you’ve noticed that all it really does is give you a string, which isn’t useful. The only way I could figure out how to get the tags to where I can format them how I want was to call get_tags() in wp-includes/category.php. You can also pass arguments to it to sort it differently. Take a look at get_terms() in wp-includes/taxonomy.php to get an idea of what you can do.

Here is a hack I put together that will output your tags as a unordered list (UL) with the total number of times the tag is used in parenthesis. You can place this code in sidebar.php

$tag_array = get_tags('orderby=count&order=DESC&number=15');
$tag_total = count($tag_array);
echo '<ul>';
for ($x = 0; $x < $tag_total; $x++)
echo '<li>';
echo '<a href="' . get_option('home') . '/tag/' . $tag_array[$x]->slug . '/" rel="tag">';
echo $tag_array[$x]->name;
echo '</a>';
echo ' (' . $tag_array[$x]->count . ') ';
echo '</li>';
echo '</ul>';

PunBB forks into FluxBB

Friday, May 9th, 2008
Posted in Web Apps · Tags: ,

Is this a repeat of what happened to Mambo and Joomla!?

Awhile back the rights to PunBB were sold to a company.

Apart from sponsoring the project, they wanted to later down the line offer paid-for web services in relation to PunBB (for example commercial grade PunBB hosting). We decided we liked the idea and sold the rights to the project.

Then a recent switch to a new domain occurred.

Moving the PunBB website under the domain is a way for our benefactors to promote their other services to the PunBB community and to promote PunBB to users of their other services.

Today many of the active developers mentioned they were forking the project into what they call FluxBB.

Some of you may have been wondering about the future of PunBB and the current development team following Rickard’s announcement that he will not be actively involved with PunBB, at least for the time being. … Now that circumstances have changed with the inevitable shift of power within the project, we all feel that we need a degree of control over future development which is no longer possible. We all share a desire to develop software for the benefit of the community and ourselves, without commercial concerns influencing the final product. This is not a condemnation of PunBB’s current owners: we simply feel that this change is necessary so that we as developers can maintain full control over the development process.

It didn’t bother me they had sold the rights to PunBB as long as it remained GPL, but what this split means now, I’m not sure. How many people will now abandon PunBB for FluxBB? A lot depends on how active the FluxBB project becomes and if the new PunBB development takes off.

Last Modified Posts in WordPress

Saturday, March 8th, 2008
Posted in Web Apps · Tags: ,

Want to show the last posts you updated in WordPress? This shows the posts you went back and updated or modified, which is different than your recent posts.

if (have_posts())
echo '<h3>Last Modified Posts</h3>';
echo '<ul>' . "\n";
while (have_posts()) : the_post();
echo '<li>';
echo '<a href="' . get_permalink() . '">' . the_title('','', false) . '</a>';
echo '</li>' . "\n";
echo '</ul>';

RSS feeds in PunBB

Saturday, March 8th, 2008
Posted in Web Apps · Tags: ,

These are quick easy hacks to get RSS feeds for each forum on the index.php page and viewforum.php pages.

I covered how to put the main RSS feed on PunBB already.

Open up index.php and after this line

$forum_field = '<h3><a href="viewforum.php?id='.$cur_forum['fid'].'">'.pun_htmlspecialchars($cur_forum['forum_name']).'</a></h3>';

Add this

$forum_field .= '<div class="forum_rss"><a class="rss" href="extern.php?action=active&type=RSS&fid='.$cur_forum['fid'].'"><span>RSS</span></a></div>';/

Now open up viewforum.php and find this line

<h2><span><?php echo pun_htmlspecialchars($cur_forum['forum_name']) ?></span></h2>

and modify it to be

<h2><span><?php echo pun_htmlspecialchars($cur_forum['forum_name']) ?> <a class="rss" href="extern.php?action=active&type=RSS&fid=<?php echo $id /*MODIFIED - RSS*/ ?>"><span>RSS</span></a></span></h2>

And now for the CSS

.forum_rss {float:right;}
a.rss {background:url(../../img/feed.png) no-repeat left; width:16px; height:16px; padding-left:20px;}
a.rss span {display:none;}

Odd and Even Forums and Hot Icons for PunBB

Tuesday, February 12th, 2008
Posted in Web Apps · Tags: ,

PunBB adds classes for odd and even posts, but not for odd and even forum rows. PunBB also adds several classes for icons we can tap into, but there is no way to know if a topic is “hot”. Let’s add a hack that will mark any topic that has more than 25 posts as “hot” and setup odd and even forum rows.

Open up viewforum.php

Find this line

// If there are topics in this forum.
if ($db->num_rows($result))

And add this afterwards

$temp_counter = 0;

Then find this line

// Should we show the "New posts" and/or the multipage links?
if (!empty($subject_new_posts) || !empty($subject_multipage))
$subject .= '  '.(!empty($subject_new_posts) ? $subject_new_posts : '');
$subject .= !empty($subject_multipage) ? ' '.$subject_multipage : '';

And add this afterwards


Then find this line

<tr<?php if ($item_status != '') echo ' class="'.trim($item_status).'"'; ?>>

And modify it to be this instead

<tr class="<?php
if ($temp_counter % 2)
echo 'forum_rowodd';
echo 'forum_roweven';
$temp_status = trim($item_status);
if (($cur_topic['num_replies'] > 25) && ($temp_status == '' || $temp_status == 'inew'))
if ($temp_status == '')
echo ' ihot';
echo ' ihot_inew';
else if ($item_status != '')
echo ' '.trim($item_status);

Now for CSS

/*style rows*/
tr.forum_rowodd {background-color:#eee;}
tr.forum_rowodd td.tc2, tr.forum_rowodd td.tc3 {background-color:#ddd;}
tr.forum_roweven {background-color:#ccc;}
tr.forum_roweven td.tc2, tr.forum_roweven td.tc3 {background-color:#bbb;}
/*style hot and hot new posts*/
tr.ihot div.icon {background-image:url(../../img/hot.png);}
tr.ihot_inew div.icon {background-image:url(../../img/hot_new.png);}
/*css we used for icons before*/
div.icon {
background-position:center center;
border:0 !important;
/*if you aren't using any images you can use something like this
tr.ihot DIV.icon {BORDER-COLOR: #600 #700 #800 #900}
tr.ihot_inew DIV.inew {BORDER-COLOR: #006 #007 #008 #009}

I updated code the code, since I didn’t like how it was before

WordPress Spam Prevention Hack

Sunday, February 10th, 2008
Posted in Web Apps · Tags: , ,

Akismet catches a lot of spam, but there is a lot it won’t catch. Therefore I decided to put together a hack to catch some more. The hack has 2 options:

  • One for you to put in spam words that if they are in the comment, the whole comment will be considered spam. Just be careful, if you add cialis you will block the word specialist also.
  • The other option lets you set the maximum number of links you will allow in a comment.

It will catch links that start with http://, https://, http://www., https://www. and www.. WordPress doesn’t convert text like into a link.

The hack also checks to see if there is more content in the comment than just A tag(s), if there isn’t it’s considered spam. I recommend to use this with the Akismet plugin because it won’t prevent all spam. Keep in mind this hack may not work with other spam prevention plugins.

Open up wp-comments-post.php and after these lines

if ( '' == $comment_content )
wp_die( __('Error: please type a comment.') );

Add the following:

else /*MODIFIED - added this else to filter strings and count links*/
$link_limit = 3;//set the maximum number of links we allow
$disallowed_strings = array('[url', '[/url]', 'zithromax', 'levaquin');//add any strings you wont allow, make them lowercase, we test for case insensitivity later
$temp_comment = strtolower($comment_content);//lowercase text so we can be case insensitive, php4 doesnt have stripos
$total_disallowed_strings = count($disallowed_strings);
//look for disallowed strings
for ($temp_counter = 0; $temp_counter < $total_disallowed_strings; $temp_counter++)
if (strpos($temp_comment, $disallowed_strings[$temp_counter]) !== false)
wp_die( __('Sorry, that looks like spam.') );
$comment_links = 0;
//regex would be better
$link_strings = array('http://www.', 'https://www.', 'http://', 'https://', 'www.');//order is important here
$temp_comment = str_replace($link_strings, '[LINK]', $temp_comment);
$comment_links = substr_count($temp_comment, '[LINK]');
//test for number of links
if ($comment_links > $link_limit)
wp_die( __('Sorry, that looks like spam.') );
//weed out all A tags and see if anything is left
$temp_comment = preg_replace('/<a[^\<]{1,}\<\/a\>/', '', $temp_comment);
$temp_comment = trim($temp_comment);
//see if the comment is nothing but links
if (empty($temp_comment))
wp_die( __('Sorry, that looks like spam.') );

Gallery2 vs Zenphoto vs Plogger

Tuesday, February 5th, 2008
Posted in Web Apps · Tags: , ,

Here I cover some of the features of the best open source PHP image gallery web applications.

Gallery 2

  • Multiple uploads via JavaScript (can add more file upload boxes)
  • Uploads by e-mail, ZIP or multiple image files
  • Configurable to run from multiple sites from one install
  • Reorder album via JavaScript
  • Ratings
  • Plugins available
  • Can’t protect original sizes of images


  • Multiple uploads via JavaScript (can add more file upload boxes)
  • Uploads by ZIP or multiple image files
  • Spam filter options (Akismet, CAPTCHA, SpamAssassin, …)
  • Reorder album via JavaScript
  • AJAX editing of albums and images
  • Ratings
  • Watermarks
  • Can’t protect original sizes of images (except with a watermark)
  • RSS feed


  • No multiple uploads via JavaScript (can’t add more file upload boxes)
  • Uploads by ZIP or single image files
  • Import from folder (you can FTP all images to a folder and have it import the images from that folder)
  • You can protect the original size images
  • RSS feed

All of these have a clean interface and design, search, EXIF data, subfolder/album creation, cruft-free URLs (for SEO), and comments (Gallery requires the comments plugin to be enabled).

It comes down to what your needs are, if you want something that can run on multiple sites Gallery 2 is the app to choose. If you have to protect your original size images you’ll want to use Plogger. I personally think Zenphoto has the most to offer and the best design out of the bunch, but they are all very well done. I went through all the ones on OpenSourceCMS and these were the best. Coppermine is popular but it’s too ugly and the admin is kind of confusing.

More PunBB Styling

Monday, February 4th, 2008
Posted in Web Apps · Tags: ,

Want to style the usertitles in PunBB based on their usertype (as in styling admins, moderators, members and guests)? Open up viewtopic.php and after this line
<div class="postleft">

We are going to modify the DL to this:

<dl class="<?php
if ($user_title == 'Administrator')
echo 'usertype_admin';
else if ($user_title == 'Moderator')
echo 'usertype_mod';
else if ($user_title == 'Member')
echo 'usertype_member';
else if ($user_title == 'Guest')
echo 'usertype_guest';

I added it a little higher than you might of assumed, so you can style the username and avatars if you want also. Its easy to add new types if you have more groups than the standard ones.

Now for more CSS to make PunBB not so boring:

/*styles for the usertype hack*/
dd.usertitle {padding-left:20px; height:16px;}
dl.usertype_admin dd.usertitle {background:url(../img/award_star_gold_3.png) no-repeat left;}
dl.usertype_mod dd.usertitle {background:url(../img/bronze_medal.png) no-repeat left;}
dl.usertype_member dd.usertitle {background:url(../img/vcard.png) no-repeat left;}
dl.usertype_guest dd.usertitle {background:url(../img/status_offline.png) no-repeat left;}
/*style your announcements*/
DIV#announce H2 {BACKGROUND-COLOR:#ffc}
DIV#announce {BORDER-COLOR:#f90 #f90 #f90}
DIV#announce DIV.inbox {BACKGROUND-COLOR:#ffc}
/*style errors*/
DIV#posterror H2 {BACKGROUND-COLOR:#bf3030; color:#ff0;}
DIV#posterror {BORDER-COLOR:#bf3030 #bf3030 #bf3030}
DIV#posterror DIV.inbox {BACKGROUND-COLOR:#592d2d}
#posterror LI STRONG {COLOR:#ff0}
/*style messages (info boxes from punbb)*/
DIV#msg {color:#fff;}
DIV#msg H2 {BACKGROUND-COLOR:#bfbf8f; color:#000;}
DIV#msg {BORDER-COLOR:#bfbf8f #bfbf8f #bfbf8f}
DIV#msg DIV.inbox {BACKGROUND-COLOR:#808060}
DIV#msg a {color:#89d9ff;}
DIV#msg a:hover {color:#b8ffff;}
/*style even row posts, odd posts will get default styling already set to them*/
DIV.roweven, DIV.roweven DIV.postright, DIV.roweven DIV.postfootright {BACKGROUND-COLOR:#c9c}
DIV.roweven DIV.postright, DIV.roweven DIV.postfootright {BORDER-LEFT-COLOR:#dad}
DIV.roweven DIV.postleft, DIV.roweven DIV.postfootleft, DIV.roweven DIV.blockpost LABEL {BACKGROUND-COLOR:#dad;}
DIV.roweven H2 {BACKGROUND-COLOR:#fcc}
DIV.roweven {BORDER-COLOR:#fcc #fcc #fcc}
/*style first post*/
DIV.firstpost, DIV.firstpost DIV.postright, DIV.firstpost DIV.postfootright {BACKGROUND-COLOR:#c96 !important;}
DIV.firstpost DIV.postright, DIV.firstpost DIV.postfootright {BORDER-LEFT-COLOR:#da7 !important}
DIV.firstpost DIV.postleft, DIV.firstpost DIV.postfootleft, DIV.firstpost DIV.blockpost LABEL {BACKGROUND-COLOR:#da7 !important}
DIV.firstpost {BORDER-COLOR:#fc9 #fc9 #fc9 !important}
DIV.firstpost H2 {BACKGROUND-COLOR:#fc9 !important;}
div.firstpost h2 span a, div.firstpost h2 span a:link, div.firstpost h2 span a:visited {color:#ccc !important;}
DIV.firstpost DIV.postright .postmsg {background:url(../../img/firstpost.png) no-repeat top right;}