source: branches/version-2_11-dev/data/class/session/sessionfactory/SC_SessionFactory_UseRequest.php @ 21354

Revision 21354, 15.5 KB checked in by eccuore, 12 years ago (diff)

#1555 モバイルダウンロード対応(一部、スマフォも対応)

MIMETYPE判定追加
カタカナ変換をしている部分でエラー発生していたので、ダウンロード時は変換をしないように修正
AU実機では、Aタグでダウンロード出来ないケースがあるのでTPLでAU判定を追加
AndroidでのPDFダウンロード対応

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