Back to index

php5  5.3.10
mbfilter_uuencode.c
Go to the documentation of this file.
00001 /*
00002  * "streamable kanji code filter and converter"
00003  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
00004  *
00005  * LICENSE NOTICES
00006  *
00007  * This file is part of "streamable kanji code filter and converter",
00008  * which is distributed under the terms of GNU Lesser General Public 
00009  * License (version 2) as published by the Free Software Foundation.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with "streamable kanji code filter and converter";
00018  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
00019  * Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * The author of this file:
00022  *
00023  */
00024 /*
00025  * The source code included in this files was separated from mbfilter.c
00026  * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
00027  * 
00028  */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include "config.h"
00032 #endif
00033 
00034 #include "mbfilter.h"
00035 #include "mbfilter_uuencode.h"
00036 
00037 const mbfl_encoding mbfl_encoding_uuencode = {
00038        mbfl_no_encoding_uuencode,
00039        "UUENCODE",
00040        "x-uuencode",
00041        NULL,
00042        NULL,
00043        MBFL_ENCTYPE_SBCS
00044 };
00045 
00046 const struct mbfl_convert_vtbl vtbl_uuencode_8bit = {
00047        mbfl_no_encoding_uuencode,
00048        mbfl_no_encoding_8bit,
00049        mbfl_filt_conv_common_ctor,
00050        mbfl_filt_conv_common_dtor,
00051        mbfl_filt_conv_uudec,
00052        mbfl_filt_conv_common_flush
00053 };
00054 
00055 #define CK(statement)       do { if ((statement) < 0) return (-1); } while (0)
00056 
00057 /* uuencode => any */
00058 #define UUDEC(c)     (char)(((c)-' ')&077)
00059 static const char * uuenc_begin_text = "begin ";
00060 enum { uudec_state_ground=0, uudec_state_inbegin,
00061        uudec_state_until_newline,
00062        uudec_state_size, uudec_state_a, uudec_state_b, uudec_state_c, uudec_state_d,
00063        uudec_state_skip_newline};
00064 
00065 int mbfl_filt_conv_uudec(int c, mbfl_convert_filter * filter)
00066 {
00067        int n;
00068        
00069        switch(filter->status)      {
00070               case uudec_state_ground:
00071                      /* looking for "begin 0666 filename\n" line */
00072                      if (filter->cache == 0 && c == 'b')
00073                      {
00074                             filter->status = uudec_state_inbegin;
00075                             filter->cache = 1; /* move to 'e' */
00076                      }
00077                      else if (c == '\n')
00078                             filter->cache = 0;
00079                      else
00080                             filter->cache++;
00081                      break;
00082               case uudec_state_inbegin:
00083                      if (uuenc_begin_text[filter->cache++] != c)      {
00084                             /* doesn't match pattern */
00085                             filter->status = uudec_state_ground;
00086                             break;
00087                      }
00088                      if (filter->cache == 5)
00089                      {
00090                             /* thats good enough - wait for a newline */
00091                             filter->status = uudec_state_until_newline;
00092                             filter->cache = 0;
00093                      }
00094                      break;
00095               case uudec_state_until_newline:
00096                      if (c == '\n')
00097                             filter->status = uudec_state_size;
00098                      break;
00099               case uudec_state_size:
00100                      /* get "size" byte */
00101                      n = UUDEC(c);
00102                      filter->cache = n << 24;
00103                      filter->status = uudec_state_a;
00104                      break;
00105               case uudec_state_a:
00106                      /* get "a" byte */
00107                      n = UUDEC(c);
00108                      filter->cache |= (n << 16);
00109                      filter->status = uudec_state_b;
00110                      break;
00111               case uudec_state_b:
00112                      /* get "b" byte */
00113                      n = UUDEC(c);
00114                      filter->cache |= (n << 8);
00115                      filter->status = uudec_state_c;
00116                      break;
00117               case uudec_state_c:
00118                      /* get "c" byte */
00119                      n = UUDEC(c);
00120                      filter->cache |= n;
00121                      filter->status = uudec_state_d;
00122                      break;
00123               case uudec_state_d:
00124                      /* get "d" byte */
00125                      {
00126                             int A, B, C, D = UUDEC(c);
00127                             A = (filter->cache >> 16) & 0xff;
00128                             B = (filter->cache >> 8) & 0xff;
00129                             C = (filter->cache) & 0xff;
00130                             n = (filter->cache >> 24) & 0xff;
00131                             if (n-- > 0)
00132                                    CK((*filter->output_function)( (A << 2) | (B >> 4), filter->data));
00133                             if (n-- > 0)
00134                                    CK((*filter->output_function)( (B << 4) | (C >> 2), filter->data));
00135                             if (n-- > 0)
00136                                    CK((*filter->output_function)( (C << 6) | D, filter->data));
00137                             filter->cache = n << 24;
00138 
00139                             if (n == 0)
00140                                    filter->status = uudec_state_skip_newline;       /* skip next byte (newline) */
00141                             else
00142                                    filter->status = uudec_state_a; /* go back to fetch "A" byte */
00143                      }
00144                      break;
00145               case uudec_state_skip_newline:
00146                      /* skip newline */
00147                      filter->status = uudec_state_size;
00148        }
00149        return c;
00150 }
00151 
00152