Ejemplo n.º 1
0
static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *filterparams, int persistent)
{
	php_stream_filter_ops *fops = NULL;
	php_bz2_filter_data *data;
	int status = BZ_OK;

	/* Create this filter */
	data = pecalloc(1, sizeof(php_bz2_filter_data), persistent);
	if (!data) {
		php_error_docref(NULL, E_WARNING, "Failed allocating %zu bytes", sizeof(php_bz2_filter_data));
		return NULL;
	}

	/* Circular reference */
	data->strm.opaque = (void *) data;

	data->strm.bzalloc = php_bz2_alloc;
	data->strm.bzfree = php_bz2_free;
	data->persistent = persistent;
	data->strm.avail_out = data->outbuf_len = data->inbuf_len = 2048;
	data->strm.next_in = data->inbuf = (char *) pemalloc(data->inbuf_len, persistent);
	if (!data->inbuf) {
		php_error_docref(NULL, E_WARNING, "Failed allocating %zu bytes", data->inbuf_len);
		pefree(data, persistent);
		return NULL;
	}
	data->strm.avail_in = 0;
	data->strm.next_out = data->outbuf = (char *) pemalloc(data->outbuf_len, persistent);
	if (!data->outbuf) {
		php_error_docref(NULL, E_WARNING, "Failed allocating %zu bytes", data->outbuf_len);
		pefree(data->inbuf, persistent);
		pefree(data, persistent);
		return NULL;
	}

	if (strcasecmp(filtername, "bzip2.decompress") == 0) {
		data->small_footprint = 0;
		data->expect_concatenated = 0;

		if (filterparams) {
			zval *tmpzval = NULL;

			if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
				if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated")-1))) {
					data->expect_concatenated = zend_is_true(tmpzval);
					tmpzval = NULL;
				}

				tmpzval = zend_hash_str_find(HASH_OF(filterparams), "small", sizeof("small")-1);
			} else {
				tmpzval = filterparams;
			}

			if (tmpzval) {
				data->small_footprint = zend_is_true(tmpzval);
			}
		}

		data->status = PHP_BZ2_UNITIALIZED;
		fops = &php_bz2_decompress_ops;
	} else if (strcasecmp(filtername, "bzip2.compress") == 0) {
		int blockSize100k = PHP_BZ2_FILTER_DEFAULT_BLOCKSIZE;
		int workFactor = PHP_BZ2_FILTER_DEFAULT_WORKFACTOR;

		if (filterparams) {
			zval *tmpzval;

			if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) {
				if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "blocks", sizeof("blocks")-1))) {
					/* How much memory to allocate (1 - 9) x 100kb */
					zend_long blocks = zval_get_long(tmpzval);
					if (blocks < 1 || blocks > 9) {
						php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate. (%pd)", blocks);
					} else {
						blockSize100k = (int) blocks;
					}
				}

				if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "work", sizeof("work")-1))) {
					/* Work Factor (0 - 250) */
					zend_long work = zval_get_long(tmpzval);
					if (work < 0 || work > 250) {
						php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor. (%pd)", work);
					} else {
						workFactor = (int) work;
					}
				}
			}
		}

		status = BZ2_bzCompressInit(&(data->strm), blockSize100k, 0, workFactor);
		fops = &php_bz2_compress_ops;
	} else {
		status = BZ_DATA_ERROR;
	}

	if (status != BZ_OK) {
		/* Unspecified (probably strm) error, let stream-filter error do its own whining */
		pefree(data->strm.next_in, persistent);
		pefree(data->strm.next_out, persistent);
		pefree(data, persistent);
		return NULL;
	}

	return php_stream_filter_alloc(fops, data, persistent);
}
Ejemplo n.º 2
0
static php_stream_filter *user_filter_factory_create(const char *filtername,
		zval *filterparams, uint8_t persistent)
{
	struct php_user_filter_data *fdat = NULL;
	php_stream_filter *filter;
	zval obj, zfilter;
	zval func_name;
	zval retval;
	size_t len;

	/* some sanity checks */
	if (persistent) {
		php_error_docref(NULL, E_WARNING,
				"cannot use a user-space filter with a persistent stream");
		return NULL;
	}

	len = strlen(filtername);

	/* determine the classname/class entry */
	if (NULL == (fdat = zend_hash_str_find_ptr(BG(user_filter_map), (char*)filtername, len))) {
		char *period;

		/* Userspace Filters using ambiguous wildcards could cause problems.
           i.e.: myfilter.foo.bar will always call into myfilter.foo.*
                 never seeing myfilter.*
           TODO: Allow failed userfilter creations to continue
                 scanning through the list */
		if ((period = strrchr(filtername, '.'))) {
			char *wildcard = safe_emalloc(len, 1, 3);

			/* Search for wildcard matches instead */
			memcpy(wildcard, filtername, len + 1); /* copy \0 */
			period = wildcard + (period - filtername);
			while (period) {
				*period = '\0';
				strncat(wildcard, ".*", 2);
				if (NULL != (fdat = zend_hash_str_find_ptr(BG(user_filter_map), wildcard, strlen(wildcard)))) {
					period = NULL;
				} else {
					*period = '\0';
					period = strrchr(wildcard, '.');
				}
			}
			efree(wildcard);
		}
		if (fdat == NULL) {
			php_error_docref(NULL, E_WARNING,
					"Err, filter \"%s\" is not in the user-filter map, but somehow the user-filter-factory was invoked for it!?", filtername);
			return NULL;
		}
	}

	/* bind the classname to the actual class */
	if (fdat->ce == NULL) {
		if (NULL == (fdat->ce = zend_lookup_class(fdat->classname))) {
			php_error_docref(NULL, E_WARNING,
					"user-filter \"%s\" requires class \"%s\", but that class is not defined",
					filtername, ZSTR_VAL(fdat->classname));
			return NULL;
		}
	}

	filter = php_stream_filter_alloc(&userfilter_ops, NULL, 0);
	if (filter == NULL) {
		return NULL;
	}

	/* create the object */
	object_init_ex(&obj, fdat->ce);

	/* filtername */
	add_property_string(&obj, "filtername", (char*)filtername);

	/* and the parameters, if any */
	if (filterparams) {
		add_property_zval(&obj, "params", filterparams);
	} else {
		add_property_null(&obj, "params");
	}

	/* invoke the constructor */
	ZVAL_STRINGL(&func_name, "oncreate", sizeof("oncreate")-1);

	call_user_function_ex(NULL,
			&obj,
			&func_name,
			&retval,
			0, NULL,
			0, NULL);

	if (Z_TYPE(retval) != IS_UNDEF) {
		if (Z_TYPE(retval) == IS_FALSE) {
			/* User reported filter creation error "return false;" */
			zval_ptr_dtor(&retval);

			/* Kill the filter (safely) */
			ZVAL_UNDEF(&filter->abstract);
			php_stream_filter_free(filter);

			/* Kill the object */
			zval_ptr_dtor(&obj);

			/* Report failure to filter_alloc */
			return NULL;
		}
		zval_ptr_dtor(&retval);
	}
	zval_ptr_dtor(&func_name);

	/* set the filter property, this will be used during cleanup */
	ZVAL_RES(&zfilter, zend_register_resource(filter, le_userfilters));
	ZVAL_COPY_VALUE(&filter->abstract, &obj);
	add_property_zval(&obj, "filter", &zfilter);
	/* add_property_zval increments the refcount which is unwanted here */
	zval_ptr_dtor(&zfilter);

	return filter;
}
Ejemplo n.º 3
0
static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *filterparams, int persistent)
{
	php_stream_filter_ops *fops = NULL;
	php_zlib_filter_data *data;
	int status;

	/* Create this filter */
	data = pecalloc(1, sizeof(php_zlib_filter_data), persistent);
	if (!data) {
		php_error_docref(NULL, E_WARNING, "Failed allocating %zd bytes", sizeof(php_zlib_filter_data));
		return NULL;
	}

	/* Circular reference */
	data->strm.opaque = (voidpf) data;

	data->strm.zalloc = (alloc_func) php_zlib_alloc;
	data->strm.zfree = (free_func) php_zlib_free;
	data->strm.avail_out = data->outbuf_len = data->inbuf_len = 0x8000;
	data->strm.next_in = data->inbuf = (Bytef *) pemalloc(data->inbuf_len, persistent);
	if (!data->inbuf) {
		php_error_docref(NULL, E_WARNING, "Failed allocating %zd bytes", data->inbuf_len);
		pefree(data, persistent);
		return NULL;
	}
	data->strm.avail_in = 0;
	data->strm.next_out = data->outbuf = (Bytef *) pemalloc(data->outbuf_len, persistent);
	if (!data->outbuf) {
		php_error_docref(NULL, E_WARNING, "Failed allocating %zd bytes", data->outbuf_len);
		pefree(data->inbuf, persistent);
		pefree(data, persistent);
		return NULL;
	}

	data->strm.data_type = Z_ASCII;

	if (strcasecmp(filtername, "zlib.inflate") == 0) {
		int windowBits = -MAX_WBITS;

		if (filterparams) {
			zval *tmpzval;

			if ((Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) &&
				(tmpzval = zend_hash_str_find(HASH_OF(filterparams), "window", sizeof("window") - 1))) {
				/* log-2 base of history window (9 - 15) */
				zend_long tmp = zval_get_long(tmpzval);
				if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 32) {
					php_error_docref(NULL, E_WARNING, "Invalid parameter give for window size. (%pd)", tmp);
				} else {
					windowBits = tmp;
				}
			}
		}

		/* RFC 1951 Inflate */
		data->finished = '\0';
		status = inflateInit2(&(data->strm), windowBits);
		fops = &php_zlib_inflate_ops;
	} else if (strcasecmp(filtername, "zlib.deflate") == 0) {
		/* RFC 1951 Deflate */
		int level = Z_DEFAULT_COMPRESSION;
		int windowBits = -MAX_WBITS;
		int memLevel = MAX_MEM_LEVEL;


		if (filterparams) {
			zval *tmpzval;
			zend_long tmp;

			/* filterparams can either be a scalar value to indicate compression level (shortcut method)
               Or can be a hash containing one or more of 'window', 'memory', and/or 'level' members. */

			switch (Z_TYPE_P(filterparams)) {
				case IS_ARRAY:
				case IS_OBJECT:
					if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "memory", sizeof("memory") -1))) {
						/* Memory Level (1 - 9) */
						tmp = zval_get_long(tmpzval);
						if (tmp < 1 || tmp > MAX_MEM_LEVEL) {
							php_error_docref(NULL, E_WARNING, "Invalid parameter give for memory level. (%pd)", tmp);
						} else {
							memLevel = tmp;
						}
					}

					if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "window", sizeof("window") - 1))) {
						/* log-2 base of history window (9 - 15) */
						tmp = zval_get_long(tmpzval);
						if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 16) {
							php_error_docref(NULL, E_WARNING, "Invalid parameter give for window size. (%pd)", tmp);
						} else {
							windowBits = tmp;
						}
					}

					if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "level", sizeof("level") - 1))) {
						tmp = zval_get_long(tmpzval);

						/* Pseudo pass through to catch level validating code */
						goto factory_setlevel;
					}
					break;
				case IS_STRING:
				case IS_DOUBLE:
				case IS_LONG:
					tmp = zval_get_long(filterparams);
factory_setlevel:
					/* Set compression level within reason (-1 == default, 0 == none, 1-9 == least to most compression */
					if (tmp < -1 || tmp > 9) {
						php_error_docref(NULL, E_WARNING, "Invalid compression level specified. (%pd)", tmp);
					} else {
						level = tmp;
					}
					break;
				default:
					php_error_docref(NULL, E_WARNING, "Invalid filter parameter, ignored");
			}
		}
		status = deflateInit2(&(data->strm), level, Z_DEFLATED, windowBits, memLevel, 0);
		fops = &php_zlib_deflate_ops;
	} else {
		status = Z_DATA_ERROR;
	}

	if (status != Z_OK) {
		/* Unspecified (probably strm) error, let stream-filter error do its own whining */
		pefree(data->strm.next_in, persistent);
		pefree(data->strm.next_out, persistent);
		pefree(data, persistent);
		return NULL;
	}

	return php_stream_filter_alloc(fops, data, persistent);
}
Ejemplo n.º 4
0
static php_stream_filter *http_filter_create(const char *name, zval *params, int p)
#endif
{
	zval *tmp = params;
	php_stream_filter *f = NULL;
	int flags = p ? PHP_HTTP_ENCODING_STREAM_PERSISTENT : 0;
	
	if (params) {
		switch (Z_TYPE_P(params)) {
		case IS_ARRAY:
		case IS_OBJECT:
			if (!(tmp = zend_hash_str_find_ind(HASH_OF(params), ZEND_STRL("flags")))) {
				break;
			}
			/* no break */
		default:
			flags |= zval_get_long(tmp) & 0x0fffffff;
			break;
		}
	}

	if (!strcasecmp(name, "http.chunked_decode")) {
		PHP_HTTP_FILTER_BUFFER(chunked_decode) *b = NULL;
		
		if ((b = pecalloc(1, sizeof(PHP_HTTP_FILTER_BUFFER(chunked_decode)), p))) {
			php_http_buffer_init_ex(PHP_HTTP_BUFFER(b), 4096, p ? PHP_HTTP_BUFFER_INIT_PERSISTENT : 0);
			if (!(f = php_stream_filter_alloc(&PHP_HTTP_FILTER_OP(chunked_decode), b, p))) {
				pefree(b, p);
			}
		}
	} else
	
	if (!strcasecmp(name, "http.chunked_encode")) {
		f = php_stream_filter_alloc(&PHP_HTTP_FILTER_OP(chunked_encode), NULL, p);
	} else
	
	if (!strcasecmp(name, "http.inflate")) {
		PHP_HTTP_FILTER_BUFFER(stream) *b = NULL;
		
		if ((b = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_inflate_ops(), flags))) {
			if (!(f = php_stream_filter_alloc(&PHP_HTTP_FILTER_OP(inflate), b, p))) {
				php_http_encoding_stream_free(&b);
			}
		}
	} else
	
	if (!strcasecmp(name, "http.deflate")) {
		PHP_HTTP_FILTER_BUFFER(stream) *b = NULL;
		
		if ((b = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_deflate_ops(), flags))) {
			if (!(f = php_stream_filter_alloc(&PHP_HTTP_FILTER_OP(deflate), b, p))) {
				php_http_encoding_stream_free(&b);
			}
		}
#if PHP_HTTP_HAVE_LIBBROTLI
	} else

	if (!strcasecmp(name, "http.brotli_encode")) {
		PHP_HTTP_FILTER_BUFFER(stream) *b = NULL;

		if ((b = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_enbrotli_ops(), flags))) {
			if (!(f = php_stream_filter_alloc(&PHP_HTTP_FILTER_OP(brotli_encode), b, p))) {
				php_http_encoding_stream_free(&b);
			}
		}
	} else

	if (!strcasecmp(name, "http.brotli_decode")) {
		PHP_HTTP_FILTER_BUFFER(stream) *b = NULL;

		if ((b = php_http_encoding_stream_init(NULL, php_http_encoding_stream_get_debrotli_ops(), flags))) {
			if (!(f = php_stream_filter_alloc(&PHP_HTTP_FILTER_OP(brotli_decode), b, p))) {
				php_http_encoding_stream_free(&b);
			}
		}
#endif
	}
	
	return f;
}
Ejemplo n.º 5
0
/* {{{ php_mcrypt_filter_create
 * Instantiate mcrypt filter
 */
static php_stream_filter *php_mcrypt_filter_create(const char *filtername, zval *filterparams, int persistent)
{
	int encrypt = 1, iv_len, key_len, keyl, result;
	const char *cipher = filtername + sizeof("mcrypt.") - 1;
	zval *tmpzval;
	MCRYPT mcrypt_module;
	char *iv = NULL, *key = NULL;
	char *algo_dir = INI_STR("mcrypt.algorithms_dir");
	char *mode_dir = INI_STR("mcrypt.modes_dir");
	char *mode = "cbc";
	php_mcrypt_filter_data *data;

	if (strncasecmp(filtername, "mdecrypt.", sizeof("mdecrypt.") - 1) == 0) {
		encrypt = 0;
		cipher += sizeof("de") - 1;
	} else if (strncasecmp(filtername, "mcrypt.", sizeof("mcrypt.") - 1) != 0) {
		/* Should never happen */
		return NULL;
	}

	if (!filterparams || Z_TYPE_P(filterparams) != IS_ARRAY) {
		php_error_docref(NULL, E_WARNING, "Filter parameters for %s must be an array", filtername);
		return NULL;
	}

	if ((tmpzval = zend_hash_str_find(Z_ARRVAL_P(filterparams), ZEND_STRL("mode")))) {
		if (Z_TYPE_P(tmpzval) == IS_STRING) {
			mode = Z_STRVAL_P(tmpzval);
		} else {
			php_error_docref(NULL, E_WARNING, "mode is not a string, ignoring");
		}
	}

	if ((tmpzval=zend_hash_str_find(Z_ARRVAL_P(filterparams), ZEND_STRL("algorithms_dir")))) {
		if (Z_TYPE_P(tmpzval) == IS_STRING) {
			algo_dir = Z_STRVAL_P(tmpzval);
		} else {
			php_error_docref(NULL, E_WARNING, "algorithms_dir is not a string, ignoring");
		}
	}

	if ((tmpzval=zend_hash_str_find(Z_ARRVAL_P(filterparams), ZEND_STRL("modes_dir")))) {
		if (Z_TYPE_P(tmpzval) == IS_STRING) {
			mode_dir = Z_STRVAL_P(tmpzval);
		} else {
			php_error_docref(NULL, E_WARNING, "modes_dir is not a string, ignoring");
		}
	}

	if ((tmpzval = zend_hash_str_find(Z_ARRVAL_P(filterparams), ZEND_STRL("key"))) &&
		Z_TYPE_P(tmpzval) == IS_STRING) {
		key = Z_STRVAL_P(tmpzval);
		key_len = (int)Z_STRLEN_P(tmpzval);
	} else {
		php_error_docref(NULL, E_WARNING, "key not specified or is not a string");
		return NULL;
	}

	mcrypt_module = mcrypt_module_open((char *)cipher, algo_dir, mode, mode_dir);
	if (mcrypt_module == MCRYPT_FAILED) {
		php_error_docref(NULL, E_WARNING, "Could not open encryption module");
		return NULL;
	}
	iv_len = mcrypt_enc_get_iv_size(mcrypt_module);
	keyl = mcrypt_enc_get_key_size(mcrypt_module);
	if (keyl < key_len) {
		key_len = keyl;
	}

	if (!(tmpzval = zend_hash_str_find(Z_ARRVAL_P(filterparams), ZEND_STRL("iv"))) ||
		Z_TYPE_P(tmpzval) != IS_STRING) {
		php_error_docref(NULL, E_WARNING, "Filter parameter[iv] not provided or not of type: string");
		mcrypt_module_close(mcrypt_module);
		return NULL;
	}

	iv = emalloc(iv_len + 1);
	if ((size_t)iv_len <= Z_STRLEN_P(tmpzval)) {
		memcpy(iv, Z_STRVAL_P(tmpzval), iv_len);
	} else {
		memcpy(iv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval));
		memset(iv + Z_STRLEN_P(tmpzval), 0, iv_len - Z_STRLEN_P(tmpzval));
	}

	result = mcrypt_generic_init(mcrypt_module, key, key_len, iv);
	efree(iv);
	if (result < 0) {
		switch (result) {
			case -3:
				php_error_docref(NULL, E_WARNING, "Key length incorrect");
				break;
			case -4:
				php_error_docref(NULL, E_WARNING, "Memory allocation error");
				break;
			case -1:
			default:
				php_error_docref(NULL, E_WARNING, "Unknown error");
				break;
		}
		mcrypt_module_close(mcrypt_module);
		return NULL;
	}

	data = pemalloc(sizeof(php_mcrypt_filter_data), persistent);
	data->module = mcrypt_module;
	data->encrypt = encrypt;
	if (mcrypt_enc_is_block_mode(mcrypt_module)) {
		data->blocksize = mcrypt_enc_get_block_size(mcrypt_module);
		data->block_buffer = pemalloc(data->blocksize, persistent);
	} else {
		data->blocksize = 0;
		data->block_buffer = NULL;
	}
	data->block_used = 0;
	data->persistent = persistent;

	return php_stream_filter_alloc(&php_mcrypt_filter_ops, data, persistent);
}