/*
* fhist - file history and comparison tools
* Copyright (C) 2000, 2002 Peter Miller;
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
* MANIFEST: functions to deliver output, decoding quoted printable
*/
#include <output/private.h>
#include <output/quotprindeco.h>
typedef struct output_quoted_printable_decode_ty output_quoted_printable_decode_ty;
struct output_quoted_printable_decode_ty
{
output_ty inherited;
output_ty *deeper;
int delete_on_delete;
int state;
int c1;
int n1;
};
static void
destructor(output_ty *fp)
{
output_quoted_printable_decode_ty *this;
this = (output_quoted_printable_decode_ty *)fp;
switch (this->state)
{
case 1:
output_fputc(this->deeper, '=');
break;
case 2:
output_fputc(this->deeper, '=');
output_fputc(this->deeper, this->c1);
break;
}
this->state = 0;
output_flush(this->deeper);
if (this->delete_on_delete)
output_delete(this->deeper);
this->deeper = 0;
}
static const char *
filename(output_ty *fp)
{
output_quoted_printable_decode_ty *this;
this = (output_quoted_printable_decode_ty *)fp;
return output_filename(this->deeper);
}
static long
otell(output_ty *fp)
{
output_quoted_printable_decode_ty *this;
this = (output_quoted_printable_decode_ty *)fp;
return output_ftell(this->deeper);
}
static int
unhex(int c)
{
switch (c)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return (c - '0');
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
return (c - 'a' + 10);
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
return (c - 'A' + 10);
}
return -1;
}
static void
oputc(output_ty *fp, int c)
{
output_quoted_printable_decode_ty *this;
int n;
this = (output_quoted_printable_decode_ty *)fp;
switch (this->state)
{
case 0:
state0:
if (c == '=')
{
this->state = 1;
break;
}
output_fputc(this->deeper, c);
break;
case 1:
if (c == '\n')
{
this->state = 0;
break;
}
n = unhex(c);
if (n >= 0)
{
this->n1 = n;
this->c1 = c;
this->state = 2;
break;
}
output_fputc(this->deeper, '=');
this->state = 0;
goto state0;
case 2:
this->state = 0;
n = unhex(c);
if (n >= 0)
{
output_fputc(this->deeper, (this->n1 << 4) + n);
break;
}
output_fputc(this->deeper, '=');
output_fputc(this->deeper, this->c1);
goto state0;
}
}
static void
oflush(output_ty *fp)
{
output_quoted_printable_decode_ty *this;
this = (output_quoted_printable_decode_ty *)fp;
output_flush(this->deeper);
}
static output_vtbl_ty vtbl =
{
sizeof(output_quoted_printable_decode_ty),
destructor,
filename,
otell,
oputc,
output_generic_fputs,
output_generic_write,
oflush,
"quoted_printable_decode",
};
output_ty *
output_quoted_printable_decode(output_ty *deeper, int dod)
{
output_ty *result;
output_quoted_printable_decode_ty *this;
result = output_new(&vtbl);
this = (output_quoted_printable_decode_ty *)result;
this->deeper = deeper;
this->delete_on_delete = dod;
this->state = 0;
return result;
}
syntax highlighted by Code2HTML, v. 0.9.1