r6129: - add our own MSZIP decompression implementation
[bbaumbach/samba-autobuild/.git] / source4 / librpc / ndr / ndr_compression.c
index f09007a7154d9195e3b6d900fa85f5090a26193d..c806f62189e4737330bdfabd09651a1f1515a2b9 100644 (file)
 */
 
 #include "includes.h"
+#include "lib/compression/mszip.h"
 
-#ifdef HAVE_ZLIB
-#include <zlib.h>
-
-static NTSTATUS ndr_pull_compression_zlib_chunk(struct ndr_pull *ndrpull,
-                                               struct ndr_push *ndrpush,
-                                               struct z_stream_s *zs, int i)
+static NTSTATUS ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpull,
+                                                struct ndr_push *ndrpush,
+                                                struct decomp_state *decomp_state)
 {
-       uint8_t *comp_chunk;
+       DATA_BLOB comp_chunk;
        uint32_t comp_chunk_offset;
        uint32_t comp_chunk_size;
-       uint8_t *plain_chunk;
+       DATA_BLOB plain_chunk;
        uint32_t plain_chunk_offset;
        uint32_t plain_chunk_size;
-       uint8_t C_CK_marker;
-       uint8_t K_CK_marker;
        int ret;
 
-       /* I don't know why, this is needed... --metze */
-       if (i == 5) ndrpull->offset -=4;
-
        NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size));
        if (plain_chunk_size > 0x00008000) {
                return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad ZLIB plain chunk size %08X > 0x00008000 (PULL)", 
@@ -50,42 +43,23 @@ static NTSTATUS ndr_pull_compression_zlib_chunk(struct ndr_pull *ndrpull,
 
        NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &comp_chunk_size));
 
-       NDR_CHECK(ndr_pull_uint8(ndrpull, NDR_SCALARS, &C_CK_marker));
-       NDR_CHECK(ndr_pull_uint8(ndrpull, NDR_SCALARS, &K_CK_marker));
-       if (!(C_CK_marker == (uint8_t)'C' && K_CK_marker == (uint8_t)'K')) {
-               return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad ZLIB invalid CK marker C[%02X] K[%02X] (PULL)", 
-                                     C_CK_marker, K_CK_marker);
-       }
-
        DEBUG(10,("plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n",
                  plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size));
 
        comp_chunk_offset = ndrpull->offset;
        NDR_CHECK(ndr_pull_advance(ndrpull, comp_chunk_size));
-       comp_chunk = ndrpull->data + comp_chunk_offset;
+       comp_chunk.length = comp_chunk_size;
+       comp_chunk.data = ndrpull->data + comp_chunk_offset;
 
        plain_chunk_offset = ndrpush->offset;
        NDR_CHECK(ndr_push_zero(ndrpush, plain_chunk_size));
-       plain_chunk = ndrpush->data + plain_chunk_offset;
-
-       dump_data(10, comp_chunk, 16);
-
-       zs->avail_in = comp_chunk_size;
-       zs->next_in = comp_chunk;
-       zs->next_out = plain_chunk;
-       zs->avail_out = plain_chunk_size;
-
-       while (True) {
-               ret = inflate(zs, Z_BLOCK);
-               if (ret == Z_STREAM_END) {
-                       DEBUG(0,("comp_chunk_size: %u avail_in: %d, plain_chunk_size: %u, avail_out: %d\n",
-                               comp_chunk_size, zs->avail_in, plain_chunk_size, zs->avail_out));
-                       break;
-               }
-               if (ret != Z_OK) {
-                       return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad ZLIB (PULL) inflate error %d", 
+       plain_chunk.length = plain_chunk_size;
+       plain_chunk.data = ndrpush->data + plain_chunk_offset;
+
+       ret = ZIPdecompress(decomp_state, &comp_chunk, &plain_chunk);
+       if (ret != DECR_OK) {
+               return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, "Bad ZIBdecompress() error %d (PULL)",
                                      ret);
-               }
        }
 
        if ((plain_chunk_size < 0x00008000) || (ndrpull->offset+4 >= ndrpull->data_size)) {
@@ -96,84 +70,71 @@ static NTSTATUS ndr_pull_compression_zlib_chunk(struct ndr_pull *ndrpull,
        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-static NTSTATUS ndr_pull_compression_zlib(struct ndr_pull *subndr,
-                                         struct ndr_pull *comndr,
-                                         ssize_t decompressed_len)
+static NTSTATUS ndr_pull_compression_mszip(struct ndr_pull *subndr,
+                                          struct ndr_pull *comndr,
+                                          ssize_t decompressed_len)
 {
        NTSTATUS status = NT_STATUS_MORE_PROCESSING_REQUIRED;
        struct ndr_push *ndrpush;
        DATA_BLOB uncompressed;
-       struct z_stream_s zs;
-       int ret;
-       int i = 0;
-
-       ZERO_STRUCT(zs);
+       uint32_t payload_header[4];
+       uint32_t payload_size;
+       uint32_t payload_offset;
+       uint8_t *payload;
+       struct decomp_state *decomp_state;
 
        ndrpush = ndr_push_init_ctx(subndr);
        NT_STATUS_HAVE_NO_MEMORY(ndrpush);
 
-       ret = inflateInit2(&zs, -15);
-       if (ret != Z_OK) {
-               return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad ZLIB (PULL) inflateInit2 error %d", 
-                                     ret);
-       }
+       decomp_state = ZIPdecomp_state(subndr);
+       NT_STATUS_HAVE_NO_MEMORY(decomp_state);
 
        while (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
-               status = ndr_pull_compression_zlib_chunk(subndr, ndrpush, &zs, i++);
+               status = ndr_pull_compression_mszip_chunk(subndr, ndrpush, decomp_state);
        }
-       inflateEnd(&zs);
        NT_STATUS_NOT_OK_RETURN(status);
 
        uncompressed = ndr_push_blob(ndrpush);
 
+       if (uncompressed.length != decompressed_len) {
+               return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad uncompressed_len [%u] != [%d] (PULL)",
+                                     uncompressed.length, decompressed_len);
+       }
+
        *comndr = *subndr;
        comndr->data            = uncompressed.data;
        comndr->data_size       = uncompressed.length;
        comndr->offset          = 0;
 
-       return NT_STATUS_OK;
-}
+       NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[0]));
+       NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[1]));
+       NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[2]));
+       NDR_CHECK(ndr_pull_uint32(comndr, NDR_SCALARS, &payload_header[3]));
 
-static NTSTATUS ndr_push_compression_zlib(struct ndr_push *subndr,
-                                         struct ndr_push *comndr)
-{
-       DATA_BLOB inbuf;
-       DATA_BLOB outbuf = data_blob_talloc(comndr, NULL, comndr->offset + 10);
-       struct z_stream_s zs;
-       int ret;
+       payload_size = payload_header[2];
 
-       ZERO_STRUCT(zs);
-
-       inbuf = ndr_push_blob(comndr);
-
-       zs.avail_in = inbuf.length;
-       zs.next_in = inbuf.data;
-       zs.next_out = outbuf.data+10;
-       zs.avail_out = outbuf.length-10;
-
-       ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
-       if (ret != Z_OK) {
-               return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad ZLIB (PUSH) deflateInit2 error %d", 
-                                     ret);
-       }
-
-       ret = deflate(&zs, Z_SYNC_FLUSH);
-
-       if (ret != Z_OK && ret != Z_STREAM_END) {
-               return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad ZLIB (PULL) deflate error %d", 
-                                     ret);
+       /* TODO: check the first 4 bytes of the header */
+       if (payload_header[1] != 0xCCCCCCCC) {
+               return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad payload_header[1] [0x%08X] != [0xCCCCCCCC] (PULL)",
+                                     payload_header[1]);
        }
 
-       deflateEnd(&zs);
+       payload_offset = comndr->offset;
+       NDR_CHECK(ndr_pull_advance(comndr, payload_size));
+       payload = comndr->data + payload_offset;
 
-       /* TODO: push the header here */
-
-
-       NDR_CHECK(ndr_push_bytes(subndr, outbuf.data, outbuf.length));
+       comndr->data            = payload;
+       comndr->data_size       = payload_size;
+       comndr->offset          = 0;
 
        return NT_STATUS_OK;
 }
-#endif
+
+static NTSTATUS ndr_push_compression_mszip(struct ndr_push *subndr,
+                                         struct ndr_push *comndr)
+{
+       return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad MSZIP compression is not supported yet (PUSH)");
+}
 
 /*
   handle compressed subcontext buffers, which in midl land are user-marshalled, but
@@ -187,10 +148,8 @@ NTSTATUS ndr_pull_compression(struct ndr_pull *subndr,
        comndr->flags = subndr->flags;
 
        switch (compression_alg) {
-#ifdef HAVE_ZLIB
-       case NDR_COMPRESSION_ZLIB:
-               return ndr_pull_compression_zlib(subndr, comndr, decompressed_len);
-#endif
+       case NDR_COMPRESSION_MSZIP:
+               return ndr_pull_compression_mszip(subndr, comndr, decompressed_len);
        default:
                return ndr_pull_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PULL)", 
                                      compression_alg);
@@ -208,10 +167,8 @@ NTSTATUS ndr_push_compression(struct ndr_push *subndr,
        comndr->flags = subndr->flags;
 
        switch (compression_alg) {
-#ifdef HAVE_ZLIB
-       case NDR_COMPRESSION_ZLIB:
-               return ndr_push_compression_zlib(subndr, comndr);
-#endif
+       case NDR_COMPRESSION_MSZIP:
+               return ndr_push_compression_mszip(subndr, comndr);
        default:
                return ndr_push_error(subndr, NDR_ERR_COMPRESSION, "Bad compression algorithm %d (PUSH)", 
                                      compression_alg);