I’ve gone quiet

April 2, 2014

As demonstrated by the lack of recent posts, I’ve ceased work on Phorum. ¬†I am still an active user, but I have devoted my time to other non-forum related projects.

Most of my blogging is now done at http://dan.langille.org/ and on http://news.freshports.org/ both of which cover a range of topics.


Adding captcha to Phorum 3

March 4, 2008

I’m still running Phorum 3 on a few websites. I have customized it and I’m running PostgreSQL. Phorum 5 isn’t ready for me yet.

Yet the spammers don’t take any heed of that. They’re still coming strong. I’ve done several things to attempt to stop them, but nothing has taken the place of adding in captcha. In short, captcha requires that you enter a special phrase when completing the form. This is easy for people. Very difficult for computers.

In this post, I will highlight what I did to get captcha running on Phorum 3. Yesterday, there were 153 failed captchas. That’s a lot of spam I don’t have to deal with.

I warn you: this solution requires sessions to be enabled.

This solution stops the automated registrations I’ve been getting. Spammers have set up a robot that registers with the website, then posts to one of the phorume. Adding a captcha to the process causes the registration to fail, thereby stopping the spam that would have followed.

The code

It took me a while to find a simple solution. I did not want to write the code. I wanted to use an existing and easy to use solution. I found one at http://www.white-hat-web-design.co.uk/articles/php-captcha.php. I was pretty impressed with their approach.

The image file

The heart of the solution is CaptchaSecurityImages.php. This file generates the images. You also need to add monofont.ttf to your server. I’m sure there are various compile time options that you need in PHP, but I already had them, whatever they were. ūüôā

Adding the image to the form

The following code adds the image to the registration form.


      <td <?php echo bgcolor($table_body_color_1); ?>><img src="CaptchaSecurityImages.php?width=100&height=40&characters=5" mce_src="CaptchaSecurityImages.php?width=100&height=40&characters=5" /><br />  
      <td valign=top <?php echo bgcolor($table_body_color_1); ?> nowrap><font color="<?php echo $table_body_font_color_1; ?>">  
       <label for="security_code">Security Code: </label></font><input id="security_code" name="security_code" type="text" /><br /></td>  


The above code was added to register.php around line 270. See the call to CaptchaSecurityImages.php? That is what creates the image from which the user must obtain the passphrase. This value is supplied via the input field labelled security_code.

Where’s the answer?

You’ve seen how the image is added to the form. When the user posts the form how does the computer know what the answer is? Simple answer: session data. The call to the CaptchaSecurityImages.php code not only creates a random number and produces an image for the form, it also stores that random number in a SESSION variable on the webserver. Explaining sessions variables is beyond the scope of this article. Read up on it. Imagine it like a special cookie that uniquely identifies every user on the website.

To enable sessions for register.php, I added this entry around line 1:


Processing the answer

The hardest part was finding a way to process the incoming answer. Here is the code I added around line 82:

if (IsSet($_POST['process'])) { 
  if ($_SESSION['security_code'] == $_POST['security_code'] && !empty($_SESSION['security_code'] ) ) { 
     // Insert you code for processing the form here, e.g emailing the submission, entering it into a database. 
  } else { 
     syslog(LOG_ERR, "captcha failure: user='$user' IP='" . $_SERVER['REMOTE_ADDR'] . "' email='$email'"); 
     die('wrong security code.  press back'); 

Here, the code checks to verify that we are doing a post. It then compares the security code provided by the user against the code stored in the session variable. If it matches, it unsets the session variable and normal processing of the form resumes.

If the incorrect security code is supplied, syslog is invoked, and the user id, IP address, and email address are logged. The code then dies, and all processing finishes.

A log entry looks like this:

Mar  4 22:49:30 nyi httpd: captcha failure: user='Medoneax' IP='' email='obw@compassunion.cn'

Creating reports is easy. How many failed captcha entries for Mar 3?

$ grep "Mar  3" /var/log/messages.0 | grep -c capt 

That’s just on one server. ūüôā

What about posting?

At present, this solution merely stops the spammers from registering with an automated process. They could register manually, then spam. But that is not cost effective. Should they try that approach, it would not take long to add captcha to the posting code as well.



PostgreSQL 8.3 released

February 5, 2008

PostgreSQL 8.3 has been released.

The following is a list of press coverage taken from http://archives.postgresql.org/pgsql-advocacy/2008-02/msg00062.php

Lots of impressive stuff there. ¬†I’ve already run it with Bacula and all regression tests passed. ¬†Of high interest to Phorum is full text search improvements.


MySQL bought. PostgreSQL not for sale.

January 20, 2008

A very key point in this article. Product vs project.

Read: http://people.planetpostgresql.org/greg/index.php?/archives/120-Postgres-is-not-for-sale.html


Expanding Phorum

January 8, 2008

I want to expand Phorum.  I want to be able to relate specific phorum threads to one specific entry on my FreeBSD Diary website.  I do this for article feedback.  This is very much like comments on a weblog.

To see this features in action, look at Phorum – how to install and customize it. This article is about Phorum 3, so you might not find much there for your existing Phorum 5 installation. Note the link to the comments under the date in the top right corner. If you click on it, you will find it links to http://www.freebsddiary.org/phorum/list.php?f=3&article_id=258. Note the additional URL paramter article_id. This uniquely identifies the article you were reading.

In the FreeBSD Diary database (freebsdiary.org), there is an article table:

freebsddiary.org=# \d articles
                               Table "public.articles"
    Column    |     Type     |                       Modifiers
 id           | integer      | not null default nextval('articles_id_seq'::regclass)
 actual_date  | date         | not null
 name         | text         | not null
 completed    | character(1) | not null default 'N'::bpchar
 visible_date | text         | not null
 link         | text         | not null
 filename     | text         | not null
 description  | text         |
 author       | text         | default ''::text
    "articles_pkey" PRIMARY KEY, btree (id)
Check constraints:
    "articles_completed" CHECK (completed = 'Y'::bpchar OR completed = 'N'::bpchar)   


This table is referenced from the article_feedback_xref table:

freebsddiary.org=# \d article_feedback_xref
Table "public.article_feedback_xref"
   Column   |  Type   | Modifiers
 article_id | integer | not null
 thread_id  | integer | not null
    "article_feedback_xref_pkey" PRIMARY KEY, btree (article_id, thread_id)
Foreign-key constraints:
    "$2" FOREIGN KEY (thread_id) REFERENCES article_feedback(id) ON UPDATE CASCADE ON DELETE CASCADE  


I have customized the Phorum 3 code to restrict message selection to those related to this particular article. The entry in the cross reference table is added when a new post is made to the phorum.

I want Phorum 5 to provide the same functionality. I am not yet sure of how I am going to achieve this goal. It may be with a table similar to the able. It could be with custom fields on the message table.

I’m still in the idea phase. Ideas? Comments?


PostgreSQL – flexible and fast

January 8, 2008

I’m a PostgreSQL fan. I have been so since 2000. ¬†It is fast. ¬†Reliable. ¬†And best of all, it treats your data right.

I’ve been using Phorum with PostgreSQL since 2000. ¬†I’ve also been blogging since before the term blog was invented. ¬†I called it a diary.

In this blog I shall outline my ideas and intentions with PostgreSQL.  It is my way of documenting what I am going to do.  At the same time, it allows Phorum users to provide feedback on what they want out of PostgreSQL.  I think PostgreSQL has the potential to handle large forums in a very fast and efficient manner. PostgreSQL 8.3, due out within a few weeks, will have full-text search built-in (current versions have full-text search as add-on modules).

Enjoy. Comment.  Learn.  Have fun.