フォーム項目の表示と、取得は以下のようにします。 ほとんどDikiからの引用になっているのが恥ずかしいところです。 上のほうはおまじないだと思って、main関数のみ見てください。 new CGIとしてCGIオブジェクトを作って、cgi.reqsでフォーム値を取得します。 78kbyte以上のフォーム項目を受けると死んでしまうため、staticコンストラクタで処理せずにnewするようにしています。また、htmlタグを書き込むことで発生するクロスサイトスクリプティングを防止するために、入力されたデータはhtmlエスケープしています。
import std.conv; import std.stream; class URI { // I don't know why it's wrong on arm-linux... //private static int [char] h2i; //private static int [char] noEsc; private static int [256] h2i; private static int [256] noEsc; static this() { for(char c='0'; c<='9'; ++c) h2i[c] = c - '0'; for(char c='A'; c<='F'; ++c) h2i[c] = c - 'A' + 10; for(char c='a'; c<='f'; ++c) h2i[c] = c - 'a' + 10; for(char c=0x20; c<=0x7E; ++c) noEsc[c] = true; foreach(char c ; ";/?:&=+,-_.!~'()") noEsc[c] = false; } static char[] encode( char[] s ) { char[] r; foreach( char c ; s ) if( noEsc[c] ) r ~= (c==' ' ? '+' : c); else r ~= int_format("%%%02X", c); version (IgnoreCase) { r = tolower(r); } return r; } static char[] decode( char[] s ) { char[] r; for( int i=0; i!=s.length; ++i ) switch( s[i] ) { default: r ~= s[i]; break; case '+': r ~= ' '; break; case '%': if( i+1>=s.length ) break; if( s[++i]=='%' ) { r~='%'; break; } if( i+1>=s.length ) break; r~= cast(char)( 16*h2i[s[i]] + h2i[s[i+1]] ); ++i; } version (IgnoreCase) { r = tolower(r); } return r; } static char[] int_format( char[] fmt, int v ) { MemoryStream m = new MemoryStream(); m.printf( fmt, v ); return cast(char[]) m.data(); } } extern(C) char* getenv( char* envvarname ); class Env { static char[] opIndex( char[] varname ) { char* result = getenv( toStringz(varname) ); return result is null ? `` : std.string.toString(result); } class asInt { static int opIndex( char[] v ) { return toInt( Env[v] ); } } } class CGI { final static char[] self_name; final static char[][char[]] reqs; this() { char[] query; switch( Env[`REQUEST_METHOD`] ) { case `GET` : query = Env[`QUERY_STRING`]; break; case `POST`: query = readStdIn( Env.asInt[`CONTENT_LENGTH`] ); break; } foreach( char[] pair ; split(query,`&`) ) { char[][] kv = split( pair, `=` ); switch( kv.length ) { case 1: reqs[``] = URI.decode(kv[0]); break; case 2: reqs[URI.decode(kv[0])] = URI.decode(kv[1]); break; } } self_name = Env[`REQUEST_URI`]; self_name = self_name[ rfind(self_name,'/')+1 .. self_name.length ]; int end = find(self_name,'?'); if( end >= 0 ) self_name = self_name[0 .. end]; } private char[] readStdIn( uint size ) { ubyte[] buf; buf.length = size; ubyte* ptr = buf; int x=0, y=1; while( x<size && y!=0 ) { y = stdin.readBlock( ptr+x, size-x ); x += y; } buf.length = x; return cast(char[]) buf; } } char[] escapeHTML(char[] str) { str = replace(str,"&","&"); str = replace(str,"<","<"); str = replace(str,">",">"); str = replace(str,"\"","""); str = replace(str,"'","'"); return str; } void main() { CGI cgi = new CGI(); char[] name = escapeHTML(cgi.reqs["name"]); printf(`content-type:text/html; <html> <body> %.*s <form name="a" action="form.cgi"> <input type="text" value="%.*s" name="name"><br> <input type="submit" value="送信"> </form> </body> </html> `,name,name); }
&ref(): File not found: "form.zip" at page "D言語でCGI/フォーム表示、取得(UTF-8)";
http://p38.aaacafe.ne.jp/~sakurai/cgi-bin/form.cgi