Back to index

php5  5.3.10
uuencode.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Ilia Alshanetsky <ilia@php.net>                              |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: uuencode.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 /*
00022  * Portions of this code are based on Berkeley's uuencode/uudecode
00023  * implementation.
00024  *
00025  * Copyright (c) 1983, 1993
00026  *  The Regents of the University of California.  All rights reserved.
00027  *
00028  * Redistribution and use in source and binary forms, with or without
00029  * modification, are permitted provided that the following conditions
00030  * are met:
00031  * 1. Redistributions of source code must retain the above copyright
00032  *    notice, this list of conditions and the following disclaimer.
00033  * 2. Redistributions in binary form must reproduce the above copyright
00034  *    notice, this list of conditions and the following disclaimer in the
00035  *    documentation and/or other materials provided with the distribution.
00036  * 3. All advertising materials mentioning features or use of this software
00037  *    must display the following acknowledgement:
00038  *  This product includes software developed by the University of
00039  *  California, Berkeley and its contributors.
00040  * 4. Neither the name of the University nor the names of its contributors
00041  *    may be used to endorse or promote products derived from this software
00042  *    without specific prior written permission.
00043  *
00044  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00045  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00046  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00047  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00048  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00049  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00050  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00051  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00052  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00053  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00054  * SUCH DAMAGE.
00055  */
00056 
00057 #include <math.h>
00058 
00059 #include "php.h"
00060 #include "php_uuencode.h"
00061 
00062 #define PHP_UU_ENC(c) ((c) ? ((c) & 077) + ' ' : '`')
00063 #define PHP_UU_ENC_C2(c) PHP_UU_ENC(((*(c) << 4) & 060) | ((*((c) + 1) >> 4) & 017))
00064 #define PHP_UU_ENC_C3(c) PHP_UU_ENC(((*(c + 1) << 2) & 074) | ((*((c) + 2) >> 6) & 03))
00065 
00066 #define PHP_UU_DEC(c) (((c) - ' ') & 077)
00067 
00068 PHPAPI int php_uuencode(char *src, int src_len, char **dest) /* {{{ */
00069 {
00070        int len = 45;
00071        char *p, *s, *e, *ee;
00072 
00073        /* encoded length is ~ 38% greater then the original */
00074        p = *dest = safe_emalloc((size_t) ceil(src_len * 1.38), 1, 46);
00075        s = src;
00076        e = src + src_len;
00077 
00078        while ((s + 3) < e) {
00079               ee = s + len;
00080               if (ee > e) {
00081                      ee = e;
00082                      len = ee - s;
00083                      if (len % 3) {
00084                             ee = s + (int) (floor(len / 3) * 3);
00085                      }
00086               }
00087               *p++ = PHP_UU_ENC(len);
00088 
00089               while (s < ee) {
00090                      *p++ = PHP_UU_ENC(*s >> 2);
00091                      *p++ = PHP_UU_ENC_C2(s);
00092                      *p++ = PHP_UU_ENC_C3(s);
00093                      *p++ = PHP_UU_ENC(*(s + 2) & 077);
00094 
00095                      s += 3;
00096               }
00097 
00098               if (len == 45) {
00099                      *p++ = '\n';
00100               }
00101        }
00102 
00103        if (s < e) {
00104               if (len == 45) {
00105                      *p++ = PHP_UU_ENC(e - s);
00106                      len = 0;
00107               }
00108 
00109               *p++ = PHP_UU_ENC(*s >> 2);
00110               *p++ = PHP_UU_ENC_C2(s);
00111               *p++ = ((e - s) > 1) ? PHP_UU_ENC_C3(s) : PHP_UU_ENC('\0');
00112               *p++ = ((e - s) > 2) ? PHP_UU_ENC(*(s + 2) & 077) : PHP_UU_ENC('\0');
00113        }
00114 
00115        if (len < 45) {
00116               *p++ = '\n';
00117        }
00118 
00119        *p++ = PHP_UU_ENC('\0');
00120        *p++ = '\n';
00121        *p = '\0';
00122 
00123        return (p - *dest);
00124 }
00125 /* }}} */
00126 
00127 PHPAPI int php_uudecode(char *src, int src_len, char **dest) /* {{{ */
00128 {
00129        int len, total_len=0;
00130        char *s, *e, *p, *ee;
00131 
00132        p = *dest = safe_emalloc((size_t) ceil(src_len * 0.75), 1, 1);
00133        s = src;
00134        e = src + src_len;
00135 
00136        while (s < e) {
00137               if ((len = PHP_UU_DEC(*s++)) <= 0) {
00138                      break;
00139               }
00140               /* sanity check */
00141               if (len > src_len) {
00142                      goto err;
00143               }
00144 
00145               total_len += len;
00146 
00147               ee = s + (len == 45 ? 60 : (int) floor(len * 1.33));
00148               /* sanity check */
00149               if (ee > e) {
00150                      goto err;
00151               }
00152 
00153               while (s < ee) {
00154                      *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4;
00155                      *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2;
00156                      *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3));
00157                      s += 4;
00158               }
00159 
00160               if (len < 45) {
00161                      break;
00162               }
00163 
00164               /* skip \n */
00165               s++;
00166        }
00167 
00168        if ((len = total_len > (p - *dest))) {
00169               *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4;
00170               if (len > 1) {
00171                      *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2;
00172                      if (len > 2) {
00173                             *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3));
00174                      }
00175               }
00176        }
00177 
00178        *(*dest + total_len) = '\0';
00179 
00180        return total_len;
00181 
00182 err:
00183        efree(*dest);
00184        return -1;
00185 }
00186 /* }}} */
00187 
00188 /* {{{ proto string convert_uuencode(string data) 
00189    uuencode a string */
00190 PHP_FUNCTION(convert_uuencode)
00191 {
00192        char *src, *dst;
00193        int src_len, dst_len;
00194 
00195        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &src, &src_len) == FAILURE || src_len < 1) {
00196               RETURN_FALSE;
00197        }
00198 
00199        dst_len = php_uuencode(src, src_len, &dst);
00200 
00201        RETURN_STRINGL(dst, dst_len, 0);
00202 }
00203 /* }}} */
00204 
00205 /* {{{ proto string convert_uudecode(string data)
00206    decode a uuencoded string */
00207 PHP_FUNCTION(convert_uudecode)
00208 {
00209        char *src, *dst;
00210        int src_len, dst_len;
00211 
00212        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &src, &src_len) == FAILURE || src_len < 1) {
00213               RETURN_FALSE;
00214        }
00215 
00216        dst_len = php_uudecode(src, src_len, &dst);
00217        if (dst_len < 0) {
00218               php_error_docref(NULL TSRMLS_CC, E_WARNING, "The given parameter is not a valid uuencoded string");
00219               RETURN_FALSE;
00220        }
00221 
00222        RETURN_STRINGL(dst, dst_len, 0);
00223 }
00224 /* }}} */
00225 
00226 /*
00227  * Local variables:
00228  * tab-width: 4
00229  * c-basic-offset: 4
00230  * End:
00231  * vim600: noet sw=4 ts=4 fdm=marker
00232  * vim<600: noet sw=4 ts=4
00233  */