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

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