Spam

Spam has become the bane of the connected world. Whilst it is simple for a human to be able to decide if an object (email, comment, trackback) is Spam, it appears that computers have a harder time of it. Perhaps the most surprising thing is that Spam exists at all. It relies on some sort of a payoff for the Spammer: for email Spam this must mean that people actually buy the crap they advertise. My Gmail Spam folder is bulging as we speak: I seem to get around 400 Spam emails per month. Almost all of these are automatically picked up by Gmail’s Spam filter - but this filter also picks up several Ham (or legitimate emails) in the average month. The majority of these are bounced emails: almost by default all bounced replies end up as Spam, since a common occurrence seems to be for Spammers to use real (other people’s) email addresses as the From: address, resulting in a whole bunch of Undeliverable Mail messages bouncing back to that person. Usually, this is not a problem, as most people I email I get the address right. However, as I have just taken over administration of a Sporting Organisation’s member list, I now get several bounced emails each time I do a mailout - I’m going through pruning addresses each time, but people’s addresses are often lapsing. Profit from comment and trackback Spam is a little different. Rather than getting people to buy things from them, these Spammers rely on clicks or links to make money. The second has been largely overcome in many circles by the rel=“nofollow” tag, however, unless use of this is universal, Spammers may still make money. The way linking makes money is largely by improving PageRankā„¢, or prestige in Search Engines. The first one relies on users to click on links, and visit sites. If enough users do this, then it could concieveably make a significant amount of money for the Spammers. I’ve had some comment and trackback Spam where the URI isn’t even valid, so I’m not so sure how well this works for Spammers. I seem to have overcome the issues I had with comment Spam - just requiring users to have JavaScript activated seems to be enough for now. And if the Spammers catch on, then I’ll re-implement the catchpa. That leaves trackback Spam. This is the one that is causing me the most grief now. At least it’s not as bad as email Spam (in volume, anyway) on my blog. I’ll get around about 6-10 Spam trackbacks in a given month. I’m not sure how many Ham trackbacks I get - not too many, IIRC. I may turn trackbacks off, if I cannot come up with a decent solution.

Rewrite Rules

When editing RewriteRules, it’s important to remember this: rules which appear first tend to take priority. For instance, I discovered that the rules for http://schinckel.net/200_n_/page/_n_/ style URIs were missing. What was happening was the .htaccess file was finding the closest rule it could. The trick for finding what it’s actually doing under Blogsome is to have this code in your template:

1
2
3
    {foreach from=$smarty.server.argv item=var}
    {$var}
    {/foreach}

This code will print out what the server is receiving. In the case of the URI: http://schinckel.net/2005/page/2/ it’s being sent:

wpblog=schinckel&year=2005&monthnum=&day=&name=page&page=2

The important part here is that the name of the post is being set to ‘page’. Clearly, this is not desired behaviour. The RewriteRule that should apply to this instance looks something like:

1
    RewriteRule ^blogs/([_0-9a-z-]+)/([0-9]{4})/page/([0-9]+)/(.*)/    /wp-inst/index.php?wpblog=$1&year=$2&paged=$3 [L]

I don’t know exactly what the [L] stands for, but it needs to be there to stop Bad Server Errorsā„¢. The key thing to know here is that this must be before the greedy rule that was already grabbing the URL, and Rewriting it of its own accord. In my case, that was the line that looked like:

1
    RewriteRule ^blogs/([_0-9a-z-]+)/([0-9]{4})/?([0-9]{1,2})?/?([0-9]{1,2})?/?([_0-9a-z-]+)?/?([0-9]+)?/?$          /wp-inst/index.php?wpblog=$1&year=$2&monthnum=$3&day=$4&name=$5&page=$6 [L]

I made sure my new rule was before this. A good place is where the other rules for subsequent pages of posts are. Of course, this rule only works for yearly archives, you’ll want one for monthly and daily archives (if you are a nutter who posts more times per day than fits onto your front page…):

1
2
    RewriteRule ^blogs/([_0-9a-z-]+)/([0-9]{4})/([0-9]{1,2})/page/(.*)/    /wp-inst/index.php?wpblog=$1&year=$2&month=$3&paged=$4 [L] 
    RewriteRule ^blogs/([_0-9a-z-]+)/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/page/(.*)/    /wp-inst/index.php?wpblog=$1&year=$2&month=$3&day=$4&paged=$5 [L]

Of course, on Blogsome, you cannot alter this file yourself, but I’m sure these changes will be implemented soon. If the link earlier in the post still gives you “No Posts Made”, then you know it hasn’t…

Simplest Spam Comment Killer

There are two main tasks that are required to implement a Comment Spam Protection system. The first is to disable comments for all people. The second is to enable it for people who legitimately want to comment. A very simple way to solve the first task is to remove the action from the form tag. In my template, the code looked like this:

    <form action="{$siteurl}/wp-comments-post.php" method="post" 
        id="commentform" name="commentform">
    ...
    </form>

(Obviously, I’ve removed most of the code for brevity.) Deleting the contents of the form action works to a certain extent, except it creates invalid code. Another option is to replace the action with another URI, such as http://www.google.com. The second task is to re-enable it where appropriate. Since most Spammers use an automated system of some sort to generate comments, and these bots don’t use JavaScript, we can just write a JavaScript that puts the right value back in. This will prevent a user who has JavaScript disabled, or who is in an old browser, from leaving a comment. I’m prepared to live with this. Anyway, I don’t usually add script tags directly into a page, but in this case I will, just to make it easier. After the close of the form tag, insert the following:

1
2
3
    <script type="text/javascript">
        document.forms[0].action="{$siteurl}/wp-comments-post.php";
    </script>

Of course, if this isn’t the first form in your document, for example your search form appears in the source before this one, then you’ll need to change the number of forms[_x_] accordingly. You could try using document.getElementById("commentform").action, but I think there’s an issue with this method not being available until the DOM is complete, which it isn’t at this stage.