@@ -37,33 +37,43 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_brotli_compress, 0, 1, MAY_BE_ST
37
37
ZEND_ARG_TYPE_INFO (0 , data , IS_STRING , 0 )
38
38
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , level , IS_LONG , 0 , "BROTLI_COMPRESS_LEVEL_DEFAULT" )
39
39
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , mode , IS_LONG , 0 , "BROTLI_GENERIC" )
40
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , dict , IS_STRING , 1 , "null" )
40
41
#else
41
42
ZEND_BEGIN_ARG_INFO_EX (arginfo_brotli_compress , 0 , 0 , 1 )
42
43
ZEND_ARG_INFO (0 , data )
43
44
ZEND_ARG_INFO (0 , level )
44
45
ZEND_ARG_INFO (0 , mode )
46
+ ZEND_ARG_INFO (0 , dict )
45
47
#endif
46
48
ZEND_END_ARG_INFO ()
47
49
48
50
#if PHP_VERSION_ID >= 80000
49
51
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX (arginfo_brotli_uncompress , 0 , 1 , MAY_BE_STRING |MAY_BE_FALSE )
50
52
ZEND_ARG_TYPE_INFO (0 , data , IS_STRING , 0 )
51
53
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , length , IS_LONG , 0 , "0" )
54
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , dict , IS_STRING , 1 , "null" )
52
55
#else
53
56
ZEND_BEGIN_ARG_INFO_EX (arginfo_brotli_uncompress , 0 , 0 , 1 )
54
57
ZEND_ARG_INFO (0 , data )
55
58
ZEND_ARG_INFO (0 , length )
59
+ #if defined(USE_BROTLI_DICTIONARY )
60
+ ZEND_ARG_INFO (0 , dict )
61
+ #endif
56
62
#endif
57
63
ZEND_END_ARG_INFO ()
58
64
59
65
#if PHP_VERSION_ID >= 80000
60
66
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX (arginfo_brotli_compress_init , 0 , 0 , Brotli \\Compress \\Context , MAY_BE_FALSE )
61
67
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , level , IS_LONG , 0 , "BROTLI_COMPRESS_LEVEL_DEFAULT" )
62
68
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , mode , IS_LONG , 0 , "BROTLI_GENERIC" )
69
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , dict , IS_STRING , 1 , "null" )
63
70
#else
64
71
ZEND_BEGIN_ARG_INFO_EX (arginfo_brotli_compress_init , 0 , 0 , 0 )
65
72
ZEND_ARG_INFO (0 , level )
66
73
ZEND_ARG_INFO (0 , mode )
74
+ #if defined(USE_BROTLI_DICTIONARY )
75
+ ZEND_ARG_INFO (0 , dict )
76
+ #endif
67
77
#endif
68
78
ZEND_END_ARG_INFO ()
69
79
@@ -82,8 +92,10 @@ ZEND_END_ARG_INFO()
82
92
83
93
#if PHP_VERSION_ID >= 80000
84
94
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX (arginfo_brotli_uncompress_init , 0 , 0 , Brotli \\UnCompress \\Context , MAY_BE_FALSE )
95
+ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE (0 , dict , IS_STRING , 1 , "null" )
85
96
#else
86
97
ZEND_BEGIN_ARG_INFO_EX (arginfo_brotli_uncompress_init , 0 , 0 , 0 )
98
+ ZEND_ARG_INFO (0 , dict )
87
99
#endif
88
100
ZEND_END_ARG_INFO ()
89
101
@@ -100,6 +112,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_brotli_uncompress_add, 0, 0, 2)
100
112
#endif
101
113
ZEND_END_ARG_INFO ()
102
114
115
+ #ifndef Z_PARAM_STR_OR_NULL
116
+ #define Z_PARAM_STR_OR_NULL (dest ) Z_PARAM_STR_EX(dest, 1, 0)
117
+ #endif
118
+
103
119
#if defined(HAVE_APCU_SUPPORT )
104
120
static int APC_SERIALIZER_NAME (brotli )(APC_SERIALIZER_ARGS );
105
121
static int APC_UNSERIALIZER_NAME (brotli )(APC_UNSERIALIZER_ARGS );
@@ -132,6 +148,9 @@ static const size_t PHP_BROTLI_BUFFER_SIZE = 1 << 19;
132
148
struct _php_brotli_context {
133
149
BrotliEncoderState * encoder ;
134
150
BrotliDecoderState * decoder ;
151
+ #if defined(USE_BROTLI_DICTIONARY )
152
+ BrotliEncoderPreparedDictionary * dictionary ;
153
+ #endif
135
154
size_t available_in ;
136
155
const uint8_t * next_in ;
137
156
size_t available_out ;
@@ -144,6 +163,9 @@ static void php_brotli_context_init(php_brotli_context *ctx)
144
163
{
145
164
ctx -> encoder = NULL ;
146
165
ctx -> decoder = NULL ;
166
+ #if defined(USE_BROTLI_DICTIONARY )
167
+ ctx -> dictionary = NULL ;
168
+ #endif
147
169
ctx -> available_in = 0 ;
148
170
ctx -> next_in = NULL ;
149
171
ctx -> available_out = 0 ;
@@ -152,8 +174,11 @@ static void php_brotli_context_init(php_brotli_context *ctx)
152
174
}
153
175
154
176
static int php_brotli_context_create_encoder_ex (php_brotli_context * ctx ,
155
- long level , int lgwin ,
156
- long mode , int fail )
177
+ long level ,
178
+ int lgwin ,
179
+ long mode ,
180
+ zend_string * dict ,
181
+ int fail )
157
182
{
158
183
ctx -> encoder = BrotliEncoderCreateInstance (NULL , NULL , NULL );
159
184
if (!ctx -> encoder ) {
@@ -204,13 +229,37 @@ static int php_brotli_context_create_encoder_ex(php_brotli_context *ctx,
204
229
return FAILURE ;
205
230
}
206
231
232
+ if (dict ) {
233
+ #if defined(USE_BROTLI_DICTIONARY )
234
+ ctx -> dictionary
235
+ = BrotliEncoderPrepareDictionary (BROTLI_SHARED_DICTIONARY_RAW ,
236
+ ZSTR_LEN (dict ), ZSTR_VAL (dict ),
237
+ BROTLI_MAX_QUALITY ,
238
+ NULL , NULL , NULL );
239
+ if (ctx -> dictionary == NULL
240
+ || !BrotliEncoderAttachPreparedDictionary (ctx -> encoder ,
241
+ ctx -> dictionary )) {
242
+ php_error_docref (NULL , E_WARNING ,
243
+ "%sfailed to set compression dictionary" ,
244
+ (fail ? "" : "brotli: " ));
245
+ return FAILURE ;
246
+ }
247
+ #else
248
+ php_error_docref (NULL , E_WARNING ,
249
+ "%sfailed to not supported compression dictionary" ,
250
+ (fail ? "" : "brotli: " ));
251
+ return FAILURE ;
252
+ #endif
253
+ }
254
+
207
255
return SUCCESS ;
208
256
}
209
257
210
258
#define php_brotli_context_create_encoder (ctx , level , lgwin , mode ) \
211
- php_brotli_context_create_encoder_ex(ctx, level, lgwin, mode, 0)
259
+ php_brotli_context_create_encoder_ex(ctx, level, lgwin, mode, NULL, 0)
212
260
213
261
static int php_brotli_context_create_decoder_ex (php_brotli_context * ctx ,
262
+ zend_string * dict ,
214
263
int fail )
215
264
{
216
265
ctx -> decoder = BrotliDecoderCreateInstance (NULL , NULL , NULL );
@@ -229,11 +278,29 @@ static int php_brotli_context_create_decoder_ex(php_brotli_context *ctx,
229
278
return FAILURE ;
230
279
}
231
280
281
+ if (dict ) {
282
+ #if defined(USE_BROTLI_DICTIONARY )
283
+ if (!BrotliDecoderAttachDictionary (ctx -> decoder ,
284
+ BROTLI_SHARED_DICTIONARY_RAW ,
285
+ ZSTR_LEN (dict ), ZSTR_VAL (dict ))) {
286
+ php_error_docref (NULL , E_WARNING ,
287
+ "%sfailed to set uncompression dictionary" ,
288
+ (fail ? "" : "brotli: " ));
289
+ return FAILURE ;
290
+ }
291
+ #else
292
+ php_error_docref (NULL , E_WARNING ,
293
+ "%sfailed to not supported uncompression dictionary" ,
294
+ (fail ? "" : "brotli: " ));
295
+ return FAILURE ;
296
+ #endif
297
+ }
298
+
232
299
return SUCCESS ;
233
300
}
234
301
235
302
#define php_brotli_context_create_decoder (ctx ) \
236
- php_brotli_context_create_decoder_ex(ctx, 0)
303
+ php_brotli_context_create_decoder_ex(ctx, NULL, 0)
237
304
238
305
static void php_brotli_context_close (php_brotli_context * ctx )
239
306
{
@@ -245,6 +312,12 @@ static void php_brotli_context_close(php_brotli_context *ctx)
245
312
BrotliDecoderDestroyInstance (ctx -> decoder );
246
313
ctx -> decoder = NULL ;
247
314
}
315
+ #if defined(USE_BROTLI_DICTIONARY )
316
+ if (ctx -> dictionary ) {
317
+ BrotliEncoderDestroyPreparedDictionary (ctx -> dictionary );
318
+ ctx -> dictionary = NULL ;
319
+ }
320
+ #endif
248
321
249
322
if (ctx -> output ) {
250
323
efree (ctx -> output );
@@ -1063,6 +1136,14 @@ ZEND_MINIT_FUNCTION(brotli)
1063
1136
REGISTER_LONG_CONSTANT ("BROTLI_FINISH" , BROTLI_OPERATION_FINISH ,
1064
1137
CONST_CS | CONST_PERSISTENT );
1065
1138
1139
+ #if defined(USE_BROTLI_DICTIONARY )
1140
+ REGISTER_BOOL_CONSTANT ("BROTLI_DICTIONARY_SUPPORT" , 1 ,
1141
+ CONST_CS | CONST_PERSISTENT );
1142
+ #else
1143
+ REGISTER_BOOL_CONSTANT ("BROTLI_DICTIONARY_SUPPORT" , 0 ,
1144
+ CONST_CS | CONST_PERSISTENT );
1145
+ #endif
1146
+
1066
1147
php_output_handler_alias_register (ZEND_STRL (PHP_BROTLI_OUTPUT_HANDLER ),
1067
1148
php_brotli_output_handler_init );
1068
1149
php_output_handler_conflict_register (ZEND_STRL (PHP_BROTLI_OUTPUT_HANDLER ),
@@ -1176,6 +1257,11 @@ ZEND_MINFO_FUNCTION(brotli)
1176
1257
version >> 24 , (version >> 12 ) & 0xfff , version & 0xfff );
1177
1258
php_info_print_table_row (2 , "Library Version" , buffer );
1178
1259
#endif
1260
+ #if defined(USE_BROTLI_DICTIONARY )
1261
+ php_info_print_table_row (2 , "Dictionary support" , "enabled" );
1262
+ #else
1263
+ php_info_print_table_row (2 , "Dictionary support" , "disabled" );
1264
+ #endif
1179
1265
#if defined(HAVE_APCU_SUPPORT )
1180
1266
php_info_print_table_row (2 , "APCu serializer ABI" , APC_SERIALIZER_ABI );
1181
1267
#endif
@@ -1222,18 +1308,20 @@ static ZEND_FUNCTION(brotli_compress)
1222
1308
1223
1309
zend_long level = BROTLI_DEFAULT_QUALITY ;
1224
1310
zend_long mode = BROTLI_MODE_GENERIC ;
1311
+ zend_string * dict = NULL ;
1225
1312
1226
- ZEND_PARSE_PARAMETERS_START (1 , 3 )
1313
+ ZEND_PARSE_PARAMETERS_START (1 , 4 )
1227
1314
Z_PARAM_STRING (in , in_size )
1228
1315
Z_PARAM_OPTIONAL
1229
1316
Z_PARAM_LONG (level )
1230
1317
Z_PARAM_LONG (mode )
1318
+ Z_PARAM_STR_OR_NULL (dict )
1231
1319
ZEND_PARSE_PARAMETERS_END ();
1232
1320
1233
1321
php_brotli_context ctx ;
1234
1322
php_brotli_context_init (& ctx );
1235
1323
if (php_brotli_context_create_encoder_ex (& ctx , level , 0 , mode ,
1236
- 1 ) != SUCCESS ) {
1324
+ dict , 1 ) != SUCCESS ) {
1237
1325
php_brotli_context_close (& ctx );
1238
1326
RETURN_FALSE ;
1239
1327
}
@@ -1278,17 +1366,19 @@ static ZEND_FUNCTION(brotli_compress_init)
1278
1366
{
1279
1367
zend_long level = BROTLI_DEFAULT_QUALITY ;
1280
1368
zend_long mode = BROTLI_MODE_GENERIC ;
1369
+ zend_string * dict = NULL ;
1281
1370
1282
- ZEND_PARSE_PARAMETERS_START (0 , 2 )
1371
+ ZEND_PARSE_PARAMETERS_START (0 , 3 )
1283
1372
Z_PARAM_OPTIONAL
1284
1373
Z_PARAM_LONG (level )
1285
1374
Z_PARAM_LONG (mode )
1375
+ Z_PARAM_STR_OR_NULL (dict )
1286
1376
ZEND_PARSE_PARAMETERS_END ();
1287
1377
1288
1378
PHP_BROTLI_CONTEXT_OBJ_INIT_OF_CLASS (php_brotli_compress_context_ce );
1289
1379
1290
1380
if (php_brotli_context_create_encoder_ex (ctx , level , 0 , mode ,
1291
- 1 ) != SUCCESS ) {
1381
+ dict , 1 ) != SUCCESS ) {
1292
1382
zval_ptr_dtor (return_value );
1293
1383
RETURN_FALSE ;
1294
1384
}
@@ -1410,11 +1500,13 @@ static ZEND_FUNCTION(brotli_uncompress)
1410
1500
char * in ;
1411
1501
size_t in_size ;
1412
1502
smart_string out = {0 };
1503
+ zend_string * dict = NULL ;
1413
1504
1414
- ZEND_PARSE_PARAMETERS_START (1 , 2 )
1505
+ ZEND_PARSE_PARAMETERS_START (1 , 3 )
1415
1506
Z_PARAM_STRING (in , in_size )
1416
1507
Z_PARAM_OPTIONAL
1417
1508
Z_PARAM_LONG (max_size )
1509
+ Z_PARAM_STR_OR_NULL (dict )
1418
1510
ZEND_PARSE_PARAMETERS_END ();
1419
1511
1420
1512
if (max_size && max_size < in_size ) {
@@ -1423,7 +1515,7 @@ static ZEND_FUNCTION(brotli_uncompress)
1423
1515
1424
1516
php_brotli_context ctx ;
1425
1517
php_brotli_context_init (& ctx );
1426
- if (php_brotli_context_create_decoder_ex (& ctx , 1 ) != SUCCESS ) {
1518
+ if (php_brotli_context_create_decoder_ex (& ctx , dict , 1 ) != SUCCESS ) {
1427
1519
php_brotli_context_close (& ctx );
1428
1520
RETURN_FALSE ;
1429
1521
}
@@ -1463,13 +1555,16 @@ static ZEND_FUNCTION(brotli_uncompress)
1463
1555
1464
1556
static ZEND_FUNCTION (brotli_uncompress_init )
1465
1557
{
1466
- if (zend_parse_parameters_none () == FAILURE ) {
1467
- RETURN_FALSE ;
1468
- }
1558
+ zend_string * dict = NULL ;
1559
+
1560
+ ZEND_PARSE_PARAMETERS_START (0 , 1 )
1561
+ Z_PARAM_OPTIONAL
1562
+ Z_PARAM_STR_OR_NULL (dict )
1563
+ ZEND_PARSE_PARAMETERS_END ();
1469
1564
1470
1565
PHP_BROTLI_CONTEXT_OBJ_INIT_OF_CLASS (php_brotli_uncompress_context_ce );
1471
1566
1472
- if (php_brotli_context_create_decoder_ex (ctx , 1 ) != SUCCESS ) {
1567
+ if (php_brotli_context_create_decoder_ex (ctx , dict , 1 ) != SUCCESS ) {
1473
1568
zval_ptr_dtor (return_value );
1474
1569
RETURN_FALSE ;
1475
1570
}
0 commit comments