📄 quotedp.c
字号:
/* * $Id: QuotedP.C,v 1.3 2000/05/31 15:26:56 evgeny Exp $ * * Copyright (c) 1994 HAL Computer Systems International, Ltd. * * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. * 1315 Dell Avenue * Campbell, CA 95008 * * Author: Greg Hilton * Contributors: Tom Lang, Frank Bieser, and others * * 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. * * http://www.gnu.org/copyleft/gpl.html * * 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-1307, USA. */#include <config.h>#include "QuotedP.h"#include <hgl/StringC.h>#include <hgl/CharC.h>#include <hgl/SysErr.h>#include <hgl/HalAppC.h>#include <unistd.h>#include <errno.h>/*------------------------------------------------------------------------- * Lookup table for QP encoding */static char basis_qp[] = "0123456789ABCDEF";/*----------------------------------------------------------------------- * Encode any characters (< 32) or (> 127) and the '=' character. * Don't encode newline or tab. * Also encode any period on a line by itself. */inline BooleanNeedsQP(u_int c, int lineSize){ return ( (c < 32 && (c != '\n' && c != '\t')) || (c == '=') || (c >= 127) || (lineSize == 0 && c == '.') );}/*----------------------------------------------------------------------- * Encode the character and write the output to the specified file */inline BooleanEncodeQP(u_int c, FILE *fp){ return ( putc('=', fp) != EOF && putc(basis_qp[c >> 4 ], fp) != EOF && putc(basis_qp[c & 0xf], fp) != EOF );}/*----------------------------------------------------------------------- * Write a properly encoded newline character to the specified file */inline BooleanEncodeNewlineQP(u_int prevc, FILE *fp){ Boolean error = False; if ( prevc == ' ' || prevc == '\t' ) error = (putc('=', fp) == EOF || putc('\n', fp) == EOF); if ( !error ) error = (putc('\n', fp) == EOF); return !error;}/*----------------------------------------------------------------------- * Encode the character and add the output to the specified string */inline voidEncodeQP(u_int c, StringC *ostr){ *ostr += '='; *ostr += basis_qp[c >> 4 ]; *ostr += basis_qp[c & 0xf];}/*----------------------------------------------------------------------- * Add a properly encoded newline character to the specified string */inline voidEncodeNewlineQP(u_int prevc, StringC *ostr){ if ( prevc == ' ' || prevc == '\t' ) *ostr += "=\n\n"; else *ostr += '\n';}/*----------------------------------------------------------------------- * Function to encode the given string using quoted-printable encoding and * store the result in a string */BooleanTextToTextQP(CharC istr, StringC *ostr, Boolean breakLines){//// Loop through each character and check for wierd ones// int lineSize = 0; u_int prevc = 255; for (u_int i=0; i<istr.Length(); i++) { u_int c = (u_char)istr[i]; if ( NeedsQP(c, lineSize) ) { EncodeQP(c, ostr); lineSize += 3; prevc = 'A'; /* close enough */ } // End if character needs to be encoded//// If this is a newline character// else if ( c == '\n' ) { EncodeNewlineQP(prevc, ostr); lineSize = 0; prevc = '\n'; } // End if this is a newline//// Look for 'From ' at the beginning of a line// HORRIBLE but clever hack suggested by MTR for sendmail-avoidance// else if ( prevc == '\n' && istr.StartsWith("From ", i) ) { *ostr += "=46rom "; lineSize += 7; i += 4; // One more will be added at bottom of loop }//// Otherwise this is an ordinary character// else { *ostr += (char)c; lineSize++; prevc = c; }//// Wrap this line if necessary// if ( lineSize > 72 ) { if ( breakLines ) { *ostr += "=\n"; prevc = '\n'; } lineSize = 0; } } // End for each character//// Add a final newline// if ( lineSize > 0 && breakLines ) *ostr += "=\n"; return True;} // End TextToTextQP/*------------------------------------------------------------------------- * Function to encode a stream of bytes from an open file and place the * output in a file */BooleanFileToFileQP(const char *ifile, const char *ofile, FILE *ifp, FILE *ofp, u_int offset, u_int length){ Boolean closeInput = (ifp == NULL); Boolean closeOutput = (ofp == NULL); if ( !ifp ) {//// Open input file// ifp = fopen(ifile, "r"); if ( !ifp ) { StringC errmsg("Could not open file \""); errmsg += ifile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); return False; }//// Initialize length// if ( length == 0 ) { fseek(ifp, 0, SEEK_END); length = (u_int)ftell(ifp); } } // End if input file is not open//// Move to offset in input file// if ( fseek(ifp, offset, SEEK_SET) != 0 ) { StringC errmsg("Could not seek to offset "); errmsg += (int)offset; errmsg += " in input file "; errmsg += ifile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); if ( closeInput ) fclose(ifp); return False; } if ( !ofp ) {//// Create an output file// ofp = fopen(ofile, "w+"); if ( !ofp ) { StringC errmsg("Could not create file \""); errmsg += ofile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); if ( closeInput ) fclose(ifp); return False; } } // End if output file is not open//// Loop through each character and check for wierd ones// int lineSize = 0; u_int prevc = 255; int c; Boolean error = False; while ( !error && length>0 && (c=getc(ifp)) != EOF ) { length--;//// Encode normal QP stuff plus 'F' at the beginning of a line. This is to// hide possible "From "s// HORRIBLE but clever hack suggested by MTR for sendmail-avoidance// if ( NeedsQP((u_int)c, lineSize) || prevc == '\n' && c == 'F' ) { error = !EncodeQP((u_int)c, ofp); lineSize += 3; prevc = 'A'; /* close enough */ } // End if character needs to be encoded//// If this is a newline character// else if ( c == '\n' ) { error = !EncodeNewlineQP(prevc, ofp); lineSize = 0; prevc = '\n'; } // End if this is a newline//// Otherwise this is an ordinary character// else { error = (putc((char)c, ofp) == EOF); lineSize++; prevc = (u_int)c; }//// Wrap this line if necessary// if ( !error && lineSize > 72 ) { error = (putc('=', ofp) == EOF || putc('\n', ofp) == EOF); prevc = '\n'; lineSize = 0; } } // End for each character//// Add a final newline// if ( !error && lineSize > 0 ) error = (putc('=', ofp) == EOF || putc('\n', ofp) == EOF); if ( error ) { StringC errmsg("Could not write file \""); errmsg += ofile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); } else if ( c == EOF && length > 0 ) { StringC errmsg("Unexpected end of file \""); errmsg += ifile; errmsg += "\" while QP encoding.\n"; errmsg += "Expected "; errmsg += (int)length; errmsg += " more bytes. "; halApp->PopupMessage(errmsg); } if ( closeInput ) fclose(ifp); if ( closeOutput ) fclose(ofp); return !error;} // End FileToFileQP/*----------------------------------------------------------------------- * Function to encode the given string using quoted-printable encoding and * store the result in a file */BooleanTextToFileQP(CharC istr, const char *ofile, FILE *ofp){ Boolean closeOutput = (ofp == NULL); if ( !ofp ) {//// Create an output file// ofp = fopen(ofile, "w+"); if ( !ofp ) { StringC errmsg("Could not create file \""); errmsg += ofile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); return False; } }//// Loop through each character and check for wierd ones// int lineSize = 0; u_int prevc = 255; Boolean error = False; for (u_int i=0; !error && i<istr.Length(); i++) { u_int c = (u_char)istr[i]; if ( NeedsQP(c, lineSize) ) { error = !EncodeQP(c, ofp); lineSize += 3; prevc = 'A'; /* close enough */ } // End if character needs to be encoded//// If this is a newline character// else if ( c == '\n' ) { error = !EncodeNewlineQP(prevc, ofp); lineSize = 0; prevc = '\n'; } // End if this is a newline//// Look for 'From ' at the beginning of a line// HORRIBLE but clever hack suggested by MTR for sendmail-avoidance// else if ( prevc == '\n' && istr.StartsWith("From ", i) ) { error = (fwrite("=46rom ", 1, 7, ofp) != 7); lineSize += 7; i += 4; // One more will be added at bottom of loop }//// Otherwise this is an ordinary character// else { error = (putc(c, ofp) == EOF); lineSize++; prevc = c; }//// Wrap this line if necessary// if ( !error && lineSize > 72 ) { error = (putc('=', ofp) == EOF || putc('\n', ofp) == EOF); prevc = '\n'; lineSize = 0; } } // End for each character//// Add a final newline// if ( !error && lineSize > 0 ) error = (putc('=', ofp) == EOF || putc('\n', ofp) == EOF); if ( error ) { StringC errmsg("Could not write file \""); errmsg += ofile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); } if ( closeOutput ) fclose(ofp); return !error;} // End TextToFileQP/*------------------------------------------------------------------------- * Function to encode a file and place the quoted-printable encoded * output in a text string */BooleanFileToTextQP(const char *ifile, StringC *ostr, Boolean breakLines, FILE *ifp, u_int offset, u_int length){ Boolean closeInput = (ifp == NULL); if ( !ifp ) {//// Open input file// ifp = fopen(ifile, "r"); if ( !ifp ) { StringC errmsg("Could not open file \""); errmsg += ifile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); return False; }//// Initialize length// if ( length == 0 ) { fseek(ifp, 0, SEEK_END); length = (u_int)ftell(ifp); } } // End if input file is not open//// Move to offset in input file// if ( fseek(ifp, offset, SEEK_SET) != 0 ) { StringC errmsg("Could not seek to offset "); errmsg += (int)offset; errmsg += " in input file "; errmsg += ifile; errmsg += "\" for QP encoding.\n"; errmsg += SystemErrorMessage(errno); halApp->PopupMessage(errmsg); if ( closeInput ) fclose(ifp); return False; }//// Loop through each character and check for wierd ones// int lineSize = 0; u_int prevc = 255; int c; while ( length>0 && (c=getc(ifp)) != EOF ) { length--;//// Encode normal QP stuff plus 'F' at the beginning of a line. This is to// hide possible "From "s// HORRIBLE but clever hack suggested by MTR for sendmail-avoidance// if ( NeedsQP((u_int)c, lineSize) || prevc == '\n' && c == 'F' ) { EncodeQP((u_int)c, ostr); lineSize += 3; prevc = 'A'; /* close enough */ } // End if character needs to be encoded//// If this is a newline character// else if ( c == '\n' ) { EncodeNewlineQP(prevc, ostr); lineSize = 0; prevc = '\n'; } // End if this is a newline//// Otherwise this is an ordinary character// else { *ostr += (char)c; lineSize++; prevc = (u_int)c; }//// Wrap this line if necessary// if ( lineSize > 72 ) { if ( breakLines ) { *ostr += "=\n"; prevc = '\n'; } lineSize = 0; } } // End for each character//// Add a final newline// if ( lineSize > 0 && breakLines ) *ostr += "=\n"; if ( closeInput ) fclose(ifp); if ( c == EOF && length > 0 ) { StringC errmsg("Unexpected end of file \""); errmsg += ifile; errmsg += "\" while QP encoding.\n"; errmsg += "Expected "; errmsg += (int)length; errmsg += " more bytes. "; halApp->PopupMessage(errmsg); return False; } return True;} // End FileToTextQP/*----------------------------------------------------------------------- * Function to encode the given string using RFC1522 Q encoding and * store the result in a string in the following format: * * "=?charset?Q?encoded-text?=" *///// The maximum length of the entire encoded string is 75 characters.//#define MAX_1522_WORD_LENGTH 75BooleanTextToText1522Q(CharC istr, CharC charset, StringC *ostr){//// Encode the input// StringC result; if ( !TextToTextQP(istr, &result, False/*don't break lines*/) ) return False;//// Convert spaces to underscores// char *cs = result; while ( *cs ) { if ( *cs == ' ' ) *cs = '_'; cs++; }//// If the result is too long, we may have to split it.// int max = MAX_1522_WORD_LENGTH - charset.Length() - 7; CharC remaining = result; while ( remaining.Length() > max ) {//// Take as many characters as possible. If there is an equals sign within// 2 characters before the max character, back up.// CharC word = remaining(0, max); if ( word[max-1] == '=' ) word.CutEnd(1); else if ( word[max-2] == '=' ) word.CutEnd(2);//// Add this word// *ostr += "=?"; *ostr += charset; *ostr += "?Q?"; *ostr += word; *ostr += "?= "; // An extra space is required between split words//// Remove this word from the remaining// remaining.CutBeg(word.Length());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -