• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

KMIME Library

  • sources
  • kde-4.12
  • kdepimlibs
  • kmime
kmime_codec_uuencode.cpp
Go to the documentation of this file.
1 /* -*- c++ -*-
2  kmime_codec_uuencode.cpp
3 
4  KMime, the KDE Internet mail/usenet news message library.
5  Copyright (c) 2002 Marc Mutz <mutz@kde.org>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
33 #include "kmime_codec_uuencode.h"
34 
35 #include <kdebug.h>
36 
37 #include <cassert>
38 
39 using namespace KMime;
40 
41 namespace KMime {
42 
43 class UUDecoder : public Decoder
44 {
45  uint mStepNo;
46  uchar mAnnouncedOctetCount; // (on current line)
47  uchar mCurrentOctetCount; // (on current line)
48  uchar mOutbits;
49  bool mLastWasCRLF : 1;
50  bool mSawBegin : 1; // whether we already saw ^begin...
51  uint mIntoBeginLine : 3; // count #chars we compared against "begin" 0..5
52  bool mSawEnd : 1; // whether we already saw ^end...
53  uint mIntoEndLine : 2; // count #chars we compared against "end" 0..3
54 
55  void searchForBegin( const char* &scursor, const char * const send );
56 
57  protected:
58  friend class UUCodec;
59  UUDecoder( bool withCRLF=false )
60  : Decoder( withCRLF ), mStepNo( 0 ),
61  mAnnouncedOctetCount( 0 ), mCurrentOctetCount( 0 ),
62  mOutbits( 0 ), mLastWasCRLF( true ),
63  mSawBegin( false ), mIntoBeginLine( 0 ),
64  mSawEnd( false ), mIntoEndLine( 0 ) {}
65 
66  public:
67  virtual ~UUDecoder() {}
68 
69  bool decode( const char* &scursor, const char * const send,
70  char* &dcursor, const char * const dend );
71  // ### really needs no finishing???
72  bool finish( char* &dcursor, const char * const dend )
73  { Q_UNUSED( dcursor ); Q_UNUSED( dend ); return true; }
74 };
75 
76 Encoder * UUCodec::makeEncoder( bool ) const
77 {
78  return 0; // encoding not supported
79 }
80 
81 Decoder * UUCodec::makeDecoder( bool withCRLF ) const
82 {
83  return new UUDecoder( withCRLF );
84 }
85 
86 /********************************************************/
87 /********************************************************/
88 /********************************************************/
89 
90 void UUDecoder::searchForBegin( const char* &scursor, const char * const send )
91 {
92  static const char begin[] = "begin\n";
93  static const uint beginLength = 5; // sic!
94 
95  assert( !mSawBegin || mIntoBeginLine > 0 );
96 
97  while ( scursor != send ) {
98  uchar ch = *scursor++;
99  if ( ch == begin[mIntoBeginLine] ) {
100  if ( mIntoBeginLine < beginLength ) {
101  // found another char
102  ++mIntoBeginLine;
103  if ( mIntoBeginLine == beginLength ) {
104  mSawBegin = true; // "begin" complete, now search the next \n...
105  }
106  } else { // mIntoBeginLine == beginLength
107  // found '\n': begin line complete
108  mLastWasCRLF = true;
109  mIntoBeginLine = 0;
110  return;
111  }
112  } else if ( mSawBegin ) {
113  // OK, skip stuff until the next \n
114  } else {
115  kWarning() << "UUDecoder: garbage before \"begin\", resetting parser";
116  mIntoBeginLine = 0;
117  }
118  }
119 
120 }
121 
122 // uuencoding just shifts all 6-bit octets by 32 (SP/' '), except NUL,
123 // which gets mapped to 0x60
124 static inline uchar uuDecode( uchar c )
125 {
126  return ( c - ' ' ) // undo shift and
127  & 0x3F; // map 0x40 (0x60-' ') to 0...
128 }
129 
130 bool UUDecoder::decode( const char* &scursor, const char * const send,
131  char* &dcursor, const char * const dend )
132 {
133  // First, check whether we still need to find the "begin" line:
134  if ( !mSawBegin || mIntoBeginLine != 0 ) {
135  searchForBegin( scursor, send );
136  } else if ( mSawEnd ) {
137  // or if we are past the end line:
138  scursor = send; // do nothing anymore...
139  return true;
140  }
141 
142  while ( dcursor != dend && scursor != send ) {
143  uchar ch = *scursor++;
144  uchar value;
145 
146  // Check whether we need to look for the "end" line:
147  if ( mIntoEndLine > 0 ) {
148  static const char end[] = "end";
149  static const uint endLength = 3;
150 
151  if ( ch == end[mIntoEndLine] ) {
152  ++mIntoEndLine;
153  if ( mIntoEndLine == endLength ) {
154  mSawEnd = true;
155  scursor = send; // shortcut to the end
156  return true;
157  }
158  continue;
159  } else {
160  kWarning() << "UUDecoder: invalid line octet count looks like \"end\" (mIntoEndLine ="
161  << mIntoEndLine << ")!";
162  mIntoEndLine = 0;
163  // fall through...
164  }
165  }
166 
167  // Normal parsing:
168 
169  // The first char of a line is an encoding of the length of the
170  // current line. We simply ignore it:
171  if ( mLastWasCRLF ) {
172  // reset char-per-line counter:
173  mLastWasCRLF = false;
174  mCurrentOctetCount = 0;
175 
176  // try to decode the chars-on-this-line announcement:
177  if ( ch == 'e' ) { // maybe the beginning of the "end"? ;-)
178  mIntoEndLine = 1;
179  } else if ( ch > 0x60 ) {
180  // ### invalid line length char: what shall we do??
181  } else if ( ch > ' ' ) {
182  mAnnouncedOctetCount = uuDecode( ch );
183  } else if ( ch == '\n' ) {
184  mLastWasCRLF = true; // oops, empty line
185  }
186 
187  continue;
188  }
189 
190  // try converting ch to a 6-bit value:
191  if ( ch > 0x60 ) {
192  continue; // invalid char
193  } else if ( ch > ' ' ) {
194  value = uuDecode( ch );
195  } else if ( ch == '\n' ) { // line end
196  mLastWasCRLF = true;
197  continue;
198  } else {
199  continue;
200  }
201 
202  // add the new bits to the output stream and flush full octets:
203  switch ( mStepNo ) {
204  case 0:
205  mOutbits = value << 2;
206  break;
207  case 1:
208  if ( mCurrentOctetCount < mAnnouncedOctetCount ) {
209  *dcursor++ = (char)( mOutbits | value >> 4 );
210  }
211  ++mCurrentOctetCount;
212  mOutbits = value << 4;
213  break;
214  case 2:
215  if ( mCurrentOctetCount < mAnnouncedOctetCount ) {
216  *dcursor++ = (char)( mOutbits | value >> 2 );
217  }
218  ++mCurrentOctetCount;
219  mOutbits = value << 6;
220  break;
221  case 3:
222  if ( mCurrentOctetCount < mAnnouncedOctetCount ) {
223  *dcursor++ = (char)( mOutbits | value );
224  }
225  ++mCurrentOctetCount;
226  mOutbits = 0;
227  break;
228  default:
229  assert( 0 );
230  }
231  mStepNo = ( mStepNo + 1 ) % 4;
232 
233  // check whether we ran over the announced octet count for this line:
234  kWarning( mCurrentOctetCount == mAnnouncedOctetCount + 1 )
235  << "UUDecoder: mismatch between announced ("
236  << mAnnouncedOctetCount << ") and actual line octet count!";
237 
238  }
239 
240  // return false when caller should call us again:
241  return scursor == send;
242 } // UUDecoder::decode()
243 
244 } // namespace KMime
KMime::Encoder
Stateful encoder class.
Definition: kmime_codecs.h:394
kmime_codec_uuencode.h
This file is part of the API for handling MIME data and defines a uuencode Codec class.
KMime::Decoder
Stateful CTE decoder class.
Definition: kmime_codecs.h:341
KMime::UUCodec
A class representing the UUEncode codec.
Definition: kmime_codec_uuencode.h:48
KMime::UUCodec::makeDecoder
Decoder * makeDecoder(bool withCRLF=false) const
Definition: kmime_codec_uuencode.cpp:81
KMime::UUCodec::makeEncoder
Encoder * makeEncoder(bool withCRLF=false) const
Definition: kmime_codec_uuencode.cpp:76
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KMIME Library

Skip menu "KMIME Library"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal