Newsgroups: alt.sources From: Olaf Titz Subject: trn 3.6 quoted-printable/RFC1522 patch Date: 05 Sep 1995 20:50:21 GMT Message-ID: Archive-name: trn36-q3.dif Submitted-by: Olaf Titz Patch for trn 3.6 to enable quoted-printable article and RFC 1522 header decoding. Features: - Articles with "Content-Transfer-Encoding: quoted-printable" are decoded while displaying. If charset substitution is active, this is done too. The charset used is still fixed at ISO-8859-1. For replying the decoding is done too. For storing, MIMESTORE is used. (Encoding base64 still activates external MIME viewer.) - Header lines with RFC 1522 encoded-words in Q and B encodings are decoded while displaying. The charset is assumed as ISO-8859-1 regardless of the actual header. This affects header lines read from thread and overview databases, too. (Note: From lines in thread database are limited to 16 characters, which is too small for encoded-words, but the decoding can be done by mthreads, see related mthreads patch.) Other enhancements: - Charset substitutions "a" and "m" are done in displayed header lines too. - %s interpolation strips nonstandard "Re(n)", "Re^n" forms. - Nasty TeX decoding bug fixed. Remaining bugs: - Line count sometimes goes wrong - lines get swallowed in display. (Press v to fix.) I still haven't found the cause. - TeX decoding shifts \ and " across lines. - Decoder source is messy and needs restructuring. July 1995 Olaf.Titz@inka.de --- ../trn-3.6/patchlevel.h Tue Nov 22 00:42:23 1994 +++ patchlevel.h Fri Aug 4 10:42:59 1995 @@ -1 +1 @@ -#define PATCHLEVEL " 3.6 (20 Nov 1994)" +#define PATCHLEVEL " 3.6Q3 (3 Aug 1995)" --- ../trn-3.6/artio.h Sat Oct 8 03:57:28 1994 +++ artio.h Fri Aug 4 10:42:59 1995 @@ -26,12 +26,20 @@ void artio_init _((void)); FILE *artopen _((ART_NUM)); /* open an article unless already opened */ +#ifdef QPDECODE +char *readart _((char*,int)); +#else #ifdef USE_NNTP -# define seekart(pos) nntp_seekart(pos) # define readart(s,len) nntp_readart(s,len) +#else +# define readart(s,len) fgets(s,len,artfp) +#endif +#endif + +#ifdef USE_NNTP +# define seekart(pos) nntp_seekart(pos) # define tellart() nntp_tellart() #else # define seekart(pos) fseek(artfp, pos, 0) -# define readart(s,len) fgets(s,len,artfp) # define tellart() ftell(artfp) #endif --- ../trn-3.6/charsubst.h Fri Oct 21 22:18:21 1994 +++ charsubst.h Fri Aug 4 10:42:59 1995 @@ -23,3 +23,13 @@ void strcharsubst _((char*,char*)); #endif + +#ifdef QPDECODE + +void decode_qp _((char*)); +void decode_b64 _((char*)); +void decode_1522 _((char*)); +/* Encodings are: plain, quoted-printable, base64 */ +EXT char art_encoding INIT('p'); + +#endif --- ../trn-3.6/common.h Wed Nov 2 03:44:01 1994 +++ common.h Fri Aug 4 16:06:14 1995 @@ -296,6 +296,7 @@ */ #define ROTATION /* enable x, X and ^X commands to work */ #define CHARSUBST /* enable the _C command */ +#define QPDECODE /* enable quoted-printable and base64 decoding */ #define DELBOGUS /* ask if bogus newsgroups should be deleted */ #define RELOCATE /* allow newsgroup rearranging */ #define ESCSUBS /* escape substitutions in multi-character commands */ --- ../trn-3.6/head.h Sun Apr 3 03:21:13 1994 +++ head.h Fri Aug 4 16:06:15 1995 @@ -90,10 +90,13 @@ {"codes", 0, 0, 5, HT_HIDE }, #if defined(MIMESHOW) || defined(MIMESTORE) {"content-type", 0, 0, 12, HT_MAGIC }, +#else + {"content-type", 0, 0, 12, 0 }, +#endif +#if defined(MIMESHOW) || defined(MIMESTORE) || defined(QPDECODE) {"content-transfer-encoding", 0, 0, 25, HT_MAGIC }, #else - {"content-type", 0, 0, 12, 0 }, {"content-transfer-encoding", 0, 0, 25, 0 }, #endif --- ../trn-3.6/art.c Sat Nov 19 07:01:16 1994 +++ art.c Fri Aug 4 16:14:37 1995 @@ -146,6 +146,9 @@ #if defined(MIMESHOW) || defined(MIMESTORE) mime_article = FALSE; #endif +#ifdef QPDECODE + art_encoding = 'p'; +#endif #ifndef USE_NNTP if (fstat(fileno(artfp),&filestat)) /* get article file stats */ @@ -315,6 +318,14 @@ else if (in_header == CONTXFER_LINE) mime_article = mime_article || nonprint(art_buf+27); } +#else +#ifdef QPDECODE + /* just interpret the encoding */ + else if (in_header == CONTXFER_LINE) { + int nonprint _((char *)); + nonprint(art_buf+27); + } +#endif #endif } if (in_header == SUBJ_LINE && @@ -1194,6 +1205,10 @@ return 0; /* no charset, was text/plain */ } +#endif + +#if defined(MIMESHOW) || defined(MIMESTORE) || defined(QPDECODE) + /* return true if this isn't "7bit", "8bit", or "binary" */ int @@ -1208,6 +1223,17 @@ s += 4; else if (strncasecmp(s, "binary", 6) == 0) s += 6; +#ifdef QPDECODE + else if (strncasecmp(s, "quoted-printable", 16) == 0) { + art_encoding = 'q'; + return 0; } +#if 0 +/* Not yet */ + else if (strncasecmp(s, "base64", 6) == 0) { + art_encoding = 'b'; + return 0; } +#endif +#endif else return 1; return !(*s == '\0' || isspace(*s) || *s == ';' || *s == '('); /*)*/ --- ../trn-3.6/artio.c Sat Oct 8 03:57:28 1994 +++ artio.c Fri Aug 4 15:42:57 1995 @@ -23,6 +23,7 @@ #include "bits.h" #include "final.h" #include "ngdata.h" +#include "charsubst.h" #include "INTERN.h" #include "artio.h" @@ -97,3 +98,50 @@ } return artfp; /* and return either fp or NULL */ } + +#ifdef QPDECODE + +char * +readart(s, limit) +char *s; +int limit; +{ + if (in_header || (art_encoding=='p')) { /* Plain encoded body */ +#ifdef USE_NNTP + return nntp_readart(s, limit); +#else + return fgets(s, limit, artfp); +#endif + } else if (art_encoding=='q') { /* qp encoded body */ + register char *y=s; + int l; + readline: +#ifdef USE_NNTP + y=nntp_readart(y, limit); +#else + y=fgets(y, limit, artfp); +#endif + if (!y) + return Nullch; + l=strlen(y); + if (y[--l]=='\n') { + while (y[--l]==' '||y[l]=='\t'); /* kill trailing whitespace */ + if (y[l]=='=') { + /* continuation line */ + y+=l; limit-=l; + if (limit>1) + goto readline; + } + y[++l]='\n'; y[++l]='\0'; + } + decode_qp(s); +#if 0 +/* Not yet */ + } else if (art_encoding=='b') { /* b64 encoded body */ +#endif + } else + return Nullch; /* Uh? */ + return s; +} + +#endif --- ../trn-3.6/charsubst.c Fri Nov 4 22:20:54 1994 +++ charsubst.c Tue Sep 5 13:21:48 1995 @@ -72,6 +72,7 @@ texchar = (char)c; break; } else if (texchar == '\\') { + texchar = '\0'; if (outputok) putchar('\\'); if (limit == 1) { @@ -154,9 +155,16 @@ strcharsubst(inb, outb) char *inb, *outb; { + int t; switch(*charsubst) { + case 'm': + t = 1; + goto doconvert; case 'a': - Latin1toASCII((unsigned char*)inb, (unsigned char*)outb, 2); + t = 2; + /* FALL THROUGH */ + doconvert: + Latin1toASCII((unsigned char*)inb, (unsigned char*)outb, t); break; default: strcpy(outb, inb); @@ -234,6 +242,109 @@ *asc++ = *iso++; } *asc = 0; +} + +#endif + +#ifdef QPDECODE + +/* MIME decoders */ + +/* These routines do decoding of strings in-place. The encoding + guarantees that the result may be shortened but not lengthened. + qp: transforms quoted-printable =xx patterns + b64: unpacks base64 - note null termination + 1522: decode rfc1522 =?charset?e?value?= patterns + Charset parameters are ignored. */ + +#define hexdigit(x) ((x>='0'&&x<='9')?(x-'0'):((x>='A'&&x<='F')?(x-'A'+10):0)) + +void +decode_qp(src) +char *src; +{ + register char c, c0, c1; + register char *d=src; + while ((c=*src++)) { + if ((c=='=') && (c0=toupper(src[0])) && (c1=toupper(src[1]))) { + *d++ = 16*hexdigit(c0)+hexdigit(c1); + src+=2; + } else { + *d++ = c; + } + } + *d='\0'; +} + +/* base64 encoding charset */ +static char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static void +store24(d, c) +char **d; +char *c; +{ + *(*d)++=(c[0]<<2)+(c[1]>>4); + *(*d)++=((c[1]<<4)&255)+(c[2]>>2); + *(*d)++=((c[2]<<6)&255)+c[3]; +} + +void +decode_b64(src) +char *src; +{ + char c0, c[4], *p; + int i=0; + char *d=src; + while (c0 = *src++) { + if (c0=='=') + break; /* a = symbol is end padding */ + if ((p=strchr(base64, c0))) { + c[i++]=p-base64; + if (i==4) { + store24(&d, c); + i=0; + } + } /* unknown symbols are ignored */ + } + if (i>0) { + for(;i<4;c[i++]=0); /* will leave padding nulls - don't matter here */ + store24(&d, c); + } + *d=0; +} + + +void +decode_1522(src) +char *src; +{ + register char c, e; + register char *d=src, *p1, *p2; + while ((c=*src++)) { + if (((c=='=') && (*src=='?')) && + (p1=strchr(src+1, '?')) && + (e=toupper(*++p1), e=='Q'||e=='B') && + (*++p1=='?') && + (p2=strstr(++p1, "?="))) { + /* this is rfc1522 encoded-word, ignore the charset by now */ + for (src=p1; src= string_end) break; - *author_ptr++ = string_ptr; + *author_ptr = string_ptr; string_ptr += strlen(string_ptr) + 1; +#ifdef QPDECODE + decode_1522(*author_ptr); + /* This is of no point due to the 16 char limit, but leave it in + to show how things _should_ be :-) */ +#endif + author_ptr++; } subject_strings = string_ptr; @@ -284,15 +291,26 @@ for (count = total.subject; count; count--) { int len; +#ifdef QPDECODE + int len0; +#endif ARTICLE arty; if (string_ptr >= string_end) break; +#ifdef QPDECODE + len0 = strlen(string_ptr); + decode_1522(string_ptr); +#endif len = strlen(string_ptr); arty.subj = 0; set_subj_line(&arty, string_ptr, len); if (len == 72) arty.subj->flags |= SF_SUBJTRUNCED; +#ifdef QPDECODE + string_ptr += len0 + 1; +#else string_ptr += len + 1; +#endif *subj_ptr++ = arty.subj; } if (count || string_ptr != string_end) { --- ../trn-3.6/rt-ov.c Tue Nov 22 00:17:08 1994 +++ rt-ov.c Fri Aug 4 10:43:01 1995 @@ -22,6 +22,7 @@ #include "rt-process.h" #include "rt-util.h" #include "overview.h" +#include "charsubst.h" #include "INTERN.h" #include "rt-ov.h" @@ -267,6 +268,9 @@ break; } *cp++ = '\0'; +#ifdef QPDECODE + decode_1522(fields[nf]); +#endif } if (!article->subj) --- ../trn-3.6/rt-wumpus.c Mon Jul 12 07:36:16 1993 +++ rt-wumpus.c Fri Aug 4 10:43:02 1995 @@ -18,6 +18,7 @@ #include "backpage.h" #include "rthread.h" #include "rt-select.h" +#include "charsubst.h" #include "INTERN.h" #include "rt-wumpus.h" @@ -253,8 +254,13 @@ char ch; /* Make a modifiable copy of the line */ +#ifdef CHARSUBST + buf = safemalloc(2*strlen(orig_line) + 2); /* yes, I mean "2" */ + strcharsubst(orig_line, buf); +#else buf = safemalloc(strlen(orig_line) + 2); /* yes, I mean "2" */ strcpy(buf, orig_line); +#endif line = buf; /* Change any embedded control characters to spaces */ --- ../trn-3.6/intrp.c Thu Nov 10 11:30:06 1994 +++ intrp.c Tue Sep 5 13:06:58 1995 @@ -923,12 +923,28 @@ if (!(s=subj_buf)) s = subj_buf = fetchsubj(art,TRUE); /* get subject handy */ +#if 0 while ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { /* skip extra Re: */ s += 3; if (*s == ' ') s++; } +#else + /* Skip "Re:", "Re^n:", "Re(n):" */ + while ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')) { + if (s[2]==':') + s+=3; + else if (s[2]=='^'&&s[4]==':') + s+=5; + else if (s[2]=='('&&s[4]==')'&&s[5]==':') + s+=6; + else + break; + if (*s == ' ') + s++; + } +#endif if (h = instr(s,"- (nf", TRUE)) *h = '\0'; break; -- ___ Olaf.Titz@inka.de or @{stud,informatik}.uni-karlsruhe.de ____ __ o __/<_ >> Just as long as the wheels keep on turning round _)>(_)______________ I will live for the groove 'til the sun goes down << ____