• 華和梨 8.2.8 系
 
 

実際に華和梨でゴーストを作る

  • 実戦

ミドルウェアってなんぞ

  • 華和梨のマニュアルや関連した解説サイトではよく「ミドルウェア」という単語が登場
  • 里々でいう「ポストと狛犬」のような、テンプレートゴーストと思ってもそれほど間違いではない はず
    • 個人的な印象では
      • テンプレート/改造すればすぐにゴーストができる。設定箇所が少なくカスタマイズが比較的容易
      • ミドルウェア/豪華な機能を持つ。テンプレートの側面も持つが、根本からのカスタマイズは困難
    • という感じ
  • ミドルウェアの機能も思いつく限り列挙
    • 単語フレームワーク
    • セキュリティ面
    • 古いバージョンの華和梨との互換性
    • ゴースト制作のフォーマット(基礎イベントの他、多重人格などのサポート)
 

で、ミドルウェアやテンプレートを使うべき?

  • ここまでの基礎知識があればミドルウェアやテンプレートの改造によって、余裕でゴースト制作に入るはず
  • 使う
      • 表記ルールさえ覚えていればゴースト制作にすぐ入れる
      • 必要なイベントが既に用意されているので、かかる時間を短縮できる
      • セキュリティを受け持ってくれるので安心
    • ×
      • 堅牢な構成が逆に発想実現の足を引っ張る
      • それぞれに書式ルールがあり、新たなイベントを実装するのが極めて難しい
  • 使わない
      • やりたい事だけを選んで気軽にできる。イベントの追加も楽
      • 辞書構成の把握が容易になり、ファイル構成がすっきりする
      • 作りたいものがあるのなら目的に向かって一直線に作れる
    • ×
      • セーブロードや各種イベントの実装など全部自分で作る労力
      • 危険性・セキュリティについては勉強が必要
      • 自由すぎて何を作ればいいかわからん

作りたいゴーストが、独自の機能を実装するなど、一般的なゴーストを逸脱するかどうかが選ぶ基準かも

 

ミドルウェアやテンプレートを使わないやり方

とりあえず華和梨を使ってみたい・慣れておきたいという方はミドルウェアやテンプレートを使うとして、ここからは1から華和梨ゴーストを制作する基礎

 

準備

  • これまで作った事のある里々ゴーストなどから、シェルを流用するなどして準備
  • ゴーストフォルダは以下の2つのファイルが必要
    • shiori.dll
    • kawarirc.kis
 

shiori.dll / 華和梨本体

  • これがなければ始まらない
  • descript.txtを里々から流用しているのなら、栞指定の記述をチェック
    • × shiori,satori.dll
    • ○ shiori,shiori.dll
 

kawarirc.kis / 華和梨の設定ファイル、というか最初に読み込む辞書

  • 華和梨が最初に読み込む辞書ファイル。実態はテキストファイルなので、ふつうのテキストエディタで開けるようにしておくと便利
  • 起動時に最初に読み込む唯一のファイルなので、他の辞書ファイルを読み込んだりする時は、この辞書の中でkisを使ってロードしていくようにする
 

全てを決定付ける最初のイベント

  • 華和梨で処理するあらゆるイベントは、必ず System.Callback.OnGET や System.Callback.OnNOTIFY というエントリを通ってくる
  • これだけだと何がなんだか分からないので例
System.Callback.OnGET : ${${System.Request.ID}}
System.Callback.OnGET : $(entry ${System.Request.ID})
  • どちらも同じ意味
  • 挙動としては、エントリ${System.Request.ID}には、OnBootやOnCloseなどの栞イベント名がそのまま入っており、なんらかのイベントが通知されるたびにこの System.Callback.OnGET エントリが呼ばれる
  • つまりSSPから
    • 「ユーザからあんたに起動指示が出たよ」→OnBootイベント発信
    • 「ユーザからあんたに終了指示が出たよ」→OnCloseイベント発信
  • という風におしらせが来るので、それに対応するように該当エントリを呼び出す仕組みです
 
  • 順番に考える
  • もし実際に OnBoot が来た場合、${System.Request.ID} が OnBoot に置き換わるわけで、下のようになる
System.Callback.OnGET : ${OnBoot}
System.Callback.OnGET : $(entry OnBoot)
  • すなわちOnBootが通知されると、「OnBootエントリを呼ぶ」という意味になる
  • よって、以下のような記述例を実際に使えるようにするために必要なものが、上の記述なわけです
  • 当然、これを弄るとイベントに呼び出すエントリ名を自分流に改造したりできます
OnBoot : ${起動}

起動 : \0\s[0]ちゃす。\e
 

書き込んでみよう

  • kawarirc.kisをメモ帳などのテキストエディタで編集しよう
System.Callback.OnGET    : $(entry ${System.Request.ID})
System.Callback.OnNOTIFY : $(entry ${System.Request.ID})

OnBoot  : \1\s[10]\0\s[0]やあ。\w9\w9\e
OnClose : \1\s[10]\0\s[0]うい。\w9\w9\-
  • System.Callback.OnNOTIFY はnotifyイベントが来る
  • 筆者もよく分かってないものの、一部のイベントはこのOnNOTIFYエントリから来る。めんどくさいのでOnGETのほうと同じようにしてしまってOK。複雑な処理を持ち込まない限り問題なし
 

全部kawarirc.kisに書くの?

  • 別のファイルを作って記述していくなどして、好きなように別ファイルに保存すればOK
  • 作ったファイルはkawaricrc.iniの中で、kisのloadコマンドを使って一気に読み込めるので好きなようにファイル構成を作れる
  • loadコマンドは、華和梨辞書としてファイルを読み込むkisなので、実態がテキストなら拡張子もお好みでOK
  • 以下例示
=kis
	# 華和梨辞書
	load dic01_Base.txt ;
	load dic02_Event.txt ;

	# さおり
	saoriregist mciaudior.dll mciaudior preload ;
	saoriregist httpc.dll httpc preload ;
=end
  • =kis ~ =end でくくられた妙な記法は、kisを直接書くための記法で、文末にはセミコロン【;】が必要。この書き方は、例えば $(load dic01_Base.txt) と書くのと同じような意味なものの、このファイルが読み込まれた瞬間に実行されるのが特徴
  • その性質から言って kawarirc.kis 以外で使う機会は滅多にないかも
 
  • 余談として、セミコロン【;】は通常の $() でkisを使う時にも使える
  • loop系などを見やすくしたい時に使われる事が多いだけで必須でもない
設定する : $( setstr フラグ "ふつう")$(
setstr 満腹度 "100")$( setstr モード "" )

これを

設定する : $(setstr フラグ "ふつう" ;
setstr 満腹度 "100" ;
setstr モード "" )
  • と書いたりできる
  • 半角スペースで区切るところなんかはほぼ改行使い放題
 

全イベントに対応すべき?

必ずしも全てのイベントに対応する必要は「ない」。知らないイベントが来ても、「そんなエントリ名はない」=「からっぽ」で、何もしない事になるのでエラーになったりはしない

  • ただし、最低限、以下のものだけは必ず用意すべき
    • OnFirstBoot ... 初回起動時
    • OnBoot ... 起動時
    • OnGhostChanged ... 切り替わって起動した時
    • OnWindowStateRestore ... 最小化から復帰
      • これらはサーフィスの表示くらいは定義しておかないと困った事、というか面倒な事になる
      • 理由が分からない人は、里々の「*最小化から復帰」をからっぽにして、最小化→復帰をしてみましょ
    • OnClose ... 終了時
      • 終わりには必ず \- (終了するさくらスクリプト)が必要、ないと終了してくれない
    • OnChoiceSelect ... 選択肢がクリックされた時
      • 里々は自動でジャンプしてくれたけどこっちは手動で作る必要がある
      • といっても以下のように書くだけ
OnChoiceSelect : $(entry ${R0})\e

リファレンス0には、\q[~,~]で作ったIDが入っているので、その名前のエントリを呼べという意味。これで選択肢も正常に稼動する。 最後に \e をつけているのはどこかで \e を書き忘れた時のための保険

 

kawarirc.kisに書く事をまとめて突っ込む

  • resourceも当然System.Callbackを通ってやってくるので、Disc-2などでリストとにらめっこすべし
  • 例としてネットワーク更新用のURLは「homeurl」というIDで来る
  • よって、homeurlエントリを作ってそこにURLを書けばOK
System.Callback.OnGET    : $(entry ${System.Request.ID})
System.Callback.OnNOTIFY : $(entry ${System.Request.ID})

=kis
	# 華和梨辞書。自分の好きな辞書ファイルを作り、登録しましょう
	load dic01_Base.txt ;
	load dic02_Event.txt ;
=end

R0 : ${System.Request.Reference0}
R1 : ${System.Request.Reference1}
R2 : ${System.Request.Reference2}
R3 : ${System.Request.Reference3}
R4 : ${System.Request.Reference4}
R5 : ${System.Request.Reference5}
R6 : ${System.Request.Reference6}
R7 : ${System.Request.Reference7}
R8 : ${System.Request.Reference8}
R9 : ${System.Request.Reference9}

OnChoiceSelect : $(entry ${R0})\e

homeurl : "http://~"

OnBoot  : \1\s[10]\0\s[0]やあ。\w9\w9\e
OnClose : \1\s[10]\0\s[0]うい。\w9\w9\-
  • イベントとかのリファレンスに対応しやすいように、R0からR9とかもここで定義しておけば楽
  • 便利だと思いませんか
  • どうせ好きな辞書ファイルを作って登録できるんで、OnBootやOnCloseなどはそっちのファイルでやりましょう
 

descript.txtに書いておくおまじない

shiori.cache,0
  • SSPのキャッシュ機能をOFFにする
  • ミドルウェアやテンプレートを使わず、自前で作る場合、もしかすると必須になるかも。これがないと、kisのloadコマンドやsaveコマンドを使うときにエラい目にあう可能性がある
  • これについては別のところでいずれ
 

華和梨・自作におけるセキュリティ施工

  • 華和梨に慣れてきたら考えておきたいセキュリティの話
  • 慣れるまで触れなくていいよ!
  • これは華和梨に限った話ではなく、様々な栞が該当
 

概説

上のURLから要点を抜粋

  • 悪意ある攻撃スクリプト、例えばreference値にさくらスクリプト等を含ませおき、受け取ったゴーストがreference値を参照すると、送信側が任意のさくらスクリプトを実行する事ができるので非常に危険(open,browserを実行させ、危険なサイトへ飛ばす等)。それらの防御策
  • 1.setコマンド等で${System.Request.Reference*}の内容を使わない
    • setstrやpushstrなど「str」のついた、文字列として扱うコマンドを使う
  • 2.debuggerコマンドでonを指定したものを外しておく
    • 配布用アーカイブではonにしたままにしないようにする
    • debuggerコマンドを使っていない場合は問題なし
  • 3.大事なエントリは保護しておく
    • 万が一に備え、writeprotectコマンドを使ってエントリの変更を禁止する
      • 各種栞イベント全部
      • 各種resource全部(特に重要なのはネットワーク更新URLであるhomeurl)
      • 各種notifyイベント全部
  • 4.危険なさくらスクリプトタグを通さない
    • ${System.Request.Reference*}をすぐに参照せず、内容を先にチェックし、危険なタグが含まれていればそれを無害化してから渡す
 

以下、順番に、具体的なセキュリティの施工方法

 

1.setコマンド等で${System.Request.Reference*}の内容を使わない

 

2.debuggerコマンドでonを指定したものを外しておく

 

3.大事なエントリは保護しておく

  • writeprotectコマンドを使ってエントリの変更を禁止
  • 保護すべきエントリは究極的には「変数でない、起動中に変更したりする事のないエントリ全て」。イベントはもちろんあらゆるトークも保護すべき
  • つーても一つ一つに全てかける事は大変な手間なわけで、いちいち仕込んだら不便すぎる
  • よって、さっくり楽に全部保護するためにエントリの書き方を工夫する
 
  • 準備。これまで使っていたkawarirc.kisのSystem.Callbackのところをちょいと書き換える
# 横に長くなるのを防ぐため可能な限り改行してますが1行にまとめもOK

System.Callback.OnGET    : $(
	setstr @temp ${System.Request.ID} ;
		entry "event."${@temp} $(
		entry "resource."${@temp})
)
System.Callback.OnNOTIFY : $(
	setstr @temp ${System.Request.ID} ;
		entry "notify."${@temp}
)

上のを順番に追ってみると…

  • System.Callback.OnGETエントリ
    • まず@tempエントリに${System.Request.ID}、=イベント名などを保存
    • 次に【event.イベント名】というエントリを呼ぶ
    • 存在しない(又は中身が空)の場合は代わりに【resource.イベント名】を呼ぶ
    • これも存在しなければ無視
  • System.Callback.OnNOTIFYエントリ
    • まず@tempエントリに${System.Request.ID}、つまりイベント名などを保存
    • 次に【notify.イベント名】というエントリを呼ぶ
    • 存在しなければ無視

具体例を挙げると、「OnBoot」が通知された際、【event.OnBoot】エントリを呼ぶようになる。 これまではイベント名そのままのエントリ名を参照していたので、全て【event.OnClose】のように 頭にevent.とかついたエントリ名へ書き換えなければならない

 
  • このようにしたら解説ページのソースをまるごとコピー
#kawarirc.kisの最後に、以下を追加する
=kis
listtree @ToProtect System.Callback;
listtree @ToProtect event;
listtree @ToProtect resource;
listtree @ToProtect notify;
foreach @i @ToProtect $(writeprotect ${@i});
=end
  • 上の動作をぶっちゃけると、
    • System.Callback.で始まるエントリ名
    • event.で始まるエントリ名
    • resource.で始まるエントリ名
    • notify.で始まるエントリ名
  • 以上のエントリを一気にすべて保護する、というもの。すなわち、栞イベントに対応するために書いていたevent.OnBootやresource.homeurlをまとめて保護してくれる
  • どうでもいいけど System.Callback.系のエントリを上のように改造すると、 event.OnBoot と書かずに resource.OnBoot と書いたり、resource.homeurl と書かずに event.homeurl と書いても通っちゃうものの、特に弊害はないと思うので放置推奨
  • 気になる人は全イベント列挙するなり。。。でも手間ばかりかかって現実的じゃないような気が
 

4.危険なさくらスクリプトタグを通さない

  • ちょっと長いけど解説ページのソースをそのまま辞書のどこかに貼り付ける
=kis
# 外部SSTPに存在した場合、危険なタグを無害化
# 第1引数: 文字列
# 戻り値:  タグを無害化した文字列
function KillDangerousTag $(
	if $[ $(size @arg) != 2 ] $(return);
	setstr @string $@arg[1];
	foreach @tag kp.dangeroustag $(
		# 無害化したタグを生成
		setstr @killedtag " _"$(substr ${@tag} 2);
		setstr @pos $(match ${@string} ${@tag});
		# 危険タグが存在したら、無害化したタグに置換
		if $[ ${@pos} != -1 ] $(
		setstr @string $(gsub ${@string} ${@tag} ${@killedtag});
		);
	);
	return ${@string};
);
=end

# KillDangerousTag内部で参照している危険なタグのリスト
# 必ず2文字以上からなるタグを書くこと
	kp.dangeroustag (
	"\\![updatebymyself]",
	"\\![vanishbymyself]",
	"\\![enter,passivemode]",
	"\\![leave,passivemode]",
	"\\![lock,repaint]",
	"\\![unlock,repaint]",
	"\\![biff]",
	"\\![open,browser",
	"\\![open,mailer",
	"\\![raise",
	"\\j["
)

# タグリストが消されて無効化されないよう、エントリを保護
=kis
writeprotect kp.dangeroustag;
=end

=kis
# Reference*参照
# 第1引数: Reference番号
# 戻り値:  Reference*の内容
function Reference $(get System.Request.Reference$@arg[1][0]);

# 危険なさくらスクリプトタグを無害化した上でReference*参照
# 第1引数: Reference番号
# 戻り値:  危険なさくらスクリプトタグをを無害化したReference*の内容
function SReference $(KillDangerousTag $(Reference $@arg[1]));
=end
  • 貼り付けたら、以後、${System.Request.Reference*}の値はこのエントリを使わず、$(SReference *)のように記述するようにする
event.OnCommunicate : (
	\1\s[10]
	\0\s[0]
	$(SReference 0)が何か言ってるね。\w8\w8\n
	とりあえず無視しておこっと。\w8\w8
	\1危なそうだしな。\w8\w8
	\e
)
  • 解説ページにある例だとこう。でもここまでのゴースト制作に習うなら、
R0 : $(SReference 0)
R1 : $(SReference 1)
R2 : $(SReference 2)
R3 : $(SReference 3)
R4 : $(SReference 4)
R5 : $(SReference 5)
R6 : $(SReference 6)
R7 : $(SReference 7)
R8 : $(SReference 8)
R9 : $(SReference 9)
  • こうしておけばセキュリティ施工済みのリファレンス値を${R0}などで呼び出せる
  • 華和梨って便利だと思わんかね
 

kawarirc.kisに書くこと最終まとめ例

  • 長いので別の辞書にしてloadしても良い
  • ただし、エントリ保護だけはkawarirc.kisの最後に書くか、エントリ保護を記述した辞書をkawarirc.kisの文末でload
System.Callback.OnGET    : $(
	setstr @temp ${System.Request.ID} ;
		entry "event."${@temp} $(
		entry "resource."${@temp})
)
System.Callback.OnNOTIFY : $(
	setstr @temp ${System.Request.ID} ;
		entry "notify."${@temp}
)

=kis
	# 華和梨辞書。自分の好きな辞書ファイルを作り、登録しましょう
	load dic01_Base.txt ;
	load dic02_Event.txt ;
=end

R0 : $(SReference 0)
R1 : $(SReference 1)
R2 : $(SReference 2)
R3 : $(SReference 3)
R4 : $(SReference 4)
R5 : $(SReference 5)
R6 : $(SReference 6)
R7 : $(SReference 7)
R8 : $(SReference 8)
R9 : $(SReference 9)

resource.homeurl : "http://~"

event.OnChoiceSelect : $(entry ${R0})\e

event.OnBoot  : \1\s[10]\0\s[0]やあ。\w9\w9\e
event.OnClose : \1\s[10]\0\s[0]うい。\w9\w9\-

=kis
# 外部SSTPに存在した場合、危険なタグを無害化
# 第1引数: 文字列
# 戻り値:  タグを無害化した文字列
function KillDangerousTag $(
	if $[ $(size @arg) != 2 ] $(return);
	setstr @string $@arg[1];
	foreach @tag kp.dangeroustag $(
		# 無害化したタグを生成
		setstr @killedtag " _"$(substr ${@tag} 2);
		setstr @pos $(match ${@string} ${@tag});
		# 危険タグが存在したら、無害化したタグに置換
		if $[ ${@pos} != -1 ] $(
		setstr @string $(gsub ${@string} ${@tag} ${@killedtag});
		);
	);
	return ${@string};
);
=end

# KillDangerousTag内部で参照している危険なタグのリスト
# 必ず2文字以上からなるタグを書くこと
	kp.dangeroustag (
	"\\![updatebymyself]",
	"\\![vanishbymyself]",
	"\\![enter,passivemode]",
	"\\![leave,passivemode]",
	"\\![lock,repaint]",
	"\\![unlock,repaint]",
	"\\![biff]",
	"\\![open,browser",
	"\\![open,mailer",
	"\\![raise",
	"\\j["
)

# タグリストが消されて無効化されないよう、エントリを保護
=kis
writeprotect kp.dangeroustag;
=end

=kis
# Reference*参照
# 第1引数: Reference番号
# 戻り値:  Reference*の内容
function Reference $(get System.Request.Reference$@arg[1][0]);

# 危険なさくらスクリプトタグを無害化した上でReference*参照
# 第1引数: Reference番号
# 戻り値:  危険なさくらスクリプトタグをを無害化したReference*の内容
function SReference $(KillDangerousTag $(Reference $@arg[1]));
=end

#kawarirc.kisの最後に、以下を追加する
=kis
listtree @ToProtect System.Callback;
listtree @ToProtect event;
listtree @ToProtect resource;
listtree @ToProtect notify;
foreach @i @ToProtect $(writeprotect ${@i});
=end
  • さあこれで華和梨ゴーストを作る基本は出来た
 

続き→ らくだ屋/里々から華和梨への移行ガイド・SHIORI Event実装編


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-05-15 (火) 19:09:52