我正在谷歌搜索我碰巧需要的这两个C函数,而我遇到的最干净的是http://fm4dd.com/programming/base64/base64_stringencode_c.htm但它在我看来就像它的下面一小部分......
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
}
...将依赖于字节序(与您在上面的url中可以看到的相应的encodeblack()相同)。但它不是很干净,不像其他一些:一个有三个自己的头文件,另一个叫它自己的特殊malloc() - 就像函数一样。等任何人都知道一个漂亮,小巧,干净(没有标题,没有依赖关系等版本,就像这个版本一样,它更独立于架构?
编辑原因我正在寻找这个原因是base64_encode()将在一个PHP脚本中完成,该脚本是html页面的一部分,将该编码的字符串传递给已执行的远程盒子上的cgi程序。那cgi然后必须base64_decode()它。所以架构独立性只是一个额外的安全性,以防cgi在非英特尔大端盒子上运行(英特尔的小)。
根据下面的评论修改,这里是完整的代码以及我做的一些更改...
/* downloaded from...
http://fm4dd.com/programming/base64/base64_stringencode_c.htm */
/* ------------------------------------------------------------------------ *
* file: base64_stringencode.c v1.0 *
* purpose: tests encoding/decoding strings with base64 *
* author: 02/23/2009 Frank4DD *
* *
* source: http://base64.sourceforge.net/b64.c for encoding *
* http://en.literateprograms.org/Base64_(C) for decoding *
* ------------------------------------------------------------------------ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- Base64 Encoding/Decoding Table --- */
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
} /* --- end-of-function decodeblock() --- */
char *base64_decode(char *b64src /*, char *clrdst */) {
static char clrdstbuff[8192];
char *clrdst = clrdstbuff;
int c, phase, i;
unsigned char in[4];
char *p;
clrdst[0] = '\0';
phase = 0; i=0;
while(b64src[i]) {
c = (int) b64src[i];
if(c == '=') {
decodeblock(in, clrdst);
break; }
p = strchr(b64, c);
if(p) {
in[phase] = p - b64;
phase = (phase + 1) % 4;
if(phase == 0) {
decodeblock(in, clrdst);
in[0]=in[1]=in[2]=in[3]=0; }
} /* --- end-of-if(p) --- */
i++;
} /* --- end-of-while(b64src[i]) --- */
return ( clrdstbuff );
} /* --- end-of-function base64_decode() --- */
/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */
void encodeblock( unsigned char in[], char b64str[], int len ) {
unsigned char out[5];
out[0] = b64[ in[0] >> 2 ];
out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) |
((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '=');
out[4] = '\0';
strncat(b64str, out, sizeof(out));
} /* --- end-of-function encodeblock() --- */
/* encode - base64 encode a stream, adding padding if needed */
char *base64_encode(char *clrstr /*, char *b64dst */) {
static char b64dstbuff[8192];
char *b64dst = b64dstbuff;
unsigned char in[3];
int i, len = 0;
int j = 0;
b64dst[0] = '\0';
while(clrstr[j]) {
len = 0;
for(i=0; i<3; i++) {
in[i] = (unsigned char) clrstr[j];
if(clrstr[j]) {
len++; j++; }
else in[i] = 0;
} /* --- end-of-for(i) --- */
if( len ) {
encodeblock( in, b64dst, len ); }
} /* --- end-of-while(clrstr[j]) --- */
return ( b64dstbuff );
} /* --- end-of-function base64_encode() --- */
#ifdef TESTBASE64
int main( int argc, char *argv[] ) {
char *mysrc = (argc>1? argv[1] : "My bonnie is over the ocean ");
char *mysrc2 = (argc>2? argv[2] : "My bonnie is over the sea ");
char myb64[2048]="", myb642[2048]="";
char mydst[2048]="", mydst2[2048]="";
char *base64_enclode(), *base64_decode();
int testnum = 1;
if ( strncmp(mysrc,"test",4) == 0 )
testnum = atoi(mysrc+4);
if ( testnum == 1 ) {
strcpy(myb64,base64_encode(mysrc));
printf("The string [%s]\n\tencodes into base64 as: [%s]\n",mysrc,myb64);
strcpy(myb642,base64_encode(mysrc2));
printf("The string [%s]\n\tencodes into base64 as: [%s]\n",mysrc2,myb642);
printf("...\n");
strcpy(mydst,base64_decode(myb64));
printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",myb64,mydst);
strcpy(mydst2,base64_decode(myb642));
printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",myb642,mydst2);
} /* --- end-of-if(testnum==1) --- */
if ( testnum == 2 ) {
strcpy(mydst,base64_decode(mysrc2)); /* input is b64 */
printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",mysrc2,mydst);
} /* --- end-of-if(testnum==2) --- */
if ( testnum == 3 ) {
int itest, ntests = (argc>2?atoi(argv[2]):999);
int ichar, nchars = (argc>3?atoi(argv[3]):128);
unsigned int seed = (argc>4?atoi(argv[4]):987654321);
char blanks[999] = " ";
srand(seed);
for ( itest=1; itest<=ntests; itest++ ) {
for ( ichar=0; ichar<nchars; ichar++ ) mydst[ichar] = 1+(rand()%255);
mydst[nchars] = '\000';
if ( strlen(blanks) > 0 ) strcat(mydst,blanks);
strcpy(myb64,base64_encode(mydst));
strcpy(mydst2,base64_decode(myb64));
if ( strcmp(mydst,mydst2) != 0 )
printf("Test#%d:\n\t in=%s\n\tout=%s\n",itest,mydst,mydst2);
} /* --- end-of-for(itest) --- */
} /* --- end-of-if(testnum==3) --- */
return 0;
} /* --- end-of-function main() --- */
#endif
答案 0 :(得分:2)
不,它不依赖于字节序。 Base64本身是4字节到3字节的编码,并不关心内存中的实际表示。但是,如果您希望传输小/大端数据,则必须在编码之前和解码之后规范化字节序。
该片段只是独立地处理所有字节。如果它在uint32_t
左右加载了4个字节,并且使用一些比特twiddling产生了一个输出,将按原样复制到结果缓冲区中,它将依赖于字节序。
然而,该代码被其strncat
危险地破坏,并且不会使用嵌入的NUL字节。相反,你应该使用像
void decodeblock(unsigned char in[], unsigned char **clrstr) {
*((*clrstr) ++) = in[0] << 2 | in[1] >> 4;
*((*clrstr) ++) = in[1] << 4 | in[2] >> 2;
*((*clrstr) ++) = in[2] << 6 | in[3] >> 0;
}
适用于嵌入式NUL。