9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] Base64 mime encode/decode program
@ 1998-11-18  9:01 okamoto
  0 siblings, 0 replies; only message in thread
From: okamoto @ 1998-11-18  9:01 UTC (permalink / raw)


I tried to make base64 encoding/decoding program
to use with such as rin's header lines.  This is a limited
implementation of RFC 1341/1342.  However, I believe
this works for most cases.

My basic policy is:
Encoding whole text line as a part which means I don't
care even if such a text cannnot be read from English
terminal.  This is because I believe no one have any
interests on those text, even if a part can be read anyway.
All or nothing should be the reasonable way in this case.

I tested this program of decoding patrt by reading
many Japanese articles from fj, but hadn't have any
problem up to now.  The encoding part is new.

I also put new version of tcs library which would be 
neccessary to compile this program on our plan 9
site: http://basalt.cias.osakafu-u.ac.jp/plan9/p9index.html
which is written by UTF-8.

Kenji
--------cut here------
/*
 * MIME encode/decode test program   for Japanese mode rin
 *       Nov. 18, 1998  Kenji Okamoto
 *
 *      char1       char2       char3       char4
 *   |----------|-----------|-----------|-----------|
 *   1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
 *   |--------------|---------------|---------------|
 *          1               2               3
 */
#include <u.h>
#include <libc.h>
#include <tcs.h>

char *mime_decode(char *, char*);
static char *decodeB64(char *);

char *
mime_decode(char *from, char *decoded) {
	char *mimest, *charst, *newline;
	char tbuff[150], tbuff2[150];

	*decoded = 0;
	if(!(mimest = strstr(from, "=?")))
		return(from);
	else {		/* mime encoded  */
		if (charst = strstr(from, "ISO-2022-JP?"))
			charst += 12;
		else if(charst = strstr(from, "iso-2022-jp?"))
			charst += 12;
		else
			return(from);	/* MIME but other than JIS */
	}
	if(*charst++ != 'B')
		return(from);		/* probably Q encoded */
	charst++;		/* top address of B64 encoded string */
/*	if(*charst != 'G')
		return(from);	 not JIS */
	strncpy(decoded, from, mimest-from);		/* not encoded part */
	decoded[mimest-from] = 0;
	mimest = strstr(charst, "?=");	/* mimest=last address + 1 */
	strncpy(tbuff, charst, mimest-charst);
	tbuff[mimest-charst] = 0;
	if(newline = strstr(tbuff, "\n\t")) {
		tbuff2[0] =0;
		strncat(tbuff2, tbuff, newline-tbuff);
		strcat(tbuff2+(newline-tbuff), newline+2);
		tbuff[0] = 0;
		strcat(tbuff, tbuff2);
	}
	decoded = strcat(decoded, decodeB64(tbuff));
	return(decoded);
}

static char
*decodeB64(char *from) {
	char decoded[150];
	int char1, char2, char3, char4;
	int i=0,j=0;
	char base64[] = {
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
			52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
			-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
			15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
			-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
			41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
			};

	decoded[0] = '\0';
	while(from[i] != 0) {
		if((char1 = base64[from[i]]) == -1) 
			return 0;
		if(from[i+1] == '=') {
			char2 = 0;
			decoded[j] = (char1 << 2) | ((char2 & 0x30) >> 4);
			decoded[j+1] = '\0';
			break;
		}else if(from[i+2] == '=') {
			if((char2 = base64[from[i+1]]) == -1)
				return 0;
			char3 = 0;
			decoded[j] = (char1 << 2) | ((char2 & 0x30) >> 4);
			decoded[j+1] = ((char2 & 0x0f) << 4) | ((char3 & 0x3c) >> 2);
			decoded[j+2] = '\0';
			break;
		}else if(from[i+3] == '=') {
			if((char2 = base64[from[i+1]]) == -1)
				return 0;
			if((char3 = base64[from[i+2]]) == -1)
				return 0;
			char4 = 0;
			decoded[j] = (char1 << 2) | ((char2 & 0x30) >> 4);
			decoded[j+1] = ((char2 & 0x0f) << 4) | ((char3 & 0x3c) >> 2);
			decoded[j+2] = ((char3 & 0x03) << 6) | char4;
			decoded[j+3] = '\0';
			break;
		}else {
			if((char2 = base64[from[i+1]]) == -1)
				return 0;
			if((char3 = base64[from[i+2]]) == -1)
				return 0;
			if((char4 = base64[from[i+3]]) == -1)
				return 0;
			decoded[j] = (char1 << 2) | ((char2 & 0x30) >> 4);
			decoded[j+1] = ((char2 & 0x0f) << 4) | ((char3 & 0x3c) >> 2);
			decoded[j+2] = ((char3 & 0x03) << 6) | char4;
			decoded[j+3] = '\0';
			i+=4;
			j+=3;
		}
	}
	return(decoded);
}

/*
 * mime Base64 encode routine
 *		K.Okamoto Nov. 18, 1998
 */

static char	B64charset[] =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static int encodeB64(char*, char*);
char *mime_encode(char*, char*);

char
*mime_encode(char *from, char *encoded) {
	char *jisstr, *ptr;
	char buff[100];
	int i, j;

	ptr = encoded;
	while(*from) {
		if (*from >= ' ' && *from <= 0x7f)	/* ASCII code */
			*ptr++ = *from++;
		else if (*from == '\n' || *from == '\t')
			*ptr++ = *from++;
		else if (*from == '\033') {		/* ESC sequence for JIS code */
			j = 0;
			if (!strncmp(from, "\033$B", 3)) {	/* JISIN */
				strncpy(ptr, "=?ISO-2022-JP?B?", 16);
				jisstr = ptr + 16;
				j = encodeB64(from, jisstr);
				for(i=0;*jisstr;jisstr++, i++);
				ptr = ptr+i+16;
				strncpy(ptr, "?=", 2);
				ptr += 2;
				*ptr = 0;
				from += j;
			}
		}
	}
	if((i = strlen(encoded)) > 66) {		/* folding og large length line */
		strncpy(buff, encoded, 66);
		buff[66] = '\n';
		buff[67] = '\t';
		strncpy(buff+68, encoded+66, i-66);
		i += 2;
		while(*encoded) *encoded = 0;
		strncpy(encoded, buff, i);
		encoded[i] = 0;
	}
	return(encoded);
}

static int
encodeB64(char *from, char *encoded)
{
	int char1, char2, char3;
	char *first;

	first = from;
	while (char1 = *from++) {
		if (char2 = *from++) {
			if (char3 = *from++) {
				*encoded++ = B64charset[char1 >> 2];
				*encoded++ = B64charset[((char1 & 0x3) << 4) | ((char2 & 0xF0) >> 4)];
				*encoded++ = B64charset[((char2 & 0xF) << 2) | ((char3 & 0xC0) >> 6)];
				*encoded++ = B64charset[char3 & 0x3F];
			} else {
				*encoded++ = B64charset[char1 >> 2];
				*encoded++ = B64charset[((char1 & 0x3) << 4) | ((char2 & 0xF0) >> 4)];
				*encoded++ = B64charset[((char2 & 0xF) << 2) | ((0 & 0xC0) >> 6)];
				*encoded++ = '=';
				break;
			}
		} else {
			*encoded++ = B64charset[char1 >> 2];
			*encoded++ = B64charset[((char1 & 0x3) << 4) | ((0 & 0xF0) >> 4)];
			*encoded++ = '=';
			*encoded++ = '=';
			break;
		}
	}
	*encoded = '\0';
	return(from-first);
}


void *
main(void) {

  char txt[150];
  char encoded[150];
  uchar outp[150];
  int i;

  for(i=0;i<150;i++) outp[i]=0;
  for(i=0;i<150;i++) txt[i] = 0;
  strcpy(txt, "Re: ^[$B$3$l$O^[(HmimeB64^[$B$N%F%9%H$G$9^[(H.");
  print("\noriginal text = %s\n", txt);

  tcs((uchar*)txt, outp, "jis", "utf");
  print("\nvisible original text = %s\n", (char *)outp);

  for(i=0;i<150; i++) encoded[i] = 0;
  mime_encode(txt, encoded);
  print("\nencoded string = %s\n", encoded);

  for(i=0;i<150;i++) txt[i]=0;
  print("\ndecoded string = %s\n", mime_decode(encoded, txt));
}
-----end of this mail------




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1998-11-18  9:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-11-18  9:01 [9fans] Base64 mime encode/decode program okamoto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).