]> granicus.if.org Git - php/commitdiff
(PHP gzencode) Reimplementation of gzencode(). Now works as documented
authorStefan Roehrich <sr@php.net>
Tue, 12 Mar 2002 13:23:58 +0000 (13:23 +0000)
committerStefan Roehrich <sr@php.net>
Tue, 12 Mar 2002 13:23:58 +0000 (13:23 +0000)
               (gzencode(string data [, int level [, int encoding_mode]])),
               should fix #15930.
@- The second parameter of gzencode() now is the compression level like
@  in the documentation. The encoding mode is a third (optional) parameter.
# Rework of gzencode(), output should be closer to real gzip output.
# I think in the old version there could be some problems with
# this function and output compression, should be fixed, too.

ext/zlib/tests/003.phpt
ext/zlib/zlib.c

index 322996fa75179eb033598c48a0f8fd31e102e0ac..254a4563adc712bc2a71090ccf579086569b7800 100644 (file)
@@ -9,8 +9,8 @@ gzencode()/base64_encode()
 $original = str_repeat("hallo php",4096);
 $packed=gzencode($original);
 echo strlen($packed)." ".strlen($original)."\n";
-if (strcmp(base64_encode($packed),"H4sIAAAAAAAAA+zGoQ0AQAgEsFV+NdwJEthf/R6kVU11z9tsRERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERETu5gMAAP//AwDlQAe9AJAAAA==")==0) echo "Strings are equal";
+if (strcmp(base64_encode($packed),"H4sIAAAAAAAAA+3GoQ0AQAgEsFV+NdwJEthf/R6kVU11z9tsRERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERETu5gPlQAe9AJAAAA==")==0) echo "Strings are equal";
 ?>
 --EXPECT--
-124 36864
+118 36864
 Strings are equal
index 02889609c74e8ef5272ce5c5df4eeec9c24b96c7..fdb54ca76e5111541202d5d756a4bfabd66f79b9 100644 (file)
@@ -76,6 +76,8 @@
 #define OS_CODE                        0x03 /* FIXME */
 #define CODING_GZIP            1
 #define CODING_DEFLATE 2
+#define GZIP_HEADER_LENGTH             10
+#define GZIP_FOOTER_LENGTH             8
 
 /* True globals, no need for thread safety */
 static int le_zp;
@@ -761,7 +763,7 @@ PHP_FUNCTION(gzcompress)
                convert_to_long_ex(zlimit);
                limit = Z_LVAL_PP(zlimit);
                if((limit<0)||(limit>9)) {
-                       php_error(E_WARNING,"gzcompress: compression level must be whithin 0..9");
+                       php_error(E_WARNING,"gzcompress: compression level must be within 0..9");
                        RETURN_FALSE;
                }
                break;
@@ -870,7 +872,7 @@ PHP_FUNCTION(gzdeflate)
                convert_to_long_ex(zlimit);
                level = Z_LVAL_PP(zlimit);
                if((level<0)||(level>9)) {
-                       php_error(E_WARNING,"gzdeflate: compression level must be whithin 0..9");
+                       php_error(E_WARNING,"gzdeflate: compression level must be within 0..9");
                        RETURN_FALSE;
                }
                break;
@@ -1124,36 +1126,104 @@ int php_deflate_string(const char *str, uint str_length, char **newstr, uint *ne
 }
 /* }}} */
 
-/* {{{ proto string gzencode(string data [, int encoding_mode])
+/* {{{ proto string gzencode(string data [, int level [, int encoding_mode]])
    GZ encode a string */
 PHP_FUNCTION(gzencode)
 {
-       zval **zv_coding, **zv_string;
-       int coding;
+       char *data, *s2;
+       int data_len;
+       int level = Z_DEFAULT_COMPRESSION, coding = CODING_GZIP;
+       int status;
+       z_stream stream;
 
-       switch(ZEND_NUM_ARGS()) {
-               case 1:
-                       if (zend_get_parameters_ex(1, &zv_string)==FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &coding) == FAILURE) {
+               return;
+       }
+
+       if((level<-1)||(level>9)) {
+               php_error(E_WARNING,"gzencode: compression level must be within -1..9");
+               RETURN_FALSE;
+       }
+
+       if((coding!=CODING_GZIP)&&(coding!=CODING_DEFLATE)) {
+               php_error(E_WARNING,"gzencode: encoding mode must be FORCE_GZIP or FORCE_DEFLATE");
+               RETURN_FALSE;
+       }
+
+       stream.zalloc = Z_NULL;
+       stream.zfree = Z_NULL;
+       stream.opaque = Z_NULL;
+
+       stream.next_in = (Bytef*) data;
+       stream.avail_in = data_len;
+
+       stream.avail_out = stream.avail_in + (stream.avail_in/1000) + 15 + 1; /* room for \0 */
+       s2 = (char *) emalloc(stream.avail_out+GZIP_HEADER_LENGTH+(coding==CODING_GZIP?GZIP_FOOTER_LENGTH:0));
+       if(!s2)
+               RETURN_FALSE;
+
+       /* add gzip file header */
+       s2[0] = gz_magic[0];
+       s2[1] = gz_magic[1];
+       s2[2] = Z_DEFLATED;
+       s2[3] = s2[4] = s2[5] = s2[6] = s2[7] = s2[8] = 0; /* time set to 0 */
+       s2[9] = OS_CODE;
+
+       stream.next_out = &(s2[GZIP_HEADER_LENGTH]);
+
+       switch (coding) {
+               case CODING_GZIP:
+                       /* windowBits is passed < 0 to suppress zlib header & trailer */
+                       if ((status = deflateInit2(&stream, level, Z_DEFLATED,
+                                                                         -MAX_WBITS, MAX_MEM_LEVEL,
+                                                                          Z_DEFAULT_STRATEGY))
+                                                       != Z_OK) {
+                               php_error(E_WARNING,"gzencode: %s", zError(status));
                                RETURN_FALSE;
                        }
-                       convert_to_string_ex(zv_string);
-                       coding = 1;
+               
                        break;
-               case 2:
-                       if (zend_get_parameters_ex(2, &zv_string, &zv_coding)==FAILURE) {
+               case CODING_DEFLATE:
+                       if ((status = deflateInit(&stream, level)) != Z_OK) {
+                               php_error(E_WARNING,"gzencode: %s", zError(status));
                                RETURN_FALSE;
                        }
-                       convert_to_string_ex(zv_string);
-                       convert_to_long_ex(zv_coding);
-                       coding = Z_LVAL_PP(zv_coding);
-                       break;
-               default:
-                       ZEND_WRONG_PARAM_COUNT();
-                       break;
+                       break;          
        }
-       if (php_deflate_string(Z_STRVAL_PP(zv_string), Z_STRLEN_PP(zv_string), &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), coding, 1, 1 TSRMLS_CC)==SUCCESS) {
-               Z_TYPE_P(return_value) = IS_STRING;
+
+       status = deflate(&stream, Z_FINISH);
+       if (status != Z_STREAM_END) {
+               deflateEnd(&stream);
+               if (status == Z_OK) {
+                       status = Z_BUF_ERROR;
+               }
        } else {
+               status = deflateEnd(&stream);
+       }
+
+       if (status==Z_OK) {
+               s2 = erealloc(s2,stream.total_out+GZIP_HEADER_LENGTH+(coding==CODING_GZIP?GZIP_FOOTER_LENGTH:0)+1); /* resize to buffer to the "right" size */
+               if (coding == CODING_GZIP) {
+                       char *trailer = s2+(stream.total_out+GZIP_HEADER_LENGTH);
+                       uLong crc = crc32(0L, Z_NULL, 0);
+
+                       crc = crc32(crc, (const Bytef *) data, data_len);
+
+                       /* write crc & stream.total_in in LSB order */
+                       trailer[0] = (char) crc & 0xFF;
+                       trailer[1] = (char) (crc >> 8) & 0xFF;
+                       trailer[2] = (char) (crc >> 16) & 0xFF;
+                       trailer[3] = (char) (crc >> 24) & 0xFF;
+                       trailer[4] = (char) stream.total_in & 0xFF;
+                       trailer[5] = (char) (stream.total_in >> 8) & 0xFF;
+                       trailer[6] = (char) (stream.total_in >> 16) & 0xFF;
+                       trailer[7] = (char) (stream.total_in >> 24) & 0xFF;
+                       trailer[8] = '\0';
+       }
+               RETURN_STRINGL(s2, stream.total_out+GZIP_HEADER_LENGTH+(coding==CODING_GZIP?GZIP_FOOTER_LENGTH:0), 0);
+       } else {
+               efree(s2);
+               php_error(E_WARNING,"gzencode: %s",zError(status));
                RETURN_FALSE;
        }
 }