Index: doc/src/sgml/datatype.sgml =================================================================== RCS file: /home/cvs/pgsql/pgsql/doc/src/sgml/datatype.sgml,v retrieving revision 1.55 diff --unified -r1.55 datatype.sgml --- doc/src/sgml/datatype.sgml 2001/05/22 16:37:15 1.55 +++ doc/src/sgml/datatype.sgml 2001/06/22 20:09:08 @@ -48,6 +48,12 @@ + bytea + + a variable-length raw string, could contain nulls + + + bigint int8 signed eight-byte integer Index: doc/src/sgml/func.sgml =================================================================== RCS file: /home/cvs/pgsql/pgsql/doc/src/sgml/func.sgml,v retrieving revision 1.61 diff --unified -r1.61 func.sgml --- doc/src/sgml/func.sgml 2001/06/15 21:03:07 1.61 +++ doc/src/sgml/func.sgml 2001/06/22 20:19:41 @@ -1037,6 +1037,32 @@ a23x5 + + + base64_encode(string bytea) + + text + + Uses base64 algorithm to encode binary data in string. + Returns text value guaranteed to contain only printable string + + base64_encode('123\\000\\001') + MTIzAAE= + + + + + base64_decode(string text) + + bytea + + Decodes binary data from string previously + encoded with base64 algorithm. + + base64_decode('MTIzAAE=') + 123\000\001 + + Index: src/backend/utils/adt/varlena.c =================================================================== RCS file: /home/cvs/pgsql/pgsql/src/backend/utils/adt/varlena.c,v retrieving revision 1.70 diff --unified -r1.70 varlena.c --- src/backend/utils/adt/varlena.c 2001/05/03 19:00:36 1.70 +++ src/backend/utils/adt/varlena.c 2001/06/22 21:12:51 @@ -20,7 +20,14 @@ #include "miscadmin.h" #include "utils/builtins.h" +static char base64_dtable[256]; +static char base64_etable[256]; +static bool base64_tables_set=false; + static int text_cmp(text *arg1, text *arg2); +static void init_base64_tables(void); +static int do_base64_encode(char *in, int maxlen, char *out); +static int do_base64_decode(char *in, int maxlen, char *out); /***************************************************************************** @@ -875,3 +882,172 @@ PG_RETURN_TEXT_P(result); } + +/* base64_encode() + * Converts a bytea value to base-64 encoded 'text' string + */ +Datum +base64_encode(PG_FUNCTION_ARGS) +{ + bytea *s = PG_GETARG_BYTEA_P(0); + text *result; + int lenin, lenout; + + lenin = VARSIZE(s) - VARHDRSZ; + + result = (text *) palloc(lenin*4/3+10+VARHDRSZ); + + lenout=do_base64_encode(VARDATA(s), lenin, VARDATA(result)); + + VARATT_SIZEP(result) = lenout+VARHDRSZ; + + PG_RETURN_TEXT_P(result); +} + +/* base64_decode() + * Converts base-64 encoded 'text' string to bytea value + */ +Datum +base64_decode(PG_FUNCTION_ARGS) +{ + text * s = PG_GETARG_TEXT_P(0); + bytea *result; + int lenin, lenout; + + lenin = VARSIZE(s) - VARHDRSZ; + + result = (bytea *) palloc((int) lenin*3/4+10+VARHDRSZ); + + lenout = do_base64_decode(VARDATA(s), lenin, VARDATA(result)); + + VARATT_SIZEP(result) = lenout+VARHDRSZ; + + PG_RETURN_BYTEA_P(result); +} + +/* most of code lifted from public-domain base64 by John Walker */ + +void init_base64_tables(void) { + int i; + if (base64_tables_set) return; + + for (i = 0; i < 26; i++) { + base64_etable[i] = 'A' + i; + base64_etable[26 + i] = 'a' + i; + } + for (i = 0; i < 10; i++) { + base64_etable[52 + i] = '0' + i; + } + base64_etable[62] = '+'; + base64_etable[63] = '/'; + + for (i = 0; i < 255; i++) { + base64_dtable[i] = 0x80; + } + for (i = 'A'; i <= 'Z'; i++) { + base64_dtable[i] = 0 + (i - 'A'); + } + for (i = 'a'; i <= 'z'; i++) { + base64_dtable[i] = 26 + (i - 'a'); + } + for (i = '0'; i <= '9'; i++) { + base64_dtable[i] = 52 + (i - '0'); + } + + base64_dtable['+'] = 62; + base64_dtable['/'] = 63; + base64_dtable['='] = 0; + + base64_tables_set=true; +} + + +/* this function requires out to be already allocated, + it must have (maxlen*4/3)+3 bytes + returns number of characters in out +*/ +int do_base64_encode(char *in, int maxlen, char *out) +{ + int i; + bool hiteof = false; /* read the last character */ + int p; /* index of current character */ + char *s=out; + char igroup[3]; + char ogroup[4]; + int n; + + init_base64_tables(); + + for(p=0;p 0) { + ogroup[0] = base64_etable[igroup[0] >> 2]; + ogroup[1] = base64_etable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; + ogroup[2] = base64_etable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; + ogroup[3] = base64_etable[igroup[2] & 0x3F]; + + /* Replace characters in output stream with "=" pad + characters if fewer than three characters were + read from the end of the input stream. */ + + if (n < 3) { + ogroup[3] = '='; + if (n < 2) { + ogroup[2] = '='; + } + } + for (i = 0; i < 4; i++) { + *s++=ogroup[i]; + } + } + } + return s-out; +} + + +int do_base64_decode(char *in, int maxlen, char *out) +{ + int p=0; + int i,j; + char *s=out; + init_base64_tables(); + while (true) { + char a[4], b[4], o[3]; + int c; + + for (i = 0; i < 4; i++) { + while (true) { /* get a printable character*/ + if (p==maxlen) { /* end of string */ + if (i > 0) + elog(ERROR, "base64_decode: Input string incomplete"); + return s-out; /* done */ + } + c = in[p++]; + if ( c > ' ' ) break; + } + + if ( (base64_dtable[c] & 0x80) || (!isprint(c)) ) + elog(ERROR, "base64_decode: Illegal character '%c' in input string.\n", c); + a[i] = c; + b[i] = base64_dtable[c]; + } + o[0] = (b[0] << 2) | (b[1] >> 4); + o[1] = (b[1] << 4) | (b[2] >> 2); + o[2] = (b[2] << 6) | b[3]; + i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3); + + for (j=0;j