source: branches/version-2_13-dev/data/class/helper/SC_Helper_Mobile.php @ 23493

Revision 23493, 16.8 KB checked in by pineray, 7 years ago (diff)

#2565 セッションに関するクラスや関数を整理

セッションハンドラの登録をファクトリーへ移動.

  • 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 * モバイルのヘルパークラス.
26 *
27 * @package Helper
28 * @author LOCKON CO.,LTD.
29 * @version $Id$
30 */
31class SC_Helper_Mobile
32{
33    /** 基本MimeType */
34    public $defaultMimeType = 'application/force-download';
35
36    /** 拡張MimeType配列
37     * Application/octet-streamで対応出来ないファイルタイプのみ拡張子をキーに記述する
38     * 拡張子が本配列に存在しない場合は application/force-download を利用する */
39    public $arrMimetypes = array(
40            'html'=> 'text/html',
41            'css' => 'text/css',
42            'hdml'=> 'text/x-hdml',
43            'mmf' => 'application/x-smaf',
44            'jpeg'=> 'image/jpeg',
45            'jpg' => 'image/jpeg',
46            'gif' => 'image/gif',
47            'png' => 'image/png',
48            'bmp' => 'image/x-ms-bmp',
49            'amc' => 'application/x-mpeg',
50            '3g2' => 'video/3gpp2',
51            '3gp' => 'video/3gpp',
52            'jam' => 'application/x-jam',
53            'kjx' => 'application/x-kjx',
54            'jar' => 'application/java-archive',
55            'jad' => 'text/vnd.sun.j2me.app-descriptor',
56            'swf' => 'application/x-shockwave-flash',
57            'dmt' => 'application/x-decomail-template',
58            'khm' => 'application/x-kddi-htmlmail',
59            'hmt' => 'application/x-htmlmail-template',
60            'ucm' => 'application/x-ucf-package',
61            'ucp' => 'application/x-ucf-package',
62            'pdf' => 'application/pdf',
63            'wma' => 'audio/x-ms-wma',
64            'asf' => 'video/x-ms-asf',
65            'wax' => 'audio/x-ms-wax',
66            'wvx' => 'video/x-ms-wvx',
67            'wmv' => 'video/x-ms-wmv',
68            'asx' => 'video/asx',
69            'txt' => 'text/plain',
70            'exe' => 'application/octet-stream',
71            'zip' => 'application/zip',
72            'doc' => 'application/msword',
73            'xls' => 'application/vnd.ms-excel',
74            'ppt' => 'application/vnd.ms-powerpoint'
75        );
76
77    /**
78     * EC-CUBE がサポートする携帯端末かどうかをチェックする。
79     * 非対応端末の場合は /unsupported/ へリダイレクトする。
80     *
81     * @return void
82     */
83    public function lfMobileCheckCompatibility()
84    {
85        if (!SC_MobileUserAgent_Ex::isSupported()) {
86            header('Location: ' . ROOT_URLPATH . 'unsupported/' . DIR_INDEX_PATH);
87            exit;
88        }
89    }
90
91    /**
92     * 入力データを内部エンコーディングに変換し、絵文字を除去する。
93     *
94     * @param string &$value 入力データへの参照
95     * @return void
96     */
97    public function lfMobileConvertInputValue(&$value)
98    {
99        if (is_array($value)) {
100            foreach ($value as $key => $val) {
101                $this->lfMobileConvertInputValue($value[$key]);
102            }
103        } else {
104            // Shift JIS から内部エンコーディングに変換する。
105            $value = mb_convert_encoding($value, CHAR_CODE, 'SJIS');
106            // SoftBank? 以外の絵文字は外字領域に含まれるため、この段階で除去される。
107            // SoftBank? の絵文字を除去する。
108            $value = preg_replace('/\\x1b\\$[^\\x0f]*\\x0f/', '', $value);
109        }
110    }
111
112    /**
113     * モバイルサイト用の入力の初期処理を行う。
114     *
115     * @return void
116     */
117    public function lfMobileInitInput()
118    {
119        array_walk($_GET, array($this, 'lfMobileConvertInputValue'));
120        array_walk($_POST, array($this, 'lfMobileConvertInputValue'));
121        array_walk($_REQUEST, array($this, 'lfMobileConvertInputValue'));
122    }
123
124    /**
125     * dtb_mobile_ext_session_id テーブルを検索してセッションIDを取得する。
126     *
127     * @return string|null 取得したセッションIDを返す。
128     *                     取得できなかった場合は null を返す。
129     */
130    public function lfMobileGetExtSessionId()
131    {
132        if (!preg_match('|^' . ROOT_URLPATH . '(.*)$|', $_SERVER['SCRIPT_NAME'], $matches)) {
133            return null;
134        }
135
136        $url = $matches[1];
137        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
138        $objQuery =& SC_Query_Ex::getSingletonInstance();
139
140        foreach ($_REQUEST as $key => $value) {
141            $session_id = $objQuery->get('session_id', 'dtb_mobile_ext_session_id',
142                                         'param_key = ? AND param_value = ? AND url = ? AND create_date >= ?',
143                                         array($key, $value, $url, $time));
144            if (isset($session_id)) {
145                return $session_id;
146            }
147        }
148
149        return null;
150    }
151
152    /**
153     * パラメーターから有効なセッションIDを取得する。
154     *
155     * @return string|false 取得した有効なセッションIDを返す。
156     *                      取得できなかった場合は false を返す。
157     */
158    public function lfMobileGetSessionId()
159    {
160        // パラメーターからセッションIDを取得する。
161        $sessionId = @$_POST[session_name()];
162        if (!isset($sessionId)) {
163            $sessionId = @$_GET[session_name()];
164        }
165        if (!isset($sessionId)) {
166            $sessionId = $this->lfMobileGetExtSessionId();
167        }
168        if (!isset($sessionId)) {
169            return false;
170        }
171
172        // セッションIDの存在をチェックする。
173        $sessionFactory = SC_SessionFactory_Ex::getInstance();
174        if ($sessionFactory->sfSessRead($sessionId) === null) {
175            GC_Utils_Ex::gfPrintLog("Non-existent session id : sid=$sessionId");
176
177            return false;
178        }
179
180        return session_id($sessionId);
181    }
182
183    /**
184     * セッションデータが有効かどうかをチェックする。
185     *
186     * FIXME '@' でエラーを抑制するのは良くない
187     *
188     * @return boolean セッションデータが有効な場合は true、無効な場合は false を返す。
189     */
190    public function lfMobileValidateSession()
191    {
192        // 配列 mobile が登録されているかどうかをチェックする。
193        if (!is_array(@$_SESSION['mobile'])) {
194            return false;
195        }
196
197        // 有効期限を過ぎていないかどうかをチェックする。
198        if (intval(@$_SESSION['mobile']['expires']) < time()) {
199            $msg = 'Session expired at ' . date('Y/m/d H:i:s', @$_SESSION['mobile']['expires'])
200                 . ' : sid=' . session_id();
201            GC_Utils_Ex::gfPrintLog($msg);
202
203            return false;
204        }
205
206        // 携帯端末の機種が一致するかどうかをチェックする。
207        $model = SC_MobileUserAgent_Ex::getModel();
208        if (@$_SESSION['mobile']['model'] != $model) {
209            $msg = 'User agent model mismatch : '
210                 . '"$model" != "' . @$_SESSION['mobile']['model']
211                 . '" (expected), sid=' . session_id();
212            GC_Utils_Ex::gfPrintLog($msg);
213
214            return false;
215        }
216
217        return true;
218    }
219
220    /**
221     * モバイルサイト用の出力の初期処理を行う。
222     *
223     * 出力の流れ
224     * 1. ページクラスでの出力
225     * 2. 全角カタカナを半角カタカナに変換する。
226     * 3. 内部エンコーディングから Shift JIS に変換する。
227     * 4. 画像を調整する。
228     * 5. 絵文字タグを絵文字コードに変換する。(require.php で設定)
229     *
230     * @return void
231     */
232    public function lfMobileInitOutput()
233    {
234        // 出力用のエンコーディングを Shift JIS に固定する。
235        mb_http_output('SJIS-win');
236
237        // 端末に合わせて画像サイズを変換する。
238        ob_start(array('SC_MobileImage_Ex', 'handler'));
239
240        // 内部エンコーディングから Shift JIS に変換する。
241        ob_start('mb_output_handler');
242
243        //download.phpに対してカタカナ変換をするとファイルが壊れてしまうため回避する
244        if ($_SERVER['SCRIPT_FILENAME'] != HTML_REALDIR . 'mypage/download.php') {
245            // 全角カタカナを半角カタカナに変換する。
246            ob_start(create_function('$buffer', 'return mb_convert_kana($buffer, "k");'));
247        }
248    }
249
250    /**
251     * モバイルサイト用の初期処理を行う。
252     *
253     * @return void
254     */
255    public function sfMobileInit()
256    {
257        $this->lfMobileInitInput();
258
259        if (basename(dirname($_SERVER['SCRIPT_NAME'])) != 'unsupported') {
260            $this->lfMobileCheckCompatibility();
261        }
262
263        $this->lfMobileInitOutput();
264    }
265
266    /**
267     * Location等でセッションIDを付加する必要があるURLにセッションIDを付加する。
268     *
269     * @return String
270     */
271    public function gfAddSessionId($url = null)
272    {
273        $objURL = new Net_URL($url);
274        $objURL->addQueryString(session_name(), session_id());
275
276        return $objURL->getURL();
277    }
278
279    /**
280     * セッション ID を付加した配列を返す.
281     *
282     * @param array $array 元となる配列
283     * @param array セッション ID を追加した配列
284     */
285    public function sessionIdArray($array = array())
286    {
287        return array_merge($array, array(session_name() => session_id()));
288    }
289
290    /**
291     * 空メール用のトークンを生成する。
292     *
293     * @return string 生成したトークンを返す。
294     */
295    public function lfGenerateKaraMailToken()
296    {
297        $token_chars = '0123456789abcdefghijklmnopqrstuvwxyz';
298        $token_chars_length = strlen($token_chars);
299        $token_length = 10;
300        $token = '';
301
302        while ($token_length > 0) {
303            $token .= $token_chars{mt_rand(0, $token_chars_length - 1)};
304            --$token_length;
305        }
306
307        return $token;
308    }
309
310    /**
311     * 空メール管理テーブルに新規エントリーを登録し、トークンを返す。
312     *
313     * @param  string       $next_url   空メール受け付け後に遷移させるページ (モバイルサイトトップからの相対URL)
314     * @param  string       $session_id セッションID (省略した場合は現在のセッションID)
315     * @return string|false トークンを返す。エラーが発生した場合はfalseを返す。
316     */
317    public function gfPrepareKaraMail($next_url, $session_id = null)
318    {
319        if (!isset($session_id)) {
320            $session_id = session_id();
321        }
322
323        $objQuery =& SC_Query_Ex::getSingletonInstance();
324
325        // GC
326        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
327        $objQuery->delete('dtb_mobile_kara_mail', 'email IS NULL AND create_date < ?', array($time));
328
329        $objQuery->delete('dtb_mobile_kara_mail', 'session_id = ?', array($session_id));
330
331        $arrValues = array(
332            'session_id' => $session_id,
333            'next_url'   => $next_url,
334        );
335
336        $try = 10;
337
338        while ($try > 0) {
339            $arrValues['token'] = $token = $this->lfGenerateKaraMailToken();
340
341            $arrValues['kara_mail_id'] = $objQuery->nextVal('dtb_mobile_kara_mail_kara_mail_id');
342            $objQuery->insert('dtb_mobile_kara_mail', $arrValues);
343            $exists = $objQuery->exists('dtb_mobile_kara_mail', 'token = ?', array($token));
344
345            if ($exists) {
346                break;
347            }
348
349            $objQuery->delete('dtb_mobile_kara_mail', 'session_id = ?', array($session_id));
350            $token = false;
351            --$try;
352        }
353
354        return $token;
355    }
356
357    /**
358     * 空メールから取得したメールアドレスを空メール管理テーブルに登録する。
359     *
360     * @param  string  $token トークン
361     * @param  string  $email メールアドレス
362     * @return boolean 成功した場合はtrue、失敗した場合はfalseを返す。
363     */
364    public function gfRegisterKaraMail($token, $email)
365    {
366        $objQuery =& SC_Query_Ex::getSingletonInstance();
367
368        // GC
369        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
370        $objQuery->delete('dtb_mobile_kara_mail',
371                          '(email IS NULL AND create_date < ?) OR (email IS NOT NULL AND receive_date < ?)',
372                          array($time, $time));
373
374        $kara_mail_id = $objQuery->get('kara_mail_id', 'dtb_mobile_kara_mail', 'token = ?', array($token));
375        if (!isset($kara_mail_id)) {
376            return false;
377        }
378
379        $arrValues = array('email' => $email);
380        $arrRawValues = array('receive_date' => 'CURRENT_TIMESTAMP');
381        $objQuery->update('dtb_mobile_kara_mail', $arrValues, 'kara_mail_id = ?', array($kara_mail_id), $arrRawValues);
382
383        return true;
384    }
385
386    /**
387     * 空メール管理テーブルからトークンが一致する行を削除し、
388     * 次に遷移させるページのURLを返す。 
389     *
390     * メールアドレスは $_SESSION['mobile']['kara_mail_from'] に登録される。
391     *
392     * @param  string       $token トークン
393     * @return string|false URLを返す。エラーが発生した場合はfalseを返す。
394     */
395    public function gfFinishKaraMail($token)
396    {
397        $objQuery =& SC_Query_Ex::getSingletonInstance();
398
399        $arrRow = $objQuery->getRow(
400             'session_id, next_url, email'
401            ,'dtb_mobile_kara_mail'
402            ,'token = ? AND email IS NOT NULL AND receive_date >= ?'
403            ,array($token, date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME))
404            ,DB_FETCHMODE_ORDERED
405        );
406
407        if (!isset($arrRow)) {
408            return false;
409        }
410
411        $objQuery->delete('dtb_mobile_kara_mail', 'token = ?', array($token));
412
413        list($session_id, $next_url, $email) = $arrRow;
414        $objURL = new Net_URL(HTTP_URL . $next_url);
415        $objURL->addQueryString(session_name(), $session_id);
416        $url = $objURL->getURL();
417
418        session_id($session_id);
419        session_start();
420        $_SESSION['mobile']['kara_mail_from'] = $email;
421        session_write_close();
422
423        return $url;
424    }
425
426    /**
427     * 外部サイト連携用にセッションIDとパラメーターの組み合わせを保存する。
428     *
429     * @param  string $param_key   パラメーター名
430     * @param  string $param_value パラメーター値
431     * @param  string $url         URL
432     * @return void
433     */
434    public function sfMobileSetExtSessionId($param_key, $param_value, $url)
435    {
436        $objQuery =& SC_Query_Ex::getSingletonInstance();
437
438        // GC
439        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
440        $objQuery->delete('dtb_mobile_ext_session_id', 'create_date < ?', array($time));
441
442        $arrValues = array(
443            'session_id'  => session_id(),
444            'param_key'   => $param_key,
445            'param_value' => $param_value,
446            'url'         => $url,
447        );
448
449        $objQuery->insert('dtb_mobile_ext_session_id', $arrValues);
450    }
451
452    /**
453     * メールアドレスが携帯のものかどうかを判別する。
454     *
455     * @param  string  $address メールアドレス
456     * @return boolean 携帯のメールアドレスの場合はtrue、それ以外の場合はfalseを返す。
457     */
458    public function gfIsMobileMailAddress($address)
459    {
460        $masterData = new SC_DB_MasterData_Ex();
461        $arrMobileMailDomains = $masterData->getMasterData('mtb_mobile_domain');
462
463        foreach ($arrMobileMailDomains as $domain) {
464            $domain = preg_quote($domain, '/');
465            if (preg_match("/@([^@]+\\.)?$domain\$/", $address)) {
466                return true;
467            }
468        }
469
470        return false;
471    }
472
473    /**
474     * ファイルのMIMEタイプを判別する
475     *
476     * @param  string $filename ファイル名
477     * @return string MIMEタイプ
478     */
479    public function getMimeType($filename)
480    {
481        //ファイルの拡張子からコンテンツタイプを決定する
482        $file_extension = strtolower(substr(strrchr($filename,'.'),1));
483        $mime_type = $this->defaultMimeType;
484        if (array_key_exists($file_extension, $this->arrMimetypes)) {
485            $mime_type = $this->arrMimetypes[$file_extension];
486        }
487
488        return $mime_type;
489    }
490}
Note: See TracBrowser for help on using the repository browser.