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