1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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 /*
20 * Portions of this code are based on Berkeley's uuencode/uudecode
21 * implementation.
22 *
23 * Copyright (c) 1983, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 */
54
55 #include <math.h>
56
57 #include "php.h"
58 #include "php_uuencode.h"
59
60 #define PHP_UU_ENC(c) ((c) ? ((c) & 077) + ' ' : '`')
61 #define PHP_UU_ENC_C2(c) PHP_UU_ENC(((*(c) << 4) & 060) | ((*((c) + 1) >> 4) & 017))
62 #define PHP_UU_ENC_C3(c) PHP_UU_ENC(((*(c + 1) << 2) & 074) | ((*((c) + 2) >> 6) & 03))
63
64 #define PHP_UU_DEC(c) (((c) - ' ') & 077)
65
php_uuencode(char * src,size_t src_len)66 PHPAPI zend_string *php_uuencode(char *src, size_t src_len) /* {{{ */
67 {
68 size_t len = 45;
69 unsigned char *p, *s, *e, *ee;
70 zend_string *dest;
71
72 /* encoded length is ~ 38% greater than the original
73 Use 1.5 for easier calculation.
74 */
75 dest = zend_string_safe_alloc(src_len/2, 3, 46, 0);
76 p = (unsigned char *) ZSTR_VAL(dest);
77 s = (unsigned char *) src;
78 e = s + 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, (char *) p - ZSTR_VAL(dest), 0);
126 return dest;
127 }
128 /* }}} */
129
php_uudecode(char * src,size_t src_len)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_efree(dest);
194
195 return NULL;
196 }
197 /* }}} */
198
199 /* {{{ proto string convert_uuencode(string data)
200 uuencode a string */
PHP_FUNCTION(convert_uuencode)201 PHP_FUNCTION(convert_uuencode)
202 {
203 zend_string *src;
204
205 ZEND_PARSE_PARAMETERS_START(1, 1)
206 Z_PARAM_STR(src)
207 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
208 if (ZSTR_LEN(src) < 1) { RETURN_FALSE; }
209
210 RETURN_STR(php_uuencode(ZSTR_VAL(src), ZSTR_LEN(src)));
211 }
212 /* }}} */
213
214 /* {{{ proto string convert_uudecode(string data)
215 decode a uuencoded string */
PHP_FUNCTION(convert_uudecode)216 PHP_FUNCTION(convert_uudecode)
217 {
218 zend_string *src;
219 zend_string *dest;
220
221 ZEND_PARSE_PARAMETERS_START(1, 1)
222 Z_PARAM_STR(src)
223 ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
224 if (ZSTR_LEN(src) < 1) { RETURN_FALSE; }
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