This source file includes following definitions.
- register_string_constants
- php_bin2hex
- php_hex2bin
- localeconv_r
- PHP_MINIT_FUNCTION
- PHP_MSHUTDOWN_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_spn_common_handler
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_MINIT_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_charmask
- php_trim
- php_do_trim
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_explode
- php_explode_negative_limit
- PHP_FUNCTION
- php_implode
- PHP_FUNCTION
- PHP_FUNCTION
- php_strtoupper
- php_string_toupper
- PHP_FUNCTION
- php_strtolower
- php_string_tolower
- PHP_FUNCTION
- php_basename
- PHP_FUNCTION
- php_dirname
- PHP_FUNCTION
- PHP_FUNCTION
- php_stristr
- php_strspn
- php_strcspn
- php_needle_char
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_chunk_split
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_ucfirst
- PHP_FUNCTION
- php_lcfirst
- PHP_FUNCTION
- PHP_FUNCTION
- php_strtr
- php_strtr_ex
- php_strtr_array
- php_char_to_str_ex
- php_str_to_str_ex
- php_str_to_str_i_ex
- php_str_to_str
- PHP_FUNCTION
- PHP_FUNCTION
- php_similar_str
- php_similar_char
- PHP_FUNCTION
- php_stripslashes
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_strerror
- php_stripcslashes
- php_addcslashes
- php_addslashes
- php_str_replace_in_subject
- php_str_replace_common
- PHP_FUNCTION
- PHP_FUNCTION
- php_hebrev
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_tag_find
- php_strip_tags
- php_strip_tags_ex
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_strnatcmp
- string_natural_compare_function_ex
- string_natural_case_compare_function
- string_natural_compare_function
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_string_shuffle
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <stdio.h>
26 #include "php.h"
27 #include "php_rand.h"
28 #include "php_string.h"
29 #include "php_variables.h"
30 #ifdef HAVE_LOCALE_H
31 # include <locale.h>
32 #endif
33 #ifdef HAVE_LANGINFO_H
34 # include <langinfo.h>
35 #endif
36 #ifdef HAVE_MONETARY_H
37 # include <monetary.h>
38 #endif
39
40
41
42
43
44
45
46 #define php_my_setlocale setlocale
47 #ifdef HAVE_LIBINTL
48 # include <libintl.h>
49 #ifdef setlocale
50 # undef setlocale
51 #endif
52 #endif
53
54 #include "scanf.h"
55 #include "zend_API.h"
56 #include "zend_execute.h"
57 #include "php_globals.h"
58 #include "basic_functions.h"
59 #include "zend_smart_str.h"
60 #include <Zend/zend_exceptions.h>
61 #ifdef ZTS
62 #include "TSRM.h"
63 #endif
64
65
66 #include "ext/standard/file.h"
67
68 #define STR_PAD_LEFT 0
69 #define STR_PAD_RIGHT 1
70 #define STR_PAD_BOTH 2
71 #define PHP_PATHINFO_DIRNAME 1
72 #define PHP_PATHINFO_BASENAME 2
73 #define PHP_PATHINFO_EXTENSION 4
74 #define PHP_PATHINFO_FILENAME 8
75 #define PHP_PATHINFO_ALL (PHP_PATHINFO_DIRNAME | PHP_PATHINFO_BASENAME | PHP_PATHINFO_EXTENSION | PHP_PATHINFO_FILENAME)
76
77 #define STR_STRSPN 0
78 #define STR_STRCSPN 1
79
80
81
82 void register_string_constants(INIT_FUNC_ARGS)
83 {
84 REGISTER_LONG_CONSTANT("STR_PAD_LEFT", STR_PAD_LEFT, CONST_CS | CONST_PERSISTENT);
85 REGISTER_LONG_CONSTANT("STR_PAD_RIGHT", STR_PAD_RIGHT, CONST_CS | CONST_PERSISTENT);
86 REGISTER_LONG_CONSTANT("STR_PAD_BOTH", STR_PAD_BOTH, CONST_CS | CONST_PERSISTENT);
87 REGISTER_LONG_CONSTANT("PATHINFO_DIRNAME", PHP_PATHINFO_DIRNAME, CONST_CS | CONST_PERSISTENT);
88 REGISTER_LONG_CONSTANT("PATHINFO_BASENAME", PHP_PATHINFO_BASENAME, CONST_CS | CONST_PERSISTENT);
89 REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT);
90 REGISTER_LONG_CONSTANT("PATHINFO_FILENAME", PHP_PATHINFO_FILENAME, CONST_CS | CONST_PERSISTENT);
91
92 #ifdef HAVE_LOCALECONV
93
94
95
96 # ifndef HAVE_LIMITS_H
97 # define CHAR_MAX 127
98 # endif
99
100 REGISTER_LONG_CONSTANT("CHAR_MAX", CHAR_MAX, CONST_CS | CONST_PERSISTENT);
101 #endif
102
103 #ifdef HAVE_LOCALE_H
104 REGISTER_LONG_CONSTANT("LC_CTYPE", LC_CTYPE, CONST_CS | CONST_PERSISTENT);
105 REGISTER_LONG_CONSTANT("LC_NUMERIC", LC_NUMERIC, CONST_CS | CONST_PERSISTENT);
106 REGISTER_LONG_CONSTANT("LC_TIME", LC_TIME, CONST_CS | CONST_PERSISTENT);
107 REGISTER_LONG_CONSTANT("LC_COLLATE", LC_COLLATE, CONST_CS | CONST_PERSISTENT);
108 REGISTER_LONG_CONSTANT("LC_MONETARY", LC_MONETARY, CONST_CS | CONST_PERSISTENT);
109 REGISTER_LONG_CONSTANT("LC_ALL", LC_ALL, CONST_CS | CONST_PERSISTENT);
110 # ifdef LC_MESSAGES
111 REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);
112 # endif
113 #endif
114
115 }
116
117
118 int php_tag_find(char *tag, size_t len, const char *set);
119
120 #ifdef PHP_WIN32
121 # define SET_ALIGNED(alignment, decl) __declspec(align(alignment)) decl
122 #elif HAVE_ATTRIBUTE_ALIGNED
123 # define SET_ALIGNED(alignment, decl) decl __attribute__ ((__aligned__ (alignment)))
124 #else
125 # define SET_ALIGNED(alignment, decl) decl
126 #endif
127
128
129 SET_ALIGNED(16, static char hexconvtab[]) = "0123456789abcdef";
130
131
132 #ifdef ZTS
133 static MUTEX_T locale_mutex = NULL;
134 #endif
135
136
137
138 static zend_string *php_bin2hex(const unsigned char *old, const size_t oldlen)
139 {
140 zend_string *result;
141 size_t i, j;
142
143 result = zend_string_safe_alloc(oldlen, 2 * sizeof(char), 0, 0);
144
145 for (i = j = 0; i < oldlen; i++) {
146 ZSTR_VAL(result)[j++] = hexconvtab[old[i] >> 4];
147 ZSTR_VAL(result)[j++] = hexconvtab[old[i] & 15];
148 }
149 ZSTR_VAL(result)[j] = '\0';
150
151 return result;
152 }
153
154
155
156
157 static zend_string *php_hex2bin(const unsigned char *old, const size_t oldlen)
158 {
159 size_t target_length = oldlen >> 1;
160 zend_string *str = zend_string_alloc(target_length, 0);
161 unsigned char *ret = (unsigned char *)ZSTR_VAL(str);
162 size_t i, j;
163
164 for (i = j = 0; i < target_length; i++) {
165 unsigned char c = old[j++];
166 unsigned char l = c & ~0x20;
167 int is_letter = ((unsigned int) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(unsigned int) - 1);
168 unsigned char d;
169
170
171 if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(unsigned int) - 1)) | is_letter)) {
172 d = (l - 0x10 - 0x27 * is_letter) << 4;
173 } else {
174 zend_string_free(str);
175 return NULL;
176 }
177 c = old[j++];
178 l = c & ~0x20;
179 is_letter = ((unsigned int) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(unsigned int) - 1);
180 if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(unsigned int) - 1)) | is_letter)) {
181 d |= l - 0x10 - 0x27 * is_letter;
182 } else {
183 zend_string_free(str);
184 return NULL;
185 }
186 ret[i] = d;
187 }
188 ret[i] = '\0';
189
190 return str;
191 }
192
193
194 #ifdef HAVE_LOCALECONV
195
196
197 PHPAPI struct lconv *localeconv_r(struct lconv *out)
198 {
199 struct lconv *res;
200
201 # ifdef ZTS
202 tsrm_mutex_lock( locale_mutex );
203 # endif
204
205
206
207
208 #if defined(PHP_WIN32) && _MSC_VER < 1900 && defined(ZTS)
209 {
210
211
212 _locale_t cur = _get_current_locale();
213
214 res = cur->locinfo->lconv;
215 }
216 #else
217
218 res = localeconv();
219 #endif
220
221 *out = *res;
222
223 # ifdef ZTS
224 tsrm_mutex_unlock( locale_mutex );
225 # endif
226
227 return out;
228 }
229
230
231 # ifdef ZTS
232
233
234 PHP_MINIT_FUNCTION(localeconv)
235 {
236 locale_mutex = tsrm_mutex_alloc();
237 return SUCCESS;
238 }
239
240
241
242
243 PHP_MSHUTDOWN_FUNCTION(localeconv)
244 {
245 tsrm_mutex_free( locale_mutex );
246 locale_mutex = NULL;
247 return SUCCESS;
248 }
249
250 # endif
251 #endif
252
253
254
255 PHP_FUNCTION(bin2hex)
256 {
257 zend_string *result;
258 zend_string *data;
259
260 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &data) == FAILURE) {
261 return;
262 }
263
264 result = php_bin2hex((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data));
265
266 if (!result) {
267 RETURN_FALSE;
268 }
269
270 RETURN_STR(result);
271 }
272
273
274
275
276 PHP_FUNCTION(hex2bin)
277 {
278 zend_string *result, *data;
279
280 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &data) == FAILURE) {
281 return;
282 }
283
284 if (ZSTR_LEN(data) % 2 != 0) {
285 php_error_docref(NULL, E_WARNING, "Hexadecimal input string must have an even length");
286 RETURN_FALSE;
287 }
288
289 result = php_hex2bin((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data));
290
291 if (!result) {
292 php_error_docref(NULL, E_WARNING, "Input string must be hexadecimal string");
293 RETURN_FALSE;
294 }
295
296 RETVAL_STR(result);
297 }
298
299
300 static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior)
301 {
302 zend_string *s11, *s22;
303 zend_long start = 0, len = 0;
304
305 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|ll", &s11,
306 &s22, &start, &len) == FAILURE) {
307 return;
308 }
309
310 if (ZEND_NUM_ARGS() < 4) {
311 len = ZSTR_LEN(s11);
312 }
313
314
315
316 if (start < 0) {
317 start += (zend_long)ZSTR_LEN(s11);
318 if (start < 0) {
319 start = 0;
320 }
321 } else if ((size_t)start > ZSTR_LEN(s11)) {
322 RETURN_FALSE;
323 }
324
325 if (len < 0) {
326 len += (ZSTR_LEN(s11) - start);
327 if (len < 0) {
328 len = 0;
329 }
330 }
331
332 if (len > (zend_long)ZSTR_LEN(s11) - start) {
333 len = ZSTR_LEN(s11) - start;
334 }
335
336 if(len == 0) {
337 RETURN_LONG(0);
338 }
339
340 if (behavior == STR_STRSPN) {
341 RETURN_LONG(php_strspn(ZSTR_VAL(s11) + start ,
342 ZSTR_VAL(s22) ,
343 ZSTR_VAL(s11) + start + len ,
344 ZSTR_VAL(s22) + ZSTR_LEN(s22) ));
345 } else if (behavior == STR_STRCSPN) {
346 RETURN_LONG(php_strcspn(ZSTR_VAL(s11) + start ,
347 ZSTR_VAL(s22) ,
348 ZSTR_VAL(s11) + start + len ,
349 ZSTR_VAL(s22) + ZSTR_LEN(s22) ));
350 }
351
352 }
353
354
355
356
357 PHP_FUNCTION(strspn)
358 {
359 php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
360 }
361
362
363
364
365 PHP_FUNCTION(strcspn)
366 {
367 php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRCSPN);
368 }
369
370
371
372 #if HAVE_NL_LANGINFO
373 PHP_MINIT_FUNCTION(nl_langinfo)
374 {
375 #define REGISTER_NL_LANGINFO_CONSTANT(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
376 #ifdef ABDAY_1
377 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_1);
378 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_2);
379 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_3);
380 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_4);
381 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_5);
382 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_6);
383 REGISTER_NL_LANGINFO_CONSTANT(ABDAY_7);
384 #endif
385 #ifdef DAY_1
386 REGISTER_NL_LANGINFO_CONSTANT(DAY_1);
387 REGISTER_NL_LANGINFO_CONSTANT(DAY_2);
388 REGISTER_NL_LANGINFO_CONSTANT(DAY_3);
389 REGISTER_NL_LANGINFO_CONSTANT(DAY_4);
390 REGISTER_NL_LANGINFO_CONSTANT(DAY_5);
391 REGISTER_NL_LANGINFO_CONSTANT(DAY_6);
392 REGISTER_NL_LANGINFO_CONSTANT(DAY_7);
393 #endif
394 #ifdef ABMON_1
395 REGISTER_NL_LANGINFO_CONSTANT(ABMON_1);
396 REGISTER_NL_LANGINFO_CONSTANT(ABMON_2);
397 REGISTER_NL_LANGINFO_CONSTANT(ABMON_3);
398 REGISTER_NL_LANGINFO_CONSTANT(ABMON_4);
399 REGISTER_NL_LANGINFO_CONSTANT(ABMON_5);
400 REGISTER_NL_LANGINFO_CONSTANT(ABMON_6);
401 REGISTER_NL_LANGINFO_CONSTANT(ABMON_7);
402 REGISTER_NL_LANGINFO_CONSTANT(ABMON_8);
403 REGISTER_NL_LANGINFO_CONSTANT(ABMON_9);
404 REGISTER_NL_LANGINFO_CONSTANT(ABMON_10);
405 REGISTER_NL_LANGINFO_CONSTANT(ABMON_11);
406 REGISTER_NL_LANGINFO_CONSTANT(ABMON_12);
407 #endif
408 #ifdef MON_1
409 REGISTER_NL_LANGINFO_CONSTANT(MON_1);
410 REGISTER_NL_LANGINFO_CONSTANT(MON_2);
411 REGISTER_NL_LANGINFO_CONSTANT(MON_3);
412 REGISTER_NL_LANGINFO_CONSTANT(MON_4);
413 REGISTER_NL_LANGINFO_CONSTANT(MON_5);
414 REGISTER_NL_LANGINFO_CONSTANT(MON_6);
415 REGISTER_NL_LANGINFO_CONSTANT(MON_7);
416 REGISTER_NL_LANGINFO_CONSTANT(MON_8);
417 REGISTER_NL_LANGINFO_CONSTANT(MON_9);
418 REGISTER_NL_LANGINFO_CONSTANT(MON_10);
419 REGISTER_NL_LANGINFO_CONSTANT(MON_11);
420 REGISTER_NL_LANGINFO_CONSTANT(MON_12);
421 #endif
422 #ifdef AM_STR
423 REGISTER_NL_LANGINFO_CONSTANT(AM_STR);
424 #endif
425 #ifdef PM_STR
426 REGISTER_NL_LANGINFO_CONSTANT(PM_STR);
427 #endif
428 #ifdef D_T_FMT
429 REGISTER_NL_LANGINFO_CONSTANT(D_T_FMT);
430 #endif
431 #ifdef D_FMT
432 REGISTER_NL_LANGINFO_CONSTANT(D_FMT);
433 #endif
434 #ifdef T_FMT
435 REGISTER_NL_LANGINFO_CONSTANT(T_FMT);
436 #endif
437 #ifdef T_FMT_AMPM
438 REGISTER_NL_LANGINFO_CONSTANT(T_FMT_AMPM);
439 #endif
440 #ifdef ERA
441 REGISTER_NL_LANGINFO_CONSTANT(ERA);
442 #endif
443 #ifdef ERA_YEAR
444 REGISTER_NL_LANGINFO_CONSTANT(ERA_YEAR);
445 #endif
446 #ifdef ERA_D_T_FMT
447 REGISTER_NL_LANGINFO_CONSTANT(ERA_D_T_FMT);
448 #endif
449 #ifdef ERA_D_FMT
450 REGISTER_NL_LANGINFO_CONSTANT(ERA_D_FMT);
451 #endif
452 #ifdef ERA_T_FMT
453 REGISTER_NL_LANGINFO_CONSTANT(ERA_T_FMT);
454 #endif
455 #ifdef ALT_DIGITS
456 REGISTER_NL_LANGINFO_CONSTANT(ALT_DIGITS);
457 #endif
458 #ifdef INT_CURR_SYMBOL
459 REGISTER_NL_LANGINFO_CONSTANT(INT_CURR_SYMBOL);
460 #endif
461 #ifdef CURRENCY_SYMBOL
462 REGISTER_NL_LANGINFO_CONSTANT(CURRENCY_SYMBOL);
463 #endif
464 #ifdef CRNCYSTR
465 REGISTER_NL_LANGINFO_CONSTANT(CRNCYSTR);
466 #endif
467 #ifdef MON_DECIMAL_POINT
468 REGISTER_NL_LANGINFO_CONSTANT(MON_DECIMAL_POINT);
469 #endif
470 #ifdef MON_THOUSANDS_SEP
471 REGISTER_NL_LANGINFO_CONSTANT(MON_THOUSANDS_SEP);
472 #endif
473 #ifdef MON_GROUPING
474 REGISTER_NL_LANGINFO_CONSTANT(MON_GROUPING);
475 #endif
476 #ifdef POSITIVE_SIGN
477 REGISTER_NL_LANGINFO_CONSTANT(POSITIVE_SIGN);
478 #endif
479 #ifdef NEGATIVE_SIGN
480 REGISTER_NL_LANGINFO_CONSTANT(NEGATIVE_SIGN);
481 #endif
482 #ifdef INT_FRAC_DIGITS
483 REGISTER_NL_LANGINFO_CONSTANT(INT_FRAC_DIGITS);
484 #endif
485 #ifdef FRAC_DIGITS
486 REGISTER_NL_LANGINFO_CONSTANT(FRAC_DIGITS);
487 #endif
488 #ifdef P_CS_PRECEDES
489 REGISTER_NL_LANGINFO_CONSTANT(P_CS_PRECEDES);
490 #endif
491 #ifdef P_SEP_BY_SPACE
492 REGISTER_NL_LANGINFO_CONSTANT(P_SEP_BY_SPACE);
493 #endif
494 #ifdef N_CS_PRECEDES
495 REGISTER_NL_LANGINFO_CONSTANT(N_CS_PRECEDES);
496 #endif
497 #ifdef N_SEP_BY_SPACE
498 REGISTER_NL_LANGINFO_CONSTANT(N_SEP_BY_SPACE);
499 #endif
500 #ifdef P_SIGN_POSN
501 REGISTER_NL_LANGINFO_CONSTANT(P_SIGN_POSN);
502 #endif
503 #ifdef N_SIGN_POSN
504 REGISTER_NL_LANGINFO_CONSTANT(N_SIGN_POSN);
505 #endif
506 #ifdef DECIMAL_POINT
507 REGISTER_NL_LANGINFO_CONSTANT(DECIMAL_POINT);
508 #endif
509 #ifdef RADIXCHAR
510 REGISTER_NL_LANGINFO_CONSTANT(RADIXCHAR);
511 #endif
512 #ifdef THOUSANDS_SEP
513 REGISTER_NL_LANGINFO_CONSTANT(THOUSANDS_SEP);
514 #endif
515 #ifdef THOUSEP
516 REGISTER_NL_LANGINFO_CONSTANT(THOUSEP);
517 #endif
518 #ifdef GROUPING
519 REGISTER_NL_LANGINFO_CONSTANT(GROUPING);
520 #endif
521 #ifdef YESEXPR
522 REGISTER_NL_LANGINFO_CONSTANT(YESEXPR);
523 #endif
524 #ifdef NOEXPR
525 REGISTER_NL_LANGINFO_CONSTANT(NOEXPR);
526 #endif
527 #ifdef YESSTR
528 REGISTER_NL_LANGINFO_CONSTANT(YESSTR);
529 #endif
530 #ifdef NOSTR
531 REGISTER_NL_LANGINFO_CONSTANT(NOSTR);
532 #endif
533 #ifdef CODESET
534 REGISTER_NL_LANGINFO_CONSTANT(CODESET);
535 #endif
536 #undef REGISTER_NL_LANGINFO_CONSTANT
537 return SUCCESS;
538 }
539
540
541
542
543 PHP_FUNCTION(nl_langinfo)
544 {
545 zend_long item;
546 char *value;
547
548 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &item) == FAILURE) {
549 return;
550 }
551
552 switch(item) {
553 #ifdef ABDAY_1
554 case ABDAY_1:
555 case ABDAY_2:
556 case ABDAY_3:
557 case ABDAY_4:
558 case ABDAY_5:
559 case ABDAY_6:
560 case ABDAY_7:
561 #endif
562 #ifdef DAY_1
563 case DAY_1:
564 case DAY_2:
565 case DAY_3:
566 case DAY_4:
567 case DAY_5:
568 case DAY_6:
569 case DAY_7:
570 #endif
571 #ifdef ABMON_1
572 case ABMON_1:
573 case ABMON_2:
574 case ABMON_3:
575 case ABMON_4:
576 case ABMON_5:
577 case ABMON_6:
578 case ABMON_7:
579 case ABMON_8:
580 case ABMON_9:
581 case ABMON_10:
582 case ABMON_11:
583 case ABMON_12:
584 #endif
585 #ifdef MON_1
586 case MON_1:
587 case MON_2:
588 case MON_3:
589 case MON_4:
590 case MON_5:
591 case MON_6:
592 case MON_7:
593 case MON_8:
594 case MON_9:
595 case MON_10:
596 case MON_11:
597 case MON_12:
598 #endif
599 #ifdef AM_STR
600 case AM_STR:
601 #endif
602 #ifdef PM_STR
603 case PM_STR:
604 #endif
605 #ifdef D_T_FMT
606 case D_T_FMT:
607 #endif
608 #ifdef D_FMT
609 case D_FMT:
610 #endif
611 #ifdef T_FMT
612 case T_FMT:
613 #endif
614 #ifdef T_FMT_AMPM
615 case T_FMT_AMPM:
616 #endif
617 #ifdef ERA
618 case ERA:
619 #endif
620 #ifdef ERA_YEAR
621 case ERA_YEAR:
622 #endif
623 #ifdef ERA_D_T_FMT
624 case ERA_D_T_FMT:
625 #endif
626 #ifdef ERA_D_FMT
627 case ERA_D_FMT:
628 #endif
629 #ifdef ERA_T_FMT
630 case ERA_T_FMT:
631 #endif
632 #ifdef ALT_DIGITS
633 case ALT_DIGITS:
634 #endif
635 #ifdef INT_CURR_SYMBOL
636 case INT_CURR_SYMBOL:
637 #endif
638 #ifdef CURRENCY_SYMBOL
639 case CURRENCY_SYMBOL:
640 #endif
641 #ifdef CRNCYSTR
642 case CRNCYSTR:
643 #endif
644 #ifdef MON_DECIMAL_POINT
645 case MON_DECIMAL_POINT:
646 #endif
647 #ifdef MON_THOUSANDS_SEP
648 case MON_THOUSANDS_SEP:
649 #endif
650 #ifdef MON_GROUPING
651 case MON_GROUPING:
652 #endif
653 #ifdef POSITIVE_SIGN
654 case POSITIVE_SIGN:
655 #endif
656 #ifdef NEGATIVE_SIGN
657 case NEGATIVE_SIGN:
658 #endif
659 #ifdef INT_FRAC_DIGITS
660 case INT_FRAC_DIGITS:
661 #endif
662 #ifdef FRAC_DIGITS
663 case FRAC_DIGITS:
664 #endif
665 #ifdef P_CS_PRECEDES
666 case P_CS_PRECEDES:
667 #endif
668 #ifdef P_SEP_BY_SPACE
669 case P_SEP_BY_SPACE:
670 #endif
671 #ifdef N_CS_PRECEDES
672 case N_CS_PRECEDES:
673 #endif
674 #ifdef N_SEP_BY_SPACE
675 case N_SEP_BY_SPACE:
676 #endif
677 #ifdef P_SIGN_POSN
678 case P_SIGN_POSN:
679 #endif
680 #ifdef N_SIGN_POSN
681 case N_SIGN_POSN:
682 #endif
683 #ifdef DECIMAL_POINT
684 case DECIMAL_POINT:
685 #elif defined(RADIXCHAR)
686 case RADIXCHAR:
687 #endif
688 #ifdef THOUSANDS_SEP
689 case THOUSANDS_SEP:
690 #elif defined(THOUSEP)
691 case THOUSEP:
692 #endif
693 #ifdef GROUPING
694 case GROUPING:
695 #endif
696 #ifdef YESEXPR
697 case YESEXPR:
698 #endif
699 #ifdef NOEXPR
700 case NOEXPR:
701 #endif
702 #ifdef YESSTR
703 case YESSTR:
704 #endif
705 #ifdef NOSTR
706 case NOSTR:
707 #endif
708 #ifdef CODESET
709 case CODESET:
710 #endif
711 break;
712 default:
713 php_error_docref(NULL, E_WARNING, "Item '" ZEND_LONG_FMT "' is not valid", item);
714 RETURN_FALSE;
715 }
716
717
718 value = nl_langinfo(item);
719 if (value == NULL) {
720 RETURN_FALSE;
721 } else {
722 RETURN_STRING(value);
723 }
724 }
725 #endif
726
727
728 #ifdef HAVE_STRCOLL
729
730
731 PHP_FUNCTION(strcoll)
732 {
733 zend_string *s1, *s2;
734
735 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
736 return;
737 }
738
739 RETURN_LONG(strcoll((const char *) ZSTR_VAL(s1),
740 (const char *) ZSTR_VAL(s2)));
741 }
742
743 #endif
744
745
746
747
748
749
750 static inline int php_charmask(unsigned char *input, size_t len, char *mask)
751 {
752 unsigned char *end;
753 unsigned char c;
754 int result = SUCCESS;
755
756 memset(mask, 0, 256);
757 for (end = input+len; input < end; input++) {
758 c=*input;
759 if ((input+3 < end) && input[1] == '.' && input[2] == '.'
760 && input[3] >= c) {
761 memset(mask+c, 1, input[3] - c + 1);
762 input+=3;
763 } else if ((input+1 < end) && input[0] == '.' && input[1] == '.') {
764
765
766 if (end-len >= input) {
767 php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the left of '..'");
768 result = FAILURE;
769 continue;
770 }
771 if (input+2 >= end) {
772 php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'");
773 result = FAILURE;
774 continue;
775 }
776 if (input[-1] > input[2]) {
777 php_error_docref(NULL, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing");
778 result = FAILURE;
779 continue;
780 }
781
782 php_error_docref(NULL, E_WARNING, "Invalid '..'-range");
783 result = FAILURE;
784 continue;
785 } else {
786 mask[c]=1;
787 }
788 }
789 return result;
790 }
791
792
793
794
795
796
797
798
799 PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode)
800 {
801 const char *c = ZSTR_VAL(str);
802 size_t len = ZSTR_LEN(str);
803 register size_t i;
804 size_t trimmed = 0;
805 char mask[256];
806
807 if (what) {
808 if (what_len == 1) {
809 char p = *what;
810 if (mode & 1) {
811 for (i = 0; i < len; i++) {
812 if (c[i] == p) {
813 trimmed++;
814 } else {
815 break;
816 }
817 }
818 len -= trimmed;
819 c += trimmed;
820 }
821 if (mode & 2) {
822 if (len > 0) {
823 i = len - 1;
824 do {
825 if (c[i] == p) {
826 len--;
827 } else {
828 break;
829 }
830 } while (i-- != 0);
831 }
832 }
833 } else {
834 php_charmask((unsigned char*)what, what_len, mask);
835
836 if (mode & 1) {
837 for (i = 0; i < len; i++) {
838 if (mask[(unsigned char)c[i]]) {
839 trimmed++;
840 } else {
841 break;
842 }
843 }
844 len -= trimmed;
845 c += trimmed;
846 }
847 if (mode & 2) {
848 if (len > 0) {
849 i = len - 1;
850 do {
851 if (mask[(unsigned char)c[i]]) {
852 len--;
853 } else {
854 break;
855 }
856 } while (i-- != 0);
857 }
858 }
859 }
860 } else {
861 if (mode & 1) {
862 for (i = 0; i < len; i++) {
863 if ((unsigned char)c[i] <= ' ' &&
864 (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) {
865 trimmed++;
866 } else {
867 break;
868 }
869 }
870 len -= trimmed;
871 c += trimmed;
872 }
873 if (mode & 2) {
874 if (len > 0) {
875 i = len - 1;
876 do {
877 if ((unsigned char)c[i] <= ' ' &&
878 (c[i] == ' ' || c[i] == '\n' || c[i] == '\r' || c[i] == '\t' || c[i] == '\v' || c[i] == '\0')) {
879 len--;
880 } else {
881 break;
882 }
883 } while (i-- != 0);
884 }
885 }
886 }
887
888 if (ZSTR_LEN(str) == len) {
889 return zend_string_copy(str);
890 } else {
891 return zend_string_init(c, len, 0);
892 }
893 }
894
895
896
897
898
899 static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
900 {
901 zend_string *str;
902 zend_string *what = NULL;
903
904 #ifndef FAST_ZPP
905 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &str, &what) == FAILURE) {
906 return;
907 }
908 #else
909 ZEND_PARSE_PARAMETERS_START(1, 2)
910 Z_PARAM_STR(str)
911 Z_PARAM_OPTIONAL
912 Z_PARAM_STR(what)
913 ZEND_PARSE_PARAMETERS_END();
914 #endif
915
916 ZVAL_STR(return_value, php_trim(str, (what ? ZSTR_VAL(what) : NULL), (what ? ZSTR_LEN(what) : 0), mode));
917 }
918
919
920
921
922 PHP_FUNCTION(trim)
923 {
924 php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
925 }
926
927
928
929
930 PHP_FUNCTION(rtrim)
931 {
932 php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
933 }
934
935
936
937
938 PHP_FUNCTION(ltrim)
939 {
940 php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
941 }
942
943
944
945
946 PHP_FUNCTION(wordwrap)
947 {
948 zend_string *text;
949 char *breakchar = "\n";
950 size_t newtextlen, chk, breakchar_len = 1;
951 size_t alloced;
952 zend_long current = 0, laststart = 0, lastspace = 0;
953 zend_long linelength = 75;
954 zend_bool docut = 0;
955 zend_string *newtext;
956
957 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|lsb", &text, &linelength, &breakchar, &breakchar_len, &docut) == FAILURE) {
958 return;
959 }
960
961 if (ZSTR_LEN(text) == 0) {
962 RETURN_EMPTY_STRING();
963 }
964
965 if (breakchar_len == 0) {
966 php_error_docref(NULL, E_WARNING, "Break string cannot be empty");
967 RETURN_FALSE;
968 }
969
970 if (linelength == 0 && docut) {
971 php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero");
972 RETURN_FALSE;
973 }
974
975
976
977 if (breakchar_len == 1 && !docut) {
978 newtext = zend_string_init(ZSTR_VAL(text), ZSTR_LEN(text), 0);
979
980 laststart = lastspace = 0;
981 for (current = 0; current < ZSTR_LEN(text); current++) {
982 if (ZSTR_VAL(text)[current] == breakchar[0]) {
983 laststart = lastspace = current + 1;
984 } else if (ZSTR_VAL(text)[current] == ' ') {
985 if (current - laststart >= linelength) {
986 ZSTR_VAL(newtext)[current] = breakchar[0];
987 laststart = current + 1;
988 }
989 lastspace = current;
990 } else if (current - laststart >= linelength && laststart != lastspace) {
991 ZSTR_VAL(newtext)[lastspace] = breakchar[0];
992 laststart = lastspace + 1;
993 }
994 }
995
996 RETURN_NEW_STR(newtext);
997 } else {
998
999 if (linelength > 0) {
1000 chk = (size_t)(ZSTR_LEN(text)/linelength + 1);
1001 newtext = zend_string_safe_alloc(chk, breakchar_len, ZSTR_LEN(text), 0);
1002 alloced = ZSTR_LEN(text) + chk * breakchar_len + 1;
1003 } else {
1004 chk = ZSTR_LEN(text);
1005 alloced = ZSTR_LEN(text) * (breakchar_len + 1) + 1;
1006 newtext = zend_string_safe_alloc(ZSTR_LEN(text), breakchar_len + 1, 0, 0);
1007 }
1008
1009
1010 newtextlen = 0;
1011
1012 laststart = lastspace = 0;
1013 for (current = 0; current < ZSTR_LEN(text); current++) {
1014 if (chk <= 0) {
1015 alloced += (size_t) (((ZSTR_LEN(text) - current + 1)/linelength + 1) * breakchar_len) + 1;
1016 newtext = zend_string_extend(newtext, alloced, 0);
1017 chk = (size_t) ((ZSTR_LEN(text) - current)/linelength) + 1;
1018 }
1019
1020
1021 if (ZSTR_VAL(text)[current] == breakchar[0]
1022 && current + breakchar_len < ZSTR_LEN(text)
1023 && !strncmp(ZSTR_VAL(text) + current, breakchar, breakchar_len)) {
1024 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart + breakchar_len);
1025 newtextlen += current - laststart + breakchar_len;
1026 current += breakchar_len - 1;
1027 laststart = lastspace = current + 1;
1028 chk--;
1029 }
1030
1031
1032 else if (ZSTR_VAL(text)[current] == ' ') {
1033 if (current - laststart >= linelength) {
1034 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
1035 newtextlen += current - laststart;
1036 memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
1037 newtextlen += breakchar_len;
1038 laststart = current + 1;
1039 chk--;
1040 }
1041 lastspace = current;
1042 }
1043
1044
1045
1046 else if (current - laststart >= linelength
1047 && docut && laststart >= lastspace) {
1048 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
1049 newtextlen += current - laststart;
1050 memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
1051 newtextlen += breakchar_len;
1052 laststart = lastspace = current;
1053 chk--;
1054 }
1055
1056
1057
1058 else if (current - laststart >= linelength
1059 && laststart < lastspace) {
1060 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, lastspace - laststart);
1061 newtextlen += lastspace - laststart;
1062 memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
1063 newtextlen += breakchar_len;
1064 laststart = lastspace = lastspace + 1;
1065 chk--;
1066 }
1067 }
1068
1069
1070 if (laststart != current) {
1071 memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
1072 newtextlen += current - laststart;
1073 }
1074
1075 ZSTR_VAL(newtext)[newtextlen] = '\0';
1076
1077 newtext = zend_string_truncate(newtext, newtextlen, 0);
1078
1079 RETURN_NEW_STR(newtext);
1080 }
1081 }
1082
1083
1084
1085
1086 PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit)
1087 {
1088 char *p1 = ZSTR_VAL(str);
1089 char *endp = ZSTR_VAL(str) + ZSTR_LEN(str);
1090 char *p2 = (char *) php_memnstr(ZSTR_VAL(str), ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
1091 zval tmp;
1092
1093 if (p2 == NULL) {
1094 ZVAL_STR_COPY(&tmp, str);
1095 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
1096 } else {
1097 do {
1098 ZVAL_STRINGL(&tmp, p1, p2 - p1);
1099 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
1100 p1 = p2 + ZSTR_LEN(delim);
1101 p2 = (char *) php_memnstr(p1, ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
1102 } while (p2 != NULL && --limit > 1);
1103
1104 if (p1 <= endp) {
1105 ZVAL_STRINGL(&tmp, p1, endp - p1);
1106 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
1107 }
1108 }
1109 }
1110
1111
1112
1113
1114 PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit)
1115 {
1116 #define EXPLODE_ALLOC_STEP 64
1117 char *p1 = ZSTR_VAL(str);
1118 char *endp = ZSTR_VAL(str) + ZSTR_LEN(str);
1119 char *p2 = (char *) php_memnstr(ZSTR_VAL(str), ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
1120 zval tmp;
1121
1122 if (p2 == NULL) {
1123
1124
1125
1126
1127 } else {
1128 size_t allocated = EXPLODE_ALLOC_STEP, found = 0;
1129 zend_long i, to_return;
1130 char **positions = emalloc(allocated * sizeof(char *));
1131
1132 positions[found++] = p1;
1133 do {
1134 if (found >= allocated) {
1135 allocated = found + EXPLODE_ALLOC_STEP;
1136 positions = erealloc(positions, allocated*sizeof(char *));
1137 }
1138 positions[found++] = p1 = p2 + ZSTR_LEN(delim);
1139 p2 = (char *) php_memnstr(p1, ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
1140 } while (p2 != NULL);
1141
1142 to_return = limit + found;
1143
1144 for (i = 0; i < to_return; i++) {
1145 ZVAL_STRINGL(&tmp, positions[i], (positions[i+1] - ZSTR_LEN(delim)) - positions[i]);
1146 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
1147 }
1148 efree(positions);
1149 }
1150 #undef EXPLODE_ALLOC_STEP
1151 }
1152
1153
1154
1155
1156 PHP_FUNCTION(explode)
1157 {
1158 zend_string *str, *delim;
1159 zend_long limit = ZEND_LONG_MAX;
1160 zval tmp;
1161
1162 #ifndef FAST_ZPP
1163 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|l", &delim, &str, &limit) == FAILURE) {
1164 return;
1165 }
1166 #else
1167 ZEND_PARSE_PARAMETERS_START(2, 3)
1168 Z_PARAM_STR(delim)
1169 Z_PARAM_STR(str)
1170 Z_PARAM_OPTIONAL
1171 Z_PARAM_LONG(limit)
1172 ZEND_PARSE_PARAMETERS_END();
1173 #endif
1174
1175 if (ZSTR_LEN(delim) == 0) {
1176 php_error_docref(NULL, E_WARNING, "Empty delimiter");
1177 RETURN_FALSE;
1178 }
1179
1180 array_init(return_value);
1181
1182 if (ZSTR_LEN(str) == 0) {
1183 if (limit >= 0) {
1184 ZVAL_EMPTY_STRING(&tmp);
1185 zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
1186 }
1187 return;
1188 }
1189
1190 if (limit > 1) {
1191 php_explode(delim, str, return_value, limit);
1192 } else if (limit < 0) {
1193 php_explode_negative_limit(delim, str, return_value, limit);
1194 } else {
1195 ZVAL_STR_COPY(&tmp, str);
1196 zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
1197 }
1198 }
1199
1200
1201
1202
1203
1204
1205
1206
1207 PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value)
1208 {
1209 zval *tmp;
1210 int numelems;
1211 zend_string *str;
1212 char *cptr;
1213 size_t len = 0;
1214 zend_string **strings, **strptr;
1215
1216 numelems = zend_hash_num_elements(Z_ARRVAL_P(arr));
1217
1218 if (numelems == 0) {
1219 RETURN_EMPTY_STRING();
1220 } else if (numelems == 1) {
1221
1222 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
1223 RETURN_STR(zval_get_string(tmp));
1224 } ZEND_HASH_FOREACH_END();
1225 }
1226
1227 strings = emalloc((sizeof(zend_long) + sizeof(zend_string *)) * numelems);
1228 strptr = strings - 1;
1229
1230 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
1231 if (Z_TYPE_P(tmp) == IS_LONG) {
1232 double val = Z_LVAL_P(tmp);
1233 *++strptr = NULL;
1234 ((zend_long *) (strings + numelems))[strptr - strings] = Z_LVAL_P(tmp);
1235 if (val < 0) {
1236 val = -10 * val;
1237 }
1238 if (val < 10) {
1239 len++;
1240 } else {
1241 len += (int) log10(10 * (double) val);
1242 }
1243 } else {
1244 *++strptr = zval_get_string(tmp);
1245 len += ZSTR_LEN(*strptr);
1246 }
1247 } ZEND_HASH_FOREACH_END();
1248
1249 str = zend_string_safe_alloc(numelems - 1, ZSTR_LEN(delim), len, 0);
1250 cptr = ZSTR_VAL(str) + ZSTR_LEN(str);
1251 *cptr = 0;
1252
1253 do {
1254 if (*strptr) {
1255 cptr -= ZSTR_LEN(*strptr);
1256 memcpy(cptr, ZSTR_VAL(*strptr), ZSTR_LEN(*strptr));
1257 zend_string_release(*strptr);
1258 } else {
1259 char *oldPtr = cptr;
1260 char oldVal = *cptr;
1261 zend_long val = ((zend_long *) (strings + numelems))[strptr - strings];
1262 cptr = zend_print_long_to_buf(cptr, val);
1263 *oldPtr = oldVal;
1264 }
1265
1266 cptr -= ZSTR_LEN(delim);
1267 memcpy(cptr, ZSTR_VAL(delim), ZSTR_LEN(delim));
1268 } while (--strptr > strings);
1269
1270 if (*strptr) {
1271 memcpy(ZSTR_VAL(str), ZSTR_VAL(*strptr), ZSTR_LEN(*strptr));
1272 zend_string_release(*strptr);
1273 } else {
1274 char *oldPtr = cptr;
1275 char oldVal = *cptr;
1276 zend_print_long_to_buf(cptr, ((zend_long *) (strings + numelems))[strptr - strings]);
1277 *oldPtr = oldVal;
1278 }
1279
1280 efree(strings);
1281 RETURN_NEW_STR(str);
1282 }
1283
1284
1285
1286
1287 PHP_FUNCTION(implode)
1288 {
1289 zval *arg1, *arg2 = NULL, *arr;
1290 zend_string *delim;
1291
1292 #ifndef FAST_ZPP
1293 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|z", &arg1, &arg2) == FAILURE) {
1294 return;
1295 }
1296 #else
1297 ZEND_PARSE_PARAMETERS_START(1, 2)
1298 Z_PARAM_ZVAL(arg1)
1299 Z_PARAM_OPTIONAL
1300 Z_PARAM_ZVAL(arg2)
1301 ZEND_PARSE_PARAMETERS_END();
1302 #endif
1303
1304 if (arg2 == NULL) {
1305 if (Z_TYPE_P(arg1) != IS_ARRAY) {
1306 php_error_docref(NULL, E_WARNING, "Argument must be an array");
1307 return;
1308 }
1309
1310 delim = ZSTR_EMPTY_ALLOC();
1311 arr = arg1;
1312 } else {
1313 if (Z_TYPE_P(arg1) == IS_ARRAY) {
1314 delim = zval_get_string(arg2);
1315 arr = arg1;
1316 } else if (Z_TYPE_P(arg2) == IS_ARRAY) {
1317 delim = zval_get_string(arg1);
1318 arr = arg2;
1319 } else {
1320 php_error_docref(NULL, E_WARNING, "Invalid arguments passed");
1321 return;
1322 }
1323 }
1324
1325 php_implode(delim, arr, return_value);
1326 zend_string_release(delim);
1327 }
1328
1329
1330 #define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]
1331
1332
1333
1334 PHP_FUNCTION(strtok)
1335 {
1336 zend_string *str, *tok = NULL;
1337 char *token;
1338 char *token_end;
1339 char *p;
1340 char *pe;
1341 size_t skipped = 0;
1342
1343 #ifndef FAST_ZPP
1344 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &str, &tok) == FAILURE) {
1345 return;
1346 }
1347 #else
1348 ZEND_PARSE_PARAMETERS_START(1, 2)
1349 Z_PARAM_STR(str)
1350 Z_PARAM_OPTIONAL
1351 Z_PARAM_STR(tok)
1352 ZEND_PARSE_PARAMETERS_END();
1353 #endif
1354
1355 if (ZEND_NUM_ARGS() == 1) {
1356 tok = str;
1357 } else {
1358 zval_ptr_dtor(&BG(strtok_zval));
1359 ZVAL_STRINGL(&BG(strtok_zval), ZSTR_VAL(str), ZSTR_LEN(str));
1360 BG(strtok_last) = BG(strtok_string) = Z_STRVAL(BG(strtok_zval));
1361 BG(strtok_len) = ZSTR_LEN(str);
1362 }
1363
1364 p = BG(strtok_last);
1365 pe = BG(strtok_string) + BG(strtok_len);
1366
1367 if (!p || p >= pe) {
1368 RETURN_FALSE;
1369 }
1370
1371 token = ZSTR_VAL(tok);
1372 token_end = token + ZSTR_LEN(tok);
1373
1374 while (token < token_end) {
1375 STRTOK_TABLE(token++) = 1;
1376 }
1377
1378
1379 while (STRTOK_TABLE(p)) {
1380 if (++p >= pe) {
1381
1382 BG(strtok_last) = NULL;
1383 RETVAL_FALSE;
1384 goto restore;
1385 }
1386 skipped++;
1387 }
1388
1389
1390 while (++p < pe) {
1391 if (STRTOK_TABLE(p)) {
1392 goto return_token;
1393 }
1394 }
1395
1396 if (p - BG(strtok_last)) {
1397 return_token:
1398 RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped);
1399 BG(strtok_last) = p + 1;
1400 } else {
1401 RETVAL_FALSE;
1402 BG(strtok_last) = NULL;
1403 }
1404
1405
1406 restore:
1407 token = ZSTR_VAL(tok);
1408
1409 while (token < token_end) {
1410 STRTOK_TABLE(token++) = 0;
1411 }
1412 }
1413
1414
1415
1416
1417 PHPAPI char *php_strtoupper(char *s, size_t len)
1418 {
1419 unsigned char *c, *e;
1420
1421 c = (unsigned char *)s;
1422 e = (unsigned char *)c+len;
1423
1424 while (c < e) {
1425 *c = toupper(*c);
1426 c++;
1427 }
1428 return s;
1429 }
1430
1431
1432
1433
1434 PHPAPI zend_string *php_string_toupper(zend_string *s)
1435 {
1436 unsigned char *c, *e;
1437
1438 c = (unsigned char *)ZSTR_VAL(s);
1439 e = c + ZSTR_LEN(s);
1440
1441 while (c < e) {
1442 if (!isupper(*c)) {
1443 register unsigned char *r;
1444 zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
1445
1446 if (c != (unsigned char*)ZSTR_VAL(s)) {
1447 memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
1448 }
1449 r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
1450 while (c < e) {
1451 *r = toupper(*c);
1452 r++;
1453 c++;
1454 }
1455 *r = '\0';
1456 return res;
1457 }
1458 c++;
1459 }
1460 return zend_string_copy(s);
1461 }
1462
1463
1464
1465
1466 PHP_FUNCTION(strtoupper)
1467 {
1468 zend_string *arg;
1469
1470 #ifndef FAST_ZPP
1471 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
1472 return;
1473 }
1474 #else
1475 ZEND_PARSE_PARAMETERS_START(1, 1)
1476 Z_PARAM_STR(arg)
1477 ZEND_PARSE_PARAMETERS_END();
1478 #endif
1479
1480 RETURN_STR(php_string_toupper(arg));
1481 }
1482
1483
1484
1485
1486 PHPAPI char *php_strtolower(char *s, size_t len)
1487 {
1488 unsigned char *c, *e;
1489
1490 c = (unsigned char *)s;
1491 e = c+len;
1492
1493 while (c < e) {
1494 *c = tolower(*c);
1495 c++;
1496 }
1497 return s;
1498 }
1499
1500
1501
1502
1503 PHPAPI zend_string *php_string_tolower(zend_string *s)
1504 {
1505 unsigned char *c, *e;
1506
1507 c = (unsigned char *)ZSTR_VAL(s);
1508 e = c + ZSTR_LEN(s);
1509
1510 while (c < e) {
1511 if (!islower(*c)) {
1512 register unsigned char *r;
1513 zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
1514
1515 if (c != (unsigned char*)ZSTR_VAL(s)) {
1516 memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
1517 }
1518 r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
1519 while (c < e) {
1520 *r = tolower(*c);
1521 r++;
1522 c++;
1523 }
1524 *r = '\0';
1525 return res;
1526 }
1527 c++;
1528 }
1529 return zend_string_copy(s);
1530 }
1531
1532
1533
1534
1535 PHP_FUNCTION(strtolower)
1536 {
1537 zend_string *str;
1538
1539 #ifndef FAST_ZPP
1540 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
1541 return;
1542 }
1543 #else
1544 ZEND_PARSE_PARAMETERS_START(1, 1)
1545 Z_PARAM_STR(str)
1546 ZEND_PARSE_PARAMETERS_END();
1547 #endif
1548
1549 RETURN_STR(php_string_tolower(str));
1550 }
1551
1552
1553
1554
1555 PHPAPI zend_string *php_basename(const char *s, size_t len, char *suffix, size_t sufflen)
1556 {
1557 char *c, *comp, *cend;
1558 size_t inc_len, cnt;
1559 int state;
1560 zend_string *ret;
1561
1562 c = comp = cend = (char*)s;
1563 cnt = len;
1564 state = 0;
1565 while (cnt > 0) {
1566 inc_len = (*c == '\0' ? 1 : php_mblen(c, cnt));
1567
1568 switch (inc_len) {
1569 case -2:
1570 case -1:
1571 inc_len = 1;
1572 php_mb_reset();
1573 break;
1574 case 0:
1575 goto quit_loop;
1576 case 1:
1577 #if defined(PHP_WIN32) || defined(NETWARE)
1578 if (*c == '/' || *c == '\\') {
1579 #else
1580 if (*c == '/') {
1581 #endif
1582 if (state == 1) {
1583 state = 0;
1584 cend = c;
1585 }
1586 #if defined(PHP_WIN32) || defined(NETWARE)
1587
1588
1589
1590 } else if ((*c == ':' && (c - comp == 1))) {
1591 if (state == 0) {
1592 comp = c;
1593 state = 1;
1594 } else {
1595 cend = c;
1596 state = 0;
1597 }
1598 #endif
1599 } else {
1600 if (state == 0) {
1601 comp = c;
1602 state = 1;
1603 }
1604 }
1605 break;
1606 default:
1607 if (state == 0) {
1608 comp = c;
1609 state = 1;
1610 }
1611 break;
1612 }
1613 c += inc_len;
1614 cnt -= inc_len;
1615 }
1616
1617 quit_loop:
1618 if (state == 1) {
1619 cend = c;
1620 }
1621 if (suffix != NULL && sufflen < (size_t)(cend - comp) &&
1622 memcmp(cend - sufflen, suffix, sufflen) == 0) {
1623 cend -= sufflen;
1624 }
1625
1626 len = cend - comp;
1627
1628 ret = zend_string_init(comp, len, 0);
1629 return ret;
1630 }
1631
1632
1633
1634
1635 PHP_FUNCTION(basename)
1636 {
1637 char *string, *suffix = NULL;
1638 size_t string_len, suffix_len = 0;
1639
1640 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &string, &string_len, &suffix, &suffix_len) == FAILURE) {
1641 return;
1642 }
1643
1644 RETURN_STR(php_basename(string, string_len, suffix, suffix_len));
1645 }
1646
1647
1648
1649
1650 PHPAPI size_t php_dirname(char *path, size_t len)
1651 {
1652 return zend_dirname(path, len);
1653 }
1654
1655
1656
1657
1658 PHP_FUNCTION(dirname)
1659 {
1660 char *str;
1661 size_t str_len;
1662 zend_string *ret;
1663 zend_long levels = 1;
1664
1665 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &levels) == FAILURE) {
1666 return;
1667 }
1668
1669 ret = zend_string_init(str, str_len, 0);
1670
1671 if (levels == 1) {
1672
1673 ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len);
1674 } else if (levels < 1) {
1675 php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1");
1676 zend_string_free(ret);
1677 return;
1678 } else {
1679
1680 do {
1681 ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len = ZSTR_LEN(ret));
1682 } while (ZSTR_LEN(ret) < str_len && --levels);
1683 }
1684
1685 RETURN_NEW_STR(ret);
1686 }
1687
1688
1689
1690
1691 PHP_FUNCTION(pathinfo)
1692 {
1693 zval tmp;
1694 char *path, *dirname;
1695 size_t path_len;
1696 int have_basename;
1697 zend_long opt = PHP_PATHINFO_ALL;
1698 zend_string *ret = NULL;
1699
1700 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &path_len, &opt) == FAILURE) {
1701 return;
1702 }
1703
1704 have_basename = ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);
1705
1706 array_init(&tmp);
1707
1708 if ((opt & PHP_PATHINFO_DIRNAME) == PHP_PATHINFO_DIRNAME) {
1709 dirname = estrndup(path, path_len);
1710 php_dirname(dirname, path_len);
1711 if (*dirname) {
1712 add_assoc_string(&tmp, "dirname", dirname);
1713 }
1714 efree(dirname);
1715 }
1716
1717 if (have_basename) {
1718 ret = php_basename(path, path_len, NULL, 0);
1719 add_assoc_str(&tmp, "basename", zend_string_copy(ret));
1720 }
1721
1722 if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
1723 const char *p;
1724 ptrdiff_t idx;
1725
1726 if (!have_basename) {
1727 ret = php_basename(path, path_len, NULL, 0);
1728 }
1729
1730 p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
1731
1732 if (p) {
1733 idx = p - ZSTR_VAL(ret);
1734 add_assoc_stringl(&tmp, "extension", ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
1735 }
1736 }
1737
1738 if ((opt & PHP_PATHINFO_FILENAME) == PHP_PATHINFO_FILENAME) {
1739 const char *p;
1740 ptrdiff_t idx;
1741
1742
1743 if (!have_basename && !ret) {
1744 ret = php_basename(path, path_len, NULL, 0);
1745 }
1746
1747 p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
1748
1749 idx = p ? (p - ZSTR_VAL(ret)) : ZSTR_LEN(ret);
1750 add_assoc_stringl(&tmp, "filename", ZSTR_VAL(ret), idx);
1751 }
1752
1753 if (ret) {
1754 zend_string_release(ret);
1755 }
1756
1757 if (opt == PHP_PATHINFO_ALL) {
1758 ZVAL_COPY_VALUE(return_value, &tmp);
1759 } else {
1760 zval *element;
1761 if ((element = zend_hash_get_current_data(Z_ARRVAL(tmp))) != NULL) {
1762 ZVAL_DEREF(element);
1763 ZVAL_COPY(return_value, element);
1764 } else {
1765 ZVAL_EMPTY_STRING(return_value);
1766 }
1767 zval_ptr_dtor(&tmp);
1768 }
1769 }
1770
1771
1772
1773
1774 PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
1775 {
1776 php_strtolower(s, s_len);
1777 php_strtolower(t, t_len);
1778 return (char*)php_memnstr(s, t, t_len, s + s_len);
1779 }
1780
1781
1782
1783
1784 PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end)
1785 {
1786 register const char *p = s1, *spanp;
1787 register char c = *p;
1788
1789 cont:
1790 for (spanp = s2; p != s1_end && spanp != s2_end;) {
1791 if (*spanp++ == c) {
1792 c = *(++p);
1793 goto cont;
1794 }
1795 }
1796 return (p - s1);
1797 }
1798
1799
1800
1801
1802 PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end)
1803 {
1804 register const char *p, *spanp;
1805 register char c = *s1;
1806
1807 for (p = s1;;) {
1808 spanp = s2;
1809 do {
1810 if (*spanp == c || p == s1_end) {
1811 return p - s1;
1812 }
1813 } while (spanp++ < (s2_end - 1));
1814 c = *++p;
1815 }
1816
1817 }
1818
1819
1820
1821
1822 static int php_needle_char(zval *needle, char *target)
1823 {
1824 switch (Z_TYPE_P(needle)) {
1825 case IS_LONG:
1826 *target = (char)Z_LVAL_P(needle);
1827 return SUCCESS;
1828 case IS_NULL:
1829 case IS_FALSE:
1830 *target = '\0';
1831 return SUCCESS;
1832 case IS_TRUE:
1833 *target = '\1';
1834 return SUCCESS;
1835 case IS_DOUBLE:
1836 *target = (char)(int)Z_DVAL_P(needle);
1837 return SUCCESS;
1838 case IS_OBJECT:
1839 *target = (char) zval_get_long(needle);
1840 return SUCCESS;
1841 default:
1842 php_error_docref(NULL, E_WARNING, "needle is not a string or an integer");
1843 return FAILURE;
1844 }
1845 }
1846
1847
1848
1849
1850 PHP_FUNCTION(stristr)
1851 {
1852 zval *needle;
1853 zend_string *haystack;
1854 char *found = NULL;
1855 size_t found_offset;
1856 char *haystack_dup;
1857 char needle_char[2];
1858 zend_bool part = 0;
1859
1860 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|b", &haystack, &needle, &part) == FAILURE) {
1861 return;
1862 }
1863
1864 haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack));
1865
1866 if (Z_TYPE_P(needle) == IS_STRING) {
1867 char *orig_needle;
1868 if (!Z_STRLEN_P(needle)) {
1869 php_error_docref(NULL, E_WARNING, "Empty needle");
1870 efree(haystack_dup);
1871 RETURN_FALSE;
1872 }
1873 orig_needle = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle));
1874 found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), Z_STRLEN_P(needle));
1875 efree(orig_needle);
1876 } else {
1877 if (php_needle_char(needle, needle_char) != SUCCESS) {
1878 efree(haystack_dup);
1879 RETURN_FALSE;
1880 }
1881 needle_char[1] = 0;
1882
1883 found = php_stristr(haystack_dup, needle_char, ZSTR_LEN(haystack), 1);
1884 }
1885
1886 if (found) {
1887 found_offset = found - haystack_dup;
1888 if (part) {
1889 RETVAL_STRINGL(ZSTR_VAL(haystack), found_offset);
1890 } else {
1891 RETVAL_STRINGL(ZSTR_VAL(haystack) + found_offset, ZSTR_LEN(haystack) - found_offset);
1892 }
1893 } else {
1894 RETVAL_FALSE;
1895 }
1896
1897 efree(haystack_dup);
1898 }
1899
1900
1901
1902
1903 PHP_FUNCTION(strstr)
1904 {
1905 zval *needle;
1906 zend_string *haystack;
1907 char *found = NULL;
1908 char needle_char[2];
1909 zend_long found_offset;
1910 zend_bool part = 0;
1911
1912 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|b", &haystack, &needle, &part) == FAILURE) {
1913 return;
1914 }
1915
1916 if (Z_TYPE_P(needle) == IS_STRING) {
1917 if (!Z_STRLEN_P(needle)) {
1918 php_error_docref(NULL, E_WARNING, "Empty needle");
1919 RETURN_FALSE;
1920 }
1921
1922 found = (char*)php_memnstr(ZSTR_VAL(haystack), Z_STRVAL_P(needle), Z_STRLEN_P(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
1923 } else {
1924 if (php_needle_char(needle, needle_char) != SUCCESS) {
1925 RETURN_FALSE;
1926 }
1927 needle_char[1] = 0;
1928
1929 found = (char*)php_memnstr(ZSTR_VAL(haystack), needle_char, 1, ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
1930 }
1931
1932 if (found) {
1933 found_offset = found - ZSTR_VAL(haystack);
1934 if (part) {
1935 RETURN_STRINGL(ZSTR_VAL(haystack), found_offset);
1936 } else {
1937 RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
1938 }
1939 }
1940 RETURN_FALSE;
1941 }
1942
1943
1944
1945
1946
1947
1948
1949
1950 PHP_FUNCTION(strpos)
1951 {
1952 zval *needle;
1953 zend_string *haystack;
1954 char *found = NULL;
1955 char needle_char[2];
1956 zend_long offset = 0;
1957
1958 #ifndef FAST_ZPP
1959 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &needle, &offset) == FAILURE) {
1960 return;
1961 }
1962 #else
1963 ZEND_PARSE_PARAMETERS_START(2, 3)
1964 Z_PARAM_STR(haystack)
1965 Z_PARAM_ZVAL(needle)
1966 Z_PARAM_OPTIONAL
1967 Z_PARAM_LONG(offset)
1968 ZEND_PARSE_PARAMETERS_END();
1969 #endif
1970
1971 if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
1972 php_error_docref(NULL, E_WARNING, "Offset not contained in string");
1973 RETURN_FALSE;
1974 }
1975
1976 if (Z_TYPE_P(needle) == IS_STRING) {
1977 if (!Z_STRLEN_P(needle)) {
1978 php_error_docref(NULL, E_WARNING, "Empty needle");
1979 RETURN_FALSE;
1980 }
1981
1982 found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
1983 Z_STRVAL_P(needle),
1984 Z_STRLEN_P(needle),
1985 ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
1986 } else {
1987 if (php_needle_char(needle, needle_char) != SUCCESS) {
1988 RETURN_FALSE;
1989 }
1990 needle_char[1] = 0;
1991
1992 found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
1993 needle_char,
1994 1,
1995 ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
1996 }
1997
1998 if (found) {
1999 RETURN_LONG(found - ZSTR_VAL(haystack));
2000 } else {
2001 RETURN_FALSE;
2002 }
2003 }
2004
2005
2006
2007
2008 PHP_FUNCTION(stripos)
2009 {
2010 char *found = NULL;
2011 zend_string *haystack;
2012 zend_long offset = 0;
2013 char needle_char[2];
2014 zval *needle;
2015 zend_string *needle_dup = NULL, *haystack_dup;
2016
2017 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &needle, &offset) == FAILURE) {
2018 return;
2019 }
2020
2021 if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
2022 php_error_docref(NULL, E_WARNING, "Offset not contained in string");
2023 RETURN_FALSE;
2024 }
2025
2026 if (ZSTR_LEN(haystack) == 0) {
2027 RETURN_FALSE;
2028 }
2029
2030 if (Z_TYPE_P(needle) == IS_STRING) {
2031 if (Z_STRLEN_P(needle) == 0 || Z_STRLEN_P(needle) > ZSTR_LEN(haystack)) {
2032 RETURN_FALSE;
2033 }
2034
2035 haystack_dup = php_string_tolower(haystack);
2036 needle_dup = php_string_tolower(Z_STR_P(needle));
2037 found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset,
2038 ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack));
2039 } else {
2040 if (php_needle_char(needle, needle_char) != SUCCESS) {
2041 RETURN_FALSE;
2042 }
2043 haystack_dup = php_string_tolower(haystack);
2044 needle_char[0] = tolower(needle_char[0]);
2045 needle_char[1] = '\0';
2046 found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset,
2047 needle_char,
2048 sizeof(needle_char) - 1,
2049 ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack));
2050 }
2051
2052
2053 if (found) {
2054 RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
2055 } else {
2056 RETVAL_FALSE;
2057 }
2058
2059 zend_string_release(haystack_dup);
2060 if (needle_dup) {
2061 zend_string_release(needle_dup);
2062 }
2063 }
2064
2065
2066
2067
2068 PHP_FUNCTION(strrpos)
2069 {
2070 zval *zneedle;
2071 char *needle;
2072 zend_string *haystack;
2073 size_t needle_len;
2074 zend_long offset = 0;
2075 char *p, *e, ord_needle[2];
2076 char *found;
2077
2078 #ifndef FAST_ZPP
2079 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &zneedle, &offset) == FAILURE) {
2080 RETURN_FALSE;
2081 }
2082 #else
2083 ZEND_PARSE_PARAMETERS_START(2, 3)
2084 Z_PARAM_STR(haystack)
2085 Z_PARAM_ZVAL(zneedle)
2086 Z_PARAM_OPTIONAL
2087 Z_PARAM_LONG(offset)
2088 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
2089 #endif
2090
2091 if (Z_TYPE_P(zneedle) == IS_STRING) {
2092 needle = Z_STRVAL_P(zneedle);
2093 needle_len = Z_STRLEN_P(zneedle);
2094 } else {
2095 if (php_needle_char(zneedle, ord_needle) != SUCCESS) {
2096 RETURN_FALSE;
2097 }
2098 ord_needle[1] = '\0';
2099 needle = ord_needle;
2100 needle_len = 1;
2101 }
2102
2103 if ((ZSTR_LEN(haystack) == 0) || (needle_len == 0)) {
2104 RETURN_FALSE;
2105 }
2106
2107 if (offset >= 0) {
2108 if ((size_t)offset > ZSTR_LEN(haystack)) {
2109 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
2110 RETURN_FALSE;
2111 }
2112 p = ZSTR_VAL(haystack) + (size_t)offset;
2113 e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
2114 } else {
2115 if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
2116 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
2117 RETURN_FALSE;
2118 }
2119 p = ZSTR_VAL(haystack);
2120 if (-offset < needle_len) {
2121 e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
2122 } else {
2123 e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + needle_len;
2124 }
2125 }
2126
2127 if ((found = (char *)zend_memnrstr(p, needle, needle_len, e))) {
2128 RETURN_LONG(found - ZSTR_VAL(haystack));
2129 }
2130
2131 RETURN_FALSE;
2132 }
2133
2134
2135
2136
2137 PHP_FUNCTION(strripos)
2138 {
2139 zval *zneedle;
2140 zend_string *needle;
2141 zend_string *haystack;
2142 zend_long offset = 0;
2143 char *p, *e;
2144 char *found;
2145 zend_string *needle_dup, *haystack_dup, *ord_needle = NULL;
2146 ALLOCA_FLAG(use_heap);
2147
2148
2149 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|l", &haystack, &zneedle, &offset) == FAILURE) {
2150 RETURN_FALSE;
2151 }
2152
2153 ZSTR_ALLOCA_ALLOC(ord_needle, 1, use_heap);
2154 if (Z_TYPE_P(zneedle) == IS_STRING) {
2155 needle = Z_STR_P(zneedle);
2156 } else {
2157 if (php_needle_char(zneedle, ZSTR_VAL(ord_needle)) != SUCCESS) {
2158 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2159 RETURN_FALSE;
2160 }
2161 ZSTR_VAL(ord_needle)[1] = '\0';
2162 needle = ord_needle;
2163 }
2164
2165 if ((ZSTR_LEN(haystack) == 0) || (ZSTR_LEN(needle) == 0)) {
2166 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2167 RETURN_FALSE;
2168 }
2169
2170 if (ZSTR_LEN(needle) == 1) {
2171
2172
2173 if (offset >= 0) {
2174 if ((size_t)offset > ZSTR_LEN(haystack)) {
2175 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2176 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
2177 RETURN_FALSE;
2178 }
2179 p = ZSTR_VAL(haystack) + (size_t)offset;
2180 e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - 1;
2181 } else {
2182 p = ZSTR_VAL(haystack);
2183 if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
2184 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2185 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
2186 RETURN_FALSE;
2187 }
2188 e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + (size_t)offset;
2189 }
2190
2191 *ZSTR_VAL(ord_needle) = tolower(*ZSTR_VAL(needle));
2192 while (e >= p) {
2193 if (tolower(*e) == *ZSTR_VAL(ord_needle)) {
2194 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2195 RETURN_LONG(e - p + (offset > 0 ? offset : 0));
2196 }
2197 e--;
2198 }
2199 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2200 RETURN_FALSE;
2201 }
2202
2203 haystack_dup = php_string_tolower(haystack);
2204 if (offset >= 0) {
2205 if ((size_t)offset > ZSTR_LEN(haystack)) {
2206 zend_string_release(haystack_dup);
2207 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2208 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
2209 RETURN_FALSE;
2210 }
2211 p = ZSTR_VAL(haystack_dup) + offset;
2212 e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);
2213 } else {
2214 if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
2215 zend_string_release(haystack_dup);
2216 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2217 php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string");
2218 RETURN_FALSE;
2219 }
2220 p = ZSTR_VAL(haystack_dup);
2221 if (-offset < ZSTR_LEN(needle)) {
2222 e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);
2223 } else {
2224 e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack) + offset + ZSTR_LEN(needle);
2225 }
2226 }
2227
2228 needle_dup = php_string_tolower(needle);
2229 if ((found = (char *)zend_memnrstr(p, ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), e))) {
2230 RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
2231 zend_string_release(needle_dup);
2232 zend_string_release(haystack_dup);
2233 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2234 } else {
2235 zend_string_release(needle_dup);
2236 zend_string_release(haystack_dup);
2237 ZSTR_ALLOCA_FREE(ord_needle, use_heap);
2238 RETURN_FALSE;
2239 }
2240 }
2241
2242
2243
2244
2245 PHP_FUNCTION(strrchr)
2246 {
2247 zval *needle;
2248 zend_string *haystack;
2249 const char *found = NULL;
2250 zend_long found_offset;
2251
2252 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &haystack, &needle) == FAILURE) {
2253 return;
2254 }
2255
2256 if (Z_TYPE_P(needle) == IS_STRING) {
2257 found = zend_memrchr(ZSTR_VAL(haystack), *Z_STRVAL_P(needle), ZSTR_LEN(haystack));
2258 } else {
2259 char needle_chr;
2260 if (php_needle_char(needle, &needle_chr) != SUCCESS) {
2261 RETURN_FALSE;
2262 }
2263
2264 found = zend_memrchr(ZSTR_VAL(haystack), needle_chr, ZSTR_LEN(haystack));
2265 }
2266
2267 if (found) {
2268 found_offset = found - ZSTR_VAL(haystack);
2269 RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
2270 } else {
2271 RETURN_FALSE;
2272 }
2273 }
2274
2275
2276
2277
2278 static zend_string *php_chunk_split(char *src, size_t srclen, char *end, size_t endlen, size_t chunklen)
2279 {
2280 char *p, *q;
2281 size_t chunks;
2282 size_t restlen;
2283 size_t out_len;
2284 zend_string *dest;
2285
2286 chunks = srclen / chunklen;
2287 restlen = srclen - chunks * chunklen;
2288
2289 if (chunks > INT_MAX - 1) {
2290 return NULL;
2291 }
2292 out_len = chunks + 1;
2293 if (endlen !=0 && out_len > INT_MAX/endlen) {
2294 return NULL;
2295 }
2296 out_len *= endlen;
2297 if (out_len > INT_MAX - srclen - 1) {
2298 return NULL;
2299 }
2300 out_len += srclen + 1;
2301
2302 dest = zend_string_alloc(out_len * sizeof(char), 0);
2303
2304 for (p = src, q = ZSTR_VAL(dest); p < (src + srclen - chunklen + 1); ) {
2305 memcpy(q, p, chunklen);
2306 q += chunklen;
2307 memcpy(q, end, endlen);
2308 q += endlen;
2309 p += chunklen;
2310 }
2311
2312 if (restlen) {
2313 memcpy(q, p, restlen);
2314 q += restlen;
2315 memcpy(q, end, endlen);
2316 q += endlen;
2317 }
2318
2319 *q = '\0';
2320 ZSTR_LEN(dest) = q - ZSTR_VAL(dest);
2321
2322 return dest;
2323 }
2324
2325
2326
2327
2328 PHP_FUNCTION(chunk_split)
2329 {
2330 zend_string *str;
2331 char *end = "\r\n";
2332 size_t endlen = 2;
2333 zend_long chunklen = 76;
2334 zend_string *result;
2335
2336 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ls", &str, &chunklen, &end, &endlen) == FAILURE) {
2337 return;
2338 }
2339
2340 if (chunklen <= 0) {
2341 php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero");
2342 RETURN_FALSE;
2343 }
2344
2345 if ((size_t)chunklen > ZSTR_LEN(str)) {
2346
2347 result = zend_string_safe_alloc(ZSTR_LEN(str), 1, endlen, 0);
2348 memcpy(ZSTR_VAL(result), ZSTR_VAL(str), ZSTR_LEN(str));
2349 memcpy(ZSTR_VAL(result) + ZSTR_LEN(str), end, endlen);
2350 ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
2351 RETURN_NEW_STR(result);
2352 }
2353
2354 if (!ZSTR_LEN(str)) {
2355 RETURN_EMPTY_STRING();
2356 }
2357
2358 result = php_chunk_split(ZSTR_VAL(str), ZSTR_LEN(str), end, endlen, (size_t)chunklen);
2359
2360 if (result) {
2361 RETURN_STR(result);
2362 } else {
2363 RETURN_FALSE;
2364 }
2365 }
2366
2367
2368
2369
2370 PHP_FUNCTION(substr)
2371 {
2372 zend_string *str;
2373 zend_long l = 0, f;
2374 int argc = ZEND_NUM_ARGS();
2375
2376 #ifndef FAST_ZPP
2377 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|l", &str, &f, &l) == FAILURE) {
2378 return;
2379 }
2380 #else
2381 ZEND_PARSE_PARAMETERS_START(2, 3)
2382 Z_PARAM_STR(str)
2383 Z_PARAM_LONG(f)
2384 Z_PARAM_OPTIONAL
2385 Z_PARAM_LONG(l)
2386 ZEND_PARSE_PARAMETERS_END();
2387 #endif
2388
2389 if (argc > 2) {
2390 if ((l < 0 && (size_t)(-l) > ZSTR_LEN(str))) {
2391 RETURN_FALSE;
2392 } else if (l > (zend_long)ZSTR_LEN(str)) {
2393 l = ZSTR_LEN(str);
2394 }
2395 } else {
2396 l = ZSTR_LEN(str);
2397 }
2398
2399 if (f > (zend_long)ZSTR_LEN(str)) {
2400 RETURN_FALSE;
2401 } else if (f < 0 && -f > ZSTR_LEN(str)) {
2402 f = 0;
2403 }
2404
2405 if (l < 0 && (l + (zend_long)ZSTR_LEN(str) - f) < 0) {
2406 RETURN_FALSE;
2407 }
2408
2409
2410
2411
2412 if (f < 0) {
2413 f = (zend_long)ZSTR_LEN(str) + f;
2414 if (f < 0) {
2415 f = 0;
2416 }
2417 }
2418
2419
2420
2421
2422 if (l < 0) {
2423 l = ((zend_long)ZSTR_LEN(str) - f) + l;
2424 if (l < 0) {
2425 l = 0;
2426 }
2427 }
2428
2429 if (f > (zend_long)ZSTR_LEN(str)) {
2430 RETURN_FALSE;
2431 }
2432
2433 if ((f + l) > (zend_long)ZSTR_LEN(str)) {
2434 l = ZSTR_LEN(str) - f;
2435 }
2436
2437 RETURN_STRINGL(ZSTR_VAL(str) + f, l);
2438 }
2439
2440
2441
2442
2443 PHP_FUNCTION(substr_replace)
2444 {
2445 zval *str;
2446 zval *from;
2447 zval *len = NULL;
2448 zval *repl;
2449 zend_long l = 0;
2450 zend_long f;
2451 int argc = ZEND_NUM_ARGS();
2452 zend_string *result;
2453 HashPosition from_idx, repl_idx, len_idx;
2454 zval *tmp_str = NULL, *tmp_from = NULL, *tmp_repl = NULL, *tmp_len= NULL;
2455
2456 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z/", &str, &repl, &from, &len) == FAILURE) {
2457 return;
2458 }
2459
2460 if (Z_TYPE_P(str) != IS_ARRAY) {
2461 convert_to_string_ex(str);
2462 }
2463 if (Z_TYPE_P(repl) != IS_ARRAY) {
2464 convert_to_string_ex(repl);
2465 }
2466 if (Z_TYPE_P(from) != IS_ARRAY) {
2467 convert_to_long_ex(from);
2468 }
2469
2470 if (argc > 3) {
2471 if (Z_TYPE_P(len) != IS_ARRAY) {
2472 l = zval_get_long(len);
2473 }
2474 } else {
2475 if (Z_TYPE_P(str) != IS_ARRAY) {
2476 l = Z_STRLEN_P(str);
2477 }
2478 }
2479
2480 if (Z_TYPE_P(str) == IS_STRING) {
2481 if (
2482 (argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
2483 (argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
2484 ) {
2485 php_error_docref(NULL, E_WARNING, "'from' and 'len' should be of same type - numerical or array ");
2486 RETURN_STR_COPY(Z_STR_P(str));
2487 }
2488 if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
2489 if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
2490 php_error_docref(NULL, E_WARNING, "'from' and 'len' should have the same number of elements");
2491 RETURN_STR_COPY(Z_STR_P(str));
2492 }
2493 }
2494 }
2495
2496 if (Z_TYPE_P(str) != IS_ARRAY) {
2497 if (Z_TYPE_P(from) != IS_ARRAY) {
2498 zend_string *repl_str;
2499 zend_bool repl_release = 0;
2500 f = Z_LVAL_P(from);
2501
2502
2503
2504
2505 if (f < 0) {
2506 f = (zend_long)Z_STRLEN_P(str) + f;
2507 if (f < 0) {
2508 f = 0;
2509 }
2510 } else if (f > Z_STRLEN_P(str)) {
2511 f = Z_STRLEN_P(str);
2512 }
2513
2514
2515
2516 if (l < 0) {
2517 l = ((zend_long)Z_STRLEN_P(str) - f) + l;
2518 if (l < 0) {
2519 l = 0;
2520 }
2521 }
2522
2523 if (l > Z_STRLEN_P(str) || (l < 0 && (size_t)(-l) > Z_STRLEN_P(str))) {
2524 l = Z_STRLEN_P(str);
2525 }
2526
2527 if ((f + l) > (zend_long)Z_STRLEN_P(str)) {
2528 l = Z_STRLEN_P(str) - f;
2529 }
2530 if (Z_TYPE_P(repl) == IS_ARRAY) {
2531 repl_idx = 0;
2532 while (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
2533 tmp_repl = &Z_ARRVAL_P(repl)->arData[repl_idx].val;
2534 if (Z_TYPE_P(tmp_repl) != IS_UNDEF) {
2535 break;
2536 }
2537 repl_idx++;
2538 }
2539 if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
2540 repl_str = zval_get_string(tmp_repl);
2541 repl_release = 1;
2542 } else {
2543 repl_str = STR_EMPTY_ALLOC();
2544 }
2545 } else {
2546 repl_str = Z_STR_P(repl);
2547 }
2548
2549 result = zend_string_alloc(Z_STRLEN_P(str) - l + ZSTR_LEN(repl_str), 0);
2550
2551 memcpy(ZSTR_VAL(result), Z_STRVAL_P(str), f);
2552 if (ZSTR_LEN(repl_str)) {
2553 memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str));
2554 }
2555 memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), Z_STRVAL_P(str) + f + l, Z_STRLEN_P(str) - f - l);
2556 ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
2557 if (repl_release) {
2558 zend_string_release(repl_str);
2559 }
2560 RETURN_NEW_STR(result);
2561 } else {
2562 php_error_docref(NULL, E_WARNING, "Functionality of 'from' and 'len' as arrays is not implemented");
2563 RETURN_STR_COPY(Z_STR_P(str));
2564 }
2565 } else {
2566 zend_string *str_index = NULL;
2567 size_t result_len;
2568 zend_ulong num_index;
2569
2570 array_init(return_value);
2571
2572 from_idx = len_idx = repl_idx = 0;
2573
2574 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(str), num_index, str_index, tmp_str) {
2575 zend_string *orig_str = zval_get_string(tmp_str);
2576
2577 if (Z_TYPE_P(from) == IS_ARRAY) {
2578 while (from_idx < Z_ARRVAL_P(from)->nNumUsed) {
2579 tmp_from = &Z_ARRVAL_P(from)->arData[from_idx].val;
2580 if (Z_TYPE_P(tmp_from) != IS_UNDEF) {
2581 break;
2582 }
2583 from_idx++;
2584 }
2585 if (from_idx < Z_ARRVAL_P(from)->nNumUsed) {
2586 f = zval_get_long(tmp_from);
2587
2588 if (f < 0) {
2589 f = (zend_long)ZSTR_LEN(orig_str) + f;
2590 if (f < 0) {
2591 f = 0;
2592 }
2593 } else if (f > (zend_long)ZSTR_LEN(orig_str)) {
2594 f = ZSTR_LEN(orig_str);
2595 }
2596 from_idx++;
2597 } else {
2598 f = 0;
2599 }
2600 } else {
2601 f = Z_LVAL_P(from);
2602 if (f < 0) {
2603 f = (zend_long)ZSTR_LEN(orig_str) + f;
2604 if (f < 0) {
2605 f = 0;
2606 }
2607 } else if (f > (zend_long)ZSTR_LEN(orig_str)) {
2608 f = ZSTR_LEN(orig_str);
2609 }
2610 }
2611
2612 if (argc > 3 && Z_TYPE_P(len) == IS_ARRAY) {
2613 while (len_idx < Z_ARRVAL_P(len)->nNumUsed) {
2614 tmp_len = &Z_ARRVAL_P(len)->arData[len_idx].val;
2615 if (Z_TYPE_P(tmp_len) != IS_UNDEF) {
2616 break;
2617 }
2618 len_idx++;
2619 }
2620 if (len_idx < Z_ARRVAL_P(len)->nNumUsed) {
2621 l = zval_get_long(tmp_len);
2622 len_idx++;
2623 } else {
2624 l = ZSTR_LEN(orig_str);
2625 }
2626 } else if (argc > 3) {
2627 l = Z_LVAL_P(len);
2628 } else {
2629 l = ZSTR_LEN(orig_str);
2630 }
2631
2632 if (l < 0) {
2633 l = (ZSTR_LEN(orig_str) - f) + l;
2634 if (l < 0) {
2635 l = 0;
2636 }
2637 }
2638
2639 if ((f + l) > (zend_long)ZSTR_LEN(orig_str)) {
2640 l = ZSTR_LEN(orig_str) - f;
2641 }
2642
2643 result_len = ZSTR_LEN(orig_str) - l;
2644
2645 if (Z_TYPE_P(repl) == IS_ARRAY) {
2646 while (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
2647 tmp_repl = &Z_ARRVAL_P(repl)->arData[repl_idx].val;
2648 if (Z_TYPE_P(tmp_repl) != IS_UNDEF) {
2649 break;
2650 }
2651 repl_idx++;
2652 }
2653 if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
2654 zend_string *repl_str = zval_get_string(tmp_repl);
2655
2656 result_len += ZSTR_LEN(repl_str);
2657 repl_idx++;
2658 result = zend_string_alloc(result_len, 0);
2659
2660 memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
2661 memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str));
2662 memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
2663 zend_string_release(repl_str);
2664 } else {
2665 result = zend_string_alloc(result_len, 0);
2666
2667 memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
2668 memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
2669 }
2670 } else {
2671 result_len += Z_STRLEN_P(repl);
2672
2673 result = zend_string_alloc(result_len, 0);
2674
2675 memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
2676 memcpy((ZSTR_VAL(result) + f), Z_STRVAL_P(repl), Z_STRLEN_P(repl));
2677 memcpy((ZSTR_VAL(result) + f + Z_STRLEN_P(repl)), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
2678 }
2679
2680 ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
2681
2682 if (str_index) {
2683 zval tmp;
2684
2685 ZVAL_NEW_STR(&tmp, result);
2686 zend_symtable_update(Z_ARRVAL_P(return_value), str_index, &tmp);
2687 } else {
2688 add_index_str(return_value, num_index, result);
2689 }
2690
2691 zend_string_release(orig_str);
2692 } ZEND_HASH_FOREACH_END();
2693 }
2694 }
2695
2696
2697
2698
2699 PHP_FUNCTION(quotemeta)
2700 {
2701 zend_string *old;
2702 char *old_end;
2703 char *p, *q;
2704 char c;
2705 zend_string *str;
2706
2707 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &old) == FAILURE) {
2708 return;
2709 }
2710
2711 old_end = ZSTR_VAL(old) + ZSTR_LEN(old);
2712
2713 if (ZSTR_VAL(old) == old_end) {
2714 RETURN_FALSE;
2715 }
2716
2717 str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0);
2718
2719 for (p = ZSTR_VAL(old), q = ZSTR_VAL(str); p != old_end; p++) {
2720 c = *p;
2721 switch (c) {
2722 case '.':
2723 case '\\':
2724 case '+':
2725 case '*':
2726 case '?':
2727 case '[':
2728 case '^':
2729 case ']':
2730 case '$':
2731 case '(':
2732 case ')':
2733 *q++ = '\\';
2734
2735 default:
2736 *q++ = c;
2737 }
2738 }
2739
2740 *q = '\0';
2741
2742 RETURN_NEW_STR(zend_string_truncate(str, q - ZSTR_VAL(str), 0));
2743 }
2744
2745
2746
2747
2748 PHP_FUNCTION(ord)
2749 {
2750 char *str;
2751 size_t str_len;
2752
2753 #ifndef FAST_ZPP
2754 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) {
2755 return;
2756 }
2757 #else
2758 ZEND_PARSE_PARAMETERS_START(1, 1)
2759 Z_PARAM_STRING(str, str_len)
2760 ZEND_PARSE_PARAMETERS_END();
2761 #endif
2762
2763 RETURN_LONG((unsigned char) str[0]);
2764 }
2765
2766
2767
2768
2769 PHP_FUNCTION(chr)
2770 {
2771 zend_long c;
2772
2773 if (ZEND_NUM_ARGS() != 1) {
2774 WRONG_PARAM_COUNT;
2775 }
2776
2777 #ifndef FAST_ZPP
2778 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l", &c) == FAILURE) {
2779 c = 0;
2780 }
2781 #else
2782 ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_QUIET, 1, 1)
2783 Z_PARAM_LONG(c)
2784 ZEND_PARSE_PARAMETERS_END_EX(c = 0);
2785 #endif
2786
2787 c &= 0xff;
2788 if (CG(one_char_string)[c]) {
2789 ZVAL_INTERNED_STR(return_value, CG(one_char_string)[c]);
2790 } else {
2791 ZVAL_NEW_STR(return_value, zend_string_alloc(1, 0));
2792 Z_STRVAL_P(return_value)[0] = (char)c;
2793 Z_STRVAL_P(return_value)[1] = '\0';
2794 }
2795 }
2796
2797
2798
2799
2800 static void php_ucfirst(char *str)
2801 {
2802 register char *r;
2803 r = str;
2804 *r = toupper((unsigned char) *r);
2805 }
2806
2807
2808
2809
2810 PHP_FUNCTION(ucfirst)
2811 {
2812 zend_string *str;
2813
2814 #ifndef FAST_ZPP
2815 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
2816 return;
2817 }
2818 #else
2819 ZEND_PARSE_PARAMETERS_START(1, 1)
2820 Z_PARAM_STR(str)
2821 ZEND_PARSE_PARAMETERS_END();
2822 #endif
2823
2824 if (!ZSTR_LEN(str)) {
2825 RETURN_EMPTY_STRING();
2826 }
2827
2828 ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
2829 php_ucfirst(Z_STRVAL_P(return_value));
2830 }
2831
2832
2833
2834
2835 static void php_lcfirst(char *str)
2836 {
2837 register char *r;
2838 r = str;
2839 *r = tolower((unsigned char) *r);
2840 }
2841
2842
2843
2844
2845 PHP_FUNCTION(lcfirst)
2846 {
2847 zend_string *str;
2848
2849 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
2850 return;
2851 }
2852
2853 if (!ZSTR_LEN(str)) {
2854 RETURN_EMPTY_STRING();
2855 }
2856
2857 ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
2858 php_lcfirst(Z_STRVAL_P(return_value));
2859 }
2860
2861
2862
2863
2864 PHP_FUNCTION(ucwords)
2865 {
2866 zend_string *str;
2867 char *delims = " \t\r\n\f\v";
2868 register char *r, *r_end;
2869 size_t delims_len = 6;
2870 char mask[256];
2871
2872 #ifndef FAST_ZPP
2873 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|s", &str, &delims, &delims_len) == FAILURE) {
2874 return;
2875 }
2876 #else
2877 ZEND_PARSE_PARAMETERS_START(1, 2)
2878 Z_PARAM_STR(str)
2879 Z_PARAM_OPTIONAL
2880 Z_PARAM_STRING(delims, delims_len)
2881 ZEND_PARSE_PARAMETERS_END();
2882 #endif
2883
2884 if (!ZSTR_LEN(str)) {
2885 RETURN_EMPTY_STRING();
2886 }
2887
2888 php_charmask((unsigned char *)delims, delims_len, mask);
2889
2890 ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
2891 r = Z_STRVAL_P(return_value);
2892
2893 *r = toupper((unsigned char) *r);
2894 for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
2895 if (mask[(unsigned char)*r++]) {
2896 *r = toupper((unsigned char) *r);
2897 }
2898 }
2899 }
2900
2901
2902
2903
2904 PHPAPI char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen)
2905 {
2906 size_t i;
2907
2908 if (UNEXPECTED(trlen < 1)) {
2909 return str;
2910 } else if (trlen == 1) {
2911 char ch_from = *str_from;
2912 char ch_to = *str_to;
2913
2914 for (i = 0; i < len; i++) {
2915 if (str[i] == ch_from) {
2916 str[i] = ch_to;
2917 }
2918 }
2919 } else {
2920 unsigned char xlat[256], j = 0;
2921
2922 do { xlat[j] = j; } while (++j != 0);
2923
2924 for (i = 0; i < trlen; i++) {
2925 xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
2926 }
2927
2928 for (i = 0; i < len; i++) {
2929 str[i] = xlat[(size_t)(unsigned char) str[i]];
2930 }
2931 }
2932
2933 return str;
2934 }
2935
2936
2937
2938
2939 static zend_string *php_strtr_ex(zend_string *str, char *str_from, char *str_to, size_t trlen)
2940 {
2941 zend_string *new_str = NULL;
2942 size_t i;
2943
2944 if (UNEXPECTED(trlen < 1)) {
2945 return zend_string_copy(str);
2946 } else if (trlen == 1) {
2947 char ch_from = *str_from;
2948 char ch_to = *str_to;
2949
2950 for (i = 0; i < ZSTR_LEN(str); i++) {
2951 if (ZSTR_VAL(str)[i] == ch_from) {
2952 new_str = zend_string_alloc(ZSTR_LEN(str), 0);
2953 memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);
2954 ZSTR_VAL(new_str)[i] = ch_to;
2955 break;
2956 }
2957 }
2958 for (; i < ZSTR_LEN(str); i++) {
2959 ZSTR_VAL(new_str)[i] = (ZSTR_VAL(str)[i] != ch_from) ? ZSTR_VAL(str)[i] : ch_to;
2960 }
2961 } else {
2962 unsigned char xlat[256], j = 0;
2963
2964 do { xlat[j] = j; } while (++j != 0);
2965
2966 for (i = 0; i < trlen; i++) {
2967 xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
2968 }
2969
2970 for (i = 0; i < ZSTR_LEN(str); i++) {
2971 if (ZSTR_VAL(str)[i] != xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]]) {
2972 new_str = zend_string_alloc(ZSTR_LEN(str), 0);
2973 memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);
2974 ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
2975 break;
2976 }
2977 }
2978
2979 for (;i < ZSTR_LEN(str); i++) {
2980 ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
2981 }
2982 }
2983
2984 if (!new_str) {
2985 return zend_string_copy(str);
2986 }
2987
2988 ZSTR_VAL(new_str)[ZSTR_LEN(new_str)] = 0;
2989 return new_str;
2990 }
2991
2992
2993
2994 static void php_strtr_array(zval *return_value, zend_string *input, HashTable *pats)
2995 {
2996 char *str = ZSTR_VAL(input);
2997 size_t slen = ZSTR_LEN(input);
2998 zend_ulong num_key;
2999 zend_string *str_key;
3000 size_t len, pos, old_pos;
3001 int num_keys = 0;
3002 size_t minlen = 128*1024;
3003 size_t maxlen = 0;
3004 HashTable str_hash;
3005 zval *entry;
3006 char *key;
3007 smart_str result = {0};
3008 zend_ulong bitset[256/sizeof(zend_ulong)];
3009 zend_ulong *num_bitset;
3010
3011
3012 num_bitset = ecalloc((slen + sizeof(zend_ulong)) / sizeof(zend_ulong), sizeof(zend_ulong));
3013 memset(bitset, 0, sizeof(bitset));
3014
3015
3016 ZEND_HASH_FOREACH_STR_KEY(pats, str_key) {
3017 if (UNEXPECTED(!str_key)) {
3018 num_keys = 1;
3019 } else {
3020 len = ZSTR_LEN(str_key);
3021 if (UNEXPECTED(len < 1)) {
3022 RETURN_FALSE;
3023 } else if (UNEXPECTED(len > slen)) {
3024
3025 continue;
3026 }
3027 if (len > maxlen) {
3028 maxlen = len;
3029 }
3030 if (len < minlen) {
3031 minlen = len;
3032 }
3033
3034 num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));
3035 bitset[((unsigned char)ZSTR_VAL(str_key)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(str_key)[0]) % sizeof(zend_ulong));
3036 }
3037 } ZEND_HASH_FOREACH_END();
3038
3039 if (UNEXPECTED(num_keys)) {
3040 zend_string *key_used;
3041
3042 zend_hash_init(&str_hash, zend_hash_num_elements(pats), NULL, NULL, 0);
3043 ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
3044 if (UNEXPECTED(!str_key)) {
3045 key_used = zend_long_to_str(num_key);
3046 len = ZSTR_LEN(key_used);
3047 if (UNEXPECTED(len > slen)) {
3048
3049 continue;
3050 }
3051 if (len > maxlen) {
3052 maxlen = len;
3053 }
3054 if (len < minlen) {
3055 minlen = len;
3056 }
3057
3058 num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));
3059 bitset[((unsigned char)ZSTR_VAL(key_used)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(key_used)[0]) % sizeof(zend_ulong));
3060 } else {
3061 key_used = str_key;
3062 len = ZSTR_LEN(key_used);
3063 if (UNEXPECTED(len > slen)) {
3064
3065 continue;
3066 }
3067 }
3068 zend_hash_add(&str_hash, key_used, entry);
3069 if (UNEXPECTED(!str_key)) {
3070 zend_string_release(key_used);
3071 }
3072 } ZEND_HASH_FOREACH_END();
3073 pats = &str_hash;
3074 }
3075
3076 if (UNEXPECTED(minlen > maxlen)) {
3077
3078 if (pats == &str_hash) {
3079 zend_hash_destroy(&str_hash);
3080 }
3081 efree(num_bitset);
3082 RETURN_STR_COPY(input);
3083 }
3084
3085 old_pos = pos = 0;
3086 while (pos <= slen - minlen) {
3087 key = str + pos;
3088 if (bitset[((unsigned char)key[0]) / sizeof(zend_ulong)] & (Z_UL(1) << (((unsigned char)key[0]) % sizeof(zend_ulong)))) {
3089 len = maxlen;
3090 if (len > slen - pos) {
3091 len = slen - pos;
3092 }
3093 while (len >= minlen) {
3094 if ((num_bitset[len / sizeof(zend_ulong)] & (Z_UL(1) << (len % sizeof(zend_ulong))))) {
3095 entry = zend_hash_str_find(pats, key, len);
3096 if (entry != NULL) {
3097 zend_string *s = zval_get_string(entry);
3098 smart_str_appendl(&result, str + old_pos, pos - old_pos);
3099 smart_str_append(&result, s);
3100 old_pos = pos + len;
3101 pos = old_pos - 1;
3102 zend_string_release(s);
3103 break;
3104 }
3105 }
3106 len--;
3107 }
3108 }
3109 pos++;
3110 }
3111
3112 if (result.s) {
3113 smart_str_appendl(&result, str + old_pos, slen - old_pos);
3114 smart_str_0(&result);
3115 RETVAL_NEW_STR(result.s);
3116 } else {
3117 smart_str_free(&result);
3118 RETVAL_STR_COPY(input);
3119 }
3120
3121 if (pats == &str_hash) {
3122 zend_hash_destroy(&str_hash);
3123 }
3124 efree(num_bitset);
3125 }
3126
3127
3128
3129
3130 static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, size_t to_len, int case_sensitivity, zend_long *replace_count)
3131 {
3132 zend_string *result;
3133 size_t char_count = 0;
3134 char lc_from = 0;
3135 char *source, *target, *source_end= ZSTR_VAL(str) + ZSTR_LEN(str);
3136
3137 if (case_sensitivity) {
3138 char *p = ZSTR_VAL(str), *e = p + ZSTR_LEN(str);
3139 while ((p = memchr(p, from, (e - p)))) {
3140 char_count++;
3141 p++;
3142 }
3143 } else {
3144 lc_from = tolower(from);
3145 for (source = ZSTR_VAL(str); source < source_end; source++) {
3146 if (tolower(*source) == lc_from) {
3147 char_count++;
3148 }
3149 }
3150 }
3151
3152 if (char_count == 0) {
3153 return zend_string_copy(str);
3154 }
3155
3156 if (to_len > 0) {
3157 result = zend_string_safe_alloc(char_count, to_len - 1, ZSTR_LEN(str), 0);
3158 } else {
3159 result = zend_string_alloc(ZSTR_LEN(str) - char_count, 0);
3160 }
3161 target = ZSTR_VAL(result);
3162
3163 if (case_sensitivity) {
3164 char *p = ZSTR_VAL(str), *e = p + ZSTR_LEN(str), *s = ZSTR_VAL(str);
3165 while ((p = memchr(p, from, (e - p)))) {
3166 memcpy(target, s, (p - s));
3167 target += p - s;
3168 memcpy(target, to, to_len);
3169 target += to_len;
3170 p++;
3171 s = p;
3172 if (replace_count) {
3173 *replace_count += 1;
3174 }
3175 }
3176 if (s < e) {
3177 memcpy(target, s, (e - s));
3178 target += e - s;
3179 }
3180 } else {
3181 for (source = ZSTR_VAL(str); source < source_end; source++) {
3182 if (tolower(*source) == lc_from) {
3183 if (replace_count) {
3184 *replace_count += 1;
3185 }
3186 memcpy(target, to, to_len);
3187 target += to_len;
3188 } else {
3189 *target = *source;
3190 target++;
3191 }
3192 }
3193 }
3194 *target = 0;
3195 return result;
3196 }
3197
3198
3199
3200
3201 static zend_string *php_str_to_str_ex(zend_string *haystack,
3202 char *needle, size_t needle_len, char *str, size_t str_len, zend_long *replace_count)
3203 {
3204 zend_string *new_str;
3205
3206 if (needle_len < ZSTR_LEN(haystack)) {
3207 char *end;
3208 char *e, *s, *p, *r;
3209
3210 if (needle_len == str_len) {
3211 new_str = NULL;
3212 end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
3213 for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
3214 if (!new_str) {
3215 new_str = zend_string_init(ZSTR_VAL(haystack), ZSTR_LEN(haystack), 0);
3216 }
3217 memcpy(ZSTR_VAL(new_str) + (r - ZSTR_VAL(haystack)), str, str_len);
3218 (*replace_count)++;
3219 }
3220 if (!new_str) {
3221 goto nothing_todo;
3222 }
3223 return new_str;
3224 } else {
3225 size_t count = 0;
3226 char *o = ZSTR_VAL(haystack);
3227 char *n = needle;
3228 char *endp = o + ZSTR_LEN(haystack);
3229
3230 while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
3231 o += needle_len;
3232 count++;
3233 }
3234 if (count == 0) {
3235
3236 goto nothing_todo;
3237 }
3238 if (str_len > needle_len) {
3239 new_str = zend_string_safe_alloc(count, str_len - needle_len, ZSTR_LEN(haystack), 0);
3240 } else {
3241 new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0);
3242 }
3243
3244 e = s = ZSTR_VAL(new_str);
3245 end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
3246 for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
3247 memcpy(e, p, r - p);
3248 e += r - p;
3249 memcpy(e, str, str_len);
3250 e += str_len;
3251 (*replace_count)++;
3252 }
3253
3254 if (p < end) {
3255 memcpy(e, p, end - p);
3256 e += end - p;
3257 }
3258
3259 *e = '\0';
3260 return new_str;
3261 }
3262 } else if (needle_len > ZSTR_LEN(haystack) || memcmp(ZSTR_VAL(haystack), needle, ZSTR_LEN(haystack))) {
3263 nothing_todo:
3264 return zend_string_copy(haystack);
3265 } else {
3266 new_str = zend_string_init(str, str_len, 0);
3267 (*replace_count)++;
3268 return new_str;
3269 }
3270 }
3271
3272
3273
3274
3275 static zend_string *php_str_to_str_i_ex(zend_string *haystack, char *lc_haystack,
3276 zend_string *needle, char *str, size_t str_len, zend_long *replace_count)
3277 {
3278 zend_string *new_str = NULL;
3279 zend_string *lc_needle;
3280
3281 if (ZSTR_LEN(needle) < ZSTR_LEN(haystack)) {
3282 char *end;
3283 char *e, *s, *p, *r;
3284
3285 if (ZSTR_LEN(needle) == str_len) {
3286 lc_needle = php_string_tolower(needle);
3287 end = lc_haystack + ZSTR_LEN(haystack);
3288 for (p = lc_haystack; (r = (char*)php_memnstr(p, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle), end)); p = r + ZSTR_LEN(lc_needle)) {
3289 if (!new_str) {
3290 new_str = zend_string_init(ZSTR_VAL(haystack), ZSTR_LEN(haystack), 0);
3291 }
3292 memcpy(ZSTR_VAL(new_str) + (r - lc_haystack), str, str_len);
3293 (*replace_count)++;
3294 }
3295 zend_string_release(lc_needle);
3296
3297 if (!new_str) {
3298 goto nothing_todo;
3299 }
3300 return new_str;
3301 } else {
3302 size_t count = 0;
3303 char *o = lc_haystack;
3304 char *n;
3305 char *endp = o + ZSTR_LEN(haystack);
3306
3307 lc_needle = php_string_tolower(needle);
3308 n = ZSTR_VAL(lc_needle);
3309
3310 while ((o = (char*)php_memnstr(o, n, ZSTR_LEN(lc_needle), endp))) {
3311 o += ZSTR_LEN(lc_needle);
3312 count++;
3313 }
3314 if (count == 0) {
3315
3316 zend_string_release(lc_needle);
3317 goto nothing_todo;
3318 }
3319
3320 if (str_len > ZSTR_LEN(lc_needle)) {
3321 new_str = zend_string_safe_alloc(count, str_len - ZSTR_LEN(lc_needle), ZSTR_LEN(haystack), 0);
3322 } else {
3323 new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0);
3324 }
3325
3326 e = s = ZSTR_VAL(new_str);
3327 end = lc_haystack + ZSTR_LEN(haystack);
3328
3329 for (p = lc_haystack; (r = (char*)php_memnstr(p, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle), end)); p = r + ZSTR_LEN(lc_needle)) {
3330 memcpy(e, ZSTR_VAL(haystack) + (p - lc_haystack), r - p);
3331 e += r - p;
3332 memcpy(e, str, str_len);
3333 e += str_len;
3334 (*replace_count)++;
3335 }
3336
3337 if (p < end) {
3338 memcpy(e, ZSTR_VAL(haystack) + (p - lc_haystack), end - p);
3339 e += end - p;
3340 }
3341 *e = '\0';
3342
3343 zend_string_release(lc_needle);
3344
3345 return new_str;
3346 }
3347 } else if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) {
3348 nothing_todo:
3349 return zend_string_copy(haystack);
3350 } else {
3351 lc_needle = php_string_tolower(needle);
3352
3353 if (memcmp(lc_haystack, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle))) {
3354 zend_string_release(lc_needle);
3355 goto nothing_todo;
3356 }
3357 zend_string_release(lc_needle);
3358
3359 new_str = zend_string_init(str, str_len, 0);
3360
3361 (*replace_count)++;
3362 return new_str;
3363 }
3364 }
3365
3366
3367
3368
3369 PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle, size_t needle_len, char *str, size_t str_len)
3370 {
3371 zend_string *new_str;
3372
3373 if (needle_len < length) {
3374 char *end;
3375 char *e, *s, *p, *r;
3376
3377 if (needle_len == str_len) {
3378 new_str = zend_string_init(haystack, length, 0);
3379 end = ZSTR_VAL(new_str) + length;
3380 for (p = ZSTR_VAL(new_str); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
3381 memcpy(r, str, str_len);
3382 }
3383 return new_str;
3384 } else {
3385 if (str_len < needle_len) {
3386 new_str = zend_string_alloc(length, 0);
3387 } else {
3388 size_t count = 0;
3389 char *o = haystack;
3390 char *n = needle;
3391 char *endp = o + length;
3392
3393 while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
3394 o += needle_len;
3395 count++;
3396 }
3397 if (count == 0) {
3398
3399 new_str = zend_string_init(haystack, length, 0);
3400 return new_str;
3401 } else {
3402 if (str_len > needle_len) {
3403 new_str = zend_string_safe_alloc(count, str_len - needle_len, length, 0);
3404 } else {
3405 new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0);
3406 }
3407 }
3408 }
3409
3410 e = s = ZSTR_VAL(new_str);
3411 end = haystack + length;
3412 for (p = haystack; (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
3413 memcpy(e, p, r - p);
3414 e += r - p;
3415 memcpy(e, str, str_len);
3416 e += str_len;
3417 }
3418
3419 if (p < end) {
3420 memcpy(e, p, end - p);
3421 e += end - p;
3422 }
3423
3424 *e = '\0';
3425 new_str = zend_string_truncate(new_str, e - s, 0);
3426 return new_str;
3427 }
3428 } else if (needle_len > length || memcmp(haystack, needle, length)) {
3429 new_str = zend_string_init(haystack, length, 0);
3430 return new_str;
3431 } else {
3432 new_str = zend_string_init(str, str_len, 0);
3433
3434 return new_str;
3435 }
3436 }
3437
3438
3439
3440
3441 PHP_FUNCTION(strtr)
3442 {
3443 zval *from;
3444 zend_string *str;
3445 char *to = NULL;
3446 size_t to_len = 0;
3447 int ac = ZEND_NUM_ARGS();
3448
3449 #ifndef FAST_ZPP
3450 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|s", &str, &from, &to, &to_len) == FAILURE) {
3451 return;
3452 }
3453 #else
3454 ZEND_PARSE_PARAMETERS_START(2, 3)
3455 Z_PARAM_STR(str)
3456 Z_PARAM_ZVAL(from)
3457 Z_PARAM_OPTIONAL
3458 Z_PARAM_STRING(to, to_len)
3459 ZEND_PARSE_PARAMETERS_END();
3460 #endif
3461
3462 if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
3463 php_error_docref(NULL, E_WARNING, "The second argument is not an array");
3464 RETURN_FALSE;
3465 }
3466
3467
3468 if (ZSTR_LEN(str) == 0) {
3469 RETURN_EMPTY_STRING();
3470 }
3471
3472 if (ac == 2) {
3473 HashTable *pats = Z_ARRVAL_P(from);
3474
3475 if (zend_hash_num_elements(pats) < 1) {
3476 RETURN_STR_COPY(str);
3477 } else if (zend_hash_num_elements(pats) == 1) {
3478 zend_long num_key;
3479 zend_string *str_key, *replace;
3480 zval *entry, tmp;
3481
3482 ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
3483 ZVAL_UNDEF(&tmp);
3484 if (UNEXPECTED(!str_key)) {
3485 ZVAL_LONG(&tmp, num_key);
3486 convert_to_string(&tmp);
3487 str_key = Z_STR(tmp);
3488 }
3489 replace = zval_get_string(entry);
3490 if (ZSTR_LEN(str_key) < 1) {
3491 RETVAL_STR_COPY(str);
3492 } else if (ZSTR_LEN(str_key) == 1) {
3493 RETVAL_STR(php_char_to_str_ex(str,
3494 ZSTR_VAL(str_key)[0],
3495 ZSTR_VAL(replace),
3496 ZSTR_LEN(replace),
3497 1,
3498 NULL));
3499 } else {
3500 zend_long dummy;
3501 RETVAL_STR(php_str_to_str_ex(str,
3502 ZSTR_VAL(str_key), ZSTR_LEN(str_key),
3503 ZSTR_VAL(replace), ZSTR_LEN(replace), &dummy));
3504 }
3505 zend_string_release(replace);
3506 zval_dtor(&tmp);
3507 return;
3508 } ZEND_HASH_FOREACH_END();
3509 } else {
3510 php_strtr_array(return_value, str, pats);
3511 }
3512 } else {
3513 convert_to_string_ex(from);
3514
3515 RETURN_STR(php_strtr_ex(str,
3516 Z_STRVAL_P(from),
3517 to,
3518 MIN(Z_STRLEN_P(from), to_len)));
3519 }
3520 }
3521
3522
3523
3524
3525 PHP_FUNCTION(strrev)
3526 {
3527 zend_string *str;
3528 char *e, *p;
3529 zend_string *n;
3530
3531 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
3532 return;
3533 }
3534
3535 n = zend_string_alloc(ZSTR_LEN(str), 0);
3536 p = ZSTR_VAL(n);
3537
3538 e = ZSTR_VAL(str) + ZSTR_LEN(str);
3539
3540 while (--e >= ZSTR_VAL(str)) {
3541 *p++ = *e;
3542 }
3543
3544 *p = '\0';
3545
3546 RETVAL_NEW_STR(n);
3547 }
3548
3549
3550
3551
3552 static void php_similar_str(const char *txt1, size_t len1, const char *txt2, size_t len2, size_t *pos1, size_t *pos2, size_t *max)
3553 {
3554 char *p, *q;
3555 char *end1 = (char *) txt1 + len1;
3556 char *end2 = (char *) txt2 + len2;
3557 size_t l;
3558
3559 *max = 0;
3560 for (p = (char *) txt1; p < end1; p++) {
3561 for (q = (char *) txt2; q < end2; q++) {
3562 for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
3563 if (l > *max) {
3564 *max = l;
3565 *pos1 = p - txt1;
3566 *pos2 = q - txt2;
3567 }
3568 }
3569 }
3570 }
3571
3572
3573
3574
3575 static size_t php_similar_char(const char *txt1, size_t len1, const char *txt2, size_t len2)
3576 {
3577 size_t sum;
3578 size_t pos1 = 0, pos2 = 0, max;
3579
3580 php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max);
3581 if ((sum = max)) {
3582 if (pos1 && pos2) {
3583 sum += php_similar_char(txt1, pos1,
3584 txt2, pos2);
3585 }
3586 if ((pos1 + max < len1) && (pos2 + max < len2)) {
3587 sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
3588 txt2 + pos2 + max, len2 - pos2 - max);
3589 }
3590 }
3591
3592 return sum;
3593 }
3594
3595
3596
3597
3598 PHP_FUNCTION(similar_text)
3599 {
3600 zend_string *t1, *t2;
3601 zval *percent = NULL;
3602 int ac = ZEND_NUM_ARGS();
3603 size_t sim;
3604
3605 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|z/", &t1, &t2, &percent) == FAILURE) {
3606 return;
3607 }
3608
3609 if (ac > 2) {
3610 convert_to_double_ex(percent);
3611 }
3612
3613 if (ZSTR_LEN(t1) + ZSTR_LEN(t2) == 0) {
3614 if (ac > 2) {
3615 Z_DVAL_P(percent) = 0;
3616 }
3617
3618 RETURN_LONG(0);
3619 }
3620
3621 sim = php_similar_char(ZSTR_VAL(t1), ZSTR_LEN(t1), ZSTR_VAL(t2), ZSTR_LEN(t2));
3622
3623 if (ac > 2) {
3624 Z_DVAL_P(percent) = sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2));
3625 }
3626
3627 RETURN_LONG(sim);
3628 }
3629
3630
3631
3632
3633
3634 PHPAPI void php_stripslashes(zend_string *str)
3635 {
3636 char *s, *t;
3637 size_t l;
3638
3639 s = ZSTR_VAL(str);
3640 t = ZSTR_VAL(str);
3641 l = ZSTR_LEN(str);
3642
3643 while (l > 0) {
3644 if (*t == '\\') {
3645 t++;
3646 ZSTR_LEN(str)--;
3647 l--;
3648 if (l > 0) {
3649 if (*t == '0') {
3650 *s++='\0';
3651 t++;
3652 } else {
3653 *s++ = *t++;
3654 }
3655 l--;
3656 }
3657 } else {
3658 *s++ = *t++;
3659 l--;
3660 }
3661 }
3662 if (s != t) {
3663 *s = '\0';
3664 }
3665 }
3666
3667
3668
3669
3670 PHP_FUNCTION(addcslashes)
3671 {
3672 zend_string *str, *what;
3673
3674 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &str, &what) == FAILURE) {
3675 return;
3676 }
3677
3678 if (ZSTR_LEN(str) == 0) {
3679 RETURN_EMPTY_STRING();
3680 }
3681
3682 if (ZSTR_LEN(what) == 0) {
3683 RETURN_STRINGL(ZSTR_VAL(str), ZSTR_LEN(str));
3684 }
3685
3686 RETURN_STR(php_addcslashes(str, 0, ZSTR_VAL(what), ZSTR_LEN(what)));
3687 }
3688
3689
3690
3691
3692 PHP_FUNCTION(addslashes)
3693 {
3694 zend_string *str;
3695
3696 #ifndef FAST_ZPP
3697 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
3698 return;
3699 }
3700 #else
3701 ZEND_PARSE_PARAMETERS_START(1, 1)
3702 Z_PARAM_STR(str)
3703 ZEND_PARSE_PARAMETERS_END();
3704 #endif
3705
3706 if (ZSTR_LEN(str) == 0) {
3707 RETURN_EMPTY_STRING();
3708 }
3709
3710 RETURN_STR(php_addslashes(str, 0));
3711 }
3712
3713
3714
3715
3716 PHP_FUNCTION(stripcslashes)
3717 {
3718 zend_string *str;
3719
3720 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
3721 return;
3722 }
3723
3724 ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
3725 php_stripcslashes(Z_STR_P(return_value));
3726 }
3727
3728
3729
3730
3731 PHP_FUNCTION(stripslashes)
3732 {
3733 zend_string *str;
3734
3735 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
3736 return;
3737 }
3738
3739 ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
3740 php_stripslashes(Z_STR_P(return_value));
3741 }
3742
3743
3744 #ifndef HAVE_STRERROR
3745
3746
3747 char *php_strerror(int errnum)
3748 {
3749 extern int sys_nerr;
3750 extern char *sys_errlist[];
3751
3752 if ((unsigned int) errnum < sys_nerr) {
3753 return(sys_errlist[errnum]);
3754 }
3755
3756 (void) snprintf(BG(str_ebuf), sizeof(php_basic_globals.str_ebuf), "Unknown error: %d", errnum);
3757 return(BG(str_ebuf));
3758 }
3759
3760 #endif
3761
3762
3763
3764 PHPAPI void php_stripcslashes(zend_string *str)
3765 {
3766 char *source, *target, *end;
3767 size_t nlen = ZSTR_LEN(str), i;
3768 char numtmp[4];
3769
3770 for (source = (char*)ZSTR_VAL(str), end = source + ZSTR_LEN(str), target = ZSTR_VAL(str); source < end; source++) {
3771 if (*source == '\\' && source + 1 < end) {
3772 source++;
3773 switch (*source) {
3774 case 'n': *target++='\n'; nlen--; break;
3775 case 'r': *target++='\r'; nlen--; break;
3776 case 'a': *target++='\a'; nlen--; break;
3777 case 't': *target++='\t'; nlen--; break;
3778 case 'v': *target++='\v'; nlen--; break;
3779 case 'b': *target++='\b'; nlen--; break;
3780 case 'f': *target++='\f'; nlen--; break;
3781 case '\\': *target++='\\'; nlen--; break;
3782 case 'x':
3783 if (source+1 < end && isxdigit((int)(*(source+1)))) {
3784 numtmp[0] = *++source;
3785 if (source+1 < end && isxdigit((int)(*(source+1)))) {
3786 numtmp[1] = *++source;
3787 numtmp[2] = '\0';
3788 nlen-=3;
3789 } else {
3790 numtmp[1] = '\0';
3791 nlen-=2;
3792 }
3793 *target++=(char)strtol(numtmp, NULL, 16);
3794 break;
3795 }
3796
3797 default:
3798 i=0;
3799 while (source < end && *source >= '0' && *source <= '7' && i<3) {
3800 numtmp[i++] = *source++;
3801 }
3802 if (i) {
3803 numtmp[i]='\0';
3804 *target++=(char)strtol(numtmp, NULL, 8);
3805 nlen-=i;
3806 source--;
3807 } else {
3808 *target++=*source;
3809 nlen--;
3810 }
3811 }
3812 } else {
3813 *target++=*source;
3814 }
3815 }
3816
3817 if (nlen != 0) {
3818 *target='\0';
3819 }
3820
3821 ZSTR_LEN(str) = nlen;
3822 }
3823
3824
3825
3826
3827 PHPAPI zend_string *php_addcslashes(zend_string *str, int should_free, char *what, size_t wlength)
3828 {
3829 char flags[256];
3830 char *source, *target;
3831 char *end;
3832 char c;
3833 size_t newlen;
3834 zend_string *new_str = zend_string_safe_alloc(4, ZSTR_LEN(str), 0, 0);
3835
3836 php_charmask((unsigned char *)what, wlength, flags);
3837
3838 for (source = (char*)ZSTR_VAL(str), end = source + ZSTR_LEN(str), target = ZSTR_VAL(new_str); source < end; source++) {
3839 c = *source;
3840 if (flags[(unsigned char)c]) {
3841 if ((unsigned char) c < 32 || (unsigned char) c > 126) {
3842 *target++ = '\\';
3843 switch (c) {
3844 case '\n': *target++ = 'n'; break;
3845 case '\t': *target++ = 't'; break;
3846 case '\r': *target++ = 'r'; break;
3847 case '\a': *target++ = 'a'; break;
3848 case '\v': *target++ = 'v'; break;
3849 case '\b': *target++ = 'b'; break;
3850 case '\f': *target++ = 'f'; break;
3851 default: target += sprintf(target, "%03o", (unsigned char) c);
3852 }
3853 continue;
3854 }
3855 *target++ = '\\';
3856 }
3857 *target++ = c;
3858 }
3859 *target = 0;
3860 newlen = target - ZSTR_VAL(new_str);
3861 if (newlen < ZSTR_LEN(str) * 4) {
3862 new_str = zend_string_truncate(new_str, newlen, 0);
3863 }
3864 if (should_free) {
3865 zend_string_release(str);
3866 }
3867 return new_str;
3868 }
3869
3870
3871
3872
3873 PHPAPI zend_string *php_addslashes(zend_string *str, int should_free)
3874 {
3875
3876 char *source, *target;
3877 char *end;
3878 size_t offset;
3879 zend_string *new_str;
3880
3881 if (!str) {
3882 return ZSTR_EMPTY_ALLOC();
3883 }
3884
3885 source = ZSTR_VAL(str);
3886 end = source + ZSTR_LEN(str);
3887
3888 while (source < end) {
3889 switch (*source) {
3890 case '\0':
3891 case '\'':
3892 case '\"':
3893 case '\\':
3894 goto do_escape;
3895 default:
3896 source++;
3897 break;
3898 }
3899 }
3900
3901 if (!should_free) {
3902 return zend_string_copy(str);
3903 }
3904
3905 return str;
3906
3907 do_escape:
3908 offset = source - (char *)ZSTR_VAL(str);
3909 new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0);
3910 memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
3911 target = ZSTR_VAL(new_str) + offset;
3912
3913 while (source < end) {
3914 switch (*source) {
3915 case '\0':
3916 *target++ = '\\';
3917 *target++ = '0';
3918 break;
3919 case '\'':
3920 case '\"':
3921 case '\\':
3922 *target++ = '\\';
3923
3924 default:
3925 *target++ = *source;
3926 break;
3927 }
3928
3929 source++;
3930 }
3931
3932 *target = 0;
3933 if (should_free) {
3934 zend_string_release(str);
3935 }
3936
3937 if (ZSTR_LEN(new_str) - (target - ZSTR_VAL(new_str)) > 16) {
3938 new_str = zend_string_truncate(new_str, target - ZSTR_VAL(new_str), 0);
3939 } else {
3940 ZSTR_LEN(new_str) = target - ZSTR_VAL(new_str);
3941 }
3942
3943 return new_str;
3944 }
3945
3946
3947 #define _HEB_BLOCK_TYPE_ENG 1
3948 #define _HEB_BLOCK_TYPE_HEB 2
3949 #define isheb(c) (((((unsigned char) c) >= 224) && (((unsigned char) c) <= 250)) ? 1 : 0)
3950 #define _isblank(c) (((((unsigned char) c) == ' ' || ((unsigned char) c) == '\t')) ? 1 : 0)
3951 #define _isnewline(c) (((((unsigned char) c) == '\n' || ((unsigned char) c) == '\r')) ? 1 : 0)
3952
3953
3954
3955 static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *subject, zval *result, int case_sensitivity)
3956 {
3957 zval *search_entry,
3958 *replace_entry = NULL;
3959 zend_string *tmp_result,
3960 *replace_entry_str = NULL;
3961 char *replace_value = NULL;
3962 size_t replace_len = 0;
3963 zend_long replace_count = 0;
3964 zend_string *subject_str;
3965 zend_string *lc_subject_str = NULL;
3966 uint32_t replace_idx;
3967
3968
3969 subject_str = zval_get_string(subject);
3970 if (ZSTR_LEN(subject_str) == 0) {
3971 zend_string_release(subject_str);
3972 ZVAL_EMPTY_STRING(result);
3973 return 0;
3974 }
3975
3976
3977 if (Z_TYPE_P(search) == IS_ARRAY) {
3978
3979 ZVAL_STR_COPY(result, subject_str);
3980
3981 if (Z_TYPE_P(replace) == IS_ARRAY) {
3982 replace_idx = 0;
3983 } else {
3984
3985 replace_value = Z_STRVAL_P(replace);
3986 replace_len = Z_STRLEN_P(replace);
3987 }
3988
3989
3990 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(search), search_entry) {
3991
3992 zend_string *search_str = zval_get_string(search_entry);
3993 if (ZSTR_LEN(search_str) == 0) {
3994 if (Z_TYPE_P(replace) == IS_ARRAY) {
3995 replace_idx++;
3996 }
3997 zend_string_release(search_str);
3998 continue;
3999 }
4000
4001
4002 if (Z_TYPE_P(replace) == IS_ARRAY) {
4003
4004 while (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
4005 replace_entry = &Z_ARRVAL_P(replace)->arData[replace_idx].val;
4006 if (Z_TYPE_P(replace_entry) != IS_UNDEF) {
4007 break;
4008 }
4009 replace_idx++;
4010 }
4011 if (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
4012
4013 replace_entry_str = zval_get_string(replace_entry);
4014
4015
4016 replace_value = ZSTR_VAL(replace_entry_str);
4017 replace_len = ZSTR_LEN(replace_entry_str);
4018
4019 replace_idx++;
4020 } else {
4021
4022 replace_value = "";
4023 replace_len = 0;
4024 }
4025 }
4026
4027 if (ZSTR_LEN(search_str) == 1) {
4028 zend_long old_replace_count = replace_count;
4029
4030 tmp_result = php_char_to_str_ex(Z_STR_P(result),
4031 ZSTR_VAL(search_str)[0],
4032 replace_value,
4033 replace_len,
4034 case_sensitivity,
4035 &replace_count);
4036 if (lc_subject_str && replace_count != old_replace_count) {
4037 zend_string_release(lc_subject_str);
4038 lc_subject_str = NULL;
4039 }
4040 } else if (ZSTR_LEN(search_str) > 1) {
4041 if (case_sensitivity) {
4042 tmp_result = php_str_to_str_ex(Z_STR_P(result),
4043 ZSTR_VAL(search_str), ZSTR_LEN(search_str),
4044 replace_value, replace_len, &replace_count);
4045 } else {
4046 zend_long old_replace_count = replace_count;
4047
4048 if (!lc_subject_str) {
4049 lc_subject_str = php_string_tolower(Z_STR_P(result));
4050 }
4051 tmp_result = php_str_to_str_i_ex(Z_STR_P(result), ZSTR_VAL(lc_subject_str),
4052 search_str, replace_value, replace_len, &replace_count);
4053 if (replace_count != old_replace_count) {
4054 zend_string_release(lc_subject_str);
4055 lc_subject_str = NULL;
4056 }
4057 }
4058 }
4059
4060 zend_string_release(search_str);
4061
4062 if (replace_entry_str) {
4063 zend_string_release(replace_entry_str);
4064 replace_entry_str = NULL;
4065 }
4066 zend_string_release(Z_STR_P(result));
4067 ZVAL_STR(result, tmp_result);
4068
4069 if (Z_STRLEN_P(result) == 0) {
4070 if (lc_subject_str) {
4071 zend_string_release(lc_subject_str);
4072 }
4073 zend_string_release(subject_str);
4074 return replace_count;
4075 }
4076 } ZEND_HASH_FOREACH_END();
4077 if (lc_subject_str) {
4078 zend_string_release(lc_subject_str);
4079 }
4080 } else {
4081 ZEND_ASSERT(Z_TYPE_P(search) == IS_STRING);
4082 if (Z_STRLEN_P(search) == 1) {
4083 ZVAL_STR(result,
4084 php_char_to_str_ex(subject_str,
4085 Z_STRVAL_P(search)[0],
4086 Z_STRVAL_P(replace),
4087 Z_STRLEN_P(replace),
4088 case_sensitivity,
4089 &replace_count));
4090 } else if (Z_STRLEN_P(search) > 1) {
4091 if (case_sensitivity) {
4092 ZVAL_STR(result, php_str_to_str_ex(subject_str,
4093 Z_STRVAL_P(search), Z_STRLEN_P(search),
4094 Z_STRVAL_P(replace), Z_STRLEN_P(replace), &replace_count));
4095 } else {
4096 lc_subject_str = php_string_tolower(subject_str);
4097 ZVAL_STR(result, php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str),
4098 Z_STR_P(search),
4099 Z_STRVAL_P(replace), Z_STRLEN_P(replace), &replace_count));
4100 zend_string_release(lc_subject_str);
4101 }
4102 } else {
4103 ZVAL_STR_COPY(result, subject_str);
4104 }
4105 }
4106 zend_string_release(subject_str);
4107 return replace_count;
4108 }
4109
4110
4111
4112
4113 static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity)
4114 {
4115 zval *subject, *search, *replace, *subject_entry, *zcount = NULL;
4116 zval result;
4117 zend_string *string_key;
4118 zend_ulong num_key;
4119 zend_long count = 0;
4120 int argc = ZEND_NUM_ARGS();
4121
4122 #ifndef FAST_ZPP
4123 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z/", &search, &replace, &subject, &zcount) == FAILURE) {
4124 return;
4125 }
4126 #else
4127 ZEND_PARSE_PARAMETERS_START(3, 4)
4128 Z_PARAM_ZVAL(search)
4129 Z_PARAM_ZVAL(replace)
4130 Z_PARAM_ZVAL(subject)
4131 Z_PARAM_OPTIONAL
4132 Z_PARAM_ZVAL_EX(zcount, 0, 1)
4133 ZEND_PARSE_PARAMETERS_END();
4134 #endif
4135
4136
4137 if (Z_TYPE_P(search) != IS_ARRAY) {
4138 convert_to_string_ex(search);
4139 if (Z_TYPE_P(replace) != IS_STRING) {
4140 convert_to_string_ex(replace);
4141 }
4142 } else if (Z_TYPE_P(replace) != IS_ARRAY) {
4143 convert_to_string_ex(replace);
4144 }
4145
4146
4147 if (Z_TYPE_P(subject) == IS_ARRAY) {
4148 array_init(return_value);
4149
4150
4151
4152 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(subject), num_key, string_key, subject_entry) {
4153 if (Z_TYPE_P(subject_entry) != IS_ARRAY && Z_TYPE_P(subject_entry) != IS_OBJECT) {
4154 count += php_str_replace_in_subject(search, replace, subject_entry, &result, case_sensitivity);
4155 } else {
4156 ZVAL_COPY(&result, subject_entry);
4157 }
4158
4159 if (string_key) {
4160 zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, &result);
4161 } else {
4162 zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
4163 }
4164 } ZEND_HASH_FOREACH_END();
4165 } else {
4166 count = php_str_replace_in_subject(search, replace, subject, return_value, case_sensitivity);
4167 }
4168 if (argc > 3) {
4169 zval_ptr_dtor(zcount);
4170 ZVAL_LONG(zcount, count);
4171 }
4172 }
4173
4174
4175
4176
4177 PHP_FUNCTION(str_replace)
4178 {
4179 php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
4180 }
4181
4182
4183
4184
4185 PHP_FUNCTION(str_ireplace)
4186 {
4187 php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
4188 }
4189
4190
4191
4192
4193
4194
4195
4196 static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
4197 {
4198 char *str;
4199 char *heb_str, *tmp, *target;
4200 size_t block_start, block_end, block_type, block_length, i;
4201 zend_long max_chars=0;
4202 size_t begin, end, char_count, orig_begin;
4203 size_t str_len;
4204 zend_string *broken_str;
4205
4206 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &max_chars) == FAILURE) {
4207 return;
4208 }
4209
4210 if (str_len == 0) {
4211 RETURN_FALSE;
4212 }
4213
4214 tmp = str;
4215 block_start=block_end=0;
4216
4217 heb_str = (char *) emalloc(str_len+1);
4218 target = heb_str+str_len;
4219 *target = 0;
4220 target--;
4221
4222 block_length=0;
4223
4224 if (isheb(*tmp)) {
4225 block_type = _HEB_BLOCK_TYPE_HEB;
4226 } else {
4227 block_type = _HEB_BLOCK_TYPE_ENG;
4228 }
4229
4230 do {
4231 if (block_type == _HEB_BLOCK_TYPE_HEB) {
4232 while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) {
4233 tmp++;
4234 block_end++;
4235 block_length++;
4236 }
4237 for (i = block_start+1; i<= block_end+1; i++) {
4238 *target = str[i-1];
4239 switch (*target) {
4240 case '(':
4241 *target = ')';
4242 break;
4243 case ')':
4244 *target = '(';
4245 break;
4246 case '[':
4247 *target = ']';
4248 break;
4249 case ']':
4250 *target = '[';
4251 break;
4252 case '{':
4253 *target = '}';
4254 break;
4255 case '}':
4256 *target = '{';
4257 break;
4258 case '<':
4259 *target = '>';
4260 break;
4261 case '>':
4262 *target = '<';
4263 break;
4264 case '\\':
4265 *target = '/';
4266 break;
4267 case '/':
4268 *target = '\\';
4269 break;
4270 default:
4271 break;
4272 }
4273 target--;
4274 }
4275 block_type = _HEB_BLOCK_TYPE_ENG;
4276 } else {
4277 while (!isheb(*(tmp+1)) && (int)*(tmp+1)!='\n' && block_end < str_len-1) {
4278 tmp++;
4279 block_end++;
4280 block_length++;
4281 }
4282 while ((_isblank((int)*tmp) || ispunct((int)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) {
4283 tmp--;
4284 block_end--;
4285 }
4286 for (i = block_end+1; i >= block_start+1; i--) {
4287 *target = str[i-1];
4288 target--;
4289 }
4290 block_type = _HEB_BLOCK_TYPE_HEB;
4291 }
4292 block_start=block_end+1;
4293 } while (block_end < str_len-1);
4294
4295
4296 broken_str = zend_string_alloc(str_len, 0);
4297 begin = end = str_len-1;
4298 target = ZSTR_VAL(broken_str);
4299
4300 while (1) {
4301 char_count=0;
4302 while ((!max_chars || (max_chars > 0 && char_count < max_chars)) && begin > 0) {
4303 char_count++;
4304 begin--;
4305 if (begin <= 0 || _isnewline(heb_str[begin])) {
4306 while (begin > 0 && _isnewline(heb_str[begin-1])) {
4307 begin--;
4308 char_count++;
4309 }
4310 break;
4311 }
4312 }
4313 if (max_chars >= 0 && char_count == max_chars) {
4314 size_t new_char_count=char_count, new_begin=begin;
4315
4316 while (new_char_count > 0) {
4317 if (_isblank(heb_str[new_begin]) || _isnewline(heb_str[new_begin])) {
4318 break;
4319 }
4320 new_begin++;
4321 new_char_count--;
4322 }
4323 if (new_char_count > 0) {
4324 begin=new_begin;
4325 }
4326 }
4327 orig_begin=begin;
4328
4329 if (_isblank(heb_str[begin])) {
4330 heb_str[begin]='\n';
4331 }
4332 while (begin <= end && _isnewline(heb_str[begin])) {
4333 begin++;
4334 }
4335 for (i = begin; i <= end; i++) {
4336 *target = heb_str[i];
4337 target++;
4338 }
4339 for (i = orig_begin; i <= end && _isnewline(heb_str[i]); i++) {
4340 *target = heb_str[i];
4341 target++;
4342 }
4343 begin=orig_begin;
4344
4345 if (begin <= 0) {
4346 *target = 0;
4347 break;
4348 }
4349 begin--;
4350 end=begin;
4351 }
4352 efree(heb_str);
4353
4354 if (convert_newlines) {
4355 RETVAL_STR(php_char_to_str_ex(broken_str, '\n', "<br />\n", 7, 1, NULL));
4356 zend_string_release(broken_str);
4357 } else {
4358 RETURN_NEW_STR(broken_str);
4359 }
4360 }
4361
4362
4363
4364
4365 PHP_FUNCTION(hebrev)
4366 {
4367 php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
4368 }
4369
4370
4371
4372
4373 PHP_FUNCTION(hebrevc)
4374 {
4375 php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
4376 }
4377
4378
4379
4380
4381 PHP_FUNCTION(nl2br)
4382 {
4383
4384 char *tmp;
4385 zend_string *str;
4386 char *end, *target;
4387 size_t repl_cnt = 0;
4388 zend_bool is_xhtml = 1;
4389 zend_string *result;
4390
4391 #ifndef FAST_ZPP
4392 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &str, &is_xhtml) == FAILURE) {
4393 return;
4394 }
4395 #else
4396 ZEND_PARSE_PARAMETERS_START(1, 2)
4397 Z_PARAM_STR(str)
4398 Z_PARAM_OPTIONAL
4399 Z_PARAM_BOOL(is_xhtml)
4400 ZEND_PARSE_PARAMETERS_END();
4401 #endif
4402
4403 tmp = ZSTR_VAL(str);
4404 end = ZSTR_VAL(str) + ZSTR_LEN(str);
4405
4406
4407
4408 while (tmp < end) {
4409 if (*tmp == '\r') {
4410 if (*(tmp+1) == '\n') {
4411 tmp++;
4412 }
4413 repl_cnt++;
4414 } else if (*tmp == '\n') {
4415 if (*(tmp+1) == '\r') {
4416 tmp++;
4417 }
4418 repl_cnt++;
4419 }
4420
4421 tmp++;
4422 }
4423
4424 if (repl_cnt == 0) {
4425 RETURN_STR_COPY(str);
4426 }
4427
4428 {
4429 size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1);
4430
4431 result = zend_string_safe_alloc(repl_cnt, repl_len, ZSTR_LEN(str), 0);
4432 target = ZSTR_VAL(result);
4433 }
4434
4435 tmp = ZSTR_VAL(str);
4436 while (tmp < end) {
4437 switch (*tmp) {
4438 case '\r':
4439 case '\n':
4440 *target++ = '<';
4441 *target++ = 'b';
4442 *target++ = 'r';
4443
4444 if (is_xhtml) {
4445 *target++ = ' ';
4446 *target++ = '/';
4447 }
4448
4449 *target++ = '>';
4450
4451 if ((*tmp == '\r' && *(tmp+1) == '\n') || (*tmp == '\n' && *(tmp+1) == '\r')) {
4452 *target++ = *tmp++;
4453 }
4454
4455 default:
4456 *target++ = *tmp;
4457 }
4458
4459 tmp++;
4460 }
4461
4462 *target = '\0';
4463
4464 RETURN_NEW_STR(result);
4465 }
4466
4467
4468
4469
4470 PHP_FUNCTION(strip_tags)
4471 {
4472 zend_string *buf;
4473 zend_string *str;
4474 zval *allow=NULL;
4475 char *allowed_tags=NULL;
4476 size_t allowed_tags_len=0;
4477
4478 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &str, &allow) == FAILURE) {
4479 return;
4480 }
4481
4482
4483 if (allow) {
4484 convert_to_string(allow);
4485 allowed_tags = Z_STRVAL_P(allow);
4486 allowed_tags_len = Z_STRLEN_P(allow);
4487 }
4488
4489 buf = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0);
4490 ZSTR_LEN(buf) = php_strip_tags_ex(ZSTR_VAL(buf), ZSTR_LEN(str), NULL, allowed_tags, allowed_tags_len, 0);
4491 RETURN_NEW_STR(buf);
4492 }
4493
4494
4495
4496
4497 PHP_FUNCTION(setlocale)
4498 {
4499 zval *args = NULL;
4500 zval *plocale;
4501 zend_string *loc;
4502 char *retval;
4503 zend_long cat;
4504 int num_args, i = 0;
4505 uint32_t idx;
4506
4507 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l+", &cat, &args, &num_args) == FAILURE) {
4508 return;
4509 }
4510
4511 #ifdef HAVE_SETLOCALE
4512 idx = 0;
4513 while (1) {
4514 if (Z_TYPE(args[0]) == IS_ARRAY) {
4515 while (idx < Z_ARRVAL(args[0])->nNumUsed) {
4516 plocale = &Z_ARRVAL(args[0])->arData[idx].val;
4517 if (Z_TYPE_P(plocale) != IS_UNDEF) {
4518 break;
4519 }
4520 idx++;
4521 }
4522 if (idx >= Z_ARRVAL(args[0])->nNumUsed) {
4523 break;
4524 }
4525 } else {
4526 plocale = &args[i];
4527 }
4528
4529 loc = zval_get_string(plocale);
4530
4531 if (!strcmp("0", ZSTR_VAL(loc))) {
4532 zend_string_release(loc);
4533 loc = NULL;
4534 } else {
4535 if (ZSTR_LEN(loc) >= 255) {
4536 php_error_docref(NULL, E_WARNING, "Specified locale name is too long");
4537 zend_string_release(loc);
4538 break;
4539 }
4540 }
4541
4542 retval = php_my_setlocale(cat, loc ? ZSTR_VAL(loc) : NULL);
4543 zend_update_current_locale();
4544 if (retval) {
4545 if (loc) {
4546
4547 size_t len = strlen(retval);
4548
4549 BG(locale_changed) = 1;
4550 if (cat == LC_CTYPE || cat == LC_ALL) {
4551 if (BG(locale_string)) {
4552 zend_string_release(BG(locale_string));
4553 }
4554 if (len == ZSTR_LEN(loc) && !memcmp(ZSTR_VAL(loc), retval, len)) {
4555 BG(locale_string) = zend_string_copy(loc);
4556 RETURN_STR(BG(locale_string));
4557 } else {
4558 BG(locale_string) = zend_string_init(retval, len, 0);
4559 zend_string_release(loc);
4560 RETURN_STR_COPY(BG(locale_string));
4561 }
4562 } else if (len == ZSTR_LEN(loc) && !memcmp(ZSTR_VAL(loc), retval, len)) {
4563 RETURN_STR(loc);
4564 }
4565 zend_string_release(loc);
4566 }
4567 RETURN_STRING(retval);
4568 }
4569 if (loc) {
4570 zend_string_release(loc);
4571 }
4572
4573 if (Z_TYPE(args[0]) == IS_ARRAY) {
4574 idx++;
4575 } else {
4576 if (++i >= num_args) break;
4577 }
4578 }
4579
4580 #endif
4581 RETURN_FALSE;
4582 }
4583
4584
4585
4586
4587 PHP_FUNCTION(parse_str)
4588 {
4589 char *arg;
4590 zval *arrayArg = NULL;
4591 char *res = NULL;
4592 size_t arglen;
4593
4594 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z/", &arg, &arglen, &arrayArg) == FAILURE) {
4595 return;
4596 }
4597
4598 res = estrndup(arg, arglen);
4599
4600 if (arrayArg == NULL) {
4601 zval tmp;
4602 zend_array *symbol_table = zend_rebuild_symbol_table();
4603
4604 ZVAL_ARR(&tmp, symbol_table);
4605 sapi_module.treat_data(PARSE_STRING, res, &tmp);
4606 } else {
4607 zval ret;
4608
4609
4610 zval_dtor(arrayArg);
4611 array_init(&ret);
4612 sapi_module.treat_data(PARSE_STRING, res, &ret);
4613 ZVAL_COPY_VALUE(arrayArg, &ret);
4614 }
4615 }
4616
4617
4618 #define PHP_TAG_BUF_SIZE 1023
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629 int php_tag_find(char *tag, size_t len, const char *set) {
4630 char c, *n, *t;
4631 int state=0, done=0;
4632 char *norm;
4633
4634 if (len <= 0) {
4635 return 0;
4636 }
4637
4638 norm = emalloc(len+1);
4639
4640 n = norm;
4641 t = tag;
4642 c = tolower(*t);
4643
4644
4645
4646
4647
4648 while (!done) {
4649 switch (c) {
4650 case '<':
4651 *(n++) = c;
4652 break;
4653 case '>':
4654 done =1;
4655 break;
4656 default:
4657 if (!isspace((int)c)) {
4658 if (state == 0) {
4659 state=1;
4660 }
4661 if (c != '/') {
4662 *(n++) = c;
4663 }
4664 } else {
4665 if (state == 1)
4666 done=1;
4667 }
4668 break;
4669 }
4670 c = tolower(*(++t));
4671 }
4672 *(n++) = '>';
4673 *n = '\0';
4674 if (strstr(set, norm)) {
4675 done=1;
4676 } else {
4677 done=0;
4678 }
4679 efree(norm);
4680 return done;
4681 }
4682
4683
4684 PHPAPI size_t php_strip_tags(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len)
4685 {
4686 return php_strip_tags_ex(rbuf, len, stateptr, allow, allow_len, 0);
4687 }
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710 PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const char *allow, size_t allow_len, zend_bool allow_tag_spaces)
4711 {
4712 char *tbuf, *buf, *p, *tp, *rp, c, lc;
4713 int br, depth=0, in_q = 0;
4714 int state = 0;
4715 size_t pos, i = 0;
4716 char *allow_free = NULL;
4717 const char *allow_actual;
4718 char is_xml = 0;
4719
4720 if (stateptr)
4721 state = *stateptr;
4722
4723 buf = estrndup(rbuf, len);
4724 c = *buf;
4725 lc = '\0';
4726 p = buf;
4727 rp = rbuf;
4728 br = 0;
4729 if (allow) {
4730 allow_free = zend_str_tolower_dup_ex(allow, allow_len);
4731 allow_actual = allow_free ? allow_free : allow;
4732 tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
4733 tp = tbuf;
4734 } else {
4735 tbuf = tp = NULL;
4736 }
4737
4738 while (i < len) {
4739 switch (c) {
4740 case '\0':
4741 break;
4742 case '<':
4743 if (in_q) {
4744 break;
4745 }
4746 if (isspace(*(p + 1)) && !allow_tag_spaces) {
4747 goto reg_char;
4748 }
4749 if (state == 0) {
4750 lc = '<';
4751 state = 1;
4752 if (allow) {
4753 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4754 pos = tp - tbuf;
4755 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4756 tp = tbuf + pos;
4757 }
4758 *(tp++) = '<';
4759 }
4760 } else if (state == 1) {
4761 depth++;
4762 }
4763 break;
4764
4765 case '(':
4766 if (state == 2) {
4767 if (lc != '"' && lc != '\'') {
4768 lc = '(';
4769 br++;
4770 }
4771 } else if (allow && state == 1) {
4772 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4773 pos = tp - tbuf;
4774 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4775 tp = tbuf + pos;
4776 }
4777 *(tp++) = c;
4778 } else if (state == 0) {
4779 *(rp++) = c;
4780 }
4781 break;
4782
4783 case ')':
4784 if (state == 2) {
4785 if (lc != '"' && lc != '\'') {
4786 lc = ')';
4787 br--;
4788 }
4789 } else if (allow && state == 1) {
4790 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4791 pos = tp - tbuf;
4792 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4793 tp = tbuf + pos;
4794 }
4795 *(tp++) = c;
4796 } else if (state == 0) {
4797 *(rp++) = c;
4798 }
4799 break;
4800
4801 case '>':
4802 if (depth) {
4803 depth--;
4804 break;
4805 }
4806
4807 if (in_q) {
4808 break;
4809 }
4810
4811 switch (state) {
4812 case 1:
4813 lc = '>';
4814 if (is_xml && *(p -1) == '-') {
4815 break;
4816 }
4817 in_q = state = is_xml = 0;
4818 if (allow) {
4819 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4820 pos = tp - tbuf;
4821 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4822 tp = tbuf + pos;
4823 }
4824 *(tp++) = '>';
4825 *tp='\0';
4826 if (php_tag_find(tbuf, tp-tbuf, allow_actual)) {
4827 memcpy(rp, tbuf, tp-tbuf);
4828 rp += tp-tbuf;
4829 }
4830 tp = tbuf;
4831 }
4832 break;
4833
4834 case 2:
4835 if (!br && lc != '\"' && *(p-1) == '?') {
4836 in_q = state = 0;
4837 tp = tbuf;
4838 }
4839 break;
4840
4841 case 3:
4842 in_q = state = 0;
4843 tp = tbuf;
4844 break;
4845
4846 case 4:
4847 if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '-') {
4848 in_q = state = 0;
4849 tp = tbuf;
4850 }
4851 break;
4852
4853 default:
4854 *(rp++) = c;
4855 break;
4856 }
4857 break;
4858
4859 case '"':
4860 case '\'':
4861 if (state == 4) {
4862
4863 break;
4864 } else if (state == 2 && *(p-1) != '\\') {
4865 if (lc == c) {
4866 lc = '\0';
4867 } else if (lc != '\\') {
4868 lc = c;
4869 }
4870 } else if (state == 0) {
4871 *(rp++) = c;
4872 } else if (allow && state == 1) {
4873 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4874 pos = tp - tbuf;
4875 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4876 tp = tbuf + pos;
4877 }
4878 *(tp++) = c;
4879 }
4880 if (state && p != buf && (state == 1 || *(p-1) != '\\') && (!in_q || *p == in_q)) {
4881 if (in_q) {
4882 in_q = 0;
4883 } else {
4884 in_q = *p;
4885 }
4886 }
4887 break;
4888
4889 case '!':
4890
4891 if (state == 1 && *(p-1) == '<') {
4892 state = 3;
4893 lc = c;
4894 } else {
4895 if (state == 0) {
4896 *(rp++) = c;
4897 } else if (allow && state == 1) {
4898 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4899 pos = tp - tbuf;
4900 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4901 tp = tbuf + pos;
4902 }
4903 *(tp++) = c;
4904 }
4905 }
4906 break;
4907
4908 case '-':
4909 if (state == 3 && p >= buf + 2 && *(p-1) == '-' && *(p-2) == '!') {
4910 state = 4;
4911 } else {
4912 goto reg_char;
4913 }
4914 break;
4915
4916 case '?':
4917
4918 if (state == 1 && *(p-1) == '<') {
4919 br=0;
4920 state=2;
4921 break;
4922 }
4923
4924 case 'E':
4925 case 'e':
4926
4927 if (state==3 && p > buf+6
4928 && tolower(*(p-1)) == 'p'
4929 && tolower(*(p-2)) == 'y'
4930 && tolower(*(p-3)) == 't'
4931 && tolower(*(p-4)) == 'c'
4932 && tolower(*(p-5)) == 'o'
4933 && tolower(*(p-6)) == 'd') {
4934 state = 1;
4935 break;
4936 }
4937
4938
4939 case 'l':
4940 case 'L':
4941
4942
4943
4944
4945
4946 if (state == 2 && p > buf+4 && strncasecmp(p-4, "<?xm", 4) == 0) {
4947 state = 1; is_xml=1;
4948 break;
4949 }
4950
4951
4952 default:
4953 reg_char:
4954 if (state == 0) {
4955 *(rp++) = c;
4956 } else if (allow && state == 1) {
4957 if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
4958 pos = tp - tbuf;
4959 tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
4960 tp = tbuf + pos;
4961 }
4962 *(tp++) = c;
4963 }
4964 break;
4965 }
4966 c = *(++p);
4967 i++;
4968 }
4969 if (rp < rbuf + len) {
4970 *rp = '\0';
4971 }
4972 efree(buf);
4973 if (allow) {
4974 efree(tbuf);
4975 if (allow_free) {
4976 efree(allow_free);
4977 }
4978 }
4979 if (stateptr)
4980 *stateptr = state;
4981
4982 return (size_t)(rp - rbuf);
4983 }
4984
4985
4986
4987
4988 PHP_FUNCTION(str_getcsv)
4989 {
4990 zend_string *str;
4991 char delim = ',', enc = '"', esc = '\\';
4992 char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
4993 size_t delim_len = 0, enc_len = 0, esc_len = 0;
4994
4995 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|sss", &str, &delim_str, &delim_len,
4996 &enc_str, &enc_len, &esc_str, &esc_len) == FAILURE) {
4997 return;
4998 }
4999
5000 delim = delim_len ? delim_str[0] : delim;
5001 enc = enc_len ? enc_str[0] : enc;
5002 esc = esc_len ? esc_str[0] : esc;
5003
5004 php_fgetcsv(NULL, delim, enc, esc, ZSTR_LEN(str), ZSTR_VAL(str), return_value);
5005 }
5006
5007
5008
5009
5010 PHP_FUNCTION(str_repeat)
5011 {
5012 zend_string *input_str;
5013 zend_long mult;
5014 zend_string *result;
5015 size_t result_len;
5016
5017 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl", &input_str, &mult) == FAILURE) {
5018 return;
5019 }
5020
5021 if (mult < 0) {
5022 php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0");
5023 return;
5024 }
5025
5026
5027
5028 if (ZSTR_LEN(input_str) == 0 || mult == 0)
5029 RETURN_EMPTY_STRING();
5030
5031
5032 result = zend_string_safe_alloc(ZSTR_LEN(input_str), mult, 0, 0);
5033 result_len = ZSTR_LEN(input_str) * mult;
5034
5035
5036 if (ZSTR_LEN(input_str) == 1) {
5037 memset(ZSTR_VAL(result), *ZSTR_VAL(input_str), mult);
5038 } else {
5039 char *s, *e, *ee;
5040 ptrdiff_t l=0;
5041 memcpy(ZSTR_VAL(result), ZSTR_VAL(input_str), ZSTR_LEN(input_str));
5042 s = ZSTR_VAL(result);
5043 e = ZSTR_VAL(result) + ZSTR_LEN(input_str);
5044 ee = ZSTR_VAL(result) + result_len;
5045
5046 while (e<ee) {
5047 l = (e-s) < (ee-e) ? (e-s) : (ee-e);
5048 memmove(e, s, l);
5049 e += l;
5050 }
5051 }
5052
5053 ZSTR_VAL(result)[result_len] = '\0';
5054
5055 RETURN_NEW_STR(result);
5056 }
5057
5058
5059
5060
5061 PHP_FUNCTION(count_chars)
5062 {
5063 zend_string *input;
5064 int chars[256];
5065 zend_long mymode=0;
5066 unsigned char *buf;
5067 int inx;
5068 char retstr[256];
5069 size_t retlen=0;
5070 size_t tmp = 0;
5071
5072 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &input, &mymode) == FAILURE) {
5073 return;
5074 }
5075
5076 if (mymode < 0 || mymode > 4) {
5077 php_error_docref(NULL, E_WARNING, "Unknown mode");
5078 RETURN_FALSE;
5079 }
5080
5081 buf = (unsigned char *) ZSTR_VAL(input);
5082 memset((void*) chars, 0, sizeof(chars));
5083
5084 while (tmp < ZSTR_LEN(input)) {
5085 chars[*buf]++;
5086 buf++;
5087 tmp++;
5088 }
5089
5090 if (mymode < 3) {
5091 array_init(return_value);
5092 }
5093
5094 for (inx = 0; inx < 256; inx++) {
5095 switch (mymode) {
5096 case 0:
5097 add_index_long(return_value, inx, chars[inx]);
5098 break;
5099 case 1:
5100 if (chars[inx] != 0) {
5101 add_index_long(return_value, inx, chars[inx]);
5102 }
5103 break;
5104 case 2:
5105 if (chars[inx] == 0) {
5106 add_index_long(return_value, inx, chars[inx]);
5107 }
5108 break;
5109 case 3:
5110 if (chars[inx] != 0) {
5111 retstr[retlen++] = inx;
5112 }
5113 break;
5114 case 4:
5115 if (chars[inx] == 0) {
5116 retstr[retlen++] = inx;
5117 }
5118 break;
5119 }
5120 }
5121
5122 if (mymode >= 3 && mymode <= 4) {
5123 RETURN_STRINGL(retstr, retlen);
5124 }
5125 }
5126
5127
5128
5129
5130 static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
5131 {
5132 zend_string *s1, *s2;
5133
5134 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
5135 return;
5136 }
5137
5138 RETURN_LONG(strnatcmp_ex(ZSTR_VAL(s1), ZSTR_LEN(s1),
5139 ZSTR_VAL(s2), ZSTR_LEN(s2),
5140 fold_case));
5141 }
5142
5143
5144 PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive)
5145 {
5146 zend_string *str1 = zval_get_string(op1);
5147 zend_string *str2 = zval_get_string(op2);
5148
5149 ZVAL_LONG(result, strnatcmp_ex(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2), case_insensitive));
5150
5151 zend_string_release(str1);
5152 zend_string_release(str2);
5153 return SUCCESS;
5154 }
5155
5156
5157 PHPAPI int string_natural_case_compare_function(zval *result, zval *op1, zval *op2)
5158 {
5159 return string_natural_compare_function_ex(result, op1, op2, 1);
5160 }
5161
5162
5163 PHPAPI int string_natural_compare_function(zval *result, zval *op1, zval *op2)
5164 {
5165 return string_natural_compare_function_ex(result, op1, op2, 0);
5166 }
5167
5168
5169
5170
5171 PHP_FUNCTION(strnatcmp)
5172 {
5173 php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
5174 }
5175
5176
5177
5178
5179 PHP_FUNCTION(localeconv)
5180 {
5181 zval grouping, mon_grouping;
5182 int len, i;
5183
5184
5185 if (zend_parse_parameters_none() == FAILURE) {
5186 return;
5187 }
5188
5189 array_init(return_value);
5190 array_init(&grouping);
5191 array_init(&mon_grouping);
5192
5193 #ifdef HAVE_LOCALECONV
5194 {
5195 struct lconv currlocdata;
5196
5197 localeconv_r( &currlocdata );
5198
5199
5200 len = (int)strlen(currlocdata.grouping);
5201
5202 for (i = 0; i < len; i++) {
5203 add_index_long(&grouping, i, currlocdata.grouping[i]);
5204 }
5205
5206
5207 len = (int)strlen(currlocdata.mon_grouping);
5208
5209 for (i = 0; i < len; i++) {
5210 add_index_long(&mon_grouping, i, currlocdata.mon_grouping[i]);
5211 }
5212
5213 add_assoc_string(return_value, "decimal_point", currlocdata.decimal_point);
5214 add_assoc_string(return_value, "thousands_sep", currlocdata.thousands_sep);
5215 add_assoc_string(return_value, "int_curr_symbol", currlocdata.int_curr_symbol);
5216 add_assoc_string(return_value, "currency_symbol", currlocdata.currency_symbol);
5217 add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point);
5218 add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep);
5219 add_assoc_string(return_value, "positive_sign", currlocdata.positive_sign);
5220 add_assoc_string(return_value, "negative_sign", currlocdata.negative_sign);
5221 add_assoc_long( return_value, "int_frac_digits", currlocdata.int_frac_digits);
5222 add_assoc_long( return_value, "frac_digits", currlocdata.frac_digits);
5223 add_assoc_long( return_value, "p_cs_precedes", currlocdata.p_cs_precedes);
5224 add_assoc_long( return_value, "p_sep_by_space", currlocdata.p_sep_by_space);
5225 add_assoc_long( return_value, "n_cs_precedes", currlocdata.n_cs_precedes);
5226 add_assoc_long( return_value, "n_sep_by_space", currlocdata.n_sep_by_space);
5227 add_assoc_long( return_value, "p_sign_posn", currlocdata.p_sign_posn);
5228 add_assoc_long( return_value, "n_sign_posn", currlocdata.n_sign_posn);
5229 }
5230 #else
5231
5232
5233
5234 add_index_long(&grouping, 0, -1);
5235 add_index_long(&mon_grouping, 0, -1);
5236
5237 add_assoc_string(return_value, "decimal_point", "\x2E");
5238 add_assoc_string(return_value, "thousands_sep", "");
5239 add_assoc_string(return_value, "int_curr_symbol", "");
5240 add_assoc_string(return_value, "currency_symbol", "");
5241 add_assoc_string(return_value, "mon_decimal_point", "\x2E");
5242 add_assoc_string(return_value, "mon_thousands_sep", "");
5243 add_assoc_string(return_value, "positive_sign", "");
5244 add_assoc_string(return_value, "negative_sign", "");
5245 add_assoc_long( return_value, "int_frac_digits", CHAR_MAX);
5246 add_assoc_long( return_value, "frac_digits", CHAR_MAX);
5247 add_assoc_long( return_value, "p_cs_precedes", CHAR_MAX);
5248 add_assoc_long( return_value, "p_sep_by_space", CHAR_MAX);
5249 add_assoc_long( return_value, "n_cs_precedes", CHAR_MAX);
5250 add_assoc_long( return_value, "n_sep_by_space", CHAR_MAX);
5251 add_assoc_long( return_value, "p_sign_posn", CHAR_MAX);
5252 add_assoc_long( return_value, "n_sign_posn", CHAR_MAX);
5253 #endif
5254
5255 zend_hash_str_update(Z_ARRVAL_P(return_value), "grouping", sizeof("grouping")-1, &grouping);
5256 zend_hash_str_update(Z_ARRVAL_P(return_value), "mon_grouping", sizeof("mon_grouping")-1, &mon_grouping);
5257 }
5258
5259
5260
5261
5262 PHP_FUNCTION(strnatcasecmp)
5263 {
5264 php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5265 }
5266
5267
5268
5269
5270 PHP_FUNCTION(substr_count)
5271 {
5272 char *haystack, *needle;
5273 zend_long offset = 0, length = 0;
5274 int ac = ZEND_NUM_ARGS();
5275 int count = 0;
5276 size_t haystack_len, needle_len;
5277 char *p, *endp, cmp;
5278
5279 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ll", &haystack, &haystack_len, &needle, &needle_len, &offset, &length) == FAILURE) {
5280 return;
5281 }
5282
5283 if (needle_len == 0) {
5284 php_error_docref(NULL, E_WARNING, "Empty substring");
5285 RETURN_FALSE;
5286 }
5287
5288 p = haystack;
5289 endp = p + haystack_len;
5290
5291 if (offset < 0) {
5292 php_error_docref(NULL, E_WARNING, "Offset should be greater than or equal to 0");
5293 RETURN_FALSE;
5294 }
5295
5296 if ((size_t)offset > haystack_len) {
5297 php_error_docref(NULL, E_WARNING, "Offset value " ZEND_LONG_FMT " exceeds string length", offset);
5298 RETURN_FALSE;
5299 }
5300 p += offset;
5301
5302 if (ac == 4) {
5303
5304 if (length <= 0) {
5305 php_error_docref(NULL, E_WARNING, "Length should be greater than 0");
5306 RETURN_FALSE;
5307 }
5308 if (length > (haystack_len - offset)) {
5309 php_error_docref(NULL, E_WARNING, "Length value " ZEND_LONG_FMT " exceeds string length", length);
5310 RETURN_FALSE;
5311 }
5312 endp = p + length;
5313 }
5314
5315 if (needle_len == 1) {
5316 cmp = needle[0];
5317
5318 while ((p = memchr(p, cmp, endp - p))) {
5319 count++;
5320 p++;
5321 }
5322 } else {
5323 while ((p = (char*)php_memnstr(p, needle, needle_len, endp))) {
5324 p += needle_len;
5325 count++;
5326 }
5327 }
5328
5329 RETURN_LONG(count);
5330 }
5331
5332
5333
5334
5335 PHP_FUNCTION(str_pad)
5336 {
5337
5338 zend_string *input;
5339 zend_long pad_length;
5340
5341
5342 size_t num_pad_chars;
5343 char *pad_str = " ";
5344 size_t pad_str_len = 1;
5345 zend_long pad_type_val = STR_PAD_RIGHT;
5346 size_t i, left_pad=0, right_pad=0;
5347 zend_string *result = NULL;
5348
5349 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sl|sl", &input, &pad_length, &pad_str, &pad_str_len, &pad_type_val) == FAILURE) {
5350 return;
5351 }
5352
5353
5354
5355 if (pad_length < 0 || (size_t)pad_length <= ZSTR_LEN(input)) {
5356 RETURN_STRINGL(ZSTR_VAL(input), ZSTR_LEN(input));
5357 }
5358
5359 if (pad_str_len == 0) {
5360 php_error_docref(NULL, E_WARNING, "Padding string cannot be empty");
5361 return;
5362 }
5363
5364 if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
5365 php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
5366 return;
5367 }
5368
5369 num_pad_chars = pad_length - ZSTR_LEN(input);
5370 if (num_pad_chars >= INT_MAX) {
5371 php_error_docref(NULL, E_WARNING, "Padding length is too long");
5372 return;
5373 }
5374
5375 result = zend_string_safe_alloc(ZSTR_LEN(input), 1, num_pad_chars, 0);
5376 ZSTR_LEN(result) = 0;
5377
5378
5379 switch (pad_type_val) {
5380 case STR_PAD_RIGHT:
5381 left_pad = 0;
5382 right_pad = num_pad_chars;
5383 break;
5384
5385 case STR_PAD_LEFT:
5386 left_pad = num_pad_chars;
5387 right_pad = 0;
5388 break;
5389
5390 case STR_PAD_BOTH:
5391 left_pad = num_pad_chars / 2;
5392 right_pad = num_pad_chars - left_pad;
5393 break;
5394 }
5395
5396
5397 for (i = 0; i < left_pad; i++)
5398 ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len];
5399
5400
5401 memcpy(ZSTR_VAL(result) + ZSTR_LEN(result), ZSTR_VAL(input), ZSTR_LEN(input));
5402 ZSTR_LEN(result) += ZSTR_LEN(input);
5403
5404
5405 for (i = 0; i < right_pad; i++)
5406 ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len];
5407
5408 ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
5409
5410 RETURN_NEW_STR(result);
5411 }
5412
5413
5414
5415
5416 PHP_FUNCTION(sscanf)
5417 {
5418 zval *args = NULL;
5419 char *str, *format;
5420 size_t str_len, format_len;
5421 int result, num_args = 0;
5422
5423 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss*", &str, &str_len, &format, &format_len,
5424 &args, &num_args) == FAILURE) {
5425 return;
5426 }
5427
5428 result = php_sscanf_internal(str, format, num_args, args, 0, return_value);
5429
5430 if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
5431 WRONG_PARAM_COUNT;
5432 }
5433 }
5434
5435
5436 static char rot13_from[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
5437 static char rot13_to[] = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
5438
5439
5440
5441 PHP_FUNCTION(str_rot13)
5442 {
5443 zend_string *arg;
5444
5445 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
5446 return;
5447 }
5448
5449 if (ZSTR_LEN(arg) == 0) {
5450 RETURN_EMPTY_STRING();
5451 } else {
5452 RETURN_STR(php_strtr_ex(arg, rot13_from, rot13_to, 52));
5453 }
5454 }
5455
5456
5457 static void php_string_shuffle(char *str, zend_long len)
5458 {
5459 zend_long n_elems, rnd_idx, n_left;
5460 char temp;
5461
5462
5463 n_elems = len;
5464
5465 if (n_elems <= 1) {
5466 return;
5467 }
5468
5469 n_left = n_elems;
5470
5471 while (--n_left) {
5472 rnd_idx = php_rand();
5473 RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
5474 if (rnd_idx != n_left) {
5475 temp = str[n_left];
5476 str[n_left] = str[rnd_idx];
5477 str[rnd_idx] = temp;
5478 }
5479 }
5480 }
5481
5482
5483
5484
5485 PHP_FUNCTION(str_shuffle)
5486 {
5487 zend_string *arg;
5488
5489 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
5490 return;
5491 }
5492
5493 RETVAL_STRINGL(ZSTR_VAL(arg), ZSTR_LEN(arg));
5494 if (Z_STRLEN_P(return_value) > 1) {
5495 php_string_shuffle(Z_STRVAL_P(return_value), (zend_long) Z_STRLEN_P(return_value));
5496 }
5497 }
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511 PHP_FUNCTION(str_word_count)
5512 {
5513 zend_string *str;
5514 char *char_list = NULL, *p, *e, *s, ch[256];
5515 size_t char_list_len = 0, word_count = 0;
5516 zend_long type = 0;
5517
5518 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ls", &str, &type, &char_list, &char_list_len) == FAILURE) {
5519 return;
5520 }
5521
5522 switch(type) {
5523 case 1:
5524 case 2:
5525 array_init(return_value);
5526 if (!ZSTR_LEN(str)) {
5527 return;
5528 }
5529 break;
5530 case 0:
5531 if (!ZSTR_LEN(str)) {
5532 RETURN_LONG(0);
5533 }
5534
5535 break;
5536 default:
5537 php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type);
5538 RETURN_FALSE;
5539 }
5540
5541 if (char_list) {
5542 php_charmask((unsigned char *)char_list, char_list_len, ch);
5543 }
5544
5545 p = ZSTR_VAL(str);
5546 e = ZSTR_VAL(str) + ZSTR_LEN(str);
5547
5548
5549 if ((*p == '\'' && (!char_list || !ch['\''])) || (*p == '-' && (!char_list || !ch['-']))) {
5550 p++;
5551 }
5552
5553 if (*(e - 1) == '-' && (!char_list || !ch['-'])) {
5554 e--;
5555 }
5556
5557 while (p < e) {
5558 s = p;
5559 while (p < e && (isalpha((unsigned char)*p) || (char_list && ch[(unsigned char)*p]) || *p == '\'' || *p == '-')) {
5560 p++;
5561 }
5562 if (p > s) {
5563 switch (type)
5564 {
5565 case 1:
5566 add_next_index_stringl(return_value, s, p - s);
5567 break;
5568 case 2:
5569 add_index_stringl(return_value, (s - ZSTR_VAL(str)), s, p - s);
5570 break;
5571 default:
5572 word_count++;
5573 break;
5574 }
5575 }
5576 p++;
5577 }
5578
5579 if (!type) {
5580 RETURN_LONG(word_count);
5581 }
5582 }
5583
5584
5585
5586 #if HAVE_STRFMON
5587
5588
5589 PHP_FUNCTION(money_format)
5590 {
5591 size_t format_len = 0;
5592 char *format, *p, *e;
5593 double value;
5594 zend_bool check = 0;
5595 zend_string *str;
5596 ssize_t res_len;
5597
5598 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sd", &format, &format_len, &value) == FAILURE) {
5599 return;
5600 }
5601
5602 p = format;
5603 e = p + format_len;
5604 while ((p = memchr(p, '%', (e - p)))) {
5605 if (*(p + 1) == '%') {
5606 p += 2;
5607 } else if (!check) {
5608 check = 1;
5609 p++;
5610 } else {
5611 php_error_docref(NULL, E_WARNING, "Only a single %%i or %%n token can be used");
5612 RETURN_FALSE;
5613 }
5614 }
5615
5616 str = zend_string_safe_alloc(format_len, 1, 1024, 0);
5617 if ((res_len = strfmon(ZSTR_VAL(str), ZSTR_LEN(str), format, value)) < 0) {
5618 zend_string_free(str);
5619 RETURN_FALSE;
5620 }
5621 ZSTR_LEN(str) = (size_t)res_len;
5622 ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
5623
5624 RETURN_NEW_STR(zend_string_truncate(str, ZSTR_LEN(str), 0));
5625 }
5626
5627 #endif
5628
5629
5630
5631 PHP_FUNCTION(str_split)
5632 {
5633 zend_string *str;
5634 zend_long split_length = 1;
5635 char *p;
5636 size_t n_reg_segments;
5637
5638 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &str, &split_length) == FAILURE) {
5639 return;
5640 }
5641
5642 if (split_length <= 0) {
5643 php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero");
5644 RETURN_FALSE;
5645 }
5646
5647
5648 if (0 == ZSTR_LEN(str) || (size_t)split_length >= ZSTR_LEN(str)) {
5649 array_init_size(return_value, 1);
5650 add_next_index_stringl(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
5651 return;
5652 }
5653
5654 array_init_size(return_value, (uint32_t)(((ZSTR_LEN(str) - 1) / split_length) + 1));
5655
5656 n_reg_segments = ZSTR_LEN(str) / split_length;
5657 p = ZSTR_VAL(str);
5658
5659 while (n_reg_segments-- > 0) {
5660 add_next_index_stringl(return_value, p, split_length);
5661 p += split_length;
5662 }
5663
5664 if (p != (ZSTR_VAL(str) + ZSTR_LEN(str))) {
5665 add_next_index_stringl(return_value, p, (ZSTR_VAL(str) + ZSTR_LEN(str) - p));
5666 }
5667 }
5668
5669
5670
5671
5672 PHP_FUNCTION(strpbrk)
5673 {
5674 zend_string *haystack, *char_list;
5675 char *haystack_ptr, *cl_ptr;
5676
5677 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &haystack, &char_list) == FAILURE) {
5678 RETURN_FALSE;
5679 }
5680
5681 if (!ZSTR_LEN(char_list)) {
5682 php_error_docref(NULL, E_WARNING, "The character list cannot be empty");
5683 RETURN_FALSE;
5684 }
5685
5686 for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
5687 for (cl_ptr = ZSTR_VAL(char_list); cl_ptr < (ZSTR_VAL(char_list) + ZSTR_LEN(char_list)); ++cl_ptr) {
5688 if (*cl_ptr == *haystack_ptr) {
5689 RETURN_STRINGL(haystack_ptr, (ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - haystack_ptr));
5690 }
5691 }
5692 }
5693
5694 RETURN_FALSE;
5695 }
5696
5697
5698
5699
5700 PHP_FUNCTION(substr_compare)
5701 {
5702 zend_string *s1, *s2;
5703 zend_long offset, len=0;
5704 zend_bool cs=0;
5705 size_t cmp_len;
5706
5707 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl|lb", &s1, &s2, &offset, &len, &cs) == FAILURE) {
5708 RETURN_FALSE;
5709 }
5710
5711 if (ZEND_NUM_ARGS() >= 4 && len <= 0) {
5712 if (len == 0) {
5713 RETURN_LONG(0L);
5714 } else {
5715 php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero");
5716 RETURN_FALSE;
5717 }
5718 }
5719
5720 if (offset < 0) {
5721 offset = ZSTR_LEN(s1) + offset;
5722 offset = (offset < 0) ? 0 : offset;
5723 }
5724
5725 if ((size_t)offset >= ZSTR_LEN(s1)) {
5726 php_error_docref(NULL, E_WARNING, "The start position cannot exceed initial string length");
5727 RETURN_FALSE;
5728 }
5729
5730 cmp_len = (size_t) (len ? len : MAX(ZSTR_LEN(s2), (ZSTR_LEN(s1) - offset)));
5731
5732 if (!cs) {
5733 RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len));
5734 } else {
5735 RETURN_LONG(zend_binary_strncasecmp_l(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len));
5736 }
5737 }
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747