You know when you you’re working on a project and get stuck on something, so you scour the Web for solutions only to find that everyone else seems to be experiencing the exact same thing. Then, after many hours trying everything possible, you finally stumble onto something that seems to work. This time, the project was setting up a secure downloads area for Digging into WordPress. And when I finally discovered a solution, I told myself that it was definitely something I had to share here at Perishable Press.
Apparently, there is much to be desired when it comes to sending proper HTTP headers for file downloads. Different browsers (and not just IE) require different headers, and will error if not present exactly the way they expected. Confounding that equation is the fact that different file types also require specific headers. Then there are issues with sending an accurate (or should I say “acceptable”?) Content-Length headers when file compression is involved. Needless to say, finding a set of headers that works for all file types in all browsers is next to impossible. And I won’t even get into the issues involved with readfile() and large-download file-sizes.
One of my favorite security measures here at Perishable Press is the site’s virtual Blackhole trap for bad bots. The concept is simple: include a hidden link to a robots.txt-forbidden directory somewhere on your pages. Bots that ignore or disobey your robots rules will crawl the link and fall into the trap, which then performs a WHOIS Lookup and records the event in the blackhole data file. Once added to the blacklist data file, bad bots immediately are denied access to your site. I call it the “one-strike” rule: bots have one chance to follow the robots.txt protocol, check the site’s robots.txt file, and obey its directives. Failure to comply results in immediate banishment. The best part is that the Blackhole only affects bad bots: normal users never see the hidden link, and good bots obey the robots rules in the first place.
In five easy steps, you can set up your own Blackhole to trap bad bots and protect your site from evil scripts, bandwidth thieves, content scrapers, spammers, and other malicious behavior.
The Blackhole is built with PHP, and uses a bit of .htaccess to protect the blackhole directory. The blackhole script combines heavily modified versions of the Kloth.net script (for the bot trap) and the Network Query Tool (for the whois lookups). Refined over the years and completely revamped for this tutorial, the Blackhole consists of a single plug-&-play directory that contains the following four files:
Jeff Morris recently demonstrated a potential issue with the way WordPress handles multipaged posts and comments. The issue involves WordPress’ inability to discern between multipaged posts and comments that actually exist and those that do not. By redirecting requests for nonexistent numbered pages to the original post, WordPress creates an infinite amount of duplicate content for your site. In this article, we explain the issue, discuss the implications, and provide an easy, working solution.
Understanding the “infinite duplicate content” issue
Using the <!--nextpage--> tag, WordPress makes it easy to split your post content into multiple pages, and also makes it easy to paginate the display of your comment threads. For both paged posts and paged comments, WordPress appends the page number to the permalink. So for example, if we have a post split into 3 pages, WordPress will generate the following set of completely valid permalinks (based on name-only permalink structure):
Whenever I find myself working with PHP or messing around with server settings, I nearly always create a phpinfo.php file and place it in the root directory of whatever domain I happen to be working on. These types of informational files employ PHP’s handy phpinfo() function to display a concise summary of all of your server’s variables, which may then be referenced for debugging purposes, bragging rights, and so on.
While this sort of thing is normally okay, I frequently forget to remove the file and just leave it sitting there for the entire world to look at. This of course is a big “no-no” for site security, because the phpinfo.php file contains a hefty amount of information about my server, including stuff like:
The web server version
The IP address of the host
The version of the operating system
The root directory of the web server
Configuration information about the remote PHP installation
The username of the user who installed php and if they are a SUDO user
A few months ago, many WordPress sites were attacked with some extremely malicious code. While searching for a good solution, I discovered the following gem of a plugin in the pastebin repository:
<?php /* Plugin Name: Block Bad Queries */
if (strlen($_SERVER['REQUEST_URI']) > 255 ||
strpos($_SERVER['REQUEST_URI'], "eval(") ||
strpos($_SERVER['REQUEST_URI'], "base64")) {
@header("HTTP/1.1 414 Request-URI Too Long");
@header("Status: 414 Request-URI Too Long");
@header("Connection: Close");
@exit;
} ?>
This script checks for excessively long request strings (i.e., greater than 255 characters), as well as the presence of either “eval(” or “base64” in the request URI. These sorts of nefarious requests were implicated in the September 2009 WordPress attacks.
One of the most popular articles here at Perishable Press is my January 2005 post, Stupid htaccess Tricks. In that article, I bring together an extensive collection of awesome copy-&-paste HTAccess code snippets. Four years later, people continue to tell me how much they enjoy and use the content as a bookmarked reference for many of their HTAccess needs. The article was even published in a book on Joomla! Security.
This is very inspiring to me, so I have decided to create a similar post for all of the useful WordPress code snippets, tips and tricks that I have collected while working on Digging into WordPress, the new book by co-author Chris Coyier and myself that really “digs in” to all of the awesome ways to get the most out of WordPress. While writing the DiW book, I collected hundreds of incredibly useful WordPress tips and tricks. After packing the book with as many of these techniques as possible, I decided to share the “best of the rest” here at Perishable Press.
If you are one of the millions of people who use WordPress, this article will help you improve the appearance, functionality, and performance of your WordPress-powered websites. Each of these “stupid WordPress tricks” is presented as clearly and succinctly as possible, including as many notes, instructions, and pointers as needed for successful implementation. Of course, keep in mind that we are only scratching the surface here. For a much more complete resource that is packed with tons of tasty techniques, you need to get Digging into WordPress.
Let’s face it. There’s just as much scum on the Internet as there is out there in the “real world.” Maybe even more, who knows. From scammers and spammers to scrapers and crackers, the Web is just crawling with all sorts of pathetic scumbags. As predictably random as much of the malicious activity happens to be, it is virtually guaranteed that you will be hounded by at least a few persistent IP addresses that, for whatever reason, have latched on and just won’t let go. Like satanic parasites, they plague you night and day, haunting you and making your online life a living hell. Perhaps they leave endless spam comments; perhaps they are just mindless trolls giving you grief; or perhaps they continue to take flying stabs at the security of your website. Whatever the behavior, once you have determined that you need to block a collection of evil IPs, you have manychoices. Here is a simple way to blacklist multiple IP addresses with a little PHP magic..
When designing sites, it is often useful to identify different pages by adding an ID attribute to the <body> element. Commonly, the name of the page is used as the attribute value, for example:
<body id="about">
In this case, “about” would be the body ID for the “About” page, which would be named something like “about.php”. Likewise, other pages would have unique IDs as well, for example:
..again, with each ID associated with the name of the page. This identification strategy is useful for a variety of reasons, including the following:
Page-specific control over CSS via descendant selectors
Page-specific DOM manipulation via JavaScript
Page-specific control over the navigational interface, current-page highlighting et al
Page-specific content-inclusion via conditional PHP if() statements
For page-specific control over your design, using the current page name as the body ID will certainly do the trick. The question is, what is the best way to go about defining the different attributes? For static sites or for sites with only a few pages, it might be easiest to just add the IDs manually. For larger, dynamic sites, however, you can automate the process with the magical powers of PHP.
Importing and displaying external RSS feeds on your site is a great way to share your online activity with your visitors. If you are active on Flickr, Delicious, Twitter, or Tumblr, your visitors will enjoy staying current with your updates. Many social media sites provide exclusive feeds for user-generated content that may be imported and displayed on virtually any web page. In this article, you will learn three ways to import and display feed content on your WordPress-powered website — without installing yet another plugin.
In addition to your choice collection of “Share This” links, you may also want to provide visitors with a link that enables them to quickly and easily send the URL permalink of any post to their friends via email. This is a great way to increase your readership and further your influence. Just copy & paste the following code into the desired location in your page template:
<a href="mailto:?subject=Fresh%20Linkage%20@%20Perishable%20Press&body=Check%20out%20<?php the_permalink(); ?>%20from%20Perishable%20Press" title="Send a link to this post via email" rel="nofollow">Share this post via email</a>
Within the code, you will need to edit both instances of the string “Perishable%20Press” to reflect your own site name. Note that the “%20” is the encoded equivalent of a blank space, and is required to ensure validation of parameterized query strings. As is, the code will generate an email that is populated with the following information:
Here at Perishable Press, the number of posts listed in my archives is rapidly approaching the 700 mark. While this is good news in general, displaying such a large number of posts in an effective, user-friendly fashion continues to prove challenging. Unfortunately, my current strategy of simply dumping all posts into an unordered list just isn’t working. I think it’s fair to say that archive lists containing more than like 50 or 100 post titles are effectively useless and nothing more than a usability nightmare. With growing numbers of blogs building up massive collections of posts, finding better ways to display vast quantities of archived material becomes increasingly important.
One solution that seems popular involves breaking the archives down into various categories, tags, and time periods. This provides meta-context to each list of titles and usually eliminates the need for any hideously long post listings. This solution works well, especially when the different category lists are displayed adjacently in multiple vertical columns. For example, a blog with three categories would do well to display each category’s archive listings in its own vertical column. Something like this:
With the recent Feedburner service outage, many sites across the Web experienced severe drops in their Feedburner subscriber counts. Apparently, Google is requiring all Feedburner accounts to be transferred over to Google by the end of February. In the midst of this mass migration, chaotic subscriber data has been reported to include everything from dramatic count drops and fluctuating reach statistics to zero-count values and dreaded “N/A” subscriber-count errors. Obviously, displaying erroneous subscriber-count data on your site is not a good thing. Fortunately, there are several ways to ensure that this doesn’t happen.
Over at CSS Newbie, author Rob Glazebrook weighs in with an excellent point about covering your bases when displaying your Feedburner subscriber count. As explained in the article, Feedburner’s handy API makes it easy to tap your data and display your subscriber count on your blog. Despite its best intentions, however, Feedburner occasionally returns inaccurate data or even no data at all for the subscriber count. For those of us who care about the accuracy of our publicly displayed feed statistics, displaying information like this on your site is simply unacceptable:
In my previous article on temporarily redirecting visitors during site updates, I present numerous PHP and HTAccess methods for handling traffic during site maintenance, updates, and other temporary periods of downtime. Each of the PHP methods presented in the article allow for access from a single IP while redirecting everyone else. In this article, we modify our previous techniques to allow access for multiple IP addresses while temporarily redirecting everyone else to the page of our choice. Plus, while we’re at it, we’ll explore a few additional ways to adapt and use the general technique.
Most of us learned how to use “echo()” in one of our very first PHP tutorials. That was certainly the case for me. As a consequence, I never really had a need to visit PHP’s documentation page for echo(). On a recent visit to Perishable Press, I saw a Tumblr post from Jeff about the use of PHP’s shortcut syntax for echo() but somewhere deep in my memory, there lurked a warning about its use. I decided to investigate.
As we have seen in our previous post, WordPress Custom Fields Part I, custom fields provide an excellent way to add flexible content to your posts and pages. By assigning various types of content to different custom fields, you gain complete control over when, where, and how to display the associated information. For example, sub-headings may be displayed in the sidebar, footnotes may be consolidated into a single region, post images may be displayed before the post title, and so on. In this follow-up article, we will review the basics of custom fields and then jump into a few custom-field tips and tricks.
I recently developed a theme that makes heavy use of WordPress’ custom fields. The custom-field functionality of WordPress makes it possible to rig up just about any customized layout quickly and easily. Custom fields enable designers to organize post content into different sections, making it possible to create non-linear page layouts, with different types of content easily removed from the normal post loop and relocated to different parts of the document. This organizational and design flexibility has the added benefit of making it super-easy to update your content, redesign your theme, and handle blog maintenance in general. In the first part of this mini-series, we walk through the process of implementing and using custom fields; then, in part two, I will share some delicious tips and tricks to help you get the most out of everything that custom fields have to offer.
In my previous article on WordPress title tags, How to Generate Perfect WordPress Title Tags without a Plugin, We explore everything needed to create perfect titles for your WordPress-powered site. After discussing the functionality and implementation of various code examples, the article concludes with a “perfect” title-tag script that covers all the bases. Or so I thought..
Some time after the article had been posted, Mat8iou chimed in with a couple of ways to improve thie script by cleaning up tag names and specifying page numbers for archive views. Apparently, by replacing the $tag variable with WordPress’ built-in single_tag_title();, titles for Tag-Archive page views will display the tag’s “pretty” name rather than the unformatted version. For example, the tag for Pink Floyd will be displayed correctly as “Pink Floyd” rather than the less friendly “pink-floyd”. And so on.
Ever wanted to provide automatic language translations of your web pages without installing another plugin? Here is a valid, SEO-friendly technique that takes advantage of Google’s free translation service. All you need is a PHP-enabled server and you’re good to go. Just copy and paste the following code into the desired location in your page template and enjoy the results. Once in place, this code will produce translation links for eight common languages for every page on your site. Grab, gulp and go:
Recently, Joost de Valk shared an excellent technique for adding spam and delete buttons to comments on your WordPress-powered blog. The idea is to save administration time by providing links to either “spam” or “delete” individual comments without having to navigate through the WordPress admin area. Joost provides the following plug-n-play solution:
When building web pages, it is often necessary to add links that require parameterized query strings. For example, when adding links to the various validation services, you may find yourself linking to an accessibility checker, such as the freely available Cynthia service:
Simple one for you today. After posting on how to use HTAccess to redirect subordinate URLs to the root (or parent) directory, I thought I would share an alternate way of accomplishing the same trick using PHP. Fortunately, using this PHP redirect technique doesn’t require access to or fiddling with your site’s HTAccess (or Apache configuration) file and it is very easy to implement.
The scene, as discussed in greater detail in my previous article on this topic, involves a very specific type of redirect whereby some target URL is redirected up the directory structure to one of its parent directories. Redirecting such subordinate content generally falls into one of two categories:
With the explosion of social media, networking, and bookmarking services, there are a zillion ways to add “Share This Post” functionality to your WordPress-powered sites. In addition to the myriad services and plugins, we can also add these links directly, using nothing more than a little markup and a few choice PHP snippets. Such individual links provide full control over the selection, layout, and styling of each link without requiring the installation of yet another WordPress plugin.
This article shares SEO-friendly code snippets for ten of the most popular social media sites using completely valid XHMTL-Strict markup. All of the following code snippets feature:
Recently, I discussed how to implement a horizontally sequenced display order for WordPress posts in two columns. In that tutorial, I explain how to separate odd and even posts using a dual-loop configuration and PHP’s modulus operator. Such technique serves well a variety of configurational scenarios, but is limited to the display of the default (admin-specified) number of posts from all categories. In this tutorial, we adapt this odd-and-even loop configuration to accommodate a much greater degree of customization. Specifically, we will focus on separating any number of odd and even posts from any specific category or group of categories. Several additional configurational customizations will also be covered.
Welcome to the Perishable Press “Blacklist Candidate” series. In this post, we continue our new tradition of exposing, humiliating and banishing spammers, crackers and other worthless scumbags..
From time to time on the show, a contestant places a bid that is so absurd and so asinine that you literally laugh out loud, point at the monitor, and openly ridicule the pathetic loser. On such occasions, even the host of the show will laugh and mock the idiocy. Of course, this same situation happens frequently here at Perishable Press, where the scumbags that manage to escape the 3G Blacklist are proving themselves to be increasingly desperate and pathetic. Such is the case with this month’s official Blacklist Candidate Number 2008-10-19:
Come on down — you’re the next cracker whore to get banished from the site!
I know, I know, not another post about IE6! I actually typed this up a couple of weeks ago while immersed in my site redesign project. I had recently decided that I would no longer support that terrible browser, and this tangential post just kind of “fell out.” I wasn’t sure whether or not to post it, but I recently decided to purge my draft stash by posting everything for your reading pleasure. Thus, you may see a few turds in the next few weeks, but hopefully this isn’t one of them. In any case, here is my final post on IE6, at least for awhile..