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

Revision 22856, 15.5 KB checked in by Seasoft, 11 years ago (diff)

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

  • 主に空白・空白行の調整。もう少し整えたいが、一旦現状コミット。
  • 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 $state = null;
38
39
40    /**
41     * PC/モバイルのセッション管理オブジェクトを切り替える
42     *
43     * @param string $state
44     */
45    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    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    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    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    function validateSession()
132    {
133        /**
134         * PCサイトでは
135         *  ・セッションデータが適切に設定されているか
136         *  ・UserAgent
137         *  ・IPアドレス
138         *  ・有効期限
139         * モバイルサイトでは
140         *  ・セッションデータが適切に設定されているか
141         *  ・機種名
142         *  ・IPアドレス
143         *  ・有効期限
144         *  ・phone_id
145         * がチェックされる
146         */
147        return $this->state->validateSessionData();
148    }
149
150    /**
151     * パラメーターから有効なセッションIDを取得する。
152     *
153     * @return string|false 取得した有効なセッションIDを返す。
154     *                      取得できなかった場合は false を返す。
155     */
156    function getSessionId()
157    {
158        // パラメーターからセッションIDを取得する。
159        $sessionId = @$_POST[session_name()];
160        if (!isset($sessionId)) {
161            $sessionId = @$_GET[session_name()];
162            // AU動画音声ファイルダウンロード対策
163            // キャリアがAUで、動画、音声ファイルをダウンロードする際に
164            // SESSIONIDの後に余計なパラメータが付与され、セッションが無効になるケースがある
165            if (SC_MobileUserAgent::getCarrier() == 'ezweb') {
166                $idArray = split("\?", $sessionId);
167                $sessionId = $idArray[0];
168            }
169        }
170        if (!isset($sessionId)) {
171            $sessionId = $this->getExtSessionId();
172        }
173        if (!isset($sessionId)) {
174            return false;
175        }
176
177        // セッションIDの存在をチェックする。
178        $objSession = new SC_Helper_Session_Ex();
179        if ($objSession->sfSessRead($sessionId) === null) {
180            GC_Utils_Ex::gfPrintLog("Non-existent session id : sid=$sessionId");
181            return false;
182        }
183
184        return session_id($sessionId);
185    }
186
187    /**
188     * セッション初期処理を行う。
189     *
190     * @return void
191     */
192    function initSession()
193    {
194        // セッションIDの受け渡しにクッキーを使用しない。
195        ini_set('session.use_cookies', '0');
196        ini_set('session.use_trans_sid', '1');
197        ini_set('session.use_only_cookies', '0');
198
199        // パラメーターから有効なセッションIDを取得する。
200        $sessionId = $this->getSessionId();
201
202        if (!$sessionId) {
203            session_start();
204        }
205
206        /*
207         * PHP4 では session.use_trans_sid が PHP_INI_PREDIR なので
208         * ini_set() で設定できない
209         */
210        if (!ini_get('session.use_trans_sid')) {
211            output_add_rewrite_var(session_name(), session_id());
212        }
213
214        // セッションIDまたはセッションデータが無効な場合は、セッションIDを再生成
215        // し、セッションデータを初期化する。
216        if ($sessionId === false || !$this->validateSession()) {
217            session_regenerate_id(true);
218            // セッションデータの初期化
219            $this->state->inisializeSessionData();
220
221            // 新しいセッションIDを付加してリダイレクトする。
222            if ($_SERVER['REQUEST_METHOD'] == 'GET') {
223                // GET の場合は同じページにリダイレクトする。
224                $objMobile = new SC_Helper_Mobile_Ex;
225                header('Location: ' . $objMobile->gfAddSessionId());
226            } else {
227                // GET 以外の場合はトップページへリダイレクトする。
228                header('Location: ' . TOP_URLPATH . '?' . SID);
229            }
230            exit;
231        }
232
233        // 有効期限を更新する.
234        $this->state->updateExpire();
235    }
236}
237/**
238 * セッションデータ管理クラスの基底クラス
239 *
240 */
241class LC_UseRequest_State
242{
243    /** 名前空間(pc/mobile) */
244    var $namespace = '';
245    /** 有効期間 */
246    var $lifetime  = 0;
247    /** エラーチェック関数名の配列 */
248    var $validate  = array();
249
250    /**
251     * 名前空間を取得する
252     *
253     * @return string
254     */
255    function getNameSpace()
256    { return $this->namespace; }
257
258    /**
259     * 有効期間を取得する
260     *
261     * @return integer
262     */
263    function getLifeTime()
264    { return $this->lifetime; }
265
266    /**
267     * セッションデータが設定されているかを判定する.
268     * $_SESSION[$namespace]の値が配列の場合に
269     * trueを返す.
270     *
271     * @return boolean
272     */
273    function validateNameSpace()
274    {
275        $namespace = $this->getNameSpace();
276        if (isset($_SESSION[$namespace]) && is_array($_SESSION[$namespace])) {
277            return true;
278        }
279        GC_Utils_Ex::gfPrintLog("NameSpace $namespace not found in session data : sid=" . session_id());
280
281        return false;
282    }
283
284    /**
285     * セッションのデータを取得する
286     * 取得するデータは$_SESSION[$namespace][$key]となる.
287     *
288     * @param string $key
289     * @return mixed|null
290     */
291    function getValue($key)
292    {
293        $namespace = $this->getNameSpace();
294
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
347        return false;
348    }
349
350    /**
351     * IPアドレスを取得する.
352     *
353     * @return string
354     */
355    function getIp()
356    {
357        return $this->getValue('ip');
358    }
359
360    /**
361     * IPアドレスを設定する.
362     *
363     */
364    function updateIp()
365    {
366        $this->setValue('ip', $_SERVER['REMOTE_ADDR']);
367    }
368
369    /**
370     * REMOTE_ADDRとセッション中のIPが同じかどうかを判定する.
371     * 同じ場合にtrueが返る
372     *
373     * @return boolean
374     */
375    function validateIp()
376    {
377        $ip = $this->getIp();
378        if (!empty($_SERVER['REMOTE_ADDR']) && $ip === $_SERVER['REMOTE_ADDR']) {
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
385        return false;
386    }
387
388    /**
389     * UserAgentもしくは携帯の機種名を取得する.
390     *
391     * @return string
392     */
393    function getModel()
394    {
395        return $this->getValue('model');
396    }
397
398    /**
399     * セッション中のデータ検証する
400     *
401     * @return boolean
402     */
403    function validateSessionData()
404    {
405        foreach ($this->validate as $method) {
406            $method = 'validate' . $method;
407            if (!$this->$method()) {
408                return false;
409            }
410        }
411
412        return true;
413    }
414
415    /**
416     * セッションデータを初期化する.
417     *
418     */
419    function inisializeSessionData()
420    {
421    }
422}
423
424/**
425 * PCサイト用のセッションデータ管理クラス
426 *
427 */
428class LC_UseRequest_State_PC extends LC_UseRequest_State
429{
430    /**
431     * コンストラクタ
432     * セッションのデータ構造は下のようになる.
433     * $_SESSION['pc']=> array(
434     *     ['model']   => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
435     *     ['ip']      => '127.0.0.1'
436     *     ['expires'] => 1204699031
437     * )
438     *
439     * @return LC_UseRequest_State_PC
440     */
441    function LC_UseRequest_State_PC()
442    {
443        $this->namespace = 'pc';
444        $this->lifetime  = SESSION_LIFETIME;
445        $this->validate  = array('NameSpace', 'Model', 'Ip', 'Expire');
446    }
447
448    /**
449     * セッションにUserAgentを設定する.
450     *
451     */
452    function updateModel()
453    {
454        $this->setValue('model', $_SERVER['HTTP_USER_AGENT']);
455    }
456
457    /**
458     * UserAgentを検証する.
459     *
460     * @return boolean
461     */
462    function validateModel()
463    {
464        $ua = $this->getModel();
465        if (!empty($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] === $ua) {
466            return true;
467        }
468        $msg = sprintf('User agent model mismatch : %s != %s(expected), sid=%s',
469                       $_SERVER['HTTP_USER_AGENT'], $ua, session_id());
470        GC_Utils_Ex::gfPrintLog($msg);
471
472        return false;
473    }
474
475    /**
476     * セッションデータを初期化する.
477     *
478     */
479    function inisializeSessionData()
480    {
481        $_SESSION = array();
482        $this->updateModel();
483        $this->updateIp();
484        $this->updateExpire();
485    }
486}
487
488/**
489 * モバイルサイト用のセッションデータ管理クラス
490 *
491 */
492class LC_UseRequest_State_Mobile extends LC_UseRequest_State
493{
494    /**
495     * コンストラクタ
496     * セッションのデータ構造は下のようになる.
497     * $_SESSION['mobile']=> array(
498     *     ['model']   => 901sh
499     *     ['ip']      => 127.0.0.1
500     *     ['expires'] => 1204699031
501     *     ['phone_id']=> ****
502     * )
503     *
504     * @return LC_UseRequest_State_Mobile
505     */
506    function LC_UseRequest_State_Mobile()
507    {
508        $this->namespace = 'mobile';
509        $this->lifetime  = MOBILE_SESSION_LIFETIME;
510        $this->validate  = array('NameSpace', 'Model', 'Expire');
511    }
512
513    /**
514     * 携帯の機種名を設定する
515     *
516     */
517    function updateModel()
518    {
519        $this->setValue('model', SC_MobileUserAgent_Ex::getModel());
520    }
521
522    /**
523     * セッション中の携帯機種名と、アクセスしてきたブラウザの機種名が同じかどうかを判定する
524     *
525     * @return boolean
526     */
527    function validateModel()
528    {
529        $modelInSession = $this->getModel();
530        $model = SC_MobileUserAgent_Ex::getModel();
531        if (!empty($model) && $model === $modelInSession) {
532            return true;
533        }
534
535        return false;
536    }
537
538    /**
539     * 携帯のIDを取得する
540     *
541     * @return string
542     */
543    function getPhoneId()
544    {
545        return $this->getValue('phone_id');
546    }
547
548    /**
549     * 携帯のIDを登録する.
550     *
551     */
552    function updatePhoneId()
553    {
554        $this->setValue('phone_id', SC_MobileUserAgent_Ex::getId());
555    }
556
557    /**
558     * セッションデータを初期化する.
559     *
560     */
561    function inisializeSessionData()
562    {
563        $_SESSION = array();
564        $this->updateModel();
565        $this->updateIp();
566        $this->updateExpire();
567        $this->updatePhoneId();
568    }
569}
570/*
571 * Local variables:
572 * coding: utf-8
573 * End:
574 */
Note: See TracBrowser for help on using the repository browser.