source: branches/version-2/data/class/session/sessionfactory/SC_SessionFactory_UseRequest.php @ 17122

Revision 17122, 14.2 KB checked in by adachi, 15 years ago (diff)

細かな修正
*session.use_trans_sidの設定を削除
*sessionを重複して開始しないように修正

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2007 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24// {{{ requires
25require_once CLASS_PATH . 'session/SC_SessionFactory.php';
26require_once CLASS_EX_PATH . "helper_extends/SC_Helper_Mobile_Ex.php";
27
28/**
29 * Cookieを使用せず、リクエストパラメータによりセッションを継続する設定を行うクラス.
30 *
31 * このクラスを直接インスタンス化しないこと.
32 * 必ず SC_SessionFactory クラスを経由してインスタンス化する.
33 * また, SC_SessionFactory クラスの関数を必ずオーバーライドしている必要がある.
34 *
35 * @package SC_SessionFactory
36 * @author LOCKON CO.,LTD.
37 * @version $Id$
38 */
39class SC_SessionFactory_UseRequest extends SC_SessionFactory {
40
41    var $state = null;
42
43    // }}}
44    // {{{ functions
45
46    /**
47     * PC/モバイルのセッション管理オブジェクトを切り替える
48     *
49     * @param string $state
50     */
51    function setState($state = 'pc') {
52        switch($state) {
53        case 'mobile':
54            $this->state = new LC_UseRequest_State_Mobile;
55            break;
56
57        case 'pc':
58        default:
59            $this->state = new LC_UseRequest_State_PC;
60            break;
61        }
62    }
63
64    /**
65     * Cookieを使用するかどうか
66     *
67     * @return boolean 常にfalseを返す
68     */
69    function useCookie() {
70        return false;
71    }
72
73    /**
74     * dtb_mobile_ext_session_id テーブルを検索してセッションIDを取得する。
75     * PCサイトでもモバイルサイトでもこのテーブルを利用する.
76     *
77     * @return string|null 取得したセッションIDを返す。
78     *                     取得できなかった場合は null を返す。
79     */
80    function getExtSessionId() {
81        if (!preg_match('|^' . URL_DIR . '(.*)$|', $_SERVER['SCRIPT_NAME'], $matches)) {
82            return null;
83        }
84
85        $url = $matches[1];
86        $lifetime = $this->state->getLifeTime();
87        $time = date('Y-m-d H:i:s', time() - $lifetime);
88        $objQuery = new SC_Query;
89
90        foreach ($_REQUEST as $key => $value) {
91            $session_id = $objQuery->get('dtb_mobile_ext_session_id', 'session_id',
92                                         'param_key = ? AND param_value = ? AND url = ? AND create_date >= ?',
93                                         array($key, $value, $url, $time));
94            if (isset($session_id)) {
95                return $session_id;
96            }
97        }
98
99        return null;
100    }
101
102    /**
103     * 外部サイト連携用にセッションIDとパラメーターの組み合わせを保存する。
104     *
105     * @param string $param_key パラメーター名
106     * @param string $param_value パラメーター値
107     * @param string $url URL
108     * @return void
109     */
110    function setExtSessionId($param_key, $param_value, $url) {
111        $objQuery = new SC_Query;
112
113        // GC
114        $lifetime = $this->state->getLifeTime();
115        $time = date('Y-m-d H:i:s', time() - $lifetime);
116        $objQuery->delete('dtb_mobile_ext_session_id', 'create_date < ?', array($time));
117
118        $arrValues = array('session_id'  => session_id(),
119                           'param_key'   => $param_key,
120                           'param_value' => $param_value,
121                           'url'         => $url);
122
123        $objQuery->insert('dtb_mobile_ext_session_id', $arrValues);
124    }
125
126    /**
127     * セッションデータが有効かどうかをチェックする。
128     *
129     * @return boolean セッションデータが有効な場合は true、無効な場合は false を返す。
130     */
131    function validateSession() {
132        return $this->state->validateSessionData();
133    }
134
135    /**
136     * パラメーターから有効なセッションIDを取得する。
137     *
138     * @return string|false 取得した有効なセッションIDを返す。
139     *                      取得できなかった場合は false を返す。
140     */
141    function getSessionId() {
142        // パラメーターからセッションIDを取得する。
143        $sessionId = @$_POST[session_name()];
144        if (!isset($sessionId)) {
145            $sessionId = @$_GET[session_name()];
146        }
147        if (!isset($sessionId)) {
148            $sessionId = $this->getExtSessionId();
149        }
150        if (!isset($sessionId)) {
151            return false;
152        }
153
154        // セッションIDの存在をチェックする。
155        $objSession = new SC_Helper_Session_Ex();
156        if ($objSession->sfSessRead($sessionId) === null) {
157            GC_Utils_Ex::gfPrintLog("Non-existent session id : sid=$sessionId");
158            return false;
159        }
160        return session_id($sessionId);
161    }
162
163    /**
164     * セッション初期処理を行う。
165     *
166     * @return void
167     */
168    function initSession() {
169        // セッションIDの受け渡しにクッキーを使用しない。
170        ini_set('session.use_cookies', '0');
171
172        // パラメーターから有効なセッションIDを取得する。
173        $sessionId = $this->getSessionId();
174
175        if (!$sessionId) {
176            session_start();
177        }
178
179        // セッションIDまたはセッションデータが無効な場合は、セッションIDを再生成
180        // し、セッションデータを初期化する。
181        if ($sessionId === false || !$this->validateSession()) {
182            session_regenerate_id(true);
183            // セッションデータの初期化
184            $this->state->inisializeSessionData();
185
186            // 新しいセッションIDを付加してリダイレクトする。
187            if ($_SERVER['REQUEST_METHOD'] == 'GET') {
188                // GET の場合は同じページにリダイレクトする。
189                $objMobile = new SC_Helper_Mobile_Ex;
190                header('Location: ' . $objMobile->gfAddSessionId());
191            } else {
192                // GET 以外の場合はトップページへリダイレクトする。
193                header('Location: ' . URL_SITE_TOP . '?' . SID);
194            }
195            exit;
196        }
197
198        // 有効期限を更新する.
199        $this->state->updateExpire();
200    }
201}
202/**
203 * セッションデータ管理クラスの基底クラス
204 *
205 */
206class LC_UseRequest_State {
207    /** 名前空間(pc/mobile) */
208    var $namespace = '';
209    /** 有効期間 */
210    var $lifetime  = 0;
211    /** エラーチェック関数名の配列 */
212    var $validate  = array();
213
214    /**
215     * 名前空間を取得する
216     *
217     * @return string
218     */
219    function getNameSpace() { return $this->namespace; }
220
221    /**
222     * 有効期間を取得する
223     *
224     * @return integer
225     */
226    function getLifeTime() { return $this->lifetime; }
227
228    /**
229     * セッションデータが設定されているかを判定する.
230     * $_SESSION[$namespace]の値が配列の場合に
231     * trueを返す.
232     *
233     * @return boolean
234     */
235    function validateNameSpace() {
236        $namespace = $this->getNameSpace();
237        if (isset($_SESSION[$namespace]) && is_array($_SESSION[$namespace])) {
238            return true;
239        }
240        GC_Utils_Ex::gfPrintLog("NameSpace $namespace not found in session data : sid=" . session_id());
241        return false;
242    }
243
244    /**
245     * セッションのデータを取得する
246     * 取得するデータは$_SESSION[$namespace][$key]となる.
247     *
248     * @param string $key
249     * @return mixed|null
250     */
251    function getValue($key) {
252        $namespace = $this->getNameSpace();
253        return isset($_SESSION[$namespace][$key])
254            ? $_SESSION[$namespace][$key]
255            : null;
256    }
257
258    /**
259     * セッションにデータを登録する.
260     * $_SESSION[$namespace][$key] = $valueの形で登録される.
261     *
262     * @param string $key
263     * @param mixed $value
264     */
265    function setValue($key, $value) {
266        $namespace = $this->getNameSpace();
267        $_SESSION[$namespace][$key] = $value;
268    }
269
270    /**
271     * 有効期限を取得する.
272     *
273     * @return integer
274     */
275    function getExpire() {
276        return $this->getValue('expires');
277    }
278
279    /**
280     * 有効期限を設定する.
281     *
282     */
283    function updateExpire() {
284        $lifetime = $this->getLifeTime();
285        $this->setValue('expires', time() + $lifetime);
286    }
287
288    /**
289     * 有効期限内かどうかを判定する.
290     *
291     * @return boolean
292     */
293    function validateExpire() {
294        $expire = $this->getExpire();
295        if (intval($expire) > time()) {
296            return true;
297        }
298        $date = date('Y/m/d H:i:s', $expire);
299        GC_Utils_Ex::gfPrintLog("Session expired at $date : sid=" . session_id());
300        return false;
301    }
302
303    /**
304     * IPアドレスを取得する.
305     *
306     * @return string
307     */
308    function getIp() {
309        return $this->getValue('ip');
310    }
311
312    /**
313     * IPアドレスを設定する.
314     *
315     */
316    function updateIp() {
317        $this->setValue('ip', $_SERVER['REMOTE_ADDR']);
318    }
319
320    /**
321     * REMOTE_ADDRとセッション中のIPが同じかどうかを判定する.
322     * 同じ場合にtrueが返る
323     *
324     * @return boolean
325     */
326    function validateIp() {
327        $ip = $this->getIp();
328        if (!empty($_SERVER['REMOTE_ADDR'])
329         && $ip === $_SERVER['REMOTE_ADDR']) {
330
331            return true;
332        }
333
334        $msg = sprintf('Ip Addr mismatch : %s != %s(expected) : sid=%s',
335                       $_SERVER['REMOTE_ADDR'], $ip, session_id());
336        GC_Utils_Ex::gfPrintLog($msg);
337        return false;
338    }
339
340    /**
341     * UserAgentもしくは携帯の機種名を取得する.
342     *
343     * @return string
344     */
345    function getModel() {
346        return $this->getValue('model');
347    }
348
349    /**
350     * セッション中のデータ検証する
351     *
352     * @return boolean
353     */
354    function validateSessionData() {
355        foreach ($this->validate as $method) {
356            $method = 'validate' . $method;
357            if (!$this->$method()) {
358                return false;
359            }
360        }
361        return true;
362    }
363
364    /**
365     * セッションデータを初期化する.
366     *
367     */
368    function inisializeSessionData() {}
369}
370
371/**
372 * PCサイト用のセッションデータ管理クラス
373 *
374 */
375class LC_UseRequest_State_PC extends LC_UseRequest_State {
376
377    /**
378     * コンストラクタ
379     * セッションのデータ構造は下のようになる.
380     * $_SESSION["pc"]=> array(
381     *     ["model"]   => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
382     *     ["ip"]      => "127.0.0.1"
383     *     ["expires"] => 1204699031
384     * )
385     *
386     * @return LC_UseRequest_State_PC
387     */
388    function LC_UseRequest_State_PC() {
389        $this->namespace = 'pc';
390        $this->lifetime  = SESSION_LIFETIME;
391        $this->validate  = array('NameSpace', 'Model', 'Ip', 'Expire');
392    }
393
394    /**
395     * セッションにUserAgentを設定する.
396     *
397     */
398    function updateModel() {
399        $this->setValue('model', $_SERVER['HTTP_USER_AGENT']);
400    }
401
402    /**
403     * UserAgentを検証する.
404     *
405     * @return boolean
406     */
407    function validateModel() {
408        $ua = $this->getModel();
409        if (!empty($_SERVER['HTTP_USER_AGENT'])
410         && $_SERVER['HTTP_USER_AGENT'] === $ua) {
411
412            return true;
413        }
414        $msg = sprintf("User agent model mismatch : %s != %s(expected), sid=%s",
415                       $_SERVER['HTTP_USER_AGENT'], $ua, session_id());
416        GC_Utils_Ex::gfPrintLog($msg);
417        return false;
418    }
419
420    /**
421     * セッションデータを初期化する.
422     *
423     */
424    function inisializeSessionData() {
425        $_SESSION = array();
426        $this->updateModel();
427        $this->updateIp();
428        $this->updateExpire();
429    }
430}
431
432/**
433 * モバイルサイト用のセッションデータ管理クラス
434 *
435 */
436class LC_UseRequest_State_Mobile extends LC_UseRequest_State {
437
438    /**
439     * コンストラクタ
440     * セッションのデータ構造は下のようになる.
441     * $_SESSION["mobile"]=> array(
442     *     ["model"]   => 901sh
443     *     ["ip"]      => 127.0.0.1
444     *     ["expires"] => 1204699031
445     *     ["phone_id"]=> ****
446     * )
447     *
448     * @return LC_UseRequest_State_Mobile
449     */
450    function LC_UseRequest_State_Mobile() {
451        $this->namespace = 'mobile';
452        $this->lifetime  = MOBILE_SESSION_LIFETIME;
453        $this->validate  = array('NameSpace', 'Model', 'Ip', 'Expire');
454    }
455
456    /**
457     * 携帯の機種名を設定する
458     *
459     */
460    function updateModel() {
461        $this->setValue('model', SC_MobileUserAgent::getModel());
462    }
463
464    /**
465     * セッション中の携帯機種名と、アクセスしてきたブラウザの機種名が同じかどうかを判定する
466     *
467     * @return boolean
468     */
469    function validateModel() {
470        $modelInSession = $this->getModel();
471        $model = SC_MobileUserAgent::getModel();
472        if (!empty($model)
473         && $model === $modelInSession) {
474
475            return true;
476        }
477        return false;
478    }
479
480    /**
481     * 携帯のIDを取得する
482     *
483     * @return string
484     */
485    function getPhoneId() {
486        return $this->getValue('phone_id');
487    }
488
489    /**
490     * 携帯のIDを登録する.
491     *
492     */
493    function updatePhoneId() {
494        $this->setValue('phone_id', SC_MobileUserAgent::getId());
495    }
496
497    /**
498     * セッションデータを初期化する.
499     *
500     */
501    function inisializeSessionData() {
502        $_SESSION = array();
503        $this->updateModel();
504        $this->updateIp();
505        $this->updateExpire();
506        $this->updatePhoneId();
507    }
508}
509/*
510 * Local variables:
511 * coding: utf-8
512 * End:
513 */
514?>
Note: See TracBrowser for help on using the repository browser.