//================================================================ // form.cc // FORMデータをCGIが利用できるように加工するCGIプログラム // Copyright (C) Naoki Watanabe. 1995-2000. All rights reserved. //================================================================ #include #include #include #include // 漢字コードの種別を表す定数 #define ASCII 0x00 #define EUC 0x01 #define SJIS 0x02 #define JIS 0x04 #define JAPANESE 0xff // ★注目 // 2000年3月18日にこのプログラムを大幅に変更しました。 // ★注目 // 入力された日本語の漢字コードを EUC, SJIS, JIS のいずれかに変換します。 // ただし半角カナは無視します。 // 希望のコードのものを #define してください。 #define CODE EUC // EUC UNIXユーザー向け //#define CODE SJIS // SJIS Windowsユーザー向け //#define CODE JIS // JIS 誰が使う? // ★注目 // 送られてきたデータを動的確保したメモリにコピーして作業することにします。 // そのメモリの最大サイズを決めておくほうが安全でしょう。 #define MAX_MEMORY (16*1024) // 16k bytes. // ★注目 // このプログラムをモジュールとして独立にコンパイルするには // 末尾のmain関数を削除して、以下の構造体とGetForm関数のみをヘッダーファイルで // プロトタイプ宣言すればよいでしょう。 //---- begin of form.h #ifndef __FORM_H_INCLUDED #define __FORM_H_INCLUDED struct FormTerm { char* name; char* value; }; int GetForm( FormTerm*& term ); #endif //---- end of form.h char* Receive( void ); int Terms( char* src ); void Assign( FormTerm* term, char* src ); char* Decode( char* src ); void Escape( char* src ); int KanjiCode( char* text ); void ANYtoJIS( char* text ); void ANYtoEUC( char* text ); void ANYtoSJIS( char* text ); //---- FORM変数を受け取る統括関数 int GetForm( FormTerm*& term ) { char* buf = Receive(); if( !buf ) return 0; int terms = Terms( buf ); term = new FormTerm [terms]; Assign( term, buf ); // 各変数の値を復元する for( int i=0; i 0 && length < MAX_MEMORY ){ buf = new char [length+1]; int n = fread( buf, 1, length, stdin ); buf[n] = '\0'; } }else if( method && !strcmp( method, "GET" ) ){ char* env = getenv("QUERY_STRING"); if( env ){ buf = strdup(env); } } return buf; } //---- 変数の個数を数える関数 int Terms( char* src ) { int terms = 0; do{ if( *src == '=' ) terms++; }while( *src++ ); return terms; } //---- 変数の名前と値のアドレスを設定する関数 void Assign( FormTerm* term, char* src ) { int i=0; for( term[i].name = src; *src; src++ ){ if( *src == '=' ){ *src = '\0'; term[i++].value = src+1; }else if( *src == '&' ){ *src = '\0'; term[i].name = src+1; } } } //---- URL encodeされたデータの復号と漢字コードの変換 char* Decode( char* src ) { // FORM特有の復元処理 Escape( src ); // 漢字コードを指定のコードに統一する #if CODE == JIS ANYtoJIS( src ); #endif #if CODE == EUC ANYtoEUC( src ); #endif #if CODE == SJIS ANYtoSJIS( src ); #endif return src; } //---- 大文字表記の16進数を数字に変換する関数 inline char AtoH( char c ) { if( '0' <= c && c <= '9' ) return c - '0'; if( 'A' <= c && c <= 'F' ) return c - 'A' + 10; return 0; // 楽観的なエラー対処 } //---- %で始まる特殊記号を変換する関数 void Escape( char* src ) { char* dst; for( dst=src; *src; src++ ){ if( *src == '%' ){ *dst++ = (AtoH(*++src)<<4) + AtoH(*++src); }else if( *src == '+' ){ *dst++ = ' '; }else{ *dst++ = *src; } } *dst++ = '\0'; } //---- 半角カナの存在を無視した漢字コードの判定関数 int KanjiCode( char* text ) { for( u_char* ptr=(u_char*)text; *ptr; ptr++ ){ if( *ptr == 0x1b && *(ptr+1) == '$' ) return JIS; if( *ptr < 0x80 ) continue; if( 0x81 <= *ptr && *ptr <= 0x9F ) return SJIS; if( 0xA1 <= *ptr && *ptr <= 0xDF ) return EUC; if( *(ptr+1) <= 0xA0 ) return SJIS; } return ASCII; } //---- JIS文字をEUC文字に変換する関数 inline void JIStoEUC( u_char& knj1, u_char& knj2 ) { knj1 |= 0x80; knj2 |= 0x80; } //---- EUC文字をJIS文字に変換する関数 inline void EUCtoJIS( u_char& knj1, u_char& knj2 ) { knj1 &= ~0x80; knj2 &= ~0x80; } //---- SJIS文字をEUC文字に変換する関数 inline void SJIStoEUC( u_char& knj1, u_char& knj2 ) { knj1 <<= 1; if( knj2 < 0x9F ){ if( knj1 < 0x3F ) knj1 -= 0x61; else knj1 += 0x1F; if( knj2 > 0x7E ) knj2 += 0x60; else knj2 += 0x61; }else{ if( knj1 < 0x3F ) knj1 -= 0x60; else knj1 += 0x20; knj2 += 0x02; } } //---- EUC文字をSJIS文字に変換する関数 inline void EUCtoSJIS( u_char& knj1, u_char& knj2 ) { if( knj1 & 0x01 ){ knj1 >>= 1; if( knj1 < 0x6F ) knj1 += 0x31; else knj1 += 0x71; if( knj2 > 0xDF ) knj2 -= 0x60; else knj2 -= 0x61; }else{ knj1 >>= 1; if( knj1 < 0x6F ) knj1 += 0x30; else knj1 += 0x70; knj2 -= 0x02; } } //---- JIS文字をSJIS文字に変換する関数 inline void JIStoSJIS( u_char& knj1, u_char& knj2 ) { if( knj1 & 0x01 ){ knj1 >>= 1; if( knj1 < 0x2F ) knj1 += 0x71; else knj1 -= 0x4F; if( knj2 > 0x5F ) knj2 += 0x20; else knj2 += 0x1F; }else{ knj1 >>= 1; if( knj1 < 0x2F ) knj1 += 0x70; else knj1 -= 0x50; knj2 += 0x7E; } } //---- SJIS文字をJIS文字に変換する関数 inline void SJIStoJIS( u_char& knj1, u_char& knj2 ) { knj1 <<= 1; if( knj2 < 0x9F ){ if( knj1 < 0x3F ) knj1 += 0x1F; else knj1 -= 0x61; if( knj2 > 0x7E ) knj2 -= 0x20; else knj2 -= 0x1F; }else{ if( knj1 < 0x3F ) knj1 += 0x20; else knj1 -= 0x60; knj2 -= 0x7E; } } //---- JISコードをEUCコードに変換する関数 void JIStoEUC( char* text ) { int mode = ASCII; u_char *wr, *re; for( wr=re=(u_char*)text; *re; re++ ){ if( (re[0]=='\x1b' && re[1]=='$' && re[2] == 'B' ) || (re[0]=='\x1b' && re[1]=='$' && re[2] == '@' ) ){ re+=2; mode = JAPANESE; continue; }else if( (re[0]=='\x0f') || (re[0]=='\x1b' && re[1]=='(' && re[2] == 'B' ) || (re[0]=='\x1b' && re[1]=='(' && re[2] == 'J' ) ){ re+=2; mode = ASCII; continue; }else if( (re[0]=='\x0e') || (re[0]=='\x1b' && re[1]=='(' && re[2] == 'I' ) ){ re+=2; mode = ASCII; // hankaku IGNORE continue; } if( mode == ASCII ){ *wr++ = *re; continue; } *wr++ = *re; if( !(*wr = *++re) ) break; JIStoEUC( *(wr-1), *wr ); wr++; } *wr='\0'; } //---- EUCコードをJISコードに変換する関数 void EUCtoJIS( char* text ) { int mode=ASCII; char* buf2 = strdup(text); u_char *wr, *re; for( wr=(u_char*)text, re=(u_char*)buf2; *re; re++ ){ if( *re < 0x80 ){ if( mode != ASCII ){ mode = ASCII; *wr++ = '\x1b'; *wr++ = '('; *wr++ = 'B'; } *wr++ = *re; }else{ if( mode != JAPANESE ){ mode = JAPANESE; *wr++ = '\x1b'; *wr++ = '$'; *wr++ = 'B'; } *wr++ = *re; if( !(*wr = *++re) ) break; EUCtoJIS( *(wr-1), *wr ); wr++; } } if( mode != ASCII ){ mode = ASCII; *wr++ = '\x1b'; *wr++ = '('; *wr++ = 'B'; } *wr = '\0'; free(buf2); } //---- JISコードをSJISコードに変換する関数 void JIStoSJIS( char* text ) { int mode = ASCII; u_char *wr, *re; for( wr=re=(u_char*)text; *re; re++ ){ if( (re[0]=='\x1b' && re[1]=='$' && re[2] == 'B' ) || (re[0]=='\x1b' && re[1]=='$' && re[2] == '@' ) ){ re+=2; mode = JAPANESE; continue; }else if( (re[0]=='\x0f') || (re[0]=='\x1b' && re[1]=='(' && re[2] == 'B' ) || (re[0]=='\x1b' && re[1]=='(' && re[2] == 'J' ) ){ re+=2; mode = ASCII; continue; }else if( (re[0]=='\x0e') || (re[0]=='\x1b' && re[1]=='(' && re[2] == 'I' ) ){ re+=2; mode = ASCII; // hankaku IGNORE continue; } if( mode == ASCII ){ *wr++ = *re; continue; } *wr++ = *re; if( !(*wr = *++re) ) break; JIStoSJIS( *(wr-1), *wr ); wr++; } *wr='\0'; } //---- SJISコードをJISコードに変換する関数 void SJIStoJIS( char* text ) { int mode = ASCII; char* buf2 = strdup(text); u_char *wr, *re; for( wr=(u_char*)text, re=(u_char*)buf2; *re; re++ ){ if( *re < 0x80 ){ if( mode != ASCII ){ mode = ASCII; *wr++ = '\x1b'; *wr++ = '('; *wr++ = 'B'; } *wr++ = *re; }else{ if( mode != JAPANESE ){ mode = JAPANESE; *wr++ = '\x1b'; *wr++ = '$'; *wr++ = 'B'; } *wr++ = *re; if( !(*wr = *++re) ) break; SJIStoJIS( *(wr-1), *wr ); wr++; } } if( mode != ASCII ){ mode = ASCII; *wr++ = '\x1b'; *wr++ = '('; *wr++ = 'B'; } *wr = '\0'; free(buf2); } //---- EUCコードをSJISコードに変換する関数 void EUCtoSJIS( char* text ) { for( u_char* ptr=(u_char*)text; *ptr; ptr++ ){ if( *ptr < 0x80 ) continue; if( !(*++ptr) ) break; EUCtoSJIS( *(ptr-1), *ptr ); } } //---- SJISコードをEUCコードに変換する関数 void SJIStoEUC( char* text ) { for( u_char* ptr=(u_char*)text; *ptr; ptr++ ){ if( *ptr < 0x80 ) continue; if( !(*++ptr) ) break; SJIStoEUC( *(ptr-1), *ptr ); } } //---- 任意のコードをJISに変換する関数 void ANYtoJIS( char* text ) { switch( KanjiCode( text ) ){ case JIS : break; case EUC : EUCtoJIS( text ); break; case SJIS : SJIStoJIS( text ); break; case ASCII: break; } } //---- 任意のコードをEUCに変換する関数 void ANYtoEUC( char* text ) { switch( KanjiCode( text ) ){ case JIS : JIStoEUC( text ); break; case EUC : break; case SJIS : SJIStoEUC( text ); break; case ASCII: break; } } //---- 任意のコードをSJISに変換する関数 void ANYtoSJIS( char* text ) { switch( KanjiCode( text ) ){ case JIS : JIStoSJIS( text ); break; case EUC : EUCtoSJIS( text ); break; case SJIS : break; case ASCII: break; } } //---- 試食用main関数 /* int main( void ) { puts("Content-type: text/plain\n"); FormTerm* term; int terms; terms = GetForm( term ); printf("=== FORM VARIABLES ===\n"); for( int i=0; i