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