1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2016 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
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 dest = zend_string_alloc((size_t)ceil(src_len * 1.38) + 46, 0);
76 p = ZSTR_VAL(dest);
77 s = src;
78 e = src + src_len;
79
80 while ((s + 3) < e) {
81 ee = s + len;
82 if (ee > e) {
83 ee = e;
84 len = ee - s;
85 if (len % 3) {
86 ee = s + (int) (floor((double)len / 3) * 3);
87 }
88 }
89 *p++ = PHP_UU_ENC(len);
90
91 while (s < ee) {
92 *p++ = PHP_UU_ENC(*s >> 2);
93 *p++ = PHP_UU_ENC_C2(s);
94 *p++ = PHP_UU_ENC_C3(s);
95 *p++ = PHP_UU_ENC(*(s + 2) & 077);
96
97 s += 3;
98 }
99
100 if (len == 45) {
101 *p++ = '\n';
102 }
103 }
104
105 if (s < e) {
106 if (len == 45) {
107 *p++ = PHP_UU_ENC(e - s);
108 len = 0;
109 }
110
111 *p++ = PHP_UU_ENC(*s >> 2);
112 *p++ = PHP_UU_ENC_C2(s);
113 *p++ = ((e - s) > 1) ? PHP_UU_ENC_C3(s) : PHP_UU_ENC('\0');
114 *p++ = ((e - s) > 2) ? PHP_UU_ENC(*(s + 2) & 077) : PHP_UU_ENC('\0');
115 }
116
117 if (len < 45) {
118 *p++ = '\n';
119 }
120
121 *p++ = PHP_UU_ENC('\0');
122 *p++ = '\n';
123 *p = '\0';
124
125 dest = zend_string_truncate(dest, p - ZSTR_VAL(dest), 0);
126 return dest;
127 }
128 /* }}} */
129
130 PHPAPI zend_string *php_uudecode(char *src, size_t src_len) /* {{{ */
131 {
132 size_t len, total_len=0;
133 char *s, *e, *p, *ee;
134 zend_string *dest;
135
136 dest = zend_string_alloc((size_t) ceil(src_len * 0.75), 0);
137 p = ZSTR_VAL(dest);
138 s = src;
139 e = src + src_len;
140
141 while (s < e) {
142 if ((len = PHP_UU_DEC(*s++)) <= 0) {
143 break;
144 }
145 /* sanity check */
146 if (len > src_len) {
147 goto err;
148 }
149
150 total_len += len;
151
152 ee = s + (len == 45 ? 60 : (int) floor(len * 1.33));
153 /* sanity check */
154 if (ee > e) {
155 goto err;
156 }
157
158 while (s < ee) {
159 if(s+4 > e) {
160 goto err;
161 }
162 *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4;
163 *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2;
164 *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3));
165 s += 4;
166 }
167
168 if (len < 45) {
169 break;
170 }
171
172 /* skip \n */
173 s++;
174 }
175
176 assert(p >= ZSTR_VAL(dest));
177 if ((len = total_len) > (size_t)(p - ZSTR_VAL(dest))) {
178 *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4;
179 if (len > 1) {
180 *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2;
181 if (len > 2) {
182 *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3));
183 }
184 }
185 }
186
187 ZSTR_LEN(dest) = total_len;
188 ZSTR_VAL(dest)[ZSTR_LEN(dest)] = '\0';
189
190 return dest;
191
192 err:
193 zend_string_free(dest);
194
195 return NULL;
196 }
197 /* }}} */
198
199 /* {{{ proto string convert_uuencode(string data)
200 uuencode a string */
201 PHP_FUNCTION(convert_uuencode)
202 {
203 zend_string *src;
204
205 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &src) == FAILURE || ZSTR_LEN(src) < 1) {
206 RETURN_FALSE;
207 }
208
209 RETURN_STR(php_uuencode(ZSTR_VAL(src), ZSTR_LEN(src)));
210 }
211 /* }}} */
212
213 /* {{{ proto string convert_uudecode(string data)
214 decode a uuencoded string */
215 PHP_FUNCTION(convert_uudecode)
216 {
217 zend_string *src;
218 zend_string *dest;
219
220 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &src) == FAILURE || ZSTR_LEN(src) < 1) {
221 RETURN_FALSE;
222 }
223
224 if ((dest = php_uudecode(ZSTR_VAL(src), ZSTR_LEN(src))) == NULL) {
225 php_error_docref(NULL, E_WARNING, "The given parameter is not a valid uuencoded string");
226 RETURN_FALSE;
227 }
228
229 RETURN_STR(dest);
230 }
231 /* }}} */
232
233 /*
234 * Local variables:
235 * tab-width: 4
236 * c-basic-offset: 4
237 * End:
238 * vim600: noet sw=4 ts=4 fdm=marker
239 * vim<600: noet sw=4 ts=4
240 */