testing: re-organize recipes into categories
[dragora.git] / patches / unzip / unzip-6.0-alt-iconv-utf8-print.patch
blob0b0153ba54424fa095d9d2509c4d04eb4fc16383
1 From ca0212ba19b64488b9e8459a762c11ecd6e7d0bd Mon Sep 17 00:00:00 2001
2 From: Petr Stodulka <pstodulk@redhat.com>
3 Date: Tue, 24 Nov 2015 17:56:11 +0100
4 Subject: [PATCH] print correctly non-ascii filenames
6 ---
7 extract.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
8 unzpriv.h | 7 ++
9 2 files changed, 233 insertions(+), 63 deletions(-)
11 diff --git a/extract.c b/extract.c
12 index 0ee4e93..741b7e0 100644
13 --- a/extract.c
14 +++ b/extract.c
15 @@ -2648,8 +2648,21 @@ static void set_deferred_symlink(__G__ slnk_entry)
16 } /* end function set_deferred_symlink() */
17 #endif /* SYMLINKS */
19 +/*
20 + * If Unicode is supported, assume we have what we need to do this
21 + * check using wide characters, avoiding MBCS issues.
22 + */
25 +#ifndef UZ_FNFILTER_REPLACECHAR
26 + /* A convenient choice for the replacement of unprintable char codes is
27 + * the "single char wildcard", as this character is quite unlikely to
28 + * appear in filenames by itself. The following default definition
29 + * sets the replacement char to a question mark as the most common
30 + * "single char wildcard"; this setting should be overridden in the
31 + * appropiate system-specific configuration header when needed.
32 + */
33 +# define UZ_FNFILTER_REPLACECHAR '?'
34 +#endif
36 /*************************/
37 /* Function fnfilter() */ /* here instead of in list.c for SFX */
38 @@ -2661,48 +2674,168 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
39 extent size;
41 #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
42 - ZCONST uch *r=(ZCONST uch *)raw;
43 + ZCONST uch *r; // =(ZCONST uch *)raw;
44 uch *s=space;
45 uch *slim=NULL;
46 uch *se=NULL;
47 int have_overflow = FALSE;
49 - if (size > 0) {
50 - slim = space + size
51 -#ifdef _MBCS
52 - - (MB_CUR_MAX - 1)
53 -#endif
54 - - 4;
55 +# if defined( UNICODE_SUPPORT) && defined( _MBCS)
56 +/* If Unicode support is enabled, and we have multi-byte characters,
57 + * then do the isprint() checks by first converting to wide characters
58 + * and checking those. This avoids our having to parse multi-byte
59 + * characters for ourselves. After the wide-char replacements have been
60 + * made, the wide string is converted back to the local character set.
61 + */
62 + wchar_t *wstring; /* wchar_t version of raw */
63 + size_t wslen; /* length of wstring */
64 + wchar_t *wostring; /* wchar_t version of output string */
65 + size_t woslen; /* length of wostring */
66 + char *newraw; /* new raw */
68 + /* 2012-11-06 SMS.
69 + * Changed to check the value returned by mbstowcs(), and bypass the
70 + * Unicode processing if it fails. This seems to fix a problem
71 + * reported in the SourceForge forum, but it's not clear that we
72 + * should be doing any Unicode processing without some evidence that
73 + * the name actually is Unicode. (Check bit 11 in the flags before
74 + * coming here?)
75 + * http://sourceforge.net/p/infozip/bugs/40/
76 + */
78 + if (MB_CUR_MAX <= 1)
79 + {
80 + /* There's no point to converting multi-byte chars if there are
81 + * no multi-byte chars.
82 + */
83 + wslen = (size_t)-1;
85 - while (*r) {
86 - if (size > 0 && s >= slim && se == NULL) {
87 - se = s;
88 + else
89 + {
90 + /* Get Unicode wide character count (for storage allocation). */
91 + wslen = mbstowcs( NULL, raw, 0);
92 + }
94 + if (wslen != (size_t)-1)
95 + {
96 + /* Apparently valid Unicode. Allocate wide-char storage. */
97 + wstring = (wchar_t *)malloc((wslen + 1) * sizeof(wchar_t));
98 + if (wstring == NULL) {
99 + strcpy( (char *)space, raw);
100 + return (char *)space;
102 -#ifdef QDOS
103 - if (qlflag & 2) {
104 - if (*r == '/' || *r == '.') {
105 + wostring = (wchar_t *)malloc(2 * (wslen + 1) * sizeof(wchar_t));
106 + if (wostring == NULL) {
107 + free(wstring);
108 + strcpy( (char *)space, raw);
109 + return (char *)space;
112 + /* Convert the multi-byte Unicode to wide chars. */
113 + wslen = mbstowcs(wstring, raw, wslen + 1);
115 + /* Filter the wide-character string. */
116 + fnfilterw( wstring, wostring, (2 * (wslen + 1) * sizeof(wchar_t)));
118 + /* Convert filtered wide chars back to multi-byte. */
119 + woslen = wcstombs( NULL, wostring, 0);
120 + if ((newraw = malloc(woslen + 1)) == NULL) {
121 + free(wstring);
122 + free(wostring);
123 + strcpy( (char *)space, raw);
124 + return (char *)space;
126 + woslen = wcstombs( newraw, wostring, (woslen * MB_CUR_MAX) + 1);
128 + if (size > 0) {
129 + slim = space + size - 4;
131 + r = (ZCONST uch *)newraw;
132 + while (*r) {
133 + if (size > 0 && s >= slim && se == NULL) {
134 + se = s;
136 +# ifdef QDOS
137 + if (qlflag & 2) {
138 + if (*r == '/' || *r == '.') {
139 + if (se != NULL && (s > (space + (size-3)))) {
140 + have_overflow = TRUE;
141 + break;
143 + ++r;
144 + *s++ = '_';
145 + continue;
147 + } else
148 +# endif
150 if (se != NULL && (s > (space + (size-3)))) {
151 have_overflow = TRUE;
152 break;
154 - ++r;
155 - *s++ = '_';
156 - continue;
157 + *s++ = *r++;
159 - } else
161 + if (have_overflow) {
162 + strcpy((char *)se, "...");
163 + } else {
164 + *s = '\0';
167 + free(wstring);
168 + free(wostring);
169 + free(newraw);
171 + else
172 +# endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
174 + /* No Unicode support, or apparently invalid Unicode. */
175 + r = (ZCONST uch *)raw;
177 + if (size > 0) {
178 + slim = space + size
179 +#ifdef _MBCS
180 + - (MB_CUR_MAX - 1)
181 +#endif
182 + - 4;
184 + while (*r) {
185 + if (size > 0 && s >= slim && se == NULL) {
186 + se = s;
188 +#ifdef QDOS
189 + if (qlflag & 2) {
190 + if (*r == '/' || *r == '.') {
191 + if (se != NULL && (s > (space + (size-3)))) {
192 + have_overflow = TRUE;
193 + break;
195 + ++r;
196 + *s++ = '_';
197 + continue;
199 + } else
200 #endif
201 #ifdef HAVE_WORKING_ISPRINT
202 -# ifndef UZ_FNFILTER_REPLACECHAR
203 - /* A convenient choice for the replacement of unprintable char codes is
204 - * the "single char wildcard", as this character is quite unlikely to
205 - * appear in filenames by itself. The following default definition
206 - * sets the replacement char to a question mark as the most common
207 - * "single char wildcard"; this setting should be overridden in the
208 - * appropiate system-specific configuration header when needed.
209 - */
210 -# define UZ_FNFILTER_REPLACECHAR '?'
211 -# endif
212 - if (!isprint(*r)) {
213 + if (!isprint(*r)) {
214 + if (*r < 32) {
215 + /* ASCII control codes are escaped as "^{letter}". */
216 + if (se != NULL && (s > (space + (size-4)))) {
217 + have_overflow = TRUE;
218 + break;
220 + *s++ = '^', *s++ = (uch)(64 + *r++);
221 + } else {
222 + /* Other unprintable codes are replaced by the
223 + * placeholder character. */
224 + if (se != NULL && (s > (space + (size-3)))) {
225 + have_overflow = TRUE;
226 + break;
228 + *s++ = UZ_FNFILTER_REPLACECHAR;
229 + INCSTR(r);
231 +#else /* !HAVE_WORKING_ISPRINT */
232 if (*r < 32) {
233 /* ASCII control codes are escaped as "^{letter}". */
234 if (se != NULL && (s > (space + (size-4)))) {
235 @@ -2710,47 +2843,30 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
236 break;
238 *s++ = '^', *s++ = (uch)(64 + *r++);
239 +#endif /* ?HAVE_WORKING_ISPRINT */
240 } else {
241 - /* Other unprintable codes are replaced by the
242 - * placeholder character. */
243 +#ifdef _MBCS
244 + unsigned i = CLEN(r);
245 + if (se != NULL && (s > (space + (size-i-2)))) {
246 + have_overflow = TRUE;
247 + break;
249 + for (; i > 0; i--)
250 + *s++ = *r++;
251 +#else
252 if (se != NULL && (s > (space + (size-3)))) {
253 have_overflow = TRUE;
254 break;
256 - *s++ = UZ_FNFILTER_REPLACECHAR;
257 - INCSTR(r);
259 -#else /* !HAVE_WORKING_ISPRINT */
260 - if (*r < 32) {
261 - /* ASCII control codes are escaped as "^{letter}". */
262 - if (se != NULL && (s > (space + (size-4)))) {
263 - have_overflow = TRUE;
264 - break;
266 - *s++ = '^', *s++ = (uch)(64 + *r++);
267 -#endif /* ?HAVE_WORKING_ISPRINT */
268 - } else {
269 -#ifdef _MBCS
270 - unsigned i = CLEN(r);
271 - if (se != NULL && (s > (space + (size-i-2)))) {
272 - have_overflow = TRUE;
273 - break;
275 - for (; i > 0; i--)
276 *s++ = *r++;
277 -#else
278 - if (se != NULL && (s > (space + (size-3)))) {
279 - have_overflow = TRUE;
280 - break;
282 - *s++ = *r++;
283 #endif
286 - if (have_overflow) {
287 - strcpy((char *)se, "...");
288 - } else {
289 - *s = '\0';
292 + if (have_overflow) {
293 + strcpy((char *)se, "...");
294 + } else {
295 + *s = '\0';
299 #ifdef WINDLL
300 @@ -2772,6 +2888,53 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
301 } /* end function fnfilter() */
304 +#if defined( UNICODE_SUPPORT) && defined( _MBCS)
306 +/****************************/
307 +/* Function fnfilter[w]() */ /* (Here instead of in list.c for SFX.) */
308 +/****************************/
310 +/* fnfilterw() - Convert wide name to safely printable form. */
312 +/* fnfilterw() - Convert wide-character name to safely printable form. */
314 +wchar_t *fnfilterw( src, dst, siz)
315 + ZCONST wchar_t *src; /* Pointer to source char (string). */
316 + wchar_t *dst; /* Pointer to destination char (string). */
317 + extent siz; /* Not used (!). */
319 + wchar_t *dsx = dst;
321 + /* Filter the wide chars. */
322 + while (*src)
324 + if (iswprint( *src))
326 + /* Printable code. Copy it. */
327 + *dst++ = *src;
329 + else
331 + /* Unprintable code. Substitute something printable for it. */
332 + if (*src < 32)
334 + /* Replace ASCII control code with "^{letter}". */
335 + *dst++ = (wchar_t)'^';
336 + *dst++ = (wchar_t)(64 + *src);
338 + else
340 + /* Replace other unprintable code with the placeholder. */
341 + *dst++ = (wchar_t)UZ_FNFILTER_REPLACECHAR;
344 + src++;
346 + *dst = (wchar_t)0; /* NUL-terminate the destination string. */
347 + return dsx;
348 +} /* fnfilterw(). */
350 +#endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
353 #ifdef SET_DIR_ATTRIB
354 diff --git a/unzpriv.h b/unzpriv.h
355 index 22d3923..e48a652 100644
356 --- a/unzpriv.h
357 +++ b/unzpriv.h
358 @@ -1212,6 +1212,7 @@
359 # ifdef UNICODE_WCHAR
360 # if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP))
361 # include <wchar.h>
362 +# include <wctype.h>
363 # endif
364 # endif
365 # ifndef _MBCS /* no need to include <locale.h> twice, see below */
366 @@ -2410,6 +2411,12 @@ int memflush OF((__GPRO__ ZCONST uch *rawbuf, ulg size));
367 char *fnfilter OF((ZCONST char *raw, uch *space,
368 extent size));
370 +# if defined( UNICODE_SUPPORT) && defined( _MBCS)
371 +wchar_t *fnfilterw OF((ZCONST wchar_t *src, wchar_t *dst,
372 + extent siz));
373 +#endif
376 /*---------------------------------------------------------------------------
377 Decompression functions:
378 ---------------------------------------------------------------------------*/
380 2.4.3