summaryrefslogtreecommitdiff
path: root/src/cos_stream_filter.c
blob: 0c08442ee0f763eefa9b2159943c9ccb89de2150 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * Copyright 2018 Vincent Sanders <vince@netsurf-browser.org>
 *
 * This file is part of libnspdf.
 *
 * Licensed under the MIT License,
 *                http://www.opensource.org/licenses/mit-license.php
 */

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <zlib.h>

#include <nspdf/errors.h>

#include "cos_object.h"
#include "pdf_doc.h"

static nspdferror
cos_stream_inflate(struct nspdf_doc *doc, struct cos_stream **stream_out)
{
    int ret;
    z_stream strm;
    struct cos_stream *stream_in;
    struct cos_stream *stream_res;

    stream_in = *stream_out;

    stream_res = calloc(1, sizeof(struct cos_stream));

    //printf("inflating from %d bytes\n", stream_in->length);

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;

    ret = inflateInit(&strm);
    if (ret != Z_OK) {
        return NSPDFERROR_NOTFOUND;
    }

    strm.next_in = (void *)stream_in->data;
    strm.avail_in = stream_in->length;

    do {
        int64_t available; /* available buffer space for decompression */
        available = stream_res->alloc - stream_res->length;

        if (available < (strm.avail_in << 1)) {
            uint8_t *newdata;
            size_t newlength;

            newlength = stream_res->alloc + (stream_in->length << 1);
            newdata = realloc((void *)stream_res->data, newlength);
            if (newdata == NULL) {
                free((void *)stream_res->data);
                free(stream_res);
                inflateEnd(&strm);
                return NSPDFERROR_NOMEM;
            }

            //printf("realloc %d\n", newlength);

            stream_res->data = newdata;
            stream_res->alloc = newlength;
            available = stream_res->alloc - stream_res->length;
        }

        strm.avail_out = available;
        strm.next_out = (void*)(stream_res->data + stream_res->length);
        ret = inflate(&strm, Z_NO_FLUSH);
        /** \todo check zlib return code */

        stream_res->length += (available - strm.avail_out);

    } while (ret != Z_STREAM_END);

    //printf("allocated %d\n", stream_res->alloc);

    //printf("length %d\n", stream_res->length);

    inflateEnd(&strm);

    if (stream_in->alloc != 0) {
        free((void*)stream_in->data);
    }
    free(stream_in);

    *stream_out = stream_res;

    return NSPDFERROR_OK;
}

nspdferror
nspdf__cos_stream_filter(struct nspdf_doc *doc,
                         const char *filter_name,
                         struct cos_stream **stream_out)
{
    nspdferror res;

    //printf("applying filter %s\n", filter_name);

    if (strcmp(filter_name, "FlateDecode") == 0) {
        res = cos_stream_inflate(doc, stream_out);
    } else {
        res = NSPDFERROR_NOTFOUND;
    }

    return res;
}