现在的位置: 首页 > 综合 > 正文

GTMBase64

2017年12月09日 ⁄ 综合 ⁄ 共 33463字 ⁄ 字号 评论关闭

Base64.h

  1. //  
  2. //  GTMBase64.h  
  3. //  
  4. //  Copyright 2006-2008 Google Inc.  
  5. //  
  6. //  Licensed under the Apache License, Version 2.0 (the "License"); you may not  
  7. //  use this file except in compliance with the License.  You may obtain a copy  
  8. //  of the License at  
  9. //  
  10. //  http://www.apache.org/licenses/LICENSE-2.0  
  11. //  
  12. //  Unless required by applicable law or agreed to in writing, software  
  13. //  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  
  14. //  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the  
  15. //  License for the specific language governing permissions and limitations under  
  16. //  the License.  
  17. //  
  18.   
  19. #import <Foundation/Foundation.h>  
  20. #import "GTMDefines.h"  
  21.   
  22. // GTMBase64  
  23. //  
  24. /// Helper for handling Base64 and WebSafeBase64 encodings  
  25. //  
  26. /// The webSafe methods use different character set and also the results aren't  
  27. /// always padded to a multiple of 4 characters.  This is done so the resulting  
  28. /// data can be used in urls and url query arguments without needing any  
  29. /// encoding.  You must use the webSafe* methods together, the data does not  
  30. /// interop with the RFC methods.  
  31. //  
  32. @interface GTMBase64 : NSObject  
  33.   
  34. //  
  35. // Standard Base64 (RFC) handling  
  36. //  
  37.   
  38. // encodeData:  
  39. //  
  40. /// Base64 encodes contents of the NSData object.  
  41. //  
  42. /// Returns:  
  43. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  44. //  
  45. +(NSData *)encodeData:(NSData *)data;  
  46.   
  47. // decodeData:  
  48. //  
  49. /// Base64 decodes contents of the NSData object.  
  50. //  
  51. /// Returns:  
  52. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  53. //  
  54. +(NSData *)decodeData:(NSData *)data;  
  55.   
  56. // encodeBytes:length:  
  57. //  
  58. /// Base64 encodes the data pointed at by |bytes|.  
  59. //  
  60. /// Returns:  
  61. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  62. //  
  63. +(NSData *)encodeBytes:(const void *)bytes length:(NSUInteger)length;  
  64.   
  65. // decodeBytes:length:  
  66. //  
  67. /// Base64 decodes the data pointed at by |bytes|.  
  68. //  
  69. /// Returns:  
  70. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  71. //  
  72. +(NSData *)decodeBytes:(const void *)bytes length:(NSUInteger)length;  
  73.   
  74. // stringByEncodingData:  
  75. //  
  76. /// Base64 encodes contents of the NSData object.  
  77. //  
  78. /// Returns:  
  79. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  80. //  
  81. +(NSString *)stringByEncodingData:(NSData *)data;  
  82.   
  83. // stringByEncodingBytes:length:  
  84. //  
  85. /// Base64 encodes the data pointed at by |bytes|.  
  86. //  
  87. /// Returns:  
  88. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  89. //  
  90. +(NSString *)stringByEncodingBytes:(const void *)bytes length:(NSUInteger)length;  
  91.   
  92. // decodeString:  
  93. //  
  94. /// Base64 decodes contents of the NSString.  
  95. //  
  96. /// Returns:  
  97. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  98. //  
  99. +(NSData *)decodeString:(NSString *)string;  
  100.   
  101. //  
  102. // Modified Base64 encoding so the results can go onto urls.  
  103. //  
  104. // The changes are in the characters generated and also allows the result to  
  105. // not be padded to a multiple of 4.  
  106. // Must use the matching call to encode/decode, won't interop with the  
  107. // RFC versions.  
  108. //  
  109.   
  110. // webSafeEncodeData:padded:  
  111. //  
  112. /// WebSafe Base64 encodes contents of the NSData object.  If |padded| is YES  
  113. /// then padding characters are added so the result length is a multiple of 4.  
  114. //  
  115. /// Returns:  
  116. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  117. //  
  118. +(NSData *)webSafeEncodeData:(NSData *)data  
  119.                       padded:(BOOL)padded;  
  120.   
  121. // webSafeDecodeData:  
  122. //  
  123. /// WebSafe Base64 decodes contents of the NSData object.  
  124. //  
  125. /// Returns:  
  126. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  127. //  
  128. +(NSData *)webSafeDecodeData:(NSData *)data;  
  129.   
  130. // webSafeEncodeBytes:length:padded:  
  131. //  
  132. /// WebSafe Base64 encodes the data pointed at by |bytes|.  If |padded| is YES  
  133. /// then padding characters are added so the result length is a multiple of 4.  
  134. //  
  135. /// Returns:  
  136. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  137. //  
  138. +(NSData *)webSafeEncodeBytes:(const void *)bytes  
  139.                        length:(NSUInteger)length  
  140.                        padded:(BOOL)padded;  
  141.   
  142. // webSafeDecodeBytes:length:  
  143. //  
  144. /// WebSafe Base64 decodes the data pointed at by |bytes|.  
  145. //  
  146. /// Returns:  
  147. ///   A new autoreleased NSData with the encoded payload.  nil for any error.  
  148. //  
  149. +(NSData *)webSafeDecodeBytes:(const void *)bytes length:(NSUInteger)length;  
  150.   
  151. // stringByWebSafeEncodingData:padded:  
  152. //  
  153. /// WebSafe Base64 encodes contents of the NSData object.  If |padded| is YES  
  154. /// then padding characters are added so the result length is a multiple of 4.  
  155. //  
  156. /// Returns:  
  157. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  158. //  
  159. +(NSString *)stringByWebSafeEncodingData:(NSData *)data  
  160.                                   padded:(BOOL)padded;  
  161.   
  162. // stringByWebSafeEncodingBytes:length:padded:  
  163. //  
  164. /// WebSafe Base64 encodes the data pointed at by |bytes|.  If |padded| is YES  
  165. /// then padding characters are added so the result length is a multiple of 4.  
  166. //  
  167. /// Returns:  
  168. ///   A new autoreleased NSString with the encoded payload.  nil for any error.  
  169. //  
  170. +(NSString *)stringByWebSafeEncodingBytes:(const void *)bytes  
  171.                                    length:(NSUInteger)length  
  172.                                    padded:(BOOL)padded;  
  173.   
  174. // webSafeDecodeString:  
  175. //  
  176. /// WebSafe Base64 decodes contents of the NSString.  
  177. //  
  178. /// Returns:  
  179. ///   A new autoreleased NSData with the decoded payload.  nil for any error.  
  180. //  
  181. +(NSData *)webSafeDecodeString:(NSString *)string;  
  182.   
  183. @end  



Base64.m

  1. //  
  2. //  GTMBase64.m  
  3. //  
  4. //  Copyright 2006-2008 Google Inc.  
  5. //  
  6. //  Licensed under the Apache License, Version 2.0 (the "License"); you may not  
  7. //  use this file except in compliance with the License.  You may obtain a copy  
  8. //  of the License at  
  9. //  
  10. //  http://www.apache.org/licenses/LICENSE-2.0  
  11. //  
  12. //  Unless required by applicable law or agreed to in writing, software  
  13. //  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  
  14. //  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the  
  15. //  License for the specific language governing permissions and limitations under  
  16. //  the License.  
  17. //  
  18.   
  19. #import "GTMBase64.h"  
  20. #import "GTMDefines.h"  
  21.   
  22. static const char *kBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  23. static const char *kWebSafeBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";  
  24. static const char kBase64PaddingChar = '=';  
  25. static const char kBase64InvalidChar = 99;  
  26.   
  27. static const char kBase64DecodeChars[] = {  
  28.     // This array was generated by the following code:  
  29.     // #include <sys/time.h>  
  30.     // #include <stdlib.h>  
  31.     // #include <string.h>  
  32.     // main()  
  33.     // {  
  34.     //   static const char Base64[] =  
  35.     //     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
  36.     //   char *pos;  
  37.     //   int idx, i, j;  
  38.     //   printf("    ");  
  39.     //   for (i = 0; i < 255; i += 8) {  
  40.     //     for (j = i; j < i + 8; j++) {  
  41.     //       pos = strchr(Base64, j);  
  42.     //       if ((pos == NULL) || (j == 0))  
  43.     //         idx = 99;  
  44.     //       else  
  45.     //         idx = pos - Base64;  
  46.     //       if (idx == 99)  
  47.     //         printf(" %2d,     ", idx);  
  48.     //       else  
  49.     //         printf(" %2d/*%c*/,", idx, j);  
  50.     //     }  
  51.     //     printf("\n    ");  
  52.     //   }  
  53.     // }  
  54.     99,      99,      99,      99,      99,      99,      99,      99,  
  55.     99,      99,      99,      99,      99,      99,      99,      99,  
  56.     99,      99,      99,      99,      99,      99,      99,      99,  
  57.     99,      99,      99,      99,      99,      99,      99,      99,  
  58.     99,      99,      99,      99,      99,      99,      99,      99,  
  59.     99,      99,      99,      62/*+*/, 99,      99,      99,      63/*/ */,  
  60.     52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,  
  61.     60/*8*/, 61/*9*/, 99,      99,      99,      99,      99,      99,  
  62.     99,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,  
  63.     7/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,  
  64.     15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,  
  65.     23/*X*/, 24/*Y*/, 25/*Z*/, 99,      99,      99,      99,      99,  
  66.     99,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,  
  67.     33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,  
  68.     41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,  
  69.     49/*x*/, 50/*y*/, 51/*z*/, 99,      99,      99,      99,      99,  
  70.     99,      99,      99,      99,      99,      99,      99,      99,  
  71.     99,      99,      99,      99,      99,      99,      99,      99,  
  72.     99,      99,      99,      99,      99,      99,      99,      99,  
  73.     99,      99,      99,      99,      99,      99,      99,      99,  
  74.     99,      99,      99,      99,      99,      99,      99,      99,  
  75.     99,      99,      99,      99,      99,      99,      99,      99,  
  76.     99,      99,      99,      99,      99,      99,      99,      99,  
  77.     99,      99,      99,      99,      99,      99,      99,      99,  
  78.     99,      99,      99,      99,      99,      99,      99,      99,  
  79.     99,      99,      99,      99,      99,      99,      99,      99,  
  80.     99,      99,      99,      99,      99,      99,      99,      99,  
  81.     99,      99,      99,      99,      99,      99,      99,      99,  
  82.     99,      99,      99,      99,      99,      99,      99,      99,  
  83.     99,      99,      99,      99,      99,      99,      99,      99,  
  84.     99,      99,      99,      99,      99,      99,      99,      99,  
  85.     99,      99,      99,      99,      99,      99,      99,      99  
  86. };  
  87.   
  88. static const char kWebSafeBase64DecodeChars[] = {  
  89.     // This array was generated by the following code:  
  90.     // #include <sys/time.h>  
  91.     // #include <stdlib.h>  
  92.     // #include <string.h>  
  93.     // main()  
  94.     // {  
  95.     //   static const char Base64[] =  
  96.     //     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";  
  97.     //   char *pos;  
  98.     //   int idx, i, j;  
  99.     //   printf("    ");  
  100.     //   for (i = 0; i < 255; i += 8) {  
  101.     //     for (j = i; j < i + 8; j++) {  
  102.     //       pos = strchr(Base64, j);  
  103.     //       if ((pos == NULL) || (j == 0))  
  104.     //         idx = 99;  
  105.     //       else  
  106.     //         idx = pos - Base64;  
  107.     //       if (idx == 99)  
  108.     //         printf(" %2d,     ", idx);  
  109.     //       else  
  110.     //         printf(" %2d/*%c*/,", idx, j);  
  111.     //     }  
  112.     //     printf("\n    ");  
  113.     //   }  
  114.     // }  
  115.     99,      99,      99,      99,      99,      99,      99,      99,  
  116.     99,      99,      99,      99,      99,      99,      99,      99,  
  117.     99,      99,      99,      99,      99,      99,      99,      99,  
  118.     99,      99,      99,      99,      99,      99,      99,      99,  
  119.     99,      99,      99,      99,      99,      99,      99,      99,  
  120.     99,      99,      99,      99,      99,      62/*-*/, 99,      99,  
  121.     52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,  
  122.     60/*8*/, 61/*9*/, 99,      99,      99,      99,      99,      99,  
  123.     99,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,  
  124.     7/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,  
  125.     15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,  
  126.     23/*X*/, 24/*Y*/, 25/*Z*/, 99,      99,      99,      99,      63/*_*/,  
  127.     99,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,  
  128.     33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,  
  129.     41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,  
  130.     49/*x*/, 50/*y*/, 51/*z*/, 99,      99,      99,      99,      99,  
  131.     99,      99,      99,      99,      99,      99,      99,      99,  
  132.     99,      99,      99,      99,      99,      99,      99,      99,  
  133.     99,      99,      99,      99,      99,      99,      99,      99,  
  134.     99,      99,      99,      99,      99,      99,      99,      99,  
  135.     99,      99,      99,      99,      99,      99,      99,      99,  
  136.     99,      99,      99,      99,      99,      99,      99,      99,  
  137.     99,      99,      99,      99,      99,      99,      99,      99,  
  138.     99,      99,      99,      99,      99,      99,      99,      99,  
  139.     99,      99,      99,      99,      99,      99,      99,      99,  
  140.     99,      99,      99,      99,      99,      99,      99,      99,  
  141.     99,      99,      99,      99,      99,      99,      99,      99,  
  142.     99,      99,      99,      99,      99,      99,      99,      99,  
  143.     99,      99,      99,      99,      99,      99,      99,      99,  
  144.     99,      99,      99,      99,      99,      99,      99,      99,  
  145.     99,      99,      99,      99,      99,      99,      99,      99,  
  146.     99,      99,      99,      99,      99,      99,      99,      99  
  147. };  
  148.   
  149.   
  150. // Tests a charact to see if it's a whitespace character.  
  151. //  
  152. // Returns:  
  153. //   YES if the character is a whitespace character.  
  154. //   NO if the character is not a whitespace character.  
  155. //  
  156. FOUNDATION_STATIC_INLINE BOOL IsSpace(unsigned char c) {  
  157.     // we use our own mapping here because we don't want anything w/ locale  
  158.     // support.  
  159.     static BOOL kSpaces[256] = {  
  160.         0, 0, 0, 0, 0, 0, 0, 0, 0, 1,  // 0-9  
  161.         1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  // 10-19  
  162.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 20-29  
  163.         0, 0, 1, 0, 0, 0, 0, 0, 0, 0,  // 30-39  
  164.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 40-49  
  165.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 50-59  
  166.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 60-69  
  167.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 70-79  
  168.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 80-89  
  169.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 90-99  
  170.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 100-109  
  171.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 110-119  
  172.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 120-129  
  173.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 130-139  
  174.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 140-149  
  175.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 150-159  
  176.         1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 160-169  
  177.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 170-179  
  178.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 180-189  
  179.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 190-199  
  180.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 200-209  
  181.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 210-219  
  182.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 220-229  
  183.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 230-239  
  184.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 240-249  
  185.         0, 0, 0, 0, 0, 1,              // 250-255  
  186.     };  
  187.     return kSpaces[c];  
  188. }  
  189.   
  190. // Calculate how long the data will be once it's base64 encoded.  
  191. //  
  192. // Returns:  
  193. //   The guessed encoded length for a source length  
  194. //  
  195. FOUNDATION_STATIC_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen,  
  196.                                                       BOOL padded) {  
  197.     NSUInteger intermediate_result = 8 * srcLen + 5;  
  198.     NSUInteger len = intermediate_result / 6;  
  199.     if (padded) {  
  200.         len = ((len + 3) / 4) * 4;  
  201.     }  
  202.     return len;  
  203. }  
  204.   
  205. // Tries to calculate how long the data will be once it's base64 decoded.  
  206. // Unlinke the above, this is always an upperbound, since the source data  
  207. // could have spaces and might end with the padding characters on them.  
  208. //  
  209. // Returns:  
  210. //   The guessed decoded length for a source length  
  211. //  
  212. FOUNDATION_STATIC_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) {  
  213.     return (srcLen + 3) / 4 * 3;  
  214. }  
  215.   
  216.   
  217. @interface GTMBase64 (PrivateMethods)  
  218.   
  219. +(NSData *)baseEncode:(const void *)bytes  
  220.                length:(NSUInteger)length  
  221.               charset:(const char *)charset  
  222.                padded:(BOOL)padded;  
  223.   
  224. +(NSData *)baseDecode:(const void *)bytes  
  225.                length:(NSUInteger)length  
  226.               charset:(const char*)charset  
  227.        requirePadding:(BOOL)requirePadding;  
  228.   
  229. +(NSUInteger)baseEncode:(const char *)srcBytes  
  230.                  srcLen:(NSUInteger)srcLen  
  231.               destBytes:(char *)destBytes  
  232.                 destLen:(NSUInteger)destLen  
  233.                 charset:(const char *)charset  
  234.                  padded:(BOOL)padded;  
  235.   
  236. +(NSUInteger)baseDecode:(const char *)srcBytes  
  237.                  srcLen:(NSUInteger)srcLen  
  238.               destBytes:(char *)destBytes  
  239.                 destLen:(NSUInteger)destLen  
  240.                 charset:(const char *)charset  
  241.          requirePadding:(BOOL)requirePadding;  
  242.   
  243. @end  
  244.   
  245.   
  246. @implementation GTMBase64  
  247.   
  248. //  
  249. // Standard Base64 (RFC) handling  
  250. //  
  251.   
  252. +(NSData *)encodeData:(NSData *)data {  
  253.     return [self baseEncode:[data bytes]  
  254.                      length:[data length]  
  255.                     charset:kBase64EncodeChars  
  256.                      padded:YES];  
  257. }  
  258.   
  259. +(NSData *)decodeData:(NSData *)data {  
  260.     return [self baseDecode:[data bytes]  
  261.                      length:[data length]  
  262.                     charset:kBase64DecodeChars  
  263.              requirePadding:YES];  
  264. }  
  265.   
  266. +(NSData *)encodeBytes:(const void *)bytes length:(NSUInteger)length {  
  267.     return [self baseEncode:bytes  
  268.                      length:length  
  269.                     charset:kBase64EncodeChars  
  270.                      padded:YES];  
  271. }  
  272.   
  273. +(NSData *)decodeBytes:(const void *)bytes length:(NSUInteger)length {  
  274.     return [self baseDecode:bytes  
  275.                      length:length  
  276.                     charset:kBase64DecodeChars  
  277.              requirePadding:YES];  
  278. }  
  279.   
  280. +(NSString *)stringByEncodingData:(NSData *)data {  
  281.     NSString *result = nil;  
  282.     NSData *converted = [self baseEncode:[data bytes]  
  283.                                   length:[data length]  
  284.                                  charset:kBase64EncodeChars  
  285.                                   padded:YES];  
  286.     if (converted) {  
  287.         result = [[[NSString alloc] initWithData:converted  
  288.                                         encoding:NSASCIIStringEncoding] autorelease];  
  289.     }  
  290.     return result;  
  291. }  
  292.   
  293. +(NSString *)stringByEncodingBytes:(const void *)bytes length:(NSUInteger)length {  
  294.     NSString *result = nil;  
  295.     NSData *converted = [self baseEncode:bytes  
  296.                                   length:length  
  297.                                  charset:kBase64EncodeChars  
  298.                                   padded:YES];  
  299.     if (converted) {  
  300.         result = [[[NSString alloc] initWithData:converted  
  301.                                         encoding:NSASCIIStringEncoding] autorelease];  
  302.     }  
  303.     return result;  
  304. }  
  305.   
  306. +(NSData *)decodeString:(NSString *)string {  
  307.     NSData *result = nil;  
  308.     NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding];  
  309.     if (data) {  
  310.         result = [self baseDecode:[data bytes]  
  311.                            length:[data length]  
  312.                           charset:kBase64DecodeChars  
  313.                    requirePadding:YES];  
  314.     }  
  315.     return result;  
  316. }  
  317.   
  318. //  
  319. // Modified Base64 encoding so the results can go onto urls.  
  320. //  
  321. // The changes are in the characters generated and also the result isn't  
  322. // padded to a multiple of 4.  
  323. // Must use the matching call to encode/decode, won't interop with the  
  324. // RFC versions.  
  325. //  
  326.   
  327. +(NSData *)webSafeEncodeData:(NSData *)data  
  328.                       padded:(BOOL)padded {  
  329.     return [self baseEncode:[data bytes]  
  330.                      length:[data length]  
  331.                     charset:kWebSafeBase64EncodeChars  
  332.                      padded:padded];  
  333. }  
  334.   
  335. +(NSData *)webSafeDecodeData:(NSData *)data {  
  336.     return [self baseDecode:[data bytes]  
  337.                      length:[data length]  
  338.                     charset:kWebSafeBase64DecodeChars  
  339.              requirePadding:NO];  
  340. }  
  341.   
  342. +(NSData *)webSafeEncodeBytes:(const void *)bytes  
  343.                        length:(NSUInteger)length  
  344.                        padded:(BOOL)padded {  
  345.     return [self baseEncode:bytes  
  346.                      length:length  
  347.                     charset:kWebSafeBase64EncodeChars  
  348.                      padded:padded];  
  349. }  
  350.   
  351. +(NSData *)webSafeDecodeBytes:(const void *)bytes length:(NSUInteger)length {  
  352.     return [self baseDecode:bytes  
  353.                      length:length  
  354.                     charset:kWebSafeBase64DecodeChars  
  355.              requirePadding:NO];  
  356. }  
  357.   
  358. +(NSString *)stringByWebSafeEncodingData:(NSData *)data  
  359.                                   padded:(BOOL)padded {  
  360.     NSString *result = nil;  
  361.     NSData *converted = [self baseEncode:[data bytes]  
  362.                                   length:[data length]  
  363.                                  charset:kWebSafeBase64EncodeChars  
  364.                                   padded:padded];  
  365.     if (converted) {  
  366.         result = [[[NSString alloc] initWithData:converted  
  367.                                         encoding:NSASCIIStringEncoding] autorelease];  
  368.     }  
  369.     return result;  
  370. }  
  371.   
  372. +(NSString *)stringByWebSafeEncodingBytes:(const void *)bytes  
  373.                                    length:(NSUInteger)length  
  374.                                    padded:(BOOL)padded {  
  375.     NSString *result = nil;  
  376.     NSData *converted = [self baseEncode:bytes  
  377.                                   length:length  
  378.                                  charset:kWebSafeBase64EncodeChars  
  379.                                   padded:padded];  
  380.     if (converted) {  
  381.         result = [[[NSString alloc] initWithData:converted  
  382.                                         encoding:NSASCIIStringEncoding] autorelease];  
  383.     }  
  384.     return result;  
  385. }  
  386.   
  387. +(NSData *)webSafeDecodeString:(NSString *)string {  
  388.     NSData *result = nil;  
  389.     NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding];  
  390.     if (data) {  
  391.         result = [self baseDecode:[data bytes]  
  392.                            length:[data length]  
  393.                           charset:kWebSafeBase64DecodeChars  
  394.                    requirePadding:NO];  
  395.     }  
  396.     return result;  
  397. }  
  398.   
  399. @end  
  400.   
  401. @implementation GTMBase64 (PrivateMethods)  
  402.   
  403. //  
  404. // baseEncode:length:charset:padded:  
  405. //  
  406. // Does the common lifting of creating the dest NSData.  it creates & sizes the  
  407. // data for the results.  |charset| is the characters to use for the encoding  
  408. // of the data.  |padding| controls if the encoded data should be padded to a  
  409. // multiple of 4.  
  410. //  
  411. // Returns:  
  412. //   an autorelease NSData with the encoded data, nil if any error.  
  413. //  
  414. +(NSData *)baseEncode:(const void *)bytes  
  415.                length:(NSUInteger)length  
  416.               charset:(const char *)charset  
  417.                padded:(BOOL)padded {  
  418.     // how big could it be?  
  419.     NSUInteger maxLength = CalcEncodedLength(length, padded);  
  420.     // make space  
  421.     NSMutableData *result = [NSMutableData data];  
  422.     [result setLength:maxLength];  
  423.     // do it  
  424.     NSUInteger finalLength = [self baseEncode:bytes  
  425.                                        srcLen:length  
  426.                                     destBytes:[result mutableBytes]  
  427.                                       destLen:[result length]  
  428.                                       charset:charset  
  429.                                        padded:padded];  
  430.     if (finalLength) {  
  431.         _GTMDevAssert(finalLength == maxLength, @"how did we calc the length wrong?");  
  432.     } else {  
  433.         // shouldn't happen, this means we ran out of space  
  434.         result = nil;  
  435.     }  
  436.     return result;  
  437. }  
  438.   
  439. //  
  440. // baseDecode:length:charset:requirePadding:  
  441. //  
  442. // Does the common lifting of creating the dest NSData.  it creates & sizes the  
  443. // data for the results.  |charset| is the characters to use for the decoding  
  444. // of the data.  
  445. //  
  446. // Returns:  
  447. //   an autorelease NSData with the decoded data, nil if any error.  
  448. //  
  449. //  
  450. +(NSData *)baseDecode:(const void *)bytes  
  451.                length:(NSUInteger)length  
  452.               charset:(const char *)charset  
  453.        requirePadding:(BOOL)requirePadding {  
  454.     // could try to calculate what it will end up as  
  455.     NSUInteger maxLength = GuessDecodedLength(length);  
  456.     // make space  
  457.     NSMutableData *result = [NSMutableData data];  
  458.     [result setLength:maxLength];  
  459.     // do it  
  460.     NSUInteger finalLength = [self baseDecode:bytes  
  461.                                        srcLen:length  
  462.                                     destBytes:[result mutableBytes]  
  463.                                       destLen:[result length]  
  464.                                       charset:charset  
  465.                                requirePadding:requirePadding];  
  466.     if (finalLength) {  
  467.         if (finalLength != maxLength) {  
  468.             // resize down to how big it was  
  469.             [result setLength:finalLength];  
  470.         }  
  471.     } else {  
  472.         // either an error in the args, or we ran out of space  
  473.         result = nil;  
  474.     }  
  475.     return result;  
  476. }  
  477.   
  478. //  
  479. // baseEncode:srcLen:destBytes:destLen:charset:padded:  
  480. //  
  481. // Encodes the buffer into the larger.  returns the length of the encoded  
  482. // data, or zero for an error.  
  483. // |charset| is the characters to use for the encoding  
  484. // |padded| tells if the result should be padded to a multiple of 4.  
  485. //  
  486. // Returns:  
  487. //   the length of the encoded data.  zero if any error.  
  488. //  
  489. +(NSUInteger)baseEncode:(const char *)srcBytes  
  490.                  srcLen:(NSUInteger)srcLen  
  491.               destBytes:(char *)destBytes  
  492.                 destLen:(NSUInteger)destLen  
  493.                 charset:(const char *)charset  
  494.                  padded:(BOOL)padded {  
  495.     if (!srcLen || !destLen || !srcBytes || !destBytes) {  
  496.         return 0;  
  497.     }  
  498.       
  499.     char *curDest = destBytes;  
  500.     const unsigned char *curSrc = (const unsigned char *)(srcBytes);  
  501.       
  502.     // Three bytes of data encodes to four characters of cyphertext.  
  503.     // So we can pump through three-byte chunks atomically.  
  504.     while (srcLen > 2) {  
  505.         // space?  
  506.         _GTMDevAssert(destLen >= 4, @"our calc for encoded length was wrong");  
  507.         curDest[0] = charset[curSrc[0] >> 2];  
  508.         curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)];  
  509.         curDest[2] = charset[((curSrc[1] & 0x0f) << 2) + (curSrc[2] >> 6)];  
  510.         curDest[3] = charset[curSrc[2] & 0x3f];  
  511.           
  512.         curDest += 4;  
  513.         curSrc += 3;  
  514.         srcLen -= 3;  
  515.         destLen -= 4;  
  516.     }  
  517.       
  518.     // now deal with the tail (<=2 bytes)  
  519.     switch (srcLen) {  
  520.         case 0:  
  521.             // Nothing left; nothing more to do.  
  522.             break;  
  523.         case 1:  
  524.             // One byte left: this encodes to two characters, and (optionally)  
  525.             // two pad characters to round out the four-character cypherblock.  
  526.             _GTMDevAssert(destLen >= 2, @"our calc for encoded length was wrong");  
  527.             curDest[0] = charset[curSrc[0] >> 2];  
  528.             curDest[1] = charset[(curSrc[0] & 0x03) << 4];  
  529.             curDest += 2;  
  530.             destLen -= 2;  
  531.             if (padded) {  
  532.                 _GTMDevAssert(destLen >= 2, @"our calc for encoded length was wrong");  
  533.                 curDest[0] = kBase64PaddingChar;  
  534.                 curDest[1] = kBase64PaddingChar;  
  535.                 curDest += 2;  
  536.                 destLen -= 2;  
  537.             }  
  538.             break;  
  539.         case 2:  
  540.             // Two bytes left: this encodes to three characters, and (optionally)  
  541.             // one pad character to round out the four-character cypherblock.  
  542.             _GTMDevAssert(destLen >= 3, @"our calc for encoded length was wrong");  
  543.             curDest[0] = charset[curSrc[0] >> 2];  
  544.             curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)];  
  545.             curDest[2] = charset[(curSrc[1] & 0x0f) << 2];  
  546.             curDest += 3;  
  547.             destLen -= 3;  
  548.             if (padded) {  
  549.                 _GTMDevAssert(destLen >= 1, @"our calc for encoded length was wrong");  
  550.                 curDest[0] = kBase64PaddingChar;  
  551.                 curDest += 1;  
  552.                 destLen -= 1;  
  553.             }  
  554.             break;  
  555.     }  
  556.     // return the length  
  557.     return (curDest - destBytes);  
  558. }  
  559.   
  560. //  
  561. // baseDecode:srcLen:destBytes:destLen:charset:requirePadding:  
  562. //  
  563. // Decodes the buffer into the larger.  returns the length of the decoded  
  564. // data, or zero for an error.  
  565. // |charset| is the character decoding buffer to use  
  566. //  
  567. // Returns:  
  568. //   the length of the encoded data.  zero if any error.  
  569. //  
  570. +(NSUInteger)baseDecode:(const char *)srcBytes  
  571.                  srcLen:(NSUInteger)srcLen  
  572.               destBytes:(char *)destBytes  
  573.                 destLen:(NSUInteger)destLen  
  574.                 charset:(const char *)charset  
  575.          requirePadding:(BOOL)requirePadding {  
  576.     if (!srcLen || !destLen || !srcBytes || !destBytes) {  
  577.         return 0;  
  578.     }  
  579.       
  580.     int decode;  
  581.     NSUInteger destIndex = 0;  
  582.     int state = 0;  
  583.     char ch = 0;  
  584.     while (srcLen-- && (ch = *srcBytes++) != 0)  {  
  585.         if (IsSpace(ch))  // Skip whitespace  
  586.             continue;  
  587.           
  588.         if (ch == kBase64PaddingChar)  
  589.             break;  
  590.           
  591.         decode = charset[(unsigned int)ch];  
  592.         if (decode == kBase64InvalidChar)  
  593.             return 0;  
  594.           
  595.         // Four cyphertext characters decode to three bytes.  
  596.         // Therefore we can be in one of four states.  
  597.         switch (state) {  
  598.             case 0:  
  599.                 // We're at the beginning of a four-character cyphertext block.  
  600.                 // This sets the high six bits of the first byte of the  
  601.                 // plaintext block.  
  602.                 _GTMDevAssert(destIndex < destLen, @"our calc for decoded length was wrong");  
  603.                 destBytes[destIndex] = decode << 2;  
  604.                 state = 1;  
  605.                 break;  
  606.             case 1:  
  607.                 // We're one character into a four-character cyphertext block.  
  608.                 // This sets the low two bits of the first plaintext byte,  
  609.                 // and the high four bits of the second plaintext byte.  
  610.                 _GTMDevAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong");  
  611.                 destBytes[destIndex] |= decode >> 4;  
  612.                 destBytes[destIndex+1] = (decode & 0x0f) << 4;  
  613.                 destIndex++;  
  614.                 state = 2;  
  615.                 break;  
  616.             case 2:  
  617.                 // We're two characters into a four-character cyphertext block.  
  618.                 // This sets the low four bits of the second plaintext  
  619.                 // byte, and the high two bits of the third plaintext byte.  
  620.                 // However, if this is the end of data, and those two  
  621.                 // bits are zero, it could be that those two bits are  
  622.                 // leftovers from the encoding of data that had a length  
  623.                 // of two mod three.  
  624.                 _GTMDevAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong");  
  625.                 destBytes[destIndex] |= decode >> 2;  
  626.                 destBytes[destIndex+1] = (decode & 0x03) << 6;  
  627.                 destIndex++;  
  628.                 state = 3;  
  629.                 break;  
  630.             case 3:  
  631.                 // We're at the last character of a four-character cyphertext block.  
  632.                 // This sets the low six bits of the third plaintext byte.  
  633.                 _GTMDevAssert(destIndex < destLen, @"our calc for decoded length was wrong");  
  634.                 destBytes[destIndex] |= decode;  
  635.                 destIndex++;  
  636.                 state = 0;  
  637.                 break;  
  638.         }  
  639.     }  
  640.       
  641.     // We are done decoding Base-64 chars.  Let's see if we ended  
  642.     //      on a byte boundary, and/or with erroneous trailing characters.  
  643.     if (ch == kBase64PaddingChar) {               // We got a pad char  
  644.         if ((state == 0) || (state == 1)) {  
  645.             return 0;  // Invalid '=' in first or second position  
  646.         }  
  647.         if (srcLen == 0) {  
  648.             if (state == 2) { // We run out of input but we still need another '='  
  649.                 return 0;  
  650.             }  
  651.             // Otherwise, we are in state 3 and only need this '='  
  652.         } else {  
  653.             if (state == 2) {  // need another '='  
  654.                 while ((ch = *srcBytes++) && (srcLen-- > 0)) {  
  655.                     if (!IsSpace(ch))  
  656.                         break;  
  657.                 }  
  658.                 if (ch != kBase64PaddingChar) {  
  659.                     return 0;  
  660.                 }  
  661.             }  
  662.             // state = 1 or 2, check if all remain padding is space  
  663.             while ((ch = *srcBytes++) && (srcLen-- > 0)) {  
  664.                 if (!IsSpace(ch)) {  
  665.                     return 0;  
  666.                 }  
  667.             }  
  668.         }  
  669.     } else {  
  670.         // We ended by seeing the end of the string.  
  671.           
  672.         if (requirePadding) {  
  673.             // If we require padding, then anything but state 0 is an error.  
  674.             if (state != 0) {  
  675.                 return 0;  
  676.             }  
  677.         } else {  
  678.             // Make sure we have no partial bytes lying around.  Note that we do not  
  679.             // require trailing '=', so states 2 and 3 are okay too.  
  680.             if (state == 1) {  
  681.                 return 0;  
  682.             }  
  683.         }  
  684.     }  
  685.       
  686.     // If then next piece of output was valid and got written to it means we got a  
  687.     // very carefully crafted input that appeared valid but contains some trailing  
  688.     // bits past the real length, so just toss the thing.  
  689.     if ((destIndex < destLen) &&  
  690.         (destBytes[destIndex] != 0)) {  
  691.         return 0;  
  692.     }  
  693.       
  694.     return destIndex;  
  695. }  
  696.   
  697. @end  

抱歉!评论已关闭.