execute 型
用語に注意
- まずは用語に注意することを覚えてください。
- プラグインには exeute 型と plugin 型があります。
- プログラム実行の基本単位は execute 型プラグインで、これを execute と呼びます。
- ウェブの各ページは execute の結果出力されます。
- execute 型プラグインは execute 名で呼ばれる一連の処理を扱います。
- execute 型プラグインは、自己診断処理, execute 処理, 後処理を実施します。
execute の役割
- わかりやすく言うと、ブラウザに示される各ページが execute です。
- execute 型プラグインはページ特有の処理 (execute) を行い、必要に応じて plugin 型プラグインの実行を行います。
- 個々の execute においては execute 型プラグインが主体となって重要な処理を行い、plugin 型プラグインはその補助的な処理を行います。
- plugin 型プラグインが担う補助的な役割は主にスキン部品部分の作成です。
- execute 型プラグインも plugin 型プラグインも共にスキンを要求します。
- execute 型プラグインはウェブ表示全体のレイアウトを指定するスキンを要求します。
- それに対し、plugin 型プラグインは部品となるスキンを要求します。
- plugin 型プラグインにより取得されたスキンは execute 型プラグインにより取得されたスキンに挿入される形になります。
処理の準備
- 処理の準備は基本エンジン (コントローラ) が行います。
- コントローラはリクエストによって実行すべき execute 名を受け取ります。
- 受け取るリクエストは例えば以下のようになります。
main.cgi?execute=admin_gate
- リクエストによって execute が指示されなかった場合、規定値が適用されます。
- 規定値は以下に設定されています。
$config->{default}{execute_type}
- $config->{default}{execute_type} を設定しているファイルは以下の通りです。
[Apache_server]
└ [cgi-bin]
└ [config]
└ [admin]
└ config_basic.pl
- リクエストの内容は捏造が可能であるため、コントローラはリクエストされた execute が許可されているかをチェックします。
- 許可されている execute のリストは以下の通りです。
- カスタマイズによって新規に execute を作成する場合はリストに execute 名を追記しなければなりません。
$config->{list}{execute_type}
- $config->{list}{execute_type} を設定しているファイルは以下の通りです。
[Apache_server]
└ [cgi-bin]
└ [config]
└ [admin]
└ config_basic.pl
- execute が許可されていない場合は規定値に差し替えられます。
呼び出し
- コントローラは exeucte 型プラグインを require によって呼び出します。
- 呼び出すファイル名は、execute/exe_ + exeute 名 + .pl となります。
- ececute 名が user_inquiry_step1 である場合、以下のようになります。
execute/exe_user_inquiry_step1.pl
package 名
- execute 型プラグインは package を宣言しなければなりません。
- 宣言する package 名は、Execute_ + exeute 名となります。
- ececute 名が user_inquiry_step1 である場合、以下のようになります。
################################################################################
# #
# CAFEMILK SHOPPING CART V5 #
# SOHO WORKSHOP CAFEMILK 全権留保 #
# #
################################################################################
use strict;
# use warnings;
use utf8;
# use encoding "utf8";
package Execute_user_inquiry_step1;
自己診断処理
- もしくは execute の前処理 (用語注意 ex.コントローラの前処理)
- リクエストされる execute は実行すべきでないことがあります。
- たとえば、管理機能にかかわる execute に一般のユーザーがアクセスしようとした場合、execute は実行されるべきではありません。
- あるいは、ユーザーの入力内容に間違いがあったときに、もう一度入力フォームをユーザーに提示する必要があるかもしれません。
- このようなとき、自己診断処理は execute 名を差し替えることができます。
- execute の自己診断と差し替えは一度だけ認められています。
- つまり、差し替えられた execute の自己診断はスキップされます。
- 以下は自己診断処理の例です。
- 管理者ログイン済みでないユーザーを排除する場合。
sub check
{
my $package = shift;
my $argument = shift;
my $config = $argument->{config};
my $userdata = $argument->{userdata};
my $log_error = $argument->{log_error};
my $log_alert = $argument->{log_alert};
my $status = $argument->{status};
上の 7 行はコーディングルールによって義務づけられた各種情報の格納処理です。
管理者ログインが無効であるか、あるいは管理者管理権眼がない場合にアクセスを排除。
if ((!$status->{login}{admin} )
or (!$userdata->{admin_registry_values}{manage_admin}))
{
$userdata->{request_values}{execute}[0] = 'admin_gate';
}
}
- 会員機能がメンテナンス状態であるときに会員関連の手続をキャンセルする場合。
sub check
{
my $package = shift;
my $argument = shift;
my $config = $argument->{config};
my $userdata = $argument->{userdata};
my $log_error = $argument->{log_error};
my $log_alert = $argument->{log_alert};
my $status = $argument->{status};
メンテナンス中はトップページへ移動。
if (($status->{shop_mode} eq '1')
or ($status->{shop_mode} eq '3'))
{
$userdata->{request_values}{execute}[0] = 'home';
}
}
- 他の処理に転用されている場合。
- カート関連の集計は各処理に先だって行っておく必要がある。
- カート関連の処理はユーザーによる配送先都道府県や決済方法等の選択によって変更する必要がある。
- カート関連の処理はフレームワーク化されているのでほとんどの処理はサブルーチンを呼び出すだけで適切に実施されます。
sub check
{
my $package = shift;
my $argument = shift;
my $config = $argument->{config};
my $userdata = $argument->{userdata};
my $log_error = $argument->{log_error};
my $log_alert = $argument->{log_alert};
my $status = $argument->{status};
メンテナンス時にはカート処理をさせない
if (($status->{shop_mode} eq '2')
or ($status->{shop_mode} eq '3'))
{
$userdata->{request_values}{execute}[0] = 'home';
}
else
{
Cafemilk_basic::get_cart
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
コーディングルールにより %input_values にリクエストされた各情報を格納
my %input_values;
my @list =
qw(
process input_point input_ship_prefecture input_payment
);
foreach (@list)
{
$input_values{$_} = $userdata->{request_values}{$_}[0];
}
ポイント更新処理
if ($input_values{process} eq 'point')
{
my $point = $input_values{input_point};
$point =~ s/1/1/g;
$point =~ s/2/2/g;
$point =~ s/3/3/g;
$point =~ s/4/4/g;
$point =~ s/5/5/g;
$point =~ s/6/6/g;
$point =~ s/7/7/g;
$point =~ s/8/8/g;
$point =~ s/9/9/g;
$point =~ s/0/0/g;
if ($point !~ /[^0-9]/)
{
$userdata->{cart}{point} = $point;
Cafemilk_basic::make_cart_data_session
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_session::user_postscript
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart_point
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart_grandtotal
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
}
}
送料更新処理
if ($input_values{process} eq 'prefecture')
{
my $prefecture = $input_values{input_ship_prefecture};
if (($prefecture !~ /[^0-9]/ )
and ($prefecture > 0 )
and ($prefecture <= $#{$config->{mailing}{prefecture_cost}}))
{
$userdata->{cart}{ship_prefecture} = $prefecture;
Cafemilk_basic::make_cart_data_session
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_session::user_postscript
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart_mailing_cost
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart_grandtotal
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
}
}
決済手数料更新処理
if ($input_values{process} eq 'payment')
{
my $payment = $input_values{input_payment};
if ($payment !~ /[^0-9a-zA-Z_]/)
{
$userdata->{cart}{payment} = $payment;
Cafemilk_basic::make_cart_data_session
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_session::user_postscript
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart_payment_cost
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::check_cart_grandtotal
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
}
}
}
}
execute 処理
- execute 型プラグインの execute 処理です。(用語注意)
- execute 処理が execute における中核的な処理となります。
- execute 処理では、コントローラ (基本エンジン) がテンプレートコントローラを実行する準備として以下の情報を必ず用意しなければなりません。
$userdata->{path}{cgi}..... : スキン (テンプレート) のパス
$userdata->{path}{css}..... : スタイルシートのパス
$userdata->{path}{material} : 画像等ファイルのパス
$userdata->{robots_permit}. : ロボット制御タグの値
- また、テンプレートにて外部 JAVASCRIPT の使用がある場合には以下の情報を必ず用意しなければなりません。
$userdata->{path}{js} : 外部 JAVASCRIPT のディレクトリへのパス
- 一般的に execute 型プラグインの execute 処理は、実行が許可される plugin 型プラグインの設定値に execute 固有の plugin を追記します。
$config->{list}{plugin} : 許可される plugin 型プラグインのリスト
- 以上の情報は、ソース中ではこのように表記されています。
# [STEP1] SET PATH
- execute 固有の処理は、ソース中ではこのように表記されています。
# [STEP2] PROCESS
sub execute
{
コーディングルールによって義務づけられた各種情報の格納処理
my $package = shift;
my $argument = shift;
my $config = $argument->{config};
my $userdata = $argument->{userdata};
my $log_error = $argument->{log_error};
my $log_alert = $argument->{log_alert};
my $status = $argument->{status};
必要な情報の用意
# [STEP1] SET PATH
my $path_cgi = "./$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/exe_user_inquiry_step1.html";
my $path_css = "$config->{path}{cgi_to_html}$config->{path}{common}$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/$config->{filename}{admin}{css}";
my $path_material = "$config->{path}{cgi_to_html}$config->{path}{common}$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/";
my $path_js = "$config->{path}{cgi_to_html}$config->{path}{common}$config->{path}{skin}/js/";
my $robot = 'noindex,follow';
$userdata->{path}{cgi} = $path_cgi;
$userdata->{path}{css} = $path_css;
$userdata->{path}{material} = $path_material;
$userdata->{path}{js} = $path_js;
$userdata->{robots_permit} = $robot;
固有の plugin 型プラグインの追記
my @list =
qw(
user_inquiry_step1
);
push (@{$config->{list}{plugin}},@list);
固有の処理
# [STEP2] PROCESS
# none
}
- フォームからの入力情報のチェックをする場合。
- 各種処理がフレームワーク化されているので、それらの処理はサブルーチンを呼び出すだけで適切に実施されます。
sub execute
{
コーディングルールによって義務づけられた各種情報の格納処理
my $package = shift;
my $argument = shift;
my $config = $argument->{config};
my $userdata = $argument->{userdata};
my $log_error = $argument->{log_error};
my $log_alert = $argument->{log_alert};
my $status = $argument->{status};
必要な情報の用意
# [STEP1] SET PATH
my $path_cgi = "./$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/exe_user_inquiry_step2.html";
my $path_css = "$config->{path}{cgi_to_html}$config->{path}{common}$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/$config->{filename}{admin}{css}";
my $path_material = "$config->{path}{cgi_to_html}$config->{path}{common}$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/";
my $robot = 'noindex,follow';
$userdata->{path}{cgi} = $path_cgi;
$userdata->{path}{css} = $path_css;
$userdata->{path}{material} = $path_material;
$userdata->{robots_permit} = $robot;
固有の plugin 型プラグインの追記
my @list =
qw(
user_inquiry_step2
);
push (@{$config->{list}{plugin}},@list);
以下は固有の処理
# [STEP2] PROCESS
WORDLIST 型スキンを呼び出し
my @word_list = Cafemilk_basic::get_wordlist
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
filename => "./$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/list_input_status.txt",
});
入力チェック用の正規表現の取得
my $regular_expression_email_a = $config->{regular_expression}{email_a};
my $regular_expression_phone_a = $config->{regular_expression}{phone_a};
コーディングルールにより %input_values にリクエストされた各情報を格納
my %input_values;
my @list =
qw(
input_1_email_1 input_1_email_2 input_inquiry
);
foreach (@list)
{
$input_values{$_} = $userdata->{request_values}{$_}[0];
}
個別の入力チェックの結果 $status->{input_match}{$key} を初期化
foreach (@list)
{
$status->{input_match}{$_} = 1;
}
入力チェック開始
不正な入力があると $status->{input_match}{$key} = 0 に
# input_1_email_1 ( input_1_email_1 & input_1_email_2 )
my $temp_value = $input_values{input_1_email_1};
$temp_value = Encode::encode('utf8',$temp_value);
$temp_value = Encode::decode('euc-jp',$temp_value);
if ($input_values{input_1_email_1} eq "")
{
$status->{input_match}{input_1_email_1} = 0;
$status->{input_message}{error_1_email_1} = $word_list[1];
}
elsif ($temp_value !~ /^$regular_expression_email_a$/)
{
$status->{input_match}{input_1_email_1} = 0;
$status->{input_message}{error_1_email_1} = $word_list[0];
}
elsif ($input_values{input_1_email_1} ne $input_values{input_1_email_2})
{
$status->{input_match}{input_1_email_1} = 0;
$status->{input_message}{error_1_email_1} = $word_list[5];
}
# input_inquiry
if ($input_values{input_inquiry} eq "")
{
$status->{input_match}{input_inquiry} = 0;
$status->{input_message}{error_inquiry} = $word_list[1];
}
総合の入力チェックの結果 $status->{input_next} を初期化
# input_next
$status->{input_next} = 1;
総合の入力チェック
不正な入力があると $status->{input_next} = 0 に
my @list =
qw(
input_1_email_1 input_inquiry
);
foreach (@list)
{
my $list = $_;
if (!$status->{input_match}{$list})
{
$status->{input_next} = 0;
last;
}
}
総合の入力チェックが合格なら
if ($status->{input_next})
{
次の手続では guest ログイン以上のログイン状態が要求されるので
ユーザーのログイン状態をチェックして未ログインなら guest ログインにする
if ($userdata->{user_type} eq $config->{default}{user_type})
{
Cafemilk_session::user_make_guest
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_basic::make_cart_data_session
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
Cafemilk_session::user_postscript
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
});
}
次の手続では CSRF 攻撃への予防処置が必要なので
実行リクエスト保護多重セッション (user 用) の予約を行う
($userdata->{execute_key}{1},$userdata->{execute_key}{2},
$userdata->{execute_key}{3},$userdata->{execute_key}{4})
= Cafemilk_session::set_execute_session_user
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
execute_key => 'user_inquiry_step3',
});
}
}
後処理
- 後処理は仕様として存在するだけで、用いられていません。
sub post_process
{
# none
}
テンプレート処理
- execute の HTML テンプレート処理は基本エンジン (コントローラ) が肩代わりするので、execute 型プラグインにコードを書く必要はありません。
- execute がメール送信をする場合、MAIL テンプレートの処理を書く必要があります。
- 以下はメール送信処理の例 (一部)。
- テンプレート処理やメール送信処理はフレームワーク化されているので、それらの処理はサブルーチンを呼び出すだけで適切に実施されます。
実行リクエスト保護多重セッション (user 用) の検証を行う
有効なら $status->{input_execute} = 1 となる
# session
$status->{input_execute} = Cafemilk_session::check_execute_session_user
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
key_1 => $userdata->{request_values}{key_1}[0],
key_2 => $userdata->{request_values}{key_2}[0],
execute_key => 'user_inquiry_step3',
clear => 1,
});
総合の入力チェックの結果 $status->{input_next} を初期化
# input_next
$status->{input_next} = 1;
総合の入力チェック
不正な入力があると $status->{input_next} = 0 に
my @list =
qw(
input_1_email_1 input_inquiry
);
foreach (@list)
{
my $list = $_;
if (!$status->{input_match}{$list})
{
$status->{input_next} = 0;
last;
}
}
総合の入力チェックと実行リクエスト保護が合格なら
if (($status->{input_next})
and ($status->{input_execute}))
{
処理の実施を記録
$status->{execute_success} = 1;
コーディングルールにより %input_values にリクエストされた各情報を格納
my @list =
qw(
input_1_email_1 input_inquiry
);
foreach (@list)
{
$input_values{$_} = $userdata->{request_values}{$_}[0];
}
同じくコーディングルールにより $userdata->{tag_data} に MAIL テンプレート用の各情報を格納
foreach (keys %input_values)
{
$userdata->{tag_data}{temporal}{$_} = $input_values{$_};
}
MAIL テンプレートエンジンの使用にあたって処理名を準備
my $mail_name = 'user_inquiry_step3_shop';
MAIL テンプレートエンジンで使用するスキンのパスを準備
my $path = "./$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/mail_user_inquiry_step3_shop.txt";
MAIL テンプレートエンジンのオブジェクトを作成
my $skin = Cafemilk_skin_mail->new
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
name => $mail_name,
});
スキンの読み込み
$skin->set_path($path);
スキン内の MAIL MIDDLE テンプレートタグを読み込む
$skin->load_tag_middle();
許可された MAIL テンプレートタグ名の取得
my @list = @{$config->{list}{tag}{mail}};
許可されたリストに基づいて MAIL MIDDLE テンプレートタグを処理する
$skin->replace_tag_middle
({
allow => \@list,
package => "Cafemilk_tag_mail",
});
# undef $userdata->{tag_data}{temporal};
MAIL テンプレートの結果を取得
my $source = $skin->get_source();
メール送信
foreach (@{$config->{sendmail}{address}{shop}{to}})
{
my $from = $input_values{input_1_email_1};
my $to = $_;
my $cc = '';
my $bcc = '';
my $return = $config->{sendmail}{address}{shop}{return}[0];
Cafemilk_mail::skin_sendmail
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
from => $from,
to => $to,
cc => $cc,
bcc => $bcc,
source => $source,
return => $return,
});
}
以下はほぼ同じ処理を繰り返し
my $mail_name = 'user_inquiry_step3_user';
my $path = "./$config->{path}{skin}/user/cgi/$config->{default}{user_type}/$userdata->{device_type}/$userdata->{language_type}/$userdata->{currency_type}/$userdata->{template_type}/mail_user_inquiry_step3_user.txt";
my $skin = Cafemilk_skin_mail->new
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
name => $mail_name,
});
$skin->set_path($path);
$skin->load_tag_middle();
my @list = @{$config->{list}{tag}{mail}};
$skin->replace_tag_middle
({
allow => \@list,
package => "Cafemilk_tag_mail",
});
コーディングルールにしたがい $userdata->{tag_data}{temporal} は内容をクリア
undef $userdata->{tag_data}{temporal};
my $source = $skin->get_source();
my $from = $config->{sendmail}{address}{shop}{from}[0];
my $to = $input_values{input_1_email_1};
my $cc = '';
my $bcc = '';
my $return = $config->{sendmail}{address}{shop}{return}[0];
Cafemilk_mail::skin_sendmail
({
config => $config,
userdata => $userdata,
log_error => $log_error,
log_alert => $log_alert,
status => $status,
from => $from,
to => $to,
cc => $cc,
bcc => $bcc,
source => $source,
return => $return,
});
}
- 以上の例では、MAIL テンプレートエンジンの処理は部分的に実施されています。
- ここでタグの取得と処理が行われているのは MIDDLE テンプレートタグのみです。
- タグはプラグインタグとテンプレートタグ、それぞれに HIGH, MIDDLE, LOW がありますから、その一部しか活用していないことになります。
- MAIL テンプレート処理では plugin 型プラグインの使用が可能です。
最終更新:2009年09月21日 19:49