Example #1
0
static inline int unserialize_allowed_class(zend_string *class_name, HashTable *classes)
{
	zend_string *lcname;
	int res;
	ALLOCA_FLAG(use_heap)

	if(classes == NULL) {
		return 1;
	}
	if(!zend_hash_num_elements(classes)) {
		return 0;
	}

	ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(class_name), use_heap);
	zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
	res = zend_hash_exists(classes, lcname);
	ZSTR_ALLOCA_FREE(lcname, use_heap);
	return res;
}
Example #2
0
static zend_string *browscap_intern_str_ci(
		browscap_parser_ctx *ctx, zend_string *str, zend_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_dup(lcname, persistent);
		zend_hash_add_new_ptr(&ctx->str_interned, interned, interned);
	}

	ZSTR_ALLOCA_FREE(lcname, use_heap);
	return interned;
}
Example #3
0
static int browser_reg_compare(
		zval *entry_zv, int num_args, va_list args, zend_hash_key *key) /* {{{ */
{
	browscap_entry *entry = Z_PTR_P(entry_zv);
	zend_string *agent_name = va_arg(args, zend_string *);
	browscap_entry **found_entry_ptr = va_arg(args, browscap_entry **);
	browscap_entry *found_entry = *found_entry_ptr;
	ALLOCA_FLAG(use_heap);
	zend_string *pattern_lc, *regex;
	const char *cur;
	int i;

	pcre *re;
	int re_options;
	pcre_extra *re_extra;

	/* 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 ZEND_HASH_APPLY_STOP;
	}

	regex = browscap_convert_pattern(entry->pattern, 0);
	re = pcre_get_compiled_regex(regex, &re_extra, &re_options);
	if (re == NULL) {
		ZSTR_ALLOCA_FREE(pattern_lc, use_heap);
		zend_string_release(regex);
		return 0;
	}

	if (pcre_exec(re, re_extra, ZSTR_VAL(agent_name), ZSTR_LEN(agent_name), 0, re_options, NULL, 0) == 0) {
		/* 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;
}