// This may look like C code, but it is really -*- C++ -*- // ------------------------------------------------------------------ // The Goldware Library // Copyright (C) 1990-1999 Odinn Sorensen // Copyright (C) 1999-2000 Alexander S. Aganichev // ------------------------------------------------------------------ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, // MA 02111-1307, USA // ------------------------------------------------------------------ // $Id$ // ------------------------------------------------------------------ // Decoder/encoders. // ------------------------------------------------------------------ #ifdef __GNUG__ #pragma implementation "gutlcode.h" #endif // ------------------------------------------------------------------ #include #include #include // ------------------------------------------------------------------ uucode_engine::uucode_engine() { initialized = false; } // ------------------------------------------------------------------ void uucode_engine::initialize() { // Set up the default translation table. int i, j; for(i=0; i<' '; i++) table.ch[i] = -1; for(i=' ',j=0; i<' '+64; i++,j++) table.ch[i] = j; for(i=' '+64; i<256; i++) table.ch[i] = -1; table.ch['`' & 0xff] = table.ch[' ' & 0xff]; // A common mutation table.ch['~' & 0xff] = table.ch['^' & 0xff]; // Another common mutation table.blank = ' '; // Set up the line length table, to avoid computing lotsa * and / ... table.len[0] = 1; for(i=1,j=5; i<=60; i+=3, j+=4) table.len[i] = (table.len[i+1] = (table.len[i+2] = j)); initialized = true; complete = false; } // ------------------------------------------------------------------ char* uucode_engine::decode(char* outputbuffer, const char* inputbuffer) { char buf[80]; char* o = outputbuffer; int len = strlen(strcpy(buf, inputbuffer)); if(not initialized) initialize(); if(strnieql(buf, "begin ", 6)) { return o; } else if(strieql(buf, "end")) { initialized = false; complete = true; return o; } else if(strieql(buf, "table")) { defining_table = true; for(int c=0; c<256; c++) table.ch[c] = -1; table_index = 0; return o; } if(defining_table) { char* p = buf + len - 1; *p = ' '; while(*p == ' ') *p-- = 0; p = buf; char c; while((c = *p) != 0) { if(table_index == 0) table.blank = c; table.ch[c & 0xff] = table_index++; if(table_index >= 64) { defining_table = false; break; } p++; } return o; } // Get the binary line length. int n = table.ch[*buf & 0xff]; if(n > 0) { // Pad with blanks. int c = len; char* i = buf + c; int rlen = table.len[n]; while(c < rlen) { *i++ = table.blank; c++; } // Output a group of 3 bytes (4 input characters). i = buf + 1; while(n > 0) { *(o++) = (char)((table.ch[*i & 0xff] << 2) | (table.ch[i[1] & 0xff] >> 4)); n--; if(n) { *(o++) = (char)((table.ch[i[1] & 0xff] << 4) | (table.ch[i[2] & 0xff] >> 2)); n--; } if(n) { *(o++) = (char)((table.ch[i[2] & 0xff] << 6) | table.ch[i[3] & 0xff]); n--; } i += 4; } } *o = NUL; return o; } // ------------------------------------------------------------------ char* quoted_printable_engine::decode(char* outputbuffer, const char* inputbuffer) { char c; char* o = outputbuffer; const char* i = inputbuffer; while((c = *i) != NUL) { if(c == '=') { char c1 = i[1]; char c2 = i[2]; if(isxdigit(c1) and isxdigit(c2)) { // Decode the character c = (char)((xtoi(c1) << 4) | xtoi(c2)); i += 2; } } //else if(c == '_') { // c = ' '; //} *o++ = c; i++; } *o = NUL; return o; } // ------------------------------------------------------------------ char* base64_engine::decode(char* outputbuffer, const char* inputbuffer) { char* o = outputbuffer; const char* i = inputbuffer; int shift = 0; uint32_t accum = 0; while(*i) { char c = *i; uint value = (uint)-1; if((c >= 'A') and (c <= 'Z')) value = c - 'A'; else if((c >= 'a') and (c <= 'z')) value = 26 + c - 'a'; else if((c >= '0') and (c <= '9')) value = 52 + c - '0'; else if(c == '+') value = 62; else if(c == '/') value = 63; else if(c == '=') value = (uint)-2; if(value >= 64) break; else { accum <<= 6; shift += 6; accum |= value; if(shift >= 8) { shift -= 8; value = (uint)(accum >> shift); c = (byte)(value & 0xFF); *o++ = c; } } i++; } *o = NUL; return o; } // ------------------------------------------------------------------ char base64_engine::table[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' }; // ------------------------------------------------------------------ char* base64_engine::encode(char* outputbuffer, const char* inputbuffer, uint length, bool padding) { uint l = length; char* o = outputbuffer; const char* i = inputbuffer; while(l > 0) { char c1 = i[0]; char c2 = l > 1 ? i[1] : '\0'; char c3 = l > 2 ? i[2] : '\0'; int pads = l > 2 ? 0 : (3 - l); o[0] = table[c1 >> 2]; o[1] = table[((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4)]; if(pads == 2) { if(padding) { o[2] = '='; o[3] = '='; } else { o[2] = NUL; o[3] = NUL; } } else if(pads == 1) { o[2] = table[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)]; if(padding) { o[3] = '='; } else { o[3] = NUL; } } else { o[2] = table[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)]; o[3] = table[c3 & 0x3F]; } o += 4; if(l < 3) break; l -= 3; i += 3; } *o = NUL; return o; } // ------------------------------------------------------------------