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