/src/php-src/ext/standard/uuencode.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Copyright (c) The PHP Group | |
4 | | +----------------------------------------------------------------------+ |
5 | | | This source file is subject to version 3.01 of the PHP license, | |
6 | | | that is bundled with this package in the file LICENSE, and is | |
7 | | | available through the world-wide-web at the following url: | |
8 | | | https://www.php.net/license/3_01.txt | |
9 | | | If you did not receive a copy of the PHP license and are unable to | |
10 | | | obtain it through the world-wide-web, please send a note to | |
11 | | | license@php.net so we can mail you a copy immediately. | |
12 | | +----------------------------------------------------------------------+ |
13 | | | Author: Ilia Alshanetsky <ilia@php.net> | |
14 | | +----------------------------------------------------------------------+ |
15 | | */ |
16 | | |
17 | | /* |
18 | | * Portions of this code are based on Berkeley's uuencode/uudecode |
19 | | * implementation. |
20 | | * |
21 | | * Copyright (c) 1983, 1993 |
22 | | * The Regents of the University of California. All rights reserved. |
23 | | * |
24 | | * Redistribution and use in source and binary forms, with or without |
25 | | * modification, are permitted provided that the following conditions |
26 | | * are met: |
27 | | * 1. Redistributions of source code must retain the above copyright |
28 | | * notice, this list of conditions and the following disclaimer. |
29 | | * 2. Redistributions in binary form must reproduce the above copyright |
30 | | * notice, this list of conditions and the following disclaimer in the |
31 | | * documentation and/or other materials provided with the distribution. |
32 | | * 3. All advertising materials mentioning features or use of this software |
33 | | * must display the following acknowledgement: |
34 | | * This product includes software developed by the University of |
35 | | * California, Berkeley and its contributors. |
36 | | * 4. Neither the name of the University nor the names of its contributors |
37 | | * may be used to endorse or promote products derived from this software |
38 | | * without specific prior written permission. |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
41 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
44 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | | * SUCH DAMAGE. |
51 | | */ |
52 | | |
53 | | #include <math.h> |
54 | | |
55 | | #include "php.h" |
56 | | #include "php_uuencode.h" |
57 | | |
58 | 0 | #define PHP_UU_ENC(c) ((c) ? ((c) & 077) + ' ' : '`') |
59 | 0 | #define PHP_UU_ENC_C2(c) PHP_UU_ENC(((*(c) << 4) & 060) | ((*((c) + 1) >> 4) & 017)) |
60 | 0 | #define PHP_UU_ENC_C3(c) PHP_UU_ENC(((*(c + 1) << 2) & 074) | ((*((c) + 2) >> 6) & 03)) |
61 | | |
62 | 0 | #define PHP_UU_DEC(c) (((c) - ' ') & 077) |
63 | | |
64 | | PHPAPI zend_string *php_uuencode(const char *src, size_t src_len) /* {{{ */ |
65 | 0 | { |
66 | 0 | size_t len = 45; |
67 | 0 | unsigned char *p; |
68 | 0 | const unsigned char *s, *e, *ee; |
69 | 0 | zend_string *dest; |
70 | | |
71 | | /* encoded length is ~ 38% greater than the original |
72 | | Use 1.5 for easier calculation. |
73 | | */ |
74 | 0 | dest = zend_string_safe_alloc(src_len/2, 3, 46, 0); |
75 | 0 | p = (unsigned char *) ZSTR_VAL(dest); |
76 | 0 | s = (unsigned char *) src; |
77 | 0 | e = s + src_len; |
78 | |
|
79 | 0 | while ((s + 3) < e) { |
80 | 0 | ee = s + len; |
81 | 0 | if (ee > e) { |
82 | 0 | ee = e; |
83 | 0 | len = ee - s; |
84 | 0 | if (len % 3) { |
85 | 0 | ee = s + (int) (floor((double)len / 3) * 3); |
86 | 0 | } |
87 | 0 | } |
88 | 0 | *p++ = PHP_UU_ENC(len); |
89 | |
|
90 | 0 | while (s < ee) { |
91 | 0 | *p++ = PHP_UU_ENC(*s >> 2); |
92 | 0 | *p++ = PHP_UU_ENC_C2(s); |
93 | 0 | *p++ = PHP_UU_ENC_C3(s); |
94 | 0 | *p++ = PHP_UU_ENC(*(s + 2) & 077); |
95 | |
|
96 | 0 | s += 3; |
97 | 0 | } |
98 | |
|
99 | 0 | if (len == 45) { |
100 | 0 | *p++ = '\n'; |
101 | 0 | } |
102 | 0 | } |
103 | |
|
104 | 0 | if (s < e) { |
105 | 0 | if (len == 45) { |
106 | 0 | *p++ = PHP_UU_ENC(e - s); |
107 | 0 | len = 0; |
108 | 0 | } |
109 | |
|
110 | 0 | *p++ = PHP_UU_ENC(*s >> 2); |
111 | 0 | *p++ = PHP_UU_ENC_C2(s); |
112 | 0 | *p++ = ((e - s) > 1) ? PHP_UU_ENC_C3(s) : PHP_UU_ENC('\0'); |
113 | 0 | *p++ = ((e - s) > 2) ? PHP_UU_ENC(*(s + 2) & 077) : PHP_UU_ENC('\0'); |
114 | 0 | } |
115 | |
|
116 | 0 | if (len < 45) { |
117 | 0 | *p++ = '\n'; |
118 | 0 | } |
119 | |
|
120 | 0 | *p++ = PHP_UU_ENC('\0'); |
121 | 0 | *p++ = '\n'; |
122 | 0 | *p = '\0'; |
123 | |
|
124 | 0 | dest = zend_string_truncate(dest, (char *) p - ZSTR_VAL(dest), 0); |
125 | 0 | return dest; |
126 | 0 | } |
127 | | /* }}} */ |
128 | | |
129 | | PHPAPI zend_string *php_uudecode(const char *src, size_t src_len) /* {{{ */ |
130 | 0 | { |
131 | 0 | size_t len, total_len=0; |
132 | 0 | char *p; |
133 | 0 | const char *s, *e, *ee; |
134 | 0 | zend_string *dest; |
135 | |
|
136 | 0 | if (src_len == 0) { |
137 | 0 | return NULL; |
138 | 0 | } |
139 | | |
140 | 0 | dest = zend_string_alloc((size_t) ceil(src_len * 0.75), 0); |
141 | 0 | p = ZSTR_VAL(dest); |
142 | 0 | s = src; |
143 | 0 | e = src + src_len; |
144 | |
|
145 | 0 | while (s < e) { |
146 | 0 | if ((len = PHP_UU_DEC(*s++)) == 0) { |
147 | 0 | break; |
148 | 0 | } |
149 | | /* sanity check */ |
150 | 0 | if (len > src_len) { |
151 | 0 | goto err; |
152 | 0 | } |
153 | | |
154 | 0 | total_len += len; |
155 | |
|
156 | 0 | ee = s + (len == 45 ? 60 : (int) floor(len * 1.33)); |
157 | | /* sanity check */ |
158 | 0 | if (ee > e) { |
159 | 0 | goto err; |
160 | 0 | } |
161 | | |
162 | 0 | while (s < ee) { |
163 | 0 | if(s+4 > e) { |
164 | 0 | goto err; |
165 | 0 | } |
166 | 0 | *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4; |
167 | 0 | *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2; |
168 | 0 | *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3)); |
169 | 0 | s += 4; |
170 | 0 | } |
171 | | |
172 | 0 | if (len < 45) { |
173 | 0 | break; |
174 | 0 | } |
175 | | |
176 | | /* skip \n */ |
177 | 0 | s++; |
178 | 0 | } |
179 | | |
180 | 0 | assert(p >= ZSTR_VAL(dest)); |
181 | 0 | if ((len = total_len) > (size_t)(p - ZSTR_VAL(dest))) { |
182 | 0 | *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4; |
183 | 0 | if (len > 1) { |
184 | 0 | *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2; |
185 | 0 | if (len > 2) { |
186 | 0 | *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3)); |
187 | 0 | } |
188 | 0 | } |
189 | 0 | } |
190 | |
|
191 | 0 | ZSTR_LEN(dest) = total_len; |
192 | 0 | ZSTR_VAL(dest)[ZSTR_LEN(dest)] = '\0'; |
193 | |
|
194 | 0 | return dest; |
195 | | |
196 | 0 | err: |
197 | 0 | zend_string_efree(dest); |
198 | |
|
199 | 0 | return NULL; |
200 | 0 | } |
201 | | /* }}} */ |
202 | | |
203 | | /* {{{ uuencode a string */ |
204 | | PHP_FUNCTION(convert_uuencode) |
205 | 0 | { |
206 | 0 | zend_string *src; |
207 | |
|
208 | 0 | ZEND_PARSE_PARAMETERS_START(1, 1) |
209 | 0 | Z_PARAM_STR(src) |
210 | 0 | ZEND_PARSE_PARAMETERS_END(); |
211 | | |
212 | 0 | RETURN_STR(php_uuencode(ZSTR_VAL(src), ZSTR_LEN(src))); |
213 | 0 | } |
214 | | /* }}} */ |
215 | | |
216 | | /* {{{ decode a uuencoded string */ |
217 | | PHP_FUNCTION(convert_uudecode) |
218 | 0 | { |
219 | 0 | zend_string *src; |
220 | 0 | zend_string *dest; |
221 | |
|
222 | 0 | ZEND_PARSE_PARAMETERS_START(1, 1) |
223 | 0 | Z_PARAM_STR(src) |
224 | 0 | ZEND_PARSE_PARAMETERS_END(); |
225 | | |
226 | 0 | if ((dest = php_uudecode(ZSTR_VAL(src), ZSTR_LEN(src))) == NULL) { |
227 | 0 | php_error_docref(NULL, E_WARNING, "Argument #1 ($data) is not a valid uuencoded string"); |
228 | 0 | RETURN_FALSE; |
229 | 0 | } |
230 | | |
231 | 0 | RETURN_STR(dest); |
232 | 0 | } |
233 | | /* }}} */ |