📄 base64.c
字号:
/*************************************************************************** * base64.c * * Mon May 21 18:04:36 2007 * Copyright 2007 kf701 * Email <kf701.ye AT gmail.com> ****************************************************************************//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <sys/types.h>#include <fcntl.h>#include "kf701.h"/** * @brief base64 encode * * Note: dest must be at least 4/3 length of src * * @param dest encoded buffer * @param src raw buffer * @param size length of src * @return the actual data length in dest */int32_t encode_b64(uint8_t* dest,const uint8_t* src,uint32_t size){ int i, tmp = 0, b64_tmp = 0; if ( dest == NULL || src == NULL ) return -1; while ((size - b64_tmp) >= 3) { // every 3 bytes of source change to 4 bytes of destination, 4*6 = 3*8 dest[tmp] = 0x3F & (src[b64_tmp]>>2); dest[tmp+1] = ((src[b64_tmp]<<4) & 0x30) | ((src[b64_tmp+1]>>4) & 0x0F); dest[tmp+2] = ((src[b64_tmp+1]<<2) & 0x3C) | ((src[b64_tmp+2]>>6) & 0x03); dest[tmp+3] = 0x3F & src[b64_tmp+2]; for (i=0; i<=3; i++) { if ( (dest[tmp+i] <= 25) ) dest[tmp+i] += 'A'; else if (dest[tmp+i] <= 51) dest[tmp+i] += 'a' - 26; else if (dest[tmp+i] <= 61) dest[tmp+i] += '0' - 52; if (dest[tmp+i] == 62) dest[tmp+i] = '+'; if (dest[tmp+i] == 63) dest[tmp+i] = '/'; } tmp += 4; b64_tmp += 3; } //end while if (b64_tmp == size) { dest[tmp] = '\0'; return tmp; } if ((size - b64_tmp) == 1) { //one dest[tmp] = 0x3F & (src[b64_tmp]>>2); dest[tmp+1] = (src[b64_tmp]<<4) & 0x30; dest[tmp+2] = '='; } else { //two dest[tmp] = 0x3F & (src[b64_tmp]>>2); dest[tmp+1] = ((src[b64_tmp]<<4) & 0x30) | ((src[b64_tmp+1]>>4) & 0x0F); dest[tmp+2] = (src[b64_tmp+1]<<2) & 0x3F; } for (i=0; i<=(size - b64_tmp); i++) { if (dest[tmp+i] <= 25) dest[tmp+i] += 'A'; else if (dest[tmp+i] <= 51) dest[tmp+i] += 'a' - 26; else if (dest[tmp+i] <= 61) dest[tmp+i] += '0' - 52; //end if if (dest[tmp+i] == 62) dest[tmp+i] = '+'; if (dest[tmp+i] == 63) dest[tmp+i] = '/'; } dest[tmp+3] = '='; dest[tmp+4] = '\0'; return tmp+4;}static const short base64_reverse_table[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};/** * @brief base64 decode * * Note: dest must be at least 3/4 length of src * * @param dest decoded buffer * @param src encoded buffer * @param size length of src * @return the actual data length in dest */int32_t decode_b64(uint8_t *dest,const uint8_t *src,uint32_t size){ const uint8_t *current = src; int ch, i = 0, j = 0, k; /* this sucks for threaded environments */ uint8_t *result; int ret_length; result = dest ; if (result == NULL) { return -1; } /* run through the whole string, converting as we go */ while ((ch = *current++) != '\0' && size-- > 0) { if (ch == '=') break; /* When Base64 gets POSTed, all pluses are interpreted as spaces. This line changes them back. It's not exactly the Base64 spec, but it is completely compatible with it (the spec says that spaces are invalid). This will also save many people considerable headache. - Turadg Aleahmad <turadg@wise.berkeley.edu> */ if (ch == ' ') ch = '+'; ch = base64_reverse_table[ch]; if (ch < 0) continue; switch(i % 4) { case 0: result[j] = ch << 2; break; case 1: result[j++] |= ch >> 4; result[j] = (ch & 0x0f) << 4; break; case 2: result[j++] |= ch >>2; result[j] = (ch & 0x03) << 6; break; case 3: result[j++] |= ch; break; } i++; } k = j; /* mop things up if we ended on a boundary */ if (ch == '=' ) { switch(i % 4) { case 1: return -1; case 2: k++; case 3: result[k++] = 0; } } ret_length = j; result[j] = '\0'; return ret_length;}/** * @brief base64 encode a file to buffer * @param b64_buf encoded buffer * @param file raw file * @return the actual data length in b64_buf */int32_t b64_file_to_buf (uint8_t *b64_buf, const char *file){ int r_size = 100*1024; int s_fd = open(file,O_RDONLY); uint8_t s_buff[100*1024]; uint8_t *ptr ; int count; if (s_fd < 0) return -1; if (NULL == s_buff) { close(s_fd); return -2; } ptr = b64_buf; do { int i; count = read(s_fd,s_buff,r_size); if (count < 0) { close(s_fd); return -3; } i = count; while (i >= 17*3) { encode_b64(ptr,&s_buff[count-i],17*4); ptr += 17*4; ptr += sprintf((char*)ptr,"\n"); i -= 17*3; } if (i > 0) { ptr += encode_b64(ptr,&s_buff[count-i],i); ptr += sprintf((char*)ptr,"\n"); } if (count < r_size) break; } while (count == r_size); close(s_fd); return (ptr-b64_buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -