292 lines
6.8 KiB
C++
292 lines
6.8 KiB
C++
|
// 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 <gstrall.h>
|
||
|
#include <gutlmisc.h>
|
||
|
#include <gutlcode.h>
|
||
|
|
||
|
|
||
|
// ------------------------------------------------------------------
|
||
|
|
||
|
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['`'] = table.ch[' ']; // A common mutation
|
||
|
table.ch['~'] = table.ch['^']; // 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] = table_index++;
|
||
|
if(table_index >= 64) {
|
||
|
defining_table = false;
|
||
|
break;
|
||
|
}
|
||
|
p++;
|
||
|
}
|
||
|
return o;
|
||
|
}
|
||
|
|
||
|
// Get the binary line length.
|
||
|
int n = table.ch[*buf];
|
||
|
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] << 2) | (table.ch[i[1]] >> 4));
|
||
|
n--;
|
||
|
if(n) {
|
||
|
*(o++) = (char)((table.ch[i[1]] << 4) | (table.ch[i[2]] >> 2));
|
||
|
n--;
|
||
|
}
|
||
|
if(n) {
|
||
|
*(o++) = (char)((table.ch[i[2]] << 6) | table.ch[i[3]]);
|
||
|
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;
|
||
|
ulong 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
// ------------------------------------------------------------------
|