]>
Commit | Line | Data |
---|---|---|
ba73ef48 | 1 | diff --git a/AUTHORS b/AUTHORS |
2 | index f65085d..b08ec55 100644 | |
3 | --- a/AUTHORS | |
4 | +++ b/AUTHORS | |
5 | @@ -215,6 +215,9 @@ Hugo Haas <hugo@larve.net> | |
6 | Minor random hacking | |
7 | debian/watch file | |
8 | ||
9 | +<incoherent@mail.ru> | |
10 | + bzip2 decoding fix and rewrite | |
11 | + | |
12 | Ingo Blechschmidt <iblech@web.de> | |
13 | German translation updates | |
14 | ||
15 | diff --git a/src/encoding/bzip2.c b/src/encoding/bzip2.c | |
16 | index 0291a39..c33b88e 100644 | |
17 | --- a/src/encoding/bzip2.c | |
18 | +++ b/src/encoding/bzip2.c | |
19 | @@ -12,6 +12,7 @@ #endif | |
20 | #ifdef HAVE_BZLIB_H | |
21 | #include <bzlib.h> /* Everything needs this after stdio.h */ | |
22 | #endif | |
23 | +#include <errno.h> | |
24 | ||
25 | #include "elinks.h" | |
26 | ||
27 | @@ -20,29 +21,32 @@ #include "encoding/encoding.h" | |
28 | #include "util/memory.h" | |
29 | ||
30 | ||
31 | +#define ELINKS_BZ_BUFFER_LENGTH BZ_MAX_UNUSED | |
32 | + | |
33 | struct bz2_enc_data { | |
34 | - FILE *file; | |
35 | - BZFILE *bzfile; | |
36 | - int last_read; /* If err after last bzRead() was BZ_STREAM_END.. */ | |
37 | + int fdread; | |
38 | + bz_stream fbz_stream; | |
39 | + int last_read; /* If err after last bzDecompress was BZ_STREAM_END.. */ | |
40 | + unsigned char buf[ELINKS_BZ_BUFFER_LENGTH]; | |
41 | }; | |
42 | ||
43 | -/* TODO: When it'll be official, use bzdopen() from Yoshioka Tsuneo. --pasky */ | |
44 | - | |
45 | static int | |
46 | bzip2_open(struct stream_encoded *stream, int fd) | |
47 | { | |
48 | struct bz2_enc_data *data = mem_alloc(sizeof(*data)); | |
49 | int err; | |
50 | ||
51 | + stream->data = 0; | |
52 | if (!data) { | |
53 | return -1; | |
54 | } | |
55 | - data->last_read = 0; | |
56 | - | |
57 | - data->file = fdopen(fd, "rb"); | |
58 | + memset(data, 0, sizeof(struct bz2_enc_data) - ELINKS_BZ_BUFFER_LENGTH); | |
59 | ||
60 | - data->bzfile = BZ2_bzReadOpen(&err, data->file, 0, 0, NULL, 0); | |
61 | - if (!data->bzfile) { | |
62 | + data->last_read = 0; | |
63 | + data->fdread = fd; | |
64 | + | |
65 | + err = BZ2_bzDecompressInit(&data->fbz_stream, 0, 0); | |
66 | + if (err != BZ_OK) { | |
67 | mem_free(data); | |
68 | return -1; | |
69 | } | |
70 | @@ -58,17 +62,44 @@ bzip2_read(struct stream_encoded *stream | |
71 | struct bz2_enc_data *data = (struct bz2_enc_data *) stream->data; | |
72 | int err = 0; | |
73 | ||
74 | - if (data->last_read) | |
75 | - return 0; | |
76 | + if (!data) return -1; | |
77 | ||
78 | - len = BZ2_bzRead(&err, data->bzfile, buf, len); | |
79 | + assert(len > 0); | |
80 | ||
81 | - if (err == BZ_STREAM_END) | |
82 | - data->last_read = 1; | |
83 | - else if (err) | |
84 | - return -1; | |
85 | + if (data->last_read) return 0; | |
86 | + | |
87 | + data->fbz_stream.avail_out = len; | |
88 | + data->fbz_stream.next_out = buf; | |
89 | + | |
90 | + do { | |
91 | + if (data->fbz_stream.avail_in == 0) { | |
92 | + int l = safe_read(data->fdread, data->buf, | |
93 | + ELINKS_BZ_BUFFER_LENGTH); | |
94 | ||
95 | - return len; | |
96 | + if (l == -1) { | |
97 | + if (errno == EAGAIN) | |
98 | + break; | |
99 | + else | |
100 | + return -1; /* I/O error */ | |
101 | + } else if (l == 0) { | |
102 | + /* EOF. It is error: we wait for more bytes */ | |
103 | + return -1; | |
104 | + } | |
105 | + | |
106 | + data->fbz_stream.next_in = data->buf; | |
107 | + data->fbz_stream.avail_in = l; | |
108 | + } | |
109 | + | |
110 | + err = BZ2_bzDecompress(&data->fbz_stream); | |
111 | + if (err == BZ_STREAM_END) { | |
112 | + data->last_read = 1; | |
113 | + break; | |
114 | + } else if (err != BZ_OK) { | |
115 | + return -1; | |
116 | + } | |
117 | + } while (data->fbz_stream.avail_out > 0); | |
118 | + | |
119 | + return len - data->fbz_stream.avail_out; | |
120 | } | |
121 | ||
122 | static unsigned char * | |
123 | @@ -148,11 +179,13 @@ static void | |
124 | bzip2_close(struct stream_encoded *stream) | |
125 | { | |
126 | struct bz2_enc_data *data = (struct bz2_enc_data *) stream->data; | |
127 | - int err; | |
128 | ||
129 | - BZ2_bzReadClose(&err, data->bzfile); | |
130 | - fclose(data->file); | |
131 | - mem_free(data); | |
132 | + if (data) { | |
133 | + BZ2_bzDecompressEnd(&data->fbz_stream); | |
134 | + close(data->fdread); | |
135 | + mem_free(data); | |
136 | + stream->data = 0; | |
137 | + } | |
138 | } | |
139 | ||
140 | static unsigned char *bzip2_extensions[] = { ".bz2", ".tbz", NULL }; | |
141 | diff --git a/src/protocol/http/http.c b/src/protocol/http/http.c | |
142 | index 87d468d..6f7469f 100644 | |
143 | --- a/src/protocol/http/http.c | |
144 | +++ b/src/protocol/http/http.c | |
145 | @@ -720,20 +720,13 @@ http_send_header(struct socket *socket) | |
146 | #if defined(CONFIG_GZIP) || defined(CONFIG_BZIP2) | |
147 | add_to_string(&header, "Accept-Encoding: "); | |
148 | ||
149 | -#ifdef BUG_517 | |
150 | #ifdef CONFIG_BZIP2 | |
151 | add_to_string(&header, "bzip2"); | |
152 | #endif | |
153 | -#endif | |
154 | - | |
155 | #ifdef CONFIG_GZIP | |
156 | - | |
157 | -#ifdef BUG_517 | |
158 | #ifdef CONFIG_BZIP2 | |
159 | add_to_string(&header, ", "); | |
160 | #endif | |
161 | -#endif | |
162 | - | |
163 | add_to_string(&header, "gzip"); | |
164 | #endif | |
165 | add_crlf_to_string(&header); | |
166 | @@ -1810,13 +1803,11 @@ #ifdef CONFIG_GZIP | |
167 | && (!strcasecmp(d, "gzip") || !strcasecmp(d, "x-gzip"))) | |
168 | conn->content_encoding = ENCODING_GZIP; | |
169 | #endif | |
170 | -#ifdef BUG_517 | |
171 | #ifdef CONFIG_BZIP2 | |
172 | if (file_encoding != ENCODING_BZIP2 | |
173 | && (!strcasecmp(d, "bzip2") || !strcasecmp(d, "x-bzip2"))) | |
174 | conn->content_encoding = ENCODING_BZIP2; | |
175 | #endif | |
176 | -#endif | |
177 | mem_free(d); | |
178 | } | |
179 |