<?php

/////////////////////////////////////////////////////
// gpg_encrypt v1.3                                //
// http://Business-PHP.com/opensource/gpg_encrypt/ //
//                                                 //
// this PHP function provides a way to easily      //
// encrypt messages using GnuPG. See the above URL //
// for more information.                           //
//                                                 //
// should run on PHP 4.3.0 or later                //
//                                                 //
// Copyright (C) 15 Jan 2004 Atom Emet             //
// Copyright (C) 17 Feb 2006 Atom Emet             //
// Atom {at} Business-PHP.com                      //
//                                                 //
// Distributed under the terms of the              //
// GNU General Public License                      //
//                                                 //
// Other licenses available on request             //
//                                                 //
// This program is free software; you can          //
// redistribute it and/or modify it under the      //
// terms of the GNU General Public License as      //
// published by the Free Software Foundation;      //
// either version 2 of the License, or             //   
// (at your option) any later version.             //
//                                                 //
// This program is distributed in the hope         //
// that it will be useful, but WITHOUT ANY         //
// WARRANTY; without even the implied warranty     //
// of MERCHANTABILITY or FITNESS FOR A             //
// PARTICULAR PURPOSE. See the GNU General         //
// Public License for more details.                //
//                                                 //
// You should have received a copy of the          //
// GNU General Public License along with this      //
// program; if not, write to                       //
//    the Free Software Foundation, Inc.           //
//    59 Temple Place - Suite 330                  //
//    Boston, MA  02111-1307, USA                  //
/////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////
// usage - see: http://business-php.com/opensource/gpg_encrypt/
// array gpg_gpg_encrypt(secret-message, /path/to/gpg, /path/to/.gnupg/, 0x123456);

//////////////////////
// define the function
function gpg_encrypt() {

	//////////////////////////////////////////////////////////
	// sanity check - make sure there are at least 4 arguments
	// any extra arguments are considered to be additional key IDs
	if(func_num_args() < 4) {
		trigger_error("gpg_encrypt.php requires at least 4 arguments", E_USER_ERROR);
		// if an error message directs you to the line above please
		// double check that you are providing at least 4 arguments
		die();
	}

	////////////////////////////////
	// assign arguments to variables
	$gpg_encrypt_args = func_get_args();
	$gpg_encrypt_secret_message = array_shift($gpg_encrypt_args);	// 1st argument - secret message
	$gpg_encrypt_gpg_path = array_shift($gpg_encrypt_args);		// 2nd argument - full path to gpg
	$gpg_encrypt_gpg_home = array_shift($gpg_encrypt_args);		// 3rd argument - keyring directory

	///////////////////////////////////////////////////////////////////////
	// make sure that each recipient has the message encrypted to their key
	// the 4th argument, and any subsequent arguments, are key IDs
	foreach($gpg_encrypt_args as $gpg_encrypt_recipient) {
		$gpg_encrypt_recipient_list .= " -r ${gpg_encrypt_recipient}";
	}

	//////////////////////////////////////////////////////////////////////////////
	// sanity check - make sure "$gpg_encrypt_gpg_home" is pointing to a directory
	if(!is_dir($gpg_encrypt_gpg_home)) {
		trigger_error("gpg homedir is not a directory: \"${gpg_encrypt_gpg_home}\"", E_USER_ERROR);
		// if an error message directs you to the line above please
		// double check that your full path to the .gnupg directory is correct
		die();
	}

	////////////////////////////////////////////////////////////////////////////////////////
	// sanity check - make sure "$gpg_encrypt_gpg_path" is pointing to an executable program
	if(!is_executable($gpg_encrypt_gpg_path)) {
		trigger_error("gpg is not executable: \"${gpg_encrypt_gpg_path}\" :: or you may need to comment out this sanity check - see the source", E_USER_ERROR);
		// if an error message directs you to the line above please
		// double check that your full path to gpg is correct
		// ////////////////////////////////////////////////////////////////////////////////////////////
		// it has been reported that some (older) configurations of php will choke on this sanity check
		// if this is causing an error, try to comment out this test
		die();
	}

	//////////////////////////////////////////
	// find which version of GnuPG we're using
	//////////////////////////////////////////

	///////////////////////////////////////////
	// first we'll set up a pipe to read STDOUT
	$gpg_encrypt_version_descriptorspec = array(
		1 => array("pipe", "w")  // STDOUT is a pipe that GnuPG will write to
	);

	////////////////////////////////////////////////////////
	// open a process for gpg to tell us which version it is
	$gpg_encrypt_version_process = proc_open("${gpg_encrypt_gpg_path} --version",
		$gpg_encrypt_version_descriptorspec,
		$gpg_encrypt_version_pipes);

	/////////////////////////////////////////////////////
	// we're only concerned with the first line of output
	$gpg_encrypt_version_output = fgets($gpg_encrypt_version_pipes[1], 1024);

	/////////////////////////////////////////
	// close the $gpg_encrypt_version_process
	proc_close($gpg_encrypt_version_process);

	///////////////////////////////////////////////
	// sanity check - see if we're working with gpg
	if(!ereg('^gpg ', $gpg_encrypt_version_output)) {
	trigger_error("gpg executable is not GnuPG: \"${gpg_encrypt_gpg_path}\"", E_USER_ERROR);
		// if an error message directs you to the line above please
		// double check that your path to gpg is really GnuPG
		die();
	}

	/////////////////////////////////////////////////////////////
	// pick the version number out of $gpg_encrypt_version_output
	// we'll need this so we can determine the correct
	// way to tell GnuPG how to "always trust"
	$gpg_encrypt_gpg_version = eregi_replace('^.* ', '', $gpg_encrypt_version_output);

	////////////////////////////////////////////////////////
	// depending on which version of GnuPG we're using there
	// are two different ways to specify "always trust"
	if("$gpg_encrypt_gpg_version" < '1.2.3') {
		$gpg_encrypt_trust = '--always-trust';		// the old way
	} else {
		$gpg_encrypt_trust = '--trust-model always';	// the new way
	}

	/////////////////////////////////////////////
	// unset variables that we don't need anymore
	unset($gpg_encrypt_version_output,
		$gpg_encrypt_gpg_version);

	////////////////////////////////////////
	// we're done checking the GnuPG version
	////////////////////////////////////////

	//////////////////////////////////////////////
	// set up pipes for handling I/O to/from GnuPG
	$gpg_encrypt_descriptorspec = array(
		0 => array("pipe", "r"),  // STDIN is a pipe that GnuPG will read from
		1 => array("pipe", "w"),  // STDOUT is a pipe that GnuPG will write to
		2 => array("pipe", "w")   // STDERR is a pipe that GnuPG will write to
	);

	///////////////////////////////
	// this opens the GnuPG process
	$gpg_encrypt_gpg_process = proc_open("${gpg_encrypt_gpg_path} --no-random-seed-file --lock-never --homedir ${gpg_encrypt_gpg_home} ${gpg_encrypt_trust} -ea ${gpg_encrypt_recipient_list}",
		$gpg_encrypt_descriptorspec,
		$gpg_encrypt_pipes);

	//////////////////////////////////////////////////////////////////
	// this writes the "$gpg_encrypt_secret_message" to GnuPG on STDIN
	if(is_resource($gpg_encrypt_gpg_process)) {
		fwrite($gpg_encrypt_pipes[0], ${gpg_encrypt_secret_message});
		fclose($gpg_encrypt_pipes[0]);

	/////////////////////////////////////////////////////////
	// this reads the encrypted output from GnuPG from STDOUT
	while(!feof($gpg_encrypt_pipes[1])) {
		$gpg_encrypt_encrypted_message .= fgets($gpg_encrypt_pipes[1], 1024);
	}
	fclose($gpg_encrypt_pipes[1]);

	/////////////////////////////////////////////////////////
	// this reads warnings and notices from GnuPG from STDERR
	while(!feof($gpg_encrypt_pipes[2])) {
		$gpg_encrypt_error_message .= fgets($gpg_encrypt_pipes[2], 1024);
	}
	fclose($gpg_encrypt_pipes[2]);

	/////////////////////////////////////////
	// this collects the exit status of GnuPG
	$gpg_encrypt_exit_status = proc_close($gpg_encrypt_gpg_process);

	////////////////////////////////////////////
	// unset variables that are no longer needed
	// and can only cause trouble
	unset($gpg_encrypt_args,
		$gpg_encrypt_secret_message,
		$gpg_encrypt_recipient_list,
		$gpg_encrypt_recipient,
		$gpg_encrypt_gpg_path,
		$gpg_encrypt_gpg_home,
		$gpg_encrypt_trust);

	////////////////////////////////////
	// this returns an array containing:
	// [0] encrypted output (STDOUT)
	// [1] warnings and notices (STDERR)
	// [2] exit status
	return array($gpg_encrypt_encrypted_message, $gpg_encrypt_error_message, $gpg_encrypt_exit_status);
	}
}
?>
