/* {{{ php_url_encode */ PHPAPI zend_string *php_url_encode(char const *s, size_t len) { register unsigned char c; unsigned char *to; unsigned char const *from, *end; zend_string *start; from = (unsigned char *)s; end = (unsigned char *)s + len; start = zend_string_safe_alloc(3, len, 0, 0); to = (unsigned char*)ZSTR_VAL(start); while (from < end) { c = *from++; if (c == ' ') { *to++ = '+'; #ifndef CHARSET_EBCDIC } else if ((c < '0' && c != '-' && c != '.') || (c < 'A' && c > '9') || (c > 'Z' && c < 'a' && c != '_') || (c > 'z')) { to[0] = '%'; to[1] = hexchars[c >> 4]; to[2] = hexchars[c & 15]; to += 3; #else /*CHARSET_EBCDIC*/ } else if (!isalnum(c) && strchr("_-.", c) == NULL) {
static void convert_browscap_pattern(zval *pattern, int persistent) /* {{{ */ { int i, j=0; char *t; zend_string *res; char *lc_pattern; res = zend_string_safe_alloc(Z_STRLEN_P(pattern), 2, 4, persistent); t = res->val; lc_pattern = zend_str_tolower_dup(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern)); t[j++] = '\xA7'; /* section sign */ t[j++] = '^'; for (i=0; i<Z_STRLEN_P(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 '\xA7': t[j++] = '\\'; t[j] = '\xA7'; break; default: t[j] = lc_pattern[i]; break; } } t[j++] = '$'; t[j++] = '\xA7'; t[j]=0; res->len = j; Z_STR_P(pattern) = res; efree(lc_pattern); }
static zend_string *unserialize_str(const unsigned char **p, size_t len, size_t maxlen) { size_t i, j; zend_string *str = zend_string_safe_alloc(1, len, 0, 0); unsigned char *end = *(unsigned char **)p+maxlen; if (end < *p) { zend_string_free(str); return NULL; } for (i = 0; i < len; i++) { if (*p >= end) { zend_string_free(str); return NULL; } if (**p != '\\') { ZSTR_VAL(str)[i] = (char)**p; } else { unsigned char ch = 0; for (j = 0; j < 2; j++) { (*p)++; if (**p >= '0' && **p <= '9') { ch = (ch << 4) + (**p -'0'); } else if (**p >= 'a' && **p <= 'f') { ch = (ch << 4) + (**p -'a'+10); } else if (**p >= 'A' && **p <= 'F') { ch = (ch << 4) + (**p -'A'+10); } else { zend_string_free(str); return NULL; } } ZSTR_VAL(str)[i] = (char)ch; } (*p)++; } ZSTR_VAL(str)[i] = 0; ZSTR_LEN(str) = i; return str; }
PHPAPI zend_string *php_quot_print_encode(const unsigned char *str, size_t length) /* {{{ */ { zend_ulong lp = 0; unsigned char c, *d; char *hex = "0123456789ABCDEF"; zend_string *ret; ret = zend_string_safe_alloc(3, (length + (((3 * length)/(PHP_QPRINT_MAXL-9)) + 1)), 0, 0); d = (unsigned char*)ZSTR_VAL(ret); while (length--) { if (((c = *str++) == '\015') && (*str == '\012') && length > 0) { *d++ = '\015'; *d++ = *str++; length--; lp = 0; } else { if (iscntrl (c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*str == '\015'))) { if ((((lp+= 3) > PHP_QPRINT_MAXL) && (c <= 0x7f)) || ((c > 0x7f) && (c <= 0xdf) && ((lp + 3) > PHP_QPRINT_MAXL)) || ((c > 0xdf) && (c <= 0xef) && ((lp + 6) > PHP_QPRINT_MAXL)) || ((c > 0xef) && (c <= 0xf4) && ((lp + 9) > PHP_QPRINT_MAXL))) { *d++ = '='; *d++ = '\015'; *d++ = '\012'; lp = 3; } *d++ = '='; *d++ = hex[c >> 4]; *d++ = hex[c & 0xf]; } else { if ((++lp) > PHP_QPRINT_MAXL) { *d++ = '='; *d++ = '\015'; *d++ = '\012'; lp = 1; } *d++ = c; } } }
static void php_filter_encode_url(zval *value, const unsigned char* chars, const int char_len, int high, int low, int encode_nul) { unsigned char *p; unsigned char tmp[256]; unsigned char *s = (unsigned char *)chars; unsigned char *e = s + char_len; zend_string *str; memset(tmp, 1, sizeof(tmp)-1); while (s < e) { tmp[*s++] = '\0'; } /* XXX: This is not needed since these chars in the allowed list never include the high/low/null value if (encode_nul) { tmp[0] = 1; } if (high) { memset(tmp + 127, 1, sizeof(tmp) - 127); } if (low) { memset(tmp, 1, 32); } */ str = zend_string_safe_alloc(Z_STRLEN_P(value), 3, 0, 0); p = (unsigned char *) ZSTR_VAL(str); s = (unsigned char *) Z_STRVAL_P(value); e = s + Z_STRLEN_P(value); while (s < e) { if (tmp[*s]) { *p++ = '%'; *p++ = hexchars[(unsigned char) *s >> 4]; *p++ = hexchars[(unsigned char) *s & 15]; } else { *p++ = *s; } s++; }
static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */ { zend_string *digest; char *algo, *data; size_t algo_len, data_len; zend_bool raw_output = raw_output_default; const php_hash_ops *ops; void *context; php_stream *stream = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|b", &algo, &algo_len, &data, &data_len, &raw_output) == FAILURE) { return; } ops = php_hash_fetch_ops(algo, algo_len); if (!ops) { php_error_docref(NULL, E_WARNING, "Unknown hashing algorithm: %s", algo); RETURN_FALSE; } if (isfilename) { if (CHECK_NULL_PATH(data, data_len)) { php_error_docref(NULL, E_WARNING, "Invalid path"); RETURN_FALSE; } stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, FG(default_context)); if (!stream) { /* Stream will report errors opening file */ RETURN_FALSE; } } context = emalloc(ops->context_size); ops->hash_init(context); if (isfilename) { char buf[1024]; size_t n; while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) { ops->hash_update(context, (unsigned char *) buf, n); } php_stream_close(stream); } else { ops->hash_update(context, (unsigned char *) data, data_len); } digest = zend_string_alloc(ops->digest_size, 0); ops->hash_final((unsigned char *) ZSTR_VAL(digest), context); efree(context); if (raw_output) { ZSTR_VAL(digest)[ops->digest_size] = 0; RETURN_NEW_STR(digest); } else { zend_string *hex_digest = zend_string_safe_alloc(ops->digest_size, 2, 0, 0); php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops->digest_size); ZSTR_VAL(hex_digest)[2 * ops->digest_size] = 0; zend_string_release(digest); RETURN_NEW_STR(hex_digest); } }
/* {{{ php_escape_shell_arg */ PHPAPI zend_string *php_escape_shell_arg(char *str) { size_t x, y = 0; size_t l = strlen(str); zend_string *cmd; uint64_t estimate = (4 * (uint64_t)l) + 3; /* max command line length - two single quotes - \0 byte length */ if (l > cmd_max_len - 2 - 1) { php_error_docref(NULL, E_ERROR, "Argument exceeds the allowed length of %d bytes", cmd_max_len); return ZSTR_EMPTY_ALLOC(); } cmd = zend_string_safe_alloc(4, l, 2, 0); /* worst case */ #ifdef PHP_WIN32 ZSTR_VAL(cmd)[y++] = '"'; #else ZSTR_VAL(cmd)[y++] = '\''; #endif for (x = 0; x < l; x++) { int mb_len = php_mblen(str + x, (l - x)); /* skip non-valid multibyte characters */ if (mb_len < 0) { continue; } else if (mb_len > 1) { memcpy(ZSTR_VAL(cmd) + y, str + x, mb_len); y += mb_len; x += mb_len - 1; continue; } switch (str[x]) { #ifdef PHP_WIN32 case '"': case '%': case '!': ZSTR_VAL(cmd)[y++] = ' '; break; #else case '\'': ZSTR_VAL(cmd)[y++] = '\''; ZSTR_VAL(cmd)[y++] = '\\'; ZSTR_VAL(cmd)[y++] = '\''; #endif /* fall-through */ default: ZSTR_VAL(cmd)[y++] = str[x]; } } #ifdef PHP_WIN32 if (y > 0 && '\\' == ZSTR_VAL(cmd)[y - 1]) { int k = 0, n = y - 1; for (; n >= 0 && '\\' == ZSTR_VAL(cmd)[n]; n--, k++); if (k % 2) { ZSTR_VAL(cmd)[y++] = '\\'; } } ZSTR_VAL(cmd)[y++] = '"'; #else ZSTR_VAL(cmd)[y++] = '\''; #endif ZSTR_VAL(cmd)[y] = '\0'; if (y > cmd_max_len + 1) { php_error_docref(NULL, E_ERROR, "Escaped argument exceeds the allowed length of %d bytes", cmd_max_len); zend_string_release(cmd); return ZSTR_EMPTY_ALLOC(); } if ((estimate - y) > 4096) { /* realloc if the estimate was way overill * Arbitrary cutoff point of 4096 */ cmd = zend_string_truncate(cmd, y, 0); } ZSTR_LEN(cmd) = y; return cmd; }
/* {{{ php_escape_shell_cmd Escape all chars that could possibly be used to break out of a shell command This function emalloc's a string and returns the pointer. Remember to efree it when done with it. *NOT* safe for binary strings */ PHPAPI zend_string *php_escape_shell_cmd(char *str) { register size_t x, y; size_t l = strlen(str); uint64_t estimate = (2 * (uint64_t)l) + 1; zend_string *cmd; #ifndef PHP_WIN32 char *p = NULL; #endif /* max command line length - two single quotes - \0 byte length */ if (l > cmd_max_len - 2 - 1) { php_error_docref(NULL, E_ERROR, "Command exceeds the allowed length of %d bytes", cmd_max_len); return ZSTR_EMPTY_ALLOC(); } cmd = zend_string_safe_alloc(2, l, 0, 0); for (x = 0, y = 0; x < l; x++) { int mb_len = php_mblen(str + x, (l - x)); /* skip non-valid multibyte characters */ if (mb_len < 0) { continue; } else if (mb_len > 1) { memcpy(ZSTR_VAL(cmd) + y, str + x, mb_len); y += mb_len; x += mb_len - 1; continue; } switch (str[x]) { #ifndef PHP_WIN32 case '"': case '\'': if (!p && (p = memchr(str + x + 1, str[x], l - x - 1))) { /* noop */ } else if (p && *p == str[x]) { p = NULL; } else { ZSTR_VAL(cmd)[y++] = '\\'; } ZSTR_VAL(cmd)[y++] = str[x]; break; #else /* % is Windows specific for environmental variables, ^%PATH% will output PATH while ^%PATH^% will not. escapeshellcmd->val will escape all % and !. */ case '%': case '!': case '"': case '\'': #endif case '#': /* This is character-set independent */ case '&': case ';': case '`': case '|': case '*': case '?': case '~': case '<': case '>': case '^': case '(': case ')': case '[': case ']': case '{': case '}': case '$': case '\\': case '\x0A': /* excluding these two */ case '\xFF': #ifdef PHP_WIN32 ZSTR_VAL(cmd)[y++] = '^'; #else ZSTR_VAL(cmd)[y++] = '\\'; #endif /* fall-through */ default: ZSTR_VAL(cmd)[y++] = str[x]; } } ZSTR_VAL(cmd)[y] = '\0'; if (y > cmd_max_len + 1) { php_error_docref(NULL, E_ERROR, "Escaped command exceeds the allowed length of %d bytes", cmd_max_len); zend_string_release(cmd); return ZSTR_EMPTY_ALLOC(); } if ((estimate - y) > 4096) { /* realloc if the estimate was way overill * Arbitrary cutoff point of 4096 */ cmd = zend_string_truncate(cmd, y, 0); } ZSTR_LEN(cmd) = y; return cmd; }
/* {{{ php_parserr */ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, int raw, zval *subarray) { int type; u_long ttl; type = pRec->wType; ttl = pRec->dwTtl; if (type_to_fetch != DNS_TYPE_ANY && type != type_to_fetch) { return; } if (!store) { return; } array_init(subarray); add_assoc_string(subarray, "host", pRec->pName); add_assoc_string(subarray, "class", "IN"); add_assoc_long(subarray, "ttl", ttl); if (raw) { add_assoc_long(subarray, "type", type); add_assoc_stringl(subarray, "data", (char*) &pRec->Data, (uint) pRec->wDataLength); return; } switch (type) { case DNS_TYPE_A: { IN_ADDR ipaddr; ipaddr.S_un.S_addr = (pRec->Data.A.IpAddress); add_assoc_string(subarray, "type", "A"); add_assoc_string(subarray, "ip", inet_ntoa(ipaddr)); break; } case DNS_TYPE_MX: add_assoc_string(subarray, "type", "MX"); add_assoc_long(subarray, "pri", pRec->Data.Srv.wPriority); /* no break; */ case DNS_TYPE_CNAME: if (type == DNS_TYPE_CNAME) { add_assoc_string(subarray, "type", "CNAME"); } /* no break; */ case DNS_TYPE_NS: if (type == DNS_TYPE_NS) { add_assoc_string(subarray, "type", "NS"); } /* no break; */ case DNS_TYPE_PTR: if (type == DNS_TYPE_PTR) { add_assoc_string(subarray, "type", "PTR"); } add_assoc_string(subarray, "target", pRec->Data.MX.pNameExchange); break; /* Not available on windows, the query is possible but there is no DNS_HINFO_DATA structure */ case DNS_TYPE_HINFO: case DNS_TYPE_TEXT: { DWORD i = 0; DNS_TXT_DATA *data_txt = &pRec->Data.TXT; DWORD count = data_txt->dwStringCount; zend_string *txt; char *txt_dst; long txt_len = 0; zval entries; add_assoc_string(subarray, "type", "TXT"); array_init(&entries); for (i = 0; i < count; i++) { txt_len += strlen(data_txt->pStringArray[i]) + 1; } txt = zend_string_safe_alloc(txt_len, 2, 0, 0); txt_dst = txt->val; for (i = 0; i < count; i++) { int len = strlen(data_txt->pStringArray[i]); memcpy(txt_dst, data_txt->pStringArray[i], len); add_next_index_stringl(&entries, data_txt->pStringArray[i], len); txt_dst += len; } txt->len = txt_dst - txt->val; add_assoc_str(subarray, "txt", txt); add_assoc_zval(subarray, "entries", &entries); } break; case DNS_TYPE_SOA: { DNS_SOA_DATA *data_soa = &pRec->Data.Soa; add_assoc_string(subarray, "type", "SOA"); add_assoc_string(subarray, "mname", data_soa->pNamePrimaryServer); add_assoc_string(subarray, "rname", data_soa->pNameAdministrator); add_assoc_long(subarray, "serial", data_soa->dwSerialNo); add_assoc_long(subarray, "refresh", data_soa->dwRefresh); add_assoc_long(subarray, "retry", data_soa->dwRetry); add_assoc_long(subarray, "expire", data_soa->dwExpire); add_assoc_long(subarray, "minimum-ttl", data_soa->dwDefaultTtl); } break; case DNS_TYPE_AAAA: { DNS_AAAA_DATA *data_aaaa = &pRec->Data.AAAA; char buf[sizeof("AAAA:AAAA:AAAA:AAAA:AAAA:AAAA:AAAA:AAAA")]; char *tp = buf; int i; unsigned short out[8]; int have_v6_break = 0, in_v6_break = 0; for (i = 0; i < 4; ++i) { DWORD chunk = data_aaaa->Ip6Address.IP6Dword[i]; out[i * 2] = htons(LOWORD(chunk)); out[i * 2 + 1] = htons(HIWORD(chunk)); } for(i=0; i < 8; i++) { if (out[i] != 0) { if (tp > (u_char *)buf) { in_v6_break = 0; tp[0] = ':'; tp++; } tp += sprintf((char*)tp,"%x", out[i]); } else { if (!have_v6_break) { have_v6_break = 1; in_v6_break = 1; tp[0] = ':'; tp++; } else if (!in_v6_break) { tp[0] = ':'; tp++; tp[0] = '0'; tp++; } } } if (have_v6_break && in_v6_break) { tp[0] = ':'; tp++; } tp[0] = '\0'; add_assoc_string(subarray, "type", "AAAA"); add_assoc_string(subarray, "ipv6", buf); } break; #if 0 /* Won't be implemented. A6 is deprecated. (Pierre) */ case DNS_TYPE_A6: break; #endif case DNS_TYPE_SRV: { DNS_SRV_DATA *data_srv = &pRec->Data.Srv; add_assoc_string(subarray, "type", "SRV"); add_assoc_long(subarray, "pri", data_srv->wPriority); add_assoc_long(subarray, "weight", data_srv->wWeight); add_assoc_long(subarray, "port", data_srv->wPort); add_assoc_string(subarray, "target", data_srv->pNameTarget); } break; #if _MSC_VER >= 1500 case DNS_TYPE_NAPTR: { DNS_NAPTR_DATA * data_naptr = &pRec->Data.Naptr; add_assoc_string(subarray, "type", "NAPTR"); add_assoc_long(subarray, "order", data_naptr->wOrder); add_assoc_long(subarray, "pref", data_naptr->wPreference); add_assoc_string(subarray, "flags", data_naptr->pFlags); add_assoc_string(subarray, "services", data_naptr->pService); add_assoc_string(subarray, "regex", data_naptr->pRegularExpression); add_assoc_string(subarray, "replacement", data_naptr->pReplacement); } break; #endif default: /* unknown type */ ZVAL_UNDEF(subarray); return; } }