/* * 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 #include 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; }