SquirrelMail 1.4.17 & G/PGP Plugin 2.1

The issue

Using GPG Plugin 2.1 through SquirrelMail 1.4.17 crashes when a new email is encrypted or encrypted and signed, no matter if this new email message has attachments or not. The error caugh right from the PHP-error log is:

[Fri May 15 08:14:21 2009] [error] PHP Fatal error: Call to a member function on a non-object in …/squirrelmail-1.4.17.old/src/compose.php on line 1456

What’s the reason?

Reading all the sources involving GPG Plugin carefully, one can realize that that object located at line 1456 is trying to gather all attachments inside the new email, so it all seems completely normal:

$messageAttachments = $newMessage->getAttachments();

Unluckily, the object $newMessage is wrong referenced. GPG Plugin is too-dependant of SquirrelMail internal data structures, and $newMessage does not point to a valid Message instance.

First step: referencing the Message object

All the written down code designed to obtain the Message class object-reference is fake. So, I had to comment it. Then, I wrote a few lines in order to:

  • Create a new Message object, setting its headers accordingly to the compose.php code.
  • Thanks to the global session variable attachments and the sqGetGlobalVar function – available and well documented in the SquirrelMail API -, re-attach them to the new Message created previously.

The code is shown below:

$newMessage = new Message();
    $newMessage->rfc822_header = $rfc822_header;
    $newMessage->reply_rfc822_header = '';
    if (!empty($attachments)) {
        echo "<br>Adding attachments ... ";
        $attachments = unserialize($attachments);
         if (!empty($attachments) && is_array($attachments))
                 $newMessage->entities = $attachments;

Second step: getting the files on the server-side physically

The next step involves getting the files on the server side right directory, in order to encrypt them. In our case, all uploaded attachments are stored in ../../data/ path. Now, the GPG Plugin code detects all the attachments placed inside our new email object perfectly, but it cannot find them on the server:

	[Thu May 14 18:27:56 2009] [error] PHP Warning:copy(../yvn6ftEGP0DyrjJoO3EgJaElfh6qup49)
[<ahref='function.copy'>function.copy</a>]: failed to open stream: No suchfile or directory in
[...]/gpg/gpg_encrypt.php on line 333

This issue is so easy to solve, all what we need to do is modify the variable $path accordingly with our real uploads directory inside the SquirrelMail server:

$path = '../../data/';

Third step: re-attaching all encrypted files inside our new email Message-Object

Last but no least requires commenting some lines of code trying to re-attach all the encrypted attachments using, once again, the internal data-structures of Message class directly inside the GPG Plugin code. Instead of doing so, I rename the encrypted attachment with extension asc to the original local_name previously stored and referenced inside the current Message structure:


if (copy( $filename.'.asc', $tempfile)) {


All code changes have been made over the file gpg/gpg_encrypt.php. Here you have it: gpg-encrypt.tar.bz2

Installing GPG Plugin patch

It’s a piece of cake: just copy the file gpg_encrypt.php directly, overwritting the previous version, in ../path/to/squirrelmailpath/plugins/gpg/ directory.

Some screenshots

Encrypting a new message

Encrypting a new message

Reading an encrypted email

Reading an encrypted email

Popup to desencrypt the message's body

Popup to unencrypt the message's body

Message unencrypted body

Message unencrypted body

Displaying an encrypted attachment

Displaying an encrypted attachment