Rev. | bd67de4ef8b5cc67b7321d9767f328309664302a |
---|---|
Größe | 8,353 Bytes |
Zeit | 2019-07-05 14:55:07 |
Autor | tfuruka1 |
Log Message | mktemp 系の関数が mingw と gcc で統一出来なかったので、条件コンパイルにしました。
クリップボードをサポートしました。
|
/*
* Copyright(C) 2005 T.Furukawa
* $Id$
*
* Base64関連
*
* RFC 2045 をろくに読んでいないので、結構手抜きです。しかし、同じよう
* なのを何回も作っているような気がする。
*
* Table 1: The Base64 Alphabet
* Value Encoding Value Encoding Value Encoding Value Encoding
* 0 A 17 R 34 i 51 z
* 1 B 18 S 35 j 52 0
* 2 C 19 T 36 k 53 1
* 3 D 20 U 37 l 54 2
* 4 E 21 V 38 m 55 3
* 5 F 22 W 39 n 56 4
* 6 G 23 X 40 o 57 5
* 7 H 24 Y 41 p 58 6
* 8 I 25 Z 42 q 59 7
* 9 J 26 a 43 r 60 8
* 10 K 27 b 44 s 61 9
* 11 L 28 c 45 t 62 +
* 12 M 29 d 46 u 63 /
* 13 N 30 e 47 v
* 14 O 31 f 48 w (pad) =
* 15 P 32 g 49 x
* 16 Q 33 h 50 y
*
* 単体デバッグの方法:
*
* (Win VCの場合) - 当初は確認していたが現在のコードでは未確認
* cl /W3 /Zi /DDEBUG base64.c
*
* (gccの場合)
* gcc -g -Wall -W -Wformat=2 -Wcast-qual -Wcast-align \
* -Wwrite-strings -Wconversion -Wfloat-equal -Wpointer-arith \
* -DDEBUG base64.c
*
* で単体でコンパイルできます。生成された実行ファイルを引数無しで起動
* するか、
*
* a.out <base64File> <outputFile>
*
* のように、Base64でエンコードされたファイルと、出力ファイルを指定
* します。
*/
#include "base64.h"
#define BASE64_PAD_CHAR '='
#define IS_VALID(code) ((64 > (code)) && (0 <= (code)))
static const char szBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static int
ToAlphabet(int code)
{
return IS_VALID(code) ? szBase64Alphabet[code] : - 1;
}
static int
FromAlphabet(int code)
{
int i;
for (i = 0; i < 64; i++) {
if (code == szBase64Alphabet[i]) {
return i;
}
}
return -1;
}
/*
* Base64文字列への変換を行なう。
*/
static char *
ToAlphabetGroup(
const unsigned char *lpData, // 変換元(BYTE)
int cnt, // 最大で3
char *lpszGroup // 変換先(BASE64)
)
{
int i;
int code;
unsigned long data
= *(lpData + 0) * 256UL * 256
+ *(lpData + 1) * 256UL
+ *(lpData + 2);
memset(lpszGroup, BASE64_PAD_CHAR, 4);
*(lpszGroup + 4) = '\0';
// 1Byte なら,2char + ==。2Byte なら,3char + =。3Byte なら,4char
// になるので, 偶々 cnt+1と一致する
for (i = 0; i <= (cnt % 4); i++) {
code = (data >> (6 * (3 - i))) & 0x3f;
*(lpszGroup + i) = (char)(ToAlphabet((int)code) & 0xff);
}
return lpszGroup;
}
static int // 変換後のバイト数
FromAlpabetGroup(
char *lpAlphabet, // 4文字
unsigned char *lpData // 3byte
)
{
int i;
int ret;
unsigned long code;
unsigned long data = 0;
for (i = 0; i < 4; i++) {
if (BASE64_PAD_CHAR == *(lpAlphabet + i)) {
break;
}
code = (unsigned long) FromAlphabet(*(lpAlphabet + i));
data |= (code << (2 + (6 * (4 - i))));
}
ret = i - 1;
for (i = 0; i < ret; i++) {
*(lpData + i) = (unsigned char)((data >> (8 * (3 - i))) & 0xff);
}
return ret;
}
/*
* Base64にエンコードします。エンコード結果格納域は、元データの 4/3 倍
* のエリアが必要になります(3バイトが4バイトになります)。エンコード後
* のデータ長は必ずの4の倍数になります。また、最後にnullストップを付与
* しますので、さらに一バイト余分に必要になります。
*/
char *
EncodeBase64(
unsigned char *lpData, // エンコードデータ
size_t cbData, // バイト数
char *lpszEncode // エンコード結果(文字列)
)
{
char *lpszSave = lpszEncode;
size_t i;
for (i = 0; i < cbData; i += 3, lpszEncode += 4) {
ToAlphabetGroup(lpData + i,
((cbData - i) > 3UL) ? 3 : (int) (cbData - i),
lpszEncode);
}
*lpszEncode = '\0';
return lpszSave;
}
/*
* Base64でデコードします。デコードされる元の文字列長は必ず4の倍数であ
* る必要があります。デコード後のバイト数を返却します。デコード前のエ
* リアとデコード後のエリアは同じアドレスを指定する事が可能です。
*/
long
DecodeBase64(
char *lpszData, // 必ず4の倍数である事
unsigned char *lpData // デコード結果
)
{
char szAlphabet[8];
unsigned long cbData = 0;
int i = 0;
int j;
for (; *lpszData; lpszData++) {
if ((' ' == *lpszData) || ('\t' == *lpszData)
|| ('\r' == *lpszData) || ('\n' == *lpszData)) {
continue;
}
szAlphabet[i] = *lpszData;
i++;
if (i >= 4) {
szAlphabet[4] = '\0';
j = FromAlpabetGroup(szAlphabet, lpData);
cbData += (size_t) j;
lpData += j;
i = 0;
}
}
return (long) cbData;
}
/*
* Base64でエンコードされたファイルをデコードし、ファイルに出力します。
* 入力ファイルと出力ファイルを同じにする事はできません。
*/
long
DecodeBase64File(
char *lpszBase64FileName, // 入力ファイル名
char *lpszOutFileName // 出力ファイル名
)
{
FILE *fpIn;
FILE *fpOut;
char szAlphabet[8];
unsigned char szBuf[4];
unsigned long cbData = 0;
int i = 0;
int j;
int c;
if (!(fpIn = fopen(lpszBase64FileName, "rb"))) {
return -1;
}
if (!(fpOut = fopen(lpszOutFileName, "wb"))) {
fclose(fpIn);
return -2;
}
while (EOF != (c = getc(fpIn))) {
if ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' == c)) {
continue;
}
szAlphabet[i] = (char)c;
i++;
if (i >= 4) {
szAlphabet[4] = '\0';
j = (int)DecodeBase64(szAlphabet, szBuf);
for (i = 0; i < j; i++) {
putc(szBuf[i], fpOut);
}
i = 0;
cbData += (size_t) j;
}
}
fclose(fpIn);
fclose(fpOut);
return (long) cbData;
}
//━━━━━━━━━━━━━━━━━━━━━━━以下はデバッグルーチン
#if defined(DEBUG)
#include <stdio.h>
int
main(int argc, char *argv[])
{
char data[] = "0123456789ABCDEF";
char *lpData = data;
unsigned char szGroup[128];
int i;
int cbData;
for (i = 1; i < 4; i++) {
printf("%d: %s\n", i,
ToAlphabetGroup((const unsigned char *) lpData, i,
(char *) szGroup));
i = FromAlpabetGroup((char *) szGroup, szGroup);
szGroup[i] = '\0';
printf("%d: %s\n", i, szGroup);
}
for (i = 1; i <= 16; i++) {
printf("%3d: Encode: %s\n", i,
EncodeBase64((unsigned char *) lpData, (size_t) i,
(char *) szGroup));
cbData = DecodeBase64((char *) szGroup, szGroup);
szGroup[cbData] = '\0';
printf("%3d: Decode: (LEN=%d) %s\n", i, cbData, szGroup);
}
if (argc > 1) {
printf("%s ---> %s : %ld\n", argv[1], argv[2],
DecodeBase64File(argv[1], argv[2]));
}
return 0;
}
#endif
/*
* Local Variables:
* mode: c
* coding: utf-8-unix
* End:
*/