Linux ip-172-26-2-223 5.4.0-1018-aws #18-Ubuntu SMP Wed Jun 24 01:15:00 UTC 2020 x86_64
Apache
: 172.26.2.223 | : 3.133.116.221
Cant Read [ /etc/named.conf ]
8.1.13
www
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
/
www /
server /
php /
82 /
src /
ext /
standard /
[ HOME SHELL ]
Name
Size
Permission
Action
html_tables
[ DIR ]
drwxr-xr-x
tests
[ DIR ]
drwxr-xr-x
Makefile.frag
518
B
-rw-r--r--
Makefile.frag.w32
484
B
-rw-r--r--
array.c
171.38
KB
-rw-r--r--
assert.c
8.26
KB
-rw-r--r--
base64.c
30.55
KB
-rw-r--r--
base64.h
3.59
KB
-rw-r--r--
basic_functions.c
66.93
KB
-rw-r--r--
basic_functions.h
4.87
KB
-rw-r--r--
basic_functions.stub.php
48.85
KB
-rw-r--r--
basic_functions_arginfo.h
125.23
KB
-rw-r--r--
browscap.c
20.49
KB
-rw-r--r--
config.m4
10.98
KB
-rw-r--r--
config.w32
1.79
KB
-rw-r--r--
crc32.c
3.85
KB
-rw-r--r--
crc32.h
4.79
KB
-rw-r--r--
crc32_x86.c
11.99
KB
-rw-r--r--
crc32_x86.h
1.82
KB
-rw-r--r--
credits.c
5.71
KB
-rw-r--r--
credits.h
1.53
KB
-rw-r--r--
credits_ext.h
5.24
KB
-rw-r--r--
credits_sapi.h
835
B
-rw-r--r--
crypt.c
6.73
KB
-rw-r--r--
crypt_blowfish.c
30.75
KB
-rw-r--r--
crypt_blowfish.h
790
B
-rw-r--r--
crypt_freesec.c
21.52
KB
-rw-r--r--
crypt_freesec.h
662
B
-rw-r--r--
crypt_sha256.c
21.6
KB
-rw-r--r--
crypt_sha512.c
26.24
KB
-rw-r--r--
css.c
2.24
KB
-rw-r--r--
css.h
1.04
KB
-rw-r--r--
datetime.c
3.28
KB
-rw-r--r--
datetime.h
1.14
KB
-rw-r--r--
dir.c
14.04
KB
-rw-r--r--
dir.stub.php
528
B
-rw-r--r--
dir_arginfo.h
1.83
KB
-rw-r--r--
dl.c
8.18
KB
-rw-r--r--
dl.h
1.46
KB
-rw-r--r--
dl.stub.php
56
B
-rw-r--r--
dl_arginfo.h
269
B
-rw-r--r--
dns.c
29.37
KB
-rw-r--r--
dns_win32.c
15.09
KB
-rw-r--r--
exec.c
12.77
KB
-rw-r--r--
exec.h
1.27
KB
-rw-r--r--
file.c
65.14
KB
-rw-r--r--
file.h
3.93
KB
-rw-r--r--
filestat.c
28.38
KB
-rw-r--r--
filters.c
50.3
KB
-rw-r--r--
flock_compat.c
6
KB
-rw-r--r--
flock_compat.h
2.06
KB
-rw-r--r--
formatted_print.c
23.31
KB
-rw-r--r--
fsock.c
3.67
KB
-rw-r--r--
fsock.h
1.22
KB
-rw-r--r--
ftok.c
1.84
KB
-rw-r--r--
ftp_fopen_wrapper.c
31.54
KB
-rw-r--r--
head.c
10.66
KB
-rw-r--r--
head.h
1.53
KB
-rw-r--r--
hrtime.c
4.86
KB
-rw-r--r--
hrtime.h
2.31
KB
-rw-r--r--
html.c
44.9
KB
-rw-r--r--
html.h
2.34
KB
-rw-r--r--
html_tables.h
472.26
KB
-rw-r--r--
http.c
6.99
KB
-rw-r--r--
http_fopen_wrapper.c
32.23
KB
-rw-r--r--
image.c
44.79
KB
-rw-r--r--
incomplete_class.c
4.95
KB
-rw-r--r--
info.c
40.74
KB
-rw-r--r--
info.h
22.94
KB
-rw-r--r--
iptc.c
9.11
KB
-rw-r--r--
lcg.c
2.8
KB
-rw-r--r--
levenshtein.c
2.57
KB
-rw-r--r--
link.c
5.45
KB
-rw-r--r--
mail.c
15.13
KB
-rw-r--r--
math.c
27.18
KB
-rw-r--r--
md5.c
10.66
KB
-rw-r--r--
md5.h
2.02
KB
-rw-r--r--
metaphone.c
11.53
KB
-rw-r--r--
microtime.c
4.01
KB
-rw-r--r--
mt_rand.c
10.67
KB
-rw-r--r--
net.c
8.97
KB
-rw-r--r--
pack.c
31.65
KB
-rw-r--r--
pack.h
1.05
KB
-rw-r--r--
pageinfo.c
3.23
KB
-rw-r--r--
pageinfo.h
1.15
KB
-rw-r--r--
password.c
19.17
KB
-rw-r--r--
php_array.h
2.24
KB
-rw-r--r--
php_assert.h
1.24
KB
-rw-r--r--
php_browscap.h
1.11
KB
-rw-r--r--
php_crypt.h
1.37
KB
-rw-r--r--
php_crypt_r.c
5.74
KB
-rw-r--r--
php_crypt_r.h
1.64
KB
-rw-r--r--
php_dir.h
1.28
KB
-rw-r--r--
php_dns.h
2.58
KB
-rw-r--r--
php_ext_syslog.h
1.25
KB
-rw-r--r--
php_filestat.h
2.1
KB
-rw-r--r--
php_fopen_wrapper.c
11.47
KB
-rw-r--r--
php_fopen_wrappers.h
1.79
KB
-rw-r--r--
php_http.h
1.33
KB
-rw-r--r--
php_image.h
2.17
KB
-rw-r--r--
php_incomplete_class.h
2.15
KB
-rw-r--r--
php_lcg.h
1.31
KB
-rw-r--r--
php_mail.h
2.16
KB
-rw-r--r--
php_math.h
3.55
KB
-rw-r--r--
php_mt_rand.h
1.81
KB
-rw-r--r--
php_net.h
1.14
KB
-rw-r--r--
php_password.h
2.76
KB
-rw-r--r--
php_rand.h
3
KB
-rw-r--r--
php_random.h
1.86
KB
-rw-r--r--
php_smart_string.h
1.13
KB
-rw-r--r--
php_smart_string_public.h
1.14
KB
-rw-r--r--
php_standard.h
1.91
KB
-rw-r--r--
php_string.h
3.95
KB
-rw-r--r--
php_uuencode.h
1.18
KB
-rw-r--r--
php_var.h
3.41
KB
-rw-r--r--
php_versioning.h
1.18
KB
-rw-r--r--
proc_open.c
35.65
KB
-rw-r--r--
proc_open.h
1.67
KB
-rw-r--r--
quot_print.c
7
KB
-rw-r--r--
quot_print.h
1.23
KB
-rw-r--r--
rand.c
2.22
KB
-rw-r--r--
random.c
7.33
KB
-rw-r--r--
scanf.c
28.32
KB
-rw-r--r--
scanf.h
1.95
KB
-rw-r--r--
sha1.c
11.22
KB
-rw-r--r--
sha1.h
1.62
KB
-rw-r--r--
soundex.c
2.94
KB
-rw-r--r--
streamsfuncs.c
43.35
KB
-rw-r--r--
streamsfuncs.h
1.11
KB
-rw-r--r--
string.c
143.34
KB
-rw-r--r--
strnatcmp.c
4.28
KB
-rw-r--r--
syslog.c
6.02
KB
-rw-r--r--
type.c
10.77
KB
-rw-r--r--
uniqid.c
2.62
KB
-rw-r--r--
url.c
18.08
KB
-rw-r--r--
url.h
2.08
KB
-rw-r--r--
url_scanner_ex.c
38.41
KB
-rw-r--r--
url_scanner_ex.h
2.32
KB
-rw-r--r--
url_scanner_ex.re
27.63
KB
-rw-r--r--
user_filters.c
15.39
KB
-rw-r--r--
user_filters.stub.php
541
B
-rw-r--r--
user_filters_arginfo.h
2.45
KB
-rw-r--r--
uuencode.c
6.35
KB
-rw-r--r--
var.c
40.96
KB
-rw-r--r--
var_unserializer.c
42.18
KB
-rw-r--r--
var_unserializer.re
34.43
KB
-rw-r--r--
versioning.c
5.69
KB
-rw-r--r--
winver.h
6.23
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : browscap.c
/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | https://www.php.net/license/3_01.txt | | 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. | +----------------------------------------------------------------------+ | Author: Zeev Suraski <zeev@php.net> | +----------------------------------------------------------------------+ */ #include "php.h" #include "php_browscap.h" #include "php_ini.h" #include "php_string.h" #include "ext/pcre/php_pcre.h" #include "zend_ini_scanner.h" #include "zend_globals.h" #define BROWSCAP_NUM_CONTAINS 5 typedef struct { zend_string *key; zend_string *value; } browscap_kv; typedef struct { zend_string *pattern; zend_string *parent; uint32_t kv_start; uint32_t kv_end; /* We ensure that the length fits in 16 bits, so this is fine */ uint16_t contains_start[BROWSCAP_NUM_CONTAINS]; uint8_t contains_len[BROWSCAP_NUM_CONTAINS]; uint8_t prefix_len; } browscap_entry; typedef struct { HashTable *htab; browscap_kv *kv; uint32_t kv_used; uint32_t kv_size; char filename[MAXPATHLEN]; } browser_data; /* browser data defined in startup phase, eagerly loaded in MINIT */ static browser_data global_bdata = {0}; /* browser data defined in activation phase, lazily loaded in get_browser. * Per request and per thread, if applicable */ ZEND_BEGIN_MODULE_GLOBALS(browscap) browser_data activation_bdata; ZEND_END_MODULE_GLOBALS(browscap) ZEND_DECLARE_MODULE_GLOBALS(browscap) #define BROWSCAP_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(browscap, v) #define DEFAULT_SECTION_NAME "Default Browser Capability Settings" /* OBJECTS_FIXME: This whole extension needs going through. The use of objects looks pretty broken here */ static void browscap_entry_dtor(zval *zvalue) { browscap_entry *entry = Z_PTR_P(zvalue); zend_string_release_ex(entry->pattern, 0); if (entry->parent) { zend_string_release_ex(entry->parent, 0); } efree(entry); } static void browscap_entry_dtor_persistent(zval *zvalue) { browscap_entry *entry = Z_PTR_P(zvalue); zend_string_release_ex(entry->pattern, 1); if (entry->parent) { zend_string_release_ex(entry->parent, 1); } pefree(entry, 1); } static inline bool is_placeholder(char c) { return c == '?' || c == '*'; } /* Length of prefix not containing any wildcards */ static uint8_t browscap_compute_prefix_len(zend_string *pattern) { size_t i; for (i = 0; i < ZSTR_LEN(pattern); i++) { if (is_placeholder(ZSTR_VAL(pattern)[i])) { break; } } return (uint8_t)MIN(i, UINT8_MAX); } static size_t browscap_compute_contains( zend_string *pattern, size_t start_pos, uint16_t *contains_start, uint8_t *contains_len) { size_t i = start_pos; /* Find first non-placeholder character after prefix */ for (; i < ZSTR_LEN(pattern); i++) { if (!is_placeholder(ZSTR_VAL(pattern)[i])) { /* Skip the case of a single non-placeholder character. * Let's try to find something longer instead. */ if (i + 1 < ZSTR_LEN(pattern) && !is_placeholder(ZSTR_VAL(pattern)[i + 1])) { break; } } } *contains_start = (uint16_t)i; /* Find first placeholder character after that */ for (; i < ZSTR_LEN(pattern); i++) { if (is_placeholder(ZSTR_VAL(pattern)[i])) { break; } } *contains_len = (uint8_t)MIN(i - *contains_start, UINT8_MAX); return i; } /* Length of regex, including escapes, anchors, etc. */ static size_t browscap_compute_regex_len(zend_string *pattern) { size_t i, len = ZSTR_LEN(pattern); for (i = 0; i < ZSTR_LEN(pattern); i++) { switch (ZSTR_VAL(pattern)[i]) { case '*': case '.': case '\\': case '(': case ')': case '~': case '+': len++; break; } } return len + sizeof("~^$~")-1; } static zend_string *browscap_convert_pattern(zend_string *pattern, int persistent) /* {{{ */ { size_t i, j=0; char *t; zend_string *res; char *lc_pattern; ALLOCA_FLAG(use_heap); res = zend_string_alloc(browscap_compute_regex_len(pattern), persistent); t = ZSTR_VAL(res); lc_pattern = do_alloca(ZSTR_LEN(pattern) + 1, use_heap); zend_str_tolower_copy(lc_pattern, ZSTR_VAL(pattern), ZSTR_LEN(pattern)); t[j++] = '~'; t[j++] = '^'; for (i = 0; i < ZSTR_LEN(pattern); i++, j++) { switch (lc_pattern[i]) { case '?': t[j] = '.'; break; case '*': t[j++] = '.'; t[j] = '*'; break; case '.': t[j++] = '\\'; t[j] = '.'; break; case '\\': t[j++] = '\\'; t[j] = '\\'; break; case '(': t[j++] = '\\'; t[j] = '('; break; case ')': t[j++] = '\\'; t[j] = ')'; break; case '~': t[j++] = '\\'; t[j] = '~'; break; case '+': t[j++] = '\\'; t[j] = '+'; break; default: t[j] = lc_pattern[i]; break; } } t[j++] = '$'; t[j++] = '~'; t[j]=0; ZSTR_LEN(res) = j; free_alloca(lc_pattern, use_heap); return res; } /* }}} */ typedef struct _browscap_parser_ctx { browser_data *bdata; browscap_entry *current_entry; zend_string *current_section_name; HashTable str_interned; } browscap_parser_ctx; static zend_string *browscap_intern_str( browscap_parser_ctx *ctx, zend_string *str, bool persistent) { zend_string *interned = zend_hash_find_ptr(&ctx->str_interned, str); if (interned) { zend_string_addref(interned); } else { interned = zend_string_copy(str); if (persistent) { interned = zend_new_interned_string(str); } zend_hash_add_new_ptr(&ctx->str_interned, interned, interned); } return interned; } static zend_string *browscap_intern_str_ci( browscap_parser_ctx *ctx, zend_string *str, bool persistent) { zend_string *lcname; zend_string *interned; ALLOCA_FLAG(use_heap); ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(str), use_heap); zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(str), ZSTR_LEN(str)); interned = zend_hash_find_ptr(&ctx->str_interned, lcname); if (interned) { zend_string_addref(interned); } else { interned = zend_string_init(ZSTR_VAL(lcname), ZSTR_LEN(lcname), persistent); if (persistent) { interned = zend_new_interned_string(interned); } zend_hash_add_new_ptr(&ctx->str_interned, interned, interned); } ZSTR_ALLOCA_FREE(lcname, use_heap); return interned; } static void browscap_add_kv( browser_data *bdata, zend_string *key, zend_string *value, bool persistent) { if (bdata->kv_used == bdata->kv_size) { bdata->kv_size *= 2; bdata->kv = safe_perealloc(bdata->kv, sizeof(browscap_kv), bdata->kv_size, 0, persistent); } bdata->kv[bdata->kv_used].key = key; bdata->kv[bdata->kv_used].value = value; bdata->kv_used++; } static HashTable *browscap_entry_to_array(browser_data *bdata, browscap_entry *entry) { zval tmp; uint32_t i; HashTable *ht = zend_new_array(8); ZVAL_STR(&tmp, browscap_convert_pattern(entry->pattern, 0)); zend_hash_str_add(ht, "browser_name_regex", sizeof("browser_name_regex")-1, &tmp); ZVAL_STR_COPY(&tmp, entry->pattern); zend_hash_str_add(ht, "browser_name_pattern", sizeof("browser_name_pattern")-1, &tmp); if (entry->parent) { ZVAL_STR_COPY(&tmp, entry->parent); zend_hash_str_add(ht, "parent", sizeof("parent")-1, &tmp); } for (i = entry->kv_start; i < entry->kv_end; i++) { ZVAL_STR_COPY(&tmp, bdata->kv[i].value); zend_hash_add(ht, bdata->kv[i].key, &tmp); } return ht; } static void php_browscap_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */ { browscap_parser_ctx *ctx = arg; browser_data *bdata = ctx->bdata; int persistent = GC_FLAGS(bdata->htab) & IS_ARRAY_PERSISTENT; if (!arg1) { return; } switch (callback_type) { case ZEND_INI_PARSER_ENTRY: if (ctx->current_entry != NULL && arg2) { zend_string *new_key, *new_value; /* Set proper value for true/false settings */ if (zend_string_equals_literal_ci(Z_STR_P(arg2), "on") || zend_string_equals_literal_ci(Z_STR_P(arg2), "yes") || zend_string_equals_literal_ci(Z_STR_P(arg2), "true") ) { new_value = ZSTR_CHAR('1'); } else if (zend_string_equals_literal_ci(Z_STR_P(arg2), "no") || zend_string_equals_literal_ci(Z_STR_P(arg2), "off") || zend_string_equals_literal_ci(Z_STR_P(arg2), "none") || zend_string_equals_literal_ci(Z_STR_P(arg2), "false") ) { new_value = ZSTR_EMPTY_ALLOC(); } else { /* Other than true/false setting */ new_value = browscap_intern_str(ctx, Z_STR_P(arg2), persistent); } if (zend_string_equals_literal_ci(Z_STR_P(arg1), "parent")) { /* parent entry can not be same as current section -> causes infinite loop! */ if (ctx->current_section_name != NULL && zend_string_equals_ci(ctx->current_section_name, Z_STR_P(arg2)) ) { zend_error(E_CORE_ERROR, "Invalid browscap ini file: " "'Parent' value cannot be same as the section name: %s " "(in file %s)", ZSTR_VAL(ctx->current_section_name), INI_STR("browscap")); return; } if (ctx->current_entry->parent) { zend_string_release(ctx->current_entry->parent); } ctx->current_entry->parent = new_value; } else { new_key = browscap_intern_str_ci(ctx, Z_STR_P(arg1), persistent); browscap_add_kv(bdata, new_key, new_value, persistent); ctx->current_entry->kv_end = bdata->kv_used; } } break; case ZEND_INI_PARSER_SECTION: { browscap_entry *entry; zend_string *pattern = Z_STR_P(arg1); size_t pos; int i; if (ZSTR_LEN(pattern) > UINT16_MAX) { php_error_docref(NULL, E_WARNING, "Skipping excessively long pattern of length %zd", ZSTR_LEN(pattern)); break; } if (persistent) { pattern = zend_new_interned_string(zend_string_copy(pattern)); if (ZSTR_IS_INTERNED(pattern)) { Z_TYPE_FLAGS_P(arg1) = 0; } else { zend_string_release(pattern); } } entry = ctx->current_entry = pemalloc(sizeof(browscap_entry), persistent); zend_hash_update_ptr(bdata->htab, pattern, entry); if (ctx->current_section_name) { zend_string_release(ctx->current_section_name); } ctx->current_section_name = zend_string_copy(pattern); entry->pattern = zend_string_copy(pattern); entry->kv_end = entry->kv_start = bdata->kv_used; entry->parent = NULL; pos = entry->prefix_len = browscap_compute_prefix_len(pattern); for (i = 0; i < BROWSCAP_NUM_CONTAINS; i++) { pos = browscap_compute_contains(pattern, pos, &entry->contains_start[i], &entry->contains_len[i]); } break; } } } /* }}} */ static void str_interned_dtor(zval *zv) { zend_string_release(Z_STR_P(zv)); } static int browscap_read_file(char *filename, browser_data *browdata, int persistent) /* {{{ */ { zend_file_handle fh; browscap_parser_ctx ctx = {0}; FILE *fp; if (filename == NULL || filename[0] == '\0') { return FAILURE; } fp = VCWD_FOPEN(filename, "r"); if (!fp) { zend_error(E_CORE_WARNING, "Cannot open \"%s\" for reading", filename); return FAILURE; } zend_stream_init_fp(&fh, fp, filename); browdata->htab = pemalloc(sizeof *browdata->htab, persistent); zend_hash_init(browdata->htab, 0, NULL, persistent ? browscap_entry_dtor_persistent : browscap_entry_dtor, persistent); browdata->kv_size = 16 * 1024; browdata->kv_used = 0; browdata->kv = pemalloc(sizeof(browscap_kv) * browdata->kv_size, persistent); /* Create parser context */ ctx.bdata = browdata; ctx.current_entry = NULL; ctx.current_section_name = NULL; zend_hash_init(&ctx.str_interned, 8, NULL, str_interned_dtor, persistent); zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t) php_browscap_parser_cb, &ctx); /* Destroy parser context */ if (ctx.current_section_name) { zend_string_release(ctx.current_section_name); } zend_hash_destroy(&ctx.str_interned); zend_destroy_file_handle(&fh); return SUCCESS; } /* }}} */ #ifdef ZTS static void browscap_globals_ctor(zend_browscap_globals *browscap_globals) /* {{{ */ { browscap_globals->activation_bdata.htab = NULL; browscap_globals->activation_bdata.kv = NULL; browscap_globals->activation_bdata.filename[0] = '\0'; } /* }}} */ #endif static void browscap_bdata_dtor(browser_data *bdata, int persistent) /* {{{ */ { if (bdata->htab != NULL) { uint32_t i; zend_hash_destroy(bdata->htab); pefree(bdata->htab, persistent); bdata->htab = NULL; for (i = 0; i < bdata->kv_used; i++) { zend_string_release(bdata->kv[i].key); zend_string_release(bdata->kv[i].value); } pefree(bdata->kv, persistent); bdata->kv = NULL; } bdata->filename[0] = '\0'; } /* }}} */ /* {{{ PHP_INI_MH */ PHP_INI_MH(OnChangeBrowscap) { if (stage == PHP_INI_STAGE_STARTUP) { /* value handled in browscap.c's MINIT */ return SUCCESS; } else if (stage == PHP_INI_STAGE_ACTIVATE) { browser_data *bdata = &BROWSCAP_G(activation_bdata); if (bdata->filename[0] != '\0') { browscap_bdata_dtor(bdata, 0); } if (VCWD_REALPATH(ZSTR_VAL(new_value), bdata->filename) == NULL) { return FAILURE; } return SUCCESS; } return FAILURE; } /* }}} */ PHP_MINIT_FUNCTION(browscap) /* {{{ */ { char *browscap = INI_STR("browscap"); #ifdef ZTS ts_allocate_id(&browscap_globals_id, sizeof(browser_data), (ts_allocate_ctor) browscap_globals_ctor, NULL); #endif /* ctor call not really needed for non-ZTS */ if (browscap && browscap[0]) { if (browscap_read_file(browscap, &global_bdata, 1) == FAILURE) { return FAILURE; } } return SUCCESS; } /* }}} */ PHP_RSHUTDOWN_FUNCTION(browscap) /* {{{ */ { browser_data *bdata = &BROWSCAP_G(activation_bdata); if (bdata->filename[0] != '\0') { browscap_bdata_dtor(bdata, 0); } return SUCCESS; } /* }}} */ PHP_MSHUTDOWN_FUNCTION(browscap) /* {{{ */ { browscap_bdata_dtor(&global_bdata, 1); return SUCCESS; } /* }}} */ static inline size_t browscap_get_minimum_length(browscap_entry *entry) { size_t len = entry->prefix_len; int i; for (i = 0; i < BROWSCAP_NUM_CONTAINS; i++) { len += entry->contains_len[i]; } return len; } static int browser_reg_compare(browscap_entry *entry, zend_string *agent_name, browscap_entry **found_entry_ptr) /* {{{ */ { browscap_entry *found_entry = *found_entry_ptr; ALLOCA_FLAG(use_heap) zend_string *pattern_lc, *regex; const char *cur; int i; pcre2_code *re; pcre2_match_data *match_data; uint32_t capture_count; int rc; /* Agent name too short */ if (ZSTR_LEN(agent_name) < browscap_get_minimum_length(entry)) { return 0; } /* Quickly discard patterns where the prefix doesn't match. */ if (zend_binary_strcasecmp( ZSTR_VAL(agent_name), entry->prefix_len, ZSTR_VAL(entry->pattern), entry->prefix_len) != 0) { return 0; } /* Lowercase the pattern, the agent name is already lowercase */ ZSTR_ALLOCA_ALLOC(pattern_lc, ZSTR_LEN(entry->pattern), use_heap); zend_str_tolower_copy(ZSTR_VAL(pattern_lc), ZSTR_VAL(entry->pattern), ZSTR_LEN(entry->pattern)); /* Check if the agent contains the "contains" portions */ cur = ZSTR_VAL(agent_name) + entry->prefix_len; for (i = 0; i < BROWSCAP_NUM_CONTAINS; i++) { if (entry->contains_len[i] != 0) { cur = zend_memnstr(cur, ZSTR_VAL(pattern_lc) + entry->contains_start[i], entry->contains_len[i], ZSTR_VAL(agent_name) + ZSTR_LEN(agent_name)); if (!cur) { ZSTR_ALLOCA_FREE(pattern_lc, use_heap); return 0; } cur += entry->contains_len[i]; } } /* See if we have an exact match, if so, we're done... */ if (zend_string_equals(agent_name, pattern_lc)) { *found_entry_ptr = entry; ZSTR_ALLOCA_FREE(pattern_lc, use_heap); return 1; } regex = browscap_convert_pattern(entry->pattern, 0); re = pcre_get_compiled_regex(regex, &capture_count); if (re == NULL) { ZSTR_ALLOCA_FREE(pattern_lc, use_heap); zend_string_release(regex); return 0; } match_data = php_pcre_create_match_data(capture_count, re); if (!match_data) { ZSTR_ALLOCA_FREE(pattern_lc, use_heap); zend_string_release(regex); return 0; } rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(agent_name), ZSTR_LEN(agent_name), 0, 0, match_data, php_pcre_mctx()); php_pcre_free_match_data(match_data); if (PCRE2_ERROR_NOMATCH != rc) { /* If we've found a possible browser, we need to do a comparison of the number of characters changed in the user agent being checked versus the previous match found and the current match. */ if (found_entry) { size_t i, prev_len = 0, curr_len = 0; zend_string *previous_match = found_entry->pattern; zend_string *current_match = entry->pattern; for (i = 0; i < ZSTR_LEN(previous_match); i++) { switch (ZSTR_VAL(previous_match)[i]) { case '?': case '*': /* do nothing, ignore these characters in the count */ break; default: ++prev_len; } } for (i = 0; i < ZSTR_LEN(current_match); i++) { switch (ZSTR_VAL(current_match)[i]) { case '?': case '*': /* do nothing, ignore these characters in the count */ break; default: ++curr_len; } } /* Pick which browser pattern replaces the least amount of characters when compared to the original user agent string... */ if (prev_len < curr_len) { *found_entry_ptr = entry; } } else { *found_entry_ptr = entry; } } ZSTR_ALLOCA_FREE(pattern_lc, use_heap); zend_string_release(regex); return 0; } /* }}} */ static void browscap_zval_copy_ctor(zval *p) /* {{{ */ { if (Z_REFCOUNTED_P(p)) { zend_string *str; ZEND_ASSERT(Z_TYPE_P(p) == IS_STRING); str = Z_STR_P(p); if (!(GC_FLAGS(str) & GC_PERSISTENT)) { GC_ADDREF(str); } else { ZVAL_NEW_STR(p, zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), 0)); } } } /* }}} */ /* {{{ Get information about the capabilities of a browser. If browser_name is omitted or null, HTTP_USER_AGENT is used. Returns an object by default; if return_array is true, returns an array. */ PHP_FUNCTION(get_browser) { zend_string *agent_name = NULL, *lookup_browser_name; bool return_array = 0; browser_data *bdata; browscap_entry *found_entry = NULL; HashTable *agent_ht; ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_NULL(agent_name) Z_PARAM_BOOL(return_array) ZEND_PARSE_PARAMETERS_END(); if (BROWSCAP_G(activation_bdata).filename[0] != '\0') { bdata = &BROWSCAP_G(activation_bdata); if (bdata->htab == NULL) { /* not initialized yet */ if (browscap_read_file(bdata->filename, bdata, 0) == FAILURE) { RETURN_FALSE; } } } else { if (!global_bdata.htab) { php_error_docref(NULL, E_WARNING, "browscap ini directive not set"); RETURN_FALSE; } bdata = &global_bdata; } if (agent_name == NULL) { zval *http_user_agent = NULL; if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global(ZSTR_KNOWN(ZEND_STR_AUTOGLOBAL_SERVER))) { http_user_agent = zend_hash_str_find( Z_ARRVAL_P(&PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1); } if (http_user_agent == NULL) { php_error_docref(NULL, E_WARNING, "HTTP_USER_AGENT variable is not set, cannot determine user agent name"); RETURN_FALSE; } agent_name = Z_STR_P(http_user_agent); } lookup_browser_name = zend_string_tolower(agent_name); found_entry = zend_hash_find_ptr(bdata->htab, lookup_browser_name); if (found_entry == NULL) { browscap_entry *entry; ZEND_HASH_FOREACH_PTR(bdata->htab, entry) { if (browser_reg_compare(entry, lookup_browser_name, &found_entry)) { break; } } ZEND_HASH_FOREACH_END(); if (found_entry == NULL) { found_entry = zend_hash_str_find_ptr(bdata->htab, DEFAULT_SECTION_NAME, sizeof(DEFAULT_SECTION_NAME)-1); if (found_entry == NULL) { zend_string_release(lookup_browser_name); RETURN_FALSE; } } } agent_ht = browscap_entry_to_array(bdata, found_entry); if (return_array) { RETVAL_ARR(agent_ht); } else { object_and_properties_init(return_value, zend_standard_class_def, agent_ht); } while (found_entry->parent) { found_entry = zend_hash_find_ptr(bdata->htab, found_entry->parent); if (found_entry == NULL) { break; } agent_ht = browscap_entry_to_array(bdata, found_entry); if (return_array) { zend_hash_merge(Z_ARRVAL_P(return_value), agent_ht, (copy_ctor_func_t) browscap_zval_copy_ctor, 0); } else { zend_hash_merge(Z_OBJPROP_P(return_value), agent_ht, (copy_ctor_func_t) browscap_zval_copy_ctor, 0); } zend_hash_destroy(agent_ht); efree(agent_ht); } zend_string_release_ex(lookup_browser_name, 0); } /* }}} */
Close