1999-04-17 00:37:12 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2014-09-19 16:33:14 +00:00
|
|
|
| PHP Version 7 |
|
1999-04-17 00:37:12 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2019-01-30 09:00:23 +00:00
|
|
|
| Copyright (c) The PHP Group |
|
1999-04-17 00:37:12 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2006-01-01 12:51:34 +00:00
|
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
1999-07-16 13:13:16 +00:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
2003-06-10 20:04:29 +00:00
|
|
|
| available through the world-wide-web at the following url: |
|
2006-01-01 12:51:34 +00:00
|
|
|
| http://www.php.net/license/3_01.txt |
|
1999-07-16 13:13:16 +00:00
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
1999-04-17 00:37:12 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2000-05-23 20:16:14 +00:00
|
|
|
| Authors: Rasmus Lerdorf <rasmus@php.net> |
|
2018-04-03 16:52:49 +00:00
|
|
|
| Stig Sæther Bakken <ssb@php.net> |
|
2018-11-01 16:30:28 +00:00
|
|
|
| Zeev Suraski <zeev@php.net> |
|
1999-04-17 00:37:12 +00:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "php.h"
|
2002-09-26 19:18:35 +00:00
|
|
|
#include "php_rand.h"
|
1999-12-04 19:19:57 +00:00
|
|
|
#include "php_string.h"
|
2000-01-28 17:24:53 +00:00
|
|
|
#include "php_variables.h"
|
2019-02-24 09:21:25 +00:00
|
|
|
#include <locale.h>
|
2001-07-04 10:10:30 +00:00
|
|
|
#ifdef HAVE_LANGINFO_H
|
|
|
|
# include <langinfo.h>
|
|
|
|
#endif
|
2002-08-21 13:14:57 +00:00
|
|
|
#ifdef HAVE_MONETARY_H
|
|
|
|
# include <monetary.h>
|
|
|
|
#endif
|
2018-01-15 13:01:27 +00:00
|
|
|
|
2012-01-02 00:47:57 +00:00
|
|
|
/*
|
2010-06-02 19:24:36 +00:00
|
|
|
* This define is here because some versions of libintl redefine setlocale
|
|
|
|
* to point to libintl_setlocale. That's a ridiculous thing to do as far
|
2010-06-02 19:26:10 +00:00
|
|
|
* as I am concerned, but with this define and the subsequent undef we
|
|
|
|
* limit the damage to just the actual setlocale() call in this file
|
|
|
|
* without turning zif_setlocale into zif_libintl_setlocale. -Rasmus
|
2010-06-02 19:24:36 +00:00
|
|
|
*/
|
|
|
|
#define php_my_setlocale setlocale
|
2003-05-27 00:42:39 +00:00
|
|
|
#ifdef HAVE_LIBINTL
|
|
|
|
# include <libintl.h> /* For LC_MESSAGES */
|
2010-06-02 05:53:13 +00:00
|
|
|
#ifdef setlocale
|
2010-06-02 19:24:36 +00:00
|
|
|
# undef setlocale
|
2010-06-02 05:53:13 +00:00
|
|
|
#endif
|
2003-05-27 00:42:39 +00:00
|
|
|
#endif
|
2003-02-07 21:36:18 +00:00
|
|
|
|
2000-06-06 18:58:15 +00:00
|
|
|
#include "scanf.h"
|
|
|
|
#include "zend_API.h"
|
1999-06-15 21:51:00 +00:00
|
|
|
#include "zend_execute.h"
|
|
|
|
#include "php_globals.h"
|
1999-12-28 18:47:59 +00:00
|
|
|
#include "basic_functions.h"
|
2014-09-20 20:42:02 +00:00
|
|
|
#include "zend_smart_str.h"
|
2013-01-07 02:13:11 +00:00
|
|
|
#include <Zend/zend_exceptions.h>
|
2001-01-14 16:36:30 +00:00
|
|
|
#ifdef ZTS
|
|
|
|
#include "TSRM.h"
|
|
|
|
#endif
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2008-11-02 18:24:34 +00:00
|
|
|
/* For str_getcsv() support */
|
|
|
|
#include "ext/standard/file.h"
|
2016-10-13 22:33:33 +00:00
|
|
|
/* For php_next_utf8_char() */
|
|
|
|
#include "ext/standard/html.h"
|
2008-11-02 18:24:34 +00:00
|
|
|
|
2000-09-11 13:52:22 +00:00
|
|
|
#define STR_PAD_LEFT 0
|
|
|
|
#define STR_PAD_RIGHT 1
|
|
|
|
#define STR_PAD_BOTH 2
|
2002-01-22 03:35:23 +00:00
|
|
|
#define PHP_PATHINFO_DIRNAME 1
|
|
|
|
#define PHP_PATHINFO_BASENAME 2
|
|
|
|
#define PHP_PATHINFO_EXTENSION 4
|
2006-07-16 10:37:24 +00:00
|
|
|
#define PHP_PATHINFO_FILENAME 8
|
|
|
|
#define PHP_PATHINFO_ALL (PHP_PATHINFO_DIRNAME | PHP_PATHINFO_BASENAME | PHP_PATHINFO_EXTENSION | PHP_PATHINFO_FILENAME)
|
2000-07-08 20:38:23 +00:00
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
#define STR_STRSPN 0
|
|
|
|
#define STR_STRCSPN 1
|
|
|
|
|
2001-06-06 13:06:12 +00:00
|
|
|
/* {{{ register_string_constants
|
|
|
|
*/
|
2000-07-08 20:38:23 +00:00
|
|
|
void register_string_constants(INIT_FUNC_ARGS)
|
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
REGISTER_LONG_CONSTANT("STR_PAD_LEFT", STR_PAD_LEFT, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("STR_PAD_RIGHT", STR_PAD_RIGHT, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("STR_PAD_BOTH", STR_PAD_BOTH, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PATHINFO_DIRNAME", PHP_PATHINFO_DIRNAME, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PATHINFO_BASENAME", PHP_PATHINFO_BASENAME, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("PATHINFO_FILENAME", PHP_PATHINFO_FILENAME, CONST_CS | CONST_PERSISTENT);
|
2000-12-10 15:55:34 +00:00
|
|
|
|
2012-01-02 00:47:57 +00:00
|
|
|
/* If last members of struct lconv equal CHAR_MAX, no grouping is done */
|
2014-08-25 17:24:55 +00:00
|
|
|
REGISTER_LONG_CONSTANT("CHAR_MAX", CHAR_MAX, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("LC_CTYPE", LC_CTYPE, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("LC_NUMERIC", LC_NUMERIC, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("LC_TIME", LC_TIME, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("LC_COLLATE", LC_COLLATE, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("LC_MONETARY", LC_MONETARY, CONST_CS | CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("LC_ALL", LC_ALL, CONST_CS | CONST_PERSISTENT);
|
2000-12-14 15:58:14 +00:00
|
|
|
# ifdef LC_MESSAGES
|
2014-08-25 17:24:55 +00:00
|
|
|
REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);
|
2000-12-11 16:27:48 +00:00
|
|
|
# endif
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2000-07-08 20:38:23 +00:00
|
|
|
}
|
2001-06-06 13:06:12 +00:00
|
|
|
/* }}} */
|
2000-07-08 20:38:23 +00:00
|
|
|
|
2015-07-01 16:04:18 +00:00
|
|
|
int php_tag_find(char *tag, size_t len, const char *set);
|
1999-12-05 14:16:37 +00:00
|
|
|
|
1999-11-28 00:31:02 +00:00
|
|
|
/* this is read-only, so it's ok */
|
2018-01-24 09:14:28 +00:00
|
|
|
ZEND_SET_ALIGNED(16, static char hexconvtab[]) = "0123456789abcdef";
|
1999-05-16 11:12:23 +00:00
|
|
|
|
2001-01-14 16:36:30 +00:00
|
|
|
/* localeconv mutex */
|
|
|
|
#ifdef ZTS
|
|
|
|
static MUTEX_T locale_mutex = NULL;
|
|
|
|
#endif
|
|
|
|
|
2001-06-06 13:06:12 +00:00
|
|
|
/* {{{ php_bin2hex
|
|
|
|
*/
|
2014-02-18 21:12:05 +00:00
|
|
|
static zend_string *php_bin2hex(const unsigned char *old, const size_t oldlen)
|
1999-05-16 11:12:23 +00:00
|
|
|
{
|
2014-02-18 21:12:05 +00:00
|
|
|
zend_string *result;
|
1999-08-12 10:53:29 +00:00
|
|
|
size_t i, j;
|
1999-05-16 11:12:23 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
result = zend_string_safe_alloc(oldlen, 2 * sizeof(char), 0, 0);
|
2013-01-10 12:09:14 +00:00
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
for (i = j = 0; i < oldlen; i++) {
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[j++] = hexconvtab[old[i] >> 4];
|
|
|
|
ZSTR_VAL(result)[j++] = hexconvtab[old[i] & 15];
|
1999-05-16 11:12:23 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[j] = '\0';
|
1999-05-16 11:12:23 +00:00
|
|
|
|
2014-02-18 21:12:05 +00:00
|
|
|
return result;
|
1999-05-16 11:12:23 +00:00
|
|
|
}
|
2001-06-06 13:06:12 +00:00
|
|
|
/* }}} */
|
1999-05-16 11:12:23 +00:00
|
|
|
|
2011-06-03 00:12:22 +00:00
|
|
|
/* {{{ php_hex2bin
|
|
|
|
*/
|
2014-08-13 10:51:48 +00:00
|
|
|
static zend_string *php_hex2bin(const unsigned char *old, const size_t oldlen)
|
2011-06-03 00:12:22 +00:00
|
|
|
{
|
|
|
|
size_t target_length = oldlen >> 1;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_string *str = zend_string_alloc(target_length, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
unsigned char *ret = (unsigned char *)ZSTR_VAL(str);
|
2011-06-03 00:12:22 +00:00
|
|
|
size_t i, j;
|
2014-08-13 10:51:48 +00:00
|
|
|
|
2011-06-03 00:12:22 +00:00
|
|
|
for (i = j = 0; i < target_length; i++) {
|
2014-08-13 10:51:48 +00:00
|
|
|
unsigned char c = old[j++];
|
2015-08-04 20:07:13 +00:00
|
|
|
unsigned char l = c & ~0x20;
|
|
|
|
int is_letter = ((unsigned int) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(unsigned int) - 1);
|
2014-08-13 10:51:48 +00:00
|
|
|
unsigned char d;
|
|
|
|
|
2017-01-16 20:11:50 +00:00
|
|
|
/* basically (c >= '0' && c <= '9') || (l >= 'A' && l <= 'F') */
|
2015-08-04 20:07:13 +00:00
|
|
|
if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(unsigned int) - 1)) | is_letter)) {
|
|
|
|
d = (l - 0x10 - 0x27 * is_letter) << 4;
|
2011-06-03 00:12:22 +00:00
|
|
|
} else {
|
2018-05-08 14:30:15 +00:00
|
|
|
zend_string_efree(str);
|
2011-06-03 00:12:22 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
c = old[j++];
|
2015-08-04 20:07:13 +00:00
|
|
|
l = c & ~0x20;
|
|
|
|
is_letter = ((unsigned int) ((l - 'A') ^ (l - 'F' - 1))) >> (8 * sizeof(unsigned int) - 1);
|
|
|
|
if (EXPECTED((((c ^ '0') - 10) >> (8 * sizeof(unsigned int) - 1)) | is_letter)) {
|
|
|
|
d |= l - 0x10 - 0x27 * is_letter;
|
2011-06-03 00:12:22 +00:00
|
|
|
} else {
|
2018-05-08 14:30:15 +00:00
|
|
|
zend_string_efree(str);
|
2011-06-03 00:12:22 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-08-13 10:51:48 +00:00
|
|
|
ret[i] = d;
|
2011-06-03 00:12:22 +00:00
|
|
|
}
|
2014-08-13 15:43:34 +00:00
|
|
|
ret[i] = '\0';
|
2011-06-03 00:12:22 +00:00
|
|
|
|
2014-08-13 10:51:48 +00:00
|
|
|
return str;
|
2011-06-03 00:12:22 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ localeconv_r
|
|
|
|
* glibc's localeconv is not reentrant, so lets make it so ... sorta */
|
2004-11-03 23:36:51 +00:00
|
|
|
PHPAPI struct lconv *localeconv_r(struct lconv *out)
|
2001-01-14 16:36:30 +00:00
|
|
|
{
|
|
|
|
|
2019-02-24 09:21:25 +00:00
|
|
|
#ifdef ZTS
|
2001-01-14 16:36:30 +00:00
|
|
|
tsrm_mutex_lock( locale_mutex );
|
2019-02-24 09:21:25 +00:00
|
|
|
#endif
|
2001-01-14 16:36:30 +00:00
|
|
|
|
2015-04-05 18:59:26 +00:00
|
|
|
/* cur->locinfo is struct __crt_locale_info which implementation is
|
|
|
|
hidden in vc14. TODO revisit this and check if a workaround available
|
|
|
|
and needed. */
|
|
|
|
#if defined(PHP_WIN32) && _MSC_VER < 1900 && defined(ZTS)
|
2014-12-05 10:06:06 +00:00
|
|
|
{
|
|
|
|
/* Even with the enabled per thread locale, localeconv
|
|
|
|
won't check any locale change in the master thread. */
|
|
|
|
_locale_t cur = _get_current_locale();
|
2016-07-07 12:24:05 +00:00
|
|
|
*out = *cur->locinfo->lconv;
|
|
|
|
_free_locale(cur);
|
2014-12-05 10:06:06 +00:00
|
|
|
}
|
|
|
|
#else
|
2001-01-14 16:36:30 +00:00
|
|
|
/* localeconv doesn't return an error condition */
|
2016-07-07 12:24:05 +00:00
|
|
|
*out = *localeconv();
|
2014-12-05 10:06:06 +00:00
|
|
|
#endif
|
2001-01-14 16:36:30 +00:00
|
|
|
|
2019-02-24 09:21:25 +00:00
|
|
|
#ifdef ZTS
|
2001-01-14 16:36:30 +00:00
|
|
|
tsrm_mutex_unlock( locale_mutex );
|
2019-02-24 09:21:25 +00:00
|
|
|
#endif
|
2001-01-14 16:36:30 +00:00
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-14 16:36:30 +00:00
|
|
|
|
2019-02-24 09:21:25 +00:00
|
|
|
#ifdef ZTS
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ PHP_MINIT_FUNCTION
|
|
|
|
*/
|
2001-01-14 16:36:30 +00:00
|
|
|
PHP_MINIT_FUNCTION(localeconv)
|
|
|
|
{
|
|
|
|
locale_mutex = tsrm_mutex_alloc();
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-14 16:36:30 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ PHP_MSHUTDOWN_FUNCTION
|
|
|
|
*/
|
2001-01-14 16:36:30 +00:00
|
|
|
PHP_MSHUTDOWN_FUNCTION(localeconv)
|
|
|
|
{
|
|
|
|
tsrm_mutex_free( locale_mutex );
|
|
|
|
locale_mutex = NULL;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-14 16:36:30 +00:00
|
|
|
#endif
|
|
|
|
|
2019-08-16 20:44:21 +00:00
|
|
|
/* {{{ proto string bin2hex(string data)
|
2000-02-24 10:11:42 +00:00
|
|
|
Converts the binary representation of data to hex */
|
1999-05-16 11:12:23 +00:00
|
|
|
PHP_FUNCTION(bin2hex)
|
|
|
|
{
|
2014-02-18 21:12:05 +00:00
|
|
|
zend_string *result;
|
2014-08-17 20:56:26 +00:00
|
|
|
zend_string *data;
|
1999-05-16 11:12:23 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(data)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-05-16 11:12:23 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
result = php_bin2hex((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data));
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-02-18 21:12:05 +00:00
|
|
|
RETURN_STR(result);
|
1999-05-16 11:12:23 +00:00
|
|
|
}
|
2000-02-24 10:11:42 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2019-05-30 18:03:28 +00:00
|
|
|
/* {{{ proto string|false hex2bin(string data)
|
2011-06-03 00:12:22 +00:00
|
|
|
Converts the hex representation of data to binary */
|
|
|
|
PHP_FUNCTION(hex2bin)
|
|
|
|
{
|
2014-08-13 10:51:48 +00:00
|
|
|
zend_string *result, *data;
|
2011-06-03 00:12:22 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(data)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2011-06-03 00:12:22 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(data) % 2 != 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Hexadecimal input string must have an even length");
|
2012-04-08 20:36:50 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
result = php_hex2bin((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data));
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2011-06-03 00:12:22 +00:00
|
|
|
if (!result) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Input string must be hexadecimal string");
|
2011-06-03 00:12:22 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2014-08-13 10:51:48 +00:00
|
|
|
RETVAL_STR(result);
|
2011-06-03 00:12:22 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2007-06-05 13:35:26 +00:00
|
|
|
static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-17 20:56:26 +00:00
|
|
|
zend_string *s11, *s22;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long start = 0, len = 0;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 4)
|
|
|
|
Z_PARAM_STR(s11)
|
|
|
|
Z_PARAM_STR(s22)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(start)
|
|
|
|
Z_PARAM_LONG(len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
if (ZEND_NUM_ARGS() < 4) {
|
2015-06-30 01:05:24 +00:00
|
|
|
len = ZSTR_LEN(s11);
|
2002-09-25 19:06:29 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
/* look at substr() function for more information */
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
if (start < 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
start += (zend_long)ZSTR_LEN(s11);
|
2002-09-25 19:06:29 +00:00
|
|
|
if (start < 0) {
|
|
|
|
start = 0;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if ((size_t)start > ZSTR_LEN(s11)) {
|
2002-09-25 19:06:29 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
if (len < 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
len += (ZSTR_LEN(s11) - start);
|
2002-09-25 19:06:29 +00:00
|
|
|
if (len < 0) {
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (len > (zend_long)ZSTR_LEN(s11) - start) {
|
|
|
|
len = ZSTR_LEN(s11) - start;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2007-06-06 17:59:07 +00:00
|
|
|
if(len == 0) {
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(0);
|
2007-06-06 17:59:07 +00:00
|
|
|
}
|
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
if (behavior == STR_STRSPN) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(php_strspn(ZSTR_VAL(s11) + start /*str1_start*/,
|
|
|
|
ZSTR_VAL(s22) /*str2_start*/,
|
|
|
|
ZSTR_VAL(s11) + start + len /*str1_end*/,
|
|
|
|
ZSTR_VAL(s22) + ZSTR_LEN(s22) /*str2_end*/));
|
2002-09-25 19:06:29 +00:00
|
|
|
} else if (behavior == STR_STRCSPN) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(php_strcspn(ZSTR_VAL(s11) + start /*str1_start*/,
|
|
|
|
ZSTR_VAL(s22) /*str2_start*/,
|
|
|
|
ZSTR_VAL(s11) + start + len /*str1_end*/,
|
|
|
|
ZSTR_VAL(s22) + ZSTR_LEN(s22) /*str2_end*/));
|
2002-09-25 19:06:29 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-09-25 19:06:29 +00:00
|
|
|
}
|
2007-06-05 13:35:26 +00:00
|
|
|
/* }}} */
|
2002-09-25 19:06:29 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false strspn(string str, string mask [, int start [, int len]])
|
2002-09-25 19:06:29 +00:00
|
|
|
Finds length of initial segment consisting entirely of characters found in mask. If start or/and length is provided works like strspn(substr($s,$start,$len),$good_chars) */
|
|
|
|
PHP_FUNCTION(strspn)
|
|
|
|
{
|
|
|
|
php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false strcspn(string str, string mask [, int start [, int len]])
|
2002-09-25 19:06:29 +00:00
|
|
|
Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars) */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strcspn)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2002-09-25 19:06:29 +00:00
|
|
|
php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRCSPN);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-07-05 10:49:58 +00:00
|
|
|
/* {{{ PHP_MINIT_FUNCTION(nl_langinfo) */
|
2001-07-04 10:10:30 +00:00
|
|
|
#if HAVE_NL_LANGINFO
|
|
|
|
PHP_MINIT_FUNCTION(nl_langinfo)
|
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
#define REGISTER_NL_LANGINFO_CONSTANT(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
|
2001-08-10 18:02:59 +00:00
|
|
|
#ifdef ABDAY_1
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_1);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_2);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_3);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_4);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_5);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_6);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABDAY_7);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef DAY_1
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_1);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_2);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_3);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_4);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_5);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_6);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DAY_7);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ABMON_1
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_1);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_2);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_3);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_4);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_5);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_6);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_7);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_8);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_9);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_10);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_11);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ABMON_12);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef MON_1
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_1);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_2);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_3);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_4);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_5);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_6);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_7);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_8);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_9);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_10);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_11);
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_12);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef AM_STR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(AM_STR);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef PM_STR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(PM_STR);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef D_T_FMT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(D_T_FMT);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef D_FMT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(D_FMT);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef T_FMT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(T_FMT);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef T_FMT_AMPM
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(T_FMT_AMPM);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ERA
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ERA);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
2001-07-05 10:49:58 +00:00
|
|
|
#ifdef ERA_YEAR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ERA_YEAR);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
2001-08-10 18:02:59 +00:00
|
|
|
#ifdef ERA_D_T_FMT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ERA_D_T_FMT);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ERA_D_FMT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ERA_D_FMT);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ERA_T_FMT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ERA_T_FMT);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
|
|
|
#ifdef ALT_DIGITS
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(ALT_DIGITS);
|
2001-08-10 18:02:59 +00:00
|
|
|
#endif
|
2001-07-05 10:49:58 +00:00
|
|
|
#ifdef INT_CURR_SYMBOL
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(INT_CURR_SYMBOL);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
2001-07-04 10:10:30 +00:00
|
|
|
#ifdef CURRENCY_SYMBOL
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(CURRENCY_SYMBOL);
|
|
|
|
#endif
|
|
|
|
#ifdef CRNCYSTR
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(CRNCYSTR);
|
|
|
|
#endif
|
2001-07-05 10:49:58 +00:00
|
|
|
#ifdef MON_DECIMAL_POINT
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_DECIMAL_POINT);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef MON_THOUSANDS_SEP
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_THOUSANDS_SEP);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef MON_GROUPING
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(MON_GROUPING);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef POSITIVE_SIGN
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(POSITIVE_SIGN);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef NEGATIVE_SIGN
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(NEGATIVE_SIGN);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef INT_FRAC_DIGITS
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(INT_FRAC_DIGITS);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef FRAC_DIGITS
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(FRAC_DIGITS);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef P_CS_PRECEDES
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(P_CS_PRECEDES);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef P_SEP_BY_SPACE
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(P_SEP_BY_SPACE);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef N_CS_PRECEDES
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(N_CS_PRECEDES);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef N_SEP_BY_SPACE
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(N_SEP_BY_SPACE);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef P_SIGN_POSN
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(P_SIGN_POSN);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
|
|
|
#ifdef N_SIGN_POSN
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(N_SIGN_POSN);
|
2001-07-05 10:49:58 +00:00
|
|
|
#endif
|
2001-07-04 10:10:30 +00:00
|
|
|
#ifdef DECIMAL_POINT
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(DECIMAL_POINT);
|
2009-07-27 09:23:06 +00:00
|
|
|
#endif
|
|
|
|
#ifdef RADIXCHAR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(RADIXCHAR);
|
|
|
|
#endif
|
|
|
|
#ifdef THOUSANDS_SEP
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(THOUSANDS_SEP);
|
2009-07-27 09:23:06 +00:00
|
|
|
#endif
|
|
|
|
#ifdef THOUSEP
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(THOUSEP);
|
|
|
|
#endif
|
2001-07-05 10:53:15 +00:00
|
|
|
#ifdef GROUPING
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(GROUPING);
|
2001-07-05 10:53:15 +00:00
|
|
|
#endif
|
|
|
|
#ifdef YESEXPR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(YESEXPR);
|
2001-07-05 10:53:15 +00:00
|
|
|
#endif
|
|
|
|
#ifdef NOEXPR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(NOEXPR);
|
2001-07-05 10:53:15 +00:00
|
|
|
#endif
|
|
|
|
#ifdef YESSTR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(YESSTR);
|
2001-07-05 10:53:15 +00:00
|
|
|
#endif
|
|
|
|
#ifdef NOSTR
|
2001-07-04 10:10:30 +00:00
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(NOSTR);
|
2001-07-05 10:53:15 +00:00
|
|
|
#endif
|
2001-07-04 10:10:30 +00:00
|
|
|
#ifdef CODESET
|
|
|
|
REGISTER_NL_LANGINFO_CONSTANT(CODESET);
|
|
|
|
#endif
|
|
|
|
#undef REGISTER_NL_LANGINFO_CONSTANT
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
2001-07-05 10:49:58 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false nl_langinfo(int item)
|
2001-12-06 19:02:27 +00:00
|
|
|
Query language and locale information */
|
2001-07-04 10:10:30 +00:00
|
|
|
PHP_FUNCTION(nl_langinfo)
|
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long item;
|
2001-09-04 06:18:11 +00:00
|
|
|
char *value;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_LONG(item)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2007-12-13 22:29:48 +00:00
|
|
|
|
|
|
|
switch(item) { /* {{{ */
|
|
|
|
#ifdef ABDAY_1
|
|
|
|
case ABDAY_1:
|
|
|
|
case ABDAY_2:
|
|
|
|
case ABDAY_3:
|
|
|
|
case ABDAY_4:
|
|
|
|
case ABDAY_5:
|
|
|
|
case ABDAY_6:
|
|
|
|
case ABDAY_7:
|
|
|
|
#endif
|
|
|
|
#ifdef DAY_1
|
|
|
|
case DAY_1:
|
|
|
|
case DAY_2:
|
|
|
|
case DAY_3:
|
|
|
|
case DAY_4:
|
|
|
|
case DAY_5:
|
|
|
|
case DAY_6:
|
|
|
|
case DAY_7:
|
|
|
|
#endif
|
|
|
|
#ifdef ABMON_1
|
|
|
|
case ABMON_1:
|
|
|
|
case ABMON_2:
|
|
|
|
case ABMON_3:
|
|
|
|
case ABMON_4:
|
|
|
|
case ABMON_5:
|
|
|
|
case ABMON_6:
|
|
|
|
case ABMON_7:
|
|
|
|
case ABMON_8:
|
|
|
|
case ABMON_9:
|
|
|
|
case ABMON_10:
|
|
|
|
case ABMON_11:
|
|
|
|
case ABMON_12:
|
|
|
|
#endif
|
|
|
|
#ifdef MON_1
|
|
|
|
case MON_1:
|
|
|
|
case MON_2:
|
|
|
|
case MON_3:
|
|
|
|
case MON_4:
|
|
|
|
case MON_5:
|
|
|
|
case MON_6:
|
|
|
|
case MON_7:
|
|
|
|
case MON_8:
|
|
|
|
case MON_9:
|
|
|
|
case MON_10:
|
|
|
|
case MON_11:
|
|
|
|
case MON_12:
|
|
|
|
#endif
|
|
|
|
#ifdef AM_STR
|
|
|
|
case AM_STR:
|
|
|
|
#endif
|
|
|
|
#ifdef PM_STR
|
|
|
|
case PM_STR:
|
|
|
|
#endif
|
|
|
|
#ifdef D_T_FMT
|
|
|
|
case D_T_FMT:
|
|
|
|
#endif
|
|
|
|
#ifdef D_FMT
|
|
|
|
case D_FMT:
|
|
|
|
#endif
|
|
|
|
#ifdef T_FMT
|
|
|
|
case T_FMT:
|
|
|
|
#endif
|
|
|
|
#ifdef T_FMT_AMPM
|
|
|
|
case T_FMT_AMPM:
|
|
|
|
#endif
|
|
|
|
#ifdef ERA
|
|
|
|
case ERA:
|
|
|
|
#endif
|
|
|
|
#ifdef ERA_YEAR
|
|
|
|
case ERA_YEAR:
|
|
|
|
#endif
|
|
|
|
#ifdef ERA_D_T_FMT
|
|
|
|
case ERA_D_T_FMT:
|
|
|
|
#endif
|
|
|
|
#ifdef ERA_D_FMT
|
|
|
|
case ERA_D_FMT:
|
|
|
|
#endif
|
|
|
|
#ifdef ERA_T_FMT
|
|
|
|
case ERA_T_FMT:
|
|
|
|
#endif
|
|
|
|
#ifdef ALT_DIGITS
|
|
|
|
case ALT_DIGITS:
|
|
|
|
#endif
|
|
|
|
#ifdef INT_CURR_SYMBOL
|
|
|
|
case INT_CURR_SYMBOL:
|
|
|
|
#endif
|
|
|
|
#ifdef CURRENCY_SYMBOL
|
|
|
|
case CURRENCY_SYMBOL:
|
|
|
|
#endif
|
|
|
|
#ifdef CRNCYSTR
|
|
|
|
case CRNCYSTR:
|
|
|
|
#endif
|
|
|
|
#ifdef MON_DECIMAL_POINT
|
|
|
|
case MON_DECIMAL_POINT:
|
|
|
|
#endif
|
|
|
|
#ifdef MON_THOUSANDS_SEP
|
|
|
|
case MON_THOUSANDS_SEP:
|
|
|
|
#endif
|
|
|
|
#ifdef MON_GROUPING
|
|
|
|
case MON_GROUPING:
|
|
|
|
#endif
|
|
|
|
#ifdef POSITIVE_SIGN
|
|
|
|
case POSITIVE_SIGN:
|
|
|
|
#endif
|
|
|
|
#ifdef NEGATIVE_SIGN
|
|
|
|
case NEGATIVE_SIGN:
|
|
|
|
#endif
|
|
|
|
#ifdef INT_FRAC_DIGITS
|
|
|
|
case INT_FRAC_DIGITS:
|
|
|
|
#endif
|
|
|
|
#ifdef FRAC_DIGITS
|
|
|
|
case FRAC_DIGITS:
|
|
|
|
#endif
|
|
|
|
#ifdef P_CS_PRECEDES
|
|
|
|
case P_CS_PRECEDES:
|
|
|
|
#endif
|
|
|
|
#ifdef P_SEP_BY_SPACE
|
|
|
|
case P_SEP_BY_SPACE:
|
|
|
|
#endif
|
|
|
|
#ifdef N_CS_PRECEDES
|
|
|
|
case N_CS_PRECEDES:
|
|
|
|
#endif
|
|
|
|
#ifdef N_SEP_BY_SPACE
|
|
|
|
case N_SEP_BY_SPACE:
|
|
|
|
#endif
|
|
|
|
#ifdef P_SIGN_POSN
|
|
|
|
case P_SIGN_POSN:
|
|
|
|
#endif
|
|
|
|
#ifdef N_SIGN_POSN
|
|
|
|
case N_SIGN_POSN:
|
|
|
|
#endif
|
|
|
|
#ifdef DECIMAL_POINT
|
|
|
|
case DECIMAL_POINT:
|
2009-07-27 07:14:40 +00:00
|
|
|
#elif defined(RADIXCHAR)
|
2007-12-13 22:29:48 +00:00
|
|
|
case RADIXCHAR:
|
|
|
|
#endif
|
|
|
|
#ifdef THOUSANDS_SEP
|
|
|
|
case THOUSANDS_SEP:
|
2009-07-27 07:14:40 +00:00
|
|
|
#elif defined(THOUSEP)
|
2007-12-13 22:29:48 +00:00
|
|
|
case THOUSEP:
|
|
|
|
#endif
|
|
|
|
#ifdef GROUPING
|
|
|
|
case GROUPING:
|
|
|
|
#endif
|
|
|
|
#ifdef YESEXPR
|
|
|
|
case YESEXPR:
|
|
|
|
#endif
|
|
|
|
#ifdef NOEXPR
|
|
|
|
case NOEXPR:
|
|
|
|
#endif
|
|
|
|
#ifdef YESSTR
|
|
|
|
case YESSTR:
|
|
|
|
#endif
|
|
|
|
#ifdef NOSTR
|
|
|
|
case NOSTR:
|
|
|
|
#endif
|
|
|
|
#ifdef CODESET
|
|
|
|
case CODESET:
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
default:
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Item '" ZEND_LONG_FMT "' is not valid", item);
|
2007-12-13 22:29:48 +00:00
|
|
|
RETURN_FALSE;
|
2001-07-04 10:10:30 +00:00
|
|
|
}
|
2007-12-13 22:29:48 +00:00
|
|
|
/* }}} */
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2007-12-13 22:29:48 +00:00
|
|
|
value = nl_langinfo(item);
|
2002-10-02 18:13:56 +00:00
|
|
|
if (value == NULL) {
|
2001-07-04 10:10:30 +00:00
|
|
|
RETURN_FALSE;
|
2002-10-02 18:13:56 +00:00
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
RETURN_STRING(value);
|
2001-07-04 10:10:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2002-05-16 14:41:15 +00:00
|
|
|
/* }}} */
|
2001-07-04 10:10:30 +00:00
|
|
|
|
2001-01-17 01:10:50 +00:00
|
|
|
/* {{{ proto int strcoll(string str1, string str2)
|
2001-09-04 10:44:28 +00:00
|
|
|
Compares two strings using the current locale */
|
2001-01-17 01:10:50 +00:00
|
|
|
PHP_FUNCTION(strcoll)
|
|
|
|
{
|
2014-08-18 06:39:39 +00:00
|
|
|
zend_string *s1, *s2;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2001-01-17 01:10:50 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(strcoll((const char *) ZSTR_VAL(s1),
|
|
|
|
(const char *) ZSTR_VAL(s2)));
|
2001-01-17 01:10:50 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-17 01:10:50 +00:00
|
|
|
|
2001-08-03 23:09:05 +00:00
|
|
|
/* {{{ php_charmask
|
|
|
|
* Fills a 256-byte bytemask with input. You can specify a range like 'a..z',
|
2012-01-02 00:47:57 +00:00
|
|
|
* it needs to be incrementing.
|
2006-01-05 20:49:37 +00:00
|
|
|
* Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
|
2001-08-03 23:09:05 +00:00
|
|
|
*/
|
2018-03-16 14:42:41 +00:00
|
|
|
static inline int php_charmask(const unsigned char *input, size_t len, char *mask)
|
2001-08-03 23:09:05 +00:00
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
const unsigned char *end;
|
2001-08-03 23:09:05 +00:00
|
|
|
unsigned char c;
|
2001-08-05 19:38:49 +00:00
|
|
|
int result = SUCCESS;
|
2001-08-03 23:09:05 +00:00
|
|
|
|
|
|
|
memset(mask, 0, 256);
|
2002-10-02 17:56:04 +00:00
|
|
|
for (end = input+len; input < end; input++) {
|
2012-01-02 00:47:57 +00:00
|
|
|
c=*input;
|
|
|
|
if ((input+3 < end) && input[1] == '.' && input[2] == '.'
|
2001-08-05 19:38:49 +00:00
|
|
|
&& input[3] >= c) {
|
|
|
|
memset(mask+c, 1, input[3] - c + 1);
|
2001-08-03 23:09:05 +00:00
|
|
|
input+=3;
|
2002-10-02 17:56:04 +00:00
|
|
|
} else if ((input+1 < end) && input[0] == '.' && input[1] == '.') {
|
2001-08-05 19:38:49 +00:00
|
|
|
/* Error, try to be as helpful as possible:
|
|
|
|
(a range ending/starting with '.' won't be captured here) */
|
2002-10-02 17:56:04 +00:00
|
|
|
if (end-len >= input) { /* there was no 'left' char */
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the left of '..'");
|
2001-08-05 19:38:49 +00:00
|
|
|
result = FAILURE;
|
|
|
|
continue;
|
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
if (input+2 >= end) { /* there is no 'right' char */
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'");
|
2001-08-05 19:38:49 +00:00
|
|
|
result = FAILURE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (input[-1] > input[2]) { /* wrong order */
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing");
|
2001-08-05 19:38:49 +00:00
|
|
|
result = FAILURE;
|
|
|
|
continue;
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
2001-08-05 19:38:49 +00:00
|
|
|
/* FIXME: better error (a..b..c is the only left possibility?) */
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid '..'-range");
|
2001-08-05 19:38:49 +00:00
|
|
|
result = FAILURE;
|
|
|
|
continue;
|
|
|
|
} else {
|
2001-08-03 23:09:05 +00:00
|
|
|
mask[c]=1;
|
2001-08-05 19:38:49 +00:00
|
|
|
}
|
2001-08-03 23:09:05 +00:00
|
|
|
}
|
2001-08-05 19:38:49 +00:00
|
|
|
return result;
|
2001-08-03 23:09:05 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2017-05-30 14:14:08 +00:00
|
|
|
/* {{{ php_trim_int()
|
2002-07-13 04:13:43 +00:00
|
|
|
* mode 1 : trim left
|
|
|
|
* mode 2 : trim right
|
|
|
|
* mode 3 : trim left and right
|
|
|
|
* what indicates which chars are to be trimmed. NULL->default (' \t\n\r\v\0')
|
2001-06-05 13:12:10 +00:00
|
|
|
*/
|
2017-05-30 14:14:08 +00:00
|
|
|
static zend_always_inline zend_string *php_trim_int(zend_string *str, char *what, size_t what_len, int mode)
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
{
|
2017-05-30 14:14:08 +00:00
|
|
|
const char *start = ZSTR_VAL(str);
|
|
|
|
const char *end = start + ZSTR_LEN(str);
|
2001-08-03 23:09:05 +00:00
|
|
|
char mask[256];
|
|
|
|
|
|
|
|
if (what) {
|
2015-01-19 12:45:30 +00:00
|
|
|
if (what_len == 1) {
|
2015-06-24 13:35:13 +00:00
|
|
|
char p = *what;
|
2015-01-19 12:45:30 +00:00
|
|
|
if (mode & 1) {
|
2017-05-30 14:14:08 +00:00
|
|
|
while (start != end) {
|
|
|
|
if (*start == p) {
|
|
|
|
start++;
|
2015-01-19 12:45:30 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2014-12-23 01:29:41 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2015-01-19 12:45:30 +00:00
|
|
|
if (mode & 2) {
|
2017-05-30 14:14:08 +00:00
|
|
|
while (start != end) {
|
|
|
|
if (*(end-1) == p) {
|
|
|
|
end--;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2015-01-19 12:45:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
php_charmask((unsigned char*)what, what_len, mask);
|
|
|
|
|
|
|
|
if (mode & 1) {
|
2017-05-30 14:14:08 +00:00
|
|
|
while (start != end) {
|
|
|
|
if (mask[(unsigned char)*start]) {
|
|
|
|
start++;
|
2014-12-23 01:29:41 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2015-01-19 12:45:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mode & 2) {
|
2017-05-30 14:14:08 +00:00
|
|
|
while (start != end) {
|
|
|
|
if (mask[(unsigned char)*(end-1)]) {
|
|
|
|
end--;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2015-01-19 12:45:30 +00:00
|
|
|
}
|
2014-12-23 01:29:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (mode & 1) {
|
2017-05-30 14:14:08 +00:00
|
|
|
while (start != end) {
|
|
|
|
unsigned char c = (unsigned char)*start;
|
|
|
|
|
|
|
|
if (c <= ' ' &&
|
|
|
|
(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\0')) {
|
|
|
|
start++;
|
2014-09-16 20:15:27 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2014-12-23 01:29:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mode & 2) {
|
2017-05-30 14:14:08 +00:00
|
|
|
while (start != end) {
|
|
|
|
unsigned char c = (unsigned char)*(end-1);
|
|
|
|
|
|
|
|
if (c <= ' ' &&
|
|
|
|
(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\0')) {
|
|
|
|
end--;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2014-12-23 01:29:41 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-30 14:14:08 +00:00
|
|
|
if (ZSTR_LEN(str) == end - start) {
|
2014-12-23 01:29:41 +00:00
|
|
|
return zend_string_copy(str);
|
2017-05-30 14:14:08 +00:00
|
|
|
} else if (end - start == 0) {
|
|
|
|
return ZSTR_EMPTY_ALLOC();
|
2002-07-13 04:13:43 +00:00
|
|
|
} else {
|
2017-05-30 14:14:08 +00:00
|
|
|
return zend_string_init(start, end - start, 0);
|
2002-07-13 04:13:43 +00:00
|
|
|
}
|
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2017-05-30 14:14:08 +00:00
|
|
|
/* {{{ php_trim_int()
|
|
|
|
* mode 1 : trim left
|
|
|
|
* mode 2 : trim right
|
|
|
|
* mode 3 : trim left and right
|
|
|
|
* what indicates which chars are to be trimmed. NULL->default (' \t\n\r\v\0')
|
|
|
|
*/
|
|
|
|
PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode)
|
|
|
|
{
|
|
|
|
return php_trim_int(str, what, what_len, mode);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2002-07-13 04:13:43 +00:00
|
|
|
/* {{{ php_do_trim
|
|
|
|
* Base for trim(), rtrim() and ltrim() functions.
|
|
|
|
*/
|
2017-05-30 14:14:08 +00:00
|
|
|
static zend_always_inline void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str;
|
|
|
|
zend_string *what = NULL;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
2014-08-16 10:55:13 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-11 12:32:20 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
2014-08-16 10:55:13 +00:00
|
|
|
Z_PARAM_STR(what)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2017-05-30 14:14:08 +00:00
|
|
|
ZVAL_STR(return_value, php_trim_int(str, (what ? ZSTR_VAL(what) : NULL), (what ? ZSTR_LEN(what) : 0), mode));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-09-04 10:44:28 +00:00
|
|
|
/* {{{ proto string trim(string str [, string character_mask])
|
|
|
|
Strips whitespace from the beginning and end of a string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(trim)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2002-07-13 04:13:43 +00:00
|
|
|
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
|
|
|
|
}
|
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2002-07-13 04:13:43 +00:00
|
|
|
/* {{{ proto string rtrim(string str [, string character_mask])
|
|
|
|
Removes trailing whitespace */
|
|
|
|
PHP_FUNCTION(rtrim)
|
|
|
|
{
|
|
|
|
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-09-04 10:44:28 +00:00
|
|
|
/* {{{ proto string ltrim(string str [, string character_mask])
|
|
|
|
Strips whitespace from the beginning of a string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(ltrim)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2002-07-13 04:13:43 +00:00
|
|
|
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 10:11:32 +00:00
|
|
|
/* {{{ proto string|false wordwrap(string str [, int width [, string break [, bool cut]]])
|
2001-09-04 10:44:28 +00:00
|
|
|
Wraps buffer to selected number of characters using string break char */
|
2000-07-22 01:12:24 +00:00
|
|
|
PHP_FUNCTION(wordwrap)
|
|
|
|
{
|
2014-08-27 13:31:48 +00:00
|
|
|
zend_string *text;
|
|
|
|
char *breakchar = "\n";
|
|
|
|
size_t newtextlen, chk, breakchar_len = 1;
|
2006-08-10 14:40:13 +00:00
|
|
|
size_t alloced;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long current = 0, laststart = 0, lastspace = 0;
|
|
|
|
zend_long linelength = 75;
|
2002-01-04 19:48:08 +00:00
|
|
|
zend_bool docut = 0;
|
2014-02-23 10:17:39 +00:00
|
|
|
zend_string *newtext;
|
2000-07-22 01:12:24 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 4)
|
|
|
|
Z_PARAM_STR(text)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(linelength)
|
|
|
|
Z_PARAM_STRING(breakchar, breakchar_len)
|
|
|
|
Z_PARAM_BOOL(docut)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2014-08-18 13:39:38 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(text) == 0) {
|
2004-07-06 22:16:42 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
2000-07-22 01:12:24 +00:00
|
|
|
|
2014-08-27 13:31:48 +00:00
|
|
|
if (breakchar_len == 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Break string cannot be empty");
|
2007-07-22 15:55:16 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2002-01-04 19:48:08 +00:00
|
|
|
if (linelength == 0 && docut) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero");
|
2002-01-04 19:48:08 +00:00
|
|
|
RETURN_FALSE;
|
2000-09-11 20:06:24 +00:00
|
|
|
}
|
|
|
|
|
2000-07-22 01:12:24 +00:00
|
|
|
/* Special case for a single-character break as it needs no
|
|
|
|
additional storage space */
|
2014-08-27 13:31:48 +00:00
|
|
|
if (breakchar_len == 1 && !docut) {
|
2015-06-30 01:05:24 +00:00
|
|
|
newtext = zend_string_init(ZSTR_VAL(text), ZSTR_LEN(text), 0);
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2002-01-05 20:46:43 +00:00
|
|
|
laststart = lastspace = 0;
|
2016-06-23 09:47:06 +00:00
|
|
|
for (current = 0; current < (zend_long)ZSTR_LEN(text); current++) {
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_VAL(text)[current] == breakchar[0]) {
|
2009-08-31 12:28:46 +00:00
|
|
|
laststart = lastspace = current + 1;
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (ZSTR_VAL(text)[current] == ' ') {
|
2002-01-05 20:46:43 +00:00
|
|
|
if (current - laststart >= linelength) {
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(newtext)[current] = breakchar[0];
|
2004-05-13 17:44:23 +00:00
|
|
|
laststart = current + 1;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
2002-01-05 20:46:43 +00:00
|
|
|
lastspace = current;
|
2002-10-10 18:41:24 +00:00
|
|
|
} else if (current - laststart >= linelength && laststart != lastspace) {
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(newtext)[lastspace] = breakchar[0];
|
2006-07-28 12:23:18 +00:00
|
|
|
laststart = lastspace + 1;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(newtext);
|
2002-10-10 18:41:24 +00:00
|
|
|
} else {
|
2002-01-05 20:46:43 +00:00
|
|
|
/* Multiple character line break or forced cut */
|
|
|
|
if (linelength > 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
chk = (size_t)(ZSTR_LEN(text)/linelength + 1);
|
2016-01-27 06:10:43 +00:00
|
|
|
newtext = zend_string_safe_alloc(chk, breakchar_len, ZSTR_LEN(text), 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
alloced = ZSTR_LEN(text) + chk * breakchar_len + 1;
|
2002-10-10 18:41:24 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
chk = ZSTR_LEN(text);
|
|
|
|
alloced = ZSTR_LEN(text) * (breakchar_len + 1) + 1;
|
2016-01-27 06:10:43 +00:00
|
|
|
newtext = zend_string_safe_alloc(ZSTR_LEN(text), breakchar_len + 1, 0, 0);
|
2002-01-05 20:46:43 +00:00
|
|
|
}
|
2002-12-12 13:38:19 +00:00
|
|
|
|
2002-01-05 20:46:43 +00:00
|
|
|
/* now keep track of the actual new text length */
|
|
|
|
newtextlen = 0;
|
|
|
|
|
|
|
|
laststart = lastspace = 0;
|
2016-06-23 09:47:06 +00:00
|
|
|
for (current = 0; current < (zend_long)ZSTR_LEN(text); current++) {
|
2017-11-17 20:35:22 +00:00
|
|
|
if (chk == 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
alloced += (size_t) (((ZSTR_LEN(text) - current + 1)/linelength + 1) * breakchar_len) + 1;
|
2015-03-19 23:02:42 +00:00
|
|
|
newtext = zend_string_extend(newtext, alloced, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
chk = (size_t) ((ZSTR_LEN(text) - current)/linelength) + 1;
|
2002-12-12 13:38:19 +00:00
|
|
|
}
|
2002-01-05 20:46:43 +00:00
|
|
|
/* when we hit an existing break, copy to new buffer, and
|
|
|
|
* fix up laststart and lastspace */
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_VAL(text)[current] == breakchar[0]
|
|
|
|
&& current + breakchar_len < ZSTR_LEN(text)
|
|
|
|
&& !strncmp(ZSTR_VAL(text) + current, breakchar, breakchar_len)) {
|
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart + breakchar_len);
|
2014-08-27 13:31:48 +00:00
|
|
|
newtextlen += current - laststart + breakchar_len;
|
|
|
|
current += breakchar_len - 1;
|
2002-01-05 20:46:43 +00:00
|
|
|
laststart = lastspace = current + 1;
|
2002-12-12 13:38:19 +00:00
|
|
|
chk--;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
2002-01-05 20:46:43 +00:00
|
|
|
/* if it is a space, check if it is at the line boundary,
|
|
|
|
* copy and insert a break, or just keep track of it */
|
2015-06-30 01:05:24 +00:00
|
|
|
else if (ZSTR_VAL(text)[current] == ' ') {
|
2002-01-05 20:46:43 +00:00
|
|
|
if (current - laststart >= linelength) {
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
|
2002-01-05 20:46:43 +00:00
|
|
|
newtextlen += current - laststart;
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
|
2014-08-27 13:31:48 +00:00
|
|
|
newtextlen += breakchar_len;
|
2002-01-05 20:46:43 +00:00
|
|
|
laststart = current + 1;
|
2002-12-12 13:38:19 +00:00
|
|
|
chk--;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
2002-01-05 20:46:43 +00:00
|
|
|
lastspace = current;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
2002-01-05 20:46:43 +00:00
|
|
|
/* if we are cutting, and we've accumulated enough
|
2002-01-05 23:49:58 +00:00
|
|
|
* characters, and we haven't see a space for this line,
|
|
|
|
* copy and insert a break. */
|
|
|
|
else if (current - laststart >= linelength
|
|
|
|
&& docut && laststart >= lastspace) {
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
|
2002-01-05 20:46:43 +00:00
|
|
|
newtextlen += current - laststart;
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
|
2014-08-27 13:31:48 +00:00
|
|
|
newtextlen += breakchar_len;
|
2002-01-05 20:46:43 +00:00
|
|
|
laststart = lastspace = current;
|
2002-12-12 13:38:19 +00:00
|
|
|
chk--;
|
2002-01-05 20:46:43 +00:00
|
|
|
}
|
|
|
|
/* if the current word puts us over the linelength, copy
|
|
|
|
* back up until the last space, insert a break, and move
|
|
|
|
* up the laststart */
|
|
|
|
else if (current - laststart >= linelength
|
|
|
|
&& laststart < lastspace) {
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, lastspace - laststart);
|
2002-01-05 20:46:43 +00:00
|
|
|
newtextlen += lastspace - laststart;
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, breakchar, breakchar_len);
|
2014-08-27 13:31:48 +00:00
|
|
|
newtextlen += breakchar_len;
|
2002-01-05 20:46:43 +00:00
|
|
|
laststart = lastspace = lastspace + 1;
|
2002-12-12 13:38:19 +00:00
|
|
|
chk--;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-01-05 20:46:43 +00:00
|
|
|
/* copy over any stragglers */
|
|
|
|
if (laststart != current) {
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(newtext) + newtextlen, ZSTR_VAL(text) + laststart, current - laststart);
|
2002-01-05 20:46:43 +00:00
|
|
|
newtextlen += current - laststart;
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(newtext)[newtextlen] = '\0';
|
2002-09-05 14:00:28 +00:00
|
|
|
/* free unused memory */
|
2015-03-19 23:02:42 +00:00
|
|
|
newtext = zend_string_truncate(newtext, newtextlen, 0);
|
2002-01-05 20:46:43 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(newtext);
|
2000-07-22 01:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_explode
|
|
|
|
*/
|
2014-10-07 14:43:50 +00:00
|
|
|
PHPAPI void php_explode(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
const char *p1 = ZSTR_VAL(str);
|
|
|
|
const char *endp = ZSTR_VAL(str) + ZSTR_LEN(str);
|
|
|
|
const char *p2 = php_memnstr(ZSTR_VAL(str), ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
|
2015-05-05 13:20:29 +00:00
|
|
|
zval tmp;
|
1999-12-06 18:29:22 +00:00
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
if (p2 == NULL) {
|
2015-05-05 13:20:29 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, str);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
1999-12-07 08:14:00 +00:00
|
|
|
} else {
|
|
|
|
do {
|
2017-05-18 14:59:59 +00:00
|
|
|
size_t l = p2 - p1;
|
|
|
|
|
|
|
|
if (l == 0) {
|
|
|
|
ZVAL_EMPTY_STRING(&tmp);
|
|
|
|
} else if (l == 1) {
|
|
|
|
ZVAL_INTERNED_STR(&tmp, ZSTR_CHAR((zend_uchar)(*p1)));
|
|
|
|
} else {
|
|
|
|
ZVAL_STRINGL(&tmp, p1, p2 - p1);
|
|
|
|
}
|
2015-05-05 13:20:29 +00:00
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
2015-06-30 01:05:24 +00:00
|
|
|
p1 = p2 + ZSTR_LEN(delim);
|
2018-03-16 14:42:41 +00:00
|
|
|
p2 = php_memnstr(p1, ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
|
2014-10-07 14:43:50 +00:00
|
|
|
} while (p2 != NULL && --limit > 1);
|
1999-12-07 08:14:00 +00:00
|
|
|
|
2014-10-07 14:43:50 +00:00
|
|
|
if (p1 <= endp) {
|
2015-05-05 13:20:29 +00:00
|
|
|
ZVAL_STRINGL(&tmp, p1, endp - p1);
|
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
2014-10-07 14:43:50 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2004-07-18 11:34:28 +00:00
|
|
|
/* {{{ php_explode_negative_limit
|
|
|
|
*/
|
2014-10-07 14:43:50 +00:00
|
|
|
PHPAPI void php_explode_negative_limit(const zend_string *delim, zend_string *str, zval *return_value, zend_long limit)
|
2004-07-18 11:34:28 +00:00
|
|
|
{
|
2009-04-01 17:05:36 +00:00
|
|
|
#define EXPLODE_ALLOC_STEP 64
|
2018-03-16 14:42:41 +00:00
|
|
|
const char *p1 = ZSTR_VAL(str);
|
|
|
|
const char *endp = ZSTR_VAL(str) + ZSTR_LEN(str);
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *p2 = php_memnstr(ZSTR_VAL(str), ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
|
2015-05-05 13:20:29 +00:00
|
|
|
zval tmp;
|
2004-07-18 11:34:28 +00:00
|
|
|
|
|
|
|
if (p2 == NULL) {
|
|
|
|
/*
|
|
|
|
do nothing since limit <= -1, thus if only one chunk - 1 + (limit) <= 0
|
|
|
|
by doing nothing we return empty array
|
|
|
|
*/
|
|
|
|
} else {
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t allocated = EXPLODE_ALLOC_STEP, found = 0;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long i, to_return;
|
2018-03-16 14:42:41 +00:00
|
|
|
const char **positions = emalloc(allocated * sizeof(char *));
|
2009-04-01 17:05:36 +00:00
|
|
|
|
2004-07-18 11:34:28 +00:00
|
|
|
positions[found++] = p1;
|
|
|
|
do {
|
|
|
|
if (found >= allocated) {
|
|
|
|
allocated = found + EXPLODE_ALLOC_STEP;/* make sure we have enough memory */
|
|
|
|
positions = erealloc(positions, allocated*sizeof(char *));
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
positions[found++] = p1 = p2 + ZSTR_LEN(delim);
|
2018-03-16 19:36:41 +00:00
|
|
|
p2 = php_memnstr(p1, ZSTR_VAL(delim), ZSTR_LEN(delim), endp);
|
2014-10-07 14:43:50 +00:00
|
|
|
} while (p2 != NULL);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2004-07-18 11:34:28 +00:00
|
|
|
to_return = limit + found;
|
|
|
|
/* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
|
2014-10-07 14:43:50 +00:00
|
|
|
for (i = 0; i < to_return; i++) { /* this checks also for to_return > 0 */
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_STRINGL(&tmp, positions[i], (positions[i+1] - ZSTR_LEN(delim)) - positions[i]);
|
2015-05-05 13:20:29 +00:00
|
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
2004-07-18 11:34:28 +00:00
|
|
|
}
|
2018-03-16 14:42:41 +00:00
|
|
|
efree((void *)positions);
|
2004-07-18 11:34:28 +00:00
|
|
|
}
|
|
|
|
#undef EXPLODE_ALLOC_STEP
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto array|false explode(string separator, string str [, int limit])
|
2004-07-18 11:34:28 +00:00
|
|
|
Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
PHP_FUNCTION(explode)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-02-24 07:03:35 +00:00
|
|
|
zend_string *str, *delim;
|
2014-08-25 18:22:49 +00:00
|
|
|
zend_long limit = ZEND_LONG_MAX; /* No limit */
|
2015-05-05 13:20:29 +00:00
|
|
|
zval tmp;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(delim)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_PARAM_LONG(limit)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(delim) == 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Empty delimiter");
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-12-06 18:29:22 +00:00
|
|
|
|
2002-12-05 22:28:02 +00:00
|
|
|
array_init(return_value);
|
1999-12-06 18:29:22 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(str) == 0) {
|
2009-04-01 17:05:36 +00:00
|
|
|
if (limit >= 0) {
|
2015-05-05 13:20:29 +00:00
|
|
|
ZVAL_EMPTY_STRING(&tmp);
|
|
|
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
2004-07-18 11:34:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-01 17:05:36 +00:00
|
|
|
if (limit > 1) {
|
2014-10-07 14:43:50 +00:00
|
|
|
php_explode(delim, str, return_value, limit);
|
2009-04-01 17:05:36 +00:00
|
|
|
} else if (limit < 0) {
|
2014-10-07 14:43:50 +00:00
|
|
|
php_explode_negative_limit(delim, str, return_value, limit);
|
2000-05-23 05:04:28 +00:00
|
|
|
} else {
|
2015-05-05 13:20:29 +00:00
|
|
|
ZVAL_STR_COPY(&tmp, str);
|
|
|
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
|
2000-05-23 05:04:28 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string join(array src, string glue)
|
|
|
|
An alias for implode */
|
|
|
|
/* }}} */
|
2001-06-05 13:12:10 +00:00
|
|
|
|
|
|
|
/* {{{ php_implode
|
|
|
|
*/
|
2016-11-20 21:50:56 +00:00
|
|
|
PHPAPI void php_implode(const zend_string *glue, zval *pieces, zval *return_value)
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
{
|
2015-06-23 13:46:41 +00:00
|
|
|
zval *tmp;
|
2015-05-25 20:58:30 +00:00
|
|
|
int numelems;
|
|
|
|
zend_string *str;
|
|
|
|
char *cptr;
|
|
|
|
size_t len = 0;
|
2017-12-26 10:29:18 +00:00
|
|
|
struct {
|
|
|
|
zend_string *str;
|
|
|
|
zend_long lval;
|
|
|
|
} *strings, *ptr;
|
|
|
|
ALLOCA_FLAG(use_heap)
|
2002-10-04 20:44:19 +00:00
|
|
|
|
2016-11-20 21:50:56 +00:00
|
|
|
numelems = zend_hash_num_elements(Z_ARRVAL_P(pieces));
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2003-02-08 15:26:17 +00:00
|
|
|
if (numelems == 0) {
|
2002-10-06 11:28:11 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
2015-05-25 20:58:30 +00:00
|
|
|
} else if (numelems == 1) {
|
|
|
|
/* loop to search the first not undefined element... */
|
2016-11-20 21:50:56 +00:00
|
|
|
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pieces), tmp) {
|
2015-05-25 20:58:30 +00:00
|
|
|
RETURN_STR(zval_get_string(tmp));
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
2002-10-06 11:28:11 +00:00
|
|
|
}
|
|
|
|
|
2017-12-26 10:29:18 +00:00
|
|
|
ptr = strings = do_alloca((sizeof(*strings)) * numelems, use_heap);
|
2014-05-28 16:45:00 +00:00
|
|
|
|
2016-11-20 21:50:56 +00:00
|
|
|
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pieces), tmp) {
|
2017-12-26 10:29:18 +00:00
|
|
|
if (EXPECTED(Z_TYPE_P(tmp) == IS_STRING)) {
|
|
|
|
ptr->str = Z_STR_P(tmp);
|
|
|
|
len += ZSTR_LEN(ptr->str);
|
|
|
|
ptr->lval = 0;
|
|
|
|
ptr++;
|
|
|
|
} else if (UNEXPECTED(Z_TYPE_P(tmp) == IS_LONG)) {
|
2016-04-26 10:04:06 +00:00
|
|
|
zend_long val = Z_LVAL_P(tmp);
|
|
|
|
|
2017-12-26 10:29:18 +00:00
|
|
|
ptr->str = NULL;
|
|
|
|
ptr->lval = val;
|
|
|
|
ptr++;
|
2016-04-26 10:04:06 +00:00
|
|
|
if (val <= 0) {
|
|
|
|
len++;
|
2015-06-23 13:46:41 +00:00
|
|
|
}
|
2016-04-26 10:04:06 +00:00
|
|
|
while (val) {
|
|
|
|
val /= 10;
|
2015-06-23 13:46:41 +00:00
|
|
|
len++;
|
|
|
|
}
|
|
|
|
} else {
|
2017-12-26 10:29:18 +00:00
|
|
|
ptr->str = zval_get_string_func(tmp);
|
|
|
|
len += ZSTR_LEN(ptr->str);
|
|
|
|
ptr->lval = 1;
|
|
|
|
ptr++;
|
2015-06-23 13:46:41 +00:00
|
|
|
}
|
2015-05-25 20:58:30 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2017-12-26 10:29:18 +00:00
|
|
|
|
2016-01-27 06:10:43 +00:00
|
|
|
/* numelems can not be 0, we checked above */
|
2016-11-20 21:50:56 +00:00
|
|
|
str = zend_string_safe_alloc(numelems - 1, ZSTR_LEN(glue), len, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
cptr = ZSTR_VAL(str) + ZSTR_LEN(str);
|
2015-06-23 13:46:41 +00:00
|
|
|
*cptr = 0;
|
|
|
|
|
2017-12-26 10:29:18 +00:00
|
|
|
while (1) {
|
|
|
|
ptr--;
|
|
|
|
if (EXPECTED(ptr->str)) {
|
|
|
|
cptr -= ZSTR_LEN(ptr->str);
|
|
|
|
memcpy(cptr, ZSTR_VAL(ptr->str), ZSTR_LEN(ptr->str));
|
|
|
|
if (ptr->lval) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(ptr->str, 0);
|
2017-12-26 10:29:18 +00:00
|
|
|
}
|
2015-06-23 13:46:41 +00:00
|
|
|
} else {
|
|
|
|
char *oldPtr = cptr;
|
|
|
|
char oldVal = *cptr;
|
2017-12-26 10:29:18 +00:00
|
|
|
cptr = zend_print_long_to_buf(cptr, ptr->lval);
|
2015-06-23 13:46:41 +00:00
|
|
|
*oldPtr = oldVal;
|
|
|
|
}
|
2015-05-25 23:12:23 +00:00
|
|
|
|
2017-12-26 10:29:18 +00:00
|
|
|
if (ptr == strings) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-11-20 21:50:56 +00:00
|
|
|
cptr -= ZSTR_LEN(glue);
|
|
|
|
memcpy(cptr, ZSTR_VAL(glue), ZSTR_LEN(glue));
|
2015-06-23 13:46:41 +00:00
|
|
|
}
|
2015-06-23 09:57:36 +00:00
|
|
|
|
2017-12-26 10:29:18 +00:00
|
|
|
free_alloca(strings, use_heap);
|
2015-05-25 20:58:30 +00:00
|
|
|
RETURN_NEW_STR(str);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2002-10-04 16:53:14 +00:00
|
|
|
/* {{{ proto string implode([string glue,] array pieces)
|
2001-09-04 10:44:28 +00:00
|
|
|
Joins array elements placing glue string between items and return one string */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
PHP_FUNCTION(implode)
|
|
|
|
{
|
2016-11-20 21:50:56 +00:00
|
|
|
zval *arg1, *arg2 = NULL, *pieces;
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *glue, *tmp_glue;
|
2002-10-04 16:53:14 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_ZVAL(arg1)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_ZVAL(arg2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-06-22 19:22:41 +00:00
|
|
|
if (arg2 == NULL) {
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(arg1) != IS_ARRAY) {
|
2019-05-31 09:04:13 +00:00
|
|
|
zend_type_error("Argument must be an array");
|
2002-10-04 16:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-20 21:50:56 +00:00
|
|
|
glue = ZSTR_EMPTY_ALLOC();
|
2017-11-16 14:09:32 +00:00
|
|
|
tmp_glue = NULL;
|
2016-11-20 21:50:56 +00:00
|
|
|
pieces = arg1;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(arg1) == IS_ARRAY) {
|
2017-11-16 14:09:32 +00:00
|
|
|
glue = zval_get_tmp_string(arg2, &tmp_glue);
|
2016-11-20 21:50:56 +00:00
|
|
|
pieces = arg1;
|
2019-07-12 08:31:16 +00:00
|
|
|
php_error_docref(NULL, E_DEPRECATED,
|
|
|
|
"Passing glue string after array is deprecated. Swap the parameters");
|
2014-02-10 13:49:21 +00:00
|
|
|
} else if (Z_TYPE_P(arg2) == IS_ARRAY) {
|
2017-11-16 14:09:32 +00:00
|
|
|
glue = zval_get_tmp_string(arg1, &tmp_glue);
|
2016-11-20 21:50:56 +00:00
|
|
|
pieces = arg2;
|
2002-10-04 16:53:14 +00:00
|
|
|
} else {
|
2019-05-31 09:04:13 +00:00
|
|
|
zend_type_error("Invalid arguments passed");
|
2002-10-04 16:53:14 +00:00
|
|
|
return;
|
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-11-20 21:50:56 +00:00
|
|
|
php_implode(glue, pieces, return_value);
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_glue);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2012-01-02 00:47:57 +00:00
|
|
|
#define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]
|
2001-08-03 23:09:05 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false strtok([string str,] string token)
|
1999-04-17 00:37:12 +00:00
|
|
|
Tokenize a string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strtok)
|
2012-01-02 00:47:57 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str, *tok = NULL;
|
2001-08-03 23:09:05 +00:00
|
|
|
char *token;
|
|
|
|
char *token_end;
|
|
|
|
char *p;
|
|
|
|
char *pe;
|
2014-08-28 19:59:00 +00:00
|
|
|
size_t skipped = 0;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-01-17 16:30:40 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STR(tok)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-02-08 15:26:17 +00:00
|
|
|
|
2008-08-16 21:32:41 +00:00
|
|
|
if (ZEND_NUM_ARGS() == 1) {
|
|
|
|
tok = str;
|
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
zval_ptr_dtor(&BG(strtok_zval));
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_STRINGL(&BG(strtok_zval), ZSTR_VAL(str), ZSTR_LEN(str));
|
2014-02-10 13:49:21 +00:00
|
|
|
BG(strtok_last) = BG(strtok_string) = Z_STRVAL(BG(strtok_zval));
|
2015-06-30 01:05:24 +00:00
|
|
|
BG(strtok_len) = ZSTR_LEN(str);
|
2001-08-03 08:49:19 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-08-03 23:09:05 +00:00
|
|
|
p = BG(strtok_last); /* Where we start to search */
|
|
|
|
pe = BG(strtok_string) + BG(strtok_len);
|
2001-08-03 08:49:19 +00:00
|
|
|
|
2003-02-08 15:26:17 +00:00
|
|
|
if (!p || p >= pe) {
|
2001-08-03 23:09:05 +00:00
|
|
|
RETURN_FALSE;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
token = ZSTR_VAL(tok);
|
|
|
|
token_end = token + ZSTR_LEN(tok);
|
2001-08-03 23:09:05 +00:00
|
|
|
|
2003-02-08 15:26:17 +00:00
|
|
|
while (token < token_end) {
|
2001-08-03 23:09:05 +00:00
|
|
|
STRTOK_TABLE(token++) = 1;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-08-03 23:09:05 +00:00
|
|
|
/* Skip leading delimiters */
|
2002-10-10 18:41:24 +00:00
|
|
|
while (STRTOK_TABLE(p)) {
|
2001-08-03 23:09:05 +00:00
|
|
|
if (++p >= pe) {
|
|
|
|
/* no other chars left */
|
|
|
|
BG(strtok_last) = NULL;
|
|
|
|
RETVAL_FALSE;
|
|
|
|
goto restore;
|
2001-08-03 22:42:02 +00:00
|
|
|
}
|
2001-11-02 19:19:24 +00:00
|
|
|
skipped++;
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
|
|
|
/* We know at this place that *p is no delimiter, so skip it */
|
2003-02-08 15:26:17 +00:00
|
|
|
while (++p < pe) {
|
|
|
|
if (STRTOK_TABLE(p)) {
|
2012-01-02 00:47:57 +00:00
|
|
|
goto return_token;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-08-03 23:09:05 +00:00
|
|
|
if (p - BG(strtok_last)) {
|
|
|
|
return_token:
|
2014-02-10 13:49:21 +00:00
|
|
|
RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped);
|
2001-08-03 23:09:05 +00:00
|
|
|
BG(strtok_last) = p + 1;
|
1999-04-17 00:37:12 +00:00
|
|
|
} else {
|
|
|
|
RETVAL_FALSE;
|
2001-08-03 23:09:05 +00:00
|
|
|
BG(strtok_last) = NULL;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-08-03 23:09:05 +00:00
|
|
|
|
2003-02-08 15:26:17 +00:00
|
|
|
/* Restore table -- usually faster then memset'ing the table on every invocation */
|
2001-08-03 23:09:05 +00:00
|
|
|
restore:
|
2015-06-30 01:05:24 +00:00
|
|
|
token = ZSTR_VAL(tok);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2003-02-08 15:26:17 +00:00
|
|
|
while (token < token_end) {
|
2001-08-03 23:09:05 +00:00
|
|
|
STRTOK_TABLE(token++) = 0;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strtoupper
|
|
|
|
*/
|
1999-12-09 23:45:30 +00:00
|
|
|
PHPAPI char *php_strtoupper(char *s, size_t len)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
unsigned char *c;
|
|
|
|
const unsigned char *e;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2009-08-13 06:44:50 +00:00
|
|
|
c = (unsigned char *)s;
|
|
|
|
e = (unsigned char *)c+len;
|
2002-08-25 19:08:07 +00:00
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
while (c < e) {
|
2002-08-25 19:08:07 +00:00
|
|
|
*c = toupper(*c);
|
|
|
|
c++;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
return s;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2014-12-25 03:28:54 +00:00
|
|
|
/* {{{ php_string_toupper
|
|
|
|
*/
|
|
|
|
PHPAPI zend_string *php_string_toupper(zend_string *s)
|
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
unsigned char *c;
|
|
|
|
const unsigned char *e;
|
2014-12-25 03:28:54 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
c = (unsigned char *)ZSTR_VAL(s);
|
|
|
|
e = c + ZSTR_LEN(s);
|
2014-12-25 03:28:54 +00:00
|
|
|
|
|
|
|
while (c < e) {
|
2015-12-13 05:22:50 +00:00
|
|
|
if (islower(*c)) {
|
2014-12-25 03:28:54 +00:00
|
|
|
register unsigned char *r;
|
2015-06-30 01:05:24 +00:00
|
|
|
zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
|
2014-12-25 03:28:54 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (c != (unsigned char*)ZSTR_VAL(s)) {
|
|
|
|
memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
|
2014-12-25 03:28:54 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
|
2014-12-25 03:28:54 +00:00
|
|
|
while (c < e) {
|
|
|
|
*r = toupper(*c);
|
|
|
|
r++;
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
*r = '\0';
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
return zend_string_copy(s);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
/* {{{ proto string strtoupper(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Makes a string uppercase */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strtoupper)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *arg;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-01-12 16:26:12 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(arg)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2014-12-25 03:28:54 +00:00
|
|
|
RETURN_STR(php_string_toupper(arg));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strtolower
|
|
|
|
*/
|
1999-12-09 23:45:30 +00:00
|
|
|
PHPAPI char *php_strtolower(char *s, size_t len)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
unsigned char *c;
|
|
|
|
const unsigned char *e;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2009-08-13 06:44:50 +00:00
|
|
|
c = (unsigned char *)s;
|
2002-08-25 19:08:07 +00:00
|
|
|
e = c+len;
|
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
while (c < e) {
|
2002-08-25 19:08:07 +00:00
|
|
|
*c = tolower(*c);
|
|
|
|
c++;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
return s;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2014-12-25 03:28:54 +00:00
|
|
|
/* {{{ php_string_tolower
|
|
|
|
*/
|
|
|
|
PHPAPI zend_string *php_string_tolower(zend_string *s)
|
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
unsigned char *c;
|
|
|
|
const unsigned char *e;
|
2014-12-25 03:28:54 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
c = (unsigned char *)ZSTR_VAL(s);
|
|
|
|
e = c + ZSTR_LEN(s);
|
2014-12-25 03:28:54 +00:00
|
|
|
|
|
|
|
while (c < e) {
|
2015-12-13 05:22:50 +00:00
|
|
|
if (isupper(*c)) {
|
2014-12-25 03:28:54 +00:00
|
|
|
register unsigned char *r;
|
2015-06-30 01:05:24 +00:00
|
|
|
zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
|
2014-12-25 03:28:54 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (c != (unsigned char*)ZSTR_VAL(s)) {
|
|
|
|
memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
|
2014-12-25 03:28:54 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
|
2014-12-25 03:28:54 +00:00
|
|
|
while (c < e) {
|
|
|
|
*r = tolower(*c);
|
|
|
|
r++;
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
*r = '\0';
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
return zend_string_copy(s);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
/* {{{ proto string strtolower(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Makes a string lowercase */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strtolower)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2014-08-16 10:55:13 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2014-12-25 03:28:54 +00:00
|
|
|
RETURN_STR(php_string_tolower(str));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_basename
|
|
|
|
*/
|
2014-12-13 22:06:14 +00:00
|
|
|
PHPAPI zend_string *php_basename(const char *s, size_t len, char *suffix, size_t sufflen)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-03-16 14:42:41 +00:00
|
|
|
char *c;
|
|
|
|
const char *comp, *cend;
|
2003-12-10 07:15:28 +00:00
|
|
|
size_t inc_len, cnt;
|
|
|
|
int state;
|
2014-02-23 10:08:35 +00:00
|
|
|
zend_string *ret;
|
2003-12-10 07:15:28 +00:00
|
|
|
|
2018-03-16 14:42:41 +00:00
|
|
|
comp = cend = c = (char*)s;
|
2003-12-10 07:15:28 +00:00
|
|
|
cnt = len;
|
|
|
|
state = 0;
|
|
|
|
while (cnt > 0) {
|
2014-09-03 18:37:04 +00:00
|
|
|
inc_len = (*c == '\0' ? 1 : php_mblen(c, cnt));
|
2003-12-10 07:15:28 +00:00
|
|
|
|
|
|
|
switch (inc_len) {
|
|
|
|
case -2:
|
|
|
|
case -1:
|
|
|
|
inc_len = 1;
|
2014-09-03 18:37:04 +00:00
|
|
|
php_mb_reset();
|
2003-12-10 07:15:28 +00:00
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
goto quit_loop;
|
|
|
|
case 1:
|
2016-11-12 10:20:01 +00:00
|
|
|
#if defined(PHP_WIN32)
|
2014-01-05 18:05:04 +00:00
|
|
|
if (*c == '/' || *c == '\\') {
|
2003-12-10 07:15:28 +00:00
|
|
|
#else
|
|
|
|
if (*c == '/') {
|
1999-04-17 00:37:12 +00:00
|
|
|
#endif
|
2003-12-10 07:15:28 +00:00
|
|
|
if (state == 1) {
|
|
|
|
state = 0;
|
|
|
|
cend = c;
|
|
|
|
}
|
2016-11-12 10:20:01 +00:00
|
|
|
#if defined(PHP_WIN32)
|
2014-01-05 18:05:04 +00:00
|
|
|
/* Catch relative paths in c:file.txt style. They're not to confuse
|
2015-01-03 09:22:58 +00:00
|
|
|
with the NTFS streams. This part ensures also, that no drive
|
2014-01-05 18:05:04 +00:00
|
|
|
letter traversing happens. */
|
|
|
|
} else if ((*c == ':' && (c - comp == 1))) {
|
|
|
|
if (state == 0) {
|
|
|
|
comp = c;
|
|
|
|
state = 1;
|
|
|
|
} else {
|
|
|
|
cend = c;
|
|
|
|
state = 0;
|
|
|
|
}
|
|
|
|
#endif
|
2003-12-10 07:15:28 +00:00
|
|
|
} else {
|
|
|
|
if (state == 0) {
|
|
|
|
comp = c;
|
|
|
|
state = 1;
|
|
|
|
}
|
|
|
|
}
|
2006-07-17 20:36:47 +00:00
|
|
|
break;
|
2003-12-10 07:15:28 +00:00
|
|
|
default:
|
2006-07-17 20:36:47 +00:00
|
|
|
if (state == 0) {
|
|
|
|
comp = c;
|
|
|
|
state = 1;
|
|
|
|
}
|
2003-12-10 07:15:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
c += inc_len;
|
|
|
|
cnt -= inc_len;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
|
|
|
|
2003-12-10 07:15:28 +00:00
|
|
|
quit_loop:
|
|
|
|
if (state == 1) {
|
|
|
|
cend = c;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
2014-08-28 19:59:00 +00:00
|
|
|
if (suffix != NULL && sufflen < (size_t)(cend - comp) &&
|
2003-12-10 07:15:28 +00:00
|
|
|
memcmp(cend - sufflen, suffix, sufflen) == 0) {
|
|
|
|
cend -= sufflen;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
2003-05-05 13:46:14 +00:00
|
|
|
|
2003-12-10 07:15:28 +00:00
|
|
|
len = cend - comp;
|
2003-05-05 13:46:14 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
ret = zend_string_init(comp, len, 0);
|
2014-02-23 10:08:35 +00:00
|
|
|
return ret;
|
2000-05-23 20:16:14 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2000-05-23 20:16:14 +00:00
|
|
|
|
2001-06-23 00:51:03 +00:00
|
|
|
/* {{{ proto string basename(string path [, string suffix])
|
2001-09-04 10:44:28 +00:00
|
|
|
Returns the filename component of the path */
|
2000-05-23 20:16:14 +00:00
|
|
|
PHP_FUNCTION(basename)
|
|
|
|
{
|
2014-02-23 10:08:35 +00:00
|
|
|
char *string, *suffix = NULL;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t string_len, suffix_len = 0;
|
2000-05-23 20:16:14 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STRING(string, string_len)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STRING(suffix, suffix_len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2001-06-23 00:51:03 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
RETURN_STR(php_basename(string, string_len, suffix, suffix_len));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_dirname
|
2002-05-16 16:04:45 +00:00
|
|
|
Returns directory name component of path */
|
2003-04-12 21:53:46 +00:00
|
|
|
PHPAPI size_t php_dirname(char *path, size_t len)
|
2000-10-03 14:43:04 +00:00
|
|
|
{
|
2008-02-12 00:21:15 +00:00
|
|
|
return zend_dirname(path, len);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|null dirname(string path[, int levels])
|
2001-09-04 10:44:28 +00:00
|
|
|
Returns the directory name component of the path */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(dirname)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2008-06-22 19:22:41 +00:00
|
|
|
char *str;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t str_len;
|
2015-07-27 14:22:13 +00:00
|
|
|
zend_string *ret;
|
2015-07-25 14:58:36 +00:00
|
|
|
zend_long levels = 1;
|
2003-04-12 21:53:46 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STRING(str, str_len)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(levels)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
ret = zend_string_init(str, str_len, 0);
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2015-07-25 14:58:36 +00:00
|
|
|
if (levels == 1) {
|
2018-02-05 00:16:50 +00:00
|
|
|
/* Default case */
|
Fixed the UTF-8 and long path support in the streams on Windows.
Since long the default PHP charset is UTF-8, however the Windows part is
out of step with this important point. The current implementation in PHP
doesn't technically permit to handle UTF-8 filepath and several other
things. Till now, only the ANSI compatible APIs are being used. Here is more
about it
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317752%28v=vs.85%29.aspx
The patch fixes not only issues with multibyte filenames under
incompatible codepages, but indirectly also issues with some other multibyte
encodings like BIG5, Shift-JIS, etc. by providing a clean way to access
filenames in UTF-8. Below is a small list of issues from the bug tracker,
that are getting fixed:
https://bugs.php.net/63401
https://bugs.php.net/41199
https://bugs.php.net/50203
https://bugs.php.net/71509
https://bugs.php.net/64699
https://bugs.php.net/64506
https://bugs.php.net/30195
https://bugs.php.net/65358
https://bugs.php.net/61315
https://bugs.php.net/70943
https://bugs.php.net/70903
https://bugs.php.net/63593
https://bugs.php.net/54977
https://bugs.php.net/54028
https://bugs.php.net/43148
https://bugs.php.net/30730
https://bugs.php.net/33350
https://bugs.php.net/35300
https://bugs.php.net/46990
https://bugs.php.net/61309
https://bugs.php.net/69333
https://bugs.php.net/45517
https://bugs.php.net/70551
https://bugs.php.net/50197
https://bugs.php.net/72200
https://bugs.php.net/37672
Yet more related tickets can for sure be found - on bugs.php.net, Stackoverflow
and Github. Some of the bugs are pretty recent, some descend to early
2000th, but the user comments in there last even till today. Just for example,
bug #30195 was opened in 2004, the latest comment in there was made in 2014. It
is certain, that these bugs descend not only to pure PHP use cases, but get also
redirected from the popular PHP based projects. Given the modern systems (and
those supported by PHP) are always based on NTFS, there is no excuse to keep
these issues unresolved.
The internalization approach on Windows is in many ways different from
UNIX and Linux, while it supports and is based on Unicode. It depends on the
current system code page, APIs used and exact kind how the binary was compiled
The locale doesn't affect the way Unicode or ANSI API work. PHP in particular
is being compiled without _UNICODE defined and this is conditioned by the
way we handle strings. Here is more about it
https://msdn.microsoft.com/en-us/library/tsbaswba.aspx
However, with any system code page ANSI functions automatically convert
paths to UTF-16. Paths in some encodings incompatible with the
current system code page, won't work correctly with ANSI APIs. PHP
till now only uses the ANSI Windows APIs.
For example, on a system with the current code page 1252, the paths
in cp1252 are supported and transparently converted to UTF-16 by the
ANSI functions. Once one wants to handle a filepath encoded with cp932 on
that particular system, an ANSI or a POSIX compatible function used in
PHP will produce an erroneous result. When trying to convert that cp932 path
to UTF-8 and passing to the ANSI functions, an ANSI function would
likely interpret the UTF-8 string as some string in the current code page and
create a filepath that represents every single byte of the UTF-8 string.
These behaviors are not only broken but also disregard the documented
INI settings.
This patch solves the issies with the multibyte paths on Windows by
intelligently enforcing the usage of the Unicode aware APIs. For
functions expect Unicode (fe CreateFileW, FindFirstFileW, etc.), arguments
will be converted to UTF-16 wide chars. For functions returning Unicode
aware data (fe GetCurrentDirectoryW, etc.), resulting wide string is
converted back to char's depending on the current PHP charset settings,
either to the current ANSI codepage (this is the behavior prior to this patch)
or to UTF-8 (the default behavior).
In a particular case, users might have to explicitly set
internal_encoding or default_charset, if filenames in ANSI codepage are
necessary. Current tests show no regressions and witness that this will be an
exotic case, the current default UTF-8 encoding is compatible with any
supported system. The dependency libraries are long switching to Unicode APIs,
so some tests were also added for extensions not directly related to streams.
At large, the patch brings over 150 related tests into the core. Those target
and was run on various environments with European, Asian, etc. codepages.
General PHP frameworks was tested and showed no regressions.
The impact on the current C code base is low, the most places affected
are the Windows only places in the three files tsrm_win32.c, zend_virtual_cwd.c
and plain_wrapper.c. The actual implementation of the most of the wide
char supporting functionality is in win32/ioutil.* and win32/codepage.*,
several low level functionsare extended in place to avoid reimplementation for
now. No performance impact was sighted. As previously mentioned, the ANSI APIs
used prior the patch perform Unicode conversions internally. Using the
Unicode APIs directly while doing custom conversions just retains the status
quo. The ways to optimize it are open (fe. by implementing caching for the
strings converted to wide variants).
The long path implementation is user transparent. If a path exceeds the
length of _MAX_PATH, it'll be automatically prefixed with \\?\. The MAXPATHLEN
is set to 2048 bytes.
Appreciation to Pierre Joye, Matt Ficken, @algo13 and others for tips, ideas
and testing.
Thanks.
2016-06-20 07:32:19 +00:00
|
|
|
#ifdef PHP_WIN32
|
|
|
|
ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), str_len);
|
|
|
|
#else
|
2015-07-25 14:58:36 +00:00
|
|
|
ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len);
|
Fixed the UTF-8 and long path support in the streams on Windows.
Since long the default PHP charset is UTF-8, however the Windows part is
out of step with this important point. The current implementation in PHP
doesn't technically permit to handle UTF-8 filepath and several other
things. Till now, only the ANSI compatible APIs are being used. Here is more
about it
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317752%28v=vs.85%29.aspx
The patch fixes not only issues with multibyte filenames under
incompatible codepages, but indirectly also issues with some other multibyte
encodings like BIG5, Shift-JIS, etc. by providing a clean way to access
filenames in UTF-8. Below is a small list of issues from the bug tracker,
that are getting fixed:
https://bugs.php.net/63401
https://bugs.php.net/41199
https://bugs.php.net/50203
https://bugs.php.net/71509
https://bugs.php.net/64699
https://bugs.php.net/64506
https://bugs.php.net/30195
https://bugs.php.net/65358
https://bugs.php.net/61315
https://bugs.php.net/70943
https://bugs.php.net/70903
https://bugs.php.net/63593
https://bugs.php.net/54977
https://bugs.php.net/54028
https://bugs.php.net/43148
https://bugs.php.net/30730
https://bugs.php.net/33350
https://bugs.php.net/35300
https://bugs.php.net/46990
https://bugs.php.net/61309
https://bugs.php.net/69333
https://bugs.php.net/45517
https://bugs.php.net/70551
https://bugs.php.net/50197
https://bugs.php.net/72200
https://bugs.php.net/37672
Yet more related tickets can for sure be found - on bugs.php.net, Stackoverflow
and Github. Some of the bugs are pretty recent, some descend to early
2000th, but the user comments in there last even till today. Just for example,
bug #30195 was opened in 2004, the latest comment in there was made in 2014. It
is certain, that these bugs descend not only to pure PHP use cases, but get also
redirected from the popular PHP based projects. Given the modern systems (and
those supported by PHP) are always based on NTFS, there is no excuse to keep
these issues unresolved.
The internalization approach on Windows is in many ways different from
UNIX and Linux, while it supports and is based on Unicode. It depends on the
current system code page, APIs used and exact kind how the binary was compiled
The locale doesn't affect the way Unicode or ANSI API work. PHP in particular
is being compiled without _UNICODE defined and this is conditioned by the
way we handle strings. Here is more about it
https://msdn.microsoft.com/en-us/library/tsbaswba.aspx
However, with any system code page ANSI functions automatically convert
paths to UTF-16. Paths in some encodings incompatible with the
current system code page, won't work correctly with ANSI APIs. PHP
till now only uses the ANSI Windows APIs.
For example, on a system with the current code page 1252, the paths
in cp1252 are supported and transparently converted to UTF-16 by the
ANSI functions. Once one wants to handle a filepath encoded with cp932 on
that particular system, an ANSI or a POSIX compatible function used in
PHP will produce an erroneous result. When trying to convert that cp932 path
to UTF-8 and passing to the ANSI functions, an ANSI function would
likely interpret the UTF-8 string as some string in the current code page and
create a filepath that represents every single byte of the UTF-8 string.
These behaviors are not only broken but also disregard the documented
INI settings.
This patch solves the issies with the multibyte paths on Windows by
intelligently enforcing the usage of the Unicode aware APIs. For
functions expect Unicode (fe CreateFileW, FindFirstFileW, etc.), arguments
will be converted to UTF-16 wide chars. For functions returning Unicode
aware data (fe GetCurrentDirectoryW, etc.), resulting wide string is
converted back to char's depending on the current PHP charset settings,
either to the current ANSI codepage (this is the behavior prior to this patch)
or to UTF-8 (the default behavior).
In a particular case, users might have to explicitly set
internal_encoding or default_charset, if filenames in ANSI codepage are
necessary. Current tests show no regressions and witness that this will be an
exotic case, the current default UTF-8 encoding is compatible with any
supported system. The dependency libraries are long switching to Unicode APIs,
so some tests were also added for extensions not directly related to streams.
At large, the patch brings over 150 related tests into the core. Those target
and was run on various environments with European, Asian, etc. codepages.
General PHP frameworks was tested and showed no regressions.
The impact on the current C code base is low, the most places affected
are the Windows only places in the three files tsrm_win32.c, zend_virtual_cwd.c
and plain_wrapper.c. The actual implementation of the most of the wide
char supporting functionality is in win32/ioutil.* and win32/codepage.*,
several low level functionsare extended in place to avoid reimplementation for
now. No performance impact was sighted. As previously mentioned, the ANSI APIs
used prior the patch perform Unicode conversions internally. Using the
Unicode APIs directly while doing custom conversions just retains the status
quo. The ways to optimize it are open (fe. by implementing caching for the
strings converted to wide variants).
The long path implementation is user transparent. If a path exceeds the
length of _MAX_PATH, it'll be automatically prefixed with \\?\. The MAXPATHLEN
is set to 2048 bytes.
Appreciation to Pierre Joye, Matt Ficken, @algo13 and others for tips, ideas
and testing.
Thanks.
2016-06-20 07:32:19 +00:00
|
|
|
#endif
|
2015-07-25 14:58:36 +00:00
|
|
|
} else if (levels < 1) {
|
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1");
|
2018-05-08 14:30:15 +00:00
|
|
|
zend_string_efree(ret);
|
2015-07-25 14:58:36 +00:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* Some levels up */
|
|
|
|
do {
|
Fixed the UTF-8 and long path support in the streams on Windows.
Since long the default PHP charset is UTF-8, however the Windows part is
out of step with this important point. The current implementation in PHP
doesn't technically permit to handle UTF-8 filepath and several other
things. Till now, only the ANSI compatible APIs are being used. Here is more
about it
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317752%28v=vs.85%29.aspx
The patch fixes not only issues with multibyte filenames under
incompatible codepages, but indirectly also issues with some other multibyte
encodings like BIG5, Shift-JIS, etc. by providing a clean way to access
filenames in UTF-8. Below is a small list of issues from the bug tracker,
that are getting fixed:
https://bugs.php.net/63401
https://bugs.php.net/41199
https://bugs.php.net/50203
https://bugs.php.net/71509
https://bugs.php.net/64699
https://bugs.php.net/64506
https://bugs.php.net/30195
https://bugs.php.net/65358
https://bugs.php.net/61315
https://bugs.php.net/70943
https://bugs.php.net/70903
https://bugs.php.net/63593
https://bugs.php.net/54977
https://bugs.php.net/54028
https://bugs.php.net/43148
https://bugs.php.net/30730
https://bugs.php.net/33350
https://bugs.php.net/35300
https://bugs.php.net/46990
https://bugs.php.net/61309
https://bugs.php.net/69333
https://bugs.php.net/45517
https://bugs.php.net/70551
https://bugs.php.net/50197
https://bugs.php.net/72200
https://bugs.php.net/37672
Yet more related tickets can for sure be found - on bugs.php.net, Stackoverflow
and Github. Some of the bugs are pretty recent, some descend to early
2000th, but the user comments in there last even till today. Just for example,
bug #30195 was opened in 2004, the latest comment in there was made in 2014. It
is certain, that these bugs descend not only to pure PHP use cases, but get also
redirected from the popular PHP based projects. Given the modern systems (and
those supported by PHP) are always based on NTFS, there is no excuse to keep
these issues unresolved.
The internalization approach on Windows is in many ways different from
UNIX and Linux, while it supports and is based on Unicode. It depends on the
current system code page, APIs used and exact kind how the binary was compiled
The locale doesn't affect the way Unicode or ANSI API work. PHP in particular
is being compiled without _UNICODE defined and this is conditioned by the
way we handle strings. Here is more about it
https://msdn.microsoft.com/en-us/library/tsbaswba.aspx
However, with any system code page ANSI functions automatically convert
paths to UTF-16. Paths in some encodings incompatible with the
current system code page, won't work correctly with ANSI APIs. PHP
till now only uses the ANSI Windows APIs.
For example, on a system with the current code page 1252, the paths
in cp1252 are supported and transparently converted to UTF-16 by the
ANSI functions. Once one wants to handle a filepath encoded with cp932 on
that particular system, an ANSI or a POSIX compatible function used in
PHP will produce an erroneous result. When trying to convert that cp932 path
to UTF-8 and passing to the ANSI functions, an ANSI function would
likely interpret the UTF-8 string as some string in the current code page and
create a filepath that represents every single byte of the UTF-8 string.
These behaviors are not only broken but also disregard the documented
INI settings.
This patch solves the issies with the multibyte paths on Windows by
intelligently enforcing the usage of the Unicode aware APIs. For
functions expect Unicode (fe CreateFileW, FindFirstFileW, etc.), arguments
will be converted to UTF-16 wide chars. For functions returning Unicode
aware data (fe GetCurrentDirectoryW, etc.), resulting wide string is
converted back to char's depending on the current PHP charset settings,
either to the current ANSI codepage (this is the behavior prior to this patch)
or to UTF-8 (the default behavior).
In a particular case, users might have to explicitly set
internal_encoding or default_charset, if filenames in ANSI codepage are
necessary. Current tests show no regressions and witness that this will be an
exotic case, the current default UTF-8 encoding is compatible with any
supported system. The dependency libraries are long switching to Unicode APIs,
so some tests were also added for extensions not directly related to streams.
At large, the patch brings over 150 related tests into the core. Those target
and was run on various environments with European, Asian, etc. codepages.
General PHP frameworks was tested and showed no regressions.
The impact on the current C code base is low, the most places affected
are the Windows only places in the three files tsrm_win32.c, zend_virtual_cwd.c
and plain_wrapper.c. The actual implementation of the most of the wide
char supporting functionality is in win32/ioutil.* and win32/codepage.*,
several low level functionsare extended in place to avoid reimplementation for
now. No performance impact was sighted. As previously mentioned, the ANSI APIs
used prior the patch perform Unicode conversions internally. Using the
Unicode APIs directly while doing custom conversions just retains the status
quo. The ways to optimize it are open (fe. by implementing caching for the
strings converted to wide variants).
The long path implementation is user transparent. If a path exceeds the
length of _MAX_PATH, it'll be automatically prefixed with \\?\. The MAXPATHLEN
is set to 2048 bytes.
Appreciation to Pierre Joye, Matt Ficken, @algo13 and others for tips, ideas
and testing.
Thanks.
2016-06-20 07:32:19 +00:00
|
|
|
#ifdef PHP_WIN32
|
|
|
|
ZSTR_LEN(ret) = php_win32_ioutil_dirname(ZSTR_VAL(ret), str_len = ZSTR_LEN(ret));
|
|
|
|
#else
|
2015-07-27 14:22:13 +00:00
|
|
|
ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len = ZSTR_LEN(ret));
|
Fixed the UTF-8 and long path support in the streams on Windows.
Since long the default PHP charset is UTF-8, however the Windows part is
out of step with this important point. The current implementation in PHP
doesn't technically permit to handle UTF-8 filepath and several other
things. Till now, only the ANSI compatible APIs are being used. Here is more
about it
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317752%28v=vs.85%29.aspx
The patch fixes not only issues with multibyte filenames under
incompatible codepages, but indirectly also issues with some other multibyte
encodings like BIG5, Shift-JIS, etc. by providing a clean way to access
filenames in UTF-8. Below is a small list of issues from the bug tracker,
that are getting fixed:
https://bugs.php.net/63401
https://bugs.php.net/41199
https://bugs.php.net/50203
https://bugs.php.net/71509
https://bugs.php.net/64699
https://bugs.php.net/64506
https://bugs.php.net/30195
https://bugs.php.net/65358
https://bugs.php.net/61315
https://bugs.php.net/70943
https://bugs.php.net/70903
https://bugs.php.net/63593
https://bugs.php.net/54977
https://bugs.php.net/54028
https://bugs.php.net/43148
https://bugs.php.net/30730
https://bugs.php.net/33350
https://bugs.php.net/35300
https://bugs.php.net/46990
https://bugs.php.net/61309
https://bugs.php.net/69333
https://bugs.php.net/45517
https://bugs.php.net/70551
https://bugs.php.net/50197
https://bugs.php.net/72200
https://bugs.php.net/37672
Yet more related tickets can for sure be found - on bugs.php.net, Stackoverflow
and Github. Some of the bugs are pretty recent, some descend to early
2000th, but the user comments in there last even till today. Just for example,
bug #30195 was opened in 2004, the latest comment in there was made in 2014. It
is certain, that these bugs descend not only to pure PHP use cases, but get also
redirected from the popular PHP based projects. Given the modern systems (and
those supported by PHP) are always based on NTFS, there is no excuse to keep
these issues unresolved.
The internalization approach on Windows is in many ways different from
UNIX and Linux, while it supports and is based on Unicode. It depends on the
current system code page, APIs used and exact kind how the binary was compiled
The locale doesn't affect the way Unicode or ANSI API work. PHP in particular
is being compiled without _UNICODE defined and this is conditioned by the
way we handle strings. Here is more about it
https://msdn.microsoft.com/en-us/library/tsbaswba.aspx
However, with any system code page ANSI functions automatically convert
paths to UTF-16. Paths in some encodings incompatible with the
current system code page, won't work correctly with ANSI APIs. PHP
till now only uses the ANSI Windows APIs.
For example, on a system with the current code page 1252, the paths
in cp1252 are supported and transparently converted to UTF-16 by the
ANSI functions. Once one wants to handle a filepath encoded with cp932 on
that particular system, an ANSI or a POSIX compatible function used in
PHP will produce an erroneous result. When trying to convert that cp932 path
to UTF-8 and passing to the ANSI functions, an ANSI function would
likely interpret the UTF-8 string as some string in the current code page and
create a filepath that represents every single byte of the UTF-8 string.
These behaviors are not only broken but also disregard the documented
INI settings.
This patch solves the issies with the multibyte paths on Windows by
intelligently enforcing the usage of the Unicode aware APIs. For
functions expect Unicode (fe CreateFileW, FindFirstFileW, etc.), arguments
will be converted to UTF-16 wide chars. For functions returning Unicode
aware data (fe GetCurrentDirectoryW, etc.), resulting wide string is
converted back to char's depending on the current PHP charset settings,
either to the current ANSI codepage (this is the behavior prior to this patch)
or to UTF-8 (the default behavior).
In a particular case, users might have to explicitly set
internal_encoding or default_charset, if filenames in ANSI codepage are
necessary. Current tests show no regressions and witness that this will be an
exotic case, the current default UTF-8 encoding is compatible with any
supported system. The dependency libraries are long switching to Unicode APIs,
so some tests were also added for extensions not directly related to streams.
At large, the patch brings over 150 related tests into the core. Those target
and was run on various environments with European, Asian, etc. codepages.
General PHP frameworks was tested and showed no regressions.
The impact on the current C code base is low, the most places affected
are the Windows only places in the three files tsrm_win32.c, zend_virtual_cwd.c
and plain_wrapper.c. The actual implementation of the most of the wide
char supporting functionality is in win32/ioutil.* and win32/codepage.*,
several low level functionsare extended in place to avoid reimplementation for
now. No performance impact was sighted. As previously mentioned, the ANSI APIs
used prior the patch perform Unicode conversions internally. Using the
Unicode APIs directly while doing custom conversions just retains the status
quo. The ways to optimize it are open (fe. by implementing caching for the
strings converted to wide variants).
The long path implementation is user transparent. If a path exceeds the
length of _MAX_PATH, it'll be automatically prefixed with \\?\. The MAXPATHLEN
is set to 2048 bytes.
Appreciation to Pierre Joye, Matt Ficken, @algo13 and others for tips, ideas
and testing.
Thanks.
2016-06-20 07:32:19 +00:00
|
|
|
#endif
|
2015-07-27 14:22:13 +00:00
|
|
|
} while (ZSTR_LEN(ret) < str_len && --levels);
|
2015-07-25 14:58:36 +00:00
|
|
|
}
|
2015-07-27 14:22:13 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(ret);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-06-09 20:55:56 +00:00
|
|
|
/* {{{ proto array|string pathinfo(string path[, int options])
|
2001-09-04 10:44:28 +00:00
|
|
|
Returns information about a certain string */
|
2000-09-10 05:59:16 +00:00
|
|
|
PHP_FUNCTION(pathinfo)
|
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval tmp;
|
2014-02-23 10:08:35 +00:00
|
|
|
char *path, *dirname;
|
2014-08-27 15:31:24 +00:00
|
|
|
size_t path_len;
|
|
|
|
int have_basename;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long opt = PHP_PATHINFO_ALL;
|
2014-02-24 08:14:46 +00:00
|
|
|
zend_string *ret = NULL;
|
2002-01-22 03:35:23 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STRING(path, path_len)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(opt)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2006-07-17 06:45:08 +00:00
|
|
|
have_basename = ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
array_init(&tmp);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-01-22 03:35:23 +00:00
|
|
|
if ((opt & PHP_PATHINFO_DIRNAME) == PHP_PATHINFO_DIRNAME) {
|
2014-02-23 10:08:35 +00:00
|
|
|
dirname = estrndup(path, path_len);
|
|
|
|
php_dirname(dirname, path_len);
|
|
|
|
if (*dirname) {
|
2014-04-15 11:40:40 +00:00
|
|
|
add_assoc_string(&tmp, "dirname", dirname);
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
2014-02-23 10:08:35 +00:00
|
|
|
efree(dirname);
|
2000-09-10 05:59:16 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2006-07-17 06:45:08 +00:00
|
|
|
if (have_basename) {
|
2014-12-13 22:06:14 +00:00
|
|
|
ret = php_basename(path, path_len, NULL, 0);
|
2014-08-25 17:24:55 +00:00
|
|
|
add_assoc_str(&tmp, "basename", zend_string_copy(ret));
|
2006-07-17 06:45:08 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-01-22 03:35:23 +00:00
|
|
|
if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
|
2010-11-19 16:03:00 +00:00
|
|
|
const char *p;
|
2014-08-28 19:59:00 +00:00
|
|
|
ptrdiff_t idx;
|
2002-01-22 03:35:23 +00:00
|
|
|
|
|
|
|
if (!have_basename) {
|
2014-12-13 22:06:14 +00:00
|
|
|
ret = php_basename(path, path_len, NULL, 0);
|
2002-01-22 03:35:23 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
|
2000-09-10 05:59:16 +00:00
|
|
|
|
2001-04-13 18:22:13 +00:00
|
|
|
if (p) {
|
2015-06-30 01:05:24 +00:00
|
|
|
idx = p - ZSTR_VAL(ret);
|
|
|
|
add_assoc_stringl(&tmp, "extension", ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
|
2002-01-22 03:35:23 +00:00
|
|
|
}
|
2000-09-10 05:59:16 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2006-07-16 10:37:24 +00:00
|
|
|
if ((opt & PHP_PATHINFO_FILENAME) == PHP_PATHINFO_FILENAME) {
|
2010-11-19 16:03:00 +00:00
|
|
|
const char *p;
|
2014-08-28 19:59:00 +00:00
|
|
|
ptrdiff_t idx;
|
2006-07-16 10:37:24 +00:00
|
|
|
|
2013-07-13 12:37:04 +00:00
|
|
|
/* Have we already looked up the basename? */
|
2006-07-17 06:45:08 +00:00
|
|
|
if (!have_basename && !ret) {
|
2014-12-13 22:06:14 +00:00
|
|
|
ret = php_basename(path, path_len, NULL, 0);
|
2006-07-16 10:37:24 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
|
2006-07-16 10:37:24 +00:00
|
|
|
|
2016-06-23 09:47:06 +00:00
|
|
|
idx = p ? (p - ZSTR_VAL(ret)) : (ptrdiff_t)ZSTR_LEN(ret);
|
2015-06-30 01:05:24 +00:00
|
|
|
add_assoc_stringl(&tmp, "filename", ZSTR_VAL(ret), idx);
|
2006-07-17 06:45:08 +00:00
|
|
|
}
|
2006-07-16 10:37:24 +00:00
|
|
|
|
2014-02-24 08:14:46 +00:00
|
|
|
if (ret) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(ret, 0);
|
2006-07-16 10:37:24 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2002-01-22 03:35:23 +00:00
|
|
|
if (opt == PHP_PATHINFO_ALL) {
|
2015-06-12 09:33:23 +00:00
|
|
|
ZVAL_COPY_VALUE(return_value, &tmp);
|
2002-01-22 03:35:23 +00:00
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *element;
|
|
|
|
if ((element = zend_hash_get_current_data(Z_ARRVAL(tmp))) != NULL) {
|
2018-07-09 09:46:46 +00:00
|
|
|
ZVAL_COPY_DEREF(return_value, element);
|
2002-01-22 03:35:23 +00:00
|
|
|
} else {
|
|
|
|
ZVAL_EMPTY_STRING(return_value);
|
|
|
|
}
|
2015-06-12 09:33:23 +00:00
|
|
|
zval_ptr_dtor(&tmp);
|
2000-09-10 05:59:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_stristr
|
2019-02-18 16:14:22 +00:00
|
|
|
case insensitive strstr */
|
2009-08-13 06:44:50 +00:00
|
|
|
PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
1999-12-11 19:50:01 +00:00
|
|
|
php_strtolower(s, s_len);
|
|
|
|
php_strtolower(t, t_len);
|
2014-02-10 13:49:21 +00:00
|
|
|
return (char*)php_memnstr(s, t, t_len, s + s_len);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strspn
|
|
|
|
*/
|
1999-12-13 23:40:36 +00:00
|
|
|
PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end)
|
|
|
|
{
|
|
|
|
register const char *p = s1, *spanp;
|
|
|
|
register char c = *p;
|
|
|
|
|
|
|
|
cont:
|
2003-02-08 15:26:17 +00:00
|
|
|
for (spanp = s2; p != s1_end && spanp != s2_end;) {
|
1999-12-13 23:40:36 +00:00
|
|
|
if (*spanp++ == c) {
|
|
|
|
c = *(++p);
|
|
|
|
goto cont;
|
|
|
|
}
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
1999-12-13 23:40:36 +00:00
|
|
|
return (p - s1);
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-12-13 23:40:36 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strcspn
|
|
|
|
*/
|
1999-12-13 23:40:36 +00:00
|
|
|
PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end)
|
|
|
|
{
|
|
|
|
register const char *p, *spanp;
|
|
|
|
register char c = *s1;
|
|
|
|
|
|
|
|
for (p = s1;;) {
|
|
|
|
spanp = s2;
|
|
|
|
do {
|
2003-02-08 15:26:17 +00:00
|
|
|
if (*spanp == c || p == s1_end) {
|
2001-09-04 06:18:11 +00:00
|
|
|
return p - s1;
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
2006-10-04 11:14:32 +00:00
|
|
|
} while (spanp++ < (s2_end - 1));
|
2001-09-04 06:18:11 +00:00
|
|
|
c = *++p;
|
1999-12-13 23:40:36 +00:00
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-12-13 23:40:36 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false stristr(string haystack, string needle[, bool part])
|
2001-09-04 10:44:28 +00:00
|
|
|
Finds first occurrence of a string within another, case insensitive */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(stristr)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_string *haystack, *needle;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *found = NULL;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t found_offset;
|
2009-08-13 06:44:50 +00:00
|
|
|
char *haystack_dup;
|
2019-01-29 09:02:03 +00:00
|
|
|
char *orig_needle;
|
2008-02-01 12:28:44 +00:00
|
|
|
zend_bool part = 0;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STR(needle)
|
2016-12-31 00:40:45 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(part)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2001-09-06 08:54:54 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
if (!ZSTR_LEN(needle)) {
|
|
|
|
php_error_docref(NULL, E_WARNING, "Empty needle");
|
|
|
|
RETURN_FALSE;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2002-09-11 14:40:52 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack));
|
|
|
|
orig_needle = estrndup(ZSTR_VAL(needle), ZSTR_LEN(needle));
|
|
|
|
found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), ZSTR_LEN(needle));
|
|
|
|
efree(orig_needle);
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
if (found) {
|
2009-08-13 06:44:50 +00:00
|
|
|
found_offset = found - haystack_dup;
|
2008-02-01 12:28:44 +00:00
|
|
|
if (part) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETVAL_STRINGL(ZSTR_VAL(haystack), found_offset);
|
2008-02-01 12:28:44 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETVAL_STRINGL(ZSTR_VAL(haystack) + found_offset, ZSTR_LEN(haystack) - found_offset);
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
} else {
|
2001-09-27 00:21:21 +00:00
|
|
|
RETVAL_FALSE;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2009-08-13 06:44:50 +00:00
|
|
|
efree(haystack_dup);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false strstr(string haystack, string needle[, bool part])
|
2001-09-04 10:44:28 +00:00
|
|
|
Finds first occurrence of a string within another */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strstr)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_string *haystack, *needle;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *found = NULL;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long found_offset;
|
2008-02-01 12:28:44 +00:00
|
|
|
zend_bool part = 0;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STR(needle)
|
2016-12-31 00:40:45 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(part)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-02-08 15:26:17 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
if (!ZSTR_LEN(needle)) {
|
|
|
|
php_error_docref(NULL, E_WARNING, "Empty needle");
|
|
|
|
RETURN_FALSE;
|
2001-09-04 06:18:11 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
if (found) {
|
2015-06-30 01:05:24 +00:00
|
|
|
found_offset = found - ZSTR_VAL(haystack);
|
2008-02-01 12:28:44 +00:00
|
|
|
if (part) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_STRINGL(ZSTR_VAL(haystack), found_offset);
|
2008-02-01 12:28:44 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
|
2008-02-01 12:28:44 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2008-02-03 14:30:25 +00:00
|
|
|
RETURN_FALSE;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-08-09 20:52:58 +00:00
|
|
|
/* {{{ proto string strchr(string haystack, string needle)
|
|
|
|
An alias for strstr */
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false strpos(string haystack, string needle [, int offset])
|
2001-09-04 10:44:28 +00:00
|
|
|
Finds position of first occurrence of a string within another */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strpos)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_string *haystack, *needle;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *found = NULL;
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_long offset = 0;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
2014-08-16 12:00:02 +00:00
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STR(needle)
|
2014-07-11 12:32:20 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_PARAM_LONG(offset)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2015-07-22 22:08:57 +00:00
|
|
|
if (offset < 0) {
|
|
|
|
offset += (zend_long)ZSTR_LEN(haystack);
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2001-09-04 06:18:11 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
1999-12-06 17:37:59 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
if (!ZSTR_LEN(needle)) {
|
|
|
|
php_error_docref(NULL, E_WARNING, "Empty needle");
|
|
|
|
RETURN_FALSE;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
|
|
|
|
ZSTR_VAL(needle), ZSTR_LEN(needle),
|
|
|
|
ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
if (found) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(found - ZSTR_VAL(haystack));
|
1999-04-17 00:37:12 +00:00
|
|
|
} else {
|
2001-09-04 06:18:11 +00:00
|
|
|
RETURN_FALSE;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false stripos(string haystack, string needle [, int offset])
|
2003-01-11 17:52:38 +00:00
|
|
|
Finds position of first occurrence of a string within another, case insensitive */
|
|
|
|
PHP_FUNCTION(stripos)
|
|
|
|
{
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *found = NULL;
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_string *haystack, *needle;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long offset = 0;
|
2015-01-12 09:24:37 +00:00
|
|
|
zend_string *needle_dup = NULL, *haystack_dup;
|
2003-01-11 17:52:38 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STR(needle)
|
2016-12-31 00:40:45 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(offset)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-02-08 15:26:17 +00:00
|
|
|
|
2015-07-22 22:08:57 +00:00
|
|
|
if (offset < 0) {
|
|
|
|
offset += (zend_long)ZSTR_LEN(haystack);
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2003-01-11 17:52:38 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(haystack) == 0) {
|
2006-07-12 12:33:48 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
if (ZSTR_LEN(needle) == 0 || ZSTR_LEN(needle) > ZSTR_LEN(haystack)) {
|
|
|
|
RETURN_FALSE;
|
2003-01-11 17:52:38 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
haystack_dup = php_string_tolower(haystack);
|
|
|
|
needle_dup = php_string_tolower(needle);
|
|
|
|
found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset,
|
|
|
|
ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack));
|
2003-01-11 17:52:38 +00:00
|
|
|
|
|
|
|
if (found) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
|
2003-01-11 17:52:38 +00:00
|
|
|
} else {
|
2015-01-12 09:24:37 +00:00
|
|
|
RETVAL_FALSE;
|
|
|
|
}
|
|
|
|
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(haystack_dup, 0);
|
2015-01-12 09:24:37 +00:00
|
|
|
if (needle_dup) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(needle_dup, 0);
|
2003-01-11 17:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false strrpos(string haystack, string needle [, int offset])
|
2003-04-12 07:36:22 +00:00
|
|
|
Finds position of last occurrence of a string within another string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strrpos)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-16 12:00:02 +00:00
|
|
|
zend_string *haystack;
|
2019-01-29 09:02:03 +00:00
|
|
|
char *needle;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t needle_len;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long offset = 0;
|
2019-01-29 09:02:03 +00:00
|
|
|
const char *p, *e, *found;
|
2003-01-11 17:52:38 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
2014-08-16 12:00:02 +00:00
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STRING(needle, needle_len)
|
2014-07-11 12:32:20 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_PARAM_LONG(offset)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
|
2003-01-11 17:52:38 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
if (ZSTR_LEN(haystack) == 0 || needle_len == 0) {
|
2003-04-12 20:04:06 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-04-12 07:36:22 +00:00
|
|
|
if (offset >= 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((size_t)offset > ZSTR_LEN(haystack)) {
|
2019-08-22 09:09:44 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2006-10-02 19:42:42 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(haystack) + (size_t)offset;
|
|
|
|
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
|
2003-01-11 17:52:38 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
|
2019-08-22 09:09:44 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2006-10-02 19:42:42 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(haystack);
|
2016-06-23 09:47:06 +00:00
|
|
|
if ((size_t)-offset < needle_len) {
|
2015-06-30 01:05:24 +00:00
|
|
|
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
|
2015-01-19 02:38:25 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + needle_len;
|
2003-04-12 07:36:22 +00:00
|
|
|
}
|
2003-01-11 17:52:38 +00:00
|
|
|
}
|
|
|
|
|
2018-03-16 19:36:41 +00:00
|
|
|
if ((found = zend_memnrstr(p, needle, needle_len, e))) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(found - ZSTR_VAL(haystack));
|
2003-01-11 17:52:38 +00:00
|
|
|
}
|
2003-04-12 07:36:22 +00:00
|
|
|
|
|
|
|
RETURN_FALSE;
|
2003-01-11 17:52:38 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false strripos(string haystack, string needle [, int offset])
|
2003-04-12 07:36:22 +00:00
|
|
|
Finds position of last occurrence of a string within another string */
|
2003-01-11 17:52:38 +00:00
|
|
|
PHP_FUNCTION(strripos)
|
|
|
|
{
|
2015-01-12 09:24:37 +00:00
|
|
|
zend_string *needle;
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *haystack;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long offset = 0;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *p, *e, *found;
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_string *needle_dup, *haystack_dup;
|
2015-01-12 09:24:37 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STR(needle)
|
2016-12-31 00:40:45 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(offset)
|
|
|
|
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
|
2003-01-11 17:52:38 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
if (ZSTR_LEN(haystack) == 0 || ZSTR_LEN(needle) == 0) {
|
2003-04-12 20:04:06 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(needle) == 1) {
|
2012-01-02 00:47:57 +00:00
|
|
|
/* Single character search can shortcut memcmps
|
2003-12-03 01:31:56 +00:00
|
|
|
Can also avoid tolower emallocs */
|
2019-01-29 09:02:03 +00:00
|
|
|
char lowered;
|
2003-12-03 01:31:56 +00:00
|
|
|
if (offset >= 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((size_t)offset > ZSTR_LEN(haystack)) {
|
2019-08-22 09:09:44 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2006-10-02 19:58:15 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(haystack) + (size_t)offset;
|
|
|
|
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - 1;
|
2003-12-03 01:31:56 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(haystack);
|
|
|
|
if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
|
2019-08-22 09:09:44 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2006-10-02 19:58:15 +00:00
|
|
|
RETURN_FALSE;
|
2004-05-06 16:11:50 +00:00
|
|
|
}
|
2019-06-20 11:06:56 +00:00
|
|
|
e = ZSTR_VAL(haystack) + (ZSTR_LEN(haystack) + (size_t)offset);
|
2003-12-03 01:31:56 +00:00
|
|
|
}
|
|
|
|
/* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */
|
2019-01-29 09:02:03 +00:00
|
|
|
lowered = tolower(*ZSTR_VAL(needle));
|
2003-12-03 01:31:56 +00:00
|
|
|
while (e >= p) {
|
2019-01-29 09:02:03 +00:00
|
|
|
if (tolower(*e) == lowered) {
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(e - p + (offset > 0 ? offset : 0));
|
2003-12-03 01:31:56 +00:00
|
|
|
}
|
|
|
|
e--;
|
|
|
|
}
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2015-01-12 09:24:37 +00:00
|
|
|
haystack_dup = php_string_tolower(haystack);
|
2003-04-12 07:36:22 +00:00
|
|
|
if (offset >= 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((size_t)offset > ZSTR_LEN(haystack)) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(haystack_dup, 0);
|
2019-08-22 09:09:44 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2006-10-02 19:58:15 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(haystack_dup) + offset;
|
|
|
|
e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);
|
2002-10-10 18:41:24 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(haystack_dup, 0);
|
2019-08-22 09:09:44 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2006-10-02 19:58:15 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(haystack_dup);
|
2016-06-23 09:47:06 +00:00
|
|
|
if ((size_t)-offset < ZSTR_LEN(needle)) {
|
2015-06-30 01:05:24 +00:00
|
|
|
e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);
|
2015-01-19 02:38:25 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack) + offset + ZSTR_LEN(needle);
|
2003-04-12 07:36:22 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
|
2015-01-12 09:24:37 +00:00
|
|
|
needle_dup = php_string_tolower(needle);
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((found = (char *)zend_memnrstr(p, ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), e))) {
|
|
|
|
RETVAL_LONG(found - ZSTR_VAL(haystack_dup));
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(needle_dup, 0);
|
|
|
|
zend_string_release_ex(haystack_dup, 0);
|
2015-01-12 09:24:37 +00:00
|
|
|
} else {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(needle_dup, 0);
|
|
|
|
zend_string_release_ex(haystack_dup, 0);
|
2015-01-12 09:24:37 +00:00
|
|
|
RETURN_FALSE;
|
2003-04-12 07:36:22 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false strrchr(string haystack, string needle)
|
2001-09-04 10:44:28 +00:00
|
|
|
Finds the last occurrence of a character in a string within another */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strrchr)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2019-01-29 09:02:03 +00:00
|
|
|
zend_string *haystack, *needle;
|
2010-11-19 16:03:00 +00:00
|
|
|
const char *found = NULL;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long found_offset;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(haystack)
|
2019-01-29 09:02:03 +00:00
|
|
|
Z_PARAM_STR(needle)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2019-01-29 09:02:03 +00:00
|
|
|
found = zend_memrchr(ZSTR_VAL(haystack), *ZSTR_VAL(needle), ZSTR_LEN(haystack));
|
1999-04-17 00:37:12 +00:00
|
|
|
if (found) {
|
2015-06-30 01:05:24 +00:00
|
|
|
found_offset = found - ZSTR_VAL(haystack);
|
|
|
|
RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset);
|
1999-04-17 00:37:12 +00:00
|
|
|
} else {
|
2001-09-04 06:18:11 +00:00
|
|
|
RETURN_FALSE;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_chunk_split
|
|
|
|
*/
|
2018-03-16 19:36:41 +00:00
|
|
|
static zend_string *php_chunk_split(const char *src, size_t srclen, const char *end, size_t endlen, size_t chunklen)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-03-16 19:36:41 +00:00
|
|
|
char *q;
|
|
|
|
const char *p;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t chunks; /* complete chunks! */
|
|
|
|
size_t restlen;
|
|
|
|
size_t out_len;
|
2014-02-24 09:35:47 +00:00
|
|
|
zend_string *dest;
|
1999-04-17 00:37:12 +00:00
|
|
|
|
|
|
|
chunks = srclen / chunklen;
|
|
|
|
restlen = srclen - chunks * chunklen; /* srclen % chunklen */
|
|
|
|
|
2014-02-24 09:35:47 +00:00
|
|
|
if (chunks > INT_MAX - 1) {
|
2007-06-06 17:59:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-06-03 18:47:10 +00:00
|
|
|
out_len = chunks + 1;
|
2014-02-24 09:35:47 +00:00
|
|
|
if (endlen !=0 && out_len > INT_MAX/endlen) {
|
2007-06-06 17:59:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-06-03 18:47:10 +00:00
|
|
|
out_len *= endlen;
|
2014-02-24 09:35:47 +00:00
|
|
|
if (out_len > INT_MAX - srclen - 1) {
|
2007-05-30 00:33:13 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-06-06 17:59:07 +00:00
|
|
|
out_len += srclen + 1;
|
2007-05-30 00:33:13 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
dest = zend_string_alloc(out_len * sizeof(char), 0);
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (p = src, q = ZSTR_VAL(dest); p < (src + srclen - chunklen + 1); ) {
|
1999-04-17 00:37:12 +00:00
|
|
|
memcpy(q, p, chunklen);
|
|
|
|
q += chunklen;
|
|
|
|
memcpy(q, end, endlen);
|
|
|
|
q += endlen;
|
|
|
|
p += chunklen;
|
|
|
|
}
|
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
if (restlen) {
|
1999-04-17 00:37:12 +00:00
|
|
|
memcpy(q, p, restlen);
|
|
|
|
q += restlen;
|
|
|
|
memcpy(q, end, endlen);
|
|
|
|
q += endlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
*q = '\0';
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_LEN(dest) = q - ZSTR_VAL(dest);
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2014-02-24 09:35:47 +00:00
|
|
|
return dest;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false chunk_split(string str [, int chunklen [, string ending]])
|
2001-09-04 10:44:28 +00:00
|
|
|
Returns split line */
|
2012-01-02 00:47:57 +00:00
|
|
|
PHP_FUNCTION(chunk_split)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
1999-04-17 00:37:12 +00:00
|
|
|
char *end = "\r\n";
|
2014-08-27 15:31:24 +00:00
|
|
|
size_t endlen = 2;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long chunklen = 76;
|
2014-02-24 09:35:47 +00:00
|
|
|
zend_string *result;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 3)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(chunklen)
|
|
|
|
Z_PARAM_STRING(end, endlen)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-02-08 15:26:17 +00:00
|
|
|
|
2001-09-04 06:18:11 +00:00
|
|
|
if (chunklen <= 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero");
|
1999-04-17 00:37:12 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2000-08-17 08:47:42 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((size_t)chunklen > ZSTR_LEN(str)) {
|
2005-04-03 18:08:40 +00:00
|
|
|
/* to maintain BC, we must return original string + ending */
|
2016-01-27 06:10:43 +00:00
|
|
|
result = zend_string_safe_alloc(ZSTR_LEN(str), 1, endlen, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result), ZSTR_VAL(str), ZSTR_LEN(str));
|
|
|
|
memcpy(ZSTR_VAL(result) + ZSTR_LEN(str), end, endlen);
|
|
|
|
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(result);
|
2005-01-18 15:47:57 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(str)) {
|
2000-08-17 08:47:42 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
result = php_chunk_split(ZSTR_VAL(str), ZSTR_LEN(str), end, endlen, (size_t)chunklen);
|
2003-02-08 15:26:17 +00:00
|
|
|
|
2001-09-04 06:18:11 +00:00
|
|
|
if (result) {
|
2014-02-24 09:35:47 +00:00
|
|
|
RETURN_STR(result);
|
1999-04-17 00:37:12 +00:00
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false substr(string str, int start [, int length])
|
2001-09-04 10:44:28 +00:00
|
|
|
Returns part of a string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(substr)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long l = 0, f;
|
2001-09-04 06:18:11 +00:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
2014-08-16 10:55:13 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_PARAM_LONG(f)
|
2014-07-11 12:32:20 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_PARAM_LONG(l)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-02-08 15:26:17 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (f > (zend_long)ZSTR_LEN(str)) {
|
2007-03-09 01:58:34 +00:00
|
|
|
RETURN_FALSE;
|
2018-10-29 10:11:41 +00:00
|
|
|
} else if (f < 0) {
|
|
|
|
/* if "from" position is negative, count start position from the end
|
|
|
|
* of the string
|
|
|
|
*/
|
|
|
|
if ((size_t)-f > ZSTR_LEN(str)) {
|
1999-04-17 00:37:12 +00:00
|
|
|
f = 0;
|
2018-10-29 10:11:41 +00:00
|
|
|
} else {
|
|
|
|
f = (zend_long)ZSTR_LEN(str) + f;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2018-10-29 10:11:41 +00:00
|
|
|
if (argc > 2) {
|
|
|
|
if (l < 0) {
|
|
|
|
/* if "length" position is negative, set it to the length
|
|
|
|
* needed to stop that many chars from the end of the string
|
|
|
|
*/
|
|
|
|
if ((size_t)(-l) > ZSTR_LEN(str) - (size_t)f) {
|
|
|
|
if ((size_t)(-l) > ZSTR_LEN(str)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
} else {
|
|
|
|
l = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
l = (zend_long)ZSTR_LEN(str) - f + l;
|
|
|
|
}
|
|
|
|
} else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
|
|
|
|
goto truncate_len;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
goto truncate_len;
|
|
|
|
}
|
|
|
|
} else if (argc > 2) {
|
1999-04-17 00:37:12 +00:00
|
|
|
if (l < 0) {
|
2018-10-29 10:11:41 +00:00
|
|
|
/* if "length" position is negative, set it to the length
|
|
|
|
* needed to stop that many chars from the end of the string
|
|
|
|
*/
|
|
|
|
if ((size_t)(-l) > ZSTR_LEN(str) - (size_t)f) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
} else {
|
|
|
|
l = (zend_long)ZSTR_LEN(str) - f + l;
|
|
|
|
}
|
|
|
|
} else if ((size_t)l > ZSTR_LEN(str) - (size_t)f) {
|
|
|
|
goto truncate_len;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2018-10-29 10:11:41 +00:00
|
|
|
} else {
|
|
|
|
truncate_len:
|
|
|
|
l = (zend_long)ZSTR_LEN(str) - f;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
1999-06-15 21:51:00 +00:00
|
|
|
|
2017-05-18 14:59:59 +00:00
|
|
|
if (l == 0) {
|
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
} else if (l == 1) {
|
|
|
|
RETURN_INTERNED_STR(ZSTR_CHAR((zend_uchar)(ZSTR_VAL(str)[f])));
|
|
|
|
} else if (l == ZSTR_LEN(str)) {
|
|
|
|
RETURN_STR_COPY(str);
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_STRINGL(ZSTR_VAL(str) + f, l);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|array|false substr_replace(mixed str, mixed repl, mixed start [, mixed length])
|
2001-09-04 10:44:28 +00:00
|
|
|
Replaces part of a string with another string */
|
1999-11-16 22:44:13 +00:00
|
|
|
PHP_FUNCTION(substr_replace)
|
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *str;
|
|
|
|
zval *from;
|
|
|
|
zval *len = NULL;
|
|
|
|
zval *repl;
|
2015-06-29 08:56:51 +00:00
|
|
|
zend_long l = 0;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long f;
|
2002-09-11 14:40:52 +00:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
2014-02-24 07:58:38 +00:00
|
|
|
zend_string *result;
|
2015-02-10 13:59:34 +00:00
|
|
|
HashPosition from_idx, repl_idx, len_idx;
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *tmp_str = NULL, *tmp_from = NULL, *tmp_repl = NULL, *tmp_len= NULL;
|
2003-05-02 10:02:40 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(3, 4)
|
2017-06-19 09:55:59 +00:00
|
|
|
Z_PARAM_ZVAL(str)
|
|
|
|
Z_PARAM_ZVAL(repl)
|
|
|
|
Z_PARAM_ZVAL(from)
|
2016-12-31 00:40:45 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
2017-06-19 09:55:59 +00:00
|
|
|
Z_PARAM_ZVAL(len)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(str) != IS_ARRAY) {
|
2003-05-02 10:02:40 +00:00
|
|
|
convert_to_string_ex(str);
|
|
|
|
}
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(repl) != IS_ARRAY) {
|
2003-05-02 10:02:40 +00:00
|
|
|
convert_to_string_ex(repl);
|
|
|
|
}
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(from) != IS_ARRAY) {
|
2014-08-25 19:51:49 +00:00
|
|
|
convert_to_long_ex(from);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 14:32:18 +00:00
|
|
|
if (EG(exception)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-09-04 06:18:11 +00:00
|
|
|
if (argc > 3) {
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(len) != IS_ARRAY) {
|
2016-03-31 16:10:12 +00:00
|
|
|
convert_to_long_ex(len);
|
2017-12-07 16:24:55 +00:00
|
|
|
l = Z_LVAL_P(len);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2002-10-10 18:41:24 +00:00
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(str) != IS_ARRAY) {
|
2014-08-25 17:24:55 +00:00
|
|
|
l = Z_STRLEN_P(str);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
1999-11-16 22:44:13 +00:00
|
|
|
}
|
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(str) == IS_STRING) {
|
2003-05-02 10:02:40 +00:00
|
|
|
if (
|
2014-02-10 13:49:21 +00:00
|
|
|
(argc == 3 && Z_TYPE_P(from) == IS_ARRAY) ||
|
|
|
|
(argc == 4 && Z_TYPE_P(from) != Z_TYPE_P(len))
|
2003-05-02 10:02:40 +00:00
|
|
|
) {
|
2016-03-31 16:10:12 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "'start' and 'length' should be of same type - numerical or array ");
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(Z_STR_P(str));
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2014-02-10 13:49:21 +00:00
|
|
|
if (argc == 4 && Z_TYPE_P(from) == IS_ARRAY) {
|
|
|
|
if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) {
|
2016-03-31 16:10:12 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "'start' and 'length' should have the same number of elements");
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(Z_STR_P(str));
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
1999-11-16 22:44:13 +00:00
|
|
|
}
|
2002-10-10 18:41:24 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(str) != IS_ARRAY) {
|
|
|
|
if (Z_TYPE_P(from) != IS_ARRAY) {
|
2015-12-22 04:07:44 +00:00
|
|
|
zend_string *repl_str;
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *tmp_repl_str = NULL;
|
2014-08-25 17:24:55 +00:00
|
|
|
f = Z_LVAL_P(from);
|
2003-05-02 10:02:40 +00:00
|
|
|
|
|
|
|
/* if "from" position is negative, count start position from the end
|
|
|
|
* of the string
|
|
|
|
*/
|
|
|
|
if (f < 0) {
|
2015-06-29 18:33:34 +00:00
|
|
|
f = (zend_long)Z_STRLEN_P(str) + f;
|
|
|
|
if (f < 0) {
|
2003-05-02 10:02:40 +00:00
|
|
|
f = 0;
|
|
|
|
}
|
2016-06-23 09:47:06 +00:00
|
|
|
} else if ((size_t)f > Z_STRLEN_P(str)) {
|
2014-08-25 17:24:55 +00:00
|
|
|
f = Z_STRLEN_P(str);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
|
|
|
/* if "length" position is negative, set it to the length
|
|
|
|
* needed to stop that many chars from the end of the string
|
|
|
|
*/
|
|
|
|
if (l < 0) {
|
2015-06-29 18:33:34 +00:00
|
|
|
l = ((zend_long)Z_STRLEN_P(str) - f) + l;
|
2003-05-02 10:02:40 +00:00
|
|
|
if (l < 0) {
|
|
|
|
l = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-23 09:47:06 +00:00
|
|
|
if ((size_t)l > Z_STRLEN_P(str) || (l < 0 && (size_t)(-l) > Z_STRLEN_P(str))) {
|
2014-08-25 17:24:55 +00:00
|
|
|
l = Z_STRLEN_P(str);
|
2007-03-09 01:58:34 +00:00
|
|
|
}
|
|
|
|
|
2015-06-29 18:33:34 +00:00
|
|
|
if ((f + l) > (zend_long)Z_STRLEN_P(str)) {
|
2014-08-25 17:24:55 +00:00
|
|
|
l = Z_STRLEN_P(str) - f;
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(repl) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
repl_idx = 0;
|
|
|
|
while (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
|
|
|
|
tmp_repl = &Z_ARRVAL_P(repl)->arData[repl_idx].val;
|
|
|
|
if (Z_TYPE_P(tmp_repl) != IS_UNDEF) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
repl_idx++;
|
|
|
|
}
|
|
|
|
if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
|
2017-11-16 14:09:32 +00:00
|
|
|
repl_str = zval_get_tmp_string(tmp_repl, &tmp_repl_str);
|
2015-12-22 04:07:44 +00:00
|
|
|
} else {
|
|
|
|
repl_str = STR_EMPTY_ALLOC();
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-12-22 04:07:44 +00:00
|
|
|
repl_str = Z_STR_P(repl);
|
2003-12-01 23:17:22 +00:00
|
|
|
}
|
2003-05-02 10:02:40 +00:00
|
|
|
|
2016-09-13 09:50:18 +00:00
|
|
|
result = zend_string_safe_alloc(1, Z_STRLEN_P(str) - l + ZSTR_LEN(repl_str), 0, 0);
|
2014-02-24 07:58:38 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result), Z_STRVAL_P(str), f);
|
2015-12-22 04:07:44 +00:00
|
|
|
if (ZSTR_LEN(repl_str)) {
|
|
|
|
memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str));
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2015-12-22 04:07:44 +00:00
|
|
|
memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), Z_STRVAL_P(str) + f + l, Z_STRLEN_P(str) - f - l);
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_repl_str);
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(result);
|
2003-05-02 10:02:40 +00:00
|
|
|
} else {
|
2016-03-31 16:10:12 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Functionality of 'start' and 'length' as arrays is not implemented");
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(Z_STR_P(str));
|
1999-11-16 22:44:13 +00:00
|
|
|
}
|
2003-05-02 10:02:40 +00:00
|
|
|
} else { /* str is array of strings */
|
2014-02-10 13:49:21 +00:00
|
|
|
zend_string *str_index = NULL;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t result_len;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_ulong num_index;
|
2011-08-29 20:38:52 +00:00
|
|
|
|
2003-05-02 10:02:40 +00:00
|
|
|
array_init(return_value);
|
1999-11-16 22:44:13 +00:00
|
|
|
|
2015-02-10 13:59:34 +00:00
|
|
|
from_idx = len_idx = repl_idx = 0;
|
2003-12-01 23:17:22 +00:00
|
|
|
|
2014-04-21 10:20:05 +00:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(str), num_index, str_index, tmp_str) {
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *tmp_orig_str;
|
|
|
|
zend_string *orig_str = zval_get_tmp_string(tmp_str, &tmp_orig_str);
|
2003-12-01 23:17:22 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(from) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
while (from_idx < Z_ARRVAL_P(from)->nNumUsed) {
|
|
|
|
tmp_from = &Z_ARRVAL_P(from)->arData[from_idx].val;
|
|
|
|
if (Z_TYPE_P(tmp_from) != IS_UNDEF) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
from_idx++;
|
|
|
|
}
|
|
|
|
if (from_idx < Z_ARRVAL_P(from)->nNumUsed) {
|
2014-08-25 17:24:55 +00:00
|
|
|
f = zval_get_long(tmp_from);
|
2003-12-01 23:17:22 +00:00
|
|
|
|
2003-05-02 10:02:40 +00:00
|
|
|
if (f < 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
f = (zend_long)ZSTR_LEN(orig_str) + f;
|
2015-06-29 18:33:34 +00:00
|
|
|
if (f < 0) {
|
2003-05-02 10:02:40 +00:00
|
|
|
f = 0;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (f > (zend_long)ZSTR_LEN(orig_str)) {
|
|
|
|
f = ZSTR_LEN(orig_str);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2015-02-10 13:59:34 +00:00
|
|
|
from_idx++;
|
2003-05-02 10:02:40 +00:00
|
|
|
} else {
|
|
|
|
f = 0;
|
2003-12-01 23:17:22 +00:00
|
|
|
}
|
2003-05-02 10:02:40 +00:00
|
|
|
} else {
|
2014-08-25 17:24:55 +00:00
|
|
|
f = Z_LVAL_P(from);
|
2003-05-02 10:02:40 +00:00
|
|
|
if (f < 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
f = (zend_long)ZSTR_LEN(orig_str) + f;
|
2015-06-29 18:33:34 +00:00
|
|
|
if (f < 0) {
|
2003-05-02 10:02:40 +00:00
|
|
|
f = 0;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (f > (zend_long)ZSTR_LEN(orig_str)) {
|
|
|
|
f = ZSTR_LEN(orig_str);
|
2003-12-01 23:17:22 +00:00
|
|
|
}
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (argc > 3 && Z_TYPE_P(len) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
while (len_idx < Z_ARRVAL_P(len)->nNumUsed) {
|
|
|
|
tmp_len = &Z_ARRVAL_P(len)->arData[len_idx].val;
|
|
|
|
if (Z_TYPE_P(tmp_len) != IS_UNDEF) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
len_idx++;
|
|
|
|
}
|
|
|
|
if (len_idx < Z_ARRVAL_P(len)->nNumUsed) {
|
2014-08-25 17:24:55 +00:00
|
|
|
l = zval_get_long(tmp_len);
|
2015-02-10 13:59:34 +00:00
|
|
|
len_idx++;
|
2003-05-02 10:02:40 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
l = ZSTR_LEN(orig_str);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
} else if (argc > 3) {
|
2014-08-25 17:24:55 +00:00
|
|
|
l = Z_LVAL_P(len);
|
2003-05-02 10:02:40 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
l = ZSTR_LEN(orig_str);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2003-12-01 23:17:22 +00:00
|
|
|
|
2003-05-02 10:02:40 +00:00
|
|
|
if (l < 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
l = (ZSTR_LEN(orig_str) - f) + l;
|
2003-05-02 10:02:40 +00:00
|
|
|
if (l < 0) {
|
|
|
|
l = 0;
|
|
|
|
}
|
2003-12-01 23:17:22 +00:00
|
|
|
}
|
2003-05-02 10:02:40 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((f + l) > (zend_long)ZSTR_LEN(orig_str)) {
|
|
|
|
l = ZSTR_LEN(orig_str) - f;
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
2003-12-01 23:17:22 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
result_len = ZSTR_LEN(orig_str) - l;
|
2003-12-01 23:17:22 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(repl) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
while (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
|
|
|
|
tmp_repl = &Z_ARRVAL_P(repl)->arData[repl_idx].val;
|
|
|
|
if (Z_TYPE_P(tmp_repl) != IS_UNDEF) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
repl_idx++;
|
|
|
|
}
|
|
|
|
if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) {
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *tmp_repl_str;
|
|
|
|
zend_string *repl_str = zval_get_tmp_string(tmp_repl, &tmp_repl_str);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
result_len += ZSTR_LEN(repl_str);
|
2015-02-10 13:59:34 +00:00
|
|
|
repl_idx++;
|
2016-09-13 09:50:18 +00:00
|
|
|
result = zend_string_safe_alloc(1, result_len, 0, 0);
|
2003-05-02 10:02:40 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
|
|
|
|
memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str));
|
|
|
|
memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_repl_str);
|
2003-05-02 10:02:40 +00:00
|
|
|
} else {
|
2016-09-13 09:50:18 +00:00
|
|
|
result = zend_string_safe_alloc(1, result_len, 0, 0);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
|
|
|
|
memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-08-25 17:24:55 +00:00
|
|
|
result_len += Z_STRLEN_P(repl);
|
2003-05-02 10:02:40 +00:00
|
|
|
|
2016-09-13 09:50:18 +00:00
|
|
|
result = zend_string_safe_alloc(1, result_len, 0, 0);
|
1999-11-16 22:44:13 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result), ZSTR_VAL(orig_str), f);
|
|
|
|
memcpy((ZSTR_VAL(result) + f), Z_STRVAL_P(repl), Z_STRLEN_P(repl));
|
|
|
|
memcpy((ZSTR_VAL(result) + f + Z_STRLEN_P(repl)), ZSTR_VAL(orig_str) + f + l, ZSTR_LEN(orig_str) - f - l);
|
2003-05-02 10:02:40 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
|
2011-08-29 20:38:52 +00:00
|
|
|
|
2014-04-21 10:20:05 +00:00
|
|
|
if (str_index) {
|
|
|
|
zval tmp;
|
|
|
|
|
2014-09-19 13:32:50 +00:00
|
|
|
ZVAL_NEW_STR(&tmp, result);
|
2014-04-21 10:20:05 +00:00
|
|
|
zend_symtable_update(Z_ARRVAL_P(return_value), str_index, &tmp);
|
2011-08-29 20:38:52 +00:00
|
|
|
} else {
|
2014-02-24 07:58:38 +00:00
|
|
|
add_index_str(return_value, num_index, result);
|
2011-08-29 20:38:52 +00:00
|
|
|
}
|
|
|
|
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_orig_str);
|
2014-04-21 10:20:05 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2003-05-02 10:02:40 +00:00
|
|
|
} /* if */
|
1999-11-16 22:44:13 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
/* {{{ proto string quotemeta(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Quotes meta characters */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(quotemeta)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *old;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *old_end, *p;
|
|
|
|
char *q;
|
1999-04-17 00:37:12 +00:00
|
|
|
char c;
|
2014-02-25 05:08:16 +00:00
|
|
|
zend_string *str;
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(old)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
old_end = ZSTR_VAL(old) + ZSTR_LEN(old);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2019-02-11 08:58:10 +00:00
|
|
|
if (ZSTR_LEN(old) == 0) {
|
|
|
|
RETURN_EMPTY_STRING();
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-01-27 06:10:43 +00:00
|
|
|
str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (p = ZSTR_VAL(old), q = ZSTR_VAL(str); p != old_end; p++) {
|
1999-12-20 20:43:47 +00:00
|
|
|
c = *p;
|
2002-10-02 17:56:04 +00:00
|
|
|
switch (c) {
|
1999-04-17 00:37:12 +00:00
|
|
|
case '.':
|
|
|
|
case '\\':
|
|
|
|
case '+':
|
|
|
|
case '*':
|
|
|
|
case '?':
|
|
|
|
case '[':
|
|
|
|
case '^':
|
|
|
|
case ']':
|
|
|
|
case '$':
|
|
|
|
case '(':
|
|
|
|
case ')':
|
|
|
|
*q++ = '\\';
|
|
|
|
/* break is missing _intentionally_ */
|
|
|
|
default:
|
|
|
|
*q++ = c;
|
|
|
|
}
|
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2014-02-25 05:08:16 +00:00
|
|
|
*q = '\0';
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_NEW_STR(zend_string_truncate(str, q - ZSTR_VAL(str), 0));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto int ord(string character)
|
2016-02-19 12:44:11 +00:00
|
|
|
Returns ASCII value of character
|
|
|
|
Warning: This function is special-cased by zend_compile.c and so is bypassed for constant string argument */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(ord)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-02-17 14:29:59 +00:00
|
|
|
zend_string *str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2018-02-17 14:29:59 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2018-02-17 14:29:59 +00:00
|
|
|
RETURN_LONG((unsigned char) ZSTR_VAL(str)[0]);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string chr(int ascii)
|
2016-02-19 12:44:11 +00:00
|
|
|
Converts ASCII code to a character
|
|
|
|
Warning: This function is special-cased by zend_compile.c and so is bypassed for constant integer argument */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(chr)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long c;
|
2008-01-22 01:34:24 +00:00
|
|
|
|
2019-05-08 19:42:02 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2014-12-19 02:05:30 +00:00
|
|
|
Z_PARAM_LONG(c)
|
2019-05-28 11:03:41 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-01-25 01:31:10 +00:00
|
|
|
|
2014-12-19 02:05:30 +00:00
|
|
|
c &= 0xff;
|
2017-03-04 09:39:13 +00:00
|
|
|
ZVAL_INTERNED_STR(return_value, ZSTR_CHAR(c));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2008-01-16 03:11:26 +00:00
|
|
|
/* {{{ php_ucfirst
|
|
|
|
Uppercase the first character of the word in a native string */
|
2017-08-06 06:56:16 +00:00
|
|
|
static zend_string* php_ucfirst(zend_string *str)
|
2008-01-16 03:11:26 +00:00
|
|
|
{
|
2017-08-06 06:56:16 +00:00
|
|
|
unsigned char r = toupper(ZSTR_VAL(str)[0]);
|
|
|
|
if (r == ZSTR_VAL(str)[0]) {
|
|
|
|
return zend_string_copy(str);
|
|
|
|
} else {
|
|
|
|
zend_string *s = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0);
|
|
|
|
ZSTR_VAL(s)[0] = r;
|
|
|
|
return s;
|
|
|
|
}
|
2008-01-16 03:11:26 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-08-09 20:52:58 +00:00
|
|
|
/* {{{ proto string ucfirst(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Makes a string's first character uppercase */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(ucfirst)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2014-08-18 13:39:38 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(str)) {
|
2002-06-17 11:37:49 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
1999-11-14 17:20:56 +00:00
|
|
|
|
2017-08-06 06:56:16 +00:00
|
|
|
RETURN_STR(php_ucfirst(str));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2008-01-19 19:27:22 +00:00
|
|
|
/* {{{
|
|
|
|
Lowercase the first character of the word in a native string */
|
2017-08-06 06:56:16 +00:00
|
|
|
static zend_string* php_lcfirst(zend_string *str)
|
2008-01-19 19:27:22 +00:00
|
|
|
{
|
2017-08-06 06:56:16 +00:00
|
|
|
unsigned char r = tolower(ZSTR_VAL(str)[0]);
|
|
|
|
if (r == ZSTR_VAL(str)[0]) {
|
|
|
|
return zend_string_copy(str);
|
|
|
|
} else {
|
|
|
|
zend_string *s = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0);
|
|
|
|
ZSTR_VAL(s)[0] = r;
|
|
|
|
return s;
|
|
|
|
}
|
2008-01-19 19:27:22 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2010-07-20 04:26:57 +00:00
|
|
|
/* {{{ proto string lcfirst(string str)
|
2008-01-19 19:27:22 +00:00
|
|
|
Make a string's first character lowercase */
|
|
|
|
PHP_FUNCTION(lcfirst)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2008-01-19 19:27:22 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-01-19 19:27:22 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(str)) {
|
2008-01-19 19:27:22 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
|
|
|
|
2017-08-06 06:56:16 +00:00
|
|
|
RETURN_STR(php_lcfirst(str));
|
2008-01-19 19:27:22 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2015-07-07 13:48:55 +00:00
|
|
|
/* {{{ proto string ucwords(string str [, string delims])
|
1999-04-17 00:37:12 +00:00
|
|
|
Uppercase the first character of every word in a string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(ucwords)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
|
|
|
char *delims = " \t\r\n\f\v";
|
2018-03-16 19:36:41 +00:00
|
|
|
register char *r;
|
|
|
|
register const char *r_end;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t delims_len = 6;
|
2014-07-02 14:22:11 +00:00
|
|
|
char mask[256];
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-14 07:44:53 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
2014-08-18 13:39:38 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-14 07:44:53 +00:00
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STRING(delims, delims_len)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(str)) {
|
2002-06-17 11:37:49 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2000-06-01 10:07:44 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
php_charmask((unsigned char *)delims, delims_len, mask);
|
2014-07-02 14:22:11 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
|
2001-09-04 06:18:11 +00:00
|
|
|
r = Z_STRVAL_P(return_value);
|
|
|
|
|
|
|
|
*r = toupper((unsigned char) *r);
|
2014-08-25 17:24:55 +00:00
|
|
|
for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
|
2014-07-02 14:22:11 +00:00
|
|
|
if (mask[(unsigned char)*r++]) {
|
2001-09-04 06:18:11 +00:00
|
|
|
*r = toupper((unsigned char) *r);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strtr
|
|
|
|
*/
|
2017-12-14 19:14:36 +00:00
|
|
|
PHPAPI char *php_strtr(char *str, size_t len, const char *str_from, const char *str_to, size_t trlen)
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
{
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t i;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2015-01-12 13:51:59 +00:00
|
|
|
if (UNEXPECTED(trlen < 1)) {
|
2000-02-08 22:21:43 +00:00
|
|
|
return str;
|
2015-01-12 13:51:59 +00:00
|
|
|
} else if (trlen == 1) {
|
|
|
|
char ch_from = *str_from;
|
|
|
|
char ch_to = *str_to;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2015-01-12 13:51:59 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if (str[i] == ch_from) {
|
|
|
|
str[i] = ch_to;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsigned char xlat[256], j = 0;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2015-01-12 13:51:59 +00:00
|
|
|
do { xlat[j] = j; } while (++j != 0);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2015-01-12 13:51:59 +00:00
|
|
|
for (i = 0; i < trlen; i++) {
|
|
|
|
xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
|
|
|
|
}
|
2017-01-16 20:11:50 +00:00
|
|
|
|
2015-01-12 13:51:59 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
str[i] = xlat[(size_t)(unsigned char) str[i]];
|
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
|
|
|
|
2000-02-08 22:21:43 +00:00
|
|
|
return str;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2015-01-14 17:58:41 +00:00
|
|
|
/* {{{ php_strtr_ex
|
|
|
|
*/
|
2017-12-14 19:14:36 +00:00
|
|
|
static zend_string *php_strtr_ex(zend_string *str, const char *str_from, const char *str_to, size_t trlen)
|
2015-01-14 17:58:41 +00:00
|
|
|
{
|
|
|
|
zend_string *new_str = NULL;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (UNEXPECTED(trlen < 1)) {
|
|
|
|
return zend_string_copy(str);
|
|
|
|
} else if (trlen == 1) {
|
|
|
|
char ch_from = *str_from;
|
|
|
|
char ch_to = *str_to;
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (i = 0; i < ZSTR_LEN(str); i++) {
|
|
|
|
if (ZSTR_VAL(str)[i] == ch_from) {
|
|
|
|
new_str = zend_string_alloc(ZSTR_LEN(str), 0);
|
|
|
|
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);
|
|
|
|
ZSTR_VAL(new_str)[i] = ch_to;
|
2015-01-14 17:58:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
for (; i < ZSTR_LEN(str); i++) {
|
|
|
|
ZSTR_VAL(new_str)[i] = (ZSTR_VAL(str)[i] != ch_from) ? ZSTR_VAL(str)[i] : ch_to;
|
2015-01-14 17:58:41 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsigned char xlat[256], j = 0;
|
|
|
|
|
|
|
|
do { xlat[j] = j; } while (++j != 0);
|
|
|
|
|
|
|
|
for (i = 0; i < trlen; i++) {
|
|
|
|
xlat[(size_t)(unsigned char) str_from[i]] = str_to[i];
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (i = 0; i < ZSTR_LEN(str); i++) {
|
|
|
|
if (ZSTR_VAL(str)[i] != xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]]) {
|
|
|
|
new_str = zend_string_alloc(ZSTR_LEN(str), 0);
|
|
|
|
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), i);
|
|
|
|
ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
|
2015-01-14 17:58:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (;i < ZSTR_LEN(str); i++) {
|
|
|
|
ZSTR_VAL(new_str)[i] = xlat[(size_t)(unsigned char) ZSTR_VAL(str)[i]];
|
2015-01-14 17:58:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!new_str) {
|
|
|
|
return zend_string_copy(str);
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(new_str)[ZSTR_LEN(new_str)] = 0;
|
2015-01-14 17:58:41 +00:00
|
|
|
return new_str;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2014-04-24 15:14:29 +00:00
|
|
|
/* {{{ php_strtr_array */
|
2015-01-14 17:58:41 +00:00
|
|
|
static void php_strtr_array(zval *return_value, zend_string *input, HashTable *pats)
|
2013-01-07 02:13:11 +00:00
|
|
|
{
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *str = ZSTR_VAL(input);
|
2015-06-30 01:05:24 +00:00
|
|
|
size_t slen = ZSTR_LEN(input);
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_ulong num_key;
|
2014-04-24 15:14:29 +00:00
|
|
|
zend_string *str_key;
|
2015-01-14 17:58:41 +00:00
|
|
|
size_t len, pos, old_pos;
|
2014-04-24 15:14:29 +00:00
|
|
|
int num_keys = 0;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t minlen = 128*1024;
|
|
|
|
size_t maxlen = 0;
|
2015-05-15 01:03:30 +00:00
|
|
|
HashTable str_hash;
|
2015-06-20 02:37:53 +00:00
|
|
|
zval *entry;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *key;
|
2014-04-24 15:14:29 +00:00
|
|
|
smart_str result = {0};
|
2015-01-14 12:04:04 +00:00
|
|
|
zend_ulong bitset[256/sizeof(zend_ulong)];
|
2015-05-15 01:03:30 +00:00
|
|
|
zend_ulong *num_bitset;
|
2014-04-24 15:14:29 +00:00
|
|
|
|
2014-11-19 19:59:31 +00:00
|
|
|
/* we will collect all possible key lengths */
|
2015-10-08 11:30:43 +00:00
|
|
|
num_bitset = ecalloc((slen + sizeof(zend_ulong)) / sizeof(zend_ulong), sizeof(zend_ulong));
|
2015-01-14 12:04:04 +00:00
|
|
|
memset(bitset, 0, sizeof(bitset));
|
2014-04-24 15:14:29 +00:00
|
|
|
|
|
|
|
/* check if original array has numeric keys */
|
2015-05-15 01:03:30 +00:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY(pats, str_key) {
|
2014-04-24 15:14:29 +00:00
|
|
|
if (UNEXPECTED(!str_key)) {
|
|
|
|
num_keys = 1;
|
2013-01-08 23:33:14 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
len = ZSTR_LEN(str_key);
|
2014-04-24 15:14:29 +00:00
|
|
|
if (UNEXPECTED(len < 1)) {
|
2016-08-29 13:43:10 +00:00
|
|
|
efree(num_bitset);
|
2014-04-24 15:14:29 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
} else if (UNEXPECTED(len > slen)) {
|
|
|
|
/* skip long patterns */
|
|
|
|
continue;
|
2013-01-07 02:13:11 +00:00
|
|
|
}
|
2014-04-24 15:14:29 +00:00
|
|
|
if (len > maxlen) {
|
|
|
|
maxlen = len;
|
|
|
|
}
|
|
|
|
if (len < minlen) {
|
|
|
|
minlen = len;
|
|
|
|
}
|
2014-11-19 19:59:31 +00:00
|
|
|
/* remember possible key length */
|
2015-05-15 01:03:30 +00:00
|
|
|
num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));
|
2015-06-30 01:05:24 +00:00
|
|
|
bitset[((unsigned char)ZSTR_VAL(str_key)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(str_key)[0]) % sizeof(zend_ulong));
|
1999-11-20 15:53:18 +00:00
|
|
|
}
|
2014-04-24 15:14:29 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2013-01-07 02:13:11 +00:00
|
|
|
|
2015-05-15 01:03:30 +00:00
|
|
|
if (UNEXPECTED(num_keys)) {
|
2015-06-18 14:28:29 +00:00
|
|
|
zend_string *key_used;
|
2014-04-24 15:14:29 +00:00
|
|
|
/* we have to rebuild HashTable with numeric keys */
|
|
|
|
zend_hash_init(&str_hash, zend_hash_num_elements(pats), NULL, NULL, 0);
|
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
|
|
|
|
if (UNEXPECTED(!str_key)) {
|
2015-06-18 14:28:29 +00:00
|
|
|
key_used = zend_long_to_str(num_key);
|
2015-06-30 01:05:24 +00:00
|
|
|
len = ZSTR_LEN(key_used);
|
2014-04-24 15:14:29 +00:00
|
|
|
if (UNEXPECTED(len > slen)) {
|
|
|
|
/* skip long patterns */
|
2013-01-07 02:13:11 +00:00
|
|
|
continue;
|
2014-04-24 15:14:29 +00:00
|
|
|
}
|
|
|
|
if (len > maxlen) {
|
|
|
|
maxlen = len;
|
|
|
|
}
|
|
|
|
if (len < minlen) {
|
|
|
|
minlen = len;
|
|
|
|
}
|
2014-11-19 19:59:31 +00:00
|
|
|
/* remember possible key length */
|
2015-05-15 01:03:30 +00:00
|
|
|
num_bitset[len / sizeof(zend_ulong)] |= Z_UL(1) << (len % sizeof(zend_ulong));
|
2015-06-30 01:05:24 +00:00
|
|
|
bitset[((unsigned char)ZSTR_VAL(key_used)[0]) / sizeof(zend_ulong)] |= Z_UL(1) << (((unsigned char)ZSTR_VAL(key_used)[0]) % sizeof(zend_ulong));
|
2014-04-24 15:14:29 +00:00
|
|
|
} else {
|
2015-06-18 14:28:29 +00:00
|
|
|
key_used = str_key;
|
2015-06-30 01:05:24 +00:00
|
|
|
len = ZSTR_LEN(key_used);
|
2014-04-24 15:14:29 +00:00
|
|
|
if (UNEXPECTED(len > slen)) {
|
|
|
|
/* skip long patterns */
|
2013-01-07 02:13:11 +00:00
|
|
|
continue;
|
2014-04-24 15:14:29 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-18 14:28:29 +00:00
|
|
|
zend_hash_add(&str_hash, key_used, entry);
|
|
|
|
if (UNEXPECTED(!str_key)) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(key_used, 0);
|
2014-04-24 15:14:29 +00:00
|
|
|
}
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
pats = &str_hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UNEXPECTED(minlen > maxlen)) {
|
|
|
|
/* return the original string */
|
|
|
|
if (pats == &str_hash) {
|
|
|
|
zend_hash_destroy(&str_hash);
|
|
|
|
}
|
2015-05-15 01:03:30 +00:00
|
|
|
efree(num_bitset);
|
|
|
|
RETURN_STR_COPY(input);
|
|
|
|
}
|
|
|
|
|
|
|
|
old_pos = pos = 0;
|
|
|
|
while (pos <= slen - minlen) {
|
|
|
|
key = str + pos;
|
2015-06-19 14:59:31 +00:00
|
|
|
if (bitset[((unsigned char)key[0]) / sizeof(zend_ulong)] & (Z_UL(1) << (((unsigned char)key[0]) % sizeof(zend_ulong)))) {
|
2015-05-15 01:03:30 +00:00
|
|
|
len = maxlen;
|
|
|
|
if (len > slen - pos) {
|
|
|
|
len = slen - pos;
|
2014-04-24 15:14:29 +00:00
|
|
|
}
|
2015-05-15 01:03:30 +00:00
|
|
|
while (len >= minlen) {
|
2015-06-19 14:59:31 +00:00
|
|
|
if ((num_bitset[len / sizeof(zend_ulong)] & (Z_UL(1) << (len % sizeof(zend_ulong))))) {
|
|
|
|
entry = zend_hash_str_find(pats, key, len);
|
|
|
|
if (entry != NULL) {
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *tmp;
|
|
|
|
zend_string *s = zval_get_tmp_string(entry, &tmp);
|
2015-06-19 14:59:31 +00:00
|
|
|
smart_str_appendl(&result, str + old_pos, pos - old_pos);
|
|
|
|
smart_str_append(&result, s);
|
|
|
|
old_pos = pos + len;
|
|
|
|
pos = old_pos - 1;
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp);
|
2015-06-19 14:59:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-01-03 09:22:58 +00:00
|
|
|
}
|
2015-05-15 01:03:30 +00:00
|
|
|
len--;
|
2014-04-24 15:14:29 +00:00
|
|
|
}
|
|
|
|
}
|
2015-05-15 01:03:30 +00:00
|
|
|
pos++;
|
2015-01-14 17:58:41 +00:00
|
|
|
}
|
2015-05-15 01:03:30 +00:00
|
|
|
|
2015-02-28 14:37:46 +00:00
|
|
|
if (result.s) {
|
2015-01-14 17:58:41 +00:00
|
|
|
smart_str_appendl(&result, str + old_pos, slen - old_pos);
|
|
|
|
smart_str_0(&result);
|
2015-03-12 13:53:51 +00:00
|
|
|
RETVAL_NEW_STR(result.s);
|
2015-01-14 17:58:41 +00:00
|
|
|
} else {
|
|
|
|
smart_str_free(&result);
|
2015-03-12 13:53:51 +00:00
|
|
|
RETVAL_STR_COPY(input);
|
2013-01-07 02:13:11 +00:00
|
|
|
}
|
|
|
|
|
2014-04-24 15:14:29 +00:00
|
|
|
if (pats == &str_hash) {
|
|
|
|
zend_hash_destroy(&str_hash);
|
1999-11-20 15:53:18 +00:00
|
|
|
}
|
2015-05-15 01:03:30 +00:00
|
|
|
efree(num_bitset);
|
1999-11-20 15:53:18 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-11-20 15:53:18 +00:00
|
|
|
|
2015-01-13 20:23:50 +00:00
|
|
|
/* {{{ php_char_to_str_ex
|
|
|
|
*/
|
|
|
|
static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, size_t to_len, int case_sensitivity, zend_long *replace_count)
|
|
|
|
{
|
|
|
|
zend_string *result;
|
|
|
|
size_t char_count = 0;
|
|
|
|
char lc_from = 0;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *source, *source_end= ZSTR_VAL(str) + ZSTR_LEN(str);
|
|
|
|
char *target;
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
if (case_sensitivity) {
|
2015-06-30 01:05:24 +00:00
|
|
|
char *p = ZSTR_VAL(str), *e = p + ZSTR_LEN(str);
|
2015-01-13 20:23:50 +00:00
|
|
|
while ((p = memchr(p, from, (e - p)))) {
|
|
|
|
char_count++;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lc_from = tolower(from);
|
2015-06-30 01:05:24 +00:00
|
|
|
for (source = ZSTR_VAL(str); source < source_end; source++) {
|
2015-01-13 20:23:50 +00:00
|
|
|
if (tolower(*source) == lc_from) {
|
|
|
|
char_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (char_count == 0) {
|
|
|
|
return zend_string_copy(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (to_len > 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
result = zend_string_safe_alloc(char_count, to_len - 1, ZSTR_LEN(str), 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
result = zend_string_alloc(ZSTR_LEN(str) - char_count, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
target = ZSTR_VAL(result);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
if (case_sensitivity) {
|
2015-06-30 01:05:24 +00:00
|
|
|
char *p = ZSTR_VAL(str), *e = p + ZSTR_LEN(str), *s = ZSTR_VAL(str);
|
2015-01-13 20:23:50 +00:00
|
|
|
while ((p = memchr(p, from, (e - p)))) {
|
|
|
|
memcpy(target, s, (p - s));
|
|
|
|
target += p - s;
|
|
|
|
memcpy(target, to, to_len);
|
|
|
|
target += to_len;
|
|
|
|
p++;
|
|
|
|
s = p;
|
|
|
|
if (replace_count) {
|
|
|
|
*replace_count += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (s < e) {
|
|
|
|
memcpy(target, s, (e - s));
|
|
|
|
target += e - s;
|
|
|
|
}
|
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
for (source = ZSTR_VAL(str); source < source_end; source++) {
|
2015-01-13 20:23:50 +00:00
|
|
|
if (tolower(*source) == lc_from) {
|
|
|
|
if (replace_count) {
|
|
|
|
*replace_count += 1;
|
|
|
|
}
|
|
|
|
memcpy(target, to, to_len);
|
|
|
|
target += to_len;
|
|
|
|
} else {
|
|
|
|
*target = *source;
|
|
|
|
target++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*target = 0;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_str_to_str_ex
|
|
|
|
*/
|
|
|
|
static zend_string *php_str_to_str_ex(zend_string *haystack,
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *needle, size_t needle_len, const char *str, size_t str_len, zend_long *replace_count)
|
2015-01-13 20:23:50 +00:00
|
|
|
{
|
|
|
|
zend_string *new_str;
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (needle_len < ZSTR_LEN(haystack)) {
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *end;
|
2018-04-26 14:53:58 +00:00
|
|
|
const char *p, *r;
|
2018-03-16 19:36:41 +00:00
|
|
|
char *e;
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
if (needle_len == str_len) {
|
|
|
|
new_str = NULL;
|
2015-06-30 01:05:24 +00:00
|
|
|
end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
|
|
|
|
for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
|
2015-01-13 20:23:50 +00:00
|
|
|
if (!new_str) {
|
2015-06-30 01:05:24 +00:00
|
|
|
new_str = zend_string_init(ZSTR_VAL(haystack), ZSTR_LEN(haystack), 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(new_str) + (r - ZSTR_VAL(haystack)), str, str_len);
|
2015-01-13 20:23:50 +00:00
|
|
|
(*replace_count)++;
|
|
|
|
}
|
|
|
|
if (!new_str) {
|
|
|
|
goto nothing_todo;
|
|
|
|
}
|
|
|
|
return new_str;
|
|
|
|
} else {
|
|
|
|
size_t count = 0;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *o = ZSTR_VAL(haystack);
|
|
|
|
const char *n = needle;
|
|
|
|
const char *endp = o + ZSTR_LEN(haystack);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
|
|
|
|
o += needle_len;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
if (count == 0) {
|
|
|
|
/* Needle doesn't occur, shortcircuit the actual replacement. */
|
|
|
|
goto nothing_todo;
|
|
|
|
}
|
2016-01-27 06:10:43 +00:00
|
|
|
if (str_len > needle_len) {
|
|
|
|
new_str = zend_string_safe_alloc(count, str_len - needle_len, ZSTR_LEN(haystack), 0);
|
|
|
|
} else {
|
|
|
|
new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0);
|
|
|
|
}
|
2015-01-13 20:23:50 +00:00
|
|
|
|
2018-04-26 14:53:58 +00:00
|
|
|
e = ZSTR_VAL(new_str);
|
2015-06-30 01:05:24 +00:00
|
|
|
end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
|
|
|
|
for (p = ZSTR_VAL(haystack); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
|
2015-01-13 20:23:50 +00:00
|
|
|
memcpy(e, p, r - p);
|
|
|
|
e += r - p;
|
|
|
|
memcpy(e, str, str_len);
|
|
|
|
e += str_len;
|
|
|
|
(*replace_count)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) {
|
|
|
|
memcpy(e, p, end - p);
|
|
|
|
e += end - p;
|
|
|
|
}
|
|
|
|
|
|
|
|
*e = '\0';
|
|
|
|
return new_str;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (needle_len > ZSTR_LEN(haystack) || memcmp(ZSTR_VAL(haystack), needle, ZSTR_LEN(haystack))) {
|
2015-01-13 20:23:50 +00:00
|
|
|
nothing_todo:
|
|
|
|
return zend_string_copy(haystack);
|
|
|
|
} else {
|
2017-05-18 14:59:59 +00:00
|
|
|
if (str_len == 0) {
|
|
|
|
new_str = ZSTR_EMPTY_ALLOC();
|
|
|
|
} else if (str_len == 1) {
|
|
|
|
new_str = ZSTR_CHAR((zend_uchar)(*str));
|
|
|
|
} else {
|
|
|
|
new_str = zend_string_init(str, str_len, 0);
|
|
|
|
}
|
|
|
|
|
2015-01-13 20:23:50 +00:00
|
|
|
(*replace_count)++;
|
|
|
|
return new_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_str_to_str_i_ex
|
|
|
|
*/
|
2018-03-16 19:36:41 +00:00
|
|
|
static zend_string *php_str_to_str_i_ex(zend_string *haystack, const char *lc_haystack,
|
|
|
|
zend_string *needle, const char *str, size_t str_len, zend_long *replace_count)
|
2015-01-13 20:23:50 +00:00
|
|
|
{
|
|
|
|
zend_string *new_str = NULL;
|
|
|
|
zend_string *lc_needle;
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(needle) < ZSTR_LEN(haystack)) {
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *end;
|
2018-04-26 14:53:58 +00:00
|
|
|
const char *p, *r;
|
2018-03-16 19:36:41 +00:00
|
|
|
char *e;
|
2015-01-13 20:23:50 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(needle) == str_len) {
|
2015-01-13 20:23:50 +00:00
|
|
|
lc_needle = php_string_tolower(needle);
|
2015-06-30 01:05:24 +00:00
|
|
|
end = lc_haystack + ZSTR_LEN(haystack);
|
|
|
|
for (p = lc_haystack; (r = (char*)php_memnstr(p, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle), end)); p = r + ZSTR_LEN(lc_needle)) {
|
2015-01-13 20:23:50 +00:00
|
|
|
if (!new_str) {
|
2015-06-30 01:05:24 +00:00
|
|
|
new_str = zend_string_init(ZSTR_VAL(haystack), ZSTR_LEN(haystack), 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(new_str) + (r - lc_haystack), str, str_len);
|
2015-01-13 20:23:50 +00:00
|
|
|
(*replace_count)++;
|
|
|
|
}
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_needle, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
if (!new_str) {
|
|
|
|
goto nothing_todo;
|
|
|
|
}
|
|
|
|
return new_str;
|
|
|
|
} else {
|
|
|
|
size_t count = 0;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *o = lc_haystack;
|
|
|
|
const char *n;
|
|
|
|
const char *endp = o + ZSTR_LEN(haystack);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
lc_needle = php_string_tolower(needle);
|
2015-06-30 01:05:24 +00:00
|
|
|
n = ZSTR_VAL(lc_needle);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
while ((o = (char*)php_memnstr(o, n, ZSTR_LEN(lc_needle), endp))) {
|
|
|
|
o += ZSTR_LEN(lc_needle);
|
2015-01-13 20:23:50 +00:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
if (count == 0) {
|
|
|
|
/* Needle doesn't occur, shortcircuit the actual replacement. */
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_needle, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
goto nothing_todo;
|
|
|
|
}
|
2017-01-16 20:11:50 +00:00
|
|
|
|
2016-01-27 06:10:43 +00:00
|
|
|
if (str_len > ZSTR_LEN(lc_needle)) {
|
|
|
|
new_str = zend_string_safe_alloc(count, str_len - ZSTR_LEN(lc_needle), ZSTR_LEN(haystack), 0);
|
|
|
|
} else {
|
|
|
|
new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0);
|
|
|
|
}
|
2015-01-13 20:23:50 +00:00
|
|
|
|
2018-04-26 14:53:58 +00:00
|
|
|
e = ZSTR_VAL(new_str);
|
2015-06-30 01:05:24 +00:00
|
|
|
end = lc_haystack + ZSTR_LEN(haystack);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (p = lc_haystack; (r = (char*)php_memnstr(p, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle), end)); p = r + ZSTR_LEN(lc_needle)) {
|
|
|
|
memcpy(e, ZSTR_VAL(haystack) + (p - lc_haystack), r - p);
|
2015-01-13 20:23:50 +00:00
|
|
|
e += r - p;
|
|
|
|
memcpy(e, str, str_len);
|
|
|
|
e += str_len;
|
|
|
|
(*replace_count)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) {
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(e, ZSTR_VAL(haystack) + (p - lc_haystack), end - p);
|
2015-01-13 20:23:50 +00:00
|
|
|
e += end - p;
|
|
|
|
}
|
|
|
|
*e = '\0';
|
|
|
|
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_needle, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
return new_str;
|
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) {
|
2015-01-13 20:23:50 +00:00
|
|
|
nothing_todo:
|
|
|
|
return zend_string_copy(haystack);
|
|
|
|
} else {
|
|
|
|
lc_needle = php_string_tolower(needle);
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (memcmp(lc_haystack, ZSTR_VAL(lc_needle), ZSTR_LEN(lc_needle))) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_needle, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
goto nothing_todo;
|
|
|
|
}
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_needle, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
new_str = zend_string_init(str, str_len, 0);
|
|
|
|
|
|
|
|
(*replace_count)++;
|
|
|
|
return new_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_str_to_str
|
|
|
|
*/
|
2018-03-16 19:36:41 +00:00
|
|
|
PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const char *needle, size_t needle_len, const char *str, size_t str_len)
|
2015-01-13 20:23:50 +00:00
|
|
|
{
|
|
|
|
zend_string *new_str;
|
|
|
|
|
|
|
|
if (needle_len < length) {
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *end;
|
|
|
|
const char *s, *p;
|
|
|
|
char *e, *r;
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
if (needle_len == str_len) {
|
|
|
|
new_str = zend_string_init(haystack, length, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
end = ZSTR_VAL(new_str) + length;
|
|
|
|
for (p = ZSTR_VAL(new_str); (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
|
2015-01-13 20:23:50 +00:00
|
|
|
memcpy(r, str, str_len);
|
|
|
|
}
|
|
|
|
return new_str;
|
|
|
|
} else {
|
|
|
|
if (str_len < needle_len) {
|
|
|
|
new_str = zend_string_alloc(length, 0);
|
|
|
|
} else {
|
|
|
|
size_t count = 0;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *o = haystack;
|
|
|
|
const char *n = needle;
|
|
|
|
const char *endp = o + length;
|
2015-01-13 20:23:50 +00:00
|
|
|
|
|
|
|
while ((o = (char*)php_memnstr(o, n, needle_len, endp))) {
|
|
|
|
o += needle_len;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
if (count == 0) {
|
|
|
|
/* Needle doesn't occur, shortcircuit the actual replacement. */
|
|
|
|
new_str = zend_string_init(haystack, length, 0);
|
|
|
|
return new_str;
|
|
|
|
} else {
|
2016-01-27 06:10:43 +00:00
|
|
|
if (str_len > needle_len) {
|
|
|
|
new_str = zend_string_safe_alloc(count, str_len - needle_len, length, 0);
|
|
|
|
} else {
|
|
|
|
new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0);
|
|
|
|
}
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-16 19:36:41 +00:00
|
|
|
s = e = ZSTR_VAL(new_str);
|
2015-01-13 20:23:50 +00:00
|
|
|
end = haystack + length;
|
|
|
|
for (p = haystack; (r = (char*)php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
|
|
|
|
memcpy(e, p, r - p);
|
|
|
|
e += r - p;
|
|
|
|
memcpy(e, str, str_len);
|
|
|
|
e += str_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p < end) {
|
|
|
|
memcpy(e, p, end - p);
|
|
|
|
e += end - p;
|
|
|
|
}
|
|
|
|
|
|
|
|
*e = '\0';
|
2015-03-19 23:02:42 +00:00
|
|
|
new_str = zend_string_truncate(new_str, e - s, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
return new_str;
|
|
|
|
}
|
|
|
|
} else if (needle_len > length || memcmp(haystack, needle, length)) {
|
|
|
|
new_str = zend_string_init(haystack, length, 0);
|
|
|
|
return new_str;
|
|
|
|
} else {
|
|
|
|
new_str = zend_string_init(str, str_len, 0);
|
|
|
|
|
|
|
|
return new_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false strtr(string str, string from[, string to])
|
2001-09-04 10:44:28 +00:00
|
|
|
Translates characters in str using given translation tables */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strtr)
|
2012-01-02 00:47:57 +00:00
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *from;
|
2015-01-12 13:51:59 +00:00
|
|
|
zend_string *str;
|
|
|
|
char *to = NULL;
|
|
|
|
size_t to_len = 0;
|
2000-06-05 19:47:54 +00:00
|
|
|
int ac = ZEND_NUM_ARGS();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
2015-01-12 13:51:59 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-11 12:32:20 +00:00
|
|
|
Z_PARAM_ZVAL(from)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STRING(to, to_len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "The second argument is not an array");
|
1999-11-20 15:53:18 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2000-12-13 10:22:36 +00:00
|
|
|
/* shortcut for empty string */
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(str) == 0) {
|
2000-12-13 10:22:36 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
|
|
|
|
1999-11-20 15:53:18 +00:00
|
|
|
if (ac == 2) {
|
2015-09-24 19:39:59 +00:00
|
|
|
HashTable *pats = Z_ARRVAL_P(from);
|
2015-01-12 13:51:59 +00:00
|
|
|
|
|
|
|
if (zend_hash_num_elements(pats) < 1) {
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(str);
|
2015-01-12 13:51:59 +00:00
|
|
|
} else if (zend_hash_num_elements(pats) == 1) {
|
|
|
|
zend_long num_key;
|
2018-01-10 10:22:59 +00:00
|
|
|
zend_string *str_key, *tmp_str, *replace, *tmp_replace;
|
|
|
|
zval *entry;
|
2015-01-12 13:51:59 +00:00
|
|
|
|
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) {
|
2018-01-10 10:22:59 +00:00
|
|
|
tmp_str = NULL;
|
2015-01-12 13:51:59 +00:00
|
|
|
if (UNEXPECTED(!str_key)) {
|
2018-01-10 10:22:59 +00:00
|
|
|
str_key = tmp_str = zend_long_to_str(num_key);
|
2017-01-16 20:11:50 +00:00
|
|
|
}
|
2017-11-16 14:09:32 +00:00
|
|
|
replace = zval_get_tmp_string(entry, &tmp_replace);
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(str_key) < 1) {
|
2015-03-12 13:53:51 +00:00
|
|
|
RETVAL_STR_COPY(str);
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (ZSTR_LEN(str_key) == 1) {
|
2015-01-13 20:23:50 +00:00
|
|
|
RETVAL_STR(php_char_to_str_ex(str,
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(str_key)[0],
|
|
|
|
ZSTR_VAL(replace),
|
|
|
|
ZSTR_LEN(replace),
|
2015-01-12 19:30:55 +00:00
|
|
|
1,
|
2015-01-13 20:23:50 +00:00
|
|
|
NULL));
|
2015-01-12 13:51:59 +00:00
|
|
|
} else {
|
2015-01-13 20:23:50 +00:00
|
|
|
zend_long dummy;
|
|
|
|
RETVAL_STR(php_str_to_str_ex(str,
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(str_key), ZSTR_LEN(str_key),
|
|
|
|
ZSTR_VAL(replace), ZSTR_LEN(replace), &dummy));
|
2015-01-12 13:51:59 +00:00
|
|
|
}
|
2018-01-10 10:22:59 +00:00
|
|
|
zend_tmp_string_release(tmp_str);
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_replace);
|
2015-01-12 13:51:59 +00:00
|
|
|
return;
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
} else {
|
2015-01-14 17:58:41 +00:00
|
|
|
php_strtr_array(return_value, str, pats);
|
2015-01-12 13:51:59 +00:00
|
|
|
}
|
1999-11-20 15:53:18 +00:00
|
|
|
} else {
|
2019-02-26 14:32:18 +00:00
|
|
|
if (!try_convert_to_string(from)) {
|
|
|
|
return;
|
|
|
|
}
|
1999-11-20 15:53:18 +00:00
|
|
|
|
2015-01-14 17:58:41 +00:00
|
|
|
RETURN_STR(php_strtr_ex(str,
|
2014-02-10 13:49:21 +00:00
|
|
|
Z_STRVAL_P(from),
|
2008-06-25 12:16:17 +00:00
|
|
|
to,
|
2015-01-14 17:58:41 +00:00
|
|
|
MIN(Z_STRLEN_P(from), to_len)));
|
1999-11-20 15:53:18 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string strrev(string str)
|
|
|
|
Reverse a string */
|
2018-02-17 15:19:31 +00:00
|
|
|
#if ZEND_INTRIN_SSSE3_NATIVE
|
|
|
|
#include <tmmintrin.h>
|
2019-05-03 15:17:41 +00:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
#include <arm_neon.h>
|
2018-02-17 15:19:31 +00:00
|
|
|
#endif
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(strrev)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *s, *e;
|
|
|
|
char *p;
|
2014-02-24 10:15:40 +00:00
|
|
|
zend_string *n;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
n = zend_string_alloc(ZSTR_LEN(str), 0);
|
|
|
|
p = ZSTR_VAL(n);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2018-02-17 15:19:31 +00:00
|
|
|
s = ZSTR_VAL(str);
|
|
|
|
e = s + ZSTR_LEN(str);
|
|
|
|
--e;
|
|
|
|
#if ZEND_INTRIN_SSSE3_NATIVE
|
2018-02-18 11:47:41 +00:00
|
|
|
if (e - s > 15) {
|
2018-02-17 15:19:31 +00:00
|
|
|
const __m128i map = _mm_set_epi8(
|
|
|
|
0, 1, 2, 3,
|
|
|
|
4, 5, 6, 7,
|
|
|
|
8, 9, 10, 11,
|
|
|
|
12, 13, 14, 15);
|
2018-02-18 11:47:41 +00:00
|
|
|
do {
|
2018-02-18 11:34:48 +00:00
|
|
|
const __m128i str = _mm_loadu_si128((__m128i *)(e - 15));
|
|
|
|
_mm_storeu_si128((__m128i *)p, _mm_shuffle_epi8(str, map));
|
|
|
|
p += 16;
|
|
|
|
e -= 16;
|
2018-02-18 11:47:41 +00:00
|
|
|
} while (e - s > 15);
|
|
|
|
}
|
2019-05-03 15:17:41 +00:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
if (e - s > 15) {
|
|
|
|
do {
|
|
|
|
const uint8x16_t str = vld1q_u8((uint8_t *)(e - 15));
|
|
|
|
/* Synthesize rev128 with a rev64 + ext. */
|
|
|
|
const uint8x16_t rev = vrev64q_u8(str);
|
|
|
|
const uint8x16_t ext = (uint8x16_t)
|
|
|
|
vextq_u64((uint64x2_t)rev, (uint64x2_t)rev, 1);
|
|
|
|
vst1q_u8((uint8_t *)p, ext);
|
|
|
|
p += 16;
|
|
|
|
e -= 16;
|
|
|
|
} while (e - s > 15);
|
|
|
|
}
|
2018-02-17 15:19:31 +00:00
|
|
|
#endif
|
|
|
|
while (e >= s) {
|
|
|
|
*p++ = *e--;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-09 13:37:02 +00:00
|
|
|
*p = '\0';
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETVAL_NEW_STR(n);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_similar_str
|
|
|
|
*/
|
2018-01-13 09:12:57 +00:00
|
|
|
static void php_similar_str(const char *txt1, size_t len1, const char *txt2, size_t len2, size_t *pos1, size_t *pos2, size_t *max, size_t *count)
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
{
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *p, *q;
|
|
|
|
const char *end1 = (char *) txt1 + len1;
|
|
|
|
const char *end2 = (char *) txt2 + len2;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t l;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
*max = 0;
|
2018-01-13 09:12:57 +00:00
|
|
|
*count = 0;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
for (p = (char *) txt1; p < end1; p++) {
|
|
|
|
for (q = (char *) txt2; q < end2; q++) {
|
2002-10-10 18:41:24 +00:00
|
|
|
for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
if (l > *max) {
|
|
|
|
*max = l;
|
2018-01-13 09:12:57 +00:00
|
|
|
*count += 1;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
*pos1 = p - txt1;
|
|
|
|
*pos2 = q - txt2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_similar_char
|
|
|
|
*/
|
2014-08-25 18:22:49 +00:00
|
|
|
static size_t php_similar_char(const char *txt1, size_t len1, const char *txt2, size_t len2)
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
{
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t sum;
|
2018-01-13 09:12:57 +00:00
|
|
|
size_t pos1 = 0, pos2 = 0, max, count;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-01-13 09:12:57 +00:00
|
|
|
php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max, &count);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
if ((sum = max)) {
|
2018-01-13 09:12:57 +00:00
|
|
|
if (pos1 && pos2 && count > 1) {
|
2012-01-02 00:47:57 +00:00
|
|
|
sum += php_similar_char(txt1, pos1,
|
2003-02-08 15:26:17 +00:00
|
|
|
txt2, pos2);
|
|
|
|
}
|
|
|
|
if ((pos1 + max < len1) && (pos2 + max < len2)) {
|
2012-01-02 00:47:57 +00:00
|
|
|
sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
|
1999-10-16 16:35:20 +00:00
|
|
|
txt2 + pos2 + max, len2 - pos2 - max);
|
2003-02-08 15:26:17 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
return sum;
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2001-09-21 21:59:27 +00:00
|
|
|
/* {{{ proto int similar_text(string str1, string str2 [, float percent])
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
Calculates the similarity between two strings */
|
|
|
|
PHP_FUNCTION(similar_text)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *t1, *t2;
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *percent = NULL;
|
2000-06-05 19:47:54 +00:00
|
|
|
int ac = ZEND_NUM_ARGS();
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t sim;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 3)
|
|
|
|
Z_PARAM_STR(t1)
|
|
|
|
Z_PARAM_STR(t2)
|
|
|
|
Z_PARAM_OPTIONAL
|
2019-01-07 11:28:51 +00:00
|
|
|
Z_PARAM_ZVAL(percent)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(t1) + ZSTR_LEN(t2) == 0) {
|
2002-09-11 14:40:52 +00:00
|
|
|
if (ac > 2) {
|
2019-04-24 13:14:48 +00:00
|
|
|
ZEND_TRY_ASSIGN_REF_DOUBLE(percent, 0);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(0);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
sim = php_similar_char(ZSTR_VAL(t1), ZSTR_LEN(t1), ZSTR_VAL(t2), ZSTR_LEN(t2));
|
2002-09-11 14:40:52 +00:00
|
|
|
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
if (ac > 2) {
|
2019-04-24 13:14:48 +00:00
|
|
|
ZEND_TRY_ASSIGN_REF_DOUBLE(percent, sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2)));
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2001-09-04 06:18:11 +00:00
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(sim);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
1999-09-05 20:55:13 +00:00
|
|
|
/* {{{ proto string addcslashes(string str, string charlist)
|
2001-09-04 10:44:28 +00:00
|
|
|
Escapes all chars mentioned in charlist with backslash. It creates octal representations if asked to backslash characters with 8th bit set or with ASCII<32 (except '\n', '\r', '\t' etc...) */
|
1999-09-05 20:55:13 +00:00
|
|
|
PHP_FUNCTION(addcslashes)
|
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str, *what;
|
1999-09-05 20:55:13 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_STR(what)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-09-17 09:15:48 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(str) == 0) {
|
2000-09-17 09:15:48 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(what) == 0) {
|
2018-02-26 08:54:53 +00:00
|
|
|
RETURN_STR_COPY(str);
|
2000-09-17 09:15:48 +00:00
|
|
|
}
|
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
RETURN_STR(php_addcslashes_str(ZSTR_VAL(str), ZSTR_LEN(str), ZSTR_VAL(what), ZSTR_LEN(what)));
|
1999-09-05 20:55:13 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
/* {{{ proto string addslashes(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Escapes single quote, double quotes and backslash characters in a string with backslashes */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(addslashes)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
2014-08-16 10:55:13 +00:00
|
|
|
Z_PARAM_STR(str)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-09-17 09:15:48 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(str) == 0) {
|
2000-09-17 09:15:48 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
}
|
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
RETURN_STR(php_addslashes(str));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-09-05 20:55:13 +00:00
|
|
|
/* {{{ proto string stripcslashes(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Strips backslashes from a string. Uses C-style conventions */
|
1999-09-05 20:55:13 +00:00
|
|
|
PHP_FUNCTION(stripcslashes)
|
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-09-05 20:55:13 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
|
2015-01-20 02:59:28 +00:00
|
|
|
php_stripcslashes(Z_STR_P(return_value));
|
1999-09-05 20:55:13 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
/* {{{ proto string stripslashes(string str)
|
2001-09-04 10:44:28 +00:00
|
|
|
Strips backslashes from a string */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(stripslashes)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_STRINGL(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
|
2015-01-20 02:59:28 +00:00
|
|
|
php_stripslashes(Z_STR_P(return_value));
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_stripcslashes
|
|
|
|
*/
|
2015-01-20 02:59:28 +00:00
|
|
|
PHPAPI void php_stripcslashes(zend_string *str)
|
1999-09-05 20:55:13 +00:00
|
|
|
{
|
2018-03-16 19:36:41 +00:00
|
|
|
const char *source, *end;
|
|
|
|
char *target;
|
2015-06-30 01:05:24 +00:00
|
|
|
size_t nlen = ZSTR_LEN(str), i;
|
1999-09-05 20:55:13 +00:00
|
|
|
char numtmp[4];
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (source = (char*)ZSTR_VAL(str), end = source + ZSTR_LEN(str), target = ZSTR_VAL(str); source < end; source++) {
|
2015-01-20 02:59:28 +00:00
|
|
|
if (*source == '\\' && source + 1 < end) {
|
1999-09-05 20:55:13 +00:00
|
|
|
source++;
|
|
|
|
switch (*source) {
|
2003-02-08 15:26:17 +00:00
|
|
|
case 'n': *target++='\n'; nlen--; break;
|
|
|
|
case 'r': *target++='\r'; nlen--; break;
|
|
|
|
case 'a': *target++='\a'; nlen--; break;
|
|
|
|
case 't': *target++='\t'; nlen--; break;
|
|
|
|
case 'v': *target++='\v'; nlen--; break;
|
|
|
|
case 'b': *target++='\b'; nlen--; break;
|
|
|
|
case 'f': *target++='\f'; nlen--; break;
|
1999-09-05 20:55:13 +00:00
|
|
|
case '\\': *target++='\\'; nlen--; break;
|
2003-02-08 15:26:17 +00:00
|
|
|
case 'x':
|
|
|
|
if (source+1 < end && isxdigit((int)(*(source+1)))) {
|
1999-09-05 20:55:13 +00:00
|
|
|
numtmp[0] = *++source;
|
2002-10-02 17:56:04 +00:00
|
|
|
if (source+1 < end && isxdigit((int)(*(source+1)))) {
|
1999-09-05 20:55:13 +00:00
|
|
|
numtmp[1] = *++source;
|
|
|
|
numtmp[2] = '\0';
|
|
|
|
nlen-=3;
|
|
|
|
} else {
|
|
|
|
numtmp[1] = '\0';
|
|
|
|
nlen-=2;
|
|
|
|
}
|
1999-09-07 20:29:31 +00:00
|
|
|
*target++=(char)strtol(numtmp, NULL, 16);
|
1999-09-05 20:55:13 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* break is left intentionally */
|
2012-01-02 00:47:57 +00:00
|
|
|
default:
|
|
|
|
i=0;
|
2002-10-02 17:56:04 +00:00
|
|
|
while (source < end && *source >= '0' && *source <= '7' && i<3) {
|
1999-09-05 20:55:13 +00:00
|
|
|
numtmp[i++] = *source++;
|
|
|
|
}
|
|
|
|
if (i) {
|
|
|
|
numtmp[i]='\0';
|
1999-09-07 20:29:31 +00:00
|
|
|
*target++=(char)strtol(numtmp, NULL, 8);
|
1999-09-05 20:55:13 +00:00
|
|
|
nlen-=i;
|
|
|
|
source--;
|
|
|
|
} else {
|
|
|
|
*target++=*source;
|
2000-06-09 13:58:10 +00:00
|
|
|
nlen--;
|
1999-09-05 20:55:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*target++=*source;
|
|
|
|
}
|
|
|
|
}
|
2000-07-17 10:22:30 +00:00
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
if (nlen != 0) {
|
2000-07-17 10:22:30 +00:00
|
|
|
*target='\0';
|
|
|
|
}
|
1999-09-05 20:55:13 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_LEN(str) = nlen;
|
1999-09-05 20:55:13 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
/* {{{ php_addcslashes_str
|
2001-06-05 13:12:10 +00:00
|
|
|
*/
|
2018-06-28 21:19:16 +00:00
|
|
|
PHPAPI zend_string *php_addcslashes_str(const char *str, size_t len, char *what, size_t wlength)
|
1999-09-05 00:55:48 +00:00
|
|
|
{
|
|
|
|
char flags[256];
|
2018-03-16 19:36:41 +00:00
|
|
|
char *target;
|
|
|
|
const char *source, *end;
|
1999-09-05 00:55:48 +00:00
|
|
|
char c;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t newlen;
|
2018-06-28 21:19:16 +00:00
|
|
|
zend_string *new_str = zend_string_safe_alloc(4, len, 0, 0);
|
1999-09-05 00:55:48 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
php_charmask((unsigned char *)what, wlength, flags);
|
1999-09-05 00:55:48 +00:00
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
for (source = str, end = source + len, target = ZSTR_VAL(new_str); source < end; source++) {
|
2012-01-02 00:47:57 +00:00
|
|
|
c = *source;
|
1999-09-05 20:55:13 +00:00
|
|
|
if (flags[(unsigned char)c]) {
|
2003-02-08 15:26:17 +00:00
|
|
|
if ((unsigned char) c < 32 || (unsigned char) c > 126) {
|
1999-09-05 00:55:48 +00:00
|
|
|
*target++ = '\\';
|
|
|
|
switch (c) {
|
|
|
|
case '\n': *target++ = 'n'; break;
|
|
|
|
case '\t': *target++ = 't'; break;
|
|
|
|
case '\r': *target++ = 'r'; break;
|
1999-09-05 20:55:13 +00:00
|
|
|
case '\a': *target++ = 'a'; break;
|
|
|
|
case '\v': *target++ = 'v'; break;
|
|
|
|
case '\b': *target++ = 'b'; break;
|
|
|
|
case '\f': *target++ = 'f'; break;
|
2003-02-08 15:26:17 +00:00
|
|
|
default: target += sprintf(target, "%03o", (unsigned char) c);
|
1999-09-05 00:55:48 +00:00
|
|
|
}
|
1999-09-05 20:55:13 +00:00
|
|
|
continue;
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
1999-09-05 20:55:13 +00:00
|
|
|
*target++ = '\\';
|
|
|
|
}
|
|
|
|
*target++ = c;
|
1999-09-05 00:55:48 +00:00
|
|
|
}
|
|
|
|
*target = 0;
|
2015-06-30 01:05:24 +00:00
|
|
|
newlen = target - ZSTR_VAL(new_str);
|
2018-06-28 21:19:16 +00:00
|
|
|
if (newlen < len * 4) {
|
2015-03-19 23:02:42 +00:00
|
|
|
new_str = zend_string_truncate(new_str, newlen, 0);
|
1999-09-05 00:55:48 +00:00
|
|
|
}
|
|
|
|
return new_str;
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
/* {{{ php_addcslashes
|
|
|
|
*/
|
|
|
|
PHPAPI zend_string *php_addcslashes(zend_string *str, char *what, size_t wlength)
|
|
|
|
{
|
|
|
|
return php_addcslashes_str(ZSTR_VAL(str), ZSTR_LEN(str), what, wlength);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2018-01-15 13:01:27 +00:00
|
|
|
/* {{{ php_addslashes */
|
|
|
|
|
2018-01-24 08:33:32 +00:00
|
|
|
#if ZEND_INTRIN_SSE4_2_NATIVE
|
2018-01-17 09:31:10 +00:00
|
|
|
# include <nmmintrin.h>
|
|
|
|
# include "Zend/zend_bitset.h"
|
2018-01-24 08:33:32 +00:00
|
|
|
#elif ZEND_INTRIN_SSE4_2_RESOLVER
|
2018-01-17 09:31:10 +00:00
|
|
|
# include <nmmintrin.h>
|
|
|
|
# include "Zend/zend_bitset.h"
|
|
|
|
# include "Zend/zend_cpuinfo.h"
|
2018-01-15 13:01:27 +00:00
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
ZEND_INTRIN_SSE4_2_FUNC_DECL(zend_string *php_addslashes_sse42(zend_string *str));
|
|
|
|
zend_string *php_addslashes_default(zend_string *str);
|
2018-02-03 16:15:18 +00:00
|
|
|
|
2018-02-21 02:09:11 +00:00
|
|
|
ZEND_INTRIN_SSE4_2_FUNC_DECL(void php_stripslashes_sse42(zend_string *str));
|
|
|
|
void php_stripslashes_default(zend_string *str);
|
|
|
|
|
2018-01-24 08:33:32 +00:00
|
|
|
# if ZEND_INTRIN_SSE4_2_FUNC_PROTO
|
2018-06-28 21:19:16 +00:00
|
|
|
PHPAPI zend_string *php_addslashes(zend_string *str) __attribute__((ifunc("resolve_addslashes")));
|
2018-02-21 02:09:11 +00:00
|
|
|
PHPAPI void php_stripslashes(zend_string *str) __attribute__((ifunc("resolve_stripslashes")));
|
2018-01-15 13:01:27 +00:00
|
|
|
|
2019-01-18 14:01:51 +00:00
|
|
|
ZEND_NO_SANITIZE_ADDRESS
|
2019-06-28 14:55:54 +00:00
|
|
|
ZEND_ATTRIBUTE_UNUSED /* clang mistakenly warns about this */
|
2018-01-15 13:01:27 +00:00
|
|
|
static void *resolve_addslashes() {
|
2018-02-12 12:46:17 +00:00
|
|
|
if (zend_cpu_supports_sse42()) {
|
2018-01-17 09:31:10 +00:00
|
|
|
return php_addslashes_sse42;
|
2018-01-15 13:01:27 +00:00
|
|
|
}
|
2019-02-14 09:21:27 +00:00
|
|
|
return php_addslashes_default;
|
2018-01-15 13:01:27 +00:00
|
|
|
}
|
2018-02-21 02:09:11 +00:00
|
|
|
|
2019-01-18 14:01:51 +00:00
|
|
|
ZEND_NO_SANITIZE_ADDRESS
|
2019-06-28 14:55:54 +00:00
|
|
|
ZEND_ATTRIBUTE_UNUSED /* clang mistakenly warns about this */
|
2018-02-21 02:09:11 +00:00
|
|
|
static void *resolve_stripslashes() {
|
|
|
|
if (zend_cpu_supports_sse42()) {
|
|
|
|
return php_stripslashes_sse42;
|
|
|
|
}
|
2019-02-14 09:21:27 +00:00
|
|
|
return php_stripslashes_default;
|
2018-02-21 02:09:11 +00:00
|
|
|
}
|
2018-01-24 08:33:32 +00:00
|
|
|
# else /* ZEND_INTRIN_SSE4_2_FUNC_PTR */
|
|
|
|
|
2019-02-14 09:21:27 +00:00
|
|
|
static zend_string *(*php_addslashes_ptr)(zend_string *str) = NULL;
|
|
|
|
static void (*php_stripslashes_ptr)(zend_string *str) = NULL;
|
|
|
|
|
|
|
|
PHPAPI zend_string *php_addslashes(zend_string *str) {
|
|
|
|
return php_addslashes_ptr(str);
|
|
|
|
}
|
|
|
|
PHPAPI void php_stripslashes(zend_string *str) {
|
|
|
|
php_stripslashes_ptr(str);
|
|
|
|
}
|
2018-01-24 08:33:32 +00:00
|
|
|
|
|
|
|
/* {{{ PHP_MINIT_FUNCTION
|
|
|
|
*/
|
|
|
|
PHP_MINIT_FUNCTION(string_intrin)
|
|
|
|
{
|
|
|
|
if (zend_cpu_supports(ZEND_CPU_FEATURE_SSE42)) {
|
2019-02-14 09:21:27 +00:00
|
|
|
php_addslashes_ptr = php_addslashes_sse42;
|
|
|
|
php_stripslashes_ptr = php_stripslashes_sse42;
|
2018-01-24 08:33:32 +00:00
|
|
|
} else {
|
2019-02-14 09:21:27 +00:00
|
|
|
php_addslashes_ptr = php_addslashes_default;
|
|
|
|
php_stripslashes_ptr = php_stripslashes_default;
|
2018-01-24 08:33:32 +00:00
|
|
|
}
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
# endif
|
2018-01-17 09:31:10 +00:00
|
|
|
#endif
|
2018-01-15 13:01:27 +00:00
|
|
|
|
2018-01-24 08:33:32 +00:00
|
|
|
#if ZEND_INTRIN_SSE4_2_NATIVE || ZEND_INTRIN_SSE4_2_RESOLVER
|
|
|
|
# if ZEND_INTRIN_SSE4_2_NATIVE
|
2018-06-28 21:19:16 +00:00
|
|
|
PHPAPI zend_string *php_addslashes(zend_string *str) /* {{{ */
|
2018-01-24 08:33:32 +00:00
|
|
|
# elif ZEND_INTRIN_SSE4_2_RESOLVER
|
2018-06-28 21:19:16 +00:00
|
|
|
zend_string *php_addslashes_sse42(zend_string *str)
|
2018-01-17 09:31:10 +00:00
|
|
|
# endif
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-01-24 09:14:28 +00:00
|
|
|
ZEND_SET_ALIGNED(16, static const char slashchars[16]) = "\'\"\\\0";
|
2018-01-15 13:01:27 +00:00
|
|
|
__m128i w128, s128;
|
|
|
|
uint32_t res = 0;
|
1999-04-17 00:37:12 +00:00
|
|
|
/* maximum string length, worst case situation */
|
2018-03-16 19:36:41 +00:00
|
|
|
char *target;
|
|
|
|
const char *source, *end;
|
2015-01-19 15:46:39 +00:00
|
|
|
size_t offset;
|
2014-02-24 04:07:09 +00:00
|
|
|
zend_string *new_str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2000-02-02 21:53:27 +00:00
|
|
|
if (!str) {
|
2015-06-29 13:44:54 +00:00
|
|
|
return ZSTR_EMPTY_ALLOC();
|
2000-02-02 21:53:27 +00:00
|
|
|
}
|
2014-02-24 04:07:09 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
source = ZSTR_VAL(str);
|
|
|
|
end = source + ZSTR_LEN(str);
|
2015-01-19 15:46:39 +00:00
|
|
|
|
2018-01-15 13:01:27 +00:00
|
|
|
if (ZSTR_LEN(str) > 15) {
|
2018-03-16 08:01:32 +00:00
|
|
|
w128 = _mm_load_si128((__m128i *)slashchars);
|
2018-02-20 12:56:23 +00:00
|
|
|
do {
|
|
|
|
s128 = _mm_loadu_si128((__m128i *)source);
|
2018-01-15 13:01:27 +00:00
|
|
|
res = _mm_cvtsi128_si32(_mm_cmpestrm(w128, 4, s128, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK));
|
|
|
|
if (res) {
|
|
|
|
goto do_escape;
|
|
|
|
}
|
2018-02-20 12:56:23 +00:00
|
|
|
source += 16;
|
|
|
|
} while ((end - source) > 15);
|
2018-01-15 13:01:27 +00:00
|
|
|
}
|
|
|
|
|
2015-01-19 15:46:39 +00:00
|
|
|
while (source < end) {
|
|
|
|
switch (*source) {
|
|
|
|
case '\0':
|
|
|
|
case '\'':
|
|
|
|
case '\"':
|
|
|
|
case '\\':
|
|
|
|
goto do_escape;
|
|
|
|
default:
|
|
|
|
source++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
return zend_string_copy(str);
|
2015-01-19 15:46:39 +00:00
|
|
|
|
|
|
|
do_escape:
|
2015-06-30 01:05:24 +00:00
|
|
|
offset = source - (char *)ZSTR_VAL(str);
|
2016-01-27 06:10:43 +00:00
|
|
|
new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
|
|
|
|
target = ZSTR_VAL(new_str) + offset;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2018-01-15 13:01:27 +00:00
|
|
|
if (res) {
|
|
|
|
int pos = 0;
|
|
|
|
do {
|
|
|
|
int i, n = zend_ulong_ntz(res);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
*target++ = source[pos + i];
|
|
|
|
}
|
|
|
|
pos += n;
|
|
|
|
*target++ = '\\';
|
|
|
|
if (source[pos] == '\0') {
|
|
|
|
*target++ = '0';
|
|
|
|
} else {
|
|
|
|
*target++ = source[pos];
|
|
|
|
}
|
|
|
|
pos++;
|
|
|
|
res = res >> (n + 1);
|
|
|
|
} while (res);
|
|
|
|
|
|
|
|
for (; pos < 16; pos++) {
|
|
|
|
*target++ = source[pos];
|
|
|
|
}
|
|
|
|
source += 16;
|
|
|
|
} else if (end - source > 15) {
|
2018-03-16 08:01:32 +00:00
|
|
|
w128 = _mm_load_si128((__m128i *)slashchars);
|
2018-01-15 13:01:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (; end - source > 15; source += 16) {
|
|
|
|
int pos = 0;
|
2018-02-20 12:56:23 +00:00
|
|
|
s128 = _mm_loadu_si128((__m128i *)source);
|
2018-01-15 13:01:27 +00:00
|
|
|
res = _mm_cvtsi128_si32(_mm_cmpestrm(w128, 4, s128, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK));
|
|
|
|
if (res) {
|
|
|
|
do {
|
|
|
|
int i, n = zend_ulong_ntz(res);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
*target++ = source[pos + i];
|
|
|
|
}
|
|
|
|
pos += n;
|
|
|
|
*target++ = '\\';
|
|
|
|
if (source[pos] == '\0') {
|
|
|
|
*target++ = '0';
|
|
|
|
} else {
|
|
|
|
*target++ = source[pos];
|
|
|
|
}
|
|
|
|
pos++;
|
|
|
|
res = res >> (n + 1);
|
|
|
|
} while (res);
|
|
|
|
for (; pos < 16; pos++) {
|
|
|
|
*target++ = source[pos];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_mm_storeu_si128((__m128i*)target, s128);
|
|
|
|
target += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-22 11:25:30 +00:00
|
|
|
while (source < end) {
|
|
|
|
switch (*source) {
|
|
|
|
case '\0':
|
|
|
|
*target++ = '\\';
|
|
|
|
*target++ = '0';
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
case '\"':
|
|
|
|
case '\\':
|
|
|
|
*target++ = '\\';
|
|
|
|
/* break is missing *intentionally* */
|
|
|
|
default:
|
|
|
|
*target++ = *source;
|
2012-01-02 00:47:57 +00:00
|
|
|
break;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2018-01-15 13:01:27 +00:00
|
|
|
source++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*target = '\0';
|
|
|
|
|
|
|
|
if (ZSTR_LEN(new_str) - (target - ZSTR_VAL(new_str)) > 16) {
|
|
|
|
new_str = zend_string_truncate(new_str, target - ZSTR_VAL(new_str), 0);
|
|
|
|
} else {
|
|
|
|
ZSTR_LEN(new_str) = target - ZSTR_VAL(new_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_str;
|
|
|
|
}
|
|
|
|
/* }}} */
|
2018-01-17 09:31:10 +00:00
|
|
|
#endif
|
2011-07-22 11:25:30 +00:00
|
|
|
|
2019-07-10 18:31:27 +00:00
|
|
|
#ifdef __aarch64__
|
|
|
|
typedef union {
|
|
|
|
uint8_t mem[16];
|
|
|
|
uint64_t dw[2];
|
|
|
|
} quad_word;
|
|
|
|
|
|
|
|
static zend_always_inline quad_word aarch64_contains_slash_chars(uint8x16_t x) {
|
|
|
|
uint8x16_t s0 = vceqq_u8(x, vdupq_n_u8('\0'));
|
|
|
|
uint8x16_t s1 = vceqq_u8(x, vdupq_n_u8('\''));
|
|
|
|
uint8x16_t s2 = vceqq_u8(x, vdupq_n_u8('\"'));
|
|
|
|
uint8x16_t s3 = vceqq_u8(x, vdupq_n_u8('\\'));
|
|
|
|
uint8x16_t s01 = vorrq_u8(s0, s1);
|
|
|
|
uint8x16_t s23 = vorrq_u8(s2, s3);
|
|
|
|
uint8x16_t s0123 = vorrq_u8(s01, s23);
|
|
|
|
quad_word qw;
|
|
|
|
vst1q_u8(qw.mem, s0123);
|
|
|
|
return qw;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_always_inline char *aarch64_add_slashes(quad_word res, const char *source, char *target)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
for (; i < 16; i++) {
|
|
|
|
char s = source[i];
|
|
|
|
if (res.mem[i] == 0)
|
|
|
|
*target++ = s;
|
|
|
|
else {
|
|
|
|
*target++ = '\\';
|
|
|
|
if (s == '\0')
|
|
|
|
*target++ = '0';
|
|
|
|
else
|
|
|
|
*target++ = s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
#endif /* __aarch64__ */
|
|
|
|
|
2018-01-24 08:33:32 +00:00
|
|
|
#if !ZEND_INTRIN_SSE4_2_NATIVE
|
|
|
|
# if ZEND_INTRIN_SSE4_2_RESOLVER
|
2018-06-28 21:19:16 +00:00
|
|
|
zend_string *php_addslashes_default(zend_string *str) /* {{{ */
|
2018-01-17 09:31:10 +00:00
|
|
|
# else
|
2018-06-28 21:19:16 +00:00
|
|
|
PHPAPI zend_string *php_addslashes(zend_string *str)
|
2018-01-17 09:31:10 +00:00
|
|
|
# endif
|
2018-01-15 13:01:27 +00:00
|
|
|
{
|
|
|
|
/* maximum string length, worst case situation */
|
2018-03-16 19:36:41 +00:00
|
|
|
char *target;
|
|
|
|
const char *source, *end;
|
2018-01-15 13:01:27 +00:00
|
|
|
size_t offset;
|
|
|
|
zend_string *new_str;
|
|
|
|
|
|
|
|
if (!str) {
|
|
|
|
return ZSTR_EMPTY_ALLOC();
|
|
|
|
}
|
|
|
|
|
|
|
|
source = ZSTR_VAL(str);
|
|
|
|
end = source + ZSTR_LEN(str);
|
|
|
|
|
2019-07-10 18:31:27 +00:00
|
|
|
# ifdef __aarch64__
|
|
|
|
quad_word res = {0};
|
|
|
|
if (ZSTR_LEN(str) > 15) {
|
|
|
|
do {
|
|
|
|
res = aarch64_contains_slash_chars(vld1q_u8((uint8_t *)source));
|
|
|
|
if (res.dw[0] | res.dw[1])
|
|
|
|
goto do_escape;
|
|
|
|
source += 16;
|
|
|
|
} while ((end - source) > 15);
|
|
|
|
}
|
|
|
|
/* Finish the last 15 bytes or less with the scalar loop. */
|
|
|
|
# endif /* __aarch64__ */
|
|
|
|
|
2018-01-15 13:01:27 +00:00
|
|
|
while (source < end) {
|
|
|
|
switch (*source) {
|
|
|
|
case '\0':
|
|
|
|
case '\'':
|
|
|
|
case '\"':
|
|
|
|
case '\\':
|
|
|
|
goto do_escape;
|
|
|
|
default:
|
|
|
|
source++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 21:19:16 +00:00
|
|
|
return zend_string_copy(str);
|
2018-01-15 13:01:27 +00:00
|
|
|
|
|
|
|
do_escape:
|
|
|
|
offset = source - (char *)ZSTR_VAL(str);
|
|
|
|
new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0);
|
|
|
|
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
|
|
|
|
target = ZSTR_VAL(new_str) + offset;
|
|
|
|
|
2019-07-10 18:31:27 +00:00
|
|
|
# ifdef __aarch64__
|
|
|
|
if (res.dw[0] | res.dw[1]) {
|
|
|
|
target = aarch64_add_slashes(res, source, target);
|
|
|
|
source += 16;
|
|
|
|
}
|
|
|
|
for (; end - source > 15; source += 16) {
|
|
|
|
uint8x16_t x = vld1q_u8((uint8_t *)source);
|
|
|
|
res = aarch64_contains_slash_chars(x);
|
|
|
|
if (res.dw[0] | res.dw[1]) {
|
|
|
|
target = aarch64_add_slashes(res, source, target);
|
|
|
|
} else {
|
|
|
|
vst1q_u8((uint8_t*)target, x);
|
|
|
|
target += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Finish the last 15 bytes or less with the scalar loop. */
|
|
|
|
# endif /* __aarch64__ */
|
|
|
|
|
2018-01-15 13:01:27 +00:00
|
|
|
while (source < end) {
|
|
|
|
switch (*source) {
|
|
|
|
case '\0':
|
|
|
|
*target++ = '\\';
|
|
|
|
*target++ = '0';
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
case '\"':
|
|
|
|
case '\\':
|
|
|
|
*target++ = '\\';
|
|
|
|
/* break is missing *intentionally* */
|
|
|
|
default:
|
|
|
|
*target++ = *source;
|
|
|
|
break;
|
|
|
|
}
|
2011-07-22 11:25:30 +00:00
|
|
|
source++;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2018-01-15 13:01:27 +00:00
|
|
|
*target = '\0';
|
2015-01-19 15:46:39 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(new_str) - (target - ZSTR_VAL(new_str)) > 16) {
|
|
|
|
new_str = zend_string_truncate(new_str, target - ZSTR_VAL(new_str), 0);
|
2015-01-19 15:46:39 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_LEN(new_str) = target - ZSTR_VAL(new_str);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2014-02-24 04:07:09 +00:00
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
return new_str;
|
|
|
|
}
|
2018-01-17 09:31:10 +00:00
|
|
|
#endif
|
2018-01-15 13:01:27 +00:00
|
|
|
/* }}} */
|
2018-01-17 14:08:22 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2018-02-21 02:09:11 +00:00
|
|
|
/* {{{ php_stripslashes
|
|
|
|
*
|
|
|
|
* be careful, this edits the string in-place */
|
|
|
|
static zend_always_inline char *php_stripslashes_impl(const char *str, char *out, size_t len)
|
|
|
|
{
|
2019-07-10 18:31:27 +00:00
|
|
|
#ifdef __aarch64__
|
|
|
|
while (len > 15) {
|
|
|
|
uint8x16_t x = vld1q_u8((uint8_t *)str);
|
|
|
|
quad_word q;
|
|
|
|
vst1q_u8(q.mem, vceqq_u8(x, vdupq_n_u8('\\')));
|
|
|
|
if (q.dw[0] | q.dw[1]) {
|
|
|
|
int i = 0;
|
|
|
|
for (; i < 16; i++) {
|
|
|
|
if (q.mem[i] == 0) {
|
|
|
|
*out++ = str[i];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++; /* skip the slash */
|
|
|
|
char s = str[i];
|
|
|
|
if (s == '0')
|
|
|
|
*out++ = '\0';
|
|
|
|
else
|
|
|
|
*out++ = s; /* preserve the next character */
|
|
|
|
}
|
|
|
|
str += i;
|
|
|
|
len -= i;
|
|
|
|
} else {
|
|
|
|
vst1q_u8((uint8_t*)out, x);
|
|
|
|
out += 16;
|
|
|
|
str += 16;
|
|
|
|
len -= 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Finish the last 15 bytes or less with the scalar loop. */
|
|
|
|
#endif /* __aarch64__ */
|
2018-02-21 02:09:11 +00:00
|
|
|
while (len > 0) {
|
|
|
|
if (*str == '\\') {
|
|
|
|
str++; /* skip the slash */
|
|
|
|
len--;
|
|
|
|
if (len > 0) {
|
|
|
|
if (*str == '0') {
|
|
|
|
*out++='\0';
|
|
|
|
str++;
|
|
|
|
} else {
|
|
|
|
*out++ = *str++; /* preserve the next character */
|
|
|
|
}
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*out++ = *str++;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ZEND_INTRIN_SSE4_2_NATIVE || ZEND_INTRIN_SSE4_2_RESOLVER
|
|
|
|
# if ZEND_INTRIN_SSE4_2_NATIVE
|
|
|
|
PHPAPI void php_stripslashes(zend_string *str)
|
|
|
|
# elif ZEND_INTRIN_SSE4_2_RESOLVER
|
2018-02-21 10:53:38 +00:00
|
|
|
void php_stripslashes_sse42(zend_string *str)
|
2018-02-21 02:09:11 +00:00
|
|
|
# endif
|
|
|
|
{
|
|
|
|
const char *s = ZSTR_VAL(str);
|
|
|
|
char *t = ZSTR_VAL(str);
|
|
|
|
size_t l = ZSTR_LEN(str);
|
|
|
|
|
|
|
|
if (l > 15) {
|
|
|
|
const __m128i slash = _mm_set1_epi8('\\');
|
|
|
|
|
|
|
|
do {
|
|
|
|
__m128i in = _mm_loadu_si128((__m128i *)s);
|
|
|
|
__m128i any_slash = _mm_cmpeq_epi8(in, slash);
|
|
|
|
uint32_t res = _mm_movemask_epi8(any_slash);
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
int i, n = zend_ulong_ntz(res);
|
|
|
|
const char *e = s + 15;
|
|
|
|
l -= n;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
*t++ = *s++;
|
|
|
|
}
|
|
|
|
for (; s < e; s++) {
|
|
|
|
if (*s == '\\') {
|
|
|
|
s++;
|
|
|
|
l--;
|
|
|
|
if (*s == '0') {
|
|
|
|
*t = '\0';
|
|
|
|
} else {
|
|
|
|
*t = *s;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*t = *s;
|
|
|
|
}
|
|
|
|
t++;
|
|
|
|
l--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_mm_storeu_si128((__m128i *)t, in);
|
|
|
|
s += 16;
|
|
|
|
t += 16;
|
|
|
|
l -= 16;
|
|
|
|
}
|
|
|
|
} while (l > 15);
|
|
|
|
}
|
|
|
|
|
|
|
|
t = php_stripslashes_impl(s, t, l);
|
|
|
|
if (t != (ZSTR_VAL(str) + ZSTR_LEN(str))) {
|
|
|
|
ZSTR_LEN(str) = t - ZSTR_VAL(str);
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !ZEND_INTRIN_SSE4_2_NATIVE
|
|
|
|
# if ZEND_INTRIN_SSE4_2_RESOLVER
|
|
|
|
void php_stripslashes_default(zend_string *str) /* {{{ */
|
|
|
|
# else
|
|
|
|
PHPAPI void php_stripslashes(zend_string *str)
|
|
|
|
# endif
|
|
|
|
{
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *t = php_stripslashes_impl(ZSTR_VAL(str), ZSTR_VAL(str), ZSTR_LEN(str));
|
2018-02-21 02:09:11 +00:00
|
|
|
if (t != (ZSTR_VAL(str) + ZSTR_LEN(str))) {
|
|
|
|
ZSTR_LEN(str) = t - ZSTR_VAL(str);
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
#endif
|
|
|
|
/* }}} */
|
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
#define _HEB_BLOCK_TYPE_ENG 1
|
|
|
|
#define _HEB_BLOCK_TYPE_HEB 2
|
2003-02-08 15:26:17 +00:00
|
|
|
#define isheb(c) (((((unsigned char) c) >= 224) && (((unsigned char) c) <= 250)) ? 1 : 0)
|
|
|
|
#define _isblank(c) (((((unsigned char) c) == ' ' || ((unsigned char) c) == '\t')) ? 1 : 0)
|
|
|
|
#define _isnewline(c) (((((unsigned char) c) == '\n' || ((unsigned char) c) == '\r')) ? 1 : 0)
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_str_replace_in_subject
|
|
|
|
*/
|
2015-01-13 20:23:50 +00:00
|
|
|
static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *subject, zval *result, int case_sensitivity)
|
2001-01-22 21:39:55 +00:00
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *search_entry,
|
2015-01-13 20:23:50 +00:00
|
|
|
*replace_entry = NULL;
|
2015-01-23 20:23:35 +00:00
|
|
|
zend_string *tmp_result,
|
2017-11-16 14:09:32 +00:00
|
|
|
*tmp_subject_str,
|
|
|
|
*tmp_replace_entry_str = NULL,
|
|
|
|
*replace_entry_str;
|
2001-01-22 21:39:55 +00:00
|
|
|
char *replace_value = NULL;
|
2015-01-13 20:23:50 +00:00
|
|
|
size_t replace_len = 0;
|
|
|
|
zend_long replace_count = 0;
|
|
|
|
zend_string *subject_str;
|
|
|
|
zend_string *lc_subject_str = NULL;
|
2015-02-10 13:59:34 +00:00
|
|
|
uint32_t replace_idx;
|
2001-01-22 21:39:55 +00:00
|
|
|
|
2012-01-02 00:47:57 +00:00
|
|
|
/* Make sure we're dealing with strings. */
|
2017-11-16 14:09:32 +00:00
|
|
|
subject_str = zval_get_tmp_string(subject, &tmp_subject_str);
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(subject_str) == 0) {
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_subject_str);
|
2014-02-10 13:49:21 +00:00
|
|
|
ZVAL_EMPTY_STRING(result);
|
2015-01-13 20:23:50 +00:00
|
|
|
return 0;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-01-22 21:39:55 +00:00
|
|
|
/* If search is an array */
|
|
|
|
if (Z_TYPE_P(search) == IS_ARRAY) {
|
|
|
|
/* Duplicate subject string for repeated replacement */
|
2018-07-03 14:47:08 +00:00
|
|
|
zend_string_addref(subject_str);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-01-22 21:39:55 +00:00
|
|
|
if (Z_TYPE_P(replace) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
replace_idx = 0;
|
2001-01-22 21:39:55 +00:00
|
|
|
} else {
|
|
|
|
/* Set replacement value to the passed one */
|
|
|
|
replace_value = Z_STRVAL_P(replace);
|
2014-08-25 17:24:55 +00:00
|
|
|
replace_len = Z_STRLEN_P(replace);
|
2001-01-22 21:39:55 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2001-01-22 21:39:55 +00:00
|
|
|
/* For each entry in the search array, get the entry */
|
2014-04-18 17:49:07 +00:00
|
|
|
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(search), search_entry) {
|
2012-01-02 00:47:57 +00:00
|
|
|
/* Make sure we're dealing with strings. */
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *tmp_search_str;
|
|
|
|
zend_string *search_str = zval_get_tmp_string(search_entry, &tmp_search_str);
|
|
|
|
|
2001-01-22 21:39:55 +00:00
|
|
|
/* If replace is an array. */
|
|
|
|
if (Z_TYPE_P(replace) == IS_ARRAY) {
|
|
|
|
/* Get current entry */
|
2015-02-10 13:59:34 +00:00
|
|
|
while (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
|
|
|
|
replace_entry = &Z_ARRVAL_P(replace)->arData[replace_idx].val;
|
|
|
|
if (Z_TYPE_P(replace_entry) != IS_UNDEF) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
replace_idx++;
|
|
|
|
}
|
|
|
|
if (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
|
2012-01-02 00:47:57 +00:00
|
|
|
/* Make sure we're dealing with strings. */
|
2017-11-16 14:09:32 +00:00
|
|
|
replace_entry_str = zval_get_tmp_string(replace_entry, &tmp_replace_entry_str);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-01-22 21:39:55 +00:00
|
|
|
/* Set replacement value to the one we got from array */
|
2015-06-30 01:05:24 +00:00
|
|
|
replace_value = ZSTR_VAL(replace_entry_str);
|
|
|
|
replace_len = ZSTR_LEN(replace_entry_str);
|
2001-01-22 21:39:55 +00:00
|
|
|
|
2015-02-10 13:59:34 +00:00
|
|
|
replace_idx++;
|
2001-01-22 21:39:55 +00:00
|
|
|
} else {
|
|
|
|
/* We've run out of replacement strings, so use an empty one. */
|
2004-07-19 07:19:50 +00:00
|
|
|
replace_value = "";
|
2001-01-22 21:39:55 +00:00
|
|
|
replace_len = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-12-22 03:07:30 +00:00
|
|
|
if (ZSTR_LEN(search_str) == 1) {
|
2015-01-13 20:23:50 +00:00
|
|
|
zend_long old_replace_count = replace_count;
|
|
|
|
|
2018-07-03 14:47:08 +00:00
|
|
|
tmp_result = php_char_to_str_ex(subject_str,
|
2015-12-22 03:07:30 +00:00
|
|
|
ZSTR_VAL(search_str)[0],
|
2001-01-22 21:39:55 +00:00
|
|
|
replace_value,
|
|
|
|
replace_len,
|
2003-07-25 01:03:39 +00:00
|
|
|
case_sensitivity,
|
2015-01-13 20:23:50 +00:00
|
|
|
&replace_count);
|
|
|
|
if (lc_subject_str && replace_count != old_replace_count) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_subject_str, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
lc_subject_str = NULL;
|
|
|
|
}
|
2015-12-22 03:07:30 +00:00
|
|
|
} else if (ZSTR_LEN(search_str) > 1) {
|
2015-01-13 20:23:50 +00:00
|
|
|
if (case_sensitivity) {
|
2018-07-03 14:47:08 +00:00
|
|
|
tmp_result = php_str_to_str_ex(subject_str,
|
2015-12-22 03:07:30 +00:00
|
|
|
ZSTR_VAL(search_str), ZSTR_LEN(search_str),
|
2015-01-13 20:23:50 +00:00
|
|
|
replace_value, replace_len, &replace_count);
|
|
|
|
} else {
|
|
|
|
zend_long old_replace_count = replace_count;
|
|
|
|
|
|
|
|
if (!lc_subject_str) {
|
2018-07-03 14:47:08 +00:00
|
|
|
lc_subject_str = php_string_tolower(subject_str);
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2018-07-03 14:47:08 +00:00
|
|
|
tmp_result = php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str),
|
2015-12-22 03:07:30 +00:00
|
|
|
search_str, replace_value, replace_len, &replace_count);
|
2015-01-13 20:23:50 +00:00
|
|
|
if (replace_count != old_replace_count) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_subject_str, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
lc_subject_str = NULL;
|
|
|
|
}
|
2017-01-16 20:11:50 +00:00
|
|
|
}
|
2018-07-03 14:47:08 +00:00
|
|
|
} else {
|
|
|
|
zend_tmp_string_release(tmp_search_str);
|
|
|
|
continue;
|
2001-01-22 21:39:55 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_search_str);
|
2015-12-22 03:07:30 +00:00
|
|
|
|
2017-11-16 14:09:32 +00:00
|
|
|
if (tmp_replace_entry_str) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(tmp_replace_entry_str, 0);
|
2017-11-16 14:09:32 +00:00
|
|
|
tmp_replace_entry_str = NULL;
|
2015-01-23 20:23:35 +00:00
|
|
|
}
|
2001-01-22 21:39:55 +00:00
|
|
|
|
2018-07-03 14:47:08 +00:00
|
|
|
if (subject_str == tmp_result) {
|
|
|
|
zend_string_delref(subject_str);
|
|
|
|
} else {
|
|
|
|
zend_string_release_ex(subject_str, 0);
|
|
|
|
subject_str = tmp_result;
|
|
|
|
if (ZSTR_LEN(subject_str) == 0) {
|
|
|
|
zend_string_release_ex(subject_str, 0);
|
|
|
|
ZVAL_EMPTY_STRING(result);
|
|
|
|
if (lc_subject_str) {
|
|
|
|
zend_string_release_ex(lc_subject_str, 0);
|
|
|
|
}
|
|
|
|
zend_tmp_string_release(tmp_subject_str);
|
|
|
|
return replace_count;
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2001-11-10 23:44:04 +00:00
|
|
|
}
|
2014-04-18 17:49:07 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2018-07-03 14:47:08 +00:00
|
|
|
ZVAL_STR(result, subject_str);
|
2015-01-13 20:23:50 +00:00
|
|
|
if (lc_subject_str) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_subject_str, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2001-01-22 21:39:55 +00:00
|
|
|
} else {
|
2015-12-22 03:07:30 +00:00
|
|
|
ZEND_ASSERT(Z_TYPE_P(search) == IS_STRING);
|
2014-08-25 17:24:55 +00:00
|
|
|
if (Z_STRLEN_P(search) == 1) {
|
2015-01-13 20:23:50 +00:00
|
|
|
ZVAL_STR(result,
|
|
|
|
php_char_to_str_ex(subject_str,
|
2001-01-22 21:39:55 +00:00
|
|
|
Z_STRVAL_P(search)[0],
|
|
|
|
Z_STRVAL_P(replace),
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_STRLEN_P(replace),
|
2003-07-25 01:03:39 +00:00
|
|
|
case_sensitivity,
|
2015-01-13 20:23:50 +00:00
|
|
|
&replace_count));
|
2014-08-25 17:24:55 +00:00
|
|
|
} else if (Z_STRLEN_P(search) > 1) {
|
2015-01-13 20:23:50 +00:00
|
|
|
if (case_sensitivity) {
|
|
|
|
ZVAL_STR(result, php_str_to_str_ex(subject_str,
|
2014-08-25 17:24:55 +00:00
|
|
|
Z_STRVAL_P(search), Z_STRLEN_P(search),
|
2015-01-13 20:23:50 +00:00
|
|
|
Z_STRVAL_P(replace), Z_STRLEN_P(replace), &replace_count));
|
|
|
|
} else {
|
2015-07-27 03:17:05 +00:00
|
|
|
lc_subject_str = php_string_tolower(subject_str);
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_STR(result, php_str_to_str_i_ex(subject_str, ZSTR_VAL(lc_subject_str),
|
2015-01-13 20:23:50 +00:00
|
|
|
Z_STR_P(search),
|
|
|
|
Z_STRVAL_P(replace), Z_STRLEN_P(replace), &replace_count));
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(lc_subject_str, 0);
|
2015-01-13 20:23:50 +00:00
|
|
|
}
|
2001-01-22 21:39:55 +00:00
|
|
|
} else {
|
2015-01-13 20:23:50 +00:00
|
|
|
ZVAL_STR_COPY(result, subject_str);
|
2001-01-22 21:39:55 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_subject_str);
|
2015-01-13 20:23:50 +00:00
|
|
|
return replace_count;
|
2001-01-22 21:39:55 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2001-01-22 21:39:55 +00:00
|
|
|
|
2003-01-30 20:09:19 +00:00
|
|
|
/* {{{ php_str_replace_common
|
|
|
|
*/
|
|
|
|
static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity)
|
2001-01-22 21:39:55 +00:00
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *subject, *search, *replace, *subject_entry, *zcount = NULL;
|
|
|
|
zval result;
|
|
|
|
zend_string *string_key;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_ulong num_key;
|
2015-01-13 20:23:50 +00:00
|
|
|
zend_long count = 0;
|
2003-04-13 22:59:19 +00:00
|
|
|
int argc = ZEND_NUM_ARGS();
|
2001-01-22 21:39:55 +00:00
|
|
|
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(3, 4)
|
|
|
|
Z_PARAM_ZVAL(search)
|
|
|
|
Z_PARAM_ZVAL(replace)
|
|
|
|
Z_PARAM_ZVAL(subject)
|
|
|
|
Z_PARAM_OPTIONAL
|
2019-01-07 11:28:51 +00:00
|
|
|
Z_PARAM_ZVAL(zcount)
|
2014-07-11 12:32:20 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-05-12 15:40:15 +00:00
|
|
|
|
2003-01-30 05:00:41 +00:00
|
|
|
/* Make sure we're dealing with strings and do the replacement. */
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(search) != IS_ARRAY) {
|
2003-01-30 05:00:41 +00:00
|
|
|
convert_to_string_ex(search);
|
2014-04-01 21:56:16 +00:00
|
|
|
if (Z_TYPE_P(replace) != IS_STRING) {
|
|
|
|
convert_to_string_ex(replace);
|
|
|
|
}
|
2014-02-10 13:49:21 +00:00
|
|
|
} else if (Z_TYPE_P(replace) != IS_ARRAY) {
|
2003-01-30 05:00:41 +00:00
|
|
|
convert_to_string_ex(replace);
|
2001-07-20 01:22:29 +00:00
|
|
|
}
|
2003-01-30 05:00:41 +00:00
|
|
|
|
2019-02-26 14:32:18 +00:00
|
|
|
if (EG(exception)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-01-30 05:00:41 +00:00
|
|
|
/* if subject is an array */
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(subject) == IS_ARRAY) {
|
2003-01-30 05:00:41 +00:00
|
|
|
array_init(return_value);
|
|
|
|
|
|
|
|
/* For each subject entry, convert it to string, then perform replacement
|
|
|
|
and add the result to the return_value array. */
|
2014-04-21 10:20:05 +00:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(subject), num_key, string_key, subject_entry) {
|
2016-04-06 02:19:24 +00:00
|
|
|
ZVAL_DEREF(subject_entry);
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE_P(subject_entry) != IS_ARRAY && Z_TYPE_P(subject_entry) != IS_OBJECT) {
|
2015-01-13 20:23:50 +00:00
|
|
|
count += php_str_replace_in_subject(search, replace, subject_entry, &result, case_sensitivity);
|
2003-05-16 23:30:08 +00:00
|
|
|
} else {
|
2014-04-15 11:40:40 +00:00
|
|
|
ZVAL_COPY(&result, subject_entry);
|
2003-05-16 23:30:08 +00:00
|
|
|
}
|
2003-01-30 05:00:41 +00:00
|
|
|
/* Add to return array */
|
2014-04-21 10:20:05 +00:00
|
|
|
if (string_key) {
|
2015-01-13 20:23:50 +00:00
|
|
|
zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, &result);
|
2014-04-21 10:20:05 +00:00
|
|
|
} else {
|
2015-01-13 20:23:50 +00:00
|
|
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
|
2003-01-30 05:00:41 +00:00
|
|
|
}
|
2014-04-21 10:20:05 +00:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2003-01-30 05:00:41 +00:00
|
|
|
} else { /* if subject is not an array */
|
2015-01-13 20:23:50 +00:00
|
|
|
count = php_str_replace_in_subject(search, replace, subject, return_value, case_sensitivity);
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
2003-04-13 22:59:19 +00:00
|
|
|
if (argc > 3) {
|
2019-04-24 13:14:48 +00:00
|
|
|
ZEND_TRY_ASSIGN_REF_LONG(zcount, count);
|
2003-04-13 22:59:19 +00:00
|
|
|
}
|
2003-01-30 05:00:41 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-13 22:59:19 +00:00
|
|
|
/* {{{ proto mixed str_replace(mixed search, mixed replace, mixed subject [, int &replace_count])
|
2003-01-30 20:09:19 +00:00
|
|
|
Replaces all occurrences of search in haystack with replace */
|
|
|
|
PHP_FUNCTION(str_replace)
|
|
|
|
{
|
|
|
|
php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-13 22:59:19 +00:00
|
|
|
/* {{{ proto mixed str_ireplace(mixed search, mixed replace, mixed subject [, int &replace_count])
|
2003-01-30 05:00:41 +00:00
|
|
|
Replaces all occurrences of search in haystack with replace / case-insensitive */
|
|
|
|
PHP_FUNCTION(str_ireplace)
|
|
|
|
{
|
2003-01-30 20:09:19 +00:00
|
|
|
php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_hebrev
|
|
|
|
*
|
|
|
|
* Converts Logical Hebrew text (Hebrew Windows style) to Visual text
|
1999-04-17 00:37:12 +00:00
|
|
|
* Cheers/complaints/flames - Zeev Suraski <zeev@php.net>
|
|
|
|
*/
|
2001-08-11 17:03:37 +00:00
|
|
|
static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2018-03-17 11:45:22 +00:00
|
|
|
char *str, *heb_str, *target;
|
|
|
|
const char *tmp;
|
2014-08-28 17:35:37 +00:00
|
|
|
size_t block_start, block_end, block_type, block_length, i;
|
2016-06-23 09:47:06 +00:00
|
|
|
zend_long max_chars=0, char_count;
|
|
|
|
size_t begin, end, orig_begin;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t str_len;
|
2014-02-25 05:04:00 +00:00
|
|
|
zend_string *broken_str;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STRING(str, str_len)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(max_chars)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
if (str_len == 0) {
|
2019-05-28 11:07:03 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
tmp = str;
|
1999-04-17 00:37:12 +00:00
|
|
|
block_start=block_end=0;
|
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
heb_str = (char *) emalloc(str_len+1);
|
|
|
|
target = heb_str+str_len;
|
1999-04-17 00:37:12 +00:00
|
|
|
*target = 0;
|
|
|
|
target--;
|
|
|
|
|
|
|
|
block_length=0;
|
|
|
|
|
|
|
|
if (isheb(*tmp)) {
|
|
|
|
block_type = _HEB_BLOCK_TYPE_HEB;
|
|
|
|
} else {
|
|
|
|
block_type = _HEB_BLOCK_TYPE_ENG;
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
do {
|
2002-10-02 17:56:04 +00:00
|
|
|
if (block_type == _HEB_BLOCK_TYPE_HEB) {
|
2008-06-25 12:16:17 +00:00
|
|
|
while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) {
|
1999-04-17 00:37:12 +00:00
|
|
|
tmp++;
|
|
|
|
block_end++;
|
|
|
|
block_length++;
|
|
|
|
}
|
2014-08-28 17:35:37 +00:00
|
|
|
for (i = block_start+1; i<= block_end+1; i++) {
|
|
|
|
*target = str[i-1];
|
1999-04-17 00:37:12 +00:00
|
|
|
switch (*target) {
|
|
|
|
case '(':
|
|
|
|
*target = ')';
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
*target = '(';
|
|
|
|
break;
|
2002-03-26 07:57:07 +00:00
|
|
|
case '[':
|
|
|
|
*target = ']';
|
|
|
|
break;
|
|
|
|
case ']':
|
|
|
|
*target = '[';
|
|
|
|
break;
|
|
|
|
case '{':
|
|
|
|
*target = '}';
|
|
|
|
break;
|
|
|
|
case '}':
|
|
|
|
*target = '{';
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
*target = '>';
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
*target = '<';
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
*target = '/';
|
|
|
|
break;
|
|
|
|
case '/':
|
|
|
|
*target = '\\';
|
|
|
|
break;
|
1999-04-17 00:37:12 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
target--;
|
|
|
|
}
|
|
|
|
block_type = _HEB_BLOCK_TYPE_ENG;
|
|
|
|
} else {
|
2008-06-25 12:16:17 +00:00
|
|
|
while (!isheb(*(tmp+1)) && (int)*(tmp+1)!='\n' && block_end < str_len-1) {
|
1999-04-17 00:37:12 +00:00
|
|
|
tmp++;
|
|
|
|
block_end++;
|
|
|
|
block_length++;
|
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
while ((_isblank((int)*tmp) || ispunct((int)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) {
|
1999-04-17 00:37:12 +00:00
|
|
|
tmp--;
|
|
|
|
block_end--;
|
|
|
|
}
|
2014-08-28 17:35:37 +00:00
|
|
|
for (i = block_end+1; i >= block_start+1; i--) {
|
|
|
|
*target = str[i-1];
|
1999-04-17 00:37:12 +00:00
|
|
|
target--;
|
|
|
|
}
|
|
|
|
block_type = _HEB_BLOCK_TYPE_HEB;
|
|
|
|
}
|
|
|
|
block_start=block_end+1;
|
2008-06-25 12:16:17 +00:00
|
|
|
} while (block_end < str_len-1);
|
1999-04-17 00:37:12 +00:00
|
|
|
|
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
broken_str = zend_string_alloc(str_len, 0);
|
2014-02-25 05:04:00 +00:00
|
|
|
begin = end = str_len-1;
|
2015-06-30 01:05:24 +00:00
|
|
|
target = ZSTR_VAL(broken_str);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
while (1) {
|
|
|
|
char_count=0;
|
2014-09-28 19:30:49 +00:00
|
|
|
while ((!max_chars || (max_chars > 0 && char_count < max_chars)) && begin > 0) {
|
1999-04-17 00:37:12 +00:00
|
|
|
char_count++;
|
|
|
|
begin--;
|
2017-11-17 20:35:22 +00:00
|
|
|
if (_isnewline(heb_str[begin])) {
|
2002-10-02 17:56:04 +00:00
|
|
|
while (begin > 0 && _isnewline(heb_str[begin-1])) {
|
1999-04-17 00:37:12 +00:00
|
|
|
begin--;
|
|
|
|
char_count++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-08-28 17:35:37 +00:00
|
|
|
if (max_chars >= 0 && char_count == max_chars) { /* try to avoid breaking words */
|
|
|
|
size_t new_char_count=char_count, new_begin=begin;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
while (new_char_count > 0) {
|
1999-04-17 00:37:12 +00:00
|
|
|
if (_isblank(heb_str[new_begin]) || _isnewline(heb_str[new_begin])) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
new_begin++;
|
|
|
|
new_char_count--;
|
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
if (new_char_count > 0) {
|
1999-04-17 00:37:12 +00:00
|
|
|
begin=new_begin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
orig_begin=begin;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
if (_isblank(heb_str[begin])) {
|
|
|
|
heb_str[begin]='\n';
|
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
while (begin <= end && _isnewline(heb_str[begin])) { /* skip leading newlines */
|
1999-04-17 00:37:12 +00:00
|
|
|
begin++;
|
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
for (i = begin; i <= end; i++) { /* copy content */
|
1999-04-17 00:37:12 +00:00
|
|
|
*target = heb_str[i];
|
|
|
|
target++;
|
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
for (i = orig_begin; i <= end && _isnewline(heb_str[i]); i++) {
|
1999-04-17 00:37:12 +00:00
|
|
|
*target = heb_str[i];
|
|
|
|
target++;
|
|
|
|
}
|
|
|
|
begin=orig_begin;
|
|
|
|
|
2017-11-17 20:35:22 +00:00
|
|
|
if (begin == 0) {
|
1999-04-17 00:37:12 +00:00
|
|
|
*target = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
begin--;
|
|
|
|
end=begin;
|
|
|
|
}
|
|
|
|
efree(heb_str);
|
|
|
|
|
|
|
|
if (convert_newlines) {
|
2015-01-13 20:23:50 +00:00
|
|
|
RETVAL_STR(php_char_to_str_ex(broken_str, '\n', "<br />\n", 7, 1, NULL));
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(broken_str, 0);
|
1999-04-17 00:37:12 +00:00
|
|
|
} else {
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(broken_str);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
|
|
|
/* {{{ proto string hebrev(string str [, int max_chars_per_line])
|
2001-09-04 10:44:28 +00:00
|
|
|
Converts logical Hebrew text to visual text */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(hebrev)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2001-08-11 17:03:37 +00:00
|
|
|
php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
/* {{{ proto string hebrevc(string str [, int max_chars_per_line])
|
2001-09-04 10:44:28 +00:00
|
|
|
Converts logical Hebrew text to visual text with newline conversion */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
PHP_FUNCTION(hebrevc)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2001-08-11 17:03:37 +00:00
|
|
|
php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2008-08-14 02:56:23 +00:00
|
|
|
/* {{{ proto string nl2br(string str [, bool is_xhtml])
|
1999-04-17 00:37:12 +00:00
|
|
|
Converts newlines to HTML line breaks */
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
PHP_FUNCTION(nl2br)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2008-08-14 02:56:23 +00:00
|
|
|
/* in brief this inserts <br /> or <br> before matched regexp \n\r?|\r\n? */
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *tmp, *end;
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2018-03-17 11:45:22 +00:00
|
|
|
char *target;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t repl_cnt = 0;
|
2008-08-14 02:56:23 +00:00
|
|
|
zend_bool is_xhtml = 1;
|
2014-02-24 09:40:18 +00:00
|
|
|
zend_string *result;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-01-17 16:30:40 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_BOOL(is_xhtml)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
tmp = ZSTR_VAL(str);
|
|
|
|
end = ZSTR_VAL(str) + ZSTR_LEN(str);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2009-11-06 09:02:52 +00:00
|
|
|
/* it is really faster to scan twice and allocate mem once instead of scanning once
|
2001-09-26 19:34:46 +00:00
|
|
|
and constantly reallocing */
|
2008-06-25 12:16:17 +00:00
|
|
|
while (tmp < end) {
|
|
|
|
if (*tmp == '\r') {
|
|
|
|
if (*(tmp+1) == '\n') {
|
|
|
|
tmp++;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
|
|
|
repl_cnt++;
|
2008-06-25 12:16:17 +00:00
|
|
|
} else if (*tmp == '\n') {
|
|
|
|
if (*(tmp+1) == '\r') {
|
|
|
|
tmp++;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
2001-09-26 19:34:46 +00:00
|
|
|
repl_cnt++;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
tmp++;
|
2001-09-26 19:34:46 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-09-26 19:34:46 +00:00
|
|
|
if (repl_cnt == 0) {
|
2015-07-02 03:44:28 +00:00
|
|
|
RETURN_STR_COPY(str);
|
2001-09-24 08:33:51 +00:00
|
|
|
}
|
2001-09-09 12:55:48 +00:00
|
|
|
|
2012-07-05 18:31:58 +00:00
|
|
|
{
|
|
|
|
size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1);
|
2008-08-14 02:56:23 +00:00
|
|
|
|
2016-01-27 06:10:43 +00:00
|
|
|
result = zend_string_safe_alloc(repl_cnt, repl_len, ZSTR_LEN(str), 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
target = ZSTR_VAL(result);
|
2012-07-05 18:31:58 +00:00
|
|
|
}
|
2002-10-09 13:37:02 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
tmp = ZSTR_VAL(str);
|
2014-08-18 13:39:38 +00:00
|
|
|
while (tmp < end) {
|
|
|
|
switch (*tmp) {
|
2002-10-09 13:37:02 +00:00
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
*target++ = '<';
|
|
|
|
*target++ = 'b';
|
|
|
|
*target++ = 'r';
|
2008-08-14 02:56:23 +00:00
|
|
|
|
|
|
|
if (is_xhtml) {
|
|
|
|
*target++ = ' ';
|
|
|
|
*target++ = '/';
|
|
|
|
}
|
|
|
|
|
2002-10-09 13:37:02 +00:00
|
|
|
*target++ = '>';
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-08-18 13:39:38 +00:00
|
|
|
if ((*tmp == '\r' && *(tmp+1) == '\n') || (*tmp == '\n' && *(tmp+1) == '\r')) {
|
2014-08-20 13:32:24 +00:00
|
|
|
*target++ = *tmp++;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
|
|
|
/* lack of a break; is intentional */
|
|
|
|
default:
|
2014-08-18 13:39:38 +00:00
|
|
|
*target++ = *tmp;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-08-18 13:39:38 +00:00
|
|
|
tmp++;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-11 12:42:01 +00:00
|
|
|
*target = '\0';
|
2001-09-26 19:34:46 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(result);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-09-20 20:05:26 +00:00
|
|
|
/* {{{ proto string strip_tags(string str [, string allowable_tags])
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
Strips HTML and PHP tags from a string */
|
|
|
|
PHP_FUNCTION(strip_tags)
|
|
|
|
{
|
2014-04-15 17:56:30 +00:00
|
|
|
zend_string *buf;
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *allow=NULL;
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *allowed_tags=NULL;
|
2014-08-28 17:35:37 +00:00
|
|
|
size_t allowed_tags_len=0;
|
2018-12-29 21:10:19 +00:00
|
|
|
smart_str tags_ss = {0};
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
2017-06-19 09:55:59 +00:00
|
|
|
Z_PARAM_ZVAL(allow)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-07-01 16:04:18 +00:00
|
|
|
if (allow) {
|
2018-12-29 21:10:19 +00:00
|
|
|
if (Z_TYPE_P(allow) == IS_ARRAY) {
|
|
|
|
zval *tmp;
|
|
|
|
zend_string *tag;
|
|
|
|
|
|
|
|
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(allow), tmp) {
|
|
|
|
tag = zval_get_string(tmp);
|
|
|
|
smart_str_appendc(&tags_ss, '<');
|
|
|
|
smart_str_append(&tags_ss, tag);
|
|
|
|
smart_str_appendc(&tags_ss, '>');
|
|
|
|
zend_string_release(tag);
|
|
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
if (tags_ss.s) {
|
|
|
|
smart_str_0(&tags_ss);
|
|
|
|
allowed_tags = ZSTR_VAL(tags_ss.s);
|
|
|
|
allowed_tags_len = ZSTR_LEN(tags_ss.s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* To maintain a certain BC, we allow anything for the second parameter and return original string */
|
|
|
|
convert_to_string(allow);
|
|
|
|
allowed_tags = Z_STRVAL_P(allow);
|
|
|
|
allowed_tags_len = Z_STRLEN_P(allow);
|
|
|
|
}
|
2008-06-25 12:16:17 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
buf = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0);
|
|
|
|
ZSTR_LEN(buf) = php_strip_tags_ex(ZSTR_VAL(buf), ZSTR_LEN(str), NULL, allowed_tags, allowed_tags_len, 0);
|
2018-12-29 21:10:19 +00:00
|
|
|
smart_str_free(&tags_ss);
|
2015-07-01 16:04:18 +00:00
|
|
|
RETURN_NEW_STR(buf);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false setlocale(mixed category, string locale [, string ...])
|
1999-04-17 00:37:12 +00:00
|
|
|
Set locale information */
|
1999-06-15 21:51:00 +00:00
|
|
|
PHP_FUNCTION(setlocale)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval *args = NULL;
|
2014-09-10 15:46:54 +00:00
|
|
|
zval *plocale;
|
2017-11-16 15:10:28 +00:00
|
|
|
zend_string *loc;
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *retval;
|
2014-09-10 15:46:54 +00:00
|
|
|
zend_long cat;
|
|
|
|
int num_args, i = 0;
|
2015-02-10 13:59:34 +00:00
|
|
|
uint32_t idx;
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, -1)
|
|
|
|
Z_PARAM_LONG(cat)
|
|
|
|
Z_PARAM_VARIADIC('+', args, num_args)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-08-16 21:32:41 +00:00
|
|
|
|
2015-02-10 13:59:34 +00:00
|
|
|
idx = 0;
|
2002-10-02 17:56:04 +00:00
|
|
|
while (1) {
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE(args[0]) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
while (idx < Z_ARRVAL(args[0])->nNumUsed) {
|
|
|
|
plocale = &Z_ARRVAL(args[0])->arData[idx].val;
|
2015-02-11 11:03:35 +00:00
|
|
|
if (Z_TYPE_P(plocale) != IS_UNDEF) {
|
2015-02-10 13:59:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
idx++;
|
2003-04-03 06:21:59 +00:00
|
|
|
}
|
2015-02-10 13:59:34 +00:00
|
|
|
if (idx >= Z_ARRVAL(args[0])->nNumUsed) {
|
2014-02-25 04:09:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-09-18 07:55:30 +00:00
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
plocale = &args[i];
|
1999-10-08 02:10:57 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 22:47:22 +00:00
|
|
|
loc = zval_try_get_string(plocale);
|
|
|
|
if (UNEXPECTED(!loc)) {
|
2019-02-26 14:32:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!strcmp("0", ZSTR_VAL(loc))) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(loc, 0);
|
2017-11-16 15:10:28 +00:00
|
|
|
loc = NULL;
|
2002-09-18 07:55:30 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(loc) >= 255) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Specified locale name is too long");
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(loc, 0);
|
2007-09-07 02:28:42 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-09-18 07:55:30 +00:00
|
|
|
}
|
2007-09-07 02:28:42 +00:00
|
|
|
|
Fix #77937: preg_match failed
On some recent Windows systems, ext\pcre\tests\locales.phpt fails,
because 'pt_PT' is accepted by `setlocale()`, but not properly
supported by the ctype functions, which are used internally by PCRE2 to
build the localized character tables.
Since there appears to be no way to properly check whether a given
locale is fully supported, but we want to minimize BC impact, we filter
out typical Unix locale names, except for a few cases which have
already been properly supported on Windows. This way code like
setlocale(LC_ALL, 'de_DE.UTF-8', 'de_DE', 'German_Germany.1252');
should work like on older Windows systems.
It should be noted that the locale names causing trouble are not (yet)
documented as valid names anyway, see
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?view=vs-2019>.
2019-04-30 14:10:04 +00:00
|
|
|
# ifndef PHP_WIN32
|
2015-06-30 01:05:24 +00:00
|
|
|
retval = php_my_setlocale(cat, loc ? ZSTR_VAL(loc) : NULL);
|
Fix #77937: preg_match failed
On some recent Windows systems, ext\pcre\tests\locales.phpt fails,
because 'pt_PT' is accepted by `setlocale()`, but not properly
supported by the ctype functions, which are used internally by PCRE2 to
build the localized character tables.
Since there appears to be no way to properly check whether a given
locale is fully supported, but we want to minimize BC impact, we filter
out typical Unix locale names, except for a few cases which have
already been properly supported on Windows. This way code like
setlocale(LC_ALL, 'de_DE.UTF-8', 'de_DE', 'German_Germany.1252');
should work like on older Windows systems.
It should be noted that the locale names causing trouble are not (yet)
documented as valid names anyway, see
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?view=vs-2019>.
2019-04-30 14:10:04 +00:00
|
|
|
# else
|
|
|
|
if (loc) {
|
|
|
|
/* BC: don't try /^[a-z]{2}_[A-Z]{2}($|\..*)/ except for /^u[ks]_U[KS]$/ */
|
|
|
|
char *locp = ZSTR_VAL(loc);
|
|
|
|
if (ZSTR_LEN(loc) >= 5 && locp[2] == '_'
|
|
|
|
&& locp[0] >= 'a' && locp[0] <= 'z' && locp[1] >= 'a' && locp[1] <= 'z'
|
|
|
|
&& locp[3] >= 'A' && locp[3] <= 'Z' && locp[4] >= 'A' && locp[4] <= 'Z'
|
|
|
|
&& (locp[5] == '\0' || locp[5] == '.')
|
|
|
|
&& !(locp[0] == 'u' && (locp[1] == 'k' || locp[1] == 's')
|
|
|
|
&& locp[3] == 'U' && (locp[4] == 'K' || locp[4] == 'S')
|
|
|
|
&& locp[5] == '\0')
|
|
|
|
) {
|
|
|
|
retval = NULL;
|
|
|
|
} else {
|
|
|
|
retval = php_my_setlocale(cat, ZSTR_VAL(loc));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
retval = php_my_setlocale(cat, NULL);
|
|
|
|
}
|
|
|
|
# endif
|
2006-12-04 18:37:15 +00:00
|
|
|
zend_update_current_locale();
|
2002-09-18 07:55:30 +00:00
|
|
|
if (retval) {
|
|
|
|
if (loc) {
|
2014-12-19 15:00:16 +00:00
|
|
|
/* Remember if locale was changed */
|
2015-01-08 22:41:13 +00:00
|
|
|
size_t len = strlen(retval);
|
2014-12-19 15:00:16 +00:00
|
|
|
|
2015-01-08 22:41:13 +00:00
|
|
|
BG(locale_changed) = 1;
|
|
|
|
if (cat == LC_CTYPE || cat == LC_ALL) {
|
|
|
|
if (BG(locale_string)) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(BG(locale_string), 0);
|
2015-01-08 22:41:13 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
if (len == ZSTR_LEN(loc) && !memcmp(ZSTR_VAL(loc), retval, len)) {
|
2015-01-08 22:41:13 +00:00
|
|
|
BG(locale_string) = zend_string_copy(loc);
|
2015-01-22 08:55:20 +00:00
|
|
|
RETURN_STR(BG(locale_string));
|
2015-01-08 22:41:13 +00:00
|
|
|
} else {
|
|
|
|
BG(locale_string) = zend_string_init(retval, len, 0);
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(loc, 0);
|
2015-03-12 13:53:51 +00:00
|
|
|
RETURN_STR_COPY(BG(locale_string));
|
2015-01-08 22:41:13 +00:00
|
|
|
}
|
2015-06-30 01:05:24 +00:00
|
|
|
} else if (len == ZSTR_LEN(loc) && !memcmp(ZSTR_VAL(loc), retval, len)) {
|
2015-01-08 22:41:13 +00:00
|
|
|
RETURN_STR(loc);
|
2014-02-24 07:03:35 +00:00
|
|
|
}
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(loc, 0);
|
2014-12-19 15:00:16 +00:00
|
|
|
}
|
2015-01-08 22:41:13 +00:00
|
|
|
RETURN_STRING(retval);
|
|
|
|
}
|
2017-11-16 15:10:28 +00:00
|
|
|
if (loc) {
|
2018-05-28 13:27:12 +00:00
|
|
|
zend_string_release_ex(loc, 0);
|
2017-11-16 15:10:28 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
if (Z_TYPE(args[0]) == IS_ARRAY) {
|
2015-02-10 13:59:34 +00:00
|
|
|
idx++;
|
2002-09-18 07:55:30 +00:00
|
|
|
} else {
|
2008-08-16 21:32:41 +00:00
|
|
|
if (++i >= num_args) break;
|
2002-09-18 07:55:30 +00:00
|
|
|
}
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2002-09-18 07:55:30 +00:00
|
|
|
|
1999-04-17 00:37:12 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-01-28 12:34:36 +00:00
|
|
|
/* {{{ proto void parse_str(string encoded_string, array &result)
|
2000-07-26 11:43:01 +00:00
|
|
|
Parses GET/POST/COOKIE data and sets global variables */
|
1999-07-24 22:16:54 +00:00
|
|
|
PHP_FUNCTION(parse_str)
|
1999-04-17 00:37:12 +00:00
|
|
|
{
|
2008-06-25 12:16:17 +00:00
|
|
|
char *arg;
|
2009-08-13 06:44:50 +00:00
|
|
|
zval *arrayArg = NULL;
|
1999-04-17 00:37:12 +00:00
|
|
|
char *res = NULL;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t arglen;
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2019-01-28 12:34:36 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
2016-12-31 00:40:45 +00:00
|
|
|
Z_PARAM_STRING(arg, arglen)
|
2019-01-07 11:28:51 +00:00
|
|
|
Z_PARAM_ZVAL(arrayArg)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-09-11 14:50:26 +00:00
|
|
|
|
2019-01-28 12:34:36 +00:00
|
|
|
arrayArg = zend_try_array_init(arrayArg);
|
|
|
|
if (!arrayArg) {
|
|
|
|
return;
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
2019-01-28 12:34:36 +00:00
|
|
|
|
|
|
|
res = estrndup(arg, arglen);
|
|
|
|
sapi_module.treat_data(PARSE_STRING, res, arrayArg);
|
1999-04-17 00:37:12 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
/* }}} */
|
|
|
|
|
1999-09-20 15:50:56 +00:00
|
|
|
#define PHP_TAG_BUF_SIZE 1023
|
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_tag_find
|
|
|
|
*
|
2012-01-02 00:47:57 +00:00
|
|
|
* Check if tag is in a set of tags
|
1999-09-20 15:50:56 +00:00
|
|
|
*
|
|
|
|
* states:
|
2012-01-02 00:47:57 +00:00
|
|
|
*
|
1999-09-20 15:50:56 +00:00
|
|
|
* 0 start tag
|
|
|
|
* 1 first non-whitespace char seen
|
|
|
|
*/
|
2015-07-01 16:04:18 +00:00
|
|
|
int php_tag_find(char *tag, size_t len, const char *set) {
|
2018-03-17 11:45:22 +00:00
|
|
|
char c, *n;
|
|
|
|
const char *t;
|
2000-02-13 15:59:32 +00:00
|
|
|
int state=0, done=0;
|
2006-12-20 23:36:56 +00:00
|
|
|
char *norm;
|
|
|
|
|
2017-11-17 20:35:22 +00:00
|
|
|
if (len == 0) {
|
2006-12-20 23:36:56 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2006-12-20 23:36:56 +00:00
|
|
|
norm = emalloc(len+1);
|
1999-09-20 15:50:56 +00:00
|
|
|
|
|
|
|
n = norm;
|
|
|
|
t = tag;
|
|
|
|
c = tolower(*t);
|
2012-01-02 00:47:57 +00:00
|
|
|
/*
|
1999-09-20 15:50:56 +00:00
|
|
|
normalize the tag removing leading and trailing whitespace
|
|
|
|
and turn any <a whatever...> into just <a> and any </tag>
|
|
|
|
into <tag>
|
|
|
|
*/
|
2002-10-02 17:56:04 +00:00
|
|
|
while (!done) {
|
|
|
|
switch (c) {
|
|
|
|
case '<':
|
|
|
|
*(n++) = c;
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
done =1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!isspace((int)c)) {
|
|
|
|
if (state == 0) {
|
|
|
|
state=1;
|
2010-11-16 22:16:44 +00:00
|
|
|
}
|
|
|
|
if (c != '/') {
|
2002-10-02 17:56:04 +00:00
|
|
|
*(n++) = c;
|
|
|
|
}
|
1999-09-20 15:50:56 +00:00
|
|
|
} else {
|
2002-10-02 17:56:04 +00:00
|
|
|
if (state == 1)
|
|
|
|
done=1;
|
1999-09-20 15:50:56 +00:00
|
|
|
}
|
2002-10-02 17:56:04 +00:00
|
|
|
break;
|
1999-09-20 15:50:56 +00:00
|
|
|
}
|
|
|
|
c = tolower(*(++t));
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
1999-09-20 15:50:56 +00:00
|
|
|
*(n++) = '>';
|
2012-01-02 00:47:57 +00:00
|
|
|
*n = '\0';
|
2002-10-02 17:56:04 +00:00
|
|
|
if (strstr(set, norm)) {
|
2000-02-13 15:56:07 +00:00
|
|
|
done=1;
|
|
|
|
} else {
|
|
|
|
done=0;
|
|
|
|
}
|
1999-09-20 15:50:56 +00:00
|
|
|
efree(norm);
|
|
|
|
return done;
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-09-20 15:50:56 +00:00
|
|
|
|
2016-09-15 14:48:29 +00:00
|
|
|
PHPAPI size_t php_strip_tags(char *rbuf, size_t len, uint8_t *stateptr, const char *allow, size_t allow_len) /* {{{ */
|
2006-12-18 15:02:16 +00:00
|
|
|
{
|
|
|
|
return php_strip_tags_ex(rbuf, len, stateptr, allow, allow_len, 0);
|
|
|
|
}
|
2007-06-05 13:35:26 +00:00
|
|
|
/* }}} */
|
2006-12-18 15:02:16 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strip_tags
|
2012-01-02 00:47:57 +00:00
|
|
|
|
|
|
|
A simple little state-machine to strip out html and php tags
|
|
|
|
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
State 0 is the output state, State 1 means we are inside a
|
|
|
|
normal html tag and state 2 means we are inside a php tag.
|
|
|
|
|
|
|
|
The state variable is passed in to allow a function like fgetss
|
|
|
|
to maintain state across calls to the function.
|
|
|
|
|
|
|
|
lc holds the last significant character read and br is a bracket
|
|
|
|
counter.
|
1999-09-20 15:50:56 +00:00
|
|
|
|
|
|
|
When an allow string is passed in we keep track of the string
|
|
|
|
in state 1 and when the tag is closed check it against the
|
|
|
|
allow string to see if we should allow it.
|
2001-08-22 02:03:14 +00:00
|
|
|
|
|
|
|
swm: Added ability to strip <?xml tags without assuming it PHP
|
|
|
|
code.
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
*/
|
2016-09-15 14:48:29 +00:00
|
|
|
PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, uint8_t *stateptr, const char *allow, size_t allow_len, zend_bool allow_tag_spaces)
|
2000-02-08 21:29:18 +00:00
|
|
|
{
|
2018-03-17 11:45:22 +00:00
|
|
|
char *tbuf, *tp, *rp, c, lc;
|
2018-07-16 10:22:17 +00:00
|
|
|
const char *buf, *p, *end;
|
2014-08-28 17:35:37 +00:00
|
|
|
int br, depth=0, in_q = 0;
|
2016-09-15 14:48:29 +00:00
|
|
|
uint8_t state = 0;
|
2018-07-16 10:22:17 +00:00
|
|
|
size_t pos;
|
2013-08-15 03:36:50 +00:00
|
|
|
char *allow_free = NULL;
|
2015-12-22 15:25:51 +00:00
|
|
|
char is_xml = 0;
|
2002-03-20 14:38:13 +00:00
|
|
|
|
2001-08-11 17:03:37 +00:00
|
|
|
buf = estrndup(rbuf, len);
|
2018-07-16 10:22:17 +00:00
|
|
|
end = buf + len;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
lc = '\0';
|
|
|
|
p = buf;
|
|
|
|
rp = rbuf;
|
|
|
|
br = 0;
|
2002-10-02 17:56:04 +00:00
|
|
|
if (allow) {
|
2015-07-01 16:04:18 +00:00
|
|
|
allow_free = zend_str_tolower_dup_ex(allow, allow_len);
|
2019-04-12 12:55:37 +00:00
|
|
|
allow = allow_free ? allow_free : allow;
|
2010-02-01 12:59:08 +00:00
|
|
|
tbuf = emalloc(PHP_TAG_BUF_SIZE + 1);
|
1999-09-20 15:50:56 +00:00
|
|
|
tp = tbuf;
|
1999-09-24 15:34:54 +00:00
|
|
|
} else {
|
|
|
|
tbuf = tp = NULL;
|
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
if (stateptr) {
|
|
|
|
state = *stateptr;
|
|
|
|
switch (state) {
|
|
|
|
case 1: goto state_1;
|
|
|
|
case 2: goto state_2;
|
|
|
|
case 3: goto state_3;
|
|
|
|
case 4: goto state_4;
|
|
|
|
default:
|
2004-06-26 07:43:02 +00:00
|
|
|
break;
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
state_0:
|
|
|
|
if (p >= end) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
c = *p;
|
|
|
|
switch (c) {
|
|
|
|
case '\0':
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
if (in_q) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (isspace(*(p + 1)) && !allow_tag_spaces) {
|
|
|
|
*(rp++) = c;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lc = '<';
|
|
|
|
state = 1;
|
|
|
|
if (allow) {
|
|
|
|
if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
|
|
|
|
pos = tp - tbuf;
|
|
|
|
tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
|
|
|
|
tp = tbuf + pos;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
*(tp++) = '<';
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
goto state_1;
|
|
|
|
case '>':
|
|
|
|
if (depth) {
|
|
|
|
depth--;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
break;
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
if (in_q) {
|
2012-01-02 00:47:57 +00:00
|
|
|
break;
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
*(rp++) = c;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*(rp++) = c;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
goto state_0;
|
|
|
|
|
|
|
|
state_1:
|
|
|
|
if (p >= end) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
c = *p;
|
|
|
|
switch (c) {
|
|
|
|
case '\0':
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
if (in_q) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (isspace(*(p + 1)) && !allow_tag_spaces) {
|
|
|
|
goto reg_char_1;
|
|
|
|
}
|
|
|
|
depth++;
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
if (depth) {
|
|
|
|
depth--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (in_q) {
|
2012-01-02 00:47:57 +00:00
|
|
|
break;
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
lc = '>';
|
|
|
|
if (is_xml && *(p -1) == '-') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
in_q = state = is_xml = 0;
|
|
|
|
if (allow) {
|
|
|
|
if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
|
|
|
|
pos = tp - tbuf;
|
|
|
|
tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
|
|
|
|
tp = tbuf + pos;
|
2002-09-20 11:48:47 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
*(tp++) = '>';
|
|
|
|
*tp='\0';
|
2019-04-12 12:55:37 +00:00
|
|
|
if (php_tag_find(tbuf, tp-tbuf, allow)) {
|
2018-07-16 10:22:17 +00:00
|
|
|
memcpy(rp, tbuf, tp-tbuf);
|
|
|
|
rp += tp-tbuf;
|
|
|
|
}
|
|
|
|
tp = tbuf;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
goto state_0;
|
|
|
|
case '"':
|
|
|
|
case '\'':
|
|
|
|
if (p != buf && (!in_q || *p == in_q)) {
|
2007-02-13 02:16:22 +00:00
|
|
|
if (in_q) {
|
2018-07-16 10:22:17 +00:00
|
|
|
in_q = 0;
|
|
|
|
} else {
|
|
|
|
in_q = *p;
|
2007-02-13 02:16:22 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
|
|
|
goto reg_char_1;
|
|
|
|
case '!':
|
|
|
|
/* JavaScript & Other HTML scripting languages */
|
|
|
|
if (*(p-1) == '<') {
|
|
|
|
state = 3;
|
|
|
|
lc = c;
|
|
|
|
p++;
|
|
|
|
goto state_3;
|
|
|
|
} else {
|
|
|
|
goto reg_char_1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '?':
|
|
|
|
if (*(p-1) == '<') {
|
|
|
|
br=0;
|
|
|
|
state = 2;
|
|
|
|
p++;
|
|
|
|
goto state_2;
|
|
|
|
} else {
|
|
|
|
goto reg_char_1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
reg_char_1:
|
|
|
|
if (allow) {
|
|
|
|
if (tp - tbuf >= PHP_TAG_BUF_SIZE) {
|
|
|
|
pos = tp - tbuf;
|
|
|
|
tbuf = erealloc(tbuf, (tp - tbuf) + PHP_TAG_BUF_SIZE + 1);
|
|
|
|
tp = tbuf + pos;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
*(tp++) = c;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
goto state_1;
|
|
|
|
|
|
|
|
state_2:
|
|
|
|
if (p >= end) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
c = *p;
|
|
|
|
switch (c) {
|
|
|
|
case '(':
|
|
|
|
if (lc != '"' && lc != '\'') {
|
|
|
|
lc = '(';
|
|
|
|
br++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
if (lc != '"' && lc != '\'') {
|
|
|
|
lc = ')';
|
|
|
|
br--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '>':
|
2019-05-13 11:10:24 +00:00
|
|
|
if (depth) {
|
|
|
|
depth--;
|
|
|
|
break;
|
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
if (in_q) {
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
break;
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
if (!br && lc != '\"' && *(p-1) == '?') {
|
|
|
|
in_q = state = 0;
|
|
|
|
tp = tbuf;
|
|
|
|
p++;
|
|
|
|
goto state_0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
case '\'':
|
|
|
|
if (*(p-1) != '\\') {
|
|
|
|
if (lc == c) {
|
|
|
|
lc = '\0';
|
|
|
|
} else if (lc != '\\') {
|
|
|
|
lc = c;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2019-08-02 15:03:20 +00:00
|
|
|
if (p != buf && (!in_q || *p == in_q)) {
|
2007-02-27 00:15:21 +00:00
|
|
|
if (in_q) {
|
|
|
|
in_q = 0;
|
|
|
|
} else {
|
|
|
|
in_q = *p;
|
|
|
|
}
|
2007-02-13 02:16:22 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
case 'L':
|
|
|
|
/* swm: If we encounter '<?xml' then we shouldn't be in
|
|
|
|
* state == 2 (PHP). Switch back to HTML.
|
|
|
|
*/
|
|
|
|
if (state == 2 && p > buf+4
|
|
|
|
&& (*(p-1) == 'm' || *(p-1) == 'M')
|
|
|
|
&& (*(p-2) == 'x' || *(p-2) == 'X')
|
|
|
|
&& *(p-3) == '?'
|
|
|
|
&& *(p-4) == '<') {
|
|
|
|
state = 1; is_xml=1;
|
|
|
|
p++;
|
|
|
|
goto state_1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
goto state_2;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
state_3:
|
|
|
|
if (p >= end) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
c = *p;
|
|
|
|
switch (c) {
|
|
|
|
case '>':
|
2019-05-13 11:10:24 +00:00
|
|
|
if (depth) {
|
|
|
|
depth--;
|
|
|
|
break;
|
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
if (in_q) {
|
2002-09-21 17:34:06 +00:00
|
|
|
break;
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
|
|
|
in_q = state = 0;
|
|
|
|
tp = tbuf;
|
|
|
|
p++;
|
|
|
|
goto state_0;
|
|
|
|
case '"':
|
|
|
|
case '\'':
|
|
|
|
if (p != buf && *(p-1) != '\\' && (!in_q || *p == in_q)) {
|
|
|
|
if (in_q) {
|
|
|
|
in_q = 0;
|
2003-05-16 06:19:51 +00:00
|
|
|
} else {
|
2018-07-16 10:22:17 +00:00
|
|
|
in_q = *p;
|
2001-08-22 05:47:11 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '!') {
|
|
|
|
state = 4;
|
|
|
|
p++;
|
|
|
|
goto state_4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
case 'e':
|
|
|
|
/* !DOCTYPE exception */
|
|
|
|
if (p > buf+6
|
|
|
|
&& (*(p-1) == 'p' || *(p-1) == 'P')
|
|
|
|
&& (*(p-2) == 'y' || *(p-2) == 'Y')
|
|
|
|
&& (*(p-3) == 't' || *(p-3) == 'T')
|
|
|
|
&& (*(p-4) == 'c' || *(p-4) == 'C')
|
|
|
|
&& (*(p-5) == 'o' || *(p-5) == 'O')
|
|
|
|
&& (*(p-6) == 'd' || *(p-6) == 'D')) {
|
|
|
|
state = 1;
|
|
|
|
p++;
|
|
|
|
goto state_1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
goto state_3;
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
|
2018-07-16 10:22:17 +00:00
|
|
|
state_4:
|
|
|
|
while (p < end) {
|
|
|
|
c = *p;
|
|
|
|
if (c == '>' && !in_q) {
|
|
|
|
if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '-') {
|
|
|
|
in_q = state = 0;
|
|
|
|
tp = tbuf;
|
|
|
|
p++;
|
|
|
|
goto state_0;
|
|
|
|
}
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
p++;
|
2012-01-02 00:47:57 +00:00
|
|
|
}
|
2018-07-16 10:22:17 +00:00
|
|
|
|
|
|
|
finish:
|
2003-02-24 22:19:36 +00:00
|
|
|
if (rp < rbuf + len) {
|
|
|
|
*rp = '\0';
|
|
|
|
}
|
2018-03-17 11:45:22 +00:00
|
|
|
efree((void *)buf);
|
2019-04-12 12:55:37 +00:00
|
|
|
if (tbuf) {
|
2002-10-02 17:56:04 +00:00
|
|
|
efree(tbuf);
|
2019-04-12 12:55:37 +00:00
|
|
|
}
|
|
|
|
if (allow_free) {
|
|
|
|
efree(allow_free);
|
2010-04-20 11:05:54 +00:00
|
|
|
}
|
2002-03-20 14:38:13 +00:00
|
|
|
if (stateptr)
|
|
|
|
*stateptr = state;
|
2003-02-24 22:01:12 +00:00
|
|
|
|
|
|
|
return (size_t)(rp - rbuf);
|
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-16 17:06:53 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
1999-04-17 00:37:12 +00:00
|
|
|
|
2008-11-02 18:24:34 +00:00
|
|
|
/* {{{ proto array str_getcsv(string input[, string delimiter[, string enclosure[, string escape]]])
|
|
|
|
Parse a CSV string into an array */
|
|
|
|
PHP_FUNCTION(str_getcsv)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
Allow empty $escape to eschew escaping CSV
Albeit CSV is still a widespread data exchange format, it has never been
officially standardized. There exists, however, the “informational” RFC
4180[1] which has no notion of escape characters, but rather defines
`escaped` as strings enclosed in double-quotes where contained
double-quotes have to be doubled. While this concept is supported by
PHP's implementation (`$enclosure`), the `$escape` sometimes interferes,
so that `fgetcsv()` is unable to correctly parse externally generated
CSV, and `fputcsv()` is sometimes generating non-compliant CSV. Since
PHP's `$escape` concept is availble for many years, we cannot drop it
for BC reasons (even though many consider it as bug). Instead we allow
to pass an empty string as `$escape` parameter to the respective
functions, which results in ignoring/omitting any escaping, and as such
is more inline with RFC 4180. It is noteworthy that this is almost no
userland BC break, since formerly most functions did not accept an empty
string, and failed in this case. The only exception was `str_getcsv()`
which did accept an empty string, and used a backslash as escape
character then (which appears to be unintended behavior, anyway).
The changed functions are `fputcsv()`, `fgetcsv()` and `str_getcsv()`,
and also the `::setCsvControl()`, `::getCsvControl()`, `::fputcsv()`,
and `::fgetcsv()` methods of `SplFileObject`.
The implementation also changes the type of the escape parameter of the
PHP_APIs `php_fgetcsv()` and `php_fputcsv()` from `char` to `int`, where
`PHP_CSV_NO_ESCAPE` means to ignore/omit escaping. The parameter
accepts the same values as `isalpha()` and friends, i.e. “the value of
which shall be representable as an `unsigned char` or shall equal the
value of the macro `EOF`. If the argument has any other value, the
behavior is undefined.” This is a subtle BC break, since the character
`chr(128)` has the value `-1` if `char` is signed, and so likely would
be confused with `EOF` when converted to `int`. We consider this BC
break to be acceptable, since it's rather unlikely that anybody uses
`chr(128)` as escape character, and it easily can be fixed by casting
all `escape` arguments to `unsigned char`.
This patch implements the feature requests 38301[2] and 51496[3].
[1] <https://tools.ietf.org/html/rfc4180>
[2] <https://bugs.php.net/bug.php?id=38301>
[3] <https://bugs.php.net/bug.php?id=51496>
2018-12-02 15:28:18 +00:00
|
|
|
char delim = ',', enc = '"';
|
|
|
|
int esc = (unsigned char) '\\';
|
2008-11-02 18:24:34 +00:00
|
|
|
char *delim_str = NULL, *enc_str = NULL, *esc_str = NULL;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t delim_len = 0, enc_len = 0, esc_len = 0;
|
2008-11-02 18:24:34 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 4)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STRING(delim_str, delim_len)
|
|
|
|
Z_PARAM_STRING(enc_str, enc_len)
|
|
|
|
Z_PARAM_STRING(esc_str, esc_len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-11-02 18:24:34 +00:00
|
|
|
delim = delim_len ? delim_str[0] : delim;
|
|
|
|
enc = enc_len ? enc_str[0] : enc;
|
Allow empty $escape to eschew escaping CSV
Albeit CSV is still a widespread data exchange format, it has never been
officially standardized. There exists, however, the “informational” RFC
4180[1] which has no notion of escape characters, but rather defines
`escaped` as strings enclosed in double-quotes where contained
double-quotes have to be doubled. While this concept is supported by
PHP's implementation (`$enclosure`), the `$escape` sometimes interferes,
so that `fgetcsv()` is unable to correctly parse externally generated
CSV, and `fputcsv()` is sometimes generating non-compliant CSV. Since
PHP's `$escape` concept is availble for many years, we cannot drop it
for BC reasons (even though many consider it as bug). Instead we allow
to pass an empty string as `$escape` parameter to the respective
functions, which results in ignoring/omitting any escaping, and as such
is more inline with RFC 4180. It is noteworthy that this is almost no
userland BC break, since formerly most functions did not accept an empty
string, and failed in this case. The only exception was `str_getcsv()`
which did accept an empty string, and used a backslash as escape
character then (which appears to be unintended behavior, anyway).
The changed functions are `fputcsv()`, `fgetcsv()` and `str_getcsv()`,
and also the `::setCsvControl()`, `::getCsvControl()`, `::fputcsv()`,
and `::fgetcsv()` methods of `SplFileObject`.
The implementation also changes the type of the escape parameter of the
PHP_APIs `php_fgetcsv()` and `php_fputcsv()` from `char` to `int`, where
`PHP_CSV_NO_ESCAPE` means to ignore/omit escaping. The parameter
accepts the same values as `isalpha()` and friends, i.e. “the value of
which shall be representable as an `unsigned char` or shall equal the
value of the macro `EOF`. If the argument has any other value, the
behavior is undefined.” This is a subtle BC break, since the character
`chr(128)` has the value `-1` if `char` is signed, and so likely would
be confused with `EOF` when converted to `int`. We consider this BC
break to be acceptable, since it's rather unlikely that anybody uses
`chr(128)` as escape character, and it easily can be fixed by casting
all `escape` arguments to `unsigned char`.
This patch implements the feature requests 38301[2] and 51496[3].
[1] <https://tools.ietf.org/html/rfc4180>
[2] <https://bugs.php.net/bug.php?id=38301>
[3] <https://bugs.php.net/bug.php?id=51496>
2018-12-02 15:28:18 +00:00
|
|
|
if (esc_str != NULL) {
|
|
|
|
esc = esc_len ? (unsigned char) esc_str[0] : PHP_CSV_NO_ESCAPE;
|
|
|
|
}
|
2008-11-02 18:24:34 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
php_fgetcsv(NULL, delim, enc, esc, ZSTR_LEN(str), ZSTR_VAL(str), return_value);
|
2008-11-02 18:24:34 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
1999-10-27 22:06:05 +00:00
|
|
|
/* {{{ proto string str_repeat(string input, int mult)
|
|
|
|
Returns the input string repeat mult times */
|
|
|
|
PHP_FUNCTION(str_repeat)
|
|
|
|
{
|
2014-08-16 10:55:13 +00:00
|
|
|
zend_string *input_str; /* Input string */
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long mult; /* Multiplier */
|
2014-02-18 12:27:38 +00:00
|
|
|
zend_string *result; /* Resulting string */
|
2006-08-10 14:40:13 +00:00
|
|
|
size_t result_len; /* Length of the resulting string */
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(input_str)
|
2016-12-31 01:09:35 +00:00
|
|
|
Z_PARAM_LONG(mult)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-25 12:16:17 +00:00
|
|
|
|
|
|
|
if (mult < 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0");
|
1999-10-27 22:06:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't waste our time if it's empty */
|
2000-09-05 18:25:58 +00:00
|
|
|
/* ... or if the multiplier is zero */
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(input_str) == 0 || mult == 0)
|
2008-06-25 12:16:17 +00:00
|
|
|
RETURN_EMPTY_STRING();
|
|
|
|
|
2012-01-02 00:47:57 +00:00
|
|
|
/* Initialize the result string */
|
2015-06-30 01:05:24 +00:00
|
|
|
result = zend_string_safe_alloc(ZSTR_LEN(input_str), mult, 0, 0);
|
|
|
|
result_len = ZSTR_LEN(input_str) * mult;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-04 17:10:51 +00:00
|
|
|
/* Heavy optimization for situations where input string is 1 byte long */
|
2015-06-30 01:05:24 +00:00
|
|
|
if (ZSTR_LEN(input_str) == 1) {
|
|
|
|
memset(ZSTR_VAL(result), *ZSTR_VAL(input_str), mult);
|
2002-10-03 13:59:31 +00:00
|
|
|
} else {
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *s, *ee;
|
|
|
|
char *e;
|
2014-08-16 10:55:13 +00:00
|
|
|
ptrdiff_t l=0;
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result), ZSTR_VAL(input_str), ZSTR_LEN(input_str));
|
|
|
|
s = ZSTR_VAL(result);
|
|
|
|
e = ZSTR_VAL(result) + ZSTR_LEN(input_str);
|
|
|
|
ee = ZSTR_VAL(result) + result_len;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-03 13:59:31 +00:00
|
|
|
while (e<ee) {
|
|
|
|
l = (e-s) < (ee-e) ? (e-s) : (ee-e);
|
|
|
|
memmove(e, s, l);
|
|
|
|
e += l;
|
|
|
|
}
|
1999-10-27 22:06:05 +00:00
|
|
|
}
|
2002-10-03 13:59:31 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[result_len] = '\0';
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(result);
|
1999-10-27 22:06:05 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto array|string|false count_chars(string input [, int mode])
|
1999-12-14 03:52:12 +00:00
|
|
|
Returns info about what characters are used in input */
|
|
|
|
PHP_FUNCTION(count_chars)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *input;
|
1999-12-14 03:52:12 +00:00
|
|
|
int chars[256];
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long mymode=0;
|
2018-03-17 11:45:22 +00:00
|
|
|
const unsigned char *buf;
|
2014-08-18 13:39:38 +00:00
|
|
|
int inx;
|
1999-12-14 03:52:12 +00:00
|
|
|
char retstr[256];
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t retlen=0;
|
|
|
|
size_t tmp = 0;
|
1999-12-14 03:52:12 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STR(input)
|
|
|
|
Z_PARAM_OPTIONAL
|
2016-12-31 01:09:35 +00:00
|
|
|
Z_PARAM_LONG(mymode)
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
1999-12-14 03:52:12 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
if (mymode < 0 || mymode > 4) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Unknown mode");
|
2008-06-25 12:16:17 +00:00
|
|
|
RETURN_FALSE;
|
1999-12-14 03:52:12 +00:00
|
|
|
}
|
2008-06-25 12:16:17 +00:00
|
|
|
|
2018-03-17 11:45:22 +00:00
|
|
|
buf = (const unsigned char *) ZSTR_VAL(input);
|
2001-08-11 17:03:37 +00:00
|
|
|
memset((void*) chars, 0, sizeof(chars));
|
1999-12-14 03:52:12 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
while (tmp < ZSTR_LEN(input)) {
|
1999-12-14 03:52:12 +00:00
|
|
|
chars[*buf]++;
|
|
|
|
buf++;
|
2014-08-20 13:51:45 +00:00
|
|
|
tmp++;
|
1999-12-14 03:52:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mymode < 3) {
|
|
|
|
array_init(return_value);
|
|
|
|
}
|
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
for (inx = 0; inx < 256; inx++) {
|
1999-12-14 03:52:12 +00:00
|
|
|
switch (mymode) {
|
2002-10-03 18:15:18 +00:00
|
|
|
case 0:
|
2014-08-25 17:24:55 +00:00
|
|
|
add_index_long(return_value, inx, chars[inx]);
|
2002-10-03 18:15:18 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (chars[inx] != 0) {
|
2014-08-25 17:24:55 +00:00
|
|
|
add_index_long(return_value, inx, chars[inx]);
|
2002-10-03 18:15:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (chars[inx] == 0) {
|
2014-08-25 17:24:55 +00:00
|
|
|
add_index_long(return_value, inx, chars[inx]);
|
2002-10-03 18:15:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (chars[inx] != 0) {
|
|
|
|
retstr[retlen++] = inx;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
if (chars[inx] == 0) {
|
|
|
|
retstr[retlen++] = inx;
|
|
|
|
}
|
|
|
|
break;
|
1999-12-14 03:52:12 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
1999-12-14 03:52:12 +00:00
|
|
|
if (mymode >= 3 && mymode <= 4) {
|
2014-02-10 13:49:21 +00:00
|
|
|
RETURN_STRINGL(retstr, retlen);
|
1999-12-14 03:52:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
2000-04-12 19:39:02 +00:00
|
|
|
|
2001-06-05 13:12:10 +00:00
|
|
|
/* {{{ php_strnatcmp
|
|
|
|
*/
|
2000-04-12 19:39:02 +00:00
|
|
|
static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *s1, *s2;
|
2000-04-12 19:39:02 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-04-12 19:39:02 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(strnatcmp_ex(ZSTR_VAL(s1), ZSTR_LEN(s1),
|
|
|
|
ZSTR_VAL(s2), ZSTR_LEN(s2),
|
2000-04-12 19:39:02 +00:00
|
|
|
fold_case));
|
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2000-04-26 00:29:59 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
PHPAPI int string_natural_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive) /* {{{ */
|
2011-08-29 20:23:34 +00:00
|
|
|
{
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_string *tmp_str1, *tmp_str2;
|
|
|
|
zend_string *str1 = zval_get_tmp_string(op1, &tmp_str1);
|
|
|
|
zend_string *str2 = zval_get_tmp_string(op2, &tmp_str2);
|
2011-08-29 20:23:34 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZVAL_LONG(result, strnatcmp_ex(ZSTR_VAL(str1), ZSTR_LEN(str1), ZSTR_VAL(str2), ZSTR_LEN(str2), case_insensitive));
|
2011-08-29 20:23:34 +00:00
|
|
|
|
2017-11-16 14:09:32 +00:00
|
|
|
zend_tmp_string_release(tmp_str1);
|
|
|
|
zend_tmp_string_release(tmp_str2);
|
2011-08-29 20:23:34 +00:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
PHPAPI int string_natural_case_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
|
2011-08-29 20:23:34 +00:00
|
|
|
{
|
2014-12-13 22:06:14 +00:00
|
|
|
return string_natural_compare_function_ex(result, op1, op2, 1);
|
2011-08-29 20:23:34 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
PHPAPI int string_natural_compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
|
2011-08-29 20:23:34 +00:00
|
|
|
{
|
2014-12-13 22:06:14 +00:00
|
|
|
return string_natural_compare_function_ex(result, op1, op2, 0);
|
2011-08-29 20:23:34 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2000-04-26 00:29:59 +00:00
|
|
|
/* {{{ proto int strnatcmp(string s1, string s2)
|
|
|
|
Returns the result of string comparison using 'natural' algorithm */
|
2000-04-12 19:39:02 +00:00
|
|
|
PHP_FUNCTION(strnatcmp)
|
|
|
|
{
|
|
|
|
php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
|
|
|
}
|
2000-04-26 00:29:59 +00:00
|
|
|
/* }}} */
|
2000-04-12 19:39:02 +00:00
|
|
|
|
2001-09-04 10:44:28 +00:00
|
|
|
/* {{{ proto array localeconv(void)
|
2001-04-29 13:30:56 +00:00
|
|
|
Returns numeric formatting information based on the current locale */
|
2001-01-14 16:36:30 +00:00
|
|
|
PHP_FUNCTION(localeconv)
|
|
|
|
{
|
2014-02-10 13:49:21 +00:00
|
|
|
zval grouping, mon_grouping;
|
2001-01-14 16:36:30 +00:00
|
|
|
int len, i;
|
|
|
|
|
|
|
|
/* We don't need no stinkin' parameters... */
|
2008-03-10 22:15:36 +00:00
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
|
|
return;
|
2001-01-14 16:36:30 +00:00
|
|
|
}
|
|
|
|
|
2002-12-05 22:28:02 +00:00
|
|
|
array_init(return_value);
|
2014-02-10 13:49:21 +00:00
|
|
|
array_init(&grouping);
|
|
|
|
array_init(&mon_grouping);
|
2001-01-14 16:36:30 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
struct lconv currlocdata;
|
|
|
|
|
|
|
|
localeconv_r( &currlocdata );
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2001-01-14 16:36:30 +00:00
|
|
|
/* Grab the grouping data out of the array */
|
2014-10-24 11:12:59 +00:00
|
|
|
len = (int)strlen(currlocdata.grouping);
|
2001-01-14 16:36:30 +00:00
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2014-08-25 17:24:55 +00:00
|
|
|
add_index_long(&grouping, i, currlocdata.grouping[i]);
|
2001-01-14 16:36:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Grab the monetary grouping data out of the array */
|
2014-10-24 11:12:59 +00:00
|
|
|
len = (int)strlen(currlocdata.mon_grouping);
|
2001-01-14 16:36:30 +00:00
|
|
|
|
2002-10-02 17:56:04 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2014-08-25 17:24:55 +00:00
|
|
|
add_index_long(&mon_grouping, i, currlocdata.mon_grouping[i]);
|
2001-01-14 16:36:30 +00:00
|
|
|
}
|
|
|
|
|
2014-04-15 11:40:40 +00:00
|
|
|
add_assoc_string(return_value, "decimal_point", currlocdata.decimal_point);
|
|
|
|
add_assoc_string(return_value, "thousands_sep", currlocdata.thousands_sep);
|
|
|
|
add_assoc_string(return_value, "int_curr_symbol", currlocdata.int_curr_symbol);
|
|
|
|
add_assoc_string(return_value, "currency_symbol", currlocdata.currency_symbol);
|
|
|
|
add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point);
|
|
|
|
add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep);
|
|
|
|
add_assoc_string(return_value, "positive_sign", currlocdata.positive_sign);
|
|
|
|
add_assoc_string(return_value, "negative_sign", currlocdata.negative_sign);
|
2014-08-25 17:24:55 +00:00
|
|
|
add_assoc_long( return_value, "int_frac_digits", currlocdata.int_frac_digits);
|
|
|
|
add_assoc_long( return_value, "frac_digits", currlocdata.frac_digits);
|
|
|
|
add_assoc_long( return_value, "p_cs_precedes", currlocdata.p_cs_precedes);
|
|
|
|
add_assoc_long( return_value, "p_sep_by_space", currlocdata.p_sep_by_space);
|
|
|
|
add_assoc_long( return_value, "n_cs_precedes", currlocdata.n_cs_precedes);
|
|
|
|
add_assoc_long( return_value, "n_sep_by_space", currlocdata.n_sep_by_space);
|
|
|
|
add_assoc_long( return_value, "p_sign_posn", currlocdata.p_sign_posn);
|
|
|
|
add_assoc_long( return_value, "n_sign_posn", currlocdata.n_sign_posn);
|
2001-01-14 16:36:30 +00:00
|
|
|
}
|
|
|
|
|
2014-02-10 13:49:21 +00:00
|
|
|
zend_hash_str_update(Z_ARRVAL_P(return_value), "grouping", sizeof("grouping")-1, &grouping);
|
|
|
|
zend_hash_str_update(Z_ARRVAL_P(return_value), "mon_grouping", sizeof("mon_grouping")-1, &mon_grouping);
|
2001-01-14 16:36:30 +00:00
|
|
|
}
|
2001-06-05 13:12:10 +00:00
|
|
|
/* }}} */
|
2000-04-26 00:29:59 +00:00
|
|
|
|
|
|
|
/* {{{ proto int strnatcasecmp(string s1, string s2)
|
|
|
|
Returns the result of case-insensitive string comparison using 'natural' algorithm */
|
2000-04-12 19:39:02 +00:00
|
|
|
PHP_FUNCTION(strnatcasecmp)
|
|
|
|
{
|
|
|
|
php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
|
|
|
}
|
2000-04-26 00:29:59 +00:00
|
|
|
/* }}} */
|
|
|
|
|
2019-05-30 18:03:28 +00:00
|
|
|
/* {{{ proto int|false substr_count(string haystack, string needle [, int offset [, int length]])
|
2000-08-06 14:36:10 +00:00
|
|
|
Returns the number of times a substring occurs in the string */
|
2000-04-26 00:29:59 +00:00
|
|
|
PHP_FUNCTION(substr_count)
|
|
|
|
{
|
2008-06-25 12:16:17 +00:00
|
|
|
char *haystack, *needle;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long offset = 0, length = 0;
|
2005-06-18 18:23:12 +00:00
|
|
|
int ac = ZEND_NUM_ARGS();
|
2018-01-09 08:20:19 +00:00
|
|
|
zend_long count = 0;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t haystack_len, needle_len;
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *p, *endp;
|
|
|
|
char cmp;
|
2000-04-26 00:29:59 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 4)
|
|
|
|
Z_PARAM_STRING(haystack, haystack_len)
|
|
|
|
Z_PARAM_STRING(needle, needle_len)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(offset)
|
|
|
|
Z_PARAM_LONG(length)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-04-26 00:29:59 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
if (needle_len == 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Empty substring");
|
2000-04-26 00:29:59 +00:00
|
|
|
RETURN_FALSE;
|
2002-10-09 13:37:02 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
p = haystack;
|
|
|
|
endp = p + haystack_len;
|
|
|
|
|
|
|
|
if (offset < 0) {
|
2015-07-23 02:01:23 +00:00
|
|
|
offset += (zend_long)haystack_len;
|
2008-06-25 12:16:17 +00:00
|
|
|
}
|
2015-07-23 02:01:23 +00:00
|
|
|
if ((offset < 0) || ((size_t)offset > haystack_len)) {
|
|
|
|
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
|
2012-01-02 00:47:57 +00:00
|
|
|
RETURN_FALSE;
|
2008-06-25 12:16:17 +00:00
|
|
|
}
|
|
|
|
p += offset;
|
|
|
|
|
|
|
|
if (ac == 4) {
|
|
|
|
|
2017-02-03 16:54:39 +00:00
|
|
|
if (length < 0) {
|
2015-07-23 02:01:23 +00:00
|
|
|
length += (haystack_len - offset);
|
2005-06-18 18:23:12 +00:00
|
|
|
}
|
2017-02-03 16:54:39 +00:00
|
|
|
if (length < 0 || ((size_t)length > (haystack_len - offset))) {
|
2015-07-23 02:01:23 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid length value");
|
2008-06-25 12:16:17 +00:00
|
|
|
RETURN_FALSE;
|
2005-06-18 18:23:12 +00:00
|
|
|
}
|
2008-06-25 12:16:17 +00:00
|
|
|
endp = p + length;
|
2005-06-18 18:23:12 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
if (needle_len == 1) {
|
|
|
|
cmp = needle[0];
|
2005-06-19 16:31:51 +00:00
|
|
|
|
|
|
|
while ((p = memchr(p, cmp, endp - p))) {
|
|
|
|
count++;
|
|
|
|
p++;
|
2000-04-26 00:29:59 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-02-10 13:49:21 +00:00
|
|
|
while ((p = (char*)php_memnstr(p, needle, needle_len, endp))) {
|
2008-06-25 12:16:17 +00:00
|
|
|
p += needle_len;
|
2002-10-09 13:37:02 +00:00
|
|
|
count++;
|
2000-04-26 00:29:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(count);
|
2000-04-26 00:29:59 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
/* }}} */
|
2000-06-06 20:42:33 +00:00
|
|
|
|
2000-07-08 22:55:40 +00:00
|
|
|
/* {{{ proto string str_pad(string input, int pad_length [, string pad_string [, int pad_type]])
|
2000-06-06 20:42:33 +00:00
|
|
|
Returns input string padded on the left or right to specified length with pad_string */
|
|
|
|
PHP_FUNCTION(str_pad)
|
|
|
|
{
|
2000-07-08 20:38:23 +00:00
|
|
|
/* Input arguments */
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *input; /* Input string */
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long pad_length; /* Length to pad to */
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2000-07-08 20:38:23 +00:00
|
|
|
/* Helper variables */
|
2014-02-24 09:44:42 +00:00
|
|
|
size_t num_pad_chars; /* Number of padding characters (total - input size) */
|
2014-08-27 15:31:24 +00:00
|
|
|
char *pad_str = " "; /* Pointer to padding string */
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t pad_str_len = 1;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long pad_type_val = STR_PAD_RIGHT; /* The padding type value */
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t i, left_pad=0, right_pad=0;
|
2014-02-24 09:44:42 +00:00
|
|
|
zend_string *result = NULL; /* Resulting string */
|
2000-06-06 20:42:33 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 4)
|
|
|
|
Z_PARAM_STR(input)
|
|
|
|
Z_PARAM_LONG(pad_length)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_STRING(pad_str, pad_str_len)
|
|
|
|
Z_PARAM_LONG(pad_type_val)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2000-06-06 20:42:33 +00:00
|
|
|
|
|
|
|
/* If resulting string turns out to be shorter than input string,
|
|
|
|
we simply copy the input and return. */
|
2015-06-30 01:05:24 +00:00
|
|
|
if (pad_length < 0 || (size_t)pad_length <= ZSTR_LEN(input)) {
|
2018-02-26 08:48:49 +00:00
|
|
|
RETURN_STR_COPY(input);
|
2000-06-06 20:42:33 +00:00
|
|
|
}
|
|
|
|
|
2014-08-27 13:31:48 +00:00
|
|
|
if (pad_str_len == 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Padding string cannot be empty");
|
2008-06-25 12:16:17 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2008-06-25 12:16:17 +00:00
|
|
|
if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH");
|
2008-06-25 12:16:17 +00:00
|
|
|
return;
|
2000-06-06 20:42:33 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
num_pad_chars = pad_length - ZSTR_LEN(input);
|
2014-08-27 17:25:28 +00:00
|
|
|
if (num_pad_chars >= INT_MAX) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Padding length is too long");
|
2012-01-02 00:47:57 +00:00
|
|
|
return;
|
2010-08-06 19:55:10 +00:00
|
|
|
}
|
2014-02-24 09:44:42 +00:00
|
|
|
|
2016-04-27 04:23:51 +00:00
|
|
|
result = zend_string_safe_alloc(1, ZSTR_LEN(input), num_pad_chars, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_LEN(result) = 0;
|
2000-06-06 20:42:33 +00:00
|
|
|
|
2000-07-08 20:38:23 +00:00
|
|
|
/* We need to figure out the left/right padding lengths. */
|
|
|
|
switch (pad_type_val) {
|
|
|
|
case STR_PAD_RIGHT:
|
|
|
|
left_pad = 0;
|
|
|
|
right_pad = num_pad_chars;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STR_PAD_LEFT:
|
|
|
|
left_pad = num_pad_chars;
|
|
|
|
right_pad = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STR_PAD_BOTH:
|
|
|
|
left_pad = num_pad_chars / 2;
|
|
|
|
right_pad = num_pad_chars - left_pad;
|
|
|
|
break;
|
2000-06-06 20:42:33 +00:00
|
|
|
}
|
|
|
|
|
2000-07-08 20:38:23 +00:00
|
|
|
/* First we pad on the left. */
|
|
|
|
for (i = 0; i < left_pad; i++)
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len];
|
2000-07-08 20:38:23 +00:00
|
|
|
|
|
|
|
/* Then we copy the input string. */
|
2015-06-30 01:05:24 +00:00
|
|
|
memcpy(ZSTR_VAL(result) + ZSTR_LEN(result), ZSTR_VAL(input), ZSTR_LEN(input));
|
|
|
|
ZSTR_LEN(result) += ZSTR_LEN(input);
|
2000-07-08 20:38:23 +00:00
|
|
|
|
|
|
|
/* Finally, we pad on the right. */
|
|
|
|
for (i = 0; i < right_pad; i++)
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[ZSTR_LEN(result)++] = pad_str[i % pad_str_len];
|
2000-06-06 20:42:33 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
|
2000-06-06 20:42:33 +00:00
|
|
|
|
2014-04-03 11:26:23 +00:00
|
|
|
RETURN_NEW_STR(result);
|
2000-06-06 20:42:33 +00:00
|
|
|
}
|
2000-06-06 18:58:15 +00:00
|
|
|
/* }}} */
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2000-07-09 19:33:19 +00:00
|
|
|
/* {{{ proto mixed sscanf(string str, string format [, string ...])
|
|
|
|
Implements an ANSI C compatible sscanf */
|
2000-06-06 18:58:15 +00:00
|
|
|
PHP_FUNCTION(sscanf)
|
|
|
|
{
|
2014-02-13 13:54:23 +00:00
|
|
|
zval *args = NULL;
|
2008-08-16 21:32:41 +00:00
|
|
|
char *str, *format;
|
2014-08-28 17:35:37 +00:00
|
|
|
size_t str_len, format_len;
|
|
|
|
int result, num_args = 0;
|
2001-09-03 04:49:36 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, -1)
|
|
|
|
Z_PARAM_STRING(str, str_len)
|
|
|
|
Z_PARAM_STRING(format, format_len)
|
|
|
|
Z_PARAM_VARIADIC('*', args, num_args)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
result = php_sscanf_internal(str, format, num_args, args, 0, return_value);
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2000-06-06 18:58:15 +00:00
|
|
|
if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
|
2000-06-12 16:06:27 +00:00
|
|
|
WRONG_PARAM_COUNT;
|
2000-06-06 18:58:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2018-03-16 05:23:35 +00:00
|
|
|
/* static zend_string *php_str_rot13(zend_string *str) {{{ */
|
2018-03-16 02:52:57 +00:00
|
|
|
#ifdef __SSE2__
|
|
|
|
#include <emmintrin.h>
|
|
|
|
#endif
|
|
|
|
static zend_string *php_str_rot13(zend_string *str)
|
|
|
|
{
|
|
|
|
zend_string *ret;
|
|
|
|
const char *p, *e;
|
|
|
|
char *target;
|
|
|
|
|
|
|
|
if (UNEXPECTED(ZSTR_LEN(str) == 0)) {
|
|
|
|
return ZSTR_EMPTY_ALLOC();
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = zend_string_alloc(ZSTR_LEN(str), 0);
|
|
|
|
|
|
|
|
p = ZSTR_VAL(str);
|
|
|
|
e = p + ZSTR_LEN(str);
|
|
|
|
target = ZSTR_VAL(ret);
|
|
|
|
|
|
|
|
#ifdef __SSE2__
|
|
|
|
if (e - p > 15) {
|
2018-04-04 22:06:26 +00:00
|
|
|
const __m128i a_minus_1 = _mm_set1_epi8('a' - 1);
|
|
|
|
const __m128i m_plus_1 = _mm_set1_epi8('m' + 1);
|
|
|
|
const __m128i n_minus_1 = _mm_set1_epi8('n' - 1);
|
|
|
|
const __m128i z_plus_1 = _mm_set1_epi8('z' + 1);
|
|
|
|
const __m128i A_minus_1 = _mm_set1_epi8('A' - 1);
|
|
|
|
const __m128i M_plus_1 = _mm_set1_epi8('M' + 1);
|
|
|
|
const __m128i N_minus_1 = _mm_set1_epi8('N' - 1);
|
|
|
|
const __m128i Z_plus_1 = _mm_set1_epi8('Z' + 1);
|
2018-03-16 02:52:57 +00:00
|
|
|
const __m128i add = _mm_set1_epi8(13);
|
|
|
|
const __m128i sub = _mm_set1_epi8(-13);
|
|
|
|
|
|
|
|
do {
|
|
|
|
__m128i in, gt, lt, cmp, delta;
|
|
|
|
|
|
|
|
delta = _mm_setzero_si128();
|
|
|
|
in = _mm_loadu_si128((__m128i *)p);
|
|
|
|
|
2018-04-04 22:06:26 +00:00
|
|
|
gt = _mm_cmpgt_epi8(in, a_minus_1);
|
|
|
|
lt = _mm_cmplt_epi8(in, m_plus_1);
|
2018-03-16 02:52:57 +00:00
|
|
|
cmp = _mm_and_si128(lt, gt);
|
|
|
|
if (_mm_movemask_epi8(cmp)) {
|
|
|
|
cmp = _mm_and_si128(cmp, add);
|
|
|
|
delta = _mm_or_si128(delta, cmp);
|
|
|
|
}
|
|
|
|
|
2018-04-04 22:06:26 +00:00
|
|
|
gt = _mm_cmpgt_epi8(in, n_minus_1);
|
|
|
|
lt = _mm_cmplt_epi8(in, z_plus_1);
|
2018-03-16 02:52:57 +00:00
|
|
|
cmp = _mm_and_si128(lt, gt);
|
|
|
|
if (_mm_movemask_epi8(cmp)) {
|
|
|
|
cmp = _mm_and_si128(cmp, sub);
|
|
|
|
delta = _mm_or_si128(delta, cmp);
|
|
|
|
}
|
|
|
|
|
2018-04-04 22:06:26 +00:00
|
|
|
gt = _mm_cmpgt_epi8(in, A_minus_1);
|
|
|
|
lt = _mm_cmplt_epi8(in, M_plus_1);
|
2018-03-16 02:52:57 +00:00
|
|
|
cmp = _mm_and_si128(lt, gt);
|
|
|
|
if (_mm_movemask_epi8(cmp)) {
|
|
|
|
cmp = _mm_and_si128(cmp, add);
|
|
|
|
delta = _mm_or_si128(delta, cmp);
|
|
|
|
}
|
|
|
|
|
2018-04-04 22:06:26 +00:00
|
|
|
gt = _mm_cmpgt_epi8(in, N_minus_1);
|
|
|
|
lt = _mm_cmplt_epi8(in, Z_plus_1);
|
2018-03-16 02:52:57 +00:00
|
|
|
cmp = _mm_and_si128(lt, gt);
|
|
|
|
if (_mm_movemask_epi8(cmp)) {
|
|
|
|
cmp = _mm_and_si128(cmp, sub);
|
|
|
|
delta = _mm_or_si128(delta, cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
in = _mm_add_epi8(in, delta);
|
|
|
|
_mm_storeu_si128((__m128i *)target, in);
|
|
|
|
|
|
|
|
p += 16;
|
|
|
|
target += 16;
|
|
|
|
} while (e - p > 15);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
while (p < e) {
|
|
|
|
if (*p >= 'a' && *p <= 'z') {
|
|
|
|
*target++ = 'a' + (((*p++ - 'a') + 13) % 26);
|
|
|
|
} else if (*p >= 'A' && *p <= 'Z') {
|
|
|
|
*target++ = 'A' + (((*p++ - 'A') + 13) % 26);
|
|
|
|
} else {
|
|
|
|
*target++ = *p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*target = '\0';
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
2002-08-20 20:47:47 +00:00
|
|
|
|
2001-12-06 21:39:01 +00:00
|
|
|
/* {{{ proto string str_rot13(string str)
|
2001-12-06 19:02:27 +00:00
|
|
|
Perform the rot13 transform on a string */
|
2001-12-06 21:39:01 +00:00
|
|
|
PHP_FUNCTION(str_rot13)
|
2001-12-06 19:02:27 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *arg;
|
2002-07-30 10:51:33 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(arg)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2006-01-28 00:14:01 +00:00
|
|
|
|
2018-03-16 02:52:57 +00:00
|
|
|
RETURN_STR(php_str_rot13(arg));
|
2001-12-06 19:02:27 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2014-12-13 22:06:14 +00:00
|
|
|
static void php_string_shuffle(char *str, zend_long len) /* {{{ */
|
2002-09-25 18:06:05 +00:00
|
|
|
{
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long n_elems, rnd_idx, n_left;
|
2002-10-08 09:52:59 +00:00
|
|
|
char temp;
|
|
|
|
/* The implementation is stolen from array_data_shuffle */
|
|
|
|
/* Thus the characteristics of the randomization are the same */
|
|
|
|
n_elems = len;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-08 09:52:59 +00:00
|
|
|
if (n_elems <= 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
n_left = n_elems;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-08 09:52:59 +00:00
|
|
|
while (--n_left) {
|
2017-12-03 21:35:50 +00:00
|
|
|
rnd_idx = php_mt_rand_range(0, n_left);
|
2002-10-08 09:52:59 +00:00
|
|
|
if (rnd_idx != n_left) {
|
|
|
|
temp = str[n_left];
|
|
|
|
str[n_left] = str[rnd_idx];
|
|
|
|
str[rnd_idx] = temp;
|
|
|
|
}
|
|
|
|
}
|
2002-09-25 18:06:05 +00:00
|
|
|
}
|
2007-06-05 13:35:26 +00:00
|
|
|
/* }}} */
|
2002-10-08 09:52:59 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string str_shuffle(string str)
|
2002-09-25 18:06:05 +00:00
|
|
|
Shuffles string. One permutation of all possible is created */
|
|
|
|
PHP_FUNCTION(str_shuffle)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *arg;
|
2008-06-25 12:16:17 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STR(arg)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2008-06-25 12:16:17 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
RETVAL_STRINGL(ZSTR_VAL(arg), ZSTR_LEN(arg));
|
2014-08-25 17:24:55 +00:00
|
|
|
if (Z_STRLEN_P(return_value) > 1) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_string_shuffle(Z_STRVAL_P(return_value), (zend_long) Z_STRLEN_P(return_value));
|
2002-10-09 10:33:22 +00:00
|
|
|
}
|
2002-09-25 18:06:05 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2005-03-12 14:41:20 +00:00
|
|
|
/* {{{ proto mixed str_word_count(string str, [int format [, string charlist]])
|
2002-10-17 03:27:19 +00:00
|
|
|
Counts the number of words inside a string. If format of 1 is specified,
|
|
|
|
then the function will return an array containing all the words
|
|
|
|
found inside the string. If format of 2 is specified, then the function
|
|
|
|
will return an associated array where the position of the word is the key
|
|
|
|
and the word itself is the value.
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-17 03:27:19 +00:00
|
|
|
For the purpose of this function, 'word' is defined as a locale dependent
|
|
|
|
string containing alphabetic characters, which also may contain, but not start
|
|
|
|
with "'" and "-" characters.
|
|
|
|
*/
|
2002-10-17 22:44:44 +00:00
|
|
|
PHP_FUNCTION(str_word_count)
|
2002-10-17 03:27:19 +00:00
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2018-03-17 11:45:22 +00:00
|
|
|
char *char_list = NULL, ch[256];
|
|
|
|
const char *p, *e, *s;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t char_list_len = 0, word_count = 0;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long type = 0;
|
2005-03-12 17:51:19 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 3)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(type)
|
|
|
|
Z_PARAM_STRING(char_list, char_list_len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2005-03-12 17:51:19 +00:00
|
|
|
|
2006-10-11 13:15:30 +00:00
|
|
|
switch(type) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
array_init(return_value);
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(str)) {
|
2006-10-11 14:19:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-10-11 13:15:30 +00:00
|
|
|
break;
|
|
|
|
case 0:
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(str)) {
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(0);
|
2006-10-11 14:19:55 +00:00
|
|
|
}
|
2006-10-11 13:15:30 +00:00
|
|
|
/* nothing to be done */
|
|
|
|
break;
|
|
|
|
default:
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type);
|
2006-10-11 13:15:30 +00:00
|
|
|
RETURN_FALSE;
|
2002-10-17 03:27:19 +00:00
|
|
|
}
|
2005-11-29 16:14:19 +00:00
|
|
|
|
2006-10-11 14:19:55 +00:00
|
|
|
if (char_list) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_charmask((unsigned char *)char_list, char_list_len, ch);
|
2006-10-11 14:19:55 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
p = ZSTR_VAL(str);
|
|
|
|
e = ZSTR_VAL(str) + ZSTR_LEN(str);
|
2006-10-11 14:19:55 +00:00
|
|
|
|
2005-11-29 16:14:19 +00:00
|
|
|
/* first character cannot be ' or -, unless explicitly allowed by the user */
|
|
|
|
if ((*p == '\'' && (!char_list || !ch['\''])) || (*p == '-' && (!char_list || !ch['-']))) {
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
/* last character cannot be -, unless explicitly allowed by the user */
|
2006-10-11 14:19:55 +00:00
|
|
|
if (*(e - 1) == '-' && (!char_list || !ch['-'])) {
|
2005-11-29 16:14:19 +00:00
|
|
|
e--;
|
|
|
|
}
|
|
|
|
|
2002-10-17 03:27:19 +00:00
|
|
|
while (p < e) {
|
2005-11-29 16:14:19 +00:00
|
|
|
s = p;
|
2008-01-16 08:34:33 +00:00
|
|
|
while (p < e && (isalpha((unsigned char)*p) || (char_list && ch[(unsigned char)*p]) || *p == '\'' || *p == '-')) {
|
2005-11-29 16:14:19 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p > s) {
|
2002-10-17 03:27:19 +00:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 1:
|
2014-04-15 11:40:40 +00:00
|
|
|
add_next_index_stringl(return_value, s, p - s);
|
2002-10-17 03:27:19 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2015-06-30 01:05:24 +00:00
|
|
|
add_index_stringl(return_value, (s - ZSTR_VAL(str)), s, p - s);
|
2002-10-17 03:27:19 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
word_count++;
|
2012-01-02 00:47:57 +00:00
|
|
|
break;
|
2002-10-17 03:27:19 +00:00
|
|
|
}
|
2005-07-23 19:44:13 +00:00
|
|
|
}
|
2005-11-29 16:14:19 +00:00
|
|
|
p++;
|
2002-10-17 03:27:19 +00:00
|
|
|
}
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2002-10-17 03:27:19 +00:00
|
|
|
if (!type) {
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(word_count);
|
2002-10-17 03:27:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* }}} */
|
2002-09-25 18:06:05 +00:00
|
|
|
|
2002-08-02 10:08:53 +00:00
|
|
|
#if HAVE_STRFMON
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false money_format(string format , float value)
|
2002-08-02 10:08:53 +00:00
|
|
|
Convert monetary value(s) to string */
|
2003-02-08 15:26:17 +00:00
|
|
|
PHP_FUNCTION(money_format)
|
|
|
|
{
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t format_len = 0;
|
2014-02-25 04:36:33 +00:00
|
|
|
char *format, *p, *e;
|
2002-08-02 10:08:53 +00:00
|
|
|
double value;
|
2007-06-06 17:59:07 +00:00
|
|
|
zend_bool check = 0;
|
2014-02-25 04:36:33 +00:00
|
|
|
zend_string *str;
|
2014-12-29 07:46:28 +00:00
|
|
|
ssize_t res_len;
|
2002-08-02 10:08:53 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STRING(format, format_len)
|
|
|
|
Z_PARAM_DOUBLE(value)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2002-08-02 10:08:53 +00:00
|
|
|
|
2007-06-06 17:59:07 +00:00
|
|
|
p = format;
|
|
|
|
e = p + format_len;
|
|
|
|
while ((p = memchr(p, '%', (e - p)))) {
|
|
|
|
if (*(p + 1) == '%') {
|
2012-01-02 00:47:57 +00:00
|
|
|
p += 2;
|
2007-06-06 17:59:07 +00:00
|
|
|
} else if (!check) {
|
|
|
|
check = 1;
|
|
|
|
p++;
|
|
|
|
} else {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "Only a single %%i or %%n token can be used");
|
2007-06-06 17:59:07 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 06:10:43 +00:00
|
|
|
str = zend_string_safe_alloc(format_len, 1, 1024, 0);
|
2015-06-30 01:05:24 +00:00
|
|
|
if ((res_len = strfmon(ZSTR_VAL(str), ZSTR_LEN(str), format, value)) < 0) {
|
2018-05-08 14:30:15 +00:00
|
|
|
zend_string_efree(str);
|
2003-04-16 01:07:03 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2017-01-09 05:31:41 +00:00
|
|
|
#ifdef _AIX
|
|
|
|
/*
|
|
|
|
On AIX strfmon seems to include the terminating \0 in the length returned by strfmon,
|
|
|
|
despite the documentation indicating it is not included.
|
|
|
|
*/
|
|
|
|
ZSTR_LEN(str) = strlen(ZSTR_VAL(str));
|
|
|
|
#else
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_LEN(str) = (size_t)res_len;
|
2017-01-09 05:31:41 +00:00
|
|
|
#endif
|
2015-06-30 01:05:24 +00:00
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
2002-08-02 10:08:53 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_NEW_STR(zend_string_truncate(str, ZSTR_LEN(str), 0));
|
2002-08-02 10:08:53 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
#endif
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto array|false str_split(string str [, int split_length])
|
2003-02-07 21:36:18 +00:00
|
|
|
Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long. */
|
2003-02-08 15:26:17 +00:00
|
|
|
PHP_FUNCTION(str_split)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *str;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long split_length = 1;
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *p;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t n_reg_segments;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 2)
|
|
|
|
Z_PARAM_STR(str)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG(split_length)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2003-02-07 21:36:18 +00:00
|
|
|
|
|
|
|
if (split_length <= 0) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero");
|
2003-02-07 21:36:18 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (0 == ZSTR_LEN(str) || (size_t)split_length >= ZSTR_LEN(str)) {
|
2014-08-18 13:39:38 +00:00
|
|
|
array_init_size(return_value, 1);
|
2015-06-30 01:05:24 +00:00
|
|
|
add_next_index_stringl(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
|
2004-10-20 22:44:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
array_init_size(return_value, (uint32_t)(((ZSTR_LEN(str) - 1) / split_length) + 1));
|
2014-08-18 13:39:38 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
n_reg_segments = ZSTR_LEN(str) / split_length;
|
|
|
|
p = ZSTR_VAL(str);
|
2003-02-07 21:36:18 +00:00
|
|
|
|
|
|
|
while (n_reg_segments-- > 0) {
|
2014-04-15 11:40:40 +00:00
|
|
|
add_next_index_stringl(return_value, p, split_length);
|
2003-02-07 21:36:18 +00:00
|
|
|
p += split_length;
|
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (p != (ZSTR_VAL(str) + ZSTR_LEN(str))) {
|
|
|
|
add_next_index_stringl(return_value, p, (ZSTR_VAL(str) + ZSTR_LEN(str) - p));
|
2003-02-07 21:36:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto string|false strpbrk(string haystack, string char_list)
|
2003-02-11 22:47:26 +00:00
|
|
|
Search a string for any of a set of characters */
|
|
|
|
PHP_FUNCTION(strpbrk)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *haystack, *char_list;
|
2018-03-17 11:45:22 +00:00
|
|
|
const char *haystack_ptr, *cl_ptr;
|
2012-01-02 00:47:57 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(2, 2)
|
|
|
|
Z_PARAM_STR(haystack)
|
|
|
|
Z_PARAM_STR(char_list)
|
|
|
|
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
|
2003-02-11 22:47:26 +00:00
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
if (!ZSTR_LEN(char_list)) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "The character list cannot be empty");
|
2012-01-02 00:47:57 +00:00
|
|
|
RETURN_FALSE;
|
2003-02-11 22:47:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-30 01:05:24 +00:00
|
|
|
for (haystack_ptr = ZSTR_VAL(haystack); haystack_ptr < (ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); ++haystack_ptr) {
|
|
|
|
for (cl_ptr = ZSTR_VAL(char_list); cl_ptr < (ZSTR_VAL(char_list) + ZSTR_LEN(char_list)); ++cl_ptr) {
|
2012-03-02 03:39:04 +00:00
|
|
|
if (*cl_ptr == *haystack_ptr) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_STRINGL(haystack_ptr, (ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - haystack_ptr));
|
2012-03-02 03:39:04 +00:00
|
|
|
}
|
|
|
|
}
|
2003-02-11 22:47:26 +00:00
|
|
|
}
|
2012-03-02 03:39:04 +00:00
|
|
|
|
|
|
|
RETURN_FALSE;
|
2003-02-11 22:47:26 +00:00
|
|
|
}
|
|
|
|
/* }}} */
|
2003-02-07 21:36:18 +00:00
|
|
|
|
2019-05-28 11:03:41 +00:00
|
|
|
/* {{{ proto int|false substr_compare(string main_str, string str, int offset [, int length [, bool case_sensitivity]])
|
2003-10-30 00:49:33 +00:00
|
|
|
Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters */
|
|
|
|
PHP_FUNCTION(substr_compare)
|
|
|
|
{
|
2014-08-18 13:39:38 +00:00
|
|
|
zend_string *s1, *s2;
|
2014-08-25 17:24:55 +00:00
|
|
|
zend_long offset, len=0;
|
2016-08-03 08:29:12 +00:00
|
|
|
zend_bool len_is_default=1;
|
2003-10-30 00:49:33 +00:00
|
|
|
zend_bool cs=0;
|
2014-08-25 18:22:49 +00:00
|
|
|
size_t cmp_len;
|
2003-10-30 00:49:33 +00:00
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(3, 5)
|
|
|
|
Z_PARAM_STR(s1)
|
|
|
|
Z_PARAM_STR(s2)
|
|
|
|
Z_PARAM_LONG(offset)
|
|
|
|
Z_PARAM_OPTIONAL
|
|
|
|
Z_PARAM_LONG_EX(len, len_is_default, 1, 0)
|
|
|
|
Z_PARAM_BOOL(cs)
|
|
|
|
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
|
2003-10-30 00:49:33 +00:00
|
|
|
|
2016-08-03 08:29:12 +00:00
|
|
|
if (!len_is_default && len <= 0) {
|
2014-04-08 23:33:55 +00:00
|
|
|
if (len == 0) {
|
2014-08-25 17:24:55 +00:00
|
|
|
RETURN_LONG(0L);
|
2014-04-08 23:33:55 +00:00
|
|
|
} else {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero");
|
2014-04-08 23:33:55 +00:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-10-30 00:49:33 +00:00
|
|
|
}
|
|
|
|
|
2005-09-28 22:39:52 +00:00
|
|
|
if (offset < 0) {
|
2015-06-30 01:05:24 +00:00
|
|
|
offset = ZSTR_LEN(s1) + offset;
|
2006-04-25 12:48:42 +00:00
|
|
|
offset = (offset < 0) ? 0 : offset;
|
|
|
|
}
|
|
|
|
|
2019-04-08 09:40:50 +00:00
|
|
|
if ((size_t)offset > ZSTR_LEN(s1)) {
|
2014-12-13 22:06:14 +00:00
|
|
|
php_error_docref(NULL, E_WARNING, "The start position cannot exceed initial string length");
|
2006-04-25 12:48:42 +00:00
|
|
|
RETURN_FALSE;
|
2005-09-28 22:39:52 +00:00
|
|
|
}
|
|
|
|
|
2016-06-23 09:47:06 +00:00
|
|
|
cmp_len = len ? (size_t)len : MAX(ZSTR_LEN(s2), (ZSTR_LEN(s1) - offset));
|
2003-10-30 00:49:33 +00:00
|
|
|
|
|
|
|
if (!cs) {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len));
|
2003-10-30 00:49:33 +00:00
|
|
|
} else {
|
2015-06-30 01:05:24 +00:00
|
|
|
RETURN_LONG(zend_binary_strncasecmp_l(ZSTR_VAL(s1) + offset, (ZSTR_LEN(s1) - offset), ZSTR_VAL(s2), ZSTR_LEN(s2), cmp_len));
|
2003-10-30 00:49:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2016-10-13 22:33:33 +00:00
|
|
|
/* {{{ */
|
|
|
|
static zend_string *php_utf8_encode(const char *s, size_t len)
|
|
|
|
{
|
|
|
|
size_t pos = len;
|
|
|
|
zend_string *str;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
str = zend_string_safe_alloc(len, 2, 0, 0);
|
|
|
|
ZSTR_LEN(str) = 0;
|
|
|
|
while (pos > 0) {
|
|
|
|
/* The lower 256 codepoints of Unicode are identical to Latin-1,
|
|
|
|
* so we don't need to do any mapping here. */
|
|
|
|
c = (unsigned char)(*s);
|
|
|
|
if (c < 0x80) {
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)++] = (char) c;
|
|
|
|
/* We only account for the single-byte and two-byte cases because
|
|
|
|
* we're only dealing with the first 256 Unicode codepoints. */
|
|
|
|
} else {
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)++] = (0xc0 | (c >> 6));
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)++] = (0x80 | (c & 0x3f));
|
|
|
|
}
|
|
|
|
pos--;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
|
|
|
str = zend_string_truncate(str, ZSTR_LEN(str), 0);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ */
|
|
|
|
static zend_string *php_utf8_decode(const char *s, size_t len)
|
|
|
|
{
|
|
|
|
size_t pos = 0;
|
|
|
|
unsigned int c;
|
|
|
|
zend_string *str;
|
|
|
|
|
|
|
|
str = zend_string_alloc(len, 0);
|
|
|
|
ZSTR_LEN(str) = 0;
|
|
|
|
while (pos < len) {
|
|
|
|
int status = FAILURE;
|
|
|
|
c = php_next_utf8_char((const unsigned char*)s, (size_t) len, &pos, &status);
|
|
|
|
|
|
|
|
/* The lower 256 codepoints of Unicode are identical to Latin-1,
|
|
|
|
* so we don't need to do any mapping here beyond replacing non-Latin-1
|
|
|
|
* characters. */
|
|
|
|
if (status == FAILURE || c > 0xFFU) {
|
|
|
|
c = '?';
|
|
|
|
}
|
|
|
|
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)++] = c;
|
|
|
|
}
|
|
|
|
ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0';
|
|
|
|
if (ZSTR_LEN(str) < len) {
|
|
|
|
str = zend_string_truncate(str, ZSTR_LEN(str), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
2017-12-31 04:35:25 +00:00
|
|
|
/* {{{ proto string utf8_encode(string data)
|
2016-10-13 22:33:33 +00:00
|
|
|
Encodes an ISO-8859-1 string to UTF-8 */
|
|
|
|
PHP_FUNCTION(utf8_encode)
|
|
|
|
{
|
|
|
|
char *arg;
|
|
|
|
size_t arg_len;
|
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STRING(arg, arg_len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2016-10-13 22:33:33 +00:00
|
|
|
|
|
|
|
RETURN_STR(php_utf8_encode(arg, arg_len));
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2017-12-31 04:35:25 +00:00
|
|
|
/* {{{ proto string utf8_decode(string data)
|
2016-10-13 22:33:33 +00:00
|
|
|
Converts a UTF-8 encoded string to ISO-8859-1 */
|
|
|
|
PHP_FUNCTION(utf8_decode)
|
|
|
|
{
|
|
|
|
char *arg;
|
|
|
|
size_t arg_len;
|
|
|
|
|
2016-12-31 00:40:45 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STRING(arg, arg_len)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
2016-10-13 22:33:33 +00:00
|
|
|
|
|
|
|
RETURN_STR(php_utf8_decode(arg, arg_len));
|
|
|
|
}
|
|
|
|
/* }}} */
|