1 /*
2   +--------------------------------------------------------------------+
3   | PECL :: gnupg                                                      |
4   +--------------------------------------------------------------------+
5   | Redistribution and use in source and binary forms, with or without |
6   | modification, are permitted provided that the conditions mentioned |
7   | in the accompanying LICENSE file are met.                          |
8   +--------------------------------------------------------------------+
9   | Copyright (c) 2006, Thilo Raufeisen <traufeisen@php.net>           |
10   | Copyright (c) 2013, Jim Jagielski <jimjag@php.net>                 |
11   | Copyright (c) 2016, Jakub Zelenka <bukka@php.net>                  |
12   +--------------------------------------------------------------------+
13 */
14 
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #include <stddef.h>
20 
21 #include "php.h"
22 #include "php_ini.h"
23 #include "ext/standard/info.h"
24 #include "zend_interfaces.h"
25 #include "zend_exceptions.h"
26 #include "php_gnupg.h"
27 #include "php_gnupg_keylistiterator.h"
28 #include "phpc/phpc.h"
29 
30 static int le_gnupg_keylistiterator;
31 
32 static zend_class_entry *gnupg_keylistiterator_class_entry;
33 
34 PHPC_OBJ_DEFINE_HANDLER_VAR(gnupg_keylistiterator);
35 
36 /* {{{ GNUPG_GET_ITERATOR */
37 #define GNUPG_GET_ITERATOR() \
38 	zval *this = getThis(); \
39 	PHPC_THIS_DECLARE(gnupg_keylistiterator) = NULL; \
40 	do { \
41 		if (this) { \
42 			PHPC_THIS_FETCH_FROM_ZVAL(gnupg_keylistiterator, this); \
43 			if (!PHPC_THIS) { \
44 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized gnupg object"); \
45 				RETURN_FALSE; \
46 			} \
47 		} \
48 	} while (0)
49 /* }}} */
50 
51 /* {{{ free gnupg_keylistiterator */
PHPC_OBJ_HANDLER_FREE(gnupg_keylistiterator)52 PHPC_OBJ_HANDLER_FREE(gnupg_keylistiterator)
53 {
54 	PHPC_OBJ_HANDLER_FREE_INIT(gnupg_keylistiterator);
55 
56 	gpgme_op_keylist_end(PHPC_THIS->ctx);
57 	gpgme_key_release(PHPC_THIS->gpgkey);
58 	gpgme_release(PHPC_THIS->ctx);
59 	if (PHPC_THIS->pattern) {
60 		efree(PHPC_THIS->pattern);
61 	}
62 
63 	PHPC_OBJ_HANDLER_FREE_DESTROY();
64 }
65 
66 /* {{{ create_ex gnupg_keylistiterator */
PHPC_OBJ_HANDLER_CREATE_EX(gnupg_keylistiterator)67 PHPC_OBJ_HANDLER_CREATE_EX(gnupg_keylistiterator)
68 {
69 	PHPC_OBJ_HANDLER_CREATE_EX_INIT(gnupg_keylistiterator);
70 
71 	gpgme_check_version(NULL);
72 
73 	gpgme_new(&PHPC_THIS->ctx);
74 	PHPC_THIS->err = 0;
75 	PHPC_THIS->gpgkey = NULL;
76 	PHPC_THIS->pattern = NULL;
77 
78 	PHPC_OBJ_HANDLER_CREATE_EX_RETURN(gnupg_keylistiterator);
79 }
80 
81 /* {{{ create gnupg_keylistiterator */
PHPC_OBJ_HANDLER_CREATE(gnupg_keylistiterator)82 PHPC_OBJ_HANDLER_CREATE(gnupg_keylistiterator)
83 {
84 	PHPC_OBJ_HANDLER_CREATE_RETURN(gnupg_keylistiterator);
85 }
86 
87 
88 /* {{{ arginfo for gnupg void iterator method */
89 ZEND_BEGIN_ARG_INFO_EX(arginfo_gnupg_void_iterator_method, 0, 0, 0)
90 ZEND_END_ARG_INFO()
91 /* }}} */
92 
93 /* {{{ method list gnupg_keylistiterator */
94 static zend_function_entry gnupg_keylistiterator_methods[] = {
95 	PHP_ME(gnupg_keylistiterator, __construct, arginfo_gnupg_void_iterator_method, ZEND_ACC_PUBLIC)
96 	PHP_ME(gnupg_keylistiterator, current, arginfo_gnupg_void_iterator_method, ZEND_ACC_PUBLIC)
97 	PHP_ME(gnupg_keylistiterator, key, arginfo_gnupg_void_iterator_method, ZEND_ACC_PUBLIC)
98 	PHP_ME(gnupg_keylistiterator, next, arginfo_gnupg_void_iterator_method, ZEND_ACC_PUBLIC)
99 	PHP_ME(gnupg_keylistiterator, rewind, arginfo_gnupg_void_iterator_method, ZEND_ACC_PUBLIC)
100 	PHP_ME(gnupg_keylistiterator, valid, arginfo_gnupg_void_iterator_method, ZEND_ACC_PUBLIC)
101 	PHPC_FE_END
102 };
103 /* }}} */
104 
105 /* {{{ _gnupg_keylistiterator_init
106  */
_gnupg_keylistiterator_init(INIT_FUNC_ARGS)107 int _gnupg_keylistiterator_init(INIT_FUNC_ARGS)
108 {
109 	zend_class_entry ce;
110 
111 	/* init class */
112 	INIT_CLASS_ENTRY(ce, "gnupg_keylistiterator", gnupg_keylistiterator_methods);
113 	PHPC_CLASS_SET_HANDLER_CREATE(ce, gnupg_keylistiterator);
114 	gnupg_keylistiterator_class_entry = PHPC_CLASS_REGISTER(ce);
115 	PHPC_OBJ_INIT_HANDLERS(gnupg_keylistiterator);
116 	PHPC_OBJ_SET_HANDLER_OFFSET(gnupg_keylistiterator);
117 	PHPC_OBJ_SET_HANDLER_FREE(gnupg_keylistiterator);
118 
119 	zend_class_implements(gnupg_keylistiterator_class_entry TSRMLS_CC, 1, zend_ce_iterator);
120 
121 	le_gnupg_keylistiterator = zend_register_list_destructors_ex(NULL, NULL, "ctx_keylistiterator", module_number);
122 
123 	return SUCCESS;
124 }
125 /* }}} */
126 
127 /* {{{ proto __contruct(string $pattern)
128  * constructs keylistiterator with supplied pattern
129  */
PHP_METHOD(gnupg_keylistiterator,__construct)130 PHP_METHOD(gnupg_keylistiterator, __construct)
131 {
132 	char *pattern = NULL;
133 	phpc_str_size_t pattern_len;
134 
135 	int args = ZEND_NUM_ARGS();
136 
137 	GNUPG_GET_ITERATOR();
138 
139 	if (args > 0) {
140 		if (zend_parse_parameters(args TSRMLS_CC, "|s", &pattern, &pattern_len) == FAILURE) {
141 			return;
142 		}
143 		PHPC_THIS->pattern = estrdup(pattern);
144 	}
145 }
146 /* }}} */
147 
148 /* {{{ proto string current() */
PHP_METHOD(gnupg_keylistiterator,current)149 PHP_METHOD(gnupg_keylistiterator, current)
150 {
151 	GNUPG_GET_ITERATOR();
152 
153 	PHPC_CSTR_RETURN(PHPC_THIS->gpgkey->uids[0].uid);
154 }
155 /* }}} */
156 
157 /* {{{ proto string key() */
PHP_METHOD(gnupg_keylistiterator,key)158 PHP_METHOD(gnupg_keylistiterator, key)
159 {
160 	GNUPG_GET_ITERATOR();
161 
162 	PHPC_CSTR_RETURN(PHPC_THIS->gpgkey->subkeys[0].fpr);
163 }
164 /* }}} */
165 
166 /* {{{ proto bool next() */
PHP_METHOD(gnupg_keylistiterator,next)167 PHP_METHOD(gnupg_keylistiterator, next)
168 {
169 	GNUPG_GET_ITERATOR();
170 
171 	if (PHPC_THIS->gpgkey){
172 		gpgme_key_release(PHPC_THIS->gpgkey);
173 	}
174 
175 	if ((PHPC_THIS->err = gpgme_op_keylist_next(PHPC_THIS->ctx, &PHPC_THIS->gpgkey))) {
176 		gpgme_key_release(PHPC_THIS->gpgkey);
177 		PHPC_THIS->gpgkey = NULL;
178 	}
179 	RETURN_TRUE;
180 }
181 /* }}} */
182 
183 /* {{{ proto bool rewind() */
PHP_METHOD(gnupg_keylistiterator,rewind)184 PHP_METHOD(gnupg_keylistiterator, rewind)
185 {
186 	GNUPG_GET_ITERATOR();
187 
188 	if ((PHPC_THIS->err = gpgme_op_keylist_start(
189 			 PHPC_THIS->ctx, PHPC_THIS->pattern ? PHPC_THIS->pattern : "", 0)) != GPG_ERR_NO_ERROR){
190 		zend_throw_exception(zend_exception_get_default(TSRMLS_C), (char *)gpg_strerror(PHPC_THIS->err), 1 TSRMLS_CC);
191 	}
192 	if ((PHPC_THIS->err = gpgme_op_keylist_next(PHPC_THIS->ctx, &PHPC_THIS->gpgkey)) != GPG_ERR_NO_ERROR){
193 		RETURN_FALSE;
194 	}
195 	RETURN_TRUE;
196 }
197 /* }}} */
198 
199 /* {{{ proto bool valid() */
PHP_METHOD(gnupg_keylistiterator,valid)200 PHP_METHOD(gnupg_keylistiterator,valid)
201 {
202 	GNUPG_GET_ITERATOR();
203 
204 	if (PHPC_THIS->gpgkey != NULL) {
205 		RETURN_TRUE;
206 	} else {
207 		RETURN_FALSE;
208 	}
209 }
210 /* }}} */
211 
212 /*
213  * Local variables:
214  * tab-width: 4
215  * c-basic-offset: 4
216  * End:
217  * vim600: noet sw=4 ts=4 fdm=marker
218  * vim<600: noet sw=4 ts=4
219  */
220