📄 base64.c
字号:
/*******************************************
* Base64编码、解码
* 编码中可以指明每个若干个字符插入一个换行符
* 解码时可以忽略其中的回车、换行符
* Author: lubing
* Date: Oct. 26, 2000
*******************************************/
#include <stdio.h>
#include <string.h>
#define __A 0
#define __a 26
#define __0 52
#define __plus 62
#define __slash 63
#define __stuff -2
#define __error -1
#define STUFF_CHAR '='
#ifdef WIN32
#define CRLF "\r\n"
#define CRLF_LEN 2
#else
#define CRLF "\n"
#define CRLF_LEN 1
#endif
static char* BASES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int EncodeWithoutWrapping(const char* src, const int srclen, char* dest)
{
int i;
int limit = srclen - 2;
int len = 0;
//encode the src 3 chars as a group
for (i=0; i<limit; i += 3) {
dest[len++] = BASES[(src[i] >> 2) & 0x3f];
dest[len++] = BASES[((src[i] << 4) & 0x30) | ((src[i+1] >> 4) & 0x0f)];
dest[len++] = BASES[((src[i+1] << 2) & 0x3c) | ((src[i+2] >> 6) & 0x03)];
dest[len++] = BASES[src[i+2] & 0x3f];
}
if (i < srclen) {
dest[len++] = BASES[(src[i] >> 2) & 0x3f];
if (i == srclen - 1) {
dest[len++] = BASES[((src[i] << 4) & 0x30)];
dest[len++] = STUFF_CHAR;
} else {
dest[len++] = BASES[((src[i] << 4) & 0x30) | ((src[i+1] >> 4) & 0x0f)];
dest[len++] = BASES[((src[i+1] << 2) & 0x3c)];
}
dest[len++] = STUFF_CHAR;
}
dest[len] = '\0';
return len;
}
static int EncodeWithWrapping(const char* src, const int srclen, char* dest, const int wraplen)
{
int i;
int limit = srclen - 2;
int len = 0;
int total = 0;
//encode the src 3 chars as a group
for (i=0; i<limit; i += 3) {
dest[len++] = BASES[(src[i] >> 2) & 0x3f];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
dest[len++] = BASES[((src[i] << 4) & 0x30) | ((src[i+1] >> 4) & 0x0f)];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
dest[len++] = BASES[((src[i+1] << 2) & 0x3c) | ((src[i+2] >> 6) & 0x03)];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
dest[len++] = BASES[src[i+2] & 0x3f];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
}
if (i < srclen) {
dest[len++] = BASES[(src[i] >> 2) & 0x3f];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
if (i == srclen - 1) {
dest[len++] = BASES[(src[i] << 4) & 0x30];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
dest[len++] = STUFF_CHAR;
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
} else {
dest[len++] = BASES[((src[i] << 4) & 0x30) | ((src[i+1] >> 4) & 0x0f)];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
dest[len++] = BASES[((src[i+1] << 2) & 0x3c)];
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
}
dest[len++] = STUFF_CHAR;
total++;
if (total % wraplen == 0) {
memcpy(dest+len, CRLF, CRLF_LEN);
len += CRLF_LEN;
}
}
dest[len] = '\0';
return len;
}
int Base64Encode(const char* src, const int srclen, char* dest, const int destlen, const int wraplen)
{
int len;
if (src == NULL || dest == NULL) {
return 0;
}
len = (srclen + 2) * 4 / 3 + 1;
if (wraplen <= 0)
{
if (len > destlen) {
return 0;
}
return EncodeWithoutWrapping(src, srclen, dest);
} else {
#ifndef WIN32
if (len + len / wraplen > destlen) {
#else
if (len + (len / wraplen)*2 > destlen) {
#endif
return 0;
}
return EncodeWithWrapping(src, srclen, dest, wraplen);
}
}
static int GetIndex(char ch)
{
if (ch >= 'A' && ch <= 'Z') {
return (ch - 'A' + __A);
}
if (ch >= 'a' && ch <= 'z') {
return (ch - 'a' + __a);
}
if (ch >= '0' && ch <= '9') {
return (ch - '0' + __0);
}
switch(ch){
case '+':
return __plus;
case '/':
case '-':
case '%':
return __slash;
case STUFF_CHAR:
return __stuff;
default:
return __error;
}
}
int Base64Decode(const char* src, char* dest, const int destlen)
{
int len;
int base, index;
int done = 0;
if (src == NULL || dest == NULL) {
return 0;
}
len = strlen(src);
if ((len * 3 / 4) > destlen) {
return 0;
}
len = 0;
while (!done && (*src != '\0')) {
//skip LF & CR
if (*src == '\n' || *src == '\r') {
src++;
continue;
}
base = 0;
//join 4 character to 24-bit
//1st character
switch (index = GetIndex(*src++)) {
case __error:
return 0;
case __stuff:
//'=' as the end
done = 1;
break;
default:
base |= (index << 18);
break;
}
if (done) {
//break the loop
break;
}
//2nd character
while (*src != '\0' && (*src == '\n' || *src == '\r')) {
src++;
}
if (*src != '\0') {
switch(index = GetIndex(*src++)){
case __error:
return 0;
case __stuff:
//impossible
return 0;
default:
base |= (index << 12);
break;
}
//3rd character
while (*src != '\0' && (*src == '\n' || *src == '\r')) {
src++;
}
if (*src != '\0') {
switch (index = GetIndex(*src++)) {
case __error:
return 0;
case __stuff:
index = 0;
done = 1;
default:
base |= (index << 6);
break;
}
//4th character
if (!done) {
while (*src != '\0' && (*src == '\n' || *src == '\r')) {
src++;
}
if (*src != '\0') {
switch (index = GetIndex(*src ++)) {
case __error:
return 0;
case __stuff:
index = 0;
done = 2;
default:
base |= index;
}
} else {
done = 2;
}
}
} else {
done = 1;
}
} else {
//impossible, there must be at least 2 characters
return 0;
}
//decode it
dest[len++] = (char)(base >> 16);
if (done != 1) {
dest[len++] = (char)(base >> 8);
if (done != 2) {
dest[len ++] = (char)base;
}
}
}
if (len < destlen) {
dest[len] = 0;
}
return len;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -