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 = ''; sqGetGlobalVar('attachments',$attachments,SQ_INORDER); 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)) { deleteTempFile($filename.'.asc'); ...
Files
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.