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, ©, &use_copy);
72 if (use_copy) {
73 str = ©
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, ©, &use_copy);
94 if (use_copy) {
95 str = ©
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, ©, &use_copy);
119 if (use_copy) {
120 str = ©
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, ©);
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, ©_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, ©_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, ©, &use_copy);
608 if (use_copy) {
609 str = ©
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(©);
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, ©, &use_copy);
636 if (use_copy) {
637 str = ©
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(©);
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, ©, &use_copy);
663 if (use_copy) {
664 str = ©
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, ©, &use_copy);
967 if (use_copy) {
968 str = ©
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, ©, &use_copy);
1162 if (use_copy) {
1163 data = ©
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, ©, &use_copy);
1191 if (use_copy) {
1192 data = ©
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, ©, &use_copy);
1219 if (use_copy) {
1220 str = ©
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, ©, &use_copy);
1244 if (use_copy) {
1245 str = ©
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, ©, &use_copy);
1282 if (use_copy) {
1283 subject = ©
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(©);
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, ©, &use_copy);
1365 if (use_copy) {
1366 v = ©
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(©);
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, ©, &use_copy);
1419 if (use_copy) {
1420 s = ©
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(©);
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, ©, &use_copy);
1446 if (use_copy) {
1447 s = ©
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(©);
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, ©, &use_copy);
1503 if (use_copy) {
1504 string = ©
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(©);
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, ©, &use_copy);
1528 if (use_copy) {
1529 string = ©
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(©);
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, ©, &use_copy);
1550 if (use_copy) {
1551 zval *tmp = ©
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, ©, &use_copy);
1567 if (use_copy) {
1568 format = ©
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(©);
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, ©, &use_copy);
1589 if (use_copy) {
1590 str = ©
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(©);
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, ©, &use_copy);
1608 if (use_copy) {
1609 str = ©
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(©);
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, ©, &use_copy);
1629 if (use_copy) {
1630 str = ©
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(©);
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, ©, &use_copy);
1680 if (use_copy) {
1681 var = ©
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