3 * HTTPリクエスト、レスポンス、セッション管理マネージャー
7 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
9 * @package Magic3 Framework
10 * @author 平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
11 * @copyright Copyright 2006-2017 Magic3 Project.
12 * @license http://www.gnu.org/copyleft/gpl.html GPL License
14 * @link http://www.magic3.org
16 require_once(M3_SYSTEM_INCLUDE_PATH . '/common/core.php');
18 class RequestManager extends Core
20 private $db; // DBオブジェクト
21 private $tmpCookie; // クッキー送信前のクッキー格納データ
22 private $magicQuote; // バックスラッシュでの文字エスケープ処理
23 private $sessionNoUpdate; // セッションの更新を停止するかどうか(参照は可能)
24 private $sessionOpenEventCallbacks; // セッション開始イベントコールバック関数
25 private $sessionCloseEventCallbacks; // セッション終了イベントコールバック関数
30 function __construct()
33 parent::__construct();
36 $this->db = $this->gInstance->getSytemDbObject();
39 // セッションDBが使用可能な場合は、ハンドラを設定し、
40 // 使用不可の場合は、デフォルトのセッション管理を使用する
41 if (M3_SESSION_DB && $this->gEnv->canUseDbSession()){
42 ini_set('session.save_handler', 'user'); // 追加(2008/7/7)
43 session_set_save_handler( array($this, '_sessionOpen'),
44 array($this, '_sessionClose'),
45 array($this, '_sessionRead'),
46 array($this, '_sessionWrite'),
47 array($this, '_sessionDestroy'),
48 array($this, '_sessionGc'));
50 // シャットダウン時の処理(2015/12/21 追加)
51 if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
52 session_register_shutdown();
54 register_shutdown_function('session_write_close');
59 $this->tmpCookie = array(); // クッキー送信前のクッキー格納データ
60 $this->sessionOpenEventCallbacks = array(); // セッション開始イベントコールバック関数
61 $this->sessionCloseEventCallbacks = array(); // セッション終了イベントコールバック関数
63 // magic quoteが有効の場合は回避手段を取る
64 if (get_magic_quotes_gpc() == 1) $this->magicQuote = true;
69 public function isPost($name)
71 return isset($_POST[$name]);
76 public function isGet($name)
78 return isset($_GET[$name]);
83 public function valueOfPost($name)
85 return self::isPost($name) ? $_POST[$name] : '';
88 * POST値取得(トリミング(前後の空白削除)あり)
90 public function trimValueOfPost($name)
92 $value = self::isPost($name) ? $_POST[$name] : '';
93 return $this->_trimValueOf($name, $value);
98 public function valueOfGet($name)
100 return self::isGet($name) ? $_GET[$name] : '';
103 * GET値取得(トリミング(前後の空白削除)あり)
105 public function trimValueOfGet($name)
107 $value = self::isGet($name) ? $_GET[$name] : '';
108 return $this->_trimValueOf($name, $value);
115 * @param string $name キー値
116 * @param string $default 値が存在しないときのデフォルト値
119 public function valueOf($name, $default = '')
121 //return isset($_POST[$name]) ? $_POST[$name] : (isset($_GET[$name]) ? $_GET[$name] : $default);
122 //return self::gpc_stripslashes(isset($_POST[$name]) ? $_POST[$name] : (isset($_GET[$name]) ? $_GET[$name] : $default));
123 return $this->gpc_stripslashes(isset($_POST[$name]) ? $_POST[$name] : (isset($_GET[$name]) ? $_GET[$name] : $default));
126 * POST,GETから値を取得(トリミング(前後の空白削除)あり)
128 * POSTまたはGETから値を取得し、トリミング(前後の空白削除)する
131 * @param string $name キー値
132 * @param string $default 値が存在しないときのデフォルト値
135 public function trimValueOf($name, $default = '')
137 $srcValue = isset($_POST[$name]) ? $_POST[$name] : (isset($_GET[$name]) ? $_GET[$name] : $default);
138 return $this->_trimValueOf($name, $srcValue, $default);
141 * POST,GETから値をint値を取得(トリミング(前後の空白削除)あり)
143 * POSTまたはGETから値を取得し、トリミング(前後の空白削除)する
146 * @param string $name キー値
147 * @param string $default 値が存在しないとき、値が空文字列のときのデフォルト値
150 //public function trimIntValueOf($name, $default = '')
151 public function trimIntValueOf($name, $default) // デフォルト値必須(2015/2/13)
153 $srcValue = isset($_POST[$name]) ? $_POST[$name] : (isset($_GET[$name]) ? $_GET[$name] : $default);
154 return $this->_trimValueOf($name, $srcValue, $default, 1/* int型チェック */);
157 * POST,GETから値をチェックボックスの値を取得(トリミング(前後の空白削除)あり)
159 * POSTまたはGETから値を取得し、トリミング(前後の空白削除)する
162 * @param string $name キー値
163 * @param string $default 値が存在しないときのデフォルト値
164 * @return string 取得値(0または1)
166 public function trimCheckedValueOf($name, $default = '')
168 $srcValue = isset($_POST[$name]) ? $_POST[$name] : (isset($_GET[$name]) ? $_GET[$name] : $default);
169 $checked = $this->_trimValueOf($name, $srcValue, $default);
170 return ($checked == 'on') ? '1' : '0';
175 * デフォルトで不正な文字(HTMLタグ等)を取り除く
177 * @param string $name キー値
178 * @param string $value 値
179 * @param string $default 値が存在しないときのデフォルト値
180 * @param int $ckeckType 値の型のチェックタイプ(0=型チェックなし、1=int型)
183 public function _trimValueOf($name, $value, $default='', $ckeckType=0)
186 if (is_array($value)){
187 $trimValue = array_map('trim', $value);
188 $destValue = array();
189 foreach (array_keys($trimValue) as $key){
190 $stripValue = $this->gpc_stripslashes($trimValue[$key]);
191 $stripValue = strip_tags($stripValue);
193 // 危険性の高いその他変換。問題がある場合は文字列をクリアする
194 $saveValue = $stripValue;
195 $stripValue = $this->_convSafeText($stripValue);
196 if ($stripValue != $saveValue) $stripValue = '';
199 if (strlen($stripValue) == strlen($trimValue[$key])){ // 文字列長が同じとき
200 if ($ckeckType == 1){ // int型チェック
201 if ($stripValue == ''){ // 空文字列の場合はエラーと見なさない(2015/2/19 追加)
203 } else if (is_numeric($stripValue) && !strstr($stripValue, '.')){
205 } else { // エラーの場合は値を修正
215 // ウィジェット内での処理の場合はウィジェットIDも出力
216 $widgetId = $this->gEnv->getCurrentWidgetId();// ウィジェットID
217 if (empty($widgetId)){
218 $this->gOpeLog->writeUserData(__METHOD__, 'POSTまたはGET値の異常データを検出しました。', 2010, 'name=' . $name . ', value=[' . $value[$key] . ']');
219 } else { // ウィジェットIDが設定されているとき
220 $this->gOpeLog->writeUserData(__METHOD__, 'POSTまたはGET値の異常データを検出しました。', 2011, 'name=' . $name . ', value=[' . $value[$key] . '], widgetid=' . $widgetId);
224 if ($stripValue == '') $stripValue = $default;
225 $destValue[] = $stripValue;
228 $trimValue = trim($value);
230 // HTMLタグが含まれていた場合は、ログを残す
231 $destValue = $this->gpc_stripslashes($trimValue);
232 $destValue = strip_tags($destValue);
234 // 危険性の高いその他変換。問題がある場合は文字列をクリアする
235 $saveValue = $destValue;
236 $destValue = $this->_convSafeText($destValue);
237 if ($destValue != $saveValue) $destValue = '';
240 if (strlen($destValue) == strlen($trimValue)){ // 文字列長が同じとき
241 if ($ckeckType == 1){ // int型チェック
242 if ($destValue == ''){ // 空文字列の場合はエラーと見なさない(2015/2/19 追加)
244 } else if (is_numeric($destValue) && !strstr($destValue, '.')){
246 } else { // エラーの場合は値を修正
256 // ウィジェット内での処理の場合はウィジェットIDも出力
257 $widgetId = $this->gEnv->getCurrentWidgetId();// ウィジェットID
258 if (empty($widgetId)){
259 $this->gOpeLog->writeUserData(__METHOD__, 'POSTまたはGET値の異常データを検出しました。', 2012, 'name=' . $name . ', value=[' . $value . ']');
260 } else { // ウィジェットIDが設定されているとき
261 $this->gOpeLog->writeUserData(__METHOD__, 'POSTまたはGET値の異常データを検出しました。', 2013, 'name=' . $name . ', value=[' . $value . '], widgetid=' . $widgetId);
265 if ($destValue == '') $destValue = $default;
272 * @param string $src 変換するデータ
273 * @return string 変換後データ
275 function _convSafeText($src)
278 $search = array("':[\s]*?expression\('si", // Javascriptが実行されないための対応「:expression(」「:url(」を削除(IE6,7用対応) 2009/1/15
282 $replace = array("", "");
284 return preg_replace($search, $replace, $src);
289 * @return bool true=GETメソッド、false=GET以外
291 function isGetMethod()
293 $method = strtoupper($this->trimServerValueOf('REQUEST_METHOD')); // アクセスメソッド
294 if ($method == 'GET'){
303 * @return bool true=POSTメソッド、false=POST以外
305 function isPostMethod()
307 $method = strtoupper($this->trimServerValueOf('REQUEST_METHOD')); // アクセスメソッド
308 if ($method == 'POST'){
315 * cmdパラメータ付きのアクセスかどうか
317 * @return bool true=cmd付きアクセス、false=cmdなし
319 function isCmdAccess()
321 $cmd = $this->trimValueOf(M3_REQUEST_PARAM_OPERATION_COMMAND); // 実行コマンド
322 $isCmd = !empty($cmd); // コマンド実行かどうか
326 * $_SERVERから値を取得(トリミング(前後の空白削除)あり)
328 * $_SERVERから値を取得し、トリミング(前後の空白削除)する
330 * @param string $name キー値
331 * @param string $default 値が存在しないときのデフォルト値
334 public function trimServerValueOf($name, $default = '')
336 $value = isset($_SERVER[$name]) ? $_SERVER[$name] : $default;
339 if (is_array($value)){
340 $value = array_map('trim', $value);
342 $value = trim($value);
351 * @param string $name キー値
352 * @param string $default 値が存在しないときのデフォルト値
355 public function getSessionValue($name, $default = '')
357 $value = isset($_SESSION[$name]) ? $_SESSION[$name] : $default;
365 * @param string $name キー値
366 * @param string $value 格納値
367 * @return bool true=更新、false=更新なし
369 public function setSessionValue($name, $value = '')
371 // セッション更新が停止されている場合は終了
372 if ($this->sessionNoUpdate) return false;
374 $_SESSION[$name] = $value;
382 * @param string $name キー値
383 * @return bool true=更新、false=更新なし
385 public function unsetSessionValue($name)
387 // セッション更新が停止されている場合は終了
388 if ($this->sessionNoUpdate) return false;
390 unset($_SESSION[$name]);
394 * セッションからシリアライズされた値を取得
396 * @param string $name キー値
397 * @return object 取得したオブジェクト、なしの場合はnull
399 public function getSessionValueWithSerialize($name)
401 $value = isset($_SESSION[$name]) ? unserialize($_SESSION[$name]) : null;
407 * @param string $name キー値
408 * @param object $value 格納するオブジェクト、nullをセットした場合はセッション値を削除
409 * @return bool true=更新、false=更新なし
411 public function setSessionValueWithSerialize($name, $value = null)
413 // セッション更新が停止されている場合は終了
414 if ($this->sessionNoUpdate) return false;
417 unset($_SESSION[$name]);
419 $_SESSION[$name] = serialize($value);
428 public function stopSessionUpdate()
430 $this->sessionNoUpdate = true; // セッションの更新を停止するかどうか(参照は可能)
435 * @param string $name キー値
436 * @param string $default 値が存在しないときのデフォルト値
439 public function getCookieValue($name, $default = '')
442 $value = isset($this->tmpCookie[$name]) ? $this->tmpCookie[$name] : ''; // クッキー送信前のクッキー格納データ
444 if ($value == '') $value = isset($_COOKIE[$name]) ? $_COOKIE[$name] : $default;
450 * @param string $name キー値
451 * @param string $value 格納値
452 * @param int $expireDay クッキーの生存期間(日)。0を設定した場合はブラウザ閉じるまで生存。
455 public function setCookieValue($name, $value = '', $expireDay = 30)
457 if (floatval($expireDay) == 0){
458 $cookExpire = 0; // ブラウザ閉じるまで
460 $cookExpire = time() + 60 * 60 * 24 * $expireDay;
462 //setcookie($name, $value, $cookExpire);
463 setcookie($name, $value, $cookExpire, '/');
466 $this->tmpCookie[$name] = $value; // クッキー送信前のクッキー格納データ
471 * @param string $name キー値
474 public function removeCookieValue($name)
476 setcookie($name, '', time() - 3600, '/');
481 * @return array URLクエリー文字列を解析した配列
483 public function getQueryArray()
487 if (!isset($queryArray)){
488 $queryArray = array();
489 $queryStr = self::trimServerValueOf('QUERY_STRING');
490 if (!empty($queryStr)){
491 parse_str($queryStr, $queryArray);
498 * クエリー文字列中のWikiページ名を取得
500 * @return string Wikiページ名、空の時はWikiページ名なし
502 public function getWikiPageFromQuery()
505 $args = explode('&', $_SERVER['QUERY_STRING']);// 「&」で分割
506 for ($i = 0; $i < count($args); $i++){
508 $pos = strpos($line, '=');
509 if ($pos){ // 「=」が存在するとき
510 //list($key, $value) = explode('=', $line);
512 $wikiPage = $line; // 「=」なしのパラメータはwikiパラメータとする
521 * '(シングルクオート)、" (ダブルクオート)、\(バックスラッシュ) 、NULLにバックスラッシュでエスケープ処理を行う
523 * @param string $str 変換元文字列
524 * @return string 変換後文字列
526 /* function gpc_addslashes($str){
527 if ($this->magicQuote){
530 return addslashes($str);
536 * '(シングルクオート)、" (ダブルクオート)、\(バックスラッシュ) 、NULLのバックスラッシュでのエスケープ処理を削除
538 * @param string $str 変換元文字列
539 * @return string 変換後文字列
541 function gpc_stripslashes($str){
542 if ($this->magicQuote){
543 return stripslashes($str);
548 //******************************************************
549 // patTemplateのテンプレートに値を埋め込む。値を省略した場合は、POST,GETデータから取得したデータを再設定する。
550 // $name: patTemplateのテンプレート名
551 // $valueName: HTMLタグに設定した名前。patTemplateの値埋め込み用キーワードも同じものを使用する。
552 // $default: 値埋め込み用キーワードに埋め込む値。省略の場合はPOST,GETデータから$valueNameの値を取得する。
553 function addValueToTemplate($name, $valueName, $default = null)
555 if ($default == null){
556 $this->tmpl->addVar($name, $valueName, $this->valueOf($valueName));
558 $this->tmpl->addVar($name, $valueName, $default);
564 function _sessionOpen($save_path, $session_name)
571 function _sessionClose()
578 function _sessionRead($id)
580 return $this->db->readSession($id);
585 * @param string $id セッションID
586 * @param string $sessData セッションデータ
588 function _sessionWrite($id, $sessData)
590 return $this->db->writeSession($id, $sessData);
595 * @param string $id セッションID
597 function _sessionDestroy($id)
599 return $this->db->destroySession($id);
604 * @param int $maxlifetime セッションの生存時間(秒)
606 function _sessionGc($maxlifetime)
608 return $this->db->gcSession($maxlifetime);
613 * セッション開始イベント時のコールバック関数追加
615 * @param callable $callback コールバック関数
616 * @return bool true=正常終了,false=異常終了
618 function addSessionOpenEventCallback($callback)
620 if (!is_callable($callback)) return false;
623 $this->sessionOpenEventCallbacks[] = $callback;
628 * セッション終了イベント時のコールバック関数追加
630 * @param callable $callback コールバック関数
631 * @return bool true=正常終了,false=異常終了
633 function addSessionCloseEventCallback($callback)
635 if (!is_callable($callback)) return false;
638 $this->sessionCloseEventCallbacks[] = $callback;
643 * セッション開始イベント時のコールバック関数を実行
645 * @return bool true=正常終了,false=異常終了
647 function _doSessionOpenEventCallback()
649 $callbackCount = count($this->sessionOpenEventCallbacks);
650 if ($callbackCount == 0) return true;
653 for ($i = 0; $i < $callbackCount; $i++){
654 $callback = $this->sessionOpenEventCallbacks[$i];
655 if (is_callable($callback)){
657 $result = call_user_func($callback);
658 if (!$result) $retStatus = false;
664 * セッション終了イベント時のコールバック関数を実行
666 * @return bool true=正常終了,false=異常終了
668 function _doSessionCloseEventCallback()
670 $callbackCount = count($this->sessionCloseEventCallbacks);
671 if ($callbackCount == 0) return true;
674 for ($i = 0; $i < $callbackCount; $i++){
675 $callback = $this->sessionCloseEventCallbacks[$i];
676 if (is_callable($callback)){
678 $result = call_user_func($callback);
679 if (!$result) $retStatus = false;