2017-06-26 58 views
1

我是用Google搜索這兩個我需要的C函數,而且我遇到的最乾淨的是http://fm4dd.com/programming/base64/base64_stringencode_c.htm但是它在我看來就像它的下面一小部分...endian-independent base64_encode/decode function

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)); 
} 

...將會依賴於endian依賴(同上相應的encodeblack(),你可以在上面的url中看到)。但它不同於其他的一些:不同於其他一些:一個擁有三個自己的頭文件,另一個稱爲自己特殊的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[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 

/* 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

但是,排序*很重要。在做其他事情之前,你可以在編碼中加入htonl/s,在解碼中加入ntohl/s。然後你知道你總是有相同的字節順序。 –

+0

你能否詳細說明你的懷孕依賴懷疑?也許舉一個例子,你在兩個endianesses計算得到錯誤/不同的結果? – Yunnosch

+0

@Yunnosch我沒有得到不同的結果 - 請參閱上面的編輯(但等待一分鐘,直到我把它放在那裏) –

回答

2

不,這不是尾數依賴。 Base64本身是4字節到3字節的編碼,並不關心內存中的實際表示。但是,如果您希望傳輸小/大端數據,則必須在編碼之前和解碼之後對字節序列進行標準化。

該片段只是獨立地處理所有字節。如果它在uint32_t左右加載了4個字節,並且使用一些位旋轉產生的輸出將按照原樣複製到結果緩衝區中,那麼這將是endian相關的。


但是,這種代碼是危險的,其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; 
} 

這將與嵌入式NULs一起工作。

+0

OPs問題的最後一行是什麼:'out [3] ='\ 0';'? –

+2

@AndreKampling它不需要任何東西。這是一個不適當的嘗試,使緩衝區適合strncat,但限制3的strncat不會掃描緩衝區中的[out] [3]或第4個字符。 –

+0

謝謝Antti。這可能是最好的方法。但是他正在做一個strncat(),因爲無論正確還是錯誤(可能是錯誤的),他總是**將一個ptr傳遞給明確字符串的**開頭**(請參閱他的代碼的鏈接),所以your're總是替換前幾個字節,而不是添加到最後。相反,你需要首先通過strlen(* clrstr)撞擊目標ptr,最後添加另一個終止'\ 000'來保持清零字符串始終爲空。但是你是對的,整個事情有點混亂(但我看到的其他一些東西更混亂)。 (P.S. strncat限制實際上是4) –

相關問題