/*	
 *	clipcode.h
 *
 *	文字コード処理
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2015 Naoyuki Sawa
 *
 *	* Mon Feb 19 00:05:57 JST 2007 Naoyuki Sawa
 *	- 1st リリース。
 *	* Sun Nov 16 12:58:50 JST 2008 Naoyuki Sawa
 *	- url_encode()、url_decode()を追加しました。
 *	* Tue Jan 06 14:21:36 JST 2009 Naoyuki Sawa
 *	- md5_digest()を追加しました。
 *	* Wed Jan 07 16:23:27 JST 2009 Naoyuki Sawa
 *	- sha1_digest()を追加しました。
 *	* Thu Jan 15 16:13:35 JST 2009 Naoyuki Sawa
 *	- rc4_init()、rc4_encrypt_decrypt()を追加しました。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Mon Dec 14 21:55:09 JST 2015 Naoyuki Sawa
 *	- MIMEのBase64形式のコンテントボディのエンコードデコードを行う、ユーティリティ関数を追加しました。
 */
#ifndef __CLIP_CODE_H__
#define __CLIP_CODE_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/****************************************************************************
 *	Base64
 ****************************************************************************/

/* バイナリをBase64エンコードし、文字列に変換します。
 * [in]
 *	dst		文字列。(出力)
 *	dst_cap		dst[]の許容量。
 *	src		バイナリ。(入力)
 *	src_len		src[]の要素数。
 * [out]
 *	戻り値		文字列の長さ。
 *			終端のnul文字は、文字列の長さに含めません。
 * [note]
 *	* 出力文字列はnul終端されます。
 *	  ただし、戻り値はnul文字を含まないことに注意してください。
 *	  <例>
 *		[in]
 *			dst[]		unsigned char dst[100]
 *			dst_len		100
 *			src[]		{ 0x12,0x34 }
 *			src_len		2
 *		[out]
 *			dst[]		"EjQ=" // { 'E','j','Q','=','\0' }
 *			戻り値		4
 *		[note]
 *			戻り値は文字数の4ですが、出力はnul終端を含めて5バイトです。
 *			もし、dst_lenが5未満だったならば、アサートします。
 *	* 戻り値は、strlen(dst)に一致するので、あとで算出することもできます。
 *	  文字列の長さがすぐに必要なければ、戻り値を受け取らなくても構いません。
 */
int base64_encode(char* dst, int dst_cap, const void* src, int src_len);

/* 文字列をBase64デコードし、バイナリに変換します。
 * [in]
 *	dst		バイナリ。(出力)
 *	dst_cap		dst[]の許容量。
 *	src		文字列。(入力)
 * [out]
 *	戻り値		バイナリの長さ。
 * [note]
 *	* 出力バイナリはnul終端されません。
 *	  出力バイナリそれ自身が、有意な値「0」を含む可能性があるからです。
 *	  <例>
 *		[in]
 *			dst[]		unsigned char dst[100]
 *			dst_len		100
 *			src[]		"EjQ=" // { 'E','j','Q','=','\0' }
 *		[out]
 *			dst[]		{ 0x12,0x34 }
 *			戻り値		2
 *		[note]
 *			もし、dst_lenが2未満だったならば、アサートします。
 *	* 出力バイナリの長さを、あとで算出することはできません。
 *	  base64_encode()の場合と違って、必ず、戻り値を受け取ってください。
 */
int base64_decode(void* _dst, int dst_cap, const char* src);

//{{2015/12/14追加:MIMEのBase64形式のコンテントボディのエンコードデコードを行う、ユーティリティ関数を追加しました。
//MIMEのBase64形式のコンテントボディのエンコードを行います。
//[in]
//	buf		エンコード結果の一行分の文字列を格納するバッファ。
//			改行文字は格納しません。
//			最大で(76文字+終端のヌル文字)を格納するので、77バイト以上のバッファを指定して下さい。
//	dat		エンコードするデータ領域の先頭アドレス。
//	len		エンコードするデータ領域のデータ領域のバイト数。
//	pos		イテレーションのカウンタ。
//			前回のmime_encode()の戻り値を指定して下さい。
//[note]
//	- 簡潔にするためにmime_encode()という関数名にしましたが、MIME仕様を全て網羅している訳では有りません。
//	  MIMEの、「Content-Transfer-Encoding: Base64」形式の、コンテントボディの、エンコードを行うだけの関数です。
//	- 用途はMIMEに限らず、外部機器とPC間で7ビットの通信路を用いて通信を行う時に利用出来ます。
//	  例えば、デバッグ出力用のテキスト通信路を用いて、プロパティーテーブル(clipprp.c)を外部機器⇒PCへ送って、
//	  PC上でPrpEdt_*()を使って内容を編集した後、コマンド入力用のテキスト通信路を用いて、PC⇒外部機器へ送り返す等です。
//	- □使用例
//	  │FILE* fp = fopen("test.txt", "w");
//	  │int pos = 0;
//	  │while(pos < len) {
//	  │  char buf[128];
//	  │  pos = mime_encode(buf, TBL_Data, sizeof TBL_Data, pos);
//	  │  fputs(buf, fp);
//	  │  fputc('\n', fp); //改行を追加する。
//	  │}
//	  │fclose(fp);
int mime_encode(char buf[76 + 1/*nul*/], const void* dat, int len, int pos);
//MIMEのBase64形式のコンテントボディのデコードを行います。
//[in]
//	buf		デコードする一行の文字列。
//			改行文字は含めないで下さい。
//			終端のヌル文字を除いて、76文字を超える文字列を指定しないで下さい。
//	dat		デコード結果を格納するデータ領域の先頭アドレス。
//	len		デコード結果を格納するデータ領域のバイト数。
//	pos		イテレーションのカウンタ。
//			前回のmime_decode()の戻り値を指定して下さい。
//[note]
//	- 簡潔にするためにmime_decode()という関数名にしましたが、MIME仕様を全て網羅している訳では有りません。
//	  MIMEの、「Content-Transfer-Encoding: Base64」形式の、コンテントボディの、デコードを行うだけの関数です。
//	- 用途はMIMEに限らず、外部機器とPC間で7ビットの通信路を用いて通信を行う時に利用出来ます。
//	  例えば、デバッグ出力用のテキスト通信路を用いて、プロパティーテーブル(clipprp.c)を外部機器⇒PCへ送って、
//	  PC上でPrpEdt_*()を使って内容を編集した後、コマンド入力用のテキスト通信路を用いて、PC⇒外部機器へ送り返す等です。
//	- □使用例
//	  │FILE* fp = fopen("test.txt", "r");
//	  │int pos = 0;
//	  │while(pos < len) {
//	  │  char buf[128];
//	  │  fgets(buf, sizeof buf, fp);
//	  │  strchomp(buf); //改行を削除する。
//	  │  pos = mime_decode(buf, TBL_Data, sizeof TBL_Data, pos);
//	  │}
//	  │fclose(fp);
int mime_decode(const char buf[76 + 1/*nul*/], void* dat, int len, int pos);
//}}2015/12/14追加:MIMEのBase64形式のコンテントボディのエンコードデコードを行う、ユーティリティ関数を追加しました。

/****************************************************************************
 *	URLエンコード
 ****************************************************************************/

/* 任意の文字列を、URLエンコードされた文字列に変換します。
 * [in]
 *	dst		出力バッファ。
 *	dst_size	出力バッファのバイト数。
 *	src		任意の文字列。
 * [out]
 *	戻り値		出力した文字数。
 *			末端の'\0'は含めません。
 */
int url_encode(char* dst, int dst_size, const char* src);

/* URLエンコードされた文字列を、元の文字列に変換します。
 * [in]
 *	dst		出力バッファ。
 *	dst_size	出力バッファのバイト数。
 *	src		URLエンコードされた文字列。
 * [out]
 *	戻り値		出力した文字数。
 *			末端の'\0'は含めません。
 */
int url_decode(char* dst, int dst_size, const char* src);

/****************************************************************************
 *	MD5
 ****************************************************************************/

/* バイナリデータの、MD5ダイジェストを求めます。
 * [in]
 *	digest		MD5ダイジェストを格納するバッテァ。(出力)
 *	data		バイナリデータ。(入力)
 *	len		バイナリデータのバイト数。(>=0)
 * [out]
 *	digest		MD5ダイジェストを格納します。
 * [note]
 *	* 以下の資料を参考にしました。
 *	  「MD5 メッセージダイジェストアルゴリズム」(The MD5 Message-Digest Algorithm)
 *	   (URL: http://www.ipa.go.jp/security/rfc/RFC1321JA.html)
 *	- 本関数は、上記資料内のサンプル実装プログラムを簡略化して、実装したものです。
 *	  簡略化した点は、以下の二点です。
 *	  ・実行環境のバイトオーダーが、リトルエンディアンであるものと決め打ちました。
 *	  ・データストリームに対して繰り返し呼び出すのでなく、
 *	    メモリ上のデータブロックに対して一回の呼び出しで求める用途に限定しました。
 */
void md5_digest(unsigned char digest[/*16*/], const void* data, int len);

/****************************************************************************
 *	SHA-1
 ****************************************************************************/

/* バイナリデータの、SHA-1ダイジェストを求めます。
 * [in]
 *	digest		SHA-1ダイジェストを格納するバッテァ。(出力)
 *	data		バイナリデータ。(入力)
 *	len		バイナリデータのバイト数。(>=0)
 * [out]
 *	digest		SHA-1ダイジェストを格納します。
 * [note]
 *	* 以下の資料を参考にしました。
 *	  「SHA-1」(US Secure Hash Algorithm 1 (SHA1))
 *	   (URL: http://www.ipa.go.jp/security/rfc/RFC3174JA.html)
 *	- 本関数は、上記資料内の「6.2 方法 2」に従って、実装したものです。
 *	  本関数の実装は、以下の条件で簡略化を行ないました。
 *	  ・実行環境のバイトオーダーが、リトルエンディアンであるものと決め打ちました。
 *	  ・データストリームに対して繰り返し呼び出すのでなく、
 *	    メモリ上のデータブロックに対して一回の呼び出しで求める用途に限定しました。
 */
void sha1_digest(unsigned char digest[/*20*/], const void* data, int len);

/****************************************************************************
 *	RC4
 ****************************************************************************/

typedef struct _RC4 {
	unsigned char s[256];
	unsigned char i;
	unsigned char j;
} RC4;

/* RC4鍵ストリームをセットアップします。
 * [in]
 *	rc4		初期化するRC4構造体へのポインタ。
 *	_key		RC4鍵。
 *	keylen		RC4鍵のバイト数。
 */
void rc4_init(RC4* rc4, const void* _key/*[keylen]*/, int keylen);

/* データを暗号化、または、復号化します。
 * [in]
 *	rc4		初期化済みのRC4構造体へのポインタ。
 *	_dst		暗号化、または、復号化したデータを格納するバッファ。
 *	_src		暗号化、または、復号化するデータ。
 *	len		データのバイト数。
 * [note]
 *	* _dstと_srcに同じアドレスを指定しても構いません。
 *	  その場合は、元のデータを上書きして、暗号化、または、復号化したデータを格納します。
 */
void rc4_encrypt_decrypt(RC4* rc4, void* _dst/*[len]*/, const void* _src/*[len]*/, int len);
#define rc4_encrypt rc4_encrypt_decrypt
#define rc4_decrypt rc4_encrypt_decrypt

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_CODE_H__*/
