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

Revision 22567, 15.5 KB checked in by shutta, 11 years ago (diff)

#2043 (typo修正・ソース整形・ソースコメントの改善 for 2.12.4)
Zend Framework PHP 標準コーディング規約のコーディングスタイルへ準拠。
classおよびfunctionの開始波括弧「{」のスタイルを修正。

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