root/ext/mbstring/libmbfl/filters/mbfilter_uuencode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mbfl_filt_conv_uudec

   1 /*
   2  * "streamable kanji code filter and converter"
   3  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
   4  *
   5  * LICENSE NOTICES
   6  *
   7  * This file is part of "streamable kanji code filter and converter",
   8  * which is distributed under the terms of GNU Lesser General Public
   9  * License (version 2) as published by the Free Software Foundation.
  10  *
  11  * This software is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  * GNU Lesser General Public License for more details.
  15  *
  16  * You should have received a copy of the GNU Lesser General Public
  17  * License along with "streamable kanji code filter and converter";
  18  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  19  * Suite 330, Boston, MA  02111-1307  USA
  20  *
  21  * The author of this file:
  22  *
  23  */
  24 /*
  25  * The source code included in this files was separated from mbfilter.c
  26  * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
  27  *
  28  */
  29 
  30 #ifdef HAVE_CONFIG_H
  31 #include "config.h"
  32 #endif
  33 
  34 #include "mbfilter.h"
  35 #include "mbfilter_uuencode.h"
  36 
  37 const mbfl_encoding mbfl_encoding_uuencode = {
  38         mbfl_no_encoding_uuencode,
  39         "UUENCODE",
  40         "x-uuencode",
  41         NULL,
  42         NULL,
  43         MBFL_ENCTYPE_SBCS
  44 };
  45 
  46 const struct mbfl_convert_vtbl vtbl_uuencode_8bit = {
  47         mbfl_no_encoding_uuencode,
  48         mbfl_no_encoding_8bit,
  49         mbfl_filt_conv_common_ctor,
  50         mbfl_filt_conv_common_dtor,
  51         mbfl_filt_conv_uudec,
  52         mbfl_filt_conv_common_flush
  53 };
  54 
  55 #define CK(statement)   do { if ((statement) < 0) return (-1); } while (0)
  56 
  57 /* uuencode => any */
  58 #define UUDEC(c)        (char)(((c)-' ')&077)
  59 static const char * uuenc_begin_text = "begin ";
  60 enum { uudec_state_ground=0, uudec_state_inbegin,
  61         uudec_state_until_newline,
  62         uudec_state_size, uudec_state_a, uudec_state_b, uudec_state_c, uudec_state_d,
  63         uudec_state_skip_newline};
  64 
  65 int mbfl_filt_conv_uudec(int c, mbfl_convert_filter * filter)
  66 {
  67         int n;
  68 
  69         switch(filter->status)  {
  70                 case uudec_state_ground:
  71                         /* looking for "begin 0666 filename\n" line */
  72                         if (filter->cache == 0 && c == 'b')
  73                         {
  74                                 filter->status = uudec_state_inbegin;
  75                                 filter->cache = 1; /* move to 'e' */
  76                         }
  77                         else if (c == '\n')
  78                                 filter->cache = 0;
  79                         else
  80                                 filter->cache++;
  81                         break;
  82                 case uudec_state_inbegin:
  83                         if (uuenc_begin_text[filter->cache++] != c)     {
  84                                 /* doesn't match pattern */
  85                                 filter->status = uudec_state_ground;
  86                                 break;
  87                         }
  88                         if (filter->cache == 5)
  89                         {
  90                                 /* thats good enough - wait for a newline */
  91                                 filter->status = uudec_state_until_newline;
  92                                 filter->cache = 0;
  93                         }
  94                         break;
  95                 case uudec_state_until_newline:
  96                         if (c == '\n')
  97                                 filter->status = uudec_state_size;
  98                         break;
  99                 case uudec_state_size:
 100                         /* get "size" byte */
 101                         n = UUDEC(c);
 102                         filter->cache = n << 24;
 103                         filter->status = uudec_state_a;
 104                         break;
 105                 case uudec_state_a:
 106                         /* get "a" byte */
 107                         n = UUDEC(c);
 108                         filter->cache |= (n << 16);
 109                         filter->status = uudec_state_b;
 110                         break;
 111                 case uudec_state_b:
 112                         /* get "b" byte */
 113                         n = UUDEC(c);
 114                         filter->cache |= (n << 8);
 115                         filter->status = uudec_state_c;
 116                         break;
 117                 case uudec_state_c:
 118                         /* get "c" byte */
 119                         n = UUDEC(c);
 120                         filter->cache |= n;
 121                         filter->status = uudec_state_d;
 122                         break;
 123                 case uudec_state_d:
 124                         /* get "d" byte */
 125                         {
 126                                 int A, B, C, D = UUDEC(c);
 127                                 A = (filter->cache >> 16) & 0xff;
 128                                 B = (filter->cache >> 8) & 0xff;
 129                                 C = (filter->cache) & 0xff;
 130                                 n = (filter->cache >> 24) & 0xff;
 131                                 if (n-- > 0)
 132                                         CK((*filter->output_function)( (A << 2) | (B >> 4), filter->data));
 133                                 if (n-- > 0)
 134                                         CK((*filter->output_function)( (B << 4) | (C >> 2), filter->data));
 135                                 if (n-- > 0)
 136                                         CK((*filter->output_function)( (C << 6) | D, filter->data));
 137                                 filter->cache = n << 24;
 138 
 139                                 if (n == 0)
 140                                         filter->status = uudec_state_skip_newline;      /* skip next byte (newline) */
 141                                 else
 142                                         filter->status = uudec_state_a; /* go back to fetch "A" byte */
 143                         }
 144                         break;
 145                 case uudec_state_skip_newline:
 146                         /* skip newline */
 147                         filter->status = uudec_state_size;
 148         }
 149         return c;
 150 }
 151 
 152 

/* [<][>][^][v][top][bottom][index][help] */