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