php-gnupg/gnupg.c
2012-01-29 02:42:28 +00:00

1553 lines
49 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
+--------------------------------------------------------------------+
| PECL :: gnupg |
+--------------------------------------------------------------------+
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
| Copyright (c) 2006, Thilo Raufeisen <traufeisen@php.net> |
+--------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "zend_exceptions.h"
#include "ext/standard/info.h"
#include "php_gnupg.h"
#ifdef ZEND_ENGINE_2
#include "php_gnupg_keylistiterator.h"
#endif
static int le_gnupg;
#ifdef ZEND_ENGINE_2
static zend_object_handlers gnupg_object_handlers;
#endif
/* {{{ defs */
#ifdef ZEND_ENGINE_2
#define GNUPG_GETOBJ() \
zval *this = getThis(); \
gnupg_object *intern; \
zval *res; \
if(this){ \
intern = (gnupg_object*) zend_object_store_get_object(getThis() TSRMLS_CC); \
if(!intern){ \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized gnupg object"); \
RETURN_FALSE; \
} \
}
#define GNUPG_ERR(error) \
if(intern){ \
switch (intern->errormode) { \
case 1: \
php_error_docref(NULL TSRMLS_CC, E_WARNING, (char*)error); \
break; \
case 2: \
zend_throw_exception(zend_exception_get_default(TSRMLS_C), (char*) error, 0 TSRMLS_CC); \
break; \
default: \
intern->errortxt = (char*)error; \
} \
}else{ \
php_error_docref(NULL TSRMLS_CC, E_WARNING, (char*)error); \
} \
if(return_value){ \
RETVAL_FALSE; \
}
#else
#define GNUPG_ERR(error) \
if(intern && intern->errormode!=1) { \
intern->errortxt = (char*)error; \
}else{ \
php_error_docref(NULL TSRMLS_CC, E_WARNING, (char*)error); \
} \
if(return_value){ \
RETVAL_FALSE; \
}
#define GNUPG_GETOBJ() \
zval *this = NULL; \
zval *res; \
gnupg_object *intern;
#endif
/* }}} */
/* {{{ free encryptkeys */
static void gnupg_free_encryptkeys(gnupg_object *intern TSRMLS_DC){
if(intern){
int idx;
/* loop through all encryptkeys and unref them in the gpgme-lib */
for(idx=0;idx<intern->encrypt_size;idx++){
gpgme_key_unref (intern->encryptkeys[idx]);
}
/* it´s an odd-thing, but other solutions makes problems :
* erealloc(x,0) gives a segfault with PHP 4 and debug enabled
* efree(x) alone ends in a segfault
*/
efree(erealloc(intern->encryptkeys,0));
intern->encryptkeys = NULL;
intern->encrypt_size = 0;
}
}
/* }}} */
/* {{{ free_resource */
static void gnupg_free_resource_ptr(gnupg_object *intern TSRMLS_DC){
if(intern){
if(intern->ctx){
/* clear all signers from the gpgme-lib and finally release it */
gpgme_signers_clear (intern->ctx);
gpgme_release (intern->ctx);
intern->ctx = NULL;
}
/* basic cleanup */
gnupg_free_encryptkeys(intern TSRMLS_CC);
zend_hash_destroy(intern->signkeys);
FREE_HASHTABLE(intern->signkeys);
zend_hash_destroy(intern->decryptkeys);
FREE_HASHTABLE(intern->decryptkeys);
}
}
/* }}} */
/* {{{ gnupg_res_dtor */
static void gnupg_res_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) {
gnupg_object *intern;
intern = (gnupg_object *) rsrc->ptr;
gnupg_free_resource_ptr(intern TSRMLS_CC);
efree(intern);
}
/* }}} */
/* {{{ gnupg_res_init */
static void gnupg_res_init(gnupg_object *intern TSRMLS_DC){
/* init the gpgme-lib and set the default values */
gpgme_ctx_t ctx;
gpgme_check_version (NULL);
gpgme_new (&ctx);
#ifdef GNUPG_PATH
gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, GNUPG_PATH, NULL);
#endif
gpgme_set_armor (ctx,1);
intern->ctx = ctx;
intern->encryptkeys = NULL;
intern->encrypt_size = 0;
intern->signmode = GPGME_SIG_MODE_CLEAR;
intern->errortxt = NULL;
intern->errormode = 3;
ALLOC_HASHTABLE (intern->signkeys);
zend_hash_init (intern->signkeys, 0, NULL, NULL, 0);
ALLOC_HASHTABLE (intern->decryptkeys);
zend_hash_init (intern->decryptkeys, 0, NULL, NULL, 0);
return;
}
/* }}} */
#ifdef ZEND_ENGINE_2
/* {{{ free_storage */
static void gnupg_obj_dtor(gnupg_object *intern TSRMLS_DC){
if(!intern){
return;
}
gnupg_free_resource_ptr(intern TSRMLS_CC);
if(intern->zo.properties){
zend_hash_destroy(intern->zo.properties);
FREE_HASHTABLE(intern->zo.properties);
}
efree(intern);
}
/* }}} */
/* {{{ objects_new */
zend_object_value gnupg_obj_new(zend_class_entry *class_type TSRMLS_DC){
gnupg_object *intern;
#if PHP_VERSION_ID < 50399
zval *tmp;
#endif
zend_object_value retval;
intern = ecalloc(1, sizeof(gnupg_object));
intern->zo.ce = class_type;
#if PHP_VERSION_ID < 50399
intern->zo.properties = NULL;
ALLOC_HASHTABLE (intern->zo.properties);
zend_hash_init (intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
zend_hash_copy (intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
#else
object_properties_init(&intern->zo, class_type);
#endif
retval.handle = zend_objects_store_put(intern,NULL,(zend_objects_free_object_storage_t) gnupg_obj_dtor,NULL TSRMLS_CC);
retval.handlers = (zend_object_handlers *) & gnupg_object_handlers;
gnupg_res_init (intern TSRMLS_CC);
return retval;
}
/* }}} */
/* {{{ methodlist gnupg */
static zend_function_entry gnupg_methods[] = {
PHP_FALIAS(keyinfo, gnupg_keyinfo, NULL)
PHP_FALIAS(verify, gnupg_verify, NULL)
PHP_FALIAS(geterror, gnupg_geterror, NULL)
PHP_FALIAS(clearsignkeys, gnupg_clearsignkeys, NULL)
PHP_FALIAS(clearencryptkeys, gnupg_clearencryptkeys, NULL)
PHP_FALIAS(cleardecryptkeys, gnupg_cleardecryptkeys, NULL)
PHP_FALIAS(setarmor, gnupg_setarmor, NULL)
PHP_FALIAS(encrypt, gnupg_encrypt, NULL)
PHP_FALIAS(decrypt, gnupg_decrypt, NULL)
PHP_FALIAS(export, gnupg_export, NULL)
PHP_FALIAS(import, gnupg_import, NULL)
PHP_FALIAS(getprotocol, gnupg_getprotocol, NULL)
PHP_FALIAS(setsignmode, gnupg_setsignmode, NULL)
PHP_FALIAS(sign, gnupg_sign, NULL)
PHP_FALIAS(encryptsign, gnupg_encryptsign, NULL)
PHP_FALIAS(decryptverify, gnupg_decryptverify, NULL)
PHP_FALIAS(addsignkey, gnupg_addsignkey, NULL)
PHP_FALIAS(addencryptkey, gnupg_addencryptkey, NULL)
PHP_FALIAS(adddecryptkey, gnupg_adddecryptkey, NULL)
PHP_FALIAS(deletekey, gnupg_deletekey, NULL)
PHP_FALIAS(gettrustlist, gnupg_gettrustlist, NULL)
PHP_FALIAS(listsignatures, gnupg_listsignatures, NULL)
PHP_FALIAS(seterrormode, gnupg_seterrormode, NULL)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ class constants */
static void gnupg_declare_long_constant(const char *const_name, long value TSRMLS_DC){
#if PHP_MAJOR_VERSION > 5 || PHP_MINOR_VERSION >= 1
zend_declare_class_constant_long(gnupg_class_entry, (char*)const_name, strlen(const_name), value TSRMLS_CC);
#else
zval *constant = malloc(sizeof(*constant));
ZVAL_LONG(constant,value);
INIT_PZVAL(constant);
zend_hash_update(&gnupg_class_entry->constants_table, (char*)const_name, strlen(const_name)+1, &constant, sizeof(zval*), NULL);
#endif
}
/* }}} */
#endif /* ZEND_ENGINE_2 */
/* {{{ functionlist gnupg */
static zend_function_entry gnupg_functions[] = {
PHP_FE(gnupg_init, NULL)
PHP_FE(gnupg_keyinfo, NULL)
PHP_FE(gnupg_sign, NULL)
PHP_FE(gnupg_verify, NULL)
PHP_FE(gnupg_clearsignkeys, NULL)
PHP_FE(gnupg_clearencryptkeys, NULL)
PHP_FE(gnupg_cleardecryptkeys, NULL)
PHP_FE(gnupg_setarmor, NULL)
PHP_FE(gnupg_encrypt, NULL)
PHP_FE(gnupg_decrypt, NULL)
PHP_FE(gnupg_export, NULL)
PHP_FE(gnupg_import, NULL)
PHP_FE(gnupg_getprotocol, NULL)
PHP_FE(gnupg_setsignmode, NULL)
PHP_FE(gnupg_encryptsign, NULL)
PHP_FE(gnupg_decryptverify, NULL)
PHP_FE(gnupg_geterror, NULL)
PHP_FE(gnupg_addsignkey, NULL)
PHP_FE(gnupg_addencryptkey, NULL)
PHP_FE(gnupg_adddecryptkey, NULL)
PHP_FE(gnupg_deletekey, NULL)
PHP_FE(gnupg_gettrustlist, NULL)
PHP_FE(gnupg_listsignatures, NULL)
PHP_FE(gnupg_seterrormode, NULL)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ gnupg_module_entry
*/
zend_module_entry gnupg_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"gnupg",
gnupg_functions,
PHP_MINIT(gnupg),
PHP_MSHUTDOWN(gnupg),
NULL,
NULL,
PHP_MINFO(gnupg),
#if ZEND_MODULE_API_NO >= 20010901
PHP_GNUPG_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_GNUPG
ZEND_GET_MODULE(gnupg)
#endif
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(gnupg)
{
le_gnupg = zend_register_list_destructors_ex(gnupg_res_dtor, NULL, "ctx", module_number);
#ifdef ZEND_ENGINE_2
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "gnupg", gnupg_methods);
ce.create_object = gnupg_obj_new;
gnupg_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
memcpy(&gnupg_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
if (SUCCESS != gnupg_keylistiterator_init()){
return FAILURE;
}
gnupg_declare_long_constant("SIG_MODE_NORMAL", GPGME_SIG_MODE_NORMAL TSRMLS_CC);
gnupg_declare_long_constant("SIG_MODE_DETACH", GPGME_SIG_MODE_DETACH TSRMLS_CC);
gnupg_declare_long_constant("SIG_MODE_CLEAR", GPGME_SIG_MODE_CLEAR TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_UNKNOWN", GPGME_VALIDITY_UNKNOWN TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_UNDEFINED", GPGME_VALIDITY_UNDEFINED TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_NEVER", GPGME_VALIDITY_NEVER TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_MARGINAL", GPGME_VALIDITY_MARGINAL TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_FULL", GPGME_VALIDITY_FULL TSRMLS_CC);
gnupg_declare_long_constant("VALIDITY_ULTIMATE", GPGME_VALIDITY_ULTIMATE TSRMLS_CC);
gnupg_declare_long_constant("PROTOCOL_OpenPGP", GPGME_PROTOCOL_OpenPGP TSRMLS_CC);
gnupg_declare_long_constant("PROTOCOL_CMS", GPGME_PROTOCOL_CMS TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_VALID", GPGME_SIGSUM_VALID TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_GREEN", GPGME_SIGSUM_GREEN TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_RED", GPGME_SIGSUM_RED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_KEY_REVOKED", GPGME_SIGSUM_KEY_REVOKED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_KEY_EXPIRED", GPGME_SIGSUM_KEY_EXPIRED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_SIG_EXPIRED", GPGME_SIGSUM_SIG_EXPIRED TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_KEY_MISSING", GPGME_SIGSUM_KEY_MISSING TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_CRL_MISSING", GPGME_SIGSUM_CRL_MISSING TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_CRL_TOO_OLD", GPGME_SIGSUM_CRL_TOO_OLD TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_BAD_POLICY", GPGME_SIGSUM_BAD_POLICY TSRMLS_CC);
gnupg_declare_long_constant("SIGSUM_SYS_ERROR", GPGME_SIGSUM_SYS_ERROR TSRMLS_CC);
gnupg_declare_long_constant("ERROR_WARNING", 1 TSRMLS_CC);
gnupg_declare_long_constant("ERROR_EXCEPTION", 2 TSRMLS_CC);
gnupg_declare_long_constant("ERROR_SILENT", 3 TSRMLS_CC);
#endif
REGISTER_LONG_CONSTANT("GNUPG_SIG_MODE_NORMAL", GPGME_SIG_MODE_NORMAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIG_MODE_DETACH", GPGME_SIG_MODE_DETACH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIG_MODE_CLEAR", GPGME_SIG_MODE_CLEAR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_UNKNOWN", GPGME_VALIDITY_UNKNOWN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_UNDEFINED", GPGME_VALIDITY_UNDEFINED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_NEVER", GPGME_VALIDITY_NEVER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_MARGINAL", GPGME_VALIDITY_MARGINAL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_FULL", GPGME_VALIDITY_FULL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_VALIDITY_ULTIMATE", GPGME_VALIDITY_ULTIMATE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_PROTOCOL_OpenPGP", GPGME_PROTOCOL_OpenPGP, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_PROTOCOL_CMS", GPGME_PROTOCOL_CMS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_VALID", GPGME_SIGSUM_VALID, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_GREEN", GPGME_SIGSUM_GREEN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_RED", GPGME_SIGSUM_RED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_KEY_REVOKED", GPGME_SIGSUM_KEY_REVOKED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_KEY_EXPIRED", GPGME_SIGSUM_KEY_EXPIRED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_SIG_EXPIRED", GPGME_SIGSUM_SIG_EXPIRED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_KEY_MISSING", GPGME_SIGSUM_KEY_MISSING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_CRL_MISSING", GPGME_SIGSUM_CRL_MISSING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_CRL_TOO_OLD", GPGME_SIGSUM_CRL_TOO_OLD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_BAD_POLICY", GPGME_SIGSUM_BAD_POLICY, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_SIGSUM_SYS_ERROR", GPGME_SIGSUM_SYS_ERROR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_ERROR_WARNING", 1, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_ERROR_EXCEPTION", 2, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("GNUPG_ERROR_SILENT", 3, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(gnupg)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(gnupg)
{
php_info_print_table_start();
php_info_print_table_header(2, "gnupg support", "enabled");
php_info_print_table_row(2,"GPGme Version",gpgme_check_version(NULL));
php_info_print_table_row(2,"Extension Version",PHP_GNUPG_VERSION);
php_info_print_table_end();
}
/* }}} */
/* {{{ callback func for setting the passphrase */
gpgme_error_t passphrase_cb (gnupg_object *intern, const char *uid_hint, const char *passphrase_info,int last_was_bad, int fd TSRMLS_DC){
char uid[17];
int idx;
char *passphrase = NULL;
zval *return_value = NULL;
if(last_was_bad){
GNUPG_ERR("Incorrent passphrase");
return 1;
}
for(idx=0;idx<16;idx++){
uid[idx] = uid_hint[idx];
}
uid[16] = '\0';
if(zend_hash_find(intern->signkeys,(char *) uid,17,(void **) &passphrase)==FAILURE){
GNUPG_ERR("no passphrase set");
return 1;
}
if(!passphrase){
GNUPG_ERR("no passphrase set");
return 1;
}
write (fd, passphrase, strlen(passphrase));
write (fd, "\n", 1);
return 0;
}
gpgme_error_t passphrase_decrypt_cb (gnupg_object *intern, const char *uid_hint, const char *passphrase_info,int last_was_bad, int fd TSRMLS_DC){
char uid[17];
int idx;
char *passphrase = NULL;
zval *return_value = NULL;
if(last_was_bad){
GNUPG_ERR("Incorrent passphrase");
return 1;
}
for(idx=0;idx<16;idx++){
uid[idx] = uid_hint[idx];
}
uid[16] = '\0';
if(zend_hash_find(intern->decryptkeys,(char *) uid,17,(void **) &passphrase)==FAILURE){
GNUPG_ERR("no passphrase set");
return 1;
}
if(!passphrase){
GNUPG_ERR("no passphrase set");
return 1;
}
write (fd, passphrase, strlen(passphrase));
write (fd, "\n", 1);
return 0;
}
/* }}} */
/* {{{ gnupg_fetchsignatures */
int gnupg_fetchsignatures(gpgme_signature_t gpgme_signatures, zval *sig_arr, zval *main_arr){
array_init (main_arr);
while(gpgme_signatures){
ALLOC_INIT_ZVAL (sig_arr);
array_init (sig_arr);
add_assoc_string (sig_arr, "fingerprint", gpgme_signatures->fpr, 1);
add_assoc_long (sig_arr, "validity", gpgme_signatures->validity );
add_assoc_long (sig_arr, "timestamp", gpgme_signatures->timestamp );
add_assoc_long (sig_arr, "status", gpgme_signatures->status );
add_assoc_long (sig_arr, "summary", gpgme_signatures->summary );
add_next_index_zval (main_arr, sig_arr);
gpgme_signatures = gpgme_signatures->next;
}
return 1;
}
/* }}} */
/* {{{ proto resource gnupg_init()
* inits gnupg and returns a resource
*/
PHP_FUNCTION(gnupg_init){
gnupg_object *intern;
intern = emalloc(sizeof(gnupg_object));
gnupg_res_init(intern TSRMLS_CC);
ZEND_REGISTER_RESOURCE(return_value,intern,le_gnupg);
}
/* }}} */
/* {{{ proto bool gnupg_setarmor(int armor)
* turn on/off armor mode
* 0 = off
* >0 = on
* */
PHP_FUNCTION(gnupg_setarmor){
long armor;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &armor) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &armor) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if(armor > 1){
armor = 1; /*just to make sure */
}
gpgme_set_armor (intern->ctx,armor);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_seterrormode(int errormde) */
PHP_FUNCTION(gnupg_seterrormode){
long errormode;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &errormode) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &errormode) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
switch(errormode){
case 1: /* warning */
case 3: /* silent */
intern->errormode = errormode;
break;
#ifdef ZEND_ENGINE_2
case 2: /* exception */
intern->errormode = errormode;
break;
#endif
default:
GNUPG_ERR("invalid errormode");
}
}
/* }}} */
/* {{{ proto bool gnupg_setsignmode(int signmode)
* sets the mode for signing operations
*/
PHP_FUNCTION(gnupg_setsignmode){
long signmode;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &signmode) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &signmode) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
switch(signmode){
case GPGME_SIG_MODE_NORMAL:
case GPGME_SIG_MODE_DETACH:
case GPGME_SIG_MODE_CLEAR:
intern->signmode = signmode;
RETVAL_TRUE;
break;
default:
GNUPG_ERR("invalid signmode");
RETVAL_FALSE;
break;
}
}
/* }}} */
/* {{{ proto string gnupg_geterror(void)
* returns the last errormessage
*/
PHP_FUNCTION(gnupg_geterror){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if(!intern->errortxt){
RETURN_FALSE;
}else{
RETURN_STRINGL(intern->errortxt, strlen(intern->errortxt), 1);
}
}
/* }}} */
/* {{{ proto int gnupg_getprotocol(void)
* returns the currently used pgp-protocol.
* atm only OpenPGP is supported
*/
PHP_FUNCTION(gnupg_getprotocol){
RETURN_LONG(GPGME_PROTOCOL_OpenPGP);
}
/* }}} */
/* {{{ proto array gnupg_keyinfo(string pattern)
* returns an array with informations about all keys, that matches the given pattern
*/
PHP_FUNCTION(gnupg_keyinfo)
{
char *searchkey = NULL;
int *searchkey_len;
zval *subarr;
zval *userid;
zval *userids;
zval *subkey;
zval *subkeys;
gpgme_key_t gpgme_key;
gpgme_subkey_t gpgme_subkey;
gpgme_user_id_t gpgme_userid;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &searchkey, &searchkey_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &searchkey, &searchkey_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_op_keylist_start(intern->ctx, searchkey, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("could not init keylist");
return;
}
array_init(return_value);
while(!(intern->err = gpgme_op_keylist_next(intern->ctx, &gpgme_key))){
ALLOC_INIT_ZVAL (subarr);
array_init (subarr);
ALLOC_INIT_ZVAL (subkeys);
array_init (subkeys);
ALLOC_INIT_ZVAL (userids);
array_init (userids);
add_assoc_bool (subarr, "disabled", gpgme_key->disabled );
add_assoc_bool (subarr, "expired", gpgme_key->expired );
add_assoc_bool (subarr, "revoked", gpgme_key->revoked );
add_assoc_bool (subarr, "is_secret", gpgme_key->secret );
add_assoc_bool (subarr, "can_sign", gpgme_key->can_sign );
add_assoc_bool (subarr, "can_encrypt", gpgme_key->can_encrypt );
gpgme_userid = gpgme_key->uids;
while(gpgme_userid){
ALLOC_INIT_ZVAL (userid);
array_init (userid);
add_assoc_string (userid, "name", gpgme_userid->name, 1);
add_assoc_string (userid, "comment", gpgme_userid->comment, 1);
add_assoc_string (userid, "email", gpgme_userid->email, 1);
add_assoc_string (userid, "uid", gpgme_userid->uid, 1);
add_assoc_bool (userid, "revoked", gpgme_userid->revoked );
add_assoc_bool (userid, "invalid", gpgme_userid->invalid );
add_next_index_zval (userids, userid);
gpgme_userid = gpgme_userid->next;
}
add_assoc_zval (subarr, "uids", userids);
gpgme_subkey = gpgme_key->subkeys;
while(gpgme_subkey){
ALLOC_INIT_ZVAL (subkey);
array_init (subkey);
if(gpgme_subkey->fpr){
add_assoc_string (subkey, "fingerprint", gpgme_subkey->fpr, 1);
}
add_assoc_string (subkey, "keyid", gpgme_subkey->keyid, 1);
add_assoc_long (subkey, "timestamp", gpgme_subkey->timestamp );
add_assoc_long (subkey, "expires", gpgme_subkey->expires );
add_assoc_bool (subkey, "is_secret", gpgme_subkey->secret );
add_assoc_bool (subkey, "invalid", gpgme_subkey->invalid );
add_assoc_bool (subkey, "can_encrypt", gpgme_subkey->can_encrypt );
add_assoc_bool (subkey, "can_sign", gpgme_subkey->can_sign );
add_assoc_bool (subkey, "disabled", gpgme_subkey->disabled );
add_assoc_bool (subkey, "expired", gpgme_subkey->expired );
add_assoc_bool (subkey, "revoked", gpgme_subkey->revoked );
add_next_index_zval (subkeys, subkey);
gpgme_subkey = gpgme_subkey->next;
}
add_assoc_zval (subarr, "subkeys", subkeys);
add_next_index_zval (return_value, subarr);
gpgme_key_unref (gpgme_key);
}
return;
}
/* }}} */
/* {{{ proto bool gnupg_addsignkey(string key) */
PHP_FUNCTION(gnupg_addsignkey){
char *key_id = NULL;
int key_id_len;
char *passphrase = NULL;
int passphrase_len;
gpgme_key_t gpgme_key;
gpgme_subkey_t gpgme_subkey;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|s", &res, &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key_id, &gpgme_key, 1)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
if(passphrase){
gpgme_subkey = gpgme_key->subkeys;
while(gpgme_subkey){
if(gpgme_subkey->can_sign == 1){
zend_hash_add(intern->signkeys, (char *) gpgme_subkey->keyid, (uint) strlen(gpgme_subkey->keyid)+1, passphrase, (uint) passphrase_len+1, NULL);
}
gpgme_subkey = gpgme_subkey->next;
}
}
if((intern->err = gpgme_signers_add(intern->ctx, gpgme_key))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not add signer");
}else{
RETVAL_TRUE;
}
gpgme_key_unref(gpgme_key);
}
/* }}} */
/* {{{ proto bool gnupg_adddecryptkey(string key) */
PHP_FUNCTION(gnupg_adddecryptkey){
char *key_id = NULL;
int key_id_len;
char *passphrase = NULL;
int passphrase_len;
gpgme_key_t gpgme_key;
gpgme_subkey_t gpgme_subkey;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &res, &key_id, &key_id_len, &passphrase, &passphrase_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key_id, &gpgme_key, 1)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
gpgme_subkey = gpgme_key->subkeys;
while(gpgme_subkey){
if(gpgme_subkey->secret == 1){
zend_hash_add(intern->decryptkeys, (char *) gpgme_subkey->keyid, (uint) strlen(gpgme_subkey->keyid)+1, passphrase, (uint) passphrase_len+1, NULL);
}
gpgme_subkey = gpgme_subkey->next;
}
gpgme_key_unref(gpgme_key);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_addencryptkey(string key) */
PHP_FUNCTION(gnupg_addencryptkey){
char *key_id = NULL;
int key_id_len;
gpgme_key_t gpgme_key = NULL;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key_id, &key_id_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &key_id, &key_id_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key_id, &gpgme_key, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
intern->encryptkeys = erealloc(intern->encryptkeys, sizeof(intern->encryptkeys) * (intern->encrypt_size + 2));
intern->encryptkeys[intern->encrypt_size] = gpgme_key;
intern->encrypt_size++;
intern->encryptkeys[intern->encrypt_size] = NULL;
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_clearsignerkeys(void)
* removes all keys which are set for signing
*/
PHP_FUNCTION(gnupg_clearsignkeys){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
gpgme_signers_clear (intern->ctx);
zend_hash_clean(intern->signkeys);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_clearencryptkeys(void)
* removes all keys which are set for encryption
*/
PHP_FUNCTION(gnupg_clearencryptkeys){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
gnupg_free_encryptkeys(intern TSRMLS_CC);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool gnupg_clearsignerkeys(void)
* removes all keys which are set for signing
*/
PHP_FUNCTION(gnupg_cleardecryptkeys){
GNUPG_GETOBJ();
if(!this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
zend_hash_clean(intern->decryptkeys);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string gnupg_sign(string text)
* signs the given test with the key, which was set with setsignerkey before
* and returns the signed text
* the signmode depends on gnupg_setsignmode
*/
PHP_FUNCTION(gnupg_sign){
char *value = NULL;
int value_len;
char *userret;
size_t ret_size;
gpgme_data_t in, out;
gpgme_sign_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &value, &value_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, value, value_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
return;
}
if((intern->err = gpgme_data_new(&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_sign(intern->ctx, in, out, intern->signmode))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("data signing failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
result = gpgme_op_sign_result (intern->ctx);
if(result->invalid_signers){
GNUPG_ERR("invalid signers found");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
if(!result->signatures){
GNUPG_ERR("no signature in result");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
if(ret_size < 1){
RETVAL_FALSE;
}else{
RETVAL_STRINGL (userret,ret_size,1);
}
gpgme_data_release (in);
free (userret);
}
/* }}} */
/* {{{ proto string gnupg_encrypt(string text)
* encrypts the given text with the key, which was set with setencryptkey before
* and returns the encrypted text
*/
PHP_FUNCTION(gnupg_encrypt){
char *value = NULL;
int value_len;
char *userret = NULL;
size_t ret_size;
gpgme_data_t in, out;
gpgme_encrypt_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &value, &value_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if(!intern->encryptkeys){
GNUPG_ERR("no key for encryption set");
return;
}
if((intern->err = gpgme_data_new_from_mem (&in, value, value_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could no create in-data buffer");
return;
}
if((intern->err = gpgme_data_new(&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_encrypt(intern->ctx, intern->encryptkeys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("encrypt failed");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
result = gpgme_op_encrypt_result (intern->ctx);
if (result->invalid_recipients){
GNUPG_ERR("Invalid recipient encountered");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
gpgme_data_release (in);
RETVAL_STRINGL (userret,ret_size,1);
free (userret);
if(ret_size < 1){
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto string gnupg_encrypt_sign(string text)
* encrypts and signs the given text with the keys, which weres set with setencryptkey and setsignkey before
* and returns the encrypted text
*/
PHP_FUNCTION(gnupg_encryptsign){
char *value = NULL;
int value_len;
char *userret = NULL;
size_t ret_size;
gpgme_data_t in, out;
gpgme_encrypt_result_t result;
gpgme_sign_result_t sign_result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &value, &value_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if(!intern->encryptkeys){
GNUPG_ERR("no key for encryption set");
return;
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, value, value_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
return;
}
if((intern->err = gpgme_data_new(&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_encrypt_sign(intern->ctx, intern->encryptkeys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("encrypt-sign failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
result = gpgme_op_encrypt_result (intern->ctx);
if (result->invalid_recipients){
GNUPG_ERR("Invalid recipient encountered");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
sign_result = gpgme_op_sign_result (intern->ctx);
if(sign_result->invalid_signers){
GNUPG_ERR("invalid signers found");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
if(!sign_result->signatures){
GNUPG_ERR("could not find a signature");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
gpgme_data_release (in);
RETVAL_STRINGL (userret,ret_size,1);
free (userret);
if(ret_size < 1){
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto array gnupg_verify(string text, string signature [, string &plaintext])
* verifies the given clearsigned text and returns information about the result in an array
*/
PHP_FUNCTION(gnupg_verify){
gpgme_data_t gpgme_text, gpgme_sig;
gpgme_verify_result_t gpgme_result;
zval *signature_array;
zval *signed_text = NULL; /* text without the signature, if its a detached one, or the text incl the sig */
zval *signature = NULL; /* signature, if its a detached one */
zval *plain_text = NULL; /* signed_text without the signature if its not a detached sig */
char *gpg_plain;
size_t gpg_plain_len;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z", &signed_text, &signature, &plain_text) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzz|z", &res, &signed_text, &signature, &plain_text) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if(Z_STRVAL_P(signature)){ /* detached signature */
/* setup signature-databuffer for gpgme */
if((intern->err = gpgme_data_new_from_mem (&gpgme_sig, Z_STRVAL_P(signature), Z_STRLEN_P(signature), 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create signature-databuffer");
return;
}
/* and the text */
if((intern->err = gpgme_data_new_from_mem (&gpgme_text, Z_STRVAL_P(signed_text), Z_STRLEN_P(signed_text), 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create text-databuffer");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
/* now verify sig + text */
if((intern->err = gpgme_op_verify (intern->ctx, gpgme_sig, gpgme_text, NULL))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("verify failed");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
}else{ /* clearsign or normal signature */
if((intern->err = gpgme_data_new_from_mem (&gpgme_sig, Z_STRVAL_P(signed_text), Z_STRLEN_P(signed_text), 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create signature-databuffer");
return;
}
/* set a NULL databuffer for gpgme */
if((intern->err = gpgme_data_new_from_mem (&gpgme_text, NULL, 0, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("could not create text-databuffer");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
/* and verify the 'signature' */
if((intern->err = gpgme_op_verify (intern->ctx, gpgme_sig, NULL, gpgme_text))!=GPG_ERR_NO_ERROR){
GNUPG_ERR ("verify failed");
gpgme_data_release (gpgme_sig);
gpgme_data_release (gpgme_text);
return;
}
}
/* now get the result */
gpgme_result = gpgme_op_verify_result (intern->ctx);
if(!gpgme_result->signatures){
GNUPG_ERR ("no signature found");
}else{
/* fetch all signatures in an array */
gnupg_fetchsignatures (gpgme_result->signatures,signature_array,return_value);
/* get a 'plain' version of the text without a signature */
gpg_plain = gpgme_data_release_and_get_mem(gpgme_text,&gpg_plain_len);
if(gpg_plain && gpg_plain_len > 0 && plain_text){
ZVAL_STRINGL (plain_text, gpg_plain,gpg_plain_len,1);
}
free (gpg_plain);
}
gpgme_data_release (gpgme_sig);
}
/* }}} */
/* {{{ proto string gnupg_decrypt(string enctext)
* decrypts the given enctext
*/
PHP_FUNCTION(gnupg_decrypt){
char *enctxt;
int enctxt_len;
char *userret;
size_t ret_size;
gpgme_data_t in, out;
gpgme_decrypt_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &enctxt, &enctxt_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &enctxt, &enctxt_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_decrypt_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, enctxt, enctxt_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
}
if((intern->err = gpgme_data_new (&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_decrypt (intern->ctx, in, out))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("decrypt failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
result = gpgme_op_decrypt_result (intern->ctx);
if (result->unsupported_algorithm){
GNUPG_ERR("unsupported algorithm");
gpgme_data_release(in);
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
gpgme_data_release (in);
RETVAL_STRINGL (userret,ret_size,1);
free (userret);
if(ret_size < 1){
RETVAL_FALSE;
}
}
/* }}} */
/* {{{ proto string gnupg_decryptverify(string enctext, string &plaintext)
* decrypts the given enctext
*/
PHP_FUNCTION(gnupg_decryptverify){
char *enctxt;
int enctxt_len;
zval *plaintext;
zval *sig_arr;
char *userret;
size_t ret_size;
gpgme_data_t in, out;
gpgme_decrypt_result_t decrypt_result;
gpgme_verify_result_t verify_result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &enctxt, &enctxt_len, &plaintext) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz", &res, &enctxt, &enctxt_len, &plaintext) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
gpgme_set_passphrase_cb (intern->ctx, (void*) passphrase_decrypt_cb, intern);
if((intern->err = gpgme_data_new_from_mem (&in, enctxt, enctxt_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
}
if((intern->err = gpgme_data_new (&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create out-data buffer");
gpgme_data_release(in);
return;
}
if((intern->err = gpgme_op_decrypt_verify (intern->ctx, in, out))!=GPG_ERR_NO_ERROR){
if(!intern->errortxt){
GNUPG_ERR("decrypt-verify failed");
}
gpgme_data_release(in);
gpgme_data_release(out);
RETVAL_FALSE;
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
ZVAL_STRINGL (plaintext,userret,ret_size,1);
free (userret);
decrypt_result = gpgme_op_decrypt_result (intern->ctx);
if (decrypt_result->unsupported_algorithm){
GNUPG_ERR ("unsupported algorithm");
gpgme_data_release(in);
return;
}
verify_result = gpgme_op_verify_result (intern->ctx);
if(!verify_result->signatures){
GNUPG_ERR ("no signature found");
gpgme_data_release(in);
free(out);
return;
}
gnupg_fetchsignatures (verify_result->signatures,sig_arr,return_value);
gpgme_data_release (in);
}
/* }}} */
/* {{{ proto string gnupg_export(string pattern)
* exports the first public key which matches against the given pattern
*/
PHP_FUNCTION(gnupg_export){
char *searchkey = NULL;
int *searchkey_len;
char *userret;
size_t ret_size;
gpgme_data_t out;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &searchkey, &searchkey_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &searchkey, &searchkey_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_data_new (&out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create data buffer");
return;
}
if((intern->err = gpgme_op_export (intern->ctx, searchkey, 0, out))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("export failed");
gpgme_data_release(out);
return;
}
userret = gpgme_data_release_and_get_mem(out,&ret_size);
RETVAL_STRINGL (userret,ret_size,1);
if(ret_size < 1){
RETVAL_FALSE;
}
free(userret);
}
/* }}} */
/* {{{ proto array gnupg_import(string key)
* imports the given key and returns a status-array
*/
PHP_FUNCTION(gnupg_import){
char *importkey = NULL;
int importkey_len;
gpgme_data_t in;
gpgme_import_result_t result;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &importkey, &importkey_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &importkey, &importkey_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_data_new_from_mem (&in, importkey, importkey_len, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not create in-data buffer");
return;
}
if((intern->err = gpgme_op_import(intern->ctx,in))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("import failed");
gpgme_data_release(in);
return;
}
gpgme_data_release(in);
result = gpgme_op_import_result (intern->ctx);
array_init (return_value);
add_assoc_long (return_value, "imported", result->imported);
add_assoc_long (return_value, "unchanged", result->unchanged);
add_assoc_long (return_value, "newuserids", result->new_user_ids);
add_assoc_long (return_value, "newsubkeys", result->new_sub_keys);
add_assoc_long (return_value, "secretimported", result->secret_imported);
add_assoc_long (return_value, "secretunchanged", result->secret_unchanged);
add_assoc_long (return_value, "newsignatures", result->new_signatures);
add_assoc_long (return_value, "skippedkeys", result->skipped_new_keys);
if(result->imports && result->imports->fpr){
add_assoc_string (return_value, "fingerprint", result->imports->fpr, 1);
}
}
/* }}} */
/* {{{ proto book gnupg_deletekey(string key)
* deletes a key from the keyring
*/
PHP_FUNCTION(gnupg_deletekey){
char *key;
int key_len;
long allow_secret = 0;
gpgme_key_t gpgme_key;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &key, &key_len, &allow_secret) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &res, &key, &key_len, &allow_secret) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_get_key(intern->ctx, key, &gpgme_key, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed");
return;
}
if((intern->err = gpgme_op_delete(intern->ctx,gpgme_key,allow_secret))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("delete failed");
RETVAL_FALSE;
}else{
RETVAL_TRUE;
}
gpgme_key_unref(gpgme_key);
}
/* }}} */
/* {{{ proto array gnupg_gettrustlist(string pattern)
* searching for trust items which match PATTERN
*/
PHP_FUNCTION(gnupg_gettrustlist){
char *pattern;
int pattern_len;
zval *sub_arr;
gpgme_trust_item_t item;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pattern, &pattern_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &pattern, &pattern_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_op_trustlist_start (intern->ctx, pattern, 0))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not start trustlist");
return;
}
array_init(return_value);
while (!(intern->err = gpgme_op_trustlist_next (intern->ctx, &item))){
ALLOC_INIT_ZVAL (sub_arr);
array_init (sub_arr);
add_assoc_long (sub_arr, "level", item->level );
add_assoc_long (sub_arr, "type", item->type );
add_assoc_string (sub_arr, "keyid", item->keyid, 1);
add_assoc_string (sub_arr, "ownertrust", item->owner_trust, 1);
add_assoc_string (sub_arr, "validity", item->validity, 1);
add_assoc_string (sub_arr, "name", item->name, 1);
gpgme_trust_item_unref (item);
add_next_index_zval (return_value, sub_arr);
}
}
/* }}} */
/* {{{ proto array gnupg_listsignatures(string keyid) */
PHP_FUNCTION(gnupg_listsignatures){
char *keyid;
char keyid_len;
zval *sub_arr;
zval *sig_arr;
gpgme_key_t gpgme_key;
gpgme_user_id_t gpgme_userid;
gpgme_key_sig_t gpgme_signature;
GNUPG_GETOBJ();
if(this){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &keyid, &keyid_len) == FAILURE){
return;
}
}else{
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &res, &keyid, &keyid_len) == FAILURE){
return;
}
ZEND_FETCH_RESOURCE(intern,gnupg_object *, &res, -1, "ctx", le_gnupg);
}
if((intern->err = gpgme_set_keylist_mode(intern->ctx,GPGME_KEYLIST_MODE_SIGS))!=GPG_ERR_NO_ERROR){
GNUPG_ERR("could not switch to sigmode");
return;
}
if((intern->err = gpgme_get_key(intern->ctx, keyid, &gpgme_key, 0)) != GPG_ERR_NO_ERROR){
GNUPG_ERR("get_key failed. given key not unique?");
return;
}
if(!gpgme_key->uids){
GNUPG_ERR("no uids found");
gpgme_key_unref(gpgme_key);
return;
}
array_init(return_value);
gpgme_userid = gpgme_key->uids;
while(gpgme_userid){
ALLOC_INIT_ZVAL (sub_arr);
array_init (sub_arr);
gpgme_signature = gpgme_userid->signatures;
while(gpgme_signature){
ALLOC_INIT_ZVAL (sig_arr);
array_init (sig_arr);
add_assoc_string (sig_arr, "uid", gpgme_signature->uid, 1);
add_assoc_string (sig_arr, "name", gpgme_signature->name, 1);
add_assoc_string (sig_arr, "email", gpgme_signature->email, 1);
add_assoc_string (sig_arr, "comment", gpgme_signature->comment, 1);
add_assoc_long (sig_arr, "expires", gpgme_signature->expires );
add_assoc_bool (sig_arr, "revoked", gpgme_signature->revoked );
add_assoc_bool (sig_arr, "expired", gpgme_signature->expired );
add_assoc_bool (sig_arr, "invalid", gpgme_signature->invalid );
add_assoc_zval (sub_arr,gpgme_signature->keyid,sig_arr);
gpgme_signature = gpgme_signature->next;
}
add_assoc_zval (return_value,gpgme_userid->uid,sub_arr);
gpgme_userid = gpgme_userid->next;
}
gpgme_key_unref(gpgme_key);
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/