Classic ASP と JavaScript のJSON通信

# はじめに
今更Classic ASPで開発を進めるようなことはないとは思うが、
今回そういう環境にぶち当たってしまったので、仕方なくClassic ASPについて学ぶことにした

**※なお、この記事に記載のソースを流用し、万が一不利益が生じた場合、当方は一切責任を持ちませんのであしからず**

# 経緯
開発環境がインターネット接続不可で、インストールされているアプリもほぼない
Visual Studio も当然なく、新規でインストールすることもできないときた
リリース先にはOfficeもないし、しょうがないので、
完全ローカルなWebアプリケーションを作成することにした

リリースするときはサーバー側とクライアント側両方リリースする想定だ

# 環境
**OS: Windows 7以降
Webサーバー: IIS
ブラウザ: IE10以上、Edge
クライアント側言語: HTML、JavaScript、CSS
サーバー側言語: JScript、VBScript (ASP)**

完全ローカルなので、フレームワークは一切使わない (JQueryもなし)


# 環境構築
IISとASPを使用するにはいくつか環境設定が必要になる
今回は完全ローカルなので、**リリース先PCにも環境構築が必要になる**

環境構築の手順は、以下のサイトが参考になった
https://www.purin-it.com/asp-vbscript-first

上記サイトのやってみたこと①と②を実施
これだけで環境構築は終了
これでURL http://localhost が物理パス C:\inetpub\wwwroot と連動するようになる

例えば C:\inetpub\wwwroot\test.asp を作成した場合、 http://localhost/test.asp で接続できる
ファイルやフォルダ作成すれば勝手に接続できるので、環境構築はJavaとかより楽かも?

# ファイル構成
今回はサンプル用にアプリケーションを構築するため、ファイル構成は以下のように配置してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113190/7d1ed9e6-cd68-0a66-ea96-aedaba0fdcc7.png)

# アプリケーション設計
**今回作成するサンプル用のアプリケーションは以下のような流れで実装する**
１． http://localhost/Test/client/index.html にアクセスする
２． index.html から test.js を読み込む
３． test.js で test.asp と通信し、値の送受信
４． test.asp から受け取った値をコンソールに出力する

**実装する機能の詳細は以下の通りとする**
・ test.js と test.asp との通信はAjax (XMLHttpRequest) で実装する
　　同期通信も非同期通信も行えるし、流用しやすい
・ test.js と test.asp の通信はPOST通信にする
　　値がURLに表示されないし、大量データのやり取りができる
・ test.js と test.asp のデータのやり取りにはJSONを使用する
　　複雑なデータ構造のやり取りができるので便利
・ test.asp ではファイルの読み取り、書き出しを行う
　　クライアントサイドでファイルのやり取りすると、1ファイルごとに保存先指定しなきゃならんのはだるい

**実装するうえでの値の変換の流れは以下の通りとする**

■リクエスト
１． test.js でJSONから文字列に変換
２． test.js でUTF-16文字列からSJISでURLエンコードした文字列に変換
３． test.asp で自動でURLデコードした文字列に変換
４． test.asp でURLデコードした文字列からJSONに変換

■レスポンス
１． test.asp で文字列からJavaScriptエスケープシーケンスに変換した文字列に変換
２． test.asp でJavaScriptエスケープシーケンスに変換した文字列からJSON文字列に変換
３． test.asp でJSON文字列からUTF-8でURLエンコードした文字列に変換
４． test.js でURLエンコードした文字列からUTF-8でURLデコードした文字列に変換
５． test.js でURLデコードした文字列からJSONに変換

# コード
コードは調べながら汎用性の高いものを作成したと思う
**注意点を後述してるから、必ず読んでから実行してね**

### クライアントサイド
```index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My test page</title>
  </head>
  <body>
    <script src="./test.js"></script>
  </body>
</html>
```

```test.js
//通信成功確認用
const READYSTATE_COMPLETED = 4;
const HTTP_STATUS_OK = 200;

//-----------------適宜変更してね-------------------------------
const OUTPUT_FOLDER = "C:\\Users\\ユーザー名\\Desktop"
const OUTPUT_FILE = "test.txt";
//-------------------------------------------------------------

//サンプル用にデータ書き出し (エスケープや連携の確認のためにJSONっぽい文字列にしてる)
writeFile(OUTPUT_FOLDER, OUTPUT_FILE, 
        " param = {\"123\":\"3314\",\"おいしいヤミー感謝感謝\":\"sky peace\",\"a\":[\"123\", 334, sdsds\"]};");

//書き出したデータを読み込んで、コンソールに出力
console.log(readFile(OUTPUT_FOLDER + "\\" + OUTPUT_FILE));

//ファイルの読み込み実施
function readFile(filePath) {

    //呼び出し先ファイルで分岐するためのJSON設定
    let sendData = {
    	method: "read",
    	type: "file",
    	sub_type: "as_is",
    	file_path: filePath,
    };

    //サーバーにJSON構造を送信
    return httpSend(sendData).result;

}

//ファイルの書き出し実施
function writeFile(folderPath, fileName, fileData) {

    //呼び出し先ファイルで分岐するためのJSON設定
    let sendData = {
    	method: "write",
    	type: "file",
    	sub_type: "as_is",
    	folder_path: folderPath,
    	file_name: fileName,
    	file_data: fileData,
    };

    //サーバーにJSON構造を送信
    return httpSend(sendData).result;

}

//サーバーと通信する
function httpSend(data) {

    //通信方法をPOSTで設定
    const METHOD_TYPE = "POST";
    //通信先のURLを指定
    const SERVER_URL = "http://localhost/Test/server/test.asp";
    //同期処理で実行 (非同期処理にする場合は、returnはできなくなるよ)
    const ASYN_FLAG = false;

    //Ajaxの生成
	let xhr = new XMLHttpRequest();
	let result = "";

    //Ajaxを開く
	xhr.open(METHOD_TYPE, SERVER_URL, ASYN_FLAG);
    //送信するデータタイプの設定 (VBScriptでJSONでの受け取りができないので、文字列として送信)
	xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    try {
        //Ajaxのステータス変更時の設定
    	xhr.onreadystatechange = function() {
            //正常終了の場合
    		if( xhr.readyState == READYSTATE_COMPLETED && xhr.status == HTTP_STATUS_OK ) {
                //受信データをURLデコードしてJSONに変換
    			result = JSON.parse(decodeURIComponent(xhr.responseText));
    		}
    	};
    } catch (e) {
        console.log(e);
    }

	//送受信データの文字コード設定 (VBScriptはデフォルトでShift_JISしか文字コードを扱えないため)
	xhr.overrideMimeType("text/plain;charset=Shift_JIS")

    //Requestパラメータに送信データのJSON文字列をSJIS URLエンコード変換したものを設定
	xhr.send("Request=" + encodeURIComponentSJIS(JSON.stringify(data)));
	return result;

}


//文字列をSJISのURLエンコードする
//以下サイトから必要なソースだけ抜粋
// https://www.junoe.jp/downloads/itoh/enc_js.shtml
function encodeURIComponentSJIS(str){

	const JCT11280 = Function('var a="zKV33~jZ4zN=~ji36XazM93y!{~k2y!o~k0ZlW6zN?3Wz3W?{EKzK[33[`y|;-~j^YOTz$!~kNy|L1$353~jV3zKk3~k-4P4zK_2+~jY4y!xYHR~jlz$_~jk4z$e3X5He<0y!wy|X3[:~l|VU[F3VZ056Hy!nz/m1XD61+1XY1E1=1y|bzKiz!H034zKj~mEz#c5ZA3-3X$1~mBz$$3~lyz#,4YN5~mEz#{ZKZ3V%7Y}!J3X-YEX_J(3~mAz =V;kE0/y|F3y!}~m>z/U~mI~j_2+~mA~jp2;~m@~k32;~m>V}2u~mEX#2x~mBy+x2242(~mBy,;2242(~may->2&XkG2;~mIy-_2&NXd2;~mGz,{4<6:.:B*B:XC4>6:.>B*BBXSA+A:X]E&E<~r#z+625z s2+zN=`HXI@YMXIAXZYUM8X4K/:Q!Z&33 3YWX[~mB`{zKt4z (zV/z 3zRw2%Wd39]S11z$PAXH5Xb;ZQWU1ZgWP%3~o@{Dgl#gd}T){Uo{y5_d{e@}C(} WU9|cB{w}bzvV|)[} H|zT}d||0~{]Q|(l{|x{iv{dw}(5}[Z|kuZ }cq{{y|ij}.I{idbof%cu^d}Rj^y|-M{ESYGYfYsZslS`?ZdYO__gLYRZ&fvb4oKfhSf^d<Yeasc1f&a=hnYG{QY{D`Bsa|u,}Dl|_Q{C%xK|Aq}C>|c#ryW=}eY{L+`)][YF_Ub^h4}[X|?r|u_ex}TL@YR]j{SrXgo*|Gv|rK}B#mu{R1}hs|dP{C7|^Qt3|@P{YVV |8&}#D}ef{e/{Rl|>Hni}R1{Z#{D[}CQlQ||E}[s{SG_+i8eplY[=[|ec[$YXn#`hcm}YR|{Ci(_[ql|?8p3]-}^t{wy}4la&pc|3e{Rp{LqiJ],] `kc(]@chYnrM`O^,ZLYhZB]ywyfGY~aex!_Qww{a!|)*lHrM{N+n&YYj~Z b c#e_[hZSon|rOt`}hBXa^i{lh|<0||r{KJ{kni)|x,|0auY{D!^Sce{w;|@S|cA}Xn{C1h${E]Z-XgZ*XPbp]^_qbH^e[`YM|a||+=]!Lc}]vdBc=j-YSZD]YmyYLYKZ9Z>Xcczc2{Yh}9Fc#Z.l{}(D{G{{mRhC|L3b#|xK[Bepj#ut`H[,{E9Yr}1b{[e]{ZFk7[ZYbZ0XL]}Ye[(`d}c!|*y`Dg=b;gR]Hm=hJho}R-[n}9;{N![7k_{UbmN]rf#pTe[x8}!Qcs_rs[m`|>N}^V})7{^r|/E}),}HH{OYe2{Skx)e<_.cj.cjoMhc^d}0uYZd!^J_@g,[[[?{i@][|3S}Yl3|!1|eZ|5IYw|1D}e7|Cv{OHbnx-`wvb[6[4} =g+k:{C:}ed{S]|2M]-}WZ|/q{LF|dYu^}Gs^c{Z=}h>|/i|{W]:|ip{N:|zt|S<{DH[p_tvD{N<[8Axo{X4a.^o^X>Yfa59`#ZBYgY~_t^9`jZHZn`>G[oajZ;X,i)Z.^~YJe ZiZF^{][[#Zt^|]Fjx]&_5dddW]P0C[-]}]d|y {C_jUql] |OpaA[Z{lp|rz}:Mu#]_Yf6{Ep?f5`$[6^D][^u[$[6^.Z8]]ePc2U/=]K^_+^M{q*|9tYuZ,s(dS{i=|bNbB{uG}0jZOa:[-]dYtu3]:]<{DJ_SZIqr_`l=Yt`gkTnXb3d@kiq0a`Z{|!B|}e}Ww{Sp,^Z|0>_Z}36|]A|-t}lt{R6pi|v8hPu#{C>YOZHYmg/Z4nicK[}hF_Bg|YRZ7c|crkzYZY}_iXcZ.|)U|L5{R~qi^Uga@Y[xb}&qdbd6h5|Btw[}c<{Ds53[Y7]?Z<|e0{L[ZK]mXKZ#Z2^tavf0`PE[OSOaP`4gi`qjdYMgys/?[nc,}EEb,eL]g[n{E_b/vcvgb.{kcwi`~v%|0:|iK{Jh_vf5lb}KL|(oi=LrzhhY_^@`zgf[~g)[J_0fk_V{T)}I_{D&_/d9W/|MU[)f$xW}?$xr4<{Lb{y4}&u{XJ|cm{Iu{jQ}CMkD{CX|7A}G~{kt)nB|d5|<-}WJ}@||d@|Iy}Ts|iL|/^|no|0;}L6{Pm]7}$zf:|r2}?C_k{R(}-w|`G{Gy[g]bVje=_0|PT{^Y^yjtT[[[l!Ye_`ZN]@[n_)j3nEgMa]YtYpZy].d-Y_cjb~Y~[nc~sCi3|zg}B0}do{O^{|$`_|D{}U&|0+{J3|8*]iayx{a{xJ_9|,c{Ee]QXlYb]$[%YMc*]w[aafe]aVYi[fZEii[xq2YQZHg]Y~h#|Y:thre^@^|_F^CbTbG_1^qf7{L-`VFx Zr|@EZ;gkZ@slgko`[e}T:{Cu^pddZ_`yav^Ea+[#ZBbSbO`elQfLui}.F|txYcbQ`XehcGe~fc^RlV{D_0ZAej[l&jShxG[ipB_=u:eU}3e8[=j|{D(}dO{Do[BYUZ0/]AYE]ALYhZcYlYP/^-^{Yt_1_-;YT`P4BZG=IOZ&]H[e]YYd[9^F[1YdZxZ?Z{Z<]Ba2[5Yb[0Z4l?]d_;_)a?YGEYiYv`_XmZs4ZjY^Zb]6gqGaX^9Y}dXZr[g|]Y}K aFZp^k^F]M`^{O1Ys]ZCgCv4|E>}8eb7}l`{L5[Z_faQ|c2}Fj}hw^#|Ng|B||w2|Sh{v+[G}aB|MY}A{|8o}X~{E8paZ:]i^Njq]new)`-Z>haounWhN}c#{DfZ|fK]KqGZ=:u|fqoqcv}2ssm}.r{]{nIfV{JW)[K|,Z{Uxc|]l_KdCb%]cfobya3`p}G^|LZiSC]U|(X|kBlVg[kNo({O:g:|-N|qT}9?{MBiL}Sq{`P|3a|u.{Uaq:{_o|^S}jX{Fob0`;|#y_@[V[K|cw[<_ }KU|0F}d3|et{Q7{LuZttsmf^kYZ`Af`}$x}U`|Ww}d]| >}K,r&|XI|*e{C/a-bmr1fId4[;b>tQ_:]hk{b-pMge]gfpo.|(w[jgV{EC1Z,YhaY^q,_G[c_g[J0YX]`[h^hYK^_Yib,` {i6vf@YM^hdOKZZn(jgZ>bzSDc^Z%[[o9[2=/YHZ(_/Gu_`*|8z{DUZxYt^vuvZjhi^lc&gUd4|<UiA`z]$b/Z?l}YI^jaHxe|;F}l${sQ}5g}hA|e4}?o{ih}Uz{C)jPe4]H^J[Eg[|AMZMlc}:,{iz}#*|gc{Iq|/:|zK{l&}#u|myd{{M&v~nV};L|(g|I]ogddb0xsd7^V})$uQ{HzazsgxtsO^l}F>ZB]r|{7{j@cU^{{CbiYoHlng]f+nQ[bkTn/}<-d9q {KXadZYo+n|l[|lc}V2{[a{S4Zam~Za^`{HH{xx_SvF|ak=c^[v^7_rYT`ld@]:_ub%[$[m](Shu}G2{E.ZU_L_R{tz`vj(f?^}hswz}GdZ}{S:h`aD|?W|`dgG|if{a8|J1{N,}-Ao3{H#{mfsP|[ bzn+}_Q{MT{u4kHcj_q`eZj[8o0jy{p7}C|[}l){MuYY{|Ff!Ykn3{rT|m,^R|,R}$~Ykgx{P!]>iXh6[l[/}Jgcg{JYZ.^qYfYIZl[gZ#Xj[Pc7YyZD^+Yt;4;`e8YyZVbQ7YzZxXja.7SYl[s]2^/Ha$[6ZGYrb%XiYdf2]H]kZkZ*ZQ[ZYS^HZXcCc%Z|[(bVZ]]:OJQ_DZCg<[,]%Zaa [g{C00HY[c%[ChyZ,Z_`PbXa+eh`^&jPi0a[ggvhlekL]w{Yp^v}[e{~;k%a&k^|nR_z_Qng}[E}*Wq:{k^{FJZpXRhmh3^p>de^=_7`|ZbaAZtdhZ?n4ZL]u`9ZNc3g%[6b=e.ZVfC[ZZ^^^hD{E(9c(kyZ=bb|Sq{k`|vmr>izlH[u|e`}49}Y%}FT{[z{Rk}Bz{TCc/lMiAqkf(m$hDc;qooi[}^o:c^|Qm}a_{mrZ(pA`,}<2sY| adf_%|}`}Y5U;}/4|D>|$X{jw{C<|F.hK|*A{MRZ8Zsm?imZm_?brYWZrYx`yVZc3a@f?aK^ojEd {bN}/3ZH]/$YZhm^&j 9|(S|b]mF}UI{q&aM]LcrZ5^.|[j`T_V_Gak}9J[ ZCZD|^h{N9{~&[6Zd{}B}2O|cv]K}3s}Uy|l,fihW{EG`j_QOp~Z$F^zexS`dcISfhZBXP|.vn|_HYQ|)9|cr]<`&Z6]m_(ZhPcSg>`Z]5`~1`0Xcb4k1{O!bz|CN_T{LR|a/gFcD|j<{Z._[f)mPc:1`WtIaT1cgYkZOaVZOYFrEe[}T$}Ch}mk{K-^@]fH{Hdi`c*Z&|Kt{if[C{Q;{xYB`dYIX:ZB[}]*[{{p9|4GYRh2ao{DS|V+[zd$`F[ZXKadb*A] Ys]Maif~a/Z2bmclb8{Jro_rz|x9cHojbZ{GzZx_)]:{wAayeDlx}<=`g{H1{l#}9i|)=|lP{Qq}.({La|!Y{i2EZfp=c*}Cc{EDvVB|;g}2t{W4av^Bn=]ri,|y?|3+}T*ckZ*{Ffr5e%|sB{lx^0]eZb]9[SgAjS_D|uHZx]dive[c.YPkcq/}db{EQh&hQ|eg}G!ljil|BO]X{Qr_GkGl~YiYWu=c3eb}29v3|D|}4i||.{Mv})V{SP1{FX}CZW6{cm|vO{pS|e#}A~|1i}81|Mw}es|5[}3w{C`h9aL]o{}p[G`>i%a1Z@`Ln2bD[$_h`}ZOjhdTrH{[j_:k~kv[Sdu]CtL}41{I |[[{]Zp$]XjxjHt_eThoa#h>sSt8|gK|TVi[Y{t=}Bs|b7Zpr%{gt|Yo{CS[/{iteva|cf^hgn}($_c^wmb^Wm+|55jrbF|{9^ q6{C&c+ZKdJkq_xOYqZYSYXYl`8]-cxZAq/b%b*_Vsa[/Ybjac/OaGZ4fza|a)gY{P?| I|Y |,pi1n7}9bm9ad|=d{aV|2@[(}B`d&|Uz}B}{`q|/H|!JkM{FU|CB|.{}Az}#P|lk}K{|2rk7{^8^?`/|k>|Ka{Sq}Gz}io{DxZh[yK_#}9<{TRdgc]`~Z>JYmYJ]|`!ZKZ]gUcx|^E[rZCd`f9oQ[NcD_$ZlZ;Zr}mX|=!|$6ZPZYtIo%fj}CpcN|B,{VDw~gb}@hZg`Q{LcmA[(bo`<|@$|o1|Ss}9Z_}tC|G`{F/|9nd}i=}V-{L8aaeST]daRbujh^xlpq8|}zs4bj[S`J|]?G{P#{rD{]I`OlH{Hm]VYuSYUbRc*6[j`8]pZ[bt_/^Jc*[<Z?YE|Xb|?_Z^Vcas]h{t9|Uwd)_(=0^6Zb{Nc} E[qZAeX[a]P^|_J>e8`W^j_Y}R{{Jp__]Ee#e:iWb9q_wKbujrbR}CY`,{mJ}gz{Q^{t~N|? gSga`V_||:#mi}3t|/I`X{N*|ct|2g{km}gi|{={jC}F;|E}{ZZjYf*frmu}8Tdroi{T[|+~}HG{cJ}DM{Lp{Ctd&}$hi3|FZ| m}Kr|38}^c|m_|Tr{Qv|36}?Up>|;S{DV{k_as}BK{P}}9p|t`jR{sAm4{D=b4pWa[}Xi{EjwEkI}3S|E?u=X0{jf} S|NM|JC{qo^3cm]-|JUx/{Cj{s>{Crt[UXuv|D~|j|d{YXZR}Aq}0r}(_{pJfi_z}0b|-vi)Z mFe,{f4|q`b{}^Z{HM{rbeHZ|^x_o|XM|L%|uFXm}@C_{{Hhp%a7|0p[Xp+^K}9U{bP}: tT}B|}+$|b2|[^|~h{FAby[`{}xgygrt~h1[li`c4vz|,7p~b(|mviN}^pg[{N/|g3|^0c,gE|f%|7N{q[|tc|TKA{LU}I@|AZp(}G-sz{F |qZ{}F|f-}RGn6{Z]_5})B}UJ{FFb2]4ZI@v=k,]t_Dg5Bj]Z-]L]vrpdvdGlk|gF}G]|IW}Y0[G| /bo|Te^,_B}#n^^{QHYI[?hxg{[`]D^IYRYTb&kJ[cri[g_9]Ud~^_]<p@_e_XdNm-^/|5)|h_{J;{kacVopf!q;asqd}n)|.m|bf{QW|U)}b+{tL|w``N|to{t ZO|T]jF}CB|0Q{e5Zw|k |We}5:{HO{tPwf_uajjBfX}-V_C_{{r~gg|Ude;s+}KNXH}! `K}eW{Upwbk%ogaW}9EYN}YY|&v|SL{C3[5s.]Y]I]u{M6{pYZ`^,`ZbCYR[1mNg>rsk0Ym[jrE]RYiZTr*YJ{Ge|%-lf|y(`=[t}E6{k!|3)}Zk} ][G{E~cF{u3U.rJ|a9p#o#ZE|?|{sYc#vv{E=|LC}cu{N8`/`3`9rt[4|He{cq|iSYxY`}V |(Q|t4{C?]k_Vlvk)BZ^r<{CL}#h}R+[<|i=}X|{KAo]|W<`K{NW|Zx}#;|fe{IMr<|K~tJ_x}AyLZ?{GvbLnRgN}X&{H7|x~}Jm{]-| GpNu0}.ok>|c4{PYisrDZ|fwh9|hfo@{H~XSbO]Odv]%`N]b1Y]]|eIZ}_-ZA]aj,>eFn+j[aQ_+]h[J_m_g]%_wf.`%k1e#Z?{CvYu_B^|gk`Xfh^M3`afGZ-Z|[m{L}|k3cp[it ^>YUi~d>{T*}YJ{Q5{Jxa$hg|%4`}|LAgvb }G}{P=|<;Ux{_skR{cV|-*|s-{Mp|XP|$G|_J}c6cM{_=_D|*9^$ec{V;|4S{qO|w_|.7}d0|/D}e}|0G{Dq]Kdp{}dfDi>}B%{Gd|nl}lf{C-{y}|ANZr}#={T~|-(}c&{pI|ft{lsVP}){|@u}!W|bcmB{d?|iW|:dxj{PSkO|Hl]Li:}VYk@|2={fnWt{M3`cZ6|)}|Xj}BYa?vo{e4|L7|B7{L7|1W|lvYO}W8nJ|$Vih|{T{d*_1|:-n2dblk``fT{Ky|-%}m!|Xy|-a{Pz}[l{kFjz|iH}9N{WE{x,|jz}R {P|{D)c=nX|Kq|si}Ge{sh|[X{RF{t`|jsr*fYf,rK|/9}$}}Nf{y!1|<Std}4Wez{W${Fd_/^O[ooqaw_z[L`Nbv[;l7V[ii3_PeM}.h^viqYjZ*j1}+3{bt{DR[;UG}3Og,rS{JO{qw{d<_zbAh<R[1_r`iZTbv^^a}c{iEgQZ<exZFg.^Rb+`Uj{a+{z<[~r!]`[[|rZYR|?F|qppp]L|-d|}K}YZUM|=Y|ktm*}F]{D;g{uI|7kg^}%?Z%ca{N[_<q4xC]i|PqZC]n}.bDrnh0Wq{tr|OMn6tM|!6|T`{O`|>!]ji+]_bTeU}Tq|ds}n|{Gm{z,f)}&s{DPYJ`%{CGd5v4tvb*hUh~bf]z`jajiFqAii]bfy^U{Or|m+{I)cS|.9k:e3`^|xN}@Dnlis`B|Qo{`W|>||kA}Y}{ERYuYx`%[exd`]|OyiHtb}HofUYbFo![5|+]gD{NIZR|Go}.T{rh^4]S|C9_}xO^i`vfQ}C)bK{TL}cQ|79iu}9a];sj{P.o!f[Y]pM``Jda^Wc9ZarteBZClxtM{LW}l9|a.mU}KX}4@{I+f1}37|8u}9c|v${xGlz}jP{Dd1}e:}31}%3X$|22i<v+r@~mf{sN{C67G97855F4YL5}8f{DT|xy{sO{DXB334@55J1)4.G9A#JDYtXTYM4, YQD9;XbXm9SX]IB^4UN=Xn<5(;(F3YW@XkH-X_VM[DYM:5XP!T&Y`6|,^{IS-*D.H>:LXjYQ0I3XhAF:9:(==.F*3F1189K/7163D,:@|e2{LS36D4hq{Lw/84443@4.933:0307::6D7}&l{Mx657;89;,K5678H&93D(H<&<>0B90X^I;}Ag1{P%3A+>><975}[S{PZE453?4|T2{Q+5187;>447:81{C=hL6{Me^:=7ii{R=.=F<81;48?|h8}Uh{SE|,VxL{ST,7?9Y_5Xk3A#:$%YSYdXeKXOD8+TXh7(@>(YdXYHXl9J6X_5IXaL0N?3YK7Xh!1?XgYz9YEXhXaYPXhC3X`-YLY_XfVf[EGXZ5L8BXL9YHX]SYTXjLXdJ: YcXbQXg1PX]Yx4|Jr{Ys4.8YU+XIY`0N,<H%-H;:0@,74/:8546I=9177154870UC]d<C3HXl7ALYzXFXWP<<?E!88E5@03YYXJ?YJ@6YxX-YdXhYG|9o{`iXjY_>YVXe>AYFX[/(I@0841?):-B=14337:8=|14{c&93788|di{cW-0>0<097/A;N{FqYpugAFT%X/Yo3Yn,#=XlCYHYNX[Xk3YN:YRT4?)-YH%A5XlYF3C1=NWyY}>:74-C673<69545v {iT85YED=64=.F4..9878/D4378?48B3:7:7/1VX[f4{D,{l<5E75{dAbRB-8-@+;DBF/$ZfW8S<4YhXA.(5@*11YV8./S95C/0R-A4AXQYI7?68167B95HA1*<M3?1/@;/=54XbYP36}lc{qzSS38:19?,/39193574/66878Yw1X-87E6=;964X`T734:>86>1/=0;(I-1::7ALYGXhF+Xk[@W%TYbX7)KXdYEXi,H-XhYMRXfYK?XgXj.9HX_SX]YL1XmYJ>Y}WwIXiI-3-GXcYyXUYJ$X`Vs[7;XnYEZ;XF! 3;%8;PXX(N3Y[)Xi1YE&/ :;74YQ6X`33C;-(>Xm0(TYF/!YGXg8 9L5P01YPXO-5%C|qd{{/K/E6,=0144:361:955;6443@?B7*7:F89&F35YaX-CYf,XiFYRXE_e{}sF 0*7XRYPYfXa5YXXY8Xf8Y~XmA[9VjYj*#YMXIYOXk,HHX40YxYMXU8OXe;YFXLYuPXP?EB[QV0CXfY{:9XV[FWE0D6X^YVP*$4%OXiYQ(|xp|%c3{}V`1>Y`XH00:8/M6XhQ1:;3414|TE|&o@1*=81G8<3}6<|(f6>>>5-5:8;093B^3U*+*^*UT30XgYU&7*O1953)5@E78--F7YF*B&0:%P68W9Zn5974J9::3}Vk|-,C)=)1AJ4+<3YGXfY[XQXmT1M-XcYTYZXCYZXEYXXMYN,17>XIG*SaS|/eYJXbI?XdNZ+WRYP<F:R PXf;0Xg`$|1GX9YdXjLYxWX!ZIXGYaXNYm6X9YMX?9EXmZ&XZ#XQ>YeXRXfAY[4 ;0X!Zz0XdN$XhYL XIY^XGNXUYS/1YFXhYk.TXn4DXjB{jg|4DEX]:XcZMW=A.+QYL<LKXc[vV$+&PX*Z3XMYIXUQ:ZvW< YSXFZ,XBYeXMM)?Xa XiZ4/EXcP3%}&-|6~:1(-+YT$@XIYRBC<}&,|7aJ6}bp|8)K1|Xg|8C}[T|8Q.89;-964I38361<=/;883651467<7:>?1:.}le|:Z=39;1Y^)?:J=?XfLXbXi=Q0YVYOXaXiLXmJXO5?.SFXiCYW}-;|=u&D-X`N0X^,YzYRXO(QX_YW9`I|>hZ:N&X)DQXP@YH#XmNXi$YWX^=!G6YbYdX>XjY|XlX^XdYkX>YnXUXPYF)FXT[EVTMYmYJXmYSXmNXi#GXmT3X8HOX[ZiXN]IU2>8YdX1YbX<YfWuZ8XSXcZU%0;1XnXkZ_WTG,XZYX5YSX Yp 05G?XcYW(IXg6K/XlYP4XnI @XnO1W4Zp-9C@%QDYX+OYeX9>--YSXkD.YR%Q/Yo YUX].Xi<HYEZ2WdCE6YMXa7F)=,D>-@9/8@5=?7164;35387?N<618=6>7D+C50<6B03J0{Hj|N9$D,9I-,.KB3}m |NzE0::/81YqXjMXl7YG; [.W=Z0X4XQY]:MXiR,XgM?9$9>:?E;YE77VS[Y564760391?14941:0=:8B:;/1DXjFA-564=0B3XlH1+D85:0Q!B#:-6&N/:9<-R3/7Xn<*3J4.H:+334B.=>30H.;3833/76464665755:/83H6633:=;.>5645}&E|Y)?1/YG-,93&N3AE@5 <L1-G/8A0D858/30>8<549=@B8] V0[uVQYlXeD(P#ID&7T&7;Xi0;7T-$YE)E=1:E1GR):--0YI7=E<}n9|aT6783A>D7&4YG7=391W;Zx<5+>F#J39}o/|cc;6=A050EQXg8A1-}D-|d^5548083563695D?-.YOXd37I$@LYLWeYlX<Yd+YR A$;3-4YQ-9XmA0!9/XLY_YT(=5XdDI>YJ5XP1ZAW{9>X_6R(XhYO65&J%DA)C-!B:97#A9;@?F;&;(9=11/=657/H,<8}bz|j^5446>.L+&Y^8Xb6?(CYOXb*YF(8X`FYR(XPYVXmPQ%&DD(XmZXW??YOXZXfCYJ79,O)XnYF7K0!QXmXi4IYFRXS,6<%-:YO(+:-3Q!1E1:W,Zo}Am|n~;3580534*?3Zc4=9334361693:30C<6/717:<1/;>59&:4}6!|rS36=1?75<8}[B|s809983579I.A.>84758=108564741H*9E{L{|u%YQ<%6XfH.YUXe4YL@,>N}Tv|ve*G0X)Z;/)3@A74(4P&A1X:YVH97;,754*A66:1 D739E3553545558E4?-?K17/770843XAYf838A7K%N!YW4.$T19Z`WJ*0XdYJXTYOXNZ 1XaN1A+I&Xi.Xk3Z3GB&5%WhZ1+5#Y[X<4YMXhQYoQXVXbYQ8XSYUX4YXBXWDMG0WxZA[8V+Z8X;D],Va$%YeX?FXfX[XeYf<X:Z[WsYz8X_Y]%XmQ(!7BXIZFX]&YE3F$(1XgYgYE& +[+W!<YMYFXc;+PXCYI9YrWxGXY9DY[!GXiI7::)OC;*$.>N*HA@{C|}&k=:<TB83X`3YL+G4XiK]i}(fYK<=5$.FYE%4*5*H*6XkCYL=*6Xi6!Yi1KXR4YHXbC8Xj,B9ZbWx/XbYON#5B}Ue}+QKXnF1&YV5XmYQ0!*3IXBYb71?1B75XmF;0B976;H/RXU:YZX;BG-NXj;XjI>A#D3B636N;,*%<D:0;YRXY973H5)-4FXOYf0:0;/7759774;7;:/855:543L43<?6=E,.A4:C=L)%4YV!1(YE/4YF+ F3%;S;&JC:%/?YEXJ4GXf/YS-EXEYW,9;E}X$}547EXiK=51-?71C%?57;5>463553Zg90;6447?<>4:9.7538XgN{|!}9K/E&3-:D+YE1)YE/3;37/:05}n<}:UX8Yj4Yt864@JYK..G=.(A Q3%6K>3(P3#AYE$-6H/456*C=.XHY[#S.<780191;057C)=6HXj?955B:K1 E>-B/9,;5.!L?:0>/.@//:;7833YZ56<4:YE=/:7Z_WGC%3I6>XkC*&NA16X=Yz2$X:Y^&J48<99k8}CyB-61<18K946YO4{|N}E)YIB9K0L>4=46<1K0+R;6-=1883:478;4,S+3YJX`GJXh.Yp+Xm6MXcYpX(>7Yo,/:X=Z;Xi0YTYHXjYmXiXj;*;I-8S6N#XgY}.3XfYGO3C/$XjL$*NYX,1 6;YH&<XkK9C#I74.>}Hd`A748X[T450[n75<4439:18A107>|ET}Rf<1;14876/Yb983E<5.YNXd4149>,S=/4E/<306443G/06}0&}UkYSXFYF=44=-5095=88;63844,9E6644{PL}WA8:>)7+>763>>0/B3A545CCnT}Xm|dv}Xq1L/YNXk/H8;;.R63351YY747@15YE4J8;46;.38.>4A369.=-83,;Ye3?:3@YE.4-+N353;/;@(X[YYD>@/05-I*@.:551741Yf5>6A443<3535;.58/86=D4753442$635D1>0359NQ @73:3:>><Xn?;43C14 ?Y|X611YG1&<+,4<*,YLXl<1/AIXjF*N89A4Z576K1XbJ5YF.ZOWN.YGXO/YQ01:4G38Xl1;KI0YFXB=R<7;D/,/4>;$I,YGXm94@O35Yz66695385.>:6A#5}W7n^4336:4157597434433<3|XA}m`>=D>:4A.337370?-6Q96{`E|4A}C`|Qs{Mk|J+~r>|o,wHv>Vw}!c{H!|Gb|*Ca5}J||,U{t+{CN[!M65YXOY_*B,Y[Z9XaX[QYJYLXPYuZ%XcZ8LY[SYPYKZM<LMYG9OYqSQYM~[e{UJXmQYyZM_)>YjN1~[f3{aXFY|Yk:48YdH^NZ0|T){jVFYTZNFY^YTYN~[h{nPYMYn3I]`EYUYsYIZEYJ7Yw)YnXPQYH+Z.ZAZY]^Z1Y`YSZFZyGYHXLYG 8Yd#4~[i|+)YH9D?Y^F~Y7|-eYxZ^WHYdYfZQ~[j|3>~[k|3oYmYqY^XYYO=Z*4[]Z/OYLXhZ1YLZIXgYIHYEYK,<Y`YEXIGZI[3YOYcB4SZ!YHZ*&Y{Xi3~[l|JSY`Zz?Z,~[m|O=Yi>??XnYWXmYS617YVYIHZ(Z4[~L4/=~[n|Yu{P)|];YOHHZ}~[o33|a>~[r|aE]DH~[s|e$Zz~[t|kZFY~XhYXZB[`Y}~[u|{SZ&OYkYQYuZ2Zf8D~[v}% ~[w3},Q[X]+YGYeYPIS~[y}4aZ!YN^!6PZ*~[z}?E~[{3}CnZ=~[}}EdDZz/9A3(3S<,YR8.D=*XgYPYcXN3Z5 4)~[~}JW=$Yu.XX~] }KDX`PXdZ4XfYpTJLY[F5]X~[2Yp}U+DZJ::<446[m@~]#3}]1~]%}^LZwZQ5Z`/OT<Yh^ -~]&}jx[ ~m<z!%2+~ly4VY-~o>}p62yz!%2+Xf2+~ly4VY-zQ`z (=] 2z~o2",C={" ":0,"!":1},c=34,i=2,p,s="",u=String.fromCharCode,t=u(12539);while(++c<127)C[u(c)]=c^39&&c^92?i++:0;i=0;while(0<=(c=C[a.charAt(i++)]))if(16==c)if((c=C[a.charAt(i++)])<87){if(86==c)c=1879;while(c--)s+=u(++p)}else s+=s.substr(8272,360);else if(c<86)s+=u(p+=c<51?c-16:(c-55)*92+C[a.charAt(i++)]);else if((c=((c-86)*92+C[a.charAt(i++)])*92+C[a.charAt(i++)])<49152)s+=u(p=c<40960?c:c|57344);else{c&=511;while(c--)s+=t;p=12539}return s')();

	return str.replace(/[^*+.-9A-Z_a-z-]/g,function(s){
		let c = s.charCodeAt(0);
		let m;
		return c < 128 ? (c < 16 ? "%0" : "%") + c.toString(16).toUpperCase() : 
			65376 < c && c < 65440 ? "%" + (c - 65216).toString(16).toUpperCase() : 
			(c = JCT11280.indexOf(s)) < 0 ? "%81E" : "%" + ((m = ((c < 8272 ? c : 
			(c = JCT11280.lastIndexOf(s))) - (c %= 188)) / 188) < 31 ? m + 129 : 
			m + 193).toString(16).toUpperCase()+(64 < (c += c < 63 ? 64 : 65) && c < 91 || 
			95 == c || 96 < c && c < 123 ? String.fromCharCode(c) : "%" + c.toString(16).toUpperCase())
	})
}
```

### サーバーサイド
```test.asp
<%@ LANGUAGE="VBScript" %>

<SCRIPT LANGUAGE="JavaScript" RUNAT="Server">

    //配列にオブジェクトかどうかの判定関数付与
	Array.prototype.isObject = function() {
		return false;
	};

	//配列に配列かどうかの判定関数付与
	Array.prototype.isArray = function() {
		return true;
	};

	//オブジェクトにオブジェクトかどうかの判定関数付与
	Object.prototype.isObject = function() {
		return true;
	};

	//オブジェクトに配列かどうかの判定関数付与
	Object.prototype.isArray = function() {
		return false;
	};

	//オブジェクトにkey配列返却関数付与
	Object.prototype.keys = function() {
		var arr = [];
		for (var key in this) {
			if (this.hasOwnProperty(key)) {
				arr.push(key);
			}
		}
		return arr;
	}

	//オブジェクトにオブジェクトの値取得用関数付与
	Object.prototype.get = function(key) {
		return this[key];
	};

	//VBScriptでエンコードURLする用の関数
	function wrap_encodeURIComponent(uri) {
		return encodeURIComponent(uri);
	}

	//VBScriptでJSON構造を使用する用の関数
	//JSONオブジェクトはJScriptには存在しないため、parseはevalで再現
	//stringifyはhtmlfileを使用すれば再現できるが、IEでしか機能しないのでお勧めしない
    //また、今回に限って言えば、VBS主体のため、VBSでstringifyは用意
	function wrap_JSON_parse(jsonStr) {
		return eval("(" + jsonStr + ")");
	}

</SCRIPT>
<% 

	Const RESULT_KEY = "result"
	Dim req
	Dim res
    Dim result

	'取得したリクエストをログファイルに出力
	Call printLog("[REQUEST]" & Request.Form("Request"))

	'リクエストを取得し、Requestパラメータの値をJSON構造にしてreqに設定
	'GETメソッドでリクエストを取得する場合はRequest.QueryStringを使用
	'VBSではリクエスト情報は勝手にURLデコードされる
	Set req = jsObjectToVbsDictionary(wrap_JSON_parse(Request.Form("Request")))

	Set res = CreateObject("Scripting.Dictionary")
	Set result = CreateObject("Scripting.Dictionary")

	'JSONの内容からどのメソッドを実行するか分岐 (実行したいメソッドの設定は適宜行って分岐させてね)
	Select Case req("method")
		Case "read"
			Select Case req("type")
				Case "file"
					Select Case req("sub_type")
						Case "as_is"

							'読み込んだファイルの内容を、JavaScriptのエスケープ文字に変換してresに設定する
							'必ず最後はRESULT_KEYにまとめるようにする(クライアントサイドでresultを抜き出してるから)
							result.Add req("method"), readFile(req("file_path"))

					End Select
			End Select
		Case "write"
			Select Case req("type")
				Case "file"
					Select Case req("sub_type")
						Case "as_is"

							'書き出した結果を、JavaScriptのエスケープ文字に変換してresに設定する
							'必ず最後はRESULT_KEYにまとめるようにする(クライアントサイドでresultを抜き出してるから)
							result.Add req("method"), CStr(writeFile(req("folder_path"), req("file_name"), req("file_data"), Empty))

					End Select
			End Select
	End Select

    Call printLog("[RESPONSE]" & JSON_stringify(res))

	'Server.URLEncode関数だと規格がJavaScriptと合わないので、
	'JavaScriptでURLエンコードをかけて、JSON構造に変換する
	Response.Write wrap_encodeURIComponent(JSON_stringify(res))


	'---------------------------以下自前で用意したコード---------------------------

	'ファイル読み込み
	Function readFile(filePath)

		Dim fso
		Dim f

		'ファイルシステムオブジェクト作成
		Set fso = CreateObject("Scripting.FileSystemObject")
		' ファイルオープン
		Set f = fso.OpenTextFile(filePath, 1, False)
		' 全行読み込む
		readFile = f.ReadAll
		' ファイルクローズ
		f.Close
		Set f = Nothing
		Set fso = Nothing

	End Function

	'ファイル書き出し
	Function writeFile(folderPath, fileName, text, ioMode)

		Dim fso
		Dim f

		On Error Resume Next

		'モードの指定がない場合は、上書きモードにする
		If IsEmpty(ioMode) Then
			ioMode = 2
		End If

		' ファイルシステムオブジェクトの作成
		Set fso = CreateObject("Scripting.FileSystemObject")
		' テキストファイルのオープン
		Set f = fso.OpenTextFile(folderPath & "\" & fileName, ioMode, True)
		' テキストファイルに書き込み
		f.WriteLine(text)

		'エラーが発生しなかった場合
		If Err.Number = 0 Then
			writeFile = True

		'エラーが発生した場合
		Else
			writeFile = False

		End If

		f.Close
		Set f = Nothing
		Set fso = Nothing

		On Error GoTo 0

	End Function

	'ログ出力
	'※writeFileで出力を行っているため、writeFile関数で呼び出さないように注意!!!!!!!
	'無限ループになっちゃうからね
	Sub printLog(logText)

		'-----------------適宜変更してね-------------------------------
		Const LOG_FOLDER = "C:\inetpub\app logs\Test"
		Const LOG_FILE = "test.log"
		'-------------------------------------------------------------

		'追記モードでファイル書き出し
		Call writeFile(LOG_FOLDER, LOG_FILE, logText, 8)

	End Sub

	'JavaScript用にエスケープ文字列に変換する
	Function jsEscape(value)

        'ブール値の場合
		If VarType(value) = vbBoolean Then
            'すべて小文字の文字列で返却
			jsEscape = LCase(CStr(value))

        '数値の場合
		ElseIf IsNumeric(value) Then
            'そのまま返却
			jsEscape = value

        'null値の場合
		ElseIf IsNull(value) Then
            'Nullエスケープ文字で返却
			jsEscape = "\0"

        'それ以外(文字列)の場合
		Else
            'エスケープシーケンスに基づき、文字列置換していく
			value = Replace(value, "\", "\\")
			value = Replace(value, """", "\""")
			value = Replace(value, "'", "\'")
			value = Replace(value, vbBack, "\b")
			value = Replace(value, vbTab, "\t")
			value = Replace(value, vbVerticalTab, "\v")
			value = Replace(value, vbCr, "\r")
			value = Replace(value, vbLf, "\n")
			value = Replace(value, vbFormFeed, "\f")
			value = Replace(value, "`", "\`")
			jsEscape = """" & value & """"
		End If

	End Function

	'JsのobjectからvbsのDictionaryに変換
	Function jsObjectToVbsDictionary(jsObject)

		Dim resultObj
		Dim resultArr()
		Dim index
		Dim keys
		Dim key

        'isArray関数とisObject関数が用意されていない場合(配列でもオブジェクトでもない)
		On Error Resume Next
		If Not jsObject.isArray() And Not jsObject.isObject() Then

            'そのまま返却
			jsObjectToVbsDictionary = jsObject

        '配列の場合
		ElseIf jsObject.isArray() Then

            'VBS配列の初期化
			ReDim resultArr(jsObject.length - 1)

            'js配列を繰り返し、vbs配列に入れ替える
			For index = 0 To jsObject.length - 1
				resultArr(index) = jsObjectToVbsDictionary(jsObject.shift())
			Next

            'VBS配列を返却
			jsObjectToVbsDictionary = resultArr

        'オブジェクトの場合
		ElseIf jsObject.isObject() Then

            'VBSオブジェクトの初期化
			Set resultObj = CreateObject("Scripting.Dictionary")
            'jsオブジェクトのキー配列取得
			Set keys = jsObject.keys()

            'キー配列分繰り返す
			For index = 0 To keys.length - 1
				key = keys.shift()
                '値を再起呼び出しにて、型ごとの処理を実行
				resultObj.Add key, jsObjectToVbsDictionary(jsObject.get(key))
			Next

            'VBSオブジェクトを返却
			Set jsObjectToVbsDictionary = resultObj

		End If
		On Error GoTo 0

	End Function

	'vbsのDictionaryからJson文字列に変換
	Function JSON_stringify(vbsDictionary)

		Dim key
		Dim result
		Dim resultArr
		Dim resultIndex
		Dim index

        'オブジェクトの場合
		If IsObject(vbsDictionary) Then

            '文字列保管用配列初期化
			ReDim resultArr(vbsDictionary.Count - 1)
			resultIndex = -1

            'Dictionaryオブジェクトを繰り返す
			For Each key In vbsDictionary
				resultIndex = resultIndex + 1
                'キーをダブルクォーテーションで囲い、:区切りで値を設定
                '値は再起呼び出しにて、型ごとに処理する
				resultArr(resultIndex) = """" & key & """:" & JSON_stringify(vbsDictionary(key))
			Next

            '{}で囲い、文字列保管用配列をカンマ区切り文字列にした値を返却
			JSON_stringify = "{" & Join(resultArr, ",") & "}"

        '配列の場合
		ElseIf IsArray(vbsDictionary) Then

            '文字列保管用配列初期化
			ReDim resultArr(UBound(vbsDictionary))
			resultIndex = -1

            '配列を繰り返す
			For index = 0 To UBound(vbsDictionary)
				resultIndex = resultIndex + 1
                '値は再起呼び出しにて、型ごとに処理する
				resultArr(resultIndex) = JSON_stringify(vbsDictionary(key))
			Next

            '[]で囲い、文字列保管用配列をカンマ区切り文字列にした値を返却
			JSON_stringify = "[" & Join(resultArr, ",") & "]"

        'それ以外の場合
		Else

            '各型ごとにエスケープした文字列を指定
			JSON_stringify = jsEscape(vbsDictionary)

		End If

	End Function


 %>
```

# 注意点
１．ファイルの書き出し、読み込みについて、フォルダのアクセス権限にIISの権限設定をする必要がある
　　読み込み、書き出しを行うフォルダを右クリック > プロパティ > セキュリティ > 編集 > 追加
　　選択するオブジェクト名を入力してくださいの個所に`IUSR`と入力して、名前の確認
　　名前が正しいとOKが押せるようになるので、OKを押す
　　`IUSR`が追加されていることを確認して、`IUSR`の権限にフルコントロールを許可して適用 > OK
　　ちなみに`IUSR`はデフォルトの実行権限ってだけで、全然変えられるらしい
　　`インターネット インフォメーション サービス (IIS) マネージャー > 認証 > 匿名認証`

２．変更箇所について、`-----------------適宜変更してね-------------------------------`で記載している個所は
　　適宜変更してください

３．サーバーサイドのログ出力処理 printLog は writeFile 内では絶対に使用しちゃダメ
　　無限ループに入って、Webサーバーの強制停止とかする羽目になるからね

# 補足
１． IIS サーバーの設定や管理ついて、コントロールパネル > 管理ツール >
　　インターネット インフォメーション サービス (IIS) マネージャー でサーバー起動、停止、再起動とかいろいろできる
　　基本的に常に起動してるから何かあった時くらいしか触らない

２． IIS サーバーのログについて、`C:\inetpub\logs\LogFiles\W3SVC1`に`u_exYYMMDD.log`で作成されているから
　　エラー発生時はここを見るとわかるよ