1 /*
2   +------------------------------------------------------------------------+
3   | Zephir Language                                                        |
4   +------------------------------------------------------------------------+
5   | Copyright (c) 2011-2017 Zephir Team (http://www.zephir-lang.com)       |
6   +------------------------------------------------------------------------+
7   | This source file is subject to the New BSD License that is bundled     |
8   | with this package in the file docs/LICENSE.txt.                        |
9   |                                                                        |
10   | If you did not receive a copy of the license and are unable to         |
11   | obtain it through the world-wide-web, please send an email             |
12   | to license@zephir-lang.com so we can send you a copy immediately.      |
13   +------------------------------------------------------------------------+
14   | Authors: Andres Gutierrez <andres@zephir-lang.com>                     |
15   |          Eduar Carvajal <eduar@zephir-lang.com>                        |
16   |          Vladimir Kolesnikov <vladimir@extrememember.com>              |
17   +------------------------------------------------------------------------+
18 */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <ctype.h>
25 
26 #include <php.h>
27 #include "php_ext.h"
28 #include "php_main.h"
29 
30 #include <ext/standard/php_smart_str.h>
31 #include <ext/standard/php_string.h>
32 #include <ext/standard/php_rand.h>
33 #include <ext/standard/php_lcg.h>
34 #include <ext/standard/php_http.h>
35 #include "ext/standard/base64.h"
36 #include "ext/standard/md5.h"
37 #include "ext/standard/crc32.h"
38 #include "ext/standard/url.h"
39 #include "ext/standard/html.h"
40 #include "ext/date/php_date.h"
41 
42 #ifdef ZEPHIR_USE_PHP_PCRE
43 #include <ext/pcre/php_pcre.h>
44 #endif
45 
46 #ifdef ZEPHIR_USE_PHP_JSON
47 #include <ext/json/php_json.h>
48 #endif
49 
50 #include "kernel/main.h"
51 #include "kernel/memory.h"
52 #include "kernel/string.h"
53 #include "kernel/operators.h"
54 #include "kernel/fcall.h"
55 
56 #define PH_RANDOM_ALNUM 0
57 #define PH_RANDOM_ALPHA 1
58 #define PH_RANDOM_HEXDEC 2
59 #define PH_RANDOM_NUMERIC 3
60 #define PH_RANDOM_NOZERO 4
61 
62 /**
63  * Fast call to php strlen
64  */
zephir_fast_strlen(zval * return_value,zval * str)65 void zephir_fast_strlen(zval *return_value, zval *str){
66 
67 	zval copy;
68 	int use_copy = 0;
69 
70 	if (Z_TYPE_P(str) != IS_STRING) {
71 		zend_make_printable_zval(str, &copy, &use_copy);
72 		if (use_copy) {
73 			str = &copy;
74 		}
75 	}
76 
77 	ZVAL_LONG(return_value, Z_STRLEN_P(str));
78 
79 	if (use_copy) {
80 		zval_dtor(str);
81 	}
82 }
83 
84 /**
85  * Fast call to php strlen
86  */
zephir_fast_strlen_ev(zval * str)87 int zephir_fast_strlen_ev(zval *str){
88 
89 	zval copy;
90 	int use_copy = 0, length;
91 
92 	if (Z_TYPE_P(str) != IS_STRING) {
93 		zend_make_printable_zval(str, &copy, &use_copy);
94 		if (use_copy) {
95 			str = &copy;
96 		}
97 	}
98 
99 	length = Z_STRLEN_P(str);
100 	if (use_copy) {
101 		zval_dtor(str);
102 	}
103 
104 	return length;
105 }
106 
107 /**
108  * Fast call to php strlen
109  */
zephir_fast_strtolower(zval * return_value,zval * str)110 void zephir_fast_strtolower(zval *return_value, zval *str){
111 
112 	zval copy;
113 	int use_copy = 0;
114 	char *lower_str;
115 	unsigned int length;
116 
117 	if (Z_TYPE_P(str) != IS_STRING) {
118 		zend_make_printable_zval(str, &copy, &use_copy);
119 		if (use_copy) {
120 			str = &copy;
121 		}
122 	}
123 
124 	length = Z_STRLEN_P(str);
125 	lower_str = estrndup(Z_STRVAL_P(str), length);
126 	php_strtolower(lower_str, length);
127 
128 	if (use_copy) {
129 		zval_dtor(str);
130 	}
131 
132 	ZVAL_STRINGL(return_value, lower_str, length, 0);
133 }
134 
zephir_strtolower_inplace(zval * s)135 void zephir_strtolower_inplace(zval *s) {
136 	if (EXPECTED(Z_TYPE_P(s) == IS_STRING)) {
137 		php_strtolower(Z_STRVAL_P(s), Z_STRLEN_P(s));
138 	}
139 }
140 
141 /**
142  * Fast call to php join  function
143  */
zephir_fast_join(zval * result,zval * glue,zval * pieces TSRMLS_DC)144 void zephir_fast_join(zval *result, zval *glue, zval *pieces TSRMLS_DC) {
145 
146 	if (Z_TYPE_P(glue) != IS_STRING || Z_TYPE_P(pieces) != IS_ARRAY) {
147 		ZVAL_NULL(result);
148 		zend_error(E_WARNING, "Invalid arguments supplied for join()");
149 		return;
150 	}
151 
152 	php_implode(glue, pieces, result TSRMLS_CC);
153 }
154 
155 /**
156  * Appends to a smart_str a printable version of a zval
157  */
zephir_append_printable_zval(smart_str * implstr,zval ** tmp TSRMLS_DC)158 void zephir_append_printable_zval(smart_str *implstr, zval **tmp TSRMLS_DC) {
159 
160 	zval tmp_val;
161 	unsigned int str_len;
162 
163 	switch (Z_TYPE_PP(tmp)) {
164 		case IS_STRING:
165 			smart_str_appendl(implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
166 			break;
167 
168 		case IS_LONG:
169 			smart_str_append_long(implstr, Z_LVAL_PP(tmp));
170 			break;
171 
172 		case IS_BOOL:
173 			if (Z_LVAL_PP(tmp) == 1) {
174 				smart_str_appendl(implstr, "1", sizeof("1") - 1);
175 			}
176 			break;
177 
178 		case IS_NULL:
179 			break;
180 
181 		case IS_DOUBLE: {
182 			char *stmp;
183 			str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_PP(tmp));
184 			smart_str_appendl(implstr, stmp, str_len);
185 			efree(stmp);
186 		}
187 			break;
188 
189 		case IS_OBJECT: {
190 			int copy;
191 			zval expr;
192 			zend_make_printable_zval(*tmp, &expr, &copy);
193 			smart_str_appendl(implstr, Z_STRVAL(expr), Z_STRLEN(expr));
194 			if (copy) {
195 				zval_dtor(&expr);
196 			}
197 		}
198 			break;
199 
200 		default:
201 			tmp_val = **tmp;
202 			zval_copy_ctor(&tmp_val);
203 			convert_to_string(&tmp_val);
204 			smart_str_appendl(implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
205 			zval_dtor(&tmp_val);
206 			break;
207 	}
208 }
209 
210 /**
211  * Fast join function
212  * This function is an adaption of the php_implode function
213  *
214  */
zephir_fast_join_str(zval * return_value,char * glue,unsigned int glue_length,zval * pieces TSRMLS_DC)215 void zephir_fast_join_str(zval *return_value, char *glue, unsigned int glue_length, zval *pieces TSRMLS_DC) {
216 
217 	zval         **tmp;
218 	HashTable      *arr;
219 	HashPosition   pos;
220 	smart_str      implstr = {0};
221 	unsigned int   numelems, i = 0;
222 
223 	if (Z_TYPE_P(pieces) != IS_ARRAY) {
224 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid arguments supplied for fast_join()");
225 		RETURN_EMPTY_STRING();
226 	}
227 
228 	arr = Z_ARRVAL_P(pieces);
229 	numelems = zend_hash_num_elements(arr);
230 
231 	if (numelems == 0) {
232 		RETURN_EMPTY_STRING();
233 	}
234 
235 	zend_hash_internal_pointer_reset_ex(arr, &pos);
236 
237 	while (zend_hash_get_current_data_ex(arr, (void **) &tmp, &pos) == SUCCESS) {
238 		zephir_append_printable_zval(&implstr, tmp TSRMLS_CC);
239 		if (++i != numelems) {
240 			smart_str_appendl(&implstr, glue, glue_length);
241 		}
242 		zend_hash_move_forward_ex(arr, &pos);
243 	}
244 	smart_str_0(&implstr);
245 
246 	if (implstr.len) {
247 		RETURN_STRINGL(implstr.c, implstr.len, 0);
248 	} else {
249 		smart_str_free(&implstr);
250 		RETURN_EMPTY_STRING();
251 	}
252 }
253 
254 /**
255  * Convert dash/underscored texts returning camelized
256  * (an optional delimiter can be specified as character-mask as for ltrim)
257  */
zephir_camelize(zval * return_value,const zval * str,const zval * delimiter)258 void zephir_camelize(zval *return_value, const zval *str, const zval *delimiter) {
259 
260 	int i, len, delim_len, pre_del = 1;
261 	smart_str camelize_str = {0};
262 	char *marker, ch, *delim;
263 
264 	if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) {
265 		zend_error(E_WARNING, "Invalid arguments supplied for camelize()");
266 		RETURN_EMPTY_STRING();
267 	}
268 
269 	if (delimiter == NULL || Z_TYPE_P(delimiter) == IS_NULL) {
270 		delim = "_-";
271 		delim_len = 2;
272 	} else if (Z_TYPE_P(delimiter) == IS_STRING && Z_STRLEN_P(delimiter) > 0) {
273 		delim = Z_STRVAL_P(delimiter);
274 		delim_len = Z_STRLEN_P(delimiter);
275 	} else {
276 		zend_error(E_WARNING, "The second argument passed to the camelize() must be a string containing at least one character");
277 		RETURN_EMPTY_STRING();
278 	}
279 
280 	marker = Z_STRVAL_P(str);
281 	len    = Z_STRLEN_P(str);
282 
283 	for (i = 0; i < len; i++) {
284 		ch = marker[i];
285 
286 		if (memchr(delim, ch, delim_len)) {
287 			pre_del = 1;
288 			continue;
289 		}
290 		if (pre_del == 1) {
291 			smart_str_appendc(&camelize_str, toupper(ch));
292 			pre_del = 0;
293 		} else {
294 			smart_str_appendc(&camelize_str, tolower(ch));
295 		}
296 	}
297 
298 	smart_str_0(&camelize_str);
299 
300 	if (camelize_str.c) {
301 		RETURN_STRINGL(camelize_str.c, camelize_str.len, 0);
302 	}
303 
304 	RETURN_EMPTY_STRING();
305 }
306 
307 /**
308  * Convert a camelized to a dash/underscored texts (an optional delimiter can be specified)
309  */
zephir_uncamelize(zval * return_value,const zval * str,const zval * delimiter)310 void zephir_uncamelize(zval *return_value, const zval *str, const zval *delimiter) {
311 
312 	unsigned int i;
313 	smart_str uncamelize_str = {0};
314 	char *marker, ch, delim;
315 
316 	if (Z_TYPE_P(str) != IS_STRING) {
317 		zend_error(E_WARNING, "Invalid arguments supplied for uncamelize()");
318 		RETURN_EMPTY_STRING();
319 	}
320 
321 	if (delimiter == NULL || Z_TYPE_P(delimiter) == IS_NULL) {
322 		delim = '_';
323 	} else if (Z_TYPE_P(delimiter) == IS_STRING && Z_STRLEN_P(delimiter) == 1) {
324 		delim = *(Z_STRVAL_P(delimiter));
325 	} else {
326 		zend_error(E_WARNING, "Second argument passed to the uncamelize() must be a string of one character");
327 		RETURN_EMPTY_STRING();
328 	}
329 
330 	marker = Z_STRVAL_P(str);
331 	for (i = 0; i < Z_STRLEN_P(str); i++) {
332 
333 		ch = *marker;
334 
335 		if (ch == '\0') {
336 			break;
337 		}
338 
339 		if (ch >= 'A' && ch <= 'Z') {
340 			if (i > 0) {
341 				smart_str_appendc(&uncamelize_str, delim);
342 			}
343 			smart_str_appendc(&uncamelize_str, (*marker) + 32);
344 		} else {
345 			smart_str_appendc(&uncamelize_str, (*marker));
346 		}
347 
348 		marker++;
349 	}
350 	smart_str_0(&uncamelize_str);
351 
352 	if (uncamelize_str.c) {
353 		RETURN_STRINGL(uncamelize_str.c, uncamelize_str.len, 0);
354 	} else {
355 		RETURN_EMPTY_STRING();
356 	}
357 }
358 
359 /**
360  * Fast call to explode php function
361  */
zephir_fast_explode(zval * return_value,zval * delimiter,zval * str,long limit TSRMLS_DC)362 void zephir_fast_explode(zval *return_value, zval *delimiter, zval *str, long limit TSRMLS_DC) {
363 
364 	if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING || Z_TYPE_P(delimiter) != IS_STRING)) {
365 		zend_error(E_WARNING, "Invalid arguments supplied for explode()");
366 		RETURN_EMPTY_STRING();
367 	}
368 
369 	array_init(return_value);
370 	php_explode(delimiter, str, return_value, limit);
371 }
372 
373 /**
374  * Fast call to explode php function
375  */
zephir_fast_explode_str(zval * return_value,const char * delimiter,int delimiter_length,zval * str,long limit TSRMLS_DC)376 void zephir_fast_explode_str(zval *return_value, const char *delimiter, int delimiter_length, zval *str, long limit TSRMLS_DC) {
377 
378 	zval delimiter_zval;
379 
380 	if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) {
381 		zend_error(E_WARNING, "Invalid arguments supplied for explode()");
382 		RETURN_EMPTY_STRING();
383 	}
384 
385 	ZVAL_STRINGL(&delimiter_zval, delimiter, delimiter_length, 0);
386 
387 	array_init(return_value);
388 	php_explode(&delimiter_zval, str, return_value, limit);
389 }
390 
391 /**
392  * Check if a string is contained into another
393  */
zephir_memnstr(const zval * haystack,const zval * needle ZEPHIR_DEBUG_PARAMS)394 int zephir_memnstr(const zval *haystack, const zval *needle ZEPHIR_DEBUG_PARAMS) {
395 
396 	if (Z_TYPE_P(haystack) != IS_STRING || Z_TYPE_P(needle) != IS_STRING) {
397 		#ifndef ZEPHIR_RELEASE
398 		zend_error(E_WARNING, "Invalid arguments supplied for memnstr in %s on line %d", file, line);
399 		#else
400 		zend_error(E_WARNING, "Invalid arguments supplied for memnstr()");
401 		#endif
402 		return 0;
403 	}
404 
405 	if (Z_STRLEN_P(haystack) >= Z_STRLEN_P(needle)) {
406 		return php_memnstr(Z_STRVAL_P(haystack), Z_STRVAL_P(needle), Z_STRLEN_P(needle), Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack)) ? 1 : 0;
407 	}
408 
409 	return 0;
410 }
411 
412 /**
413  * Check if a string is contained into another
414  */
zephir_memnstr_str(const zval * haystack,char * needle,unsigned int needle_length ZEPHIR_DEBUG_PARAMS)415 int zephir_memnstr_str(const zval *haystack, char *needle, unsigned int needle_length ZEPHIR_DEBUG_PARAMS) {
416 
417 	if (Z_TYPE_P(haystack) != IS_STRING) {
418 		#ifndef ZEPHIR_RELEASE
419 		zend_error(E_WARNING, "Invalid arguments supplied for memnstr in %s on line %d", file, line);
420 		#else
421 		zend_error(E_WARNING, "Invalid arguments supplied for memnstr()");
422 		#endif
423 		return 0;
424 	}
425 
426 	if (Z_STRLEN_P(haystack) >= needle_length) {
427 		return php_memnstr(Z_STRVAL_P(haystack), needle, needle_length, Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack)) ? 1 : 0;
428 	}
429 
430 	return 0;
431 }
432 
433 /**
434  * Inmediate function resolution for strpos function
435  */
zephir_fast_strpos(zval * return_value,const zval * haystack,const zval * needle,unsigned int offset)436 void zephir_fast_strpos(zval *return_value, const zval *haystack, const zval *needle, unsigned int offset) {
437 
438 	const char *found = NULL;
439 
440 	if (UNEXPECTED(Z_TYPE_P(haystack) != IS_STRING || Z_TYPE_P(needle) != IS_STRING)) {
441 		ZVAL_NULL(return_value);
442 		zend_error(E_WARNING, "Invalid arguments supplied for strpos()");
443 		return;
444 	}
445 
446 	if (offset > Z_STRLEN_P(haystack)) {
447 		ZVAL_NULL(return_value);
448 		zend_error(E_WARNING, "Offset not contained in string");
449 		return;
450 	}
451 
452 	if (!Z_STRLEN_P(needle)) {
453 		ZVAL_NULL(return_value);
454 		zend_error(E_WARNING, "Empty delimiter");
455 		return;
456 	}
457 
458 	found = php_memnstr(Z_STRVAL_P(haystack)+offset, Z_STRVAL_P(needle), Z_STRLEN_P(needle), Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack));
459 
460 	if (found) {
461 		ZVAL_LONG(return_value, found-Z_STRVAL_P(haystack));
462 	} else {
463 		ZVAL_BOOL(return_value, 0);
464 	}
465 
466 }
467 
468 /**
469  * Inmediate function resolution for strpos function
470  */
zephir_fast_strpos_str(zval * return_value,const zval * haystack,char * needle,unsigned int needle_length)471 void zephir_fast_strpos_str(zval *return_value, const zval *haystack, char *needle, unsigned int needle_length) {
472 
473 	const char *found = NULL;
474 
475 	if (UNEXPECTED(Z_TYPE_P(haystack) != IS_STRING)) {
476 		ZVAL_NULL(return_value);
477 		zend_error(E_WARNING, "Invalid arguments supplied for strpos()");
478 		return;
479 	}
480 
481 	found = php_memnstr(Z_STRVAL_P(haystack), needle, needle_length, Z_STRVAL_P(haystack) + Z_STRLEN_P(haystack));
482 
483 	if (found) {
484 		ZVAL_LONG(return_value, found-Z_STRVAL_P(haystack));
485 	} else {
486 		ZVAL_BOOL(return_value, 0);
487 	}
488 }
489 
490 /**
491  * Inmediate function resolution for stripos function
492  */
zephir_fast_stripos_str(zval * return_value,zval * haystack,char * needle,unsigned int needle_length)493 void zephir_fast_stripos_str(zval *return_value, zval *haystack, char *needle, unsigned int needle_length) {
494 
495 	const char *found = NULL;
496 	char *needle_dup, *haystack_dup;
497 
498 	if (UNEXPECTED(Z_TYPE_P(haystack) != IS_STRING)) {
499 		ZVAL_NULL(return_value);
500 		zend_error(E_WARNING, "Invalid arguments supplied for stripos()");
501 		return;
502 	}
503 
504 	haystack_dup = estrndup(Z_STRVAL_P(haystack), Z_STRLEN_P(haystack));
505 	php_strtolower(haystack_dup, Z_STRLEN_P(haystack));
506 
507 	needle_dup = estrndup(needle, needle_length);
508 	php_strtolower(needle_dup, needle_length);
509 
510 	found = php_memnstr(haystack_dup, needle, needle_length, haystack_dup + Z_STRLEN_P(haystack));
511 
512 	efree(haystack_dup);
513 	efree(needle_dup);
514 
515 	if (found) {
516 		ZVAL_LONG(return_value, found-Z_STRVAL_P(haystack));
517 	} else {
518 		ZVAL_BOOL(return_value, 0);
519 	}
520 }
521 
522 /**
523  * Immediate function resolution for str_replace function
524  */
zephir_fast_str_replace(zval ** return_value_ptr,zval * search,zval * replace,zval * subject TSRMLS_DC)525 void zephir_fast_str_replace(zval **return_value_ptr, zval *search, zval *replace, zval *subject TSRMLS_DC) {
526 
527 	zval replace_copy, search_copy;
528 	zval *return_value = *return_value_ptr;
529 	int copy_replace = 0, copy_search = 0;
530 
531 	if (Z_TYPE_P(subject) != IS_STRING) {
532 		ZVAL_NULL(return_value);
533 		zend_error(E_WARNING, "Invalid arguments supplied for str_replace()");
534 		return;
535 	}
536 
537 	/**
538 	 * Fallback to userland function if the first parameter is an array
539 	 */
540 	if (Z_TYPE_P(search) == IS_ARRAY) {
541 		do {
542 			zval *params[] = { search, replace, subject };
543 			zval_ptr_dtor(return_value_ptr);
544 			*return_value_ptr = NULL;
545 			zephir_call_func_aparams(return_value_ptr, "str_replace", sizeof("str_replace")-1, NULL, 0, 3, params TSRMLS_CC);
546 			return;
547 		} while(0);
548 	}
549 
550 	if (Z_TYPE_P(replace) != IS_STRING) {
551 		zend_make_printable_zval(replace, &replace_copy, &copy_replace);
552 		if (copy_replace) {
553 			replace = &replace_copy;
554 		}
555 	}
556 
557 	if (Z_TYPE_P(search) != IS_STRING) {
558 		zend_make_printable_zval(search, &search_copy, &copy_search);
559 		if (copy_search) {
560 			search = &search_copy;
561 		}
562 	}
563 
564 	Z_TYPE_P(return_value) = IS_STRING;
565 	if (Z_STRLEN_P(subject) == 0) {
566 		ZVAL_STRINGL(return_value, "", 0, 1);
567 		return;
568 	}
569 
570 	if (Z_STRLEN_P(search) == 1) {
571 		php_char_to_str_ex(Z_STRVAL_P(subject),
572 			Z_STRLEN_P(subject),
573 			Z_STRVAL_P(search)[0],
574 			Z_STRVAL_P(replace),
575 			Z_STRLEN_P(replace),
576 			return_value,
577 			1,
578 			NULL);
579 	} else {
580 		if (Z_STRLEN_P(search) > 1) {
581 			Z_STRVAL_P(return_value) = php_str_to_str_ex(Z_STRVAL_P(subject), Z_STRLEN_P(subject),
582 				Z_STRVAL_P(search), Z_STRLEN_P(search),
583 				Z_STRVAL_P(replace), Z_STRLEN_P(replace), &Z_STRLEN_P(return_value), 1, NULL);
584 		} else {
585 			MAKE_COPY_ZVAL(&subject, return_value);
586 		}
587 	}
588 
589 	if (copy_replace) {
590 		zval_dtor(replace);
591 	}
592 
593 	if (copy_search) {
594 		zval_dtor(search);
595 	}
596 }
597 
598 /**
599  * Fast call to PHP trim() function
600  */
zephir_fast_trim(zval * return_value,zval * str,zval * charlist,int where TSRMLS_DC)601 void zephir_fast_trim(zval *return_value, zval *str, zval *charlist, int where TSRMLS_DC) {
602 
603 	zval copy;
604 	int use_copy = 0;
605 
606 	if (Z_TYPE_P(str) != IS_STRING) {
607 		zend_make_printable_zval(str, &copy, &use_copy);
608 		if (use_copy) {
609 			str = &copy;
610 		}
611 	}
612 
613 	if (charlist && Z_TYPE_P(charlist) == IS_STRING) {
614 		php_trim(Z_STRVAL_P(str), Z_STRLEN_P(str), Z_STRVAL_P(charlist), Z_STRLEN_P(charlist), return_value, where TSRMLS_CC);
615 	} else {
616 		php_trim(Z_STRVAL_P(str), Z_STRLEN_P(str), NULL, 0, return_value, where TSRMLS_CC);
617 	}
618 
619 	if (use_copy) {
620 		zval_dtor(&copy);
621 	}
622 }
623 
624 /**
625  * Fast call to PHP strip_tags() function
626  */
zephir_fast_strip_tags(zval * return_value,zval * str)627 void zephir_fast_strip_tags(zval *return_value, zval *str) {
628 
629 	zval copy;
630 	int use_copy = 0;
631 	char *stripped;
632 	size_t len;
633 
634 	if (Z_TYPE_P(str) != IS_STRING) {
635 		zend_make_printable_zval(str, &copy, &use_copy);
636 		if (use_copy) {
637 			str = &copy;
638 		}
639 	}
640 
641 	stripped = estrndup(Z_STRVAL_P(str), Z_STRLEN_P(str));
642 	len = php_strip_tags(stripped, Z_STRLEN_P(str), NULL, NULL, 0);
643 
644 	if (use_copy) {
645 		zval_dtor(&copy);
646 	}
647 
648 	ZVAL_STRINGL(return_value, stripped, len, 0);
649 }
650 
651 /**
652  * Fast call to PHP strtoupper() function
653  */
zephir_fast_strtoupper(zval * return_value,zval * str)654 void zephir_fast_strtoupper(zval *return_value, zval *str) {
655 
656 	zval copy;
657 	int use_copy = 0;
658 	char *lower_str;
659 	unsigned int length;
660 
661 	if (Z_TYPE_P(str) != IS_STRING) {
662 		zend_make_printable_zval(str, &copy, &use_copy);
663 		if (use_copy) {
664 			str = &copy;
665 		}
666 	}
667 
668 	length = Z_STRLEN_P(str);
669 	lower_str = estrndup(Z_STRVAL_P(str), length);
670 	php_strtoupper(lower_str, length);
671 
672 	if (use_copy) {
673 		zval_dtor(str);
674 	}
675 
676 	ZVAL_STRINGL(return_value, lower_str, length, 0);
677 }
678 
679 /**
680  * Checks if a zval string starts with a zval string
681  */
zephir_start_with(const zval * str,const zval * compared,zval * case_sensitive)682 int zephir_start_with(const zval *str, const zval *compared, zval *case_sensitive)
683 {
684 
685 	int i;
686 	int sensitive = 0;
687 	char *op1_cursor, *op2_cursor;
688 
689 	if (Z_TYPE_P(str) != IS_STRING || Z_TYPE_P(compared) != IS_STRING) {
690 		return 0;
691 	}
692 
693 	if (!Z_STRLEN_P(compared) || !Z_STRLEN_P(str) || Z_STRLEN_P(compared) > Z_STRLEN_P(str)) {
694 		return 0;
695 	}
696 
697 	if (case_sensitive) {
698 		sensitive = zend_is_true(case_sensitive);
699 	}
700 
701 	if (!sensitive) {
702 		return !memcmp(Z_STRVAL_P(str), Z_STRVAL_P(compared), Z_STRLEN_P(compared));
703 	}
704 
705 	op1_cursor = Z_STRVAL_P(str);
706 	op2_cursor = Z_STRVAL_P(compared);
707 	for (i = 0; i < Z_STRLEN_P(compared); i++) {
708 
709 		if (tolower(*op1_cursor) != tolower(*op2_cursor)) {
710 			return 0;
711 		}
712 
713 		op1_cursor++;
714 		op2_cursor++;
715 	}
716 
717 	return 1;
718 }
719 
720 /**
721  * Checks if a zval string starts with a string
722  */
zephir_start_with_str(const zval * str,char * compared,unsigned int compared_length)723 int zephir_start_with_str(const zval *str, char *compared, unsigned int compared_length)
724 {
725 
726 	if (Z_TYPE_P(str) != IS_STRING || compared_length > Z_STRLEN_P(str)) {
727 		return 0;
728 	}
729 
730 	return !memcmp(Z_STRVAL_P(str), compared, compared_length);
731 }
732 
733 /**
734  * Checks if a string starts with other string
735  */
zephir_start_with_str_str(char * str,unsigned int str_length,char * compared,unsigned int compared_length)736 int zephir_start_with_str_str(char *str, unsigned int str_length, char *compared, unsigned int compared_length)
737 {
738 
739 	if (compared_length > str_length) {
740 		return 0;
741 	}
742 
743 	return !memcmp(str, compared, compared_length);
744 }
745 
746 /**
747  * Checks if a zval string ends with a zval string
748  */
zephir_end_with(const zval * str,const zval * compared,zval * case_sensitive)749 int zephir_end_with(const zval *str, const zval *compared, zval *case_sensitive) {
750 
751 	int sensitive = 0;
752 	int i;
753 	char *op1_cursor, *op2_cursor;
754 
755 	if (Z_TYPE_P(str) != IS_STRING || Z_TYPE_P(compared) != IS_STRING) {
756 		return 0;
757 	}
758 
759 	if (!Z_STRLEN_P(compared) || !Z_STRLEN_P(str) || Z_STRLEN_P(compared) > Z_STRLEN_P(str)) {
760 		return 0;
761 	}
762 
763 	if (case_sensitive) {
764 		sensitive = zend_is_true(case_sensitive);
765 	}
766 
767 	if (!sensitive) {
768 		return !memcmp(Z_STRVAL_P(str) + Z_STRLEN_P(str) - Z_STRLEN_P(compared), Z_STRVAL_P(compared), Z_STRLEN_P(compared));
769 	}
770 
771 	op1_cursor = Z_STRVAL_P(str) + Z_STRLEN_P(str) - Z_STRLEN_P(compared);
772 	op2_cursor = Z_STRVAL_P(compared);
773 
774 	for (i = 0; i < Z_STRLEN_P(compared); ++i) {
775 
776 		if (tolower(*op1_cursor) != tolower(*op2_cursor)) {
777 			return 0;
778 		}
779 
780 		++op1_cursor;
781 		++op2_cursor;
782 	}
783 
784 	return 1;
785 }
786 
787 /**
788  * Checks if a zval string ends with a *char string
789  */
zephir_end_with_str(const zval * str,char * compared,unsigned int compared_length)790 int zephir_end_with_str(const zval *str, char *compared, unsigned int compared_length) {
791 
792 	if (Z_TYPE_P(str) != IS_STRING) {
793 		return 0;
794 	}
795 
796 	if (!compared_length || !Z_STRLEN_P(str) || compared_length > Z_STRLEN_P(str)) {
797 		return 0;
798 	}
799 
800 	return !memcmp(Z_STRVAL_P(str) + Z_STRLEN_P(str) - compared_length, compared, compared_length);
801 }
802 
803 /**
804  *
805  */
zephir_random_string(zval * return_value,const zval * type,const zval * length TSRMLS_DC)806 void zephir_random_string(zval *return_value, const zval *type, const zval *length TSRMLS_DC) {
807 
808 	long i, rand_type, ch;
809 	smart_str random_str = {0};
810 
811 	if (Z_TYPE_P(type) != IS_LONG) {
812 		return;
813 	}
814 
815 	if (Z_LVAL_P(type) > PH_RANDOM_NOZERO) {
816 		return;
817 	}
818 
819 	if (Z_TYPE_P(length) != IS_LONG) {
820 		return;
821 	}
822 
823 	/** Generate seed */
824 	if (!BG(mt_rand_is_seeded)) {
825 		php_mt_srand(GENERATE_SEED() TSRMLS_CC);
826 	}
827 
828 	for (i = 0; i < Z_LVAL_P(length); i++) {
829 
830 		switch (Z_LVAL_P(type)) {
831 
832 			case PH_RANDOM_ALNUM:
833 				rand_type = (long) (php_mt_rand(TSRMLS_C) >> 1);
834 				RAND_RANGE(rand_type, 0, 3, PHP_MT_RAND_MAX);
835 				break;
836 
837 			case PH_RANDOM_ALPHA:
838 				rand_type = (long) (php_mt_rand(TSRMLS_C) >> 1);
839 				RAND_RANGE(rand_type, 1, 2, PHP_MT_RAND_MAX);
840 				break;
841 
842 			case PH_RANDOM_HEXDEC:
843 				rand_type = (long) (php_mt_rand(TSRMLS_C) >> 1);
844 				RAND_RANGE(rand_type, 0, 1, PHP_MT_RAND_MAX);
845 				break;
846 
847 			case PH_RANDOM_NUMERIC:
848 				rand_type = 0;
849 				break;
850 
851 			case PH_RANDOM_NOZERO:
852 				rand_type = 5;
853 				break;
854 
855 			default:
856 				continue;
857 		}
858 
859 		switch (rand_type) {
860 
861 			case 0:
862 				ch = (long) (php_mt_rand(TSRMLS_C) >> 1);
863 				RAND_RANGE(ch, '0', '9', PHP_MT_RAND_MAX);
864 				break;
865 
866 			case 1:
867 				ch = (long) (php_mt_rand(TSRMLS_C) >> 1);
868 				RAND_RANGE(ch, 'a', 'f', PHP_MT_RAND_MAX);
869 				break;
870 
871 			case 2:
872 				ch = (long) (php_mt_rand(TSRMLS_C) >> 1);
873 				RAND_RANGE(ch, 'a', 'z', PHP_MT_RAND_MAX);
874 				break;
875 
876 			case 3:
877 				ch = (long) (php_mt_rand(TSRMLS_C) >> 1);
878 				RAND_RANGE(ch, 'A', 'Z', PHP_MT_RAND_MAX);
879 				break;
880 
881 			case 5:
882 				ch = (long) (php_mt_rand(TSRMLS_C) >> 1);
883 				RAND_RANGE(ch, '1', '9', PHP_MT_RAND_MAX);
884 				break;
885 
886 			default:
887 				continue;
888 		}
889 
890 		smart_str_appendc(&random_str, (unsigned int) ch);
891 	}
892 
893 	smart_str_0(&random_str);
894 
895 	if (random_str.len) {
896 		RETURN_STRINGL(random_str.c, random_str.len, 0);
897 	} else {
898 		smart_str_free(&random_str);
899 		RETURN_EMPTY_STRING();
900 	}
901 }
902 
903 /**
904  * Removes slashes at the end of a string
905  */
zephir_remove_extra_slashes(zval * return_value,const zval * str)906 void zephir_remove_extra_slashes(zval *return_value, const zval *str) {
907 
908 	char *cursor, *removed_str;
909 	unsigned int i;
910 
911 	if (Z_TYPE_P(str) != IS_STRING) {
912 		RETURN_EMPTY_STRING();
913 	}
914 
915 	if (Z_STRLEN_P(str) > 1) {
916 		cursor = Z_STRVAL_P(str);
917 		cursor += (Z_STRLEN_P(str) - 1);
918 		for (i = Z_STRLEN_P(str); i > 0; i--) {
919 			if ((*cursor) == '/') {
920 				cursor--;
921 				continue;
922 			}
923 			break;
924 		}
925 	} else {
926 		i = Z_STRLEN_P(str);
927 	}
928 
929 	removed_str = emalloc(i + 1);
930 	memcpy(removed_str, Z_STRVAL_P(str), i);
931 	removed_str[i] = '\0';
932 
933 	RETURN_STRINGL(removed_str, i, 0);
934 }
935 
936 /**
937  * This function is not external in the Zend API so we redeclare it here in the extension
938  */
zephir_spprintf(char ** message,int max_len,char * format,...)939 int zephir_spprintf(char **message, int max_len, char *format, ...)
940 {
941 	va_list arg;
942 	int len;
943 
944 	va_start(arg, format);
945 	len = vspprintf(message, max_len, format, arg);
946 	va_end(arg);
947 	return len;
948 }
949 
950 /**
951  * Makes a substr like the PHP function. This function SUPPORT negative from and length
952  */
zephir_substr(zval * return_value,zval * str,long f,long l,int flags)953 void zephir_substr(zval *return_value, zval *str, long f, long l, int flags) {
954 
955 	zval copy;
956 	int use_copy = 0;
957 	int str_len;
958 
959 	if (Z_TYPE_P(str) != IS_STRING) {
960 
961 		if (Z_TYPE_P(str) == IS_NULL || Z_TYPE_P(str) == IS_BOOL) {
962 			RETURN_FALSE;
963 		}
964 
965 		if (Z_TYPE_P(str) != IS_STRING) {
966 			zend_make_printable_zval(str, &copy, &use_copy);
967 			if (use_copy) {
968 				str = &copy;
969 			}
970 		}
971 	}
972 
973 	str_len = Z_STRLEN_P(str);
974 	if ((flags & ZEPHIR_SUBSTR_NO_LENGTH) == ZEPHIR_SUBSTR_NO_LENGTH) {
975 		l = str_len;
976 	}
977 
978 	if ((l < 0 && -l > str_len)) {
979 		if (use_copy) {
980 			zval_dtor(str);
981 		}
982 		RETURN_FALSE;
983 	} else {
984 		if (l > str_len) {
985 			l = str_len;
986 		}
987 	}
988 
989 	if (f > str_len) {
990 		if (use_copy) {
991 			zval_dtor(str);
992 		}
993 		RETURN_FALSE;
994 	} else {
995 		if (f < 0 && -f > str_len) {
996 			f = 0;
997 		}
998 	}
999 
1000 	if (l < 0 && (l + str_len - f) < 0) {
1001 		if (use_copy) {
1002 			zval_dtor(str);
1003 		}
1004 		RETURN_FALSE;
1005 	}
1006 
1007 	/* if "from" position is negative, count start position from the end
1008 	 * of the string
1009 	 */
1010 	if (f < 0) {
1011 		f = str_len + f;
1012 		if (f < 0) {
1013 			f = 0;
1014 		}
1015 	}
1016 
1017 	/* if "length" position is negative, set it to the length
1018 	 * needed to stop that many chars from the end of the string
1019 	 */
1020 	if (l < 0) {
1021 		l = (str_len - f) + l;
1022 		if (l < 0) {
1023 			l = 0;
1024 		}
1025 	}
1026 
1027 	if (f >= str_len) {
1028 		if (use_copy) {
1029 			zval_dtor(str);
1030 		}
1031 		RETURN_FALSE;
1032 	}
1033 
1034 	if ((f + l) > str_len) {
1035 		l = str_len - f;
1036 	}
1037 
1038 	if (!l) {
1039 		if (use_copy) {
1040 			zval_dtor(str);
1041 		}
1042 		RETURN_EMPTY_STRING();
1043 	}
1044 
1045 	ZVAL_STRINGL(return_value, Z_STRVAL_P(str) + f, l, 1);
1046 
1047 	if (use_copy) {
1048 		zval_dtor(str);
1049 	}
1050 
1051 	return;
1052 }
1053 
zephir_append_printable_array(smart_str * implstr,zval * value TSRMLS_DC)1054 void zephir_append_printable_array(smart_str *implstr, zval *value TSRMLS_DC) {
1055 
1056 	zval         **tmp;
1057 	HashTable      *arr;
1058 	HashPosition   pos;
1059 	unsigned int numelems, i = 0, str_len;
1060 
1061 	arr = Z_ARRVAL_P(value);
1062 	numelems = zend_hash_num_elements(arr);
1063 
1064 	smart_str_appendc(implstr, '[');
1065 
1066 	if (numelems > 0) {
1067 		zend_hash_internal_pointer_reset_ex(arr, &pos);
1068 		while (zend_hash_get_current_data_ex(arr, (void **) &tmp, &pos) == SUCCESS) {
1069 
1070 			/**
1071 			 * We don't serialize objects
1072 			 */
1073 			if (Z_TYPE_PP(tmp) == IS_OBJECT) {
1074 				smart_str_appendc(implstr, 'O');
1075 				{
1076 					char stmp[MAX_LENGTH_OF_LONG + 1];
1077 					str_len = slprintf(stmp, sizeof(stmp), "%ld", Z_OBJVAL_PP(tmp).handle);
1078 					smart_str_appendl(implstr, stmp, str_len);
1079 				}
1080 			} else {
1081 				if (Z_TYPE_PP(tmp) == IS_ARRAY) {
1082 					zephir_append_printable_array(implstr, *tmp TSRMLS_CC);
1083 				} else {
1084 					zephir_append_printable_zval(implstr, tmp TSRMLS_CC);
1085 				}
1086 			}
1087 
1088 			if (++i != numelems) {
1089 				smart_str_appendc(implstr, ',');
1090 			}
1091 
1092 			zend_hash_move_forward_ex(arr, &pos);
1093 		}
1094 	}
1095 
1096 	smart_str_appendc(implstr, ']');
1097 }
1098 
1099 /**
1100  * Creates a unique key to be used as index in a hash
1101  */
zephir_unique_key(zval * return_value,zval * prefix,zval * value TSRMLS_DC)1102 void zephir_unique_key(zval *return_value, zval *prefix, zval *value TSRMLS_DC)
1103 {
1104 
1105 	smart_str implstr = {0};
1106 
1107 	if (Z_TYPE_P(prefix) == IS_STRING) {
1108 		smart_str_appendl(&implstr, Z_STRVAL_P(prefix), Z_STRLEN_P(prefix));
1109 	}
1110 
1111 	if (Z_TYPE_P(value) == IS_ARRAY) {
1112 		zephir_append_printable_array(&implstr, value TSRMLS_CC);
1113 	} else {
1114 		zephir_append_printable_zval(&implstr, &value TSRMLS_CC);
1115 	}
1116 
1117 	smart_str_0(&implstr);
1118 
1119 	if (implstr.len) {
1120 		RETURN_STRINGL(implstr.c, implstr.len, 0);
1121 	} else {
1122 		smart_str_free(&implstr);
1123 		RETURN_NULL();
1124 	}
1125 }
1126 
1127 /**
1128  * Returns the PHP_EOL (if the passed parameter is TRUE)
1129  */
zephir_eol(int eol TSRMLS_DC)1130 zval *zephir_eol(int eol TSRMLS_DC) {
1131 
1132 	zval *local_eol;
1133 
1134 	/**
1135 	 * Initialize local var
1136 	 */
1137 	ZEPHIR_INIT_VAR(local_eol);
1138 
1139 	/**
1140 	 * Check if the eol is true and return PHP_EOL or empty string
1141 	 */
1142 	if (eol) {
1143 		ZVAL_STRING(local_eol, PHP_EOL, 1);
1144 	} else {
1145 		ZVAL_EMPTY_STRING(local_eol);
1146 	}
1147 
1148 	return local_eol;
1149 }
1150 
1151 /**
1152  * Base 64 encode
1153  */
zephir_base64_encode(zval * return_value,zval * data)1154 void zephir_base64_encode(zval *return_value, zval *data) {
1155 
1156 	zval copy;
1157 	char *encoded;
1158 	int use_copy = 0, length;
1159 
1160 	if (Z_TYPE_P(data) != IS_STRING) {
1161 		zend_make_printable_zval(data, &copy, &use_copy);
1162 		if (use_copy) {
1163 			data = &copy;
1164 		}
1165 	}
1166 
1167 	encoded = (char *) php_base64_encode((unsigned char *)(Z_STRVAL_P(data)), Z_STRLEN_P(data), &length);
1168 
1169 	if (use_copy) {
1170 		zval_dtor(data);
1171 	}
1172 
1173 	if (encoded) {
1174 		RETURN_STRINGL(encoded, length, 0);
1175 	} else {
1176 		RETURN_NULL();
1177 	}
1178 }
1179 
1180 /**
1181  * Base 64 decode
1182  */
zephir_base64_decode(zval * return_value,zval * data)1183 void zephir_base64_decode(zval *return_value, zval *data) {
1184 
1185 	zval copy;
1186 	char *decoded;
1187 	int use_copy = 0, length;
1188 
1189 	if (Z_TYPE_P(data) != IS_STRING) {
1190 		zend_make_printable_zval(data, &copy, &use_copy);
1191 		if (use_copy) {
1192 			data = &copy;
1193 		}
1194 	}
1195 
1196 	decoded = (char *) php_base64_decode((unsigned char *)(Z_STRVAL_P(data)), Z_STRLEN_P(data), &length);
1197 
1198 	if (use_copy) {
1199 		zval_dtor(data);
1200 	}
1201 
1202 	if (decoded) {
1203 		RETURN_STRINGL(decoded, length, 0);
1204 	} else {
1205 		RETURN_NULL();
1206 	}
1207 }
1208 
zephir_md5(zval * return_value,zval * str)1209 void zephir_md5(zval *return_value, zval *str) {
1210 
1211 	PHP_MD5_CTX ctx;
1212 	unsigned char digest[16];
1213 	char hexdigest[33];
1214 	zval copy;
1215 	int use_copy = 0;
1216 
1217 	if (Z_TYPE_P(str) != IS_STRING) {
1218 		zend_make_printable_zval(str, &copy, &use_copy);
1219 		if (use_copy) {
1220 			str = &copy;
1221 		}
1222 	}
1223 
1224 	PHP_MD5Init(&ctx);
1225 	PHP_MD5Update(&ctx, Z_STRVAL_P(str), Z_STRLEN_P(str));
1226 	PHP_MD5Final(digest, &ctx);
1227 
1228 	make_digest(hexdigest, digest);
1229 
1230 	ZVAL_STRINGL(return_value, hexdigest, 32, 1);
1231 }
1232 
zephir_crc32(zval * return_value,zval * str TSRMLS_DC)1233 void zephir_crc32(zval *return_value, zval *str TSRMLS_DC) {
1234 
1235 	zval copy;
1236 	int use_copy = 0;
1237 	size_t nr;
1238 	char *p;
1239 	php_uint32 crc;
1240 	php_uint32 crcinit = 0;
1241 
1242 	if (Z_TYPE_P(str) != IS_STRING) {
1243 		zend_make_printable_zval(str, &copy, &use_copy);
1244 		if (use_copy) {
1245 			str = &copy;
1246 		}
1247 	}
1248 
1249 	p = Z_STRVAL_P(str);
1250 	nr = Z_STRLEN_P(str);
1251 
1252 	crc = crcinit^0xFFFFFFFF;
1253 	for (; nr--; ++p) {
1254 		crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*p)) & 0xFF];
1255 	}
1256 
1257 	if (use_copy) {
1258 		zval_dtor(str);
1259 	}
1260 
1261 	RETVAL_LONG(crc ^ 0xFFFFFFFF);
1262 }
1263 
1264 #ifdef ZEPHIR_USE_PHP_PCRE
1265 
1266 /**
1267  * Execute preg-match without function lookup in the PHP userland
1268  */
zephir_preg_match(zval * return_value,zval * regex,zval * subject,zval * matches,int global,long flags,long offset TSRMLS_DC)1269 void zephir_preg_match(zval *return_value, zval *regex, zval *subject, zval *matches, int global, long flags, long offset TSRMLS_DC) {
1270 
1271 	zval copy;
1272 	int use_copy = 0;
1273 	pcre_cache_entry *pce;
1274 
1275 	if (Z_TYPE_P(regex) != IS_STRING) {
1276 		zend_error(E_WARNING, "Invalid arguments supplied for zephir_preg_match()");
1277 		RETURN_FALSE;
1278 	}
1279 
1280 	if (Z_TYPE_P(subject) != IS_STRING) {
1281 		zend_make_printable_zval(subject, &copy, &use_copy);
1282 		if (use_copy) {
1283 			subject = &copy;
1284 		}
1285 	}
1286 
1287 	/* Compile regex or get it from cache. */
1288 	if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(regex), Z_STRLEN_P(regex) TSRMLS_CC)) == NULL) {
1289 
1290 		if (use_copy) {
1291 			zval_dtor(subject);
1292 		}
1293 
1294 		RETURN_FALSE;
1295 	}
1296 
1297 	if (flags != 0 || offset != 0) {
1298 		php_pcre_match_impl(pce, Z_STRVAL_P(subject), Z_STRLEN_P(subject), return_value, matches, global, 1, flags, offset TSRMLS_CC);
1299 	} else {
1300 		php_pcre_match_impl(pce, Z_STRVAL_P(subject), Z_STRLEN_P(subject), return_value, matches, global, 0, 0, 0 TSRMLS_CC);
1301 	}
1302 
1303 	if (use_copy) {
1304 		zval_dtor(&copy);
1305 	}
1306 }
1307 
1308 #else
1309 
zephir_preg_match(zval * return_value,zval * regex,zval * subject,zval * matches,int global,long flags,long offset TSRMLS_DC)1310 void zephir_preg_match(zval *return_value, zval *regex, zval *subject, zval *matches, int global, long flags, long offset TSRMLS_DC)
1311 {
1312 	zval tmp_flags;
1313 	zval tmp_offset;
1314 	zval *rv = NULL;
1315 	zval **rvp = &rv;
1316 
1317 	if (matches) {
1318 		Z_SET_ISREF_P(matches);
1319 	}
1320 	ZEPHIR_SINIT_VAR(tmp_flags);
1321 	ZEPHIR_SINIT_VAR(tmp_offset);
1322 	ZVAL_LONG(&tmp_flags, flags);
1323 	ZVAL_LONG(&tmp_offset, offset);
1324 
1325 	{
1326 		zval *tmp_params[5] = { regex, subject, matches, &tmp_flags, &tmp_offset };
1327 
1328 		if (global) {
1329 			zephir_call_func_aparams(rvp, SL("preg_match_all"), NULL, 0, 5, tmp_params TSRMLS_CC);
1330 		} else {
1331 			zephir_call_func_aparams(rvp, SL("preg_match"), NULL, 0, 5, tmp_params TSRMLS_CC);
1332 		}
1333 	}
1334 	if (matches) {
1335 		Z_UNSET_ISREF_P(matches);
1336 	}
1337 
1338 	if (return_value) {
1339 		COPY_PZVAL_TO_ZVAL(*return_value, rv);
1340 	}
1341 }
1342 
1343 #endif /* ZEPHIR_USE_PHP_PCRE */
1344 
1345 #ifdef ZEPHIR_USE_PHP_JSON
1346 
zephir_json_encode(zval * return_value,zval ** return_value_ptr,zval * v,int opts TSRMLS_DC)1347 int zephir_json_encode(zval *return_value, zval **return_value_ptr, zval *v, int opts TSRMLS_DC) {
1348 
1349 	smart_str buf = { NULL, 0, 0 };
1350 
1351 	php_json_encode(&buf, v, opts TSRMLS_CC);
1352 	smart_str_0(&buf);
1353 	ZVAL_STRINGL(return_value, buf.c, buf.len, 0);
1354 
1355 	return SUCCESS;
1356 }
1357 
zephir_json_decode(zval * return_value,zval ** return_value_ptr,zval * v,zend_bool assoc TSRMLS_DC)1358 int zephir_json_decode(zval *return_value, zval **return_value_ptr, zval *v, zend_bool assoc TSRMLS_DC) {
1359 
1360 	zval copy;
1361 	int use_copy = 0;
1362 
1363 	if (UNEXPECTED(Z_TYPE_P(v) != IS_STRING)) {
1364 		zend_make_printable_zval(v, &copy, &use_copy);
1365 		if (use_copy) {
1366 			v = &copy;
1367 		}
1368 	}
1369 
1370 	php_json_decode(return_value, Z_STRVAL_P(v), Z_STRLEN_P(v), assoc, 512 /* JSON_PARSER_DEFAULT_DEPTH */ TSRMLS_CC);
1371 
1372 	if (UNEXPECTED(use_copy)) {
1373 		zval_dtor(&copy);
1374 	}
1375 
1376 	return SUCCESS;
1377 }
1378 
1379 #else
1380 
zephir_json_encode(zval * return_value,zval ** return_value_ptr,zval * v,int opts TSRMLS_DC)1381 int zephir_json_encode(zval *return_value, zval **return_value_ptr, zval *v, int opts TSRMLS_DC) {
1382 
1383 	zval zopts;
1384 	zval *params[2];
1385 
1386 	ZEPHIR_SINIT_VAR(zopts);
1387 	ZVAL_LONG(&zopts, opts);
1388 
1389 	params[0] = v;
1390 	params[1] = &zopts;
1391 
1392 	return zephir_return_call_function(return_value, NULL, ZEND_STRL("json_encode"), NULL, 0, 2, params TSRMLS_CC);
1393 }
1394 
zephir_json_decode(zval * return_value,zval ** return_value_ptr,zval * v,zend_bool assoc TSRMLS_DC)1395 int zephir_json_decode(zval *return_value, zval **return_value_ptr, zval *v, zend_bool assoc TSRMLS_DC) {
1396 
1397 	zval zassoc;
1398 	zval *params[2];
1399 
1400 	ZEPHIR_SINIT_VAR(zassoc);
1401 	ZVAL_BOOL(&zassoc, assoc);
1402 
1403 	params[0] = v;
1404 	params[1] = &zassoc;
1405 
1406 	return zephir_return_call_function(return_value, NULL, ZEND_STRL("json_decode"), NULL, 0, 2, params TSRMLS_CC);
1407 }
1408 
1409 #endif /* ZEPHIR_USE_PHP_JSON */
1410 
zephir_lcfirst(zval * return_value,zval * s)1411 void zephir_lcfirst(zval *return_value, zval *s) {
1412 
1413 	zval copy;
1414 	char *c;
1415 	int use_copy = 0;
1416 
1417 	if (UNEXPECTED(Z_TYPE_P(s) != IS_STRING)) {
1418 		zend_make_printable_zval(s, &copy, &use_copy);
1419 		if (use_copy) {
1420 			s = &copy;
1421 		}
1422 	}
1423 
1424 	if (!Z_STRLEN_P(s)) {
1425 		ZVAL_EMPTY_STRING(return_value);
1426 	}
1427 	else {
1428 		ZVAL_STRINGL(return_value, Z_STRVAL_P(s), Z_STRLEN_P(s), 1);
1429 		c = Z_STRVAL_P(return_value);
1430 		*c = tolower((unsigned char)*c);
1431 	}
1432 
1433 	if (UNEXPECTED(use_copy)) {
1434 		zval_dtor(&copy);
1435 	}
1436 }
1437 
zephir_ucfirst(zval * return_value,zval * s)1438 void zephir_ucfirst(zval *return_value, zval *s) {
1439 
1440 	zval copy;
1441 	char *c;
1442 	int use_copy = 0;
1443 
1444 	if (UNEXPECTED(Z_TYPE_P(s) != IS_STRING)) {
1445 		zend_make_printable_zval(s, &copy, &use_copy);
1446 		if (use_copy) {
1447 			s = &copy;
1448 		}
1449 	}
1450 
1451 	if (!Z_STRLEN_P(s)) {
1452 		ZVAL_EMPTY_STRING(return_value);
1453 	}
1454 	else {
1455 		ZVAL_STRINGL(return_value, Z_STRVAL_P(s), Z_STRLEN_P(s), 1);
1456 		c = Z_STRVAL_P(return_value);
1457 		*c = toupper((unsigned char)*c);
1458 	}
1459 
1460 	if (UNEXPECTED(use_copy)) {
1461 		zval_dtor(&copy);
1462 	}
1463 }
1464 
zephir_http_build_query(zval * return_value,zval * params,char * sep TSRMLS_DC)1465 int zephir_http_build_query(zval *return_value, zval *params, char *sep TSRMLS_DC) {
1466 
1467 	if (Z_TYPE_P(params) == IS_ARRAY || Z_TYPE_P(params) == IS_OBJECT) {
1468 		smart_str formstr = { NULL, 0, 0 };
1469 		int res;
1470 
1471 		res = php_url_encode_hash_ex(HASH_OF(params), &formstr, NULL, 0, NULL, 0, NULL, 0, (Z_TYPE_P(params) == IS_OBJECT ? params : NULL), sep, PHP_QUERY_RFC1738 TSRMLS_CC);
1472 
1473 		if (res == SUCCESS) {
1474 			if (!formstr.c) {
1475 				ZVAL_EMPTY_STRING(return_value);
1476 			}
1477 			else {
1478 				smart_str_0(&formstr);
1479 				ZVAL_STRINGL(return_value, formstr.c, formstr.len, 0);
1480 			}
1481 
1482 			return SUCCESS;
1483 		}
1484 
1485 		smart_str_free(&formstr);
1486 		ZVAL_FALSE(return_value);
1487 	}
1488 	else {
1489 		ZVAL_NULL(return_value);
1490 	}
1491 
1492 	return FAILURE;
1493 }
1494 
zephir_htmlspecialchars(zval * return_value,zval * string,zval * quoting,zval * charset TSRMLS_DC)1495 void zephir_htmlspecialchars(zval *return_value, zval *string, zval *quoting, zval *charset TSRMLS_DC) {
1496 	zval copy;
1497 	char *escaped, *cs;
1498 	int qs, use_copy = 0;
1499 	size_t escaped_len;
1500 
1501 	if (UNEXPECTED(Z_TYPE_P(string) != IS_STRING)) {
1502 		zend_make_printable_zval(string, &copy, &use_copy);
1503 		if (use_copy) {
1504 			string = &copy;
1505 		}
1506 	}
1507 
1508 	cs = (charset && Z_TYPE_P(charset) == IS_STRING) ? Z_STRVAL_P(charset) : NULL;
1509 	qs = (quoting && Z_TYPE_P(quoting) == IS_LONG)   ? Z_LVAL_P(quoting)   : ENT_COMPAT;
1510 
1511 	escaped = php_escape_html_entities_ex((unsigned char *)(Z_STRVAL_P(string)), Z_STRLEN_P(string), &escaped_len, 0, qs, cs, 1 TSRMLS_CC);
1512 	ZVAL_STRINGL(return_value, escaped, escaped_len, 0);
1513 
1514 	if (UNEXPECTED(use_copy)) {
1515 		zval_dtor(&copy);
1516 	}
1517 }
1518 
zephir_htmlentities(zval * return_value,zval * string,zval * quoting,zval * charset TSRMLS_DC)1519 void zephir_htmlentities(zval *return_value, zval *string, zval *quoting, zval *charset TSRMLS_DC)
1520 {
1521 	zval copy;
1522 	char *escaped, *cs;
1523 	int qs, use_copy = 0;
1524 	size_t escaped_len;
1525 
1526 	if (UNEXPECTED(Z_TYPE_P(string) != IS_STRING)) {
1527 		zend_make_printable_zval(string, &copy, &use_copy);
1528 		if (use_copy) {
1529 			string = &copy;
1530 		}
1531 	}
1532 
1533 	cs = (charset && Z_TYPE_P(charset) == IS_STRING) ? Z_STRVAL_P(charset) : NULL;
1534 	qs = (quoting && Z_TYPE_P(quoting) == IS_LONG)   ? Z_LVAL_P(quoting)   : ENT_COMPAT;
1535 
1536 	escaped = php_escape_html_entities_ex((unsigned char *)(Z_STRVAL_P(string)), Z_STRLEN_P(string), &escaped_len, 1, qs, cs, 1 TSRMLS_CC);
1537 	ZVAL_STRINGL(return_value, escaped, escaped_len, 0);
1538 
1539 	if (UNEXPECTED(use_copy)) {
1540 		zval_dtor(&copy);
1541 	}
1542 }
1543 
zephir_strval(zval * return_value,zval * v)1544 void zephir_strval(zval *return_value, zval *v)
1545 {
1546 	zval copy;
1547 	int use_copy = 0;
1548 
1549 	zend_make_printable_zval(v, &copy, &use_copy);
1550 	if (use_copy) {
1551 		zval *tmp = &copy;
1552 		ZVAL_ZVAL(return_value, tmp, 0, 0);
1553 	} else {
1554 		ZVAL_ZVAL(return_value, v, 1, 0);
1555 	}
1556 }
1557 
zephir_date(zval * return_value,zval * format,zval * timestamp TSRMLS_DC)1558 void zephir_date(zval *return_value, zval *format, zval *timestamp TSRMLS_DC)
1559 {
1560 	long int ts;
1561 	zval copy;
1562 	int use_copy = 0;
1563 	char *formatted;
1564 
1565 	if (UNEXPECTED(Z_TYPE_P(format) != IS_STRING)) {
1566 		zend_make_printable_zval(format, &copy, &use_copy);
1567 		if (use_copy) {
1568 			format = &copy;
1569 		}
1570 	}
1571 
1572 	ts = (timestamp) ? zephir_get_intval(timestamp) : time(NULL);
1573 
1574 	formatted = php_format_date(Z_STRVAL_P(format), Z_STRLEN_P(format), ts, 1 TSRMLS_CC);
1575 	ZVAL_STRING(return_value, formatted, 0);
1576 
1577 	if (UNEXPECTED(use_copy)) {
1578 		zval_dtor(&copy);
1579 	}
1580 }
1581 
zephir_addslashes(zval * return_value,zval * str TSRMLS_DC)1582 void zephir_addslashes(zval *return_value, zval *str TSRMLS_DC)
1583 {
1584 	zval copy;
1585 	int use_copy = 0;
1586 
1587 	if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) {
1588 		zend_make_printable_zval(str, &copy, &use_copy);
1589 		if (use_copy) {
1590 			str = &copy;
1591 		}
1592 	}
1593 
1594 	ZVAL_STRING(return_value, php_addslashes(Z_STRVAL_P(str), Z_STRLEN_P(str), &Z_STRLEN_P(return_value), 0 TSRMLS_CC), 0);
1595 
1596 	if (UNEXPECTED(use_copy)) {
1597 		zval_dtor(&copy);
1598 	}
1599 }
1600 
zephir_stripslashes(zval * return_value,zval * str TSRMLS_DC)1601 void zephir_stripslashes(zval *return_value, zval *str TSRMLS_DC)
1602 {
1603 	zval copy;
1604 	int use_copy = 0;
1605 
1606 	if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) {
1607 		zend_make_printable_zval(str, &copy, &use_copy);
1608 		if (use_copy) {
1609 			str = &copy;
1610 		}
1611 	}
1612 
1613 	ZVAL_STRINGL(return_value, Z_STRVAL_P(str), Z_STRLEN_P(str), 1);
1614 	php_stripslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC);
1615 
1616 	if (UNEXPECTED(use_copy)) {
1617 		zval_dtor(&copy);
1618 	}
1619 }
1620 
zephir_stripcslashes(zval * return_value,zval * str TSRMLS_DC)1621 void zephir_stripcslashes(zval *return_value, zval *str TSRMLS_DC)
1622 {
1623 
1624 	zval copy;
1625 	int use_copy = 0;
1626 
1627 	if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) {
1628 		zend_make_printable_zval(str, &copy, &use_copy);
1629 		if (use_copy) {
1630 			str = &copy;
1631 		}
1632 	}
1633 
1634 	ZVAL_STRINGL(return_value, Z_STRVAL_P(str), Z_STRLEN_P(str), 1);
1635 	php_stripcslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value));
1636 
1637 	if (UNEXPECTED(use_copy)) {
1638 		zval_dtor(&copy);
1639 	}
1640 }
1641 
1642 /**
1643  * Compares two strings using the same time whether they're equal or not.
1644  * A difference in length will leak
1645  */
zephir_hash_equals(const zval * known_zval,const zval * user_zval)1646 int zephir_hash_equals(const zval *known_zval, const zval *user_zval)
1647 {
1648 	char *known_str, *user_str;
1649 	int result = 0;
1650 	size_t j;
1651 
1652 	if (Z_TYPE_P(known_zval) != IS_STRING || Z_TYPE_P(user_zval) != IS_STRING) {
1653 		return 0;
1654 	}
1655 
1656 	if (Z_STRLEN_P(known_zval) != Z_STRLEN_P(user_zval)) {
1657 		return 0;
1658 	}
1659 
1660 	known_str = Z_STRVAL_P(known_zval);
1661 	user_str = Z_STRVAL_P(user_zval);
1662 
1663 	for (j = 0; j < Z_STRLEN_P(known_zval); j++) {
1664 		result |= known_str[j] ^ user_str[j];
1665 	}
1666 
1667 	return (int) (result == 0);
1668 }
1669 
zephir_string_to_hex(zval * return_value,zval * var)1670 void zephir_string_to_hex(zval *return_value, zval *var)
1671 {
1672 	int use_copy = 0;
1673 	zval copy;
1674 	size_t i;
1675 	char *s;
1676 	char *res;
1677 
1678 	if (Z_TYPE_P(var) != IS_STRING) {
1679 		zend_make_printable_zval(var, &copy, &use_copy);
1680 		if (use_copy) {
1681 			var = &copy;
1682 		}
1683 	}
1684 
1685 	res = emalloc(2*Z_STRLEN_P(var) + 1);
1686 	s   = Z_STRVAL_P(var);
1687 	for (i=0; i<Z_STRLEN_P(var); ++i) {
1688 		sprintf(res + 2*i, "%hhX", s[i]);
1689 	}
1690 
1691 	res[2*Z_STRLEN_P(var)] = 0;
1692 	ZVAL_STRINGL(return_value, res, 2*Z_STRLEN_P(var), 0);
1693 
1694 	if (use_copy) {
1695 		zval_dtor(var);
1696 	}
1697 }
1698