source: branches/version-2_12-dev/data/class/sessionfactory/SC_SessionFactory_UseRequest.php @ 21514

Revision 21514, 15.4 KB checked in by Seasoft, 12 years ago (diff)

#1625 (typo修正・ソース整形・ソースコメントの改善)

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