I am attaching a patch to eliminate duplicate b64_encode and decode
functions from pgcrypto, and to expose those functions for use by
add-ins (I want to use them in Veil).

The patch was made against CVS head today.  It compiles and tests
successfully.  Though I was unable to run pgrypto regression tests, I
did give the b64 encoding a sanity check.

I also added a b64_char() function that is now used from pgcrypto.  This
allowed me to remove the duplicate _base64 character array.

I hope this is the correct place to submit the patch.  The wiki
(http://wiki.postgresql.org/wiki/Submitting_a_Patch) refers to
pgsql-patches but I believe that is now deprecated.


__
Marc
Index: contrib/pgcrypto/pgp-armor.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/pgcrypto/pgp-armor.c,v
retrieving revision 1.3
diff -c -r1.3 pgp-armor.c
*** contrib/pgcrypto/pgp-armor.c	15 Oct 2005 02:49:06 -0000	1.3
--- contrib/pgcrypto/pgp-armor.c	17 Jul 2008 22:37:27 -0000
***************
*** 30,181 ****
   */
  
  #include "postgres.h"
  
  #include "px.h"
  #include "mbuf.h"
  #include "pgp.h"
  
  /*
-  * BASE64 - duplicated :(
-  */
- 
- static const unsigned char _base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- 
- static int
- b64_encode(const uint8 *src, unsigned len, uint8 *dst)
- {
- 	uint8	   *p,
- 			   *lend = dst + 76;
- 	const uint8 *s,
- 			   *end = src + len;
- 	int			pos = 2;
- 	unsigned long buf = 0;
- 
- 	s = src;
- 	p = dst;
- 
- 	while (s < end)
- 	{
- 		buf |= *s << (pos << 3);
- 		pos--;
- 		s++;
- 
- 		/*
- 		 * write it out
- 		 */
- 		if (pos < 0)
- 		{
- 			*p++ = _base64[(buf >> 18) & 0x3f];
- 			*p++ = _base64[(buf >> 12) & 0x3f];
- 			*p++ = _base64[(buf >> 6) & 0x3f];
- 			*p++ = _base64[buf & 0x3f];
- 
- 			pos = 2;
- 			buf = 0;
- 		}
- 		if (p >= lend)
- 		{
- 			*p++ = '\n';
- 			lend = p + 76;
- 		}
- 	}
- 	if (pos != 2)
- 	{
- 		*p++ = _base64[(buf >> 18) & 0x3f];
- 		*p++ = _base64[(buf >> 12) & 0x3f];
- 		*p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
- 		*p++ = '=';
- 	}
- 
- 	return p - dst;
- }
- 
- /* probably should use lookup table */
- static int
- b64_decode(const uint8 *src, unsigned len, uint8 *dst)
- {
- 	const uint8 *srcend = src + len,
- 			   *s = src;
- 	uint8	   *p = dst;
- 	char		c;
- 	unsigned	b = 0;
- 	unsigned long buf = 0;
- 	int			pos = 0,
- 				end = 0;
- 
- 	while (s < srcend)
- 	{
- 		c = *s++;
- 		if (c >= 'A' && c <= 'Z')
- 			b = c - 'A';
- 		else if (c >= 'a' && c <= 'z')
- 			b = c - 'a' + 26;
- 		else if (c >= '0' && c <= '9')
- 			b = c - '0' + 52;
- 		else if (c == '+')
- 			b = 62;
- 		else if (c == '/')
- 			b = 63;
- 		else if (c == '=')
- 		{
- 			/*
- 			 * end sequence
- 			 */
- 			if (!end)
- 			{
- 				if (pos == 2)
- 					end = 1;
- 				else if (pos == 3)
- 					end = 2;
- 				else
- 					return PXE_PGP_CORRUPT_ARMOR;
- 			}
- 			b = 0;
- 		}
- 		else if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
- 			continue;
- 		else
- 			return PXE_PGP_CORRUPT_ARMOR;
- 
- 		/*
- 		 * add it to buffer
- 		 */
- 		buf = (buf << 6) + b;
- 		pos++;
- 		if (pos == 4)
- 		{
- 			*p++ = (buf >> 16) & 255;
- 			if (end == 0 || end > 1)
- 				*p++ = (buf >> 8) & 255;
- 			if (end == 0 || end > 2)
- 				*p++ = buf & 255;
- 			buf = 0;
- 			pos = 0;
- 		}
- 	}
- 
- 	if (pos != 0)
- 		return PXE_PGP_CORRUPT_ARMOR;
- 	return p - dst;
- }
- 
- static unsigned
- b64_enc_len(unsigned srclen)
- {
- 	/*
- 	 * 3 bytes will be converted to 4, linefeed after 76 chars
- 	 */
- 	return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4);
- }
- 
- static unsigned
- b64_dec_len(unsigned srclen)
- {
- 	return (srclen * 3) >> 2;
- }
- 
- /*
   * PGP armor
   */
  
--- 30,42 ----
   */
  
  #include "postgres.h"
+ #include "utils/builtins.h"
  
  #include "px.h"
  #include "mbuf.h"
  #include "pgp.h"
  
  /*
   * PGP armor
   */
  
***************
*** 215,234 ****
  	memcpy(pos, armor_header, n);
  	pos += n;
  
! 	n = b64_encode(src, len, pos);
  	pos += n;
  
  	if (*(pos - 1) != '\n')
  		*pos++ = '\n';
  
  	*pos++ = '=';
! 	pos[3] = _base64[crc & 0x3f];
  	crc >>= 6;
! 	pos[2] = _base64[crc & 0x3f];
  	crc >>= 6;
! 	pos[1] = _base64[crc & 0x3f];
  	crc >>= 6;
! 	pos[0] = _base64[crc & 0x3f];
  	pos += 4;
  
  	n = strlen(armor_footer);
--- 76,95 ----
  	memcpy(pos, armor_header, n);
  	pos += n;
  
! 	n = b64_encode((char *) src, len, (char *) pos);
  	pos += n;
  
  	if (*(pos - 1) != '\n')
  		*pos++ = '\n';
  
  	*pos++ = '=';
! 	pos[3] = b64_char(crc);
  	crc >>= 6;
! 	pos[2] = b64_char(crc);
  	crc >>= 6;
! 	pos[1] = b64_char(crc);
  	crc >>= 6;
! 	pos[0] = b64_char(crc);
  	pos += 4;
  
  	n = strlen(armor_footer);
***************
*** 356,367 ****
  		goto out;
  
  	/* decode crc */
! 	if (b64_decode(p + 1, 4, buf) != 3)
  		goto out;
  	crc = (((long) buf[0]) << 16) + (((long) buf[1]) << 8) + (long) buf[2];
  
  	/* decode data */
! 	res = b64_decode(base64_start, base64_end - base64_start, dst);
  
  	/* check crc */
  	if (res >= 0 && crc24(dst, res) != crc)
--- 217,229 ----
  		goto out;
  
  	/* decode crc */
! 	if (b64_decode((char *) (p + 1), 4, (char *) buf) != 3)
  		goto out;
  	crc = (((long) buf[0]) << 16) + (((long) buf[1]) << 8) + (long) buf[2];
  
  	/* decode data */
! 	res = b64_decode((char *) base64_start, base64_end - base64_start, 
! 					 (char *) dst);
  
  	/* check crc */
  	if (res >= 0 && crc24(dst, res) != crc)
***************
*** 373,383 ****
  unsigned
  pgp_armor_enc_len(unsigned len)
  {
! 	return b64_enc_len(len) + strlen(armor_header) + strlen(armor_footer) + 16;
  }
  
  unsigned
  pgp_armor_dec_len(unsigned len)
  {
! 	return b64_dec_len(len);
  }
--- 235,246 ----
  unsigned
  pgp_armor_enc_len(unsigned len)
  {
! 	return b64_enc_len(NULL, len) + strlen(armor_header) + 
! 		strlen(armor_footer) + 16;
  }
  
  unsigned
  pgp_armor_dec_len(unsigned len)
  {
! 	return b64_dec_len(NULL, len);
  }
Index: src/backend/utils/adt/encode.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/encode.c,v
retrieving revision 1.22
diff -c -r1.22 encode.c
*** src/backend/utils/adt/encode.c	25 Mar 2008 22:42:44 -0000	1.22
--- src/backend/utils/adt/encode.c	17 Jul 2008 22:37:28 -0000
***************
*** 214,220 ****
  	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
  };
  
! static unsigned
  b64_encode(const char *src, unsigned len, char *dst)
  {
  	char	   *p,
--- 214,226 ----
  	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
  };
  
! char
! b64_char(unsigned src)
! {
! 	return _base64[src & 0x3f];
! }
! 
! unsigned
  b64_encode(const char *src, unsigned len, char *dst)
  {
  	char	   *p,
***************
*** 261,267 ****
  	return p - dst;
  }
  
! static unsigned
  b64_decode(const char *src, unsigned len, char *dst)
  {
  	const char *srcend = src + len,
--- 267,273 ----
  	return p - dst;
  }
  
! unsigned
  b64_decode(const char *src, unsigned len, char *dst)
  {
  	const char *srcend = src + len,
***************
*** 330,343 ****
  }
  
  
! static unsigned
  b64_enc_len(const char *src, unsigned srclen)
  {
  	/* 3 bytes will be converted to 4, linefeed after 76 chars */
  	return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4);
  }
  
! static unsigned
  b64_dec_len(const char *src, unsigned srclen)
  {
  	return (srclen * 3) >> 2;
--- 336,349 ----
  }
  
  
! unsigned
  b64_enc_len(const char *src, unsigned srclen)
  {
  	/* 3 bytes will be converted to 4, linefeed after 76 chars */
  	return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4);
  }
  
! unsigned
  b64_dec_len(const char *src, unsigned srclen)
  {
  	return (srclen * 3) >> 2;
Index: src/include/utils/builtins.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.318
diff -c -r1.318 builtins.h
*** src/include/utils/builtins.h	3 Jul 2008 20:58:47 -0000	1.318
--- src/include/utils/builtins.h	17 Jul 2008 22:37:28 -0000
***************
*** 677,684 ****
  extern Datum byteaGetBit(PG_FUNCTION_ARGS);
  extern Datum byteaSetByte(PG_FUNCTION_ARGS);
  extern Datum byteaSetBit(PG_FUNCTION_ARGS);
- extern Datum binary_encode(PG_FUNCTION_ARGS);
- extern Datum binary_decode(PG_FUNCTION_ARGS);
  extern Datum byteaeq(PG_FUNCTION_ARGS);
  extern Datum byteane(PG_FUNCTION_ARGS);
  extern Datum bytealt(PG_FUNCTION_ARGS);
--- 677,682 ----
***************
*** 692,697 ****
--- 690,704 ----
  extern Datum bytea_substr_no_len(PG_FUNCTION_ARGS);
  extern Datum pg_column_size(PG_FUNCTION_ARGS);
  
+ /* encode.c */
+ extern Datum binary_encode(PG_FUNCTION_ARGS);
+ extern Datum binary_decode(PG_FUNCTION_ARGS);
+ extern char b64_char(unsigned src);
+ extern unsigned b64_encode(const char *src, unsigned len, char *dst);
+ extern unsigned b64_decode(const char *src, unsigned len, char *dst);
+ extern unsigned b64_enc_len(const char *src, unsigned srclen);
+ extern unsigned b64_dec_len(const char *src, unsigned srclen);
+ 
  /* version.c */
  extern Datum pgsql_version(PG_FUNCTION_ARGS);
  

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to