1 /*
2     +--------------------------------------------------------------------+
3     | PECL :: http                                                       |
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) 2004-2014, Michael Wallner <mike@php.net>            |
10     +--------------------------------------------------------------------+
11 */
12 
13 #include "php_http_api.h"
14 
grab_file(zval * tmp_name,int argc,va_list argv,zend_hash_key * key)15 static int grab_file(zval *tmp_name, int argc, va_list argv, zend_hash_key *key)
16 {
17 	zval *zfiles, *name, *zname, *error, *zerror, *type, *ztype, *size, *zsize;
18 	zend_hash_key *file_key;
19 
20 	zfiles = (zval *) va_arg(argv, zval *);
21 	file_key = (zend_hash_key *) va_arg(argv, zend_hash_key *);
22 	name = (zval *) va_arg(argv, zval *);
23 	size = (zval *) va_arg(argv, zval *);
24 	type = (zval *) va_arg(argv, zval *);
25 	error = (zval *) va_arg(argv, zval *);
26 
27 	if ((zname = zend_hash_index_find(Z_ARRVAL_P(name), key->h))
28 	&&	(zsize = zend_hash_index_find(Z_ARRVAL_P(size), key->h))
29 	&&	(ztype = zend_hash_index_find(Z_ARRVAL_P(type), key->h))
30 	&&	(zerror = zend_hash_index_find(Z_ARRVAL_P(error), key->h))
31 	) {
32 		zval entry, *array;
33 
34 		array_init(&entry);
35 
36 		Z_TRY_ADDREF_P(tmp_name);
37 		add_assoc_zval_ex(&entry, ZEND_STRL("file"), tmp_name);
38 		Z_TRY_ADDREF_P(zname);
39 		add_assoc_zval_ex(&entry, ZEND_STRL("name"), zname);
40 		Z_TRY_ADDREF_P(zsize);
41 		add_assoc_zval_ex(&entry, ZEND_STRL("size"), zsize);
42 		Z_TRY_ADDREF_P(ztype);
43 		add_assoc_zval_ex(&entry, ZEND_STRL("type"), ztype);
44 		Z_TRY_ADDREF_P(zerror);
45 		add_assoc_zval_ex(&entry, ZEND_STRL("error"), zerror);
46 
47 		if (file_key->key && (array = zend_hash_find(Z_ARRVAL_P(zfiles), file_key->key))) {
48 			add_next_index_zval(array, &entry);
49 		} else if (!file_key->key && (array = zend_hash_index_find(Z_ARRVAL_P(zfiles), file_key->h))) {
50 			add_next_index_zval(array, &entry);
51 		} else {
52 			zval tmp;
53 
54 			array_init(&tmp);
55 			add_next_index_zval(&tmp, &entry);
56 			if (file_key->key) {
57 				zend_hash_update(Z_ARRVAL_P(zfiles), file_key->key, &tmp);
58 			} else {
59 				zend_hash_index_update(Z_ARRVAL_P(zfiles), file_key->h, &tmp);
60 			}
61 		}
62 	}
63 
64 	return ZEND_HASH_APPLY_KEEP;
65 }
66 
grab_files(zval * val,int argc,va_list argv,zend_hash_key * key)67 static int grab_files(zval *val, int argc, va_list argv, zend_hash_key *key)
68 {
69 	zval *zfiles, *name, *tmp_name, *error, *type, *size;
70 
71 	zfiles = (zval *) va_arg(argv, zval *);
72 
73 	if ((Z_TYPE_P(val) == IS_ARRAY)
74 	&&	(tmp_name = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("tmp_name")))
75 	&&	(name = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("name")))
76 	&&	(size = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("size")))
77 	&&	(type = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("type")))
78 	&&	(error = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("error")))
79 	) {
80 		int count;
81 
82 		if (Z_TYPE_P(tmp_name) == IS_ARRAY && (count = zend_hash_num_elements(Z_ARRVAL_P(tmp_name))) > 1) {
83 			if (count == zend_hash_num_elements(Z_ARRVAL_P(name))
84 			&&	count == zend_hash_num_elements(Z_ARRVAL_P(size))
85 			&&	count == zend_hash_num_elements(Z_ARRVAL_P(type))
86 			&&	count == zend_hash_num_elements(Z_ARRVAL_P(error))
87 			) {
88 				zend_hash_apply_with_arguments(Z_ARRVAL_P(tmp_name), grab_file, 6, zfiles, key, name, size, type, error);
89 			} else {
90 				/* wat?! */
91 				return ZEND_HASH_APPLY_STOP;
92 			}
93 		} else  {
94 			zval *tmp, entry;
95 
96 			ZVAL_DUP(&entry, val);
97 			if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), ZEND_STRL("tmp_name")))) {
98 				Z_ADDREF_P(tmp);
99 				add_assoc_zval_ex(&entry, ZEND_STRL("file"), tmp);
100 				zend_hash_str_del(Z_ARRVAL(entry), ZEND_STRL("tmp_name"));
101 			}
102 			if (key->key) {
103 				zend_hash_update(Z_ARRVAL_P(zfiles), key->key, &entry);
104 			} else {
105 				zend_hash_index_update(Z_ARRVAL_P(zfiles), key->h, &entry);
106 			}
107 		}
108 	}
109 
110 	return ZEND_HASH_APPLY_KEEP;
111 }
112 
113 #define PHP_HTTP_ENV_REQUEST_OBJECT_INIT(obj) \
114 	do { \
115 		if (!obj->message) { \
116 			obj->message = php_http_message_init_env(NULL, PHP_HTTP_REQUEST); \
117 		} \
118 	} while(0)
119 
120 static zend_class_entry *php_http_env_request_class_entry;
php_http_get_env_request_class_entry(void)121 zend_class_entry *php_http_get_env_request_class_entry(void)
122 {
123 	return php_http_env_request_class_entry;
124 }
125 
126 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnvRequest___construct, 0, 0, 0)
127 ZEND_END_ARG_INFO();
PHP_METHOD(HttpEnvRequest,__construct)128 static PHP_METHOD(HttpEnvRequest, __construct)
129 {
130 	php_http_message_object_t *obj;
131 	zval *zsg, zqs;
132 
133 	php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
134 
135 	obj = PHP_HTTP_OBJ(NULL, getThis());
136 	obj->body = NULL;
137 
138 	php_http_expect(obj->message = php_http_message_init_env(obj->message, PHP_HTTP_REQUEST), unexpected_val, return);
139 
140 	zsg = php_http_env_get_superglobal(ZEND_STRL("_GET"));
141 	object_init_ex(&zqs, php_http_querystring_get_class_entry());
142 	php_http_expect(SUCCESS == php_http_querystring_ctor(&zqs, zsg), unexpected_val, return);
143 	zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("query"), &zqs);
144 	zval_ptr_dtor(&zqs);
145 
146 	zsg = php_http_env_get_superglobal(ZEND_STRL("_POST"));
147 	object_init_ex(&zqs, php_http_querystring_get_class_entry());
148 	php_http_expect(SUCCESS == php_http_querystring_ctor(&zqs, zsg), unexpected_val, return);
149 	zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("form"), &zqs);
150 	zval_ptr_dtor(&zqs);
151 
152 	zsg = php_http_env_get_superglobal(ZEND_STRL("_COOKIE"));
153 	object_init_ex(&zqs, php_http_querystring_get_class_entry());
154 	php_http_expect(SUCCESS == php_http_querystring_ctor(&zqs, zsg), unexpected_val, return);
155 	zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("cookie"), &zqs);
156 	zval_ptr_dtor(&zqs);
157 
158 	array_init(&zqs);
159 	if ((zsg = php_http_env_get_superglobal(ZEND_STRL("_FILES")))) {
160 		zend_hash_apply_with_arguments(Z_ARRVAL_P(zsg), grab_files, 1, &zqs);
161 	}
162 	zend_update_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("files"), &zqs);
163 	zval_ptr_dtor(&zqs);
164 }
165 
166 #define call_querystring_get(prop) \
167 	do {\
168 		zend_fcall_info fci; \
169 		zend_fcall_info_cache fcc; \
170 		zval rv, mn, *args = ecalloc(sizeof(zval), ZEND_NUM_ARGS()); \
171 		zval *this_ptr = getThis(); \
172 		zval qs_tmp, *qs = zend_read_property(Z_OBJCE_P(this_ptr), this_ptr, ZEND_STRL(prop), 0, &qs_tmp); \
173 		 \
174 		ZVAL_NULL(&rv); \
175 		array_init(&mn); \
176 		Z_TRY_ADDREF_P(qs); \
177 		add_next_index_zval(&mn, qs); \
178 		add_next_index_stringl(&mn, ZEND_STRL("get")); \
179 		zend_fcall_info_init(&mn, 0, &fci, &fcc, NULL, NULL); \
180 		zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args); \
181 		zend_fcall_info_argp(&fci, ZEND_NUM_ARGS(), args); \
182 		zend_fcall_info_call(&fci, &fcc, &rv, NULL); \
183 		zend_fcall_info_args_clear(&fci, 1); \
184 		efree(args); \
185 		zval_dtor(&mn); \
186 		RETVAL_ZVAL(&rv, 0, 1); \
187 	} while(0);
188 
189 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnvRequest_getForm, 0, 0, 0)
190 	ZEND_ARG_INFO(0, name)
191 	ZEND_ARG_INFO(0, type)
192 	ZEND_ARG_INFO(0, defval)
193 	ZEND_ARG_INFO(0, delete)
194 ZEND_END_ARG_INFO();
PHP_METHOD(HttpEnvRequest,getForm)195 static PHP_METHOD(HttpEnvRequest, getForm)
196 {
197 	if (ZEND_NUM_ARGS()) {
198 		call_querystring_get("form");
199 	} else {
200 		zval zform_tmp, *zform = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("form"), 0, &zform_tmp);
201 		RETURN_ZVAL(zform, 1, 0);
202 	}
203 }
204 
205 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnvRequest_getQuery, 0, 0, 0)
206 	ZEND_ARG_INFO(0, name)
207 	ZEND_ARG_INFO(0, type)
208 	ZEND_ARG_INFO(0, defval)
209 	ZEND_ARG_INFO(0, delete)
210 ZEND_END_ARG_INFO();
PHP_METHOD(HttpEnvRequest,getQuery)211 static PHP_METHOD(HttpEnvRequest, getQuery)
212 {
213 	if (ZEND_NUM_ARGS()) {
214 		call_querystring_get("query");
215 	} else {
216 		zval zquery_tmp, *zquery = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("query"), 0, &zquery_tmp);
217 		RETURN_ZVAL(zquery, 1, 0);
218 	}
219 }
220 
221 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnvRequest_getCookie, 0, 0, 0)
222 	ZEND_ARG_INFO(0, name)
223 	ZEND_ARG_INFO(0, type)
224 	ZEND_ARG_INFO(0, defval)
225 	ZEND_ARG_INFO(0, delete)
226 ZEND_END_ARG_INFO();
PHP_METHOD(HttpEnvRequest,getCookie)227 static PHP_METHOD(HttpEnvRequest, getCookie)
228 {
229 	if (ZEND_NUM_ARGS()) {
230 		call_querystring_get("cookie");
231 	} else {
232 		zval zcookie_tmp, *zcookie = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("cookie"), 0, &zcookie_tmp);
233 		RETURN_ZVAL(zcookie, 1, 0);
234 	}
235 }
236 
237 ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnvRequest_getFiles, 0, 0, 0)
238 ZEND_END_ARG_INFO();
PHP_METHOD(HttpEnvRequest,getFiles)239 static PHP_METHOD(HttpEnvRequest, getFiles)
240 {
241 	if (SUCCESS == zend_parse_parameters_none()) {
242 		zval zfiles_tmp, *zfiles = zend_read_property(php_http_env_request_class_entry, getThis(), ZEND_STRL("files"), 0, &zfiles_tmp);
243 		RETURN_ZVAL(zfiles, 1, 0);
244 	}
245 }
246 
247 static zend_function_entry php_http_env_request_methods[] = {
248 	PHP_ME(HttpEnvRequest, __construct,  ai_HttpEnvRequest___construct,  ZEND_ACC_PUBLIC)
249 	PHP_ME(HttpEnvRequest, getForm,      ai_HttpEnvRequest_getForm,      ZEND_ACC_PUBLIC)
250 	PHP_ME(HttpEnvRequest, getQuery,     ai_HttpEnvRequest_getQuery,     ZEND_ACC_PUBLIC)
251 	PHP_ME(HttpEnvRequest, getCookie,    ai_HttpEnvRequest_getCookie,    ZEND_ACC_PUBLIC)
252 	PHP_ME(HttpEnvRequest, getFiles,     ai_HttpEnvRequest_getFiles,     ZEND_ACC_PUBLIC)
253 	EMPTY_FUNCTION_ENTRY
254 };
255 
PHP_MINIT_FUNCTION(http_env_request)256 PHP_MINIT_FUNCTION(http_env_request)
257 {
258 	zend_class_entry ce = {0};
259 
260 	INIT_NS_CLASS_ENTRY(ce, "http\\Env", "Request", php_http_env_request_methods);
261 	php_http_env_request_class_entry = zend_register_internal_class_ex(&ce, php_http_message_get_class_entry());
262 
263 	zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("query"), ZEND_ACC_PROTECTED);
264 	zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("form"), ZEND_ACC_PROTECTED);
265 	zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("cookie"), ZEND_ACC_PROTECTED);
266 	zend_declare_property_null(php_http_env_request_class_entry, ZEND_STRL("files"), ZEND_ACC_PROTECTED);
267 
268 	return SUCCESS;
269 }
270 
271 /*
272  * Local variables:
273  * tab-width: 4
274  * c-basic-offset: 4
275  * End:
276  * vim600: noet sw=4 ts=4 fdm=marker
277  * vim<600: noet sw=4 ts=4
278  */
279