/src/libzip/lib/zip_string.c
Line  | Count  | Source  | 
1  |  | /*  | 
2  |  |   zip_string.c -- string handling (with encoding)  | 
3  |  |   Copyright (C) 2012-2024 Dieter Baron and Thomas Klausner  | 
4  |  |  | 
5  |  |   This file is part of libzip, a library to manipulate ZIP archives.  | 
6  |  |   The authors can be contacted at <info@libzip.org>  | 
7  |  |  | 
8  |  |   Redistribution and use in source and binary forms, with or without  | 
9  |  |   modification, are permitted provided that the following conditions  | 
10  |  |   are met:  | 
11  |  |   1. Redistributions of source code must retain the above copyright  | 
12  |  |      notice, this list of conditions and the following disclaimer.  | 
13  |  |   2. Redistributions in binary form must reproduce the above copyright  | 
14  |  |      notice, this list of conditions and the following disclaimer in  | 
15  |  |      the documentation and/or other materials provided with the  | 
16  |  |      distribution.  | 
17  |  |   3. The names of the authors may not be used to endorse or promote  | 
18  |  |      products derived from this software without specific prior  | 
19  |  |      written permission.  | 
20  |  |  | 
21  |  |   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS  | 
22  |  |   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  | 
23  |  |   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  | 
24  |  |   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY  | 
25  |  |   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  | 
26  |  |   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE  | 
27  |  |   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  | 
28  |  |   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER  | 
29  |  |   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  | 
30  |  |   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN  | 
31  |  |   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
32  |  | */  | 
33  |  |  | 
34  |  |  | 
35  |  | #include "zipint.h"  | 
36  |  |  | 
37  |  | #include <stdlib.h>  | 
38  |  | #include <string.h>  | 
39  |  | #include <zlib.h>  | 
40  |  |  | 
41  |  | zip_uint32_t  | 
42  | 10.5k  | _zip_string_crc32(const zip_string_t *s) { | 
43  | 10.5k  |     zip_uint32_t crc;  | 
44  |  |  | 
45  | 10.5k  |     crc = (zip_uint32_t)crc32(0L, Z_NULL, 0);  | 
46  |  |  | 
47  | 10.5k  |     if (s != NULL)  | 
48  | 2.79k  |         crc = (zip_uint32_t)crc32(crc, s->raw, s->length);  | 
49  |  |  | 
50  | 10.5k  |     return crc;  | 
51  | 10.5k  | }  | 
52  |  |  | 
53  |  |  | 
54  |  | int  | 
55  | 0  | _zip_string_equal(const zip_string_t *a, const zip_string_t *b) { | 
56  | 0  |     if (a == NULL || b == NULL)  | 
57  | 0  |         return a == b;  | 
58  |  |  | 
59  | 0  |     if (a->length != b->length)  | 
60  | 0  |         return 0;  | 
61  |  |  | 
62  |  |     /* TODO: encoding */  | 
63  |  |  | 
64  | 0  |     return (memcmp(a->raw, b->raw, a->length) == 0);  | 
65  | 0  | }  | 
66  |  |  | 
67  |  |  | 
68  |  | void  | 
69  | 291k  | _zip_string_free(zip_string_t *s) { | 
70  | 291k  |     if (s == NULL)  | 
71  | 245k  |         return;  | 
72  |  |  | 
73  | 46.1k  |     free(s->raw);  | 
74  | 46.1k  |     free(s->converted);  | 
75  | 46.1k  |     free(s);  | 
76  | 46.1k  | }  | 
77  |  |  | 
78  |  |  | 
79  |  | const zip_uint8_t *  | 
80  | 105k  | _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error) { | 
81  | 105k  |     static const zip_uint8_t empty[1] = "";  | 
82  |  |  | 
83  | 105k  |     if (string == NULL) { | 
84  | 74.2k  |         if (lenp)  | 
85  | 0  |             *lenp = 0;  | 
86  | 74.2k  |         return empty;  | 
87  | 74.2k  |     }  | 
88  |  |  | 
89  | 31.2k  |     if ((flags & ZIP_FL_ENC_RAW) == 0) { | 
90  |  |         /* start guessing */  | 
91  | 31.2k  |         if (string->encoding == ZIP_ENCODING_UNKNOWN) { | 
92  |  |             /* guess encoding, sets string->encoding */  | 
93  | 15.0k  |             (void)_zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN);  | 
94  | 15.0k  |         }  | 
95  |  |  | 
96  | 31.2k  |         if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) { | 
97  | 5.57k  |             if (string->converted == NULL) { | 
98  | 2.78k  |                 if ((string->converted = _zip_cp437_to_utf8(string->raw, string->length, &string->converted_length, error)) == NULL)  | 
99  | 0  |                     return NULL;  | 
100  | 2.78k  |             }  | 
101  | 5.57k  |             if (lenp)  | 
102  | 0  |                 *lenp = string->converted_length;  | 
103  | 5.57k  |             return string->converted;  | 
104  | 5.57k  |         }  | 
105  | 31.2k  |     }  | 
106  |  |  | 
107  | 25.6k  |     if (lenp)  | 
108  | 0  |         *lenp = string->length;  | 
109  | 25.6k  |     return string->raw;  | 
110  | 31.2k  | }  | 
111  |  |  | 
112  | 0  | bool _zip_string_is_ascii(const zip_string_t *string) { | 
113  | 0  |     if (string->encoding != ZIP_ENCODING_ASCII) { | 
114  | 0  |         zip_uint16_t i;  | 
115  |  | 
  | 
116  | 0  |         for (i = 0; i < string->length; i++) { | 
117  | 0  |             if (string->raw[i] & 0x80) { | 
118  | 0  |                 return false;  | 
119  | 0  |             }  | 
120  | 0  |         }  | 
121  | 0  |     }  | 
122  |  |  | 
123  | 0  |     return true;  | 
124  | 0  | }  | 
125  |  |  | 
126  |  |  | 
127  |  | zip_uint16_t  | 
128  | 7.52k  | _zip_string_length(const zip_string_t *s) { | 
129  | 7.52k  |     if (s == NULL)  | 
130  | 3.85k  |         return 0;  | 
131  |  |  | 
132  | 3.66k  |     return s->length;  | 
133  | 7.52k  | }  | 
134  |  |  | 
135  |  |  | 
136  |  | zip_string_t *  | 
137  | 46.2k  | _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error) { | 
138  | 46.2k  |     zip_string_t *s;  | 
139  | 46.2k  |     zip_encoding_type_t expected_encoding;  | 
140  |  |  | 
141  | 46.2k  |     if (length == 0)  | 
142  | 159  |         return NULL;  | 
143  |  |  | 
144  | 46.1k  |     switch (flags & ZIP_FL_ENCODING_ALL) { | 
145  | 36.8k  |     case ZIP_FL_ENC_GUESS:  | 
146  | 36.8k  |         expected_encoding = ZIP_ENCODING_UNKNOWN;  | 
147  | 36.8k  |         break;  | 
148  | 9.24k  |     case ZIP_FL_ENC_UTF_8:  | 
149  | 9.24k  |         expected_encoding = ZIP_ENCODING_UTF8_KNOWN;  | 
150  | 9.24k  |         break;  | 
151  | 0  |     case ZIP_FL_ENC_CP437:  | 
152  | 0  |         expected_encoding = ZIP_ENCODING_CP437;  | 
153  | 0  |         break;  | 
154  | 0  |     default:  | 
155  | 0  |         zip_error_set(error, ZIP_ER_INVAL, 0);  | 
156  | 0  |         return NULL;  | 
157  | 46.1k  |     }  | 
158  |  |  | 
159  | 46.1k  |     if ((s = (zip_string_t *)malloc(sizeof(*s))) == NULL) { | 
160  | 0  |         zip_error_set(error, ZIP_ER_MEMORY, 0);  | 
161  | 0  |         return NULL;  | 
162  | 0  |     }  | 
163  |  |  | 
164  | 46.1k  |     if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) { | 
165  | 0  |         free(s);  | 
166  | 0  |         return NULL;  | 
167  | 0  |     }  | 
168  |  |  | 
169  | 46.1k  |     (void)memcpy_s(s->raw, length + 1, raw, length);  | 
170  | 46.1k  |     s->raw[length] = '\0';  | 
171  | 46.1k  |     s->length = length;  | 
172  | 46.1k  |     s->encoding = ZIP_ENCODING_UNKNOWN;  | 
173  | 46.1k  |     s->converted = NULL;  | 
174  | 46.1k  |     s->converted_length = 0;  | 
175  |  |  | 
176  | 46.1k  |     if (expected_encoding != ZIP_ENCODING_UNKNOWN) { | 
177  | 9.24k  |         if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { | 
178  | 5.27k  |             _zip_string_free(s);  | 
179  | 5.27k  |             zip_error_set(error, ZIP_ER_INVAL, 0);  | 
180  | 5.27k  |             return NULL;  | 
181  | 5.27k  |         }  | 
182  | 9.24k  |     }  | 
183  |  |  | 
184  | 40.8k  |     return s;  | 
185  | 46.1k  | }  | 
186  |  |  | 
187  |  |  | 
188  |  | int  | 
189  | 2.81k  | _zip_string_write(zip_t *za, const zip_string_t *s) { | 
190  | 2.81k  |     if (s == NULL)  | 
191  | 0  |         return 0;  | 
192  |  |  | 
193  | 2.81k  |     return _zip_write(za, s->raw, s->length);  | 
194  | 2.81k  | }  |