|
5 | 5 | #include <php.h>
|
6 | 6 | #include <SAPI.h>
|
7 | 7 | #include <php_ini.h>
|
| 8 | +#include <ext/standard/file.h> |
8 | 9 | #include <ext/standard/info.h>
|
9 | 10 | #include <ext/standard/php_smart_string.h>
|
10 | 11 | #if defined(HAVE_APCU_SUPPORT)
|
@@ -356,16 +357,78 @@ static int php_brotli_output_encoding(void)
|
356 | 357 | return BROTLI_G(compression_coding);
|
357 | 358 | }
|
358 | 359 |
|
| 360 | +static zend_string *php_brotli_output_handler_load_dict(php_brotli_context *ctx) |
| 361 | +{ |
| 362 | + char *file = BROTLI_G(output_compression_dict); |
| 363 | + if (!file || strlen(file) == 0) { |
| 364 | + return NULL; |
| 365 | + } |
| 366 | + |
| 367 | +#if defined(USE_BROTLI_DICTIONARY) |
| 368 | + php_stream *stream = NULL; |
| 369 | + zval *zcontext = NULL; |
| 370 | + php_stream_context *context = NULL; |
| 371 | + zend_long maxlen = (ssize_t) PHP_STREAM_COPY_ALL; |
| 372 | + |
| 373 | + context = php_stream_context_from_zval(zcontext, 0); |
| 374 | + stream = php_stream_open_wrapper_ex(file, "rb", |
| 375 | + REPORT_ERRORS, |
| 376 | + NULL, context); |
| 377 | + if (!stream) { |
| 378 | + php_error_docref(NULL, E_WARNING, |
| 379 | + "brotli: failed to load dictionary"); |
| 380 | + return NULL; |
| 381 | + } |
| 382 | + |
| 383 | + if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) { |
| 384 | + php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, |
| 385 | + PHP_STREAM_BUFFER_NONE, NULL); |
| 386 | + } |
| 387 | + |
| 388 | + /* dictionary size limit: |
| 389 | + zend_off_t file_size = php_stream_tell(stream); |
| 390 | + if (file_size < 0 || file_size > (64 * 1024)) { |
| 391 | + php_error_docref(NULL, E_WARNING, |
| 392 | + "brotli: dictionary size (%lld bytes) " |
| 393 | + "exceeds 64 KiB limit", |
| 394 | + (long long)file_size); |
| 395 | + php_stream_close(stream); |
| 396 | + return NULL; |
| 397 | + } |
| 398 | + */ |
| 399 | + |
| 400 | + zend_string *dict = php_stream_copy_to_mem(stream, maxlen, 0); |
| 401 | + |
| 402 | + php_stream_close(stream); |
| 403 | + |
| 404 | + return dict; |
| 405 | +#else |
| 406 | + php_error_docref(NULL, E_WARNING, |
| 407 | + "brotli: not supported compression dictionary"); |
| 408 | + return NULL; |
| 409 | +#endif |
| 410 | +} |
| 411 | + |
359 | 412 | static int php_brotli_output_handler_context_start(php_brotli_context *ctx)
|
360 | 413 | {
|
361 | 414 | long level = BROTLI_G(output_compression_level);
|
| 415 | + zend_string *dict = php_brotli_output_handler_load_dict(ctx); |
| 416 | + if (!BROTLI_G(compression_coding)) { |
| 417 | + if (dict) { |
| 418 | + zend_string_release(dict); |
| 419 | + } |
| 420 | + return FAILURE; |
| 421 | + } |
362 | 422 |
|
363 | 423 | int result = php_brotli_context_create_encoder_ex(ctx,
|
364 | 424 | level,
|
365 | 425 | BROTLI_DEFAULT_WINDOW,
|
366 | 426 | BROTLI_MODE_GENERIC,
|
367 | 427 | dict,
|
368 | 428 | 0);
|
| 429 | + if (dict) { |
| 430 | + zend_string_release(dict); |
| 431 | + } |
369 | 432 |
|
370 | 433 | return result;
|
371 | 434 | }
|
@@ -633,6 +696,9 @@ PHP_INI_BEGIN()
|
633 | 696 | TOSTRING(BROTLI_DEFAULT_QUALITY),
|
634 | 697 | PHP_INI_ALL, OnUpdateLong, output_compression_level,
|
635 | 698 | zend_brotli_globals, brotli_globals)
|
| 699 | + STD_PHP_INI_ENTRY("brotli.output_compression_dict", "", |
| 700 | + PHP_INI_ALL, OnUpdateString, output_compression_dict, |
| 701 | + zend_brotli_globals, brotli_globals) |
636 | 702 | PHP_INI_END()
|
637 | 703 |
|
638 | 704 | static void php_brotli_init_globals(zend_brotli_globals *brotli_globals)
|
|
0 commit comments