Tag: htaccess

Permanently Redirect a Specific IP Request for a Single Page via htaccess

Posted on July 23, 2007 in Function by Jeff Starr

Not the most interesting title, but “oh well”..

Recently, a reader named Alison left a comment requesting help with a particular htaccess trick. She wanted to know how to permanently redirect (301) all requests for a specific page when requested from a specific IP address. In other words, when a visitor coming from 123.456.789 requests the page requested-page.html, the visitor will be redirected to just-for-you.html. All visitors not coming from that specific IP address are not redirected, and thus will see the originally requested page. Further, the redirect must apply only to requested-page.html, such that every visitor — including the one coming from 123.456.789 — will be able to see all of the other pages. Here is the htaccess code to make it happen:

# permanently redirect specific IP request for single page
RewriteEngine On
RewriteBase /
RewriteCond %{REMOTE_HOST} 123\.456\.789
RewriteCond %{REQUEST_URI} /requested-page\.html$
RewriteRule .* /just-for-you.html [R=301,L]

To use this redirect, simply edit the IP address, requested page, and redirect page. Copy and paste the code into your htaccess file and upload to your server. Test the 301 redirect via proxy and that’s it. Relax and enjoy!

Allow Google Reader Access to Hotlink-Protected Images

Posted on July 16, 2007 in Function, Technology by Jeff Starr

[ Image: Google Reader Icon ] In our previous article, we explain the process of allowing Feedburner to access your hotlink-protected images. The article details the entire process, which covers the basics of hotlink protection and involves adding several lines of code to your htaccess file. In this article, we skip the detailed explanations and present only the main points. The discussion is very similar for both Feedburner and Google Reader, and may be extrapolated to serve virtually any purpose.

If you are using htaccess to protect your images from hotlinking and have yet to check your feeds in Google Reader, you may be in for a little surprise. Unless you explicitly permit Google Reader access, your htaccess rules may be inadvertently preventing subscribers from viewing the images in your feeds. The same is true for Google Reader Mobile, which is probably far more popular than you may realize.

Continue Reading

Allow Feedburner Access to Hotlink-Protected Images

Posted on July 9, 2007 in Function by Jeff Starr

[ Image: Feedburner Icon ] Recently, we installed and configured the excellent WordPress Feedburner plugin by the venerable Steve Smith 1. The plugin basically redirects our various WordPress-powered content feeds to Feedburner, which then delivers them to subscribers. This method enables us to take advantage of Feedburner’s excellent statistical tools. Further, all of the action happens silently, beneath the surface, and without the subscriber even realizing it.

After a few weeks running the plugin with great success, we began hearing reports of broken and missing images messing up our feeds. After some investigating, we realized that our tried-and-true anti-hotlinking htaccess rules were doing their job a little too well — blocking everyone outside our domain from accessing our image content — including Feedburner.

Continue Reading

How to Block IP Addresses with PHP

Posted on July 3, 2007 in Function by Jeff Starr

[ Image: Skeletor Blocks a Move ] Figuratively speaking, hunting down and killing spammers, scrapers, and other online scum remains one of our favorite pursuits. Once we have determined that a particular IP address is worthy of banishment, we generally invoke the magical powers of htaccess to lock the gates. When htaccess is not available, we may summon the versatile functionality of PHP to get the job done.

This method is relatively straightforward. Simply edit, copy and paste the following code example into the top of any PHP for which you wish to block access:

Continue Reading

Major Problem with cPanel Hotlink Protection and htaccess

Posted on July 1, 2007 in Function by Jeff Starr

There is a major problem with the “Hotlink Protection” feature of cPanel. To summarize the issue, allow me to quote a recent email sent to a completely unresponsive tech support department:

…The problem is that if I try to include any rewrite rules for permalinks, hotlinking, or blocking spambots, cPanel automatically enables its “Hotlink Protection” feature. And, even worse, it automatically adds every URL from every rewrite rule (even the ones for blocking spambots) to its “auto-discovered” list of URL’s for which image access is allowed. This means that every spammer that I am trying to block now has access to my images! If I try to remove the spammers directly from the “allow-image-access” list, the associated rewrite rules are automatically removed from my htaccess file, thus giving spammers full access to my entire site (instead of just access to images). So, it is indeed the case that I can’t add any rewrite rules to my site’s root htaccess file without cPanel automatically assuming that every URL on the page is related to hotlinking and subsequently adding them all to the “allow-image-access” list…

[ Image: Train Wreck ] In other words, cPanel screws up htaccess rewrite rules via its “Hotlink Protection” feature. More specifically, spammers and robots that are denied site access via root-htaccess rewrite rules are automatically listed in the “allow access to images” field of the Hotlink Protection panel. Not good. Even worse, disabling Hotlink Protection automatically removes every rewrite rule from the htaccess file. Such bizarre functionality forces the user to choose between complete hotlink protection and other essential features such as pretty permalinks or spam blocking. Pretty sucky if you ask us. Nonetheless, here is a concise summary of the problem with the cPanel Hotlink Protection (cHP) feature:

Continue Reading

Ultimate htaccess Blacklist

Posted on June 28, 2007 in Function by Jeff Starr

[ Image: Solar Eclipse ] For those of us running Apache, htaccess rewrite rules provide an excellent way to block spammers, scrapers, and other scumbags easily and effectively. While there are many htaccess tricks involving blocking domains, preventing access, and redirecting traffic, Apache’s mod_rewrite module enables us to target bad agents by testing the user-agent string against a predefined blacklist of unwanted visitors. Any matches are immediately and quietly denied access.

There are many ways to obtain an effective htaccess blacklist. There are several excellent forums around the web that provide a plethora of priceless htaccess advice. Highly suggested. Additionally, after copying and pasting your favorite forum blacklist examples to your domain’s root htaccess file, you will want to continue with its development by tracking bandwidth thieves, comment spammers, and site scrapers and adding them to the list. Or, you may wish to skip the tedious grunt work and simply grab a copy of the Ultimate htaccess Blacklist!

The Ultimate htaccess Blacklist began as a short list of only the most heinous offenders. Blocking scum was such an enjoyable activity that we soon added to the list the identity of every nasty agent we could find. The result has been a very low-stress, spam-free site with virtually zero stolen bandwidth. The list is fairly comprehensive and attempts to blacklist as many site rippers, grabbers, spammers and bad bots as possible. While no blacklist could ever block them all (nor would they want to using this method)1, an elaborate htaccess blacklist can do wonders to improve overall performance, decrease site maintenance, and reduce server expense. Overall, we consider this blacklist a great foundation on which to build and customize your own ultimate htaccess blacklist!2

Continue Reading

Compressed JavaScript Compression

Posted on April 24, 2007 in Function by Jeff Starr

In this article, we extrapolate our favorite CSS-compression technique for JavaScript. Below, we outline the steps required to auto-compress your JavaScript documents via gzip and PHP. Two different compression methods are presented. The first method does not require htaccess, but rather involves the manual editing of JavaScript files. The second method employs htaccess to do all the work for you, thus requiring much less effort to implement. In either case, the result is the same: automatically compressed content delivered only to supportive browsers, resulting in reduced bandwidth, faster loading times, and smiling visitors :)

Continue Reading

Fast, Effective PHP Compression

Posted on March 26, 2007 in Function by Jeff Starr

PHP compression is an excellent method of conserving bandwidth and reducing client download times. We have already discussed an excellent method for CSS compression, and in this article we share a super-easy technique for compressing all PHP content without editing a single file.

Using two PHP files and two corresponding lines of .htaccess, it is possible to compress your PHP files via gzip-encoding. Browsers and other user-agents capable of interpreting gz-encoded data will employ the compressed content, while other user-agents will utilize the content uncompressed.

Continue Reading

Perishable Press Redirection Lounge

Posted on March 19, 2007 in Nothing by m0n

Welcome to the Perishable Press Redirection Lounge!

You are always welcome at the Redirection Lounge!

What?
We keep a very close eye on all 404 (resource not found) errors. Every time a legitimate 404 rears its ugly head, we take the necessary steps to solve the issue. In most cases, we use htaccess redirects to prevent 404 errors. Often, the missing resource remains available, but has been moved to another location. In this situation, we simply redirect visitors to the new location. Easy. However, there are also a relatively small number of 404 errors that are generated due to content that is no longer available. For example, temporary posts, test posts, and duplicate posts often result in 404 errors, even if they were only online for a very short time. So, rather than redirecting such requests to the home page or to the 404 page, we have created an exclusive Redirection Lounge at which roaming search engines, misguided robots, and wandering visitors may find information and reassurance.
Where?
This page is actually a post handcrafted especially for this very moment in time. The post is public, exists online, and is archived at Perishable Press. In other words, you are currently deep within the Perishable Press Archives. To escape such ancient realms, click here to return to the Perishable Press home page. Otherwise, click on some other link to fight your way out of the archive database. Otherwise, enjoy your stay here at the Perishable Press Redirection Lounge. It may not be exactly what you originally had in mind, but you have to admit, the solitude provides plenty of time to think about that interesting life of yours.
Why?
You are here because you tried accessing a resource at perishablepress.com that is no longer available. Please note that the content you are seeking has not been relocated, misplaced, or renamed — it is simply no longer available on this domain. Most likely, the content has been deleted permanently. If you are absolutely convinced that the content you are seeking is worth pursuing, please check out the Google index or the excellent Wayback Machine. Indeed, if the requested content were still available on this domain (perishablepress.com), our diligent web gimps would have redirected you swiftly to the new location of the resource. However, as the requested resource is not available, and because we try to avoid as many 404 errors as possible, we have created this Redirection Lounge to serve as our official redirect target for otherwise dead-end requests. We hope you find it as comfortable as it is informative.
Huh?
If you feel that you have arrived at the Redirection Lounge in error, or have information concerning the requested resource, please use our official contact form to drop us a line.

Invite Only: Visitor Exclusivity via the Opt-In Method

Posted on January 22, 2007 in Function by Jeff Starr

Web developers trying to control comment-spam, bandwidth-theft, and content-scraping must choose between two fundamentally different approaches: selectively deny target offenders (the "blacklist" method) or selectively allow desirable agents (the "opt-in", or "whitelist" method).

Currently popular according to various online forums and discussion boards is the blacklist method. The blacklist method requires the webmaster to create and maintain a working list of undesirable agents, usually blocking their access via htaccess or php. The downside of "blacklisting" is that it requires considerable effort to stay current with the exponential number of ever-evolving threats, which require exceedingly long lists for an effective response. Although time-consuming and potentially work-intensive (there are automated methods of blacklisting bad bots), blacklisting optimizes hits by allowing site access to anyone not on the blacklist. Unfortunately for blacklisters, it has become relatively trivial to disguise bots by using standard user-agent strings. So the bad guys bypass the blacklist and slip into your site incognito. Besides, nobody wants to waste valuable time digging through endless access logs. Whereas blacklisting is reactive, whitelisting is proactive..

Continue Reading

Riding the Wave

Posted on January 10, 2007 in Blogging, Perishable by Jeff Starr

Compared to some of the big players out there on the internet, we here at Perishable Press run a relatively small website. We began this project in September of 2005 with nothing but a domain name and a pocketful of inspiration. During the first several months of development, our traffic statistics looked something like: one unique visitor and 10,000 hits (i.e., nobody but us).

Well, that went on for the first few months of 2006, and then something miraculous happened — we were linked to by another site and subsequently indexed by Google, and then Yahoo, and soon thereafter MSN. Within several weeks after being picked up by the search engines, our page rank was like 1 or 2 and our traffic was something like: 30 unique visitors and 1,000 hits (i.e., we were finishing up site development as more people began visiting).

Well, the next several months into 2006 — like, say, from around April to July — Perishable Press continued to produce content, articles, themes, scripts, and all sorts of links everywhere. We were making more noise and several more sites linked to us. Traffic began to increase into the 100’s, 200’s, and eventually leveled off around 300 unique visitors per day (with like 3000 hits due to continued site development, etc.). Things were officially up and running..

Continue Reading

Disobedient Robots and Company

Posted on January 1, 2007 in Perishable, Websites by Jeff Starr

In our never-ending battle against spammers, leeches, scrapers, and other online undesirables, we have implemented several powerful security measures to improve the operational integrity of our perpetual virtual existence. Here is a rundown of the new behind-the-scenes security features of Perishable Press:

  • Automated spambot trap, designed to identify bots (and/or stupid people) that disobey rules specified in the site’s robots.txt file.
  • Automated disobedient-robot identification (via reverse IP lookup), admin-notification (via email) and blacklist inclusion (via htaccess).
  • Automated inclusion of disobedient robot identification on our now public "Disobedient Robots" page.
  • Imroved htaccess rules, designed to eliminate scum-sucking worms and other useless vermin.
  • Automated tracking tools, designed to keep a close eye on any suspicious or questionable activity.
  • Automated 404-error statistics, designed to optimize the elimination of 404 errors.
  • Plus a few other secret-agent tricks that we are not at liberty to discuss ;)

As you can see, we have been pretty busy around here — fortunately, the new security features have been working flawlessly, reducing stolen bandwidth, potential spam, disobedient robots, and 404 errors. Hopefully, the end result of these new features will involve smoother site functionality and better browsing for everyone.

Automatic Language Translation Methods

Posted on December 18, 2006 in Accessibility, Function by Jeff Starr

As you may have noticed, Perishable Press recently added automatic language translation to each of our articles. The free, automatic translations are available as a series of image links (via corresponding country flag icons) next to each article’s individual post view. We have found that providing this free service is important as many of our visitors come from countries other than the United States, and therefore may be unable to read our articles as presented in the English language.

Although there are several excellent translation services currently available, our research has determined that Google’s free translation service exceeds our expectations and serves as an excellent online translator that remains fast, effective, and (best of all) free. Another excellent online translator service is provided by BabelFish, which is also highly efficient and free of charge.

Using either of these free online translators and a little .htaccess or PHP magic, it is very easy to serve alternate versions of site content in a wide variety of languages. This article presents two excellent methods of incorporating automatic language support using either .htaccess or PHP. We also provide the (X)HTML source code necessary to manually include automatic translation links within static (X)HTML documents. The translation configurations covered in this article include the following:

Continue Reading

Roll your own Apache Rewrite Log

Posted on November 28, 2006 in Function by Jeff Starr

Note to self: Here is the .htaccess code for creating an Apache Rewrite log. This is definitely helpful for testing .htaccess rewrite rules, permalinks, etc. Update: as jc points out in the comments section, Apache versions 2.2 or better no longer allow RewriteLog directives in htaccess files. For these versions, it is necessary to coordinate logging through the server configuration file or via virtual host. For more information, check the source. For pre-2.2 versions of Apache, continue reading to learn how to Roll your own Apache Rewrite Log!

via http.conf

Twist one up via the Apache configuration file by placing this code at the foot of your http.conf (remember to edit the path):

# Roll your own Rewrite log
# Log details via scale of 1 to 9
# 1 = few details, 5 = enough details, 9 = too much detail
RewriteEngine On
RewriteLog "/absolute/path/to/your/wwwroot/public_html/rewrite.log"
RewriteLogLevel 5

via htaccess

Roll one tuf via your site’s root .htaccess by placing this code at the end of the file (remember to edit the path):

# Roll your own Rewrite log
# Log details via scale of 1 to 9
# 1 = few details, 5 = enough details, 9 = too much detail
RewriteEngine On
RewriteLog "/absolute/path/to/your/wwwroot/public_html/rewrite.log"
RewriteLogLevel 5

Example

Here is an example indicating the type of data logged by the RewriteLog directive:

64.246.32.000 - [07/July/2007:07:07:07 - 0700] [example.com/sid#80077333][rid#800b7a33/initial] (2) init rewrite engine with requested uri /press/wp-comments-post.php
64.246.32.000 - [07/July/2007:07:07:07 - 0700] [example.com/sid#80077333][rid#800b7a33/initial] (2) rewrite /press/wp-comments-post.php -> http://64.246.32.000/
64.246.32.000 - [07/July/2007:07:07:07 - 0700] [example.com/sid#80077333][rid#800b7a33/initial] (2) explicitly forcing redirect with http://64.246.32.000/
64.246.32.000 - [07/July/2007:07:07:07 - 0700] [example.com/sid#80077333][rid#800b7a33/initial] (1) escaping http://64.246.32.000/ for redirect
64.246.32.000 - [07/July/2007:07:07:07 - 0700] [example.com/sid#80077333][rid#800b7a33/initial] (1) redirect to http://64.246.32.000/ [REDIRECT/301]

Block Spam by Denying Access to No-Referrer Requests

Posted on November 20, 2006 in Function, WordPress by Jeff Starr

What we have here is an excellent method for preventing a great deal of blog spam. With a few strategic lines placed in your htaccess file, you can prevent spambots from dropping spam bombs by denying access to all requests that do not originate from your domain.

How does it work? Well, when a legitimate user (i.e., not a robot, etc.) decides to leave a comment on your blog, they have (hopefully) read the article for which they wish to leave a comment, and have subsequently loaded your blog’s comment template (e.g., comments.php), which is most likely located within the same domain as the article, blog, etc. (i.e., your domain).

So, after filling out the comment form via comments.php, the user clicks the "submit" button, which then initiates the PHP file/script that actually processes the comment for the world to see. For WordPress users, the comment processing file is wp-comments-post.php.

Therefore, the HTTP referrer for all legitimate (user-initiated) comments will be your domain (or the domain in which the comments.php file is located). Automated spam robots typically target the comment-processing script directly, bypassing your comments.php form altogether. Such activity results in HTTP referrers that are not from your domain.

Thus, by blocking all requests for the comments-processing script (wp-comments-post.php) that are not sent directly from your domain (comments.php), you immediately eliminate a large portion of blog spam.

Sound good? Here is the script to add to your site’s .htaccess file:

# block comment spam by denying access to no-referrer requests
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .wp-comments-post\.php*
RewriteCond %{HTTP_REFERER} !.*perishablepress.com.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule ^(.*)$ ^http://the-site-where-you-want-to-send-spammers.com/$ [R=301,L]

Please note that you need to edit the following lines according to your specific setup:

.wp-comments-post\.php*
This is the default comment-processing script for WordPress users. If you are not running WordPress, you will need to determine the corresponding file and enter its name here.
!.*perishablepress.com.*
Change this value to that of your own domain.
^http://the-site-where-you-want-to-send-spammers.com/$
Because spambots typically ignore redirects, this may not be accomplishing too much. But go ahead and enter the URL of your least-favorite website anyway. Another option here is to simply bounce the spambot back to where it came from by replacing the last with this: RewriteRule ^(.*)$ ^http://%{REMOTE_ADDR}/$ [R=301,L]

And that is all there is to it! Bye bye spambots!

Stop Bitacle from Stealing Content

Posted on November 8, 2006 in Websites, WordPress by Jeff Starr

If you have yet to encounter the content-scraping site, bitacle.org, consider yourself lucky. The scum-sucking worm-holes at bitacle.org are well-known for literally, blatantly, and piggishly stealing blog content and using it for financial gains through advertising. While I am not here to discuss the legal, philosophical, or technical ramifications of illegal bitacle behavior, I am here to provide a few critical tools that will help stop bitacle from stealing your content.

The htaccess Finger

Perhaps the most straightforward and effective method for keeping the bitacle thieves away from your site, adding the following htaccess rules to your root htaccess file will literally block bitacle’s IP address and return a 403 Forbidden message (for more information on htaccess files, see our article, Stupid htaccess Tricks, referenced below). Add this to your site’s root htaccess file:

RewriteBase /
RewriteCond %{REMOTE_ADDR} ^212\.22\.59\.251$ [OR]
RewriteCond %{HTTP_USER_AGENT} Bitacle
RewriteRule .? - [F]

The robots.txt Slap

Next up, another effective anti-bitacle method that instructs the bitacle bots to stay away from your site. This method uses a robots.txt file in your site’s root directory and literally denies bitacle agents crawl-access to all site contents. Simply add the following lines to your site’s root robots.txt file (for more information on robots.txt, see our article, Robots Notes Plus, referenced below):

User-agent: Bitacle bot/1.1
Disallow: /
User-agent: Bitacle bot
Disallow: /
User-agent: Bitacle *
Disallow: /
User-agent: Bitacle*
Disallow: /
User-agent: Bitacle
Disallow: /

Related WordPress Plugins

For more help on the anti-plagiarism front, check out Redalt’s Antileech Plugin and MaxPower’s Digital Fingerprint Plugin. These fine WordPress plugins come highly recommended and are definitely worth checking out.

Other Essential Tools

Beyond the essential preventative methods discussed above, there are many other resources and tools now available for dealing with site scrapers, content thieves, and other worthless garbage. A worthwhile website is Copyscape, which provides an excellent tool that enables users to search the web for stolen content. If you find that your content has indeed been plagiarized, read up on how to respond properly and effectively. Finally, try searching for various search terms, such as "plagiarism tools", "content scraping", "copyright protection", "syndication theft", etc. Good Luck!

Stop bitacle.org
Stop bitacle.org

References & Resources

Compressed CSS Compression

Posted on October 23, 2006 in Function by Jeff Starr

In this article, we have consolidated the priceless information provided in fiftyfoureleven.com’s fine post, The Definitive Post on Gzipping your CSS, which discusses two practical methods for compressing CSS documents. Complete and utter credit for the contents of this article is hereby attributed to fiftyfoureleven.com.

Method One

Overview: This method involves adding a small PHP script to your CSS document and replacing its .css extension with a .php extension.

Place the following PHP script into the top of the CSS document that you wish to compress. Then change the .css extension to .php, to arrive at something similar to: compressed-css.php. Remember to use the new name when referencing the file.

<?php 
   ob_start ("ob_gzhandler");
   header ("content-type: text/css; charset: UTF-8");
   header ("cache-control: must-revalidate");
   $offset = 60 * 60;
   $expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";
   header ($expire);
?>

Here is the same PHP script commented with functional explanations:

<?php

   // initialize ob_gzhandler function to send and compress data
   ob_start ("ob_gzhandler");

   // send the requisite header information and character set
   header ("content-type: text/css; charset: UTF-8");

   // check cached credentials and reprocess accordingly
   header ("cache-control: must-revalidate");

   // set variable for duration of cached content
   $offset = 60 * 60;

   // set variable specifying format of expiration header
   $expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";

   // send cache expiration header to the client broswer
   header ($expire);

?>

Functional Summary: The previous PHP function will first check to see if the browser requesting the file will accept "gzip-deflate" encoding. If no such support is detected, the requested file is sent without compression. Next, the function sends a header for the content type and character set (in this case, "text/css" and "UTF-8"). Then, a "must-revalidate" "cache-control" header requires revalidation against currently specified variables. Finally, an "expires" header specifies the time duration for which the cached content should persist (one hour in this case).

Method Two

Overview: This method involves placing the PHP script in a separate .php file and adding a set of rules to an .htaccess file.

A more discrete, unobtrusive method for compressing CSS involves two steps. First, save the script provided in the first method (above) as a seperate gzip-css.php file and place it in a CSS-exclusive directory. Then, add the following ruleset to an .htaccess file located in the same CSS-exclusive directory (i.e., the CSS directory should contain only CSS files):

# css compression htaccess ruleset
AddHandler application/x-httpd-php .css
php_value auto_prepend_file gzip-css.php
php_flag zlib.output_compression On

Here is the same htaccess ruleset commented with functional explanations:

# css compression htaccess ruleset

# process all CSS files in current directory as PHP
AddHandler application/x-httpd-php .css

# prepend the PHP script to all PHP files in the current directory
php_value auto_prepend_file gzip-css.php

# compress all parsed PHP pages from current directory
# this rule is redundantly present as the first line of the PHP script
php_flag zlib.output_compression On

Functional Summary: The .htaccess rules above first instruct Apache to parse all CSS files in the current directory as PHP. After this, Apache is instructed to insert the contents of the "gzip-css.php" file into the beginning of each PHP (i.e., CSS) file parsed from the current directory. And finally, Apache is instructed to compress automatically every parsed document in the current directory.

Confirmed Browsers

  • Internet Explorer 5 and up: works great
  • Netscape Navigator 6 and up: works fine
  • Mozilla/Firefox: all versions seem to work
  • Opera: does not cache compressed CSS

References

Stupid htaccess Tricks Redux

Posted on August 21, 2006 in Websites by Jeff Starr

One of our most popular posts, Stupid htaccess Tricks, has been completely rewritten and now includes almost twice as many stupid htaccess tricks. Plus, we have added a library of regex character definitions, more information for many of the directives, and several handy references. But wait, there’s more — we even threw in a “quick-jump” Table of Contents and a complete set of “up[ ^ ] links for easy navigation. Utterly amazing!

Website Attack Recovery

Posted on July 24, 2006 in Websites by Jeff Starr

Recently, every website on our primary server was simultaneously attacked. The offending party indiscriminately replaced the contents of every index file, regardless of its extension or location, with a few vulgar lines of code, which indicated intention, identity, and influence.

Apparently, the attack occurred via Germany, through a server at the University of Hamburg. This relatively minor attack resulted in several hours of valuable online education. In this article, it is our intention to share experience with website attack recovery. This article is aimed at website developers, designers, and administrators.

Continue Reading

The htaccess Rules for all WordPress Permalinks

Posted on June 14, 2006 in WordPress by Jeff Starr

I recently performed a series of tests on a fresh installation of WordPress 2.8.6 to determine the exact htaccess rewrite rules that WordPress writes to its htaccess file for various permalink configurations. Under the WP admin option menu, WordPress lists four choices for permalink structure:

  1. Default: http://perishablepress.com/press/?=123
  2. Date and name based: http://perishablepress.com/press/index.php/2006/06/14/sample-post/
  3. Numeric: http://perishablepress.com/press/index.php/archives/123
  4. Custom: /%year%/%monthnum%/%day%/%postname%/

The "default" option is to not use permalinks. The "date and name based" setting invokes the /index.php/%year%/%monthnum%/%day%/%postname%/ rule pattern. The "numeric" setting invokes the /index.php/archives/%post_id% rule pattern. And the "custom" setting invokes whatever pattern is specifically chosen. For our "custom" option, we chose the /%category%/%author%/%postname%/ pattern.

For the test, we began with the common "date and name based" permalink configuration. Then, after invoking the chosen permalink structure, the htaccess file was downloaded and the new WP rules were recorded. After this, the admin permalink settings were switched back to the "default" configuration. Finally, we deleted the new rules and uploaded the htaccess file. This process was diligently repeated for each different permalink configuration. It should also be noted that blog performance was checked during each round of testing.

The results indicate conclusively that WordPress uses the exact same set of htaccess rules for all permalink configurations. Surely this information is available elsewhere on the internet, however we were experiencing several inconsistencies related to permalink structure that inspired us to determine for ourselves the precise htaccess rules for WordPress permalinks.

Without further ado, the htaccess rules for all WordPress permalinks1 are precisely either #1 or #2:

[ #1 ] If WordPress installed in the root directory »

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

[ #2 ] If WordPress installed in a subdirectory called "foo" »

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /foo/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /foo/index.php [L]
</IfModule>
# END WordPress

1 Note: These results are valid for standard permalink structures invoked via a standard WordPress install and may not operate effectively for non-standard or highly specialized configurations. We assume that if you are hard at work hacking and tweaking, you must know what you are doing.

Permalink Enlightenment

Posted on April 10, 2006 in Websites, WordPress by Jeff Starr

I recently enabled the permalinks feature for a fresh WordPress 2.0.2 upgrade. The process required several hours of research and approximately 90 minutes to fully implement. This brief article summarizes the process and applies to at least the following setup:

  1. WordPress 2.0.2
  2. Apache Server with mod_rewrite enabled
  3. The ability to access/modify your .htaccess file(s)
  4. You have decided to use the /%year%/%monthnum%/%day%/%postname%/ permalink format (actually, any format will work; simply swap your preferred format for the one mentioned here)
  5. You may also be using any of the plugins listed in the dungeon (actually, most plugins are compatible — only a few cause problems)

Permalinks are important for several reasons: search engines love them, people can understand them, and links (theoretically) become permanent because of them. Plus, all of the cool kids are using them, so you should too. They really add the finishing touches to your site and provide a sense of unity and sophistication that the “http://ugly-domain.com/blog/index.php?page_id=66” format just can’t match.

Before you begin any changes it is highly recommended to backup everything: WordPress files, database(s), notes, edited files, image files, htaccess file(s), etcetera. Just a friendly reminder.

Then, if you are seriously considering jumping into permalinks, do some research. Search Google, Ask, WordPress, and dig through a few blogs for terms such as “WordPress permalinks”, “permalink tips”, “permalink guide”, etc. As you learn, copy and paste any important notes, code, or links that seem important and may be useful later on. You may also wish to anticipate certain scenarios by searching for “permalink nightmare” or “permalink success”, for example.

Now that you have studied the process, you realize that certain conditions produce errors or other problems. For example, if you are planning on using the %postname% in your permalinks, very long post titles may cause problems in emails, posts, and chats. Although such an issue may be fixed after the fact, it is wise to scan through your posts and edit the post slug of any posts with excessively long titles. Regardless of the post title name, it is the post slug that is used when implementing the %postname% in permalinks. If possible, I recommend manually checking every post title and slug and editing (if needed) with permalinks %postname% in mind. Don’t forget to check your pages as well.

Now for the fun stuff. Well, almost. WordPress 2.0.2 has a problem writing to .htaccess files even when their CHMOD is set to 666 or 777. To fix this, open wp-includes/vars.php and replace the following line of code:

$is_apache = ( strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') || strstr($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') ) ? 1 : 0;

..with this one:

$is_apache = 1;

This is a change that should be needed only during the establishment of permalinks. After you have permalinks flying high, you should revert the previous replacement and restore order to the galaxy.

Now create your htaccess file(s). Open a text editor and save a blank document as “htaccess” in the root of your site. Then rename it to “.htaccess” (i.e., put a dot before the name). Upload this file and change its CHMOD setting to 666. Again, this change should only endure until permalinks are functioning. So remember to change it back to its default setting (typically 644).

Okay, get ready to party. First restart your computer (for good measure). Then, open your WordPress Admin and navigate to the Permalinks submenu (under Options). Read everything carefully and then select the “Date and name based” option under the “Common options” menu. Make sure that WordPress automatically added /%year%/%monthnum%/%day%/%postname%/ (or that of your preferred format) to the “Custom structure” field. Now click the “Update Permalink Structure” button and wait for the “success” message to appear. At this point, permalinks should work throughout your WordPress-powered website.

Almost done. Check everything. First download your htaccess file and check that WordPress automatically added the htaccess directives required to create permalinks:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /press/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /press/index.php [L]
</IfModule>
# END WordPress

If you don’t see it, then copy and paste it into your htaccess file manually. If your htaccess file is blank, permalinks will not work. Once your htaccess file is good to go, clear your browser cache and surf your entire site — pages, posts — everything. Check internal links and external links. If possible, check links pointing to your site from elsewhere online. Every page or post should now be addressed by its corresponding and unique permalink, as displayed in your browser’s address field. If all is looking smooth, great. Remember to check the functionality of everything: commenting, posting, tagging, and editing posts. Also check your calendar, archives, search function, different themes, and plugin features (if any).

One problem I encountered (besides those inherently addressed in this article) involved an unwanted index.php statement included before the date in all permalinks. To fix this, you must access the wp_options table in your WordPress database. Once there, find the index field called option_name and search for the record rewrite_rules and clear the contents of the option_value. This will force WordPress to generate new permalink values based on current user settings. Read more via this thread at the WordPress Support Forums.

Don’t forget to reverse any changes made during the permalink conversion process.

References & Resources

Stupid htaccess Tricks

Posted on January 10, 2006 in Websites by Jeff Starr

Welcome to Perishable Press! This article, Stupid htaccess Tricks, covers just about every htaccess “trick” in the book, and is easily the site’s most popular offering. In addition to this htaccess article, you may also want to explore the rapidly expanding htaccess tag archive. Along with all things htaccess, Perishable Press also focuses on (X)HTML, CSS, PHP, JavaScript, security, and just about every other aspect of web design, blogging, and online success. If these topics are of interest to you, I encourage you to subscribe to Perishable Press for a periodic dose of online enlightenment ;)

Table of Contents

Continue Reading