Commit 2b6c3110 authored by Antonio.Suerte's avatar Antonio.Suerte

Domain Whitelisting Feature

parent f912d780
This diff is collapsed.
<?php
<?php
require_once(SITE_LOGICS . 'settlement/config.php');
class SettlementModelClass extends ModelClassEx {
......@@ -238,10 +238,22 @@ class SettlementModelClass extends ModelClassEx {
return false;
}
$domWhitelistedDisabled = false;
// APIの確認
if(!$this -> checkSettlementIpAddress($this -> pNum)) {
$this -> popUpSessionMessage(ERROR, 'E_ERROR_IP_ADDRESS', array());
$rtn = false;
if(!$this -> checkSettlementDomain($this -> pNum, "allow_domain_in_payment", $domWhitelistedDisabled)){
if(!$domWhitelistedDisabled){
$this -> popUpSessionMessage(ERROR, 'E_ERROR_DOMAIN', array());
$rtn = false;
}
}
$ipWhitelistDisabled = false;
// APIの確認
if(!$this -> checkSettlementIpAddress($this -> pNum, "allow_ip_in_payment", $ipWhitelistDisabled)) {
if(!$ipWhitelistDisabled){
$this -> popUpSessionMessage(ERROR, 'E_ERROR_IP_ADDRESS', array());
$rtn = false;
}
}
// シグネチャのチェック
......@@ -588,7 +600,7 @@ class SettlementModelClass extends ModelClassEx {
}
function getAgentCodeURL(){
$baseUrl = 'https://secure.'.SITE_DOMAIN.'/'. $this -> getLangage() .'/register';
$baseUrl = 'https://'.SITE_DOMAIN_FULL.'/'. $this -> getLangage() .'/register';
if(!empty($this -> pNum)){
$rowData = $this -> getRowData($this -> accessSelect('SELECT_AGENT_CODE_BY_AID', array($this -> pNum)));
$AgentCode = $this -> getColumnData($rowData, COLUMN_AGENT_CODE);
......
......@@ -31,9 +31,7 @@ include_once('template/base_head.php');
</tr>
<tr>
<th>Name</th>
<td>
<?php $this -> echoLastName(); ?> <?php $this -> echoFirstName(); ?>
</td>
<td><?php $this -> echoLastName(); ?> <?php $this -> echoFirstName(); ?></td>
</tr>
<tr>
<th>API Signature</th>
......@@ -47,6 +45,14 @@ include_once('template/base_head.php');
<th>IP Address</th>
<td><?php $this -> echoIpAddress(); ?></td>
</tr>
<tr>
<th>Domain Name</th>
<td><?php $this -> echoDomainName(); ?></td>
</tr>
<tr>
<th>Validation Settings</th>
<td><?php $this -> echoWhitelistSettingsCheckboxes(true); ?></td>
</tr>
</table>
<input type="hidden" value="action" id="type" name="type" />
......@@ -54,6 +60,7 @@ include_once('template/base_head.php');
<input type="hidden" value="<?php $this -> echoUserName(); ?>" id="user_name" name="user_name" />
<input type="hidden" value="<?php $this -> echoPassword(); ?>" id="password" name="password" />
<input type="hidden" value="<?php $this -> echoIpAddress(); ?>" id="ip_address" name="ip_address" />
<input type="hidden" value="<?php $this -> echoDomainName(); ?>" id="domain_name" name="domain_name" />
<!-- Language Transition Data (Anton) 04/23/2016 -->
<input class="lang-trans-data" type="hidden" id="lang_data_action" value="/api_signature"/>
......
......@@ -52,7 +52,19 @@ include_once('template/base_head.php');
<tr>
<th>IP Address</th>
<td>
<input type="text" id="ip_address" name="ip_address" value="<?php $this -> echoIpAddress(); ?>" class="w30p">
<textarea id="ip_address" name="ip_address" rows="10" cols="50"><?php $this -> echoIpAddress(); ?></textarea>
</td>
</tr>
<tr>
<th>Domain Name</th>
<td>
<textarea id="domain_name" name="domain_name" rows="10" cols="50"><?php $this -> echoDomainName(); ?></textarea>
</td>
</tr>
<tr>
<th>Validation Settings</th>
<td>
<?php $this -> echoWhitelistSettingsCheckboxes(); ?>
</td>
</tr>
</table>
......
......@@ -53,7 +53,19 @@ include_once('template/base_head.php');
<tr>
<th>IP Address</th>
<td>
<input type="text" id="ip_address" name="ip_address" value="<?php $this -> echoIpAddress(); ?>" class="w30p">
<textarea id="ip_address" name="ip_address" rows="10" cols="50"><?php $this -> echoIpAddress(); ?></textarea>
</td>
</tr>
<tr>
<th>Domain Name</th>
<td>
<textarea id="domain_name" name="domain_name" rows="10" cols="50"><?php $this -> echoDomainName(); ?></textarea>
</td>
</tr>
<tr>
<th>Validation Settings</th>
<td>
<?php $this -> echoWhitelistSettingsCheckboxes(); ?>
</td>
</tr>
</table>
......
......@@ -17,6 +17,7 @@ $(function() {
});
$('#btnComplete').click(function() {
$(".wl-set-cbox").prop("disabled", false)
$('#type').val('complete');
submitForm();
});
......@@ -56,6 +57,12 @@ function actionDelete(){
}
function actionInput(){
$(".wl-set-cbox").prop("disabled", false)
$('#type').val('input');
submitForm();
}
/**
* データ修正
*/
......
......@@ -1469,27 +1469,23 @@ class Checker extends Chiket {
* @parameter : 番組コード
* @return : 成功:TRUE、失敗:FALSE
-------------------------------------------------------------------------*/
function checkSettlementIpAddress($pnum) {
function checkSettlementIpAddress($pnum, $validationProperty, &$isDisabled = false) {
// 変数宣言部
$rtn = true;
$row = null;
$ip = NO_STRING;
$connecter = NO_STRING;
// シグネチャ生成用のデータを取得する
$row = $this -> getRowData($this -> accessSelect('SELECT_API_SIGNATURE_BY_A_ID', array($pnum)));
$ip = $this -> getColumnData($row, COLUMN_IP_ADDRESS);
$ips = explode(DELIMIT_COMMA, $ip);
$row = $this -> getRowData($this -> accessSelect('SELECT_API_SIGNATURE_BY_A_ID', array($pnum)));
$ip = $this -> getColumnData($row, COLUMN_IP_ADDRESS);
$allowSet = $this -> getColumnData($row, COLUMN_WHITELIST_SETTING);
$ips = explode(DELIMIT_COMMA, $ip);
//error_log paths
$logPath = SYSTEM_PATH.DIRECTORY_SEPARATOR.'documents'.DIRECTORY_SEPARATOR.'error_log';
$serverLogPath = $logPath.DIRECTORY_SEPARATOR.'Visitor_server_params';
//check if directory exists if not, create directory
if(!file_exists($serverLogPath)) {
if(!file_exists($serverLogPath))
mkdir($serverLogPath, 0777, true);
}
//log the transaction details
error_log(date("[Y-m-d H:i:s]")."\r\n".print_r($_SERVER,true)."\r\n", 3, $serverLogPath.DIRECTORY_SEPARATOR.'Log_'.date("Y-m-d").'.log');
......@@ -1500,34 +1496,102 @@ class Checker extends Chiket {
// リファラがなければ、エラー
if($connecter == NO_STRING) { // リファラなし
$connecter = $this -> getColumnData($_SERVER, 'REMOTE_ADDR');
if($connecter == NO_STRING) {
if($connecter == NO_STRING)
return false;
}
} else { // リファラあり
$connecter = parse_url($connecter);
$connecter = gethostbyname($this -> getColumnData($connecter, PARAM_HOST));
}
// IPアドレスのチェック(複数設定対応)
if($this -> isLoopData($ips)) {
$rtn = false;
foreach($ips as $ip) {
if($connecter == $ip) {
$rtn = true;
break;
}
}
} else {
$rtn = false;
}
$rtn = false;
if($this -> checkJSONString($allowSet)){
$allowSet = json_decode($allowSet);
if(isset($allowSet -> {$validationProperty})){
if($allowSet -> {$validationProperty}){
if($this -> isLoopData($ips))
$rtn = in_array($connecter, $ips);
}else
$isDisabled = ["exception" => "The {$validationProperty} setting is disabled"];
}else{
switch($validationProperty){
case "mandatory":
if($this -> isLoopData($ips))
$rtn = in_array($connecter, $ips);
break;
default:
$isDisabled = ["exception" => "Invalid Validation Property"];
break;
}
}
}else
$isDisabled = ["exception" => "Invalid Setting Data"];
return $rtn;
}
/*-------------------------------------------------------------------------
* @function_name: Domainのチェック
* @parameter : 番組コード
* @return : 成功:TRUE、失敗:FALSE
-------------------------------------------------------------------------*/
function checkSettlementDomain($pnum, $validationProperty, &$isDisabled = false) {
// 変数宣言部
$rtn = true;
// シグネチャ生成用のデータを取得する
$row = $this -> getRowData($this -> accessSelect('SELECT_API_SIGNATURE_BY_A_ID', array($pnum)));
$domain = $this -> getColumnData($row, COLUMN_DOMAINS);
$allowSet = $this -> getColumnData($row, COLUMN_WHITELIST_SETTING);
$domains = explode(DELIMIT_COMMA, $domain);
//error_log paths
$logPath = SYSTEM_PATH.DIRECTORY_SEPARATOR.'documents'.DIRECTORY_SEPARATOR.'error_log';
$serverLogPath = $logPath.DIRECTORY_SEPARATOR.'Visitor_server_params';
//check if directory exists if not, create directory
if(!file_exists($serverLogPath))
mkdir($serverLogPath, 0777, true);
//log the transaction details
error_log(date("[Y-m-d H:i:s]")."\r\n".print_r($_SERVER,true)."\r\n", 3, $serverLogPath.DIRECTORY_SEPARATOR.'Log_'.date("Y-m-d").'.log');
chmod($serverLogPath.DIRECTORY_SEPARATOR.'Log_'.date("Y-m-d").'.log',511);
// 接続IPアドレス
$connecter = $this -> getColumnData($_SERVER, PARAM_HTTP_REFERER);
// リファラがなければ、エラー
if($connecter == NO_STRING) { // リファラなし
$connecter = $this -> getColumnData($_SERVER, 'REMOTE_ADDR');
if($connecter == NO_STRING)
return false;
} else { // リファラあり
$connecter = parse_url($connecter);
$connecter = $this -> getColumnData($connecter, PARAM_HOST);
}
$rtn = false;
if($this -> checkJSONString($allowSet)){
$allowSet = json_decode($allowSet);
if($allowSet -> {$validationProperty}){
if($this -> isLoopData($domains))
$rtn = in_array($connecter, $domains);
} else
$isDisabled = ["exception" => "The {$validationProperty} setting is disabled"];
}else
$isDisabled = ["exception" => "Invalid Setting Data"];
return $rtn;
}
/*-------------------------------------------------------------------------
* @function_name: CHIDとカード番号の存在チェック
......@@ -1560,6 +1624,17 @@ class Checker extends Chiket {
throw new Exception('E_WRONG_SIGNATURE');
}
}
/*-------------------------------------------------------------------------
* @function_name: JSON表現の確認
* @parameter : String
* @return : 成功:true、失敗:false
-------------------------------------------------------------------------*/
function checkJSONString($string){
return is_string($string)
&& is_array(json_decode($string, true))
&& (json_last_error() == JSON_ERROR_NONE) ? true : false;
}
/*-------------------------------------------------------------------------
......
......@@ -217,6 +217,8 @@ define('COLUMN_TOTAL', 'total');
define('COLUMN_TRANSACTION_ID', 'transaction_id');
define('COLUMN_FAIL_FILENAME', 'fail_filename');
define('COLUMN_IP_ADDRESS', 'ip_address');
define('COLUMN_DOMAINS', 'domains');
define('COLUMN_WHITELIST_SETTING', 'whitelist_setting');
define('COLUMN_USER_AGENT', 'user_agent');
define('COLUMN_COMMISION', 'commision');
define('COLUMN_CARD_NUMBER', 'card_number');
......
......@@ -121,6 +121,8 @@ define('VAL_STR_CEO_NAME', '代表者氏名');
define('VAL_STR_SITE_NAME', 'サイト名・屋号');
define('VAL_STR_TARGET_COUNTRY', 'サービス主要対象国');
define('VAL_STR_URL', 'URL');
define('VAL_STR_IP_ADDRESS_VALIDATION', 'IPアドレス確認');
define('VAL_STR_DOMAIN_NAME_VALIDATION', 'ドメイン名の確認');
define('VAL_STR_SITE_URL', 'サイトURL');
define('VAL_STR_MANAGER_NAME', '口座取引責任者氏名');
define('VAL_STR_MANAGER_EMAIL', '責任者メールアドレス');
......
......@@ -123,6 +123,8 @@ define('VAL_STR_CEO_NAME', 'Corporation Representative Name');
define('VAL_STR_SITE_NAME', 'Site Name・Business Name');
define('VAL_STR_TARGET_COUNTRY', 'Targeted country');
define('VAL_STR_URL', 'URL');
define('VAL_STR_IP_ADDRESS_VALIDATION', 'IP Address Validation');
define('VAL_STR_DOMAIN_NAME_VALIDATION', 'Domain Name Validation');
define('VAL_STR_SITE_URL', 'Website URL');
define('VAL_STR_MANAGER_NAME', 'Name of personal in charge of account');
define('VAL_STR_MANAGER_EMAIL', 'E-mail address of personal in charge');
......
......@@ -228,6 +228,8 @@ define('PARAM_EXCHANGE_FEE_ID', 'exchange_fee_id');
define('PARAM_PARENT_CORPORATION_NAME', 'parent_corporation_name');
define('PARAM_FAIL', 'fail');
define('PARAM_IP_ADDRESS', 'ip_address');
define('PARAM_DOMAIN_NAME', 'domain_name');
define('PARAM_WHITELIST_SETTING', 'whitelist_setting');
define('PARAM_ORDER_NUMBER', 'order_number');
define('PARAM_DATETIME', 'datetime');
define('PARAM_WL_NAME', 'wl_name');
......
......@@ -263,6 +263,9 @@
<E_ERROR_IP_ADDRESS>
不正なIPアドレスからの接続です。
</E_ERROR_IP_ADDRESS>
<E_ERROR_DOMAIN>
不正なドメインやホストなどからの接続です。
</E_ERROR_DOMAIN>
<E_DO_NOT_SELECT>
__MEGELM01__を選択してください。
</E_DO_NOT_SELECT>
......
......@@ -272,6 +272,9 @@
<E_ERROR_IP_ADDRESS>
Unable to connect to an unauthorized IP address.
</E_ERROR_IP_ADDRESS>
<E_ERROR_DOMAIN>
Unable to connect to an unauthorized Host/Domain.
</E_ERROR_DOMAIN>
<E_DO_NOT_SELECT>
Please select the requested __MEGELM01__.
</E_DO_NOT_SELECT>
......
......@@ -248,6 +248,9 @@
<E_ERROR_IP_ADDRESS>
Tidak dapat terhubung ke alamat IP yang tidak sah.
</E_ERROR_IP_ADDRESS>
<E_ERROR_DOMAIN>
Tidak dapat terhubung ke Host/Domain yang tidak sah.
</E_ERROR_DOMAIN>
<E_DO_NOT_SELECT>
Silakan pilih __MEGELM01__ yang diminta.
</E_DO_NOT_SELECT>
......
......@@ -257,6 +257,9 @@
<E_ERROR_IP_ADDRESS>
IP地址未授权。
</E_ERROR_IP_ADDRESS>
<E_ERROR_IP_ADDRESS>
HOST/Domain地址未授权。
</E_ERROR_IP_ADDRESS>
<E_DO_NOT_SELECT>
请在__MEGELM01__选择。
</E_DO_NOT_SELECT>
......
......@@ -257,6 +257,9 @@
<E_ERROR_IP_ADDRESS>
IP地址未授權。
</E_ERROR_IP_ADDRESS>
<E_ERROR_DOMAIN>
HOST/Domain地址未授權。
</E_ERROR_DOMAIN>
<E_DO_NOT_SELECT>
請在__MEGELM01__選擇。
</E_DO_NOT_SELECT>
......
......@@ -9386,6 +9386,8 @@ WHERE
, user_name
, password
, ip_address
, domain
, whitelist_setting
FROM
t_api_signature
WHERE
......@@ -9403,6 +9405,8 @@ WHERE
, user_name
, password
, ip_address
, domain
, whitelist_setting
FROM
t_api_signature
WHERE
......@@ -9420,6 +9424,8 @@ WHERE
, user_name
, password
, ip_address
, domains
, whitelist_setting
FROM
t_api_signature
WHERE
......@@ -9994,14 +10000,16 @@ WHERE
-->
<LIST_API_SIGNATURE>
SELECT
api_signature.a_id AS a_id
, api_signature.user_name AS user_name
, api_signature.password AS password
, api_signature.user_account AS user_account
, IFNULL(users.first_name, '') AS first_name
, IFNULL(users.last_name, '') AS last_name
, api_signature.ip_address AS ip_address
, api_signature.create_time AS create_time
api_signature.a_id AS a_id
, api_signature.user_name AS user_name
, api_signature.password AS password
, api_signature.user_account AS user_account
, IFNULL(users.first_name, '') AS first_name
, IFNULL(users.last_name, '') AS last_name
, api_signature.ip_address AS ip_address
, api_signature.create_time AS create_time
, api_signature.domains AS domains
, api_signature.whitelist_setting AS whitelist_setting
FROM
t_api_signature AS api_signature
LEFT OUTER JOIN
......@@ -10013,14 +10021,16 @@ WHERE
<!-- Mark -->
<LIST_API_SIGNATURE_REVISED>
SELECT
api_signature.a_id AS a_id,
api_signature.user_name AS user_name,
api_signature.password AS password,
api_signature.user_account AS user_account,
IFNULL(users.first_name, '') AS first_name,
IFNULL(users.last_name, '') AS last_name,
api_signature.ip_address AS ip_address,
api_signature.create_time AS create_time
api_signature.a_id AS a_id,
api_signature.user_name AS user_name,
api_signature.password AS password,
api_signature.user_account AS user_account,
IFNULL(users.first_name, '') AS first_name,
IFNULL(users.last_name, '') AS last_name,
api_signature.ip_address AS ip_address,
api_signature.create_time AS create_time,
api_signature.domains AS domains,
api_signature.whitelist_setting AS whitelist_setting
FROM
t_api_signature AS api_signature
LEFT OUTER JOIN
......@@ -10058,6 +10068,8 @@ WHERE
, user_name
, password
, ip_address
, domains
, whitelist_setting
, create_time
) VALUES (
'__ELEMENT01__'
......@@ -10065,6 +10077,8 @@ WHERE
, '__ELEMENT03__'
, '__ELEMENT04__'
, '__ELEMENT05__'
, '__ELEMENT06__'
, '__ELEMENT07__'
, NOW() + INTERVAL 17 HOUR
)
</INSERT_API_SIGNATURE>
......@@ -10080,9 +10094,11 @@ WHERE
UPDATE
t_api_signature
SET
user_name = '__ELEMENT02__'
, password = '__ELEMENT03__'
, ip_address = '__ELEMENT04__'
user_name = '__ELEMENT02__'
, password = '__ELEMENT03__'
, ip_address = '__ELEMENT04__'
, domains = '__ELEMENT05__'
, whitelist_setting = '__ELEMENT06__'
WHERE
user_account = '__ELEMENT01__'
</UPDATE_API_SIGNATURE>
......
......@@ -80,13 +80,13 @@ class LogicApiSignature extends ApiSignatureModelClass {
* @parameter : なし
* @return : なし
-------------------------------------------------------------------------*/
function select($newCredential = false) {
$rs = $this -> getAPISignatureCommon($this -> getAId());
function select() {
$rs = $this -> getRowData($this -> getAPISignatureCommon($this -> getAId()));
$userAccount = $this -> getUserAccount();
if(count($rs) > 0)
$userAccount = $this -> getColumnData($rs[0], COLUMN_USER_ACCOUNT);
$userAccount = $this -> getColumnData($rs, COLUMN_USER_ACCOUNT);
$this -> setResult($rs);
$this -> setAccount($this -> getAccountCommon($userAccount));
......
This diff is collapsed.
......@@ -31,9 +31,7 @@ include_once('template/base_head.php');
</tr>
<tr>
<th>氏名</th>
<td>
<?php $this -> echoLastName(); ?> <?php $this -> echoFirstName(); ?>
</td>
<td><?php $this -> echoLastName(); ?> <?php $this -> echoFirstName(); ?></td>
</tr>
<tr>
<th>APIユーザ名</th>
......@@ -47,6 +45,14 @@ include_once('template/base_head.php');
<th>IPアドレス</th>
<td><?php $this -> echoIpAddress(); ?></td>
</tr>
<tr>
<th>ドメイン名</th>
<td><?php $this -> echoDomainName(); ?></td>
</tr>
<tr>
<th>確認設定</th>
<td><?php $this -> echoWhitelistSettingsCheckboxes(true); ?></td>
</tr>
</table>
<input type="hidden" value="action" id="type" name="type" />
......@@ -54,6 +60,7 @@ include_once('template/base_head.php');
<input type="hidden" value="<?php $this -> echoUserName(); ?>" id="user_name" name="user_name" />
<input type="hidden" value="<?php $this -> echoPassword(); ?>" id="password" name="password" />
<input type="hidden" value="<?php $this -> echoIpAddress(); ?>" id="ip_address" name="ip_address" />
<input type="hidden" value="<?php $this -> echoDomainName(); ?>" id="domain_name" name="domain_name" />
</form>
<p class="calign">
<a href="javascript:actionInput();" class="btn bg-default">&laquo; 戻る</a>&emsp;
......
......@@ -28,7 +28,9 @@ include_once('template/base_head.php');
</colgroup>
<tr>
<th>口座番号</th>
<td><?php $this -> echoUserAccount(); ?></td>
<td>
<?php $this -> echoUserAccount(); ?>
</td>
</tr>
<tr>
<th>氏名</th>
......@@ -51,7 +53,19 @@ include_once('template/base_head.php');
<tr>
<th>IPアドレス</th>
<td>
<input type="text" id="ip_address" name="ip_address" value="<?php $this -> echoIpAddress(); ?>" class="w30p">
<textarea id="ip_address" name="ip_address" rows="10" cols="50"><?php $this -> echoIpAddress(); ?></textarea>
</td>
</tr>
<tr>
<th>ドメイン名</th>
<td>
<textarea id="domain_name" name="domain_name" rows="10" cols="50"><?php $this -> echoDomainName(); ?></textarea>
</td>
</tr>
<tr>
<th>確認設定</th>
<td>
<?php $this -> echoWhitelistSettingsCheckboxes(); ?>
</td>
</tr>
</table>
......
......@@ -53,7 +53,19 @@ include_once('template/base_head.php');
<tr>
<th>IPアドレス</th>
<td>
<input type="text" id="ip_address" name="ip_address" value="<?php $this -> echoIpAddress(); ?>" class="w30p">
<textarea id="ip_address" name="ip_address" rows="10" cols="50"><?php $this -> echoIpAddress(); ?></textarea>
</td>
</tr>
<tr>
<th>ドメイン名</th>
<td>
<textarea id="domain_name" name="domain_name" rows="10" cols="50"><?php $this -> echoDomainName(); ?></textarea>
</td>
</tr>
<tr>
<th>確認設定</th>
<td>
<?php $this -> echoWhitelistSettingsCheckboxes(); ?>
</td>
</tr>
</table>
......
......@@ -24,7 +24,7 @@ $apiToAccount = (isset($_GET["to_account"]) ? $_GET["to_account"] : "85823926");
パスワード:<input type="text" value="<?=$apiPwd?>" name="password" /><br/>
番組コード:<input type="text" value="<?=$apiPnum?>" name="p_num" /><br/>
金額:<input type="text" value="<?=$apiAmt?>" name="amount" /><br/>
FROM_ACCOUNT:<input type="text" value="<?=$apiFromAccount?>" name="from_account" /><br/>
FROM_ACCOUNT:<input type="text" value="<?=$apiFromAccount?>" name="from_account"/><br/>
TO_ACCOUNT::<input type="text" value="<?=$apiToAccount?>" name="to_account" /><br/>
DEBIT_CURRENCY:<input type="text" value="<?=$apiTCur?>" name="debit_currency" /><br/>
CURRENCY:<input type="text" value="<?=$apiFCur?>" name="currency" /><br/>
......
......@@ -5,6 +5,8 @@ function getServer($param){
return isset($_SERVER[$param]) ? $_SERVER[$param] : "";
}
print_r(getServer("HTTP_USER_AGENT"));
$connector = getServer("HTTP_REFERER");
if($connector == ""){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment