cvs: /php3/functions imap.c imap.h

From: Date: Mon, 17 Jan 2000 19:19:04 +0000
Subject: cvs: /php3/functions imap.c imap.h
Groups: php.dev 
Request: Send a blank email to php-dev+get-14719@lists.php.net to get a copy of this message
askalski Mon Jan 17 11:19:04 2000 EDT Modified files: /php3/functions imap.c imap.h Log: Added imap_utf7_decode() and imap_utf7_encode() functions. Index: php3/functions/imap.c diff -u php3/functions/imap.c:1.77 php3/functions/imap.c:1.78 --- php3/functions/imap.c:1.77 Sat Jan 15 13:39:15 2000 +++ php3/functions/imap.c Mon Jan 17 11:19:03 2000 @@ -33,7 +33,7 @@ | Andrew Skalski <askalski@chek.com> | +----------------------------------------------------------------------+ */ -/* $Id: imap.c,v 1.77 2000/01/15 21:39:15 fmk Exp $ */ +/* $Id: imap.c,v 1.78 2000/01/17 19:19:03 askalski Exp $ */ #define IMAP41 @@ -199,6 +199,8 @@ {"imap_mail", php3_imap_mail, NULL}, {"imap_search", php3_imap_search, NULL}, {"imap_utf8", php3_imap_utf8, NULL}, + {"imap_utf7_decode", php3_imap_utf7_decode, NULL}, + {"imap_utf7_encode", php3_imap_utf7_encode, NULL}, {NULL, NULL, NULL} }; @@ -2492,7 +2494,6 @@ /* }}} */ - /* {{{ proto string imap_utf8(string string) Convert a string to UTF8 */ void php3_imap_utf8(INTERNAL_FUNCTION_PARAMETERS) @@ -2515,6 +2516,251 @@ RETURN_STRINGL(dest.data,strlen(dest.data),1); } /* }}} */ + +/* macros for the modified utf7 conversion functions */ +/* author: Andrew Skalski <askalski@chek.com> */ + +/* tests `c' and returns true if it is a special character */ +#define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f) +/* validate a modified-base64 character */ +#define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',') +/* map the low 64 bits of `n' to the modified-base64 characters */ +#define B64(n) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz0123456789+,"[(n) & 0x3f]; +/* map the modified-base64 character `c' to its 64 bit value */ +#define UNB64(c) ((c) == '+' ? 62 : (c) == ',' ? 63 : (c) >= 'a' ? \ + (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4) + +/* {{{ proto string imap_utf7_decode(string buf) + Decode a Modified UTF-7 string */ +void php3_imap_utf7_decode(INTERNAL_FUNCTION_PARAMETERS) +{ + /* author: Andrew Skalski <askalski@chek.com> */ + int argc; + pval *arg; + const unsigned char *in, *inp, *endp; + unsigned char *out, *outp; + int inlen, outlen; + enum { ST_NORMAL, /* printable text */ + ST_DECODE0, /* encoded text rotation... */ + ST_DECODE1, + ST_DECODE2, + ST_DECODE3 + } state; + + /* collect arguments */ + argc = ARG_COUNT(ht); + if (argc != 1 || getParameters(ht, argc, &arg) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(arg); + in = (const unsigned char*) arg->value.str.val; + inlen = arg->value.str.len; + + /* validate and compute length of output string */ + outlen = 0; + state = ST_NORMAL; + for (endp = (inp = in) + inlen; inp < endp; inp++) { + if (state == ST_NORMAL) { + /* process printable character */ + if (SPECIAL(*inp)) + {RETURN_FALSE;} + else if (*inp != '&') + outlen++; + else if (inp == endp) + {RETURN_FALSE;} + else if (inp[1] != '-') + state = ST_DECODE0; + else { + outlen++; + inp++; + } + } + else if (*inp == '-') { + /* return to NORMAL mode */ + if (state == ST_DECODE1) + RETURN_FALSE; + state = ST_NORMAL; + } + else if (!B64CHAR(*inp)) + {RETURN_FALSE;} + else { + switch (state) { + case ST_DECODE3: + outlen++; + state = ST_DECODE0; + break; + case ST_DECODE2: + case ST_DECODE1: + outlen++; + case ST_DECODE0: + state++; + case ST_NORMAL: + } + } + } + + /* enforce end state */ + if (state != ST_NORMAL) + RETURN_FALSE; + + /* allocate output buffer */ + if ((out = emalloc(outlen)) == NULL) + RETURN_FALSE; + + /* decode input string */ + outp = out; + state = ST_NORMAL; + for (endp = (inp = in) + inlen; inp < endp; inp++) { + if (state == ST_NORMAL) { + if (*inp == '&' && inp[1] != '-') + state = ST_DECODE0; + else if ((*outp++ = *inp) == '&') + inp++; + } + else if (*inp == '-') + state = ST_NORMAL; + else { + /* decode input character */ + switch (state) { + case ST_DECODE0: + *outp = UNB64(*inp) << 2; + state = ST_DECODE1; + break; + case ST_DECODE1: + outp[1] = UNB64(*inp); + *outp++ |= outp[1] >> 4; + *outp <<= 4; + state = ST_DECODE2; + break; + case ST_DECODE2: + outp[1] = UNB64(*inp); + *outp++ |= outp[1] >> 2; + *outp <<= 6; + state = ST_DECODE3; + break; + case ST_DECODE3: + *outp++ |= UNB64(*inp); + state = ST_DECODE0; + case ST_NORMAL: + } + } + } + + RETURN_STRINGL(out, outlen, 0); +} +/* }}} */ + +/* {{{ proto string imap_utf7_decode(string buf) + Encode a string in Modified UTF-7 */ +void php3_imap_utf7_encode(INTERNAL_FUNCTION_PARAMETERS) +{ + /* author: Andrew Skalski <askalski@chek.com> */ + int argc; + pval *arg; + const unsigned char *in, *inp, *endp; + unsigned char *out, *outp; + int inlen, outlen; + enum { ST_NORMAL, /* printable text */ + ST_ENCODE0, /* encoded text rotation... */ + ST_ENCODE1, + ST_ENCODE2 + } state; + + /* collect arguments */ + argc = ARG_COUNT(ht); + if (argc != 1 || getParameters(ht, argc, &arg) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(arg); + in = (const unsigned char*) arg->value.str.val; + inlen = arg->value.str.len; + + /* compute the length of the result string */ + outlen = 0; + state = ST_NORMAL; + endp = (inp = in) + inlen; + while (inp < endp) { + if (state == ST_NORMAL) { + if (SPECIAL(*inp)) { + state = ST_ENCODE0; + outlen++; + } + else if (*inp++ == '&') + outlen++; + outlen++; + } + else if (!SPECIAL(*inp)) + state = ST_NORMAL; + else { + /* ST_ENCODE0 -> ST_ENCODE1 - two chars + * ST_ENCODE1 -> ST_ENCODE2 - one char + * ST_ENCODE2 -> ST_ENCODE0 - one char + */ + if (state == ST_ENCODE2) + state = ST_ENCODE0; + else if (state++ == ST_ENCODE0) + outlen++; + outlen++; + inp++; + } + } + + /* allocate output buffer */ + if ((out = emalloc(outlen)) == NULL) + RETURN_FALSE; + + /* encode input string */ + outp = out; + state = ST_NORMAL; + endp = (inp = in) + inlen; + while (inp < endp || state != ST_NORMAL) { + if (state == ST_NORMAL) { + if (SPECIAL(*inp)) { + /* begin encoding */ + *outp++ = '&'; + state = ST_ENCODE0; + } + else if ((*outp++ = *inp++) == '&') + *outp++ = '-'; + } + else if (inp == endp || !SPECIAL(*inp)) { + /* flush overflow and terminate region */ + if (state != ST_ENCODE0) + *outp++ = B64(*outp); + *outp++ = '-'; + state = ST_NORMAL; + } + else { + /* encode input character */ + switch (state) { + case ST_ENCODE0: + *outp++ = B64(*inp >> 2); + *outp = *inp++ << 4; + state = ST_ENCODE1; + break; + case ST_ENCODE1: + *outp++ = B64(*outp | *inp >> 4); + *outp = *inp++ << 2; + state = ST_ENCODE2; + break; + case ST_ENCODE2: + *outp++ = B64(*outp | *inp >> 6); + *outp++ = B64(*inp++); + state = ST_ENCODE0; + case ST_NORMAL: + } + } + } + + RETURN_STRINGL(out, outlen, 0); +} +/* }}} */ + +#undef SPECIAL +#undef B64CHAR +#undef B64 +#undef UNB64 /* {{{ proto int imap_setflag_full(int stream_id, string sequence, string flag [, int options]) Sets flags on messages */ Index: php3/functions/imap.h diff -u php3/functions/imap.h:1.15 php3/functions/imap.h:1.16 --- php3/functions/imap.h:1.15 Wed Jan 12 00:57:14 2000 +++ php3/functions/imap.h Mon Jan 17 11:19:03 2000 @@ -1,4 +1,4 @@ -/* $Id: imap.h,v 1.15 2000/01/12 08:57:14 fmk Exp $ */ +/* $Id: imap.h,v 1.16 2000/01/17 19:19:03 askalski Exp $ */ #ifndef _INCLUDED_IMAP_H #define _INCLUDED_IMAP_H @@ -76,6 +76,8 @@ void php3_imap_mail(INTERNAL_FUNCTION_PARAMETERS); void php3_imap_search(INTERNAL_FUNCTION_PARAMETERS); void php3_imap_utf8(INTERNAL_FUNCTION_PARAMETERS); +void php3_imap_utf7_decode(INTERNAL_FUNCTION_PARAMETERS); +void php3_imap_utf7_encode(INTERNAL_FUNCTION_PARAMETERS); #else #define php3_imap_module_ptr NULL #endif /* HAVE_IMAP */

« previous php.dev (#14719) next »