source: branches/version-2_13-dev/data/class/sessionfactory/SC_SessionFactory_UseRequest.php @ 23511

Revision 23511, 15.8 KB checked in by shutta, 8 years ago (diff)

#2448 typo修正・ソース整形・ソースコメントの改善 for 2.13.3

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