gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFC: en/decodeBase64 relocation


From: David Ayers
Subject: RFC: en/decodeBase64 relocation
Date: Sun, 02 Dec 2007 22:32:17 +0100
User-agent: Mozilla Thunderbird 1.0.2 (X11/20070113)

Hello everyone,

Even though base64 encoding is primarily used with MIME processing, its
usage does spring up here in related and unrelated scenarios.  It also
seems more natural as an NSData category to me.

I'm wondering whether this patch:

moving the implementation of GSMime en/decodeBase64: to an NSData
en/decodeBase64 category

would be considered too much of a name pollution issue wrt NSData.

I've had this patch in my tree for some time now (had to clean it up a
bit and check for new usage of the current method so I cleanup some
compiler warnings while I was at it to make sure I don't miss one).

Cheers,
David
Index: Source/NSPropertyList.m
===================================================================
--- Source/NSPropertyList.m     (Revision 25656)
+++ Source/NSPropertyList.m     (Arbeitskopie)
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <limits.h>
 #import "GNUstepBase/preface.h"
-#import "GNUstepBase/GSMime.h"
 
 #import "Foundation/NSArray.h"
 #import "Foundation/NSAutoreleasePool.h"
@@ -228,8 +227,7 @@
     {
       NSData   *d;
 
-      d = [GSMimeDocument decodeBase64:
-            [value dataUsingEncoding: NSASCIIStringEncoding]];
+      d = [[value dataUsingEncoding: NSASCIIStringEncoding] decodeBase64];
       if (opts == NSPropertyListMutableContainersAndLeaves)
        {
          d = AUTORELEASE([d mutableCopy]);
@@ -1304,8 +1302,8 @@
        }
       else if ([name isEqualToString: @"data"])
        {
-         result = [GSMimeDocument decodeBase64:
-                      [content dataUsingEncoding: NSASCIIStringEncoding]];
+         result
+           = [[content dataUsingEncoding: NSASCIIStringEncoding] decodeBase64];
          if (o == NSPropertyListMutableContainersAndLeaves)
            {
              result = AUTORELEASE([result mutableCopy]);
Index: Source/NSMessagePortNameServer.m
===================================================================
--- Source/NSMessagePortNameServer.m    (Revision 25656)
+++ Source/NSMessagePortNameServer.m    (Arbeitskopie)
@@ -26,6 +26,7 @@
 #include "Foundation/NSPortNameServer.h"
 
 #include "Foundation/NSAutoreleasePool.h"
+#include "Foundation/NSData.h"
 #include "Foundation/NSDebug.h"
 #include "Foundation/NSException.h"
 #include "Foundation/NSLock.h"
@@ -35,7 +36,6 @@
 #include "Foundation/NSFileManager.h"
 #include "Foundation/NSValue.h"
 #include "Foundation/NSThread.h"
-#include "GNUstepBase/GSMime.h"
 
 #include "GSPortPrivate.h"
 
@@ -151,7 +151,7 @@
    * strings are valid on all filesystems.
    */
   data = [name dataUsingEncoding: NSUTF8StringEncoding];
-  data = [GSMimeDocument encodeBase64: data];
+  data = [data encodeBase64];
   name = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
   AUTORELEASE(name);
   [serverLock lock];
Index: Source/win32/NSMessagePortNameServerWin32.m
===================================================================
--- Source/win32/NSMessagePortNameServerWin32.m (Revision 25656)
+++ Source/win32/NSMessagePortNameServerWin32.m (Arbeitskopie)
@@ -26,6 +26,7 @@
 #include "Foundation/NSPortNameServer.h"
 
 #include "Foundation/NSAutoreleasePool.h"
+#include "Foundation/NSData.h"
 #include "Foundation/NSDebug.h"
 #include "Foundation/NSError.h"
 #include "Foundation/NSException.h"
@@ -38,8 +39,6 @@
 #include "Foundation/NSThread.h"
 #include "Foundation/NSUserDefaults.h"
 
-#include "GNUstepBase/GSMime.h"
-
 #include "../GSPrivate.h"
 #include "GSPortPrivate.h"
 
@@ -271,7 +270,7 @@
    * assume base64 encoded strings are valid.
    */
   data = [name dataUsingEncoding: NSUTF8StringEncoding];
-  data = [GSMimeDocument encodeBase64: data];
+  data = [data encodeBase64];
   name = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
   AUTORELEASE(name);
   return name;
Index: Source/Additions/GSXML.m
===================================================================
--- Source/Additions/GSXML.m    (Revision 25656)
+++ Source/Additions/GSXML.m    (Arbeitskopie)
@@ -2412,7 +2412,7 @@
   entityId = (eid != 0) ? (id)UTF8Str(eid) : nil;
   location = UTF8Str(url);
   components = [location pathComponents];
-  local = [NSMutableString string];
+  local = [NSMutableString stringWithCapacity: 0];
 
   /*
    * Build a local filename by replacing path separator characters with
@@ -4502,7 +4502,7 @@
   NSData       *d;
   NSString     *s;
 
-  d = [GSMimeDocument encodeBase64: self];
+  d = [self encodeBase64];
   s = [[NSString alloc] initWithData: d encoding: NSASCIIStringEncoding];
   [str appendString: @"<base64>"];
   [str appendString: s];
@@ -4727,7 +4727,7 @@
                      format: @"missing %@ value", name];
        }
       d = [str dataUsingEncoding: NSASCIIStringEncoding];
-      return [GSMimeDocument decodeBase64: d];
+      return [d decodeBase64];
     }
 
   if ([name isEqualToString: @"dateTime.iso8601"])
Index: Source/Additions/GSCategories.m
===================================================================
--- Source/Additions/GSCategories.m     (Revision 25656)
+++ Source/Additions/GSCategories.m     (Arbeitskopie)
@@ -898,6 +898,172 @@
   [encoded appendBytes: "`\nend\n" length: 6];
   return YES;
 }
+
+/*
+ *     Name -          decodebase64()
+ *     Purpose -       Convert 4 bytes in base64 encoding to 3 bytes raw data.
+ */
+static void
+decodebase64(unsigned char *dst, const unsigned char *src)
+{
+  dst[0] =  (src[0]         << 2) | ((src[1] & 0x30) >> 4);
+  dst[1] = ((src[1] & 0x0F) << 4) | ((src[2] & 0x3C) >> 2);
+  dst[2] = ((src[2] & 0x03) << 6) |  (src[3] & 0x3F);
+}
+
+static char b64[]
+  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int
+encodebase64(unsigned char *dst, const unsigned char *src, int length)
+{
+  int  dIndex = 0;
+  int  sIndex;
+
+  for (sIndex = 0; sIndex < length; sIndex += 3)
+    {
+      int      c0 = src[sIndex];
+      int      c1 = (sIndex+1 < length) ? src[sIndex+1] : 0;
+      int      c2 = (sIndex+2 < length) ? src[sIndex+2] : 0;
+
+      dst[dIndex++] = b64[(c0 >> 2) & 077];
+      dst[dIndex++] = b64[((c0 << 4) & 060) | ((c1 >> 4) & 017)];
+      dst[dIndex++] = b64[((c1 << 2) & 074) | ((c2 >> 6) & 03)];
+      dst[dIndex++] = b64[c2 & 077];
+    }
+
+   /* If len was not a multiple of 3, then we have encoded too
+    * many characters.  Adjust appropriately.
+    */
+   if (sIndex == length + 1)
+     {
+       /* There were only 2 bytes in that last group */
+       dst[dIndex - 1] = '=';
+     }
+   else if (sIndex == length + 2)
+     {
+       /* There was only 1 byte in that last group */
+       dst[dIndex - 1] = '=';
+       dst[dIndex - 2] = '=';
+     }
+  return dIndex;
+}
+
+- (NSData*) decodeBase64
+{
+  int          length;
+  int          declen ;
+  const unsigned char  *src;
+  const unsigned char  *end;
+  unsigned char *result;
+  unsigned char        *dst;
+  unsigned char        buf[4];
+  unsigned     pos = 0;
+
+  length = [self length];
+  if (length == 0)
+    {
+      return [NSData data];
+    }
+  declen = ((length + 3) * 3)/4;
+  src = (const unsigned char*)[self bytes];
+  end = &src[length];
+
+  result = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), declen);
+  dst = result;
+
+  while ((src != end) && *src != '\0')
+    {
+      int      c = *src++;
+
+      if (isupper(c))
+       {
+         c -= 'A';
+       }
+      else if (islower(c))
+       {
+         c = c - 'a' + 26;
+       }
+      else if (isdigit(c))
+       {
+         c = c - '0' + 52;
+       }
+      else if (c == '/')
+       {
+         c = 63;
+       }
+      else if (c == '+')
+       {
+         c = 62;
+       }
+      else if  (c == '=')
+       {
+         c = -1;
+       }
+      else if (c == '-')
+       {
+         break;                /* end    */
+       }
+      else
+       {
+         c = -1;               /* ignore */
+       }
+
+      if (c >= 0)
+       {
+         buf[pos++] = c;
+         if (pos == 4)
+           {
+             pos = 0;
+             decodebase64(dst, buf);
+             dst += 3;
+           }
+       }
+    }
+
+  if (pos > 0)
+    {
+      unsigned i;
+
+      for (i = pos; i < 4; i++)
+       {
+         buf[i] = '\0';
+       }
+      pos--;
+      if (pos > 0)
+       {
+         unsigned char tail[3];
+         decodebase64(tail, buf);
+         memcpy(dst, tail, pos);
+         dst += pos;
+       }
+    }
+  return AUTORELEASE([[NSData allocWithZone: NSDefaultMallocZone()]
+    initWithBytesNoCopy: result length: dst - result]);
+}
+
+- (NSData*) encodeBase64
+{
+  int          length;
+  int          destlen;
+  unsigned char *sBuf;
+  unsigned char *dBuf;
+
+  length = [self length];
+  if (length == 0)
+    {
+      return [NSData data];
+    }
+  destlen = 4 * ((length + 2) / 3);
+  sBuf = (unsigned char*)[self bytes];
+  dBuf = NSZoneMalloc(NSDefaultMallocZone(), destlen);
+
+  destlen = encodebase64(dBuf, sBuf, length);
+
+  return AUTORELEASE([[NSData allocWithZone: NSDefaultMallocZone()]
+    initWithBytesNoCopy: dBuf length: destlen]);
+}
+
 @end
 
 
Index: Source/Additions/GSMime.m
===================================================================
--- Source/Additions/GSMime.m   (Revision 25656)
+++ Source/Additions/GSMime.m   (Arbeitskopie)
@@ -333,7 +333,7 @@
 
       [charset getCString: buf];
       md = [NSMutableData dataWithCapacity: [d length]*4/3 + len + 8];
-      d = [documentClass encodeBase64: d];
+      d = [d encodeBase64];
       [md appendBytes: "=?" length: 2];
       [md appendBytes: buf length: len];
       [md appendBytes: "?b?" length: 3];
@@ -3616,112 +3616,21 @@
 
 + (NSData*) decodeBase64: (NSData*)source
 {
-  int          length;
-  int          declen ;
-  const unsigned char  *src;
-  const unsigned char  *end;
-  unsigned char *result;
-  unsigned char        *dst;
-  unsigned char        buf[4];
-  unsigned     pos = 0;
-
-  if (source == nil)
-    {
-      return nil;
-    }
-  length = [source length];
-  if (length == 0)
-    {
-      return [NSData data];
-    }
-  declen = ((length + 3) * 3)/4;
-  src = (const unsigned char*)[source bytes];
-  end = &src[length];
-
-  result = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), declen);
-  dst = result;
-
-  while ((src != end) && *src != '\0')
-    {
-      int      c = *src++;
-
-      if (isupper(c))
-       {
-         c -= 'A';
-       }
-      else if (islower(c))
-       {
-         c = c - 'a' + 26;
-       }
-      else if (isdigit(c))
-       {
-         c = c - '0' + 52;
-       }
-      else if (c == '/')
-       {
-         c = 63;
-       }
-      else if (c == '+')
-       {
-         c = 62;
-       }
-      else if  (c == '=')
-       {
-         c = -1;
-       }
-      else if (c == '-')
-       {
-         break;                /* end    */
-       }
-      else
-       {
-         c = -1;               /* ignore */
-       }
-
-      if (c >= 0)
-       {
-         buf[pos++] = c;
-         if (pos == 4)
-           {
-             pos = 0;
-             decodebase64(dst, buf);
-             dst += 3;
-           }
-       }
-    }
-
-  if (pos > 0)
-    {
-      unsigned i;
-
-      for (i = pos; i < 4; i++)
-       {
-         buf[i] = '\0';
-       }
-      pos--;
-      if (pos > 0)
-       {
-         unsigned char tail[3];
-         decodebase64(tail, buf);
-         memcpy(dst, tail, pos);
-         dst += pos;
-       }
-    }
-  return AUTORELEASE([[NSData allocWithZone: NSDefaultMallocZone()]
-    initWithBytesNoCopy: result length: dst - result]);
+  GSOnceMLog(@"This method is deprecated, use -[NSData decodeBase64]");  
+  return [source decodeBase64];
 }
 
 /**
  * Converts the base64 encoded data in source to a decoded ASCII string
- * using the +decodeBase64: method.  If the encoded data does not represent
- * an ASCII string, you should use the +decodeBase64: method directly.
+ * using [NSData-decodeBase64] method.  If the encoded data does not represent
+ * an ASCII string, you should use the [NSData-decodeBase64] method directly.
  */
 + (NSString*) decodeBase64String: (NSString*)source
 {
   NSData       *d = [source dataUsingEncoding: NSASCIIStringEncoding];
   NSString     *r = nil;
 
-  d = [self decodeBase64: d];
+  d = [d decodeBase64];
   if (d != nil)
     {
       r = [NSStringClass allocWithZone: NSDefaultMallocZone()];
@@ -3748,41 +3657,22 @@
 
 + (NSData*) encodeBase64: (NSData*)source
 {
-  int          length;
-  int          destlen;
-  unsigned char *sBuf;
-  unsigned char *dBuf;
-
-  if (source == nil)
-    {
-      return nil;
-    }
-  length = [source length];
-  if (length == 0)
-    {
-      return [NSData data];
-    }
-  destlen = 4 * ((length + 2) / 3);
-  sBuf = (unsigned char*)[source bytes];
-  dBuf = NSZoneMalloc(NSDefaultMallocZone(), destlen);
-
-  destlen = encodebase64(dBuf, sBuf, length);
-
-  return AUTORELEASE([[NSData allocWithZone: NSDefaultMallocZone()]
-    initWithBytesNoCopy: dBuf length: destlen]);
+  GSOnceMLog(@"This method is deprecated, use -[NSData encodeBase64]");  
+  return [source encodeBase64];
 }
 
 /**
- * Converts the ASCII string source into base64 encoded data using the
- * +encodeBase64: method.  If the original data is not an ASCII string,
- * you should use the +encodeBase64: method directly.
+ * Converts the ASCII string source into base64 encoded data using
+ * [NSData-encodeBase64] method.  If the original data is not an ASCII string,
+ * you should encode the data of the string with [NSData-encodeBase64]
+ * method directly.
  */
 + (NSString*) encodeBase64String: (NSString*)source
 {
   NSData       *d = [source dataUsingEncoding: NSASCIIStringEncoding];
   NSString     *r = nil;
 
-  d = [self encodeBase64: d];
+  d = [d encodeBase64];
   if (d != nil)
     {
       r = [NSStringClass allocWithZone: NSDefaultMallocZone()];
@@ -5346,7 +5236,7 @@
          unsigned      len;
          unsigned      pos = 0;
 
-         d = [documentClass encodeBase64: d];
+         d = [d encodeBase64];
          ptr = [d bytes];
          len = [d length];
 
Index: Headers/Foundation/NSData.h
===================================================================
--- Headers/Foundation/NSData.h (Revision 25656)
+++ Headers/Foundation/NSData.h (Arbeitskopie)
@@ -189,6 +189,22 @@
 - (BOOL) uuencodeInto: (NSMutableData*)encoded
                 name: (NSString*)name
                 mode: (int)mode;
+/**
+ * Encode the source data to base64 encoding and return the result.<br />
+ * The resulting data is ASCII text and contains only the base64 encoded
+ * values with no line breaks or extraneous data.  This is base64 encoded
+ * data in it's general format as mandated in RFC 3548.  If the data is
+ * to be used as part of a MIME document body, line breaks must be
+ * introduced at 76 byte intervals.  If the data is to be used in a PEM 
document
+ * line breaks must be introduced at 74 byte intervals.
+ */
+- (NSData*) encodeBase64;
+/**
+ * Decode the source data from base64 encoding and return the result.<br />
+ * The source data is expected to be ASCII text and may be multiple
+ * lines or a line of any length (decoding is very tolerant).
+ */
+- (NSData*) decodeBase64;
 @end
 
 /*
Index: Headers/Additions/GNUstepBase/GSCategories.h
===================================================================
--- Headers/Additions/GNUstepBase/GSCategories.h        (Revision 25656)
+++ Headers/Additions/GNUstepBase/GSCategories.h        (Arbeitskopie)
@@ -213,6 +213,22 @@
 - (BOOL) uuencodeInto: (NSMutableData*)encoded
                 name: (NSString*)name
                 mode: (int)mode;
+/**
+ * Encode the source data to base64 encoding and return the result.<br />
+ * The resulting data is ASCII text and contains only the base64 encoded
+ * values with no line breaks or extraneous data.  This is base64 encoded
+ * data in it's general format as mandated in RFC 3548.  If the data is
+ * to be used as part of a MIME document body, line breaks must be
+ * introduced at 76 byte intervals.  If the data is to be used in a PEM 
document
+ * line breaks must be introduced at 74 byte intervals.
+ */
+- (NSData*) encodeBase64;
+/**
+ * Decode the source data from base64 encoding and return the result.<br />
+ * The source data is expected to be ASCII text and may be multiple
+ * lines or a line of any length (decoding is very tolerant).
+ */
+- (NSData*) decodeBase64;
 @end
 
 @interface NSString (GSCategories)
Index: Headers/Additions/GNUstepBase/GSMime.h
===================================================================
--- Headers/Additions/GNUstepBase/GSMime.h      (Revision 25656)
+++ Headers/Additions/GNUstepBase/GSMime.h      (Arbeitskopie)
@@ -116,7 +116,6 @@
  * The source data is expected to be ASCII text and may be multiple
  * lines or a line of any length (decoding is very tolerant).
  */
-+ (NSData*) decodeBase64: (NSData*)source;
 + (NSString*) decodeBase64String: (NSString*)source;
 + (GSMimeDocument*) documentWithContent: (id)newContent
                                   type: (NSString*)type
@@ -131,7 +130,6 @@
  * encoding data for you).  If the data is to be used in a PEM document
  * line breaks must be introduced at 74 byte intervals.
  */
-+ (NSData*) encodeBase64: (NSData*)source;
 + (NSString*) encodeBase64String: (NSString*)source;
 + (NSStringEncoding) encodingFromCharset: (NSString*)charset;
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]