プログラムテクニックメモ(2001/07/12) 
 

URLエンコードとは

画面フォーム間でのデータ送信は、POST か GET の形式にて通常行いますが、このデータ送信の際に困るのが、データ項目名とデータとの切り分けなのです。実際なにが困るのかと言うと、データの区切り文字とデータ中に区切り文字が発生した場合が困るのです。

「xyz=aaaa」という場合は、xyz項目名は aaaa というデータです。となるのですが、「xyz=x=a」と記述された場合は、xyz項目名は x=a と解釈できないからです。この問題を解決するためにURLエンコードという手法を使い、データ部を特殊文字に置き換える事によって解決します。「xyz=%82%A1%AB%62」とかという文字列を見たことありませんか?  それがURLエンコードされた文字なのです。

URLエンコード方法

半角の[0-9]、[a-z]、[A-Z]、[*-.@_]は、そのまま記述([]は、関係ないです)し、半角スペースは 「+」で置き換え、日本語等の8bit文字は、漢字コードの上位・下位に「%」を付け変換します。例えば漢字コード "あ" は 0xA4A2 ですので %A4%A2 となります。

変換例: ()'~!あ*-._ → abZ+%28%29%27%7E%21%A4%A2*-._

URLエンコードのサンプルプログラム

下記ソースは、gcc でコンパイルしましたが、特殊な命令は使用していないので、大抵の Cコンパイラでコンパイルできるでしょう。(ソース

下記関数の仕様としては、エラー時には(-1)を返し、正常時には変換した文字列長を返します。また、第2引数に指定された領域には、URLエンコードした文字列ポインタが格納(使用終了後は、必ずfreeすること)されます。

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

/* *-._ はそのまま、スペースは +、あとはエンコード */
static char enctbl[256] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   '+', 0, 0, 0, 0, 0, 0, 0, 0, 0, '*', 0, 0, '-', '.', 0,
   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0,
   0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
   'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0, 0, 0, 0, '_',
   0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

static char codetbl[16] = {
   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
   'A', 'B', 'C', 'D', 'E', 'F' };

URLencode(char *in, char **out)
{
   int len; /* data length */
   char *str = in; /* in data pointer */
   unsigned char hi, lo;
   unsigned char cstr;
   char *outp;
   int cnt = 0;

   /* in param nodata */
   if (!in || (len = strlen(in)) == 0)
      return -1;

   /* output area */
   outp = (char *)malloc(sizeof(char) * ((len * 3) + 1));
   memset( outp, 0, (len * 3) + 1);

   /**/
   while( *str ) {
      cstr = *str;

      if ( enctbl[cstr] > 0) {
         outp[cnt++] = enctbl[cstr];
      } else {
         hi = cstr >> 4;
         lo = cstr << 4; lo = lo >> 4;
         outp[cnt++] = '%';
         outp[cnt++] = codetbl[hi];
         outp[cnt++] = codetbl[lo];
      }

      str++;
   }

   /* data output area malloc */
   if ((*out = (char *)malloc(sizeof(char) * cnt + 1)) == NULL) {
      free(outp);
   return(-1);
   }

   /**/
   strcpy(*out, outp);
   free(outp);

   return (cnt + 1);
}

リンク

エンコード・コレクション

CGIサンプル

←topへ