CGIパラメータの自前処理

Cでcgiを書くときのために、とりあえず動く小さなパラメータ処理関数を作った。

未来の自分向け使い方メモ

関数cgi()に文字列(char*)を渡すと、文字列の配列(char**)を返す。
例えば、cgi("a=123&b=%23&c=1+3")と呼び出すと、{"a","123","b","#","c","1 3",NULL}を返す。
配列の0,2,4,…番目には各パラメータの名前へのポインタが、1,3,5,…番目には各パラメータの値へのポインタが入る。
配列の最後の要素にはNULLが入る。
文字列中に%nnの形式があった場合にはそれに対応する文字に変換する。
文字列中に+があった場合にはスペースに変換する。
また、引数が空文字列("")だった場合には、NULLのみが入った要素1の配列を返す。
引数で与えられた文字列自体を加工する方式なので必要ならばコピーを渡すこと。

cgi()関数本体

#include<stdlib.h>

char **cgi(char *src){
  char **m,*x,*y,i=0,n=0;
  for(x=src;*x;x++) if(*x=='=') n++;
  m = malloc(sizeof(char*)*(n*2+1));
  for(x=y=m[0]=src;*x;x++,y++){
    if(*x=='='||*x=='&'){ *y = '\0'; m[++i] = y+1; }
    else     if(*x=='%') sscanf((x+=2)-1,"%2hhx",y);
    else   *y = *x=='+' ? ' ' : *x;
  }
  *y = '\0';
  m[n*2] = NULL;
  return m;
}

サンプルのmain関数

各パラメータをtableにして表示する例

#include<stdio.h>
#include<stdlib.h>
char **cgi(char*);

main(){
  char **q,i;
  puts("Content-Type: text/html\n");
  puts("<form><input name=a><input name=b><input type=submit></form>");
  q=cgi(getenv("QUERY_STRING"));
  if(q[0]!=NULL){ /* パラメータが渡されているかの判定 */
    puts("<table border><tr><th>key<th>value");
    for(i=0;q[i]!=NULL;i+=2) printf("<tr><td>%s<td>%s\n",q[i],q[i+1]); /* q[i]が名前でq[i+1]が値 */
    puts("</table>");
  }
}