source: branches/version-2_5-dev/data/class/helper/SC_Helper_Mobile.php @ 18770

Revision 18770, 16.5 KB checked in by nanasess, 14 years ago (diff)
  • SC_DbConn のインスタンスを直接使用している個所を SC_Query に変更(#565)
    • 削除予定の機能については未対応
  • SC_Customer で未使用の処理を削除
  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id Revision Date
  • 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-2010 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_PATH . '../module/Net/URL.php');
26require_once(CLASS_PATH . 'SC_Query.php');
27
28/**
29 * モバイルのヘルパークラス.
30 *
31 * @package Helper
32 * @author LOCKON CO.,LTD.
33 * @version $Id$
34 */
35class SC_Helper_Mobile {
36
37    /**
38     * EC-CUBE がサポートする携帯端末かどうかをチェックする。
39     * 非対応端末の場合は /mobile/unsupported/ へリダイレクトする。
40     *
41     * @return void
42     */
43    function lfMobileCheckCompatibility() {
44        if (!SC_MobileUserAgent::isSupported()) {
45            header('Location: ' . URL_DIR . 'mobile/unsupported/' . DIR_INDEX_URL);
46            exit;
47        }
48    }
49
50    /**
51     * 入力データを内部エンコーディングに変換し、絵文字を除去する。
52     *
53     * @param string &$value 入力データへの参照
54     * @return void
55     */
56    function lfMobileConvertInputValue(&$value) {
57        if (is_array($value)) {
58            foreach($value as $key => $val ){
59                $this->lfMobileConvertInputValue($value[$key]);
60            }
61        } else {
62            // Shift JIS から内部エンコーディングに変換する。
63            $value = mb_convert_encoding($value, CHAR_CODE, 'SJIS');
64            // SoftBank? 以外の絵文字は外字領域に含まれるため、この段階で除去される。
65            // SoftBank? の絵文字を除去する。
66            $value = preg_replace('/\\x1b\\$[^\\x0f]*\\x0f/', '', $value);
67        }
68    }
69
70    /**
71     * モバイルサイト用の入力の初期処理を行う。
72     *
73     * @return void
74     */
75    function lfMobileInitInput() {
76        array_walk($_GET, array($this, 'lfMobileConvertInputValue'));
77        array_walk($_POST, array($this, 'lfMobileConvertInputValue'));
78        array_walk($_REQUEST, array($this, 'lfMobileConvertInputValue'));
79    }
80
81    /**
82     * dtb_mobile_ext_session_id テーブルを検索してセッションIDを取得する。
83     *
84     * @return string|null 取得したセッションIDを返す。
85     *                     取得できなかった場合は null を返す。
86     */
87    function lfMobileGetExtSessionId() {
88        if (!preg_match('|^' . URL_DIR . '(.*)$|', $_SERVER['SCRIPT_NAME'], $matches)) {
89            return null;
90        }
91
92        $url = $matches[1];
93        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
94        $objQuery = new SC_Query;
95
96        foreach ($_REQUEST as $key => $value) {
97            $session_id = $objQuery->get('dtb_mobile_ext_session_id', 'session_id',
98                                         'param_key = ? AND param_value = ? AND url = ? AND create_date >= ?',
99                                         array($key, $value, $url, $time));
100            if (isset($session_id)) {
101                return $session_id;
102            }
103        }
104
105        return null;
106    }
107
108    /**
109     * パラメーターから有効なセッションIDを取得する。
110     *
111     * @return string|false 取得した有効なセッションIDを返す。
112     *                      取得できなかった場合は false を返す。
113     */
114    function lfMobileGetSessionId() {
115        // パラメーターからセッションIDを取得する。
116        $sessionId = @$_POST[session_name()];
117        if (!isset($sessionId)) {
118            $sessionId = @$_GET[session_name()];
119        }
120        if (!isset($sessionId)) {
121            $sessionId = $this->lfMobileGetExtSessionId();
122        }
123        if (!isset($sessionId)) {
124            return false;
125        }
126
127        // セッションIDの存在をチェックする。
128        $objSession = new SC_Helper_Session_Ex();
129        if ($objSession->sfSessRead($sessionId) === null) {
130            GC_Utils_Ex::gfPrintLog("Non-existent session id : sid=$sessionId");
131            return false;
132        }
133        return session_id($sessionId);
134    }
135
136    /**
137     * セッションデータが有効かどうかをチェックする。
138     *
139     * FIXME "@" でエラーを抑制するのは良くない
140     *
141     * @return boolean セッションデータが有効な場合は true、無効な場合は false を返す。
142     */
143    function lfMobileValidateSession() {
144        // 配列 mobile が登録されているかどうかをチェックする。
145        if (!is_array(@$_SESSION['mobile'])) {
146            return false;
147        }
148
149        // 有効期限を過ぎていないかどうかをチェックする。
150        if (intval(@$_SESSION['mobile']['expires']) < time()) {
151            GC_Utils_Ex::gfPrintLog("Session expired at " .
152                       date('Y/m/d H:i:s', @$_SESSION['mobile']['expires']) .
153                       ' : sid=' . session_id());
154
155            return false;
156        }
157
158        // 携帯端末の機種が一致するかどうかをチェックする。
159        $model = SC_MobileUserAgent::getModel();
160        if (@$_SESSION['mobile']['model'] != $model) {
161            GC_Utils_Ex::gfPrintLog("User agent model mismatch : " .
162                       "\"$model\" != \"" . @$_SESSION['mobile']['model'] .
163                       '" (expected), sid=' . session_id());
164            return false;
165        }
166
167        return true;
168    }
169
170    /**
171     * モバイルサイト用のセッション関連の初期処理を行う。
172     *
173     * @return void
174     */
175    function lfMobileInitSession() {
176        // セッションIDの受け渡しにクッキーを使用しない。
177        ini_set('session.use_cookies', '0');
178
179        // パラメーターから有効なセッションIDを取得する。
180        $sessionId = $this->lfMobileGetSessionId();
181
182        session_start();
183
184        // セッションIDまたはセッションデータが無効な場合は、セッションIDを再生成
185        // し、セッションデータを初期化する。
186        if ($sessionId === false || !$this->lfMobileValidateSession()) {
187            session_regenerate_id();
188            $_SESSION = array('mobile' => array('model'    => SC_MobileUserAgent::getModel(),
189                                                'phone_id' => SC_MobileUserAgent::getId(),
190                                                'expires'  => time() + MOBILE_SESSION_LIFETIME));
191
192            // 新しいセッションIDを付加してリダイレクトする。
193            if ($_SERVER['REQUEST_METHOD'] == 'GET') {
194                // GET の場合は同じページにリダイレクトする。
195                header('Location: ' . $this->gfAddSessionId());
196            } else {
197                // GET 以外の場合はトップページへリダイレクトする。
198                header('Location: ' . URL_SITE_TOP . '?' . SID);
199            }
200            exit;
201        }
202
203        // 携帯端末IDを取得できた場合はセッションデータに保存する。
204        $phoneId = SC_MobileUserAgent::getId();
205        if ($phoneId !== false) {
206            $_SESSION['mobile']['phone_id'] = $phoneId;
207        }
208
209        // セッションの有効期限を更新する。
210        $_SESSION['mobile']['expires'] = time() + MOBILE_SESSION_LIFETIME;
211    }
212
213    /**
214     * モバイルサイト用の出力の初期処理を行う。
215     *
216     * 出力の流れ
217     * 1. Smarty
218     * 2. 内部エンコーディングから Shift JIS に変換する。
219     * 3. 全角カタカナを半角カタカナに変換する。
220     * 4. 画像用のタグを調整する。
221     * 5. 絵文字タグを絵文字コードに変換する。
222     * 6. 出力
223     *
224     * @return void
225     */
226    function lfMobileInitOutput() {
227        // Smarty 用のディレクトリーを作成する。
228        @mkdir(COMPILE_DIR);
229
230        // 出力用のエンコーディングを Shift JIS に固定する。
231        mb_http_output('SJIS-win');
232
233        // 絵文字タグを絵文字コードに変換する。
234        ob_start(array('SC_MobileEmoji', 'handler'));
235
236        // 端末に合わせて画像サイズを変換する。
237        ob_start(array('SC_MobileImage', 'handler'));
238
239        // 全角カタカナを半角カタカナに変換する。
240        ob_start(create_function('$buffer', 'return mb_convert_kana($buffer, "k", "SJIS-win");'));
241
242        // 内部エンコーディングから Shift JIS に変換する。
243        ob_start('mb_output_handler');
244    }
245
246    /**
247     * モバイルサイト用の初期処理を行う。
248     *
249     * @return void
250     */
251    function sfMobileInit() {
252        $this->lfMobileInitInput();
253
254        if (basename(dirname($_SERVER['SCRIPT_NAME'])) != 'unsupported') {
255            $this->lfMobileCheckCompatibility();
256            /**
257             * 共有SSL対応のため、SC_SessionFactory_UseRequest::initSession()へ移行
258             * また、他のセッション関連メソッドもSC_SessionFactory_UseRequestのインスタンスから呼び出すこと
259             *
260             * @see data/class/session/sessionfactory/SC_SessionFactory_UseRequest.php
261             */
262            // $this->lfMobileInitSession();
263        }
264
265        $this->lfMobileInitOutput();
266    }
267
268    /**
269     * Location等でセッションIDを付加する必要があるURLにセッションIDを付加する。
270     *
271     * @return String
272     */
273    function gfAddSessionId($url = null) {
274        $objURL = new Net_URL($url);
275        $objURL->addQueryString(session_name(), session_id());
276        return $objURL->getURL();
277    }
278
279    /**
280     * セッション ID を付加した配列を返す.
281     *
282     * @param array $array 元となる配列
283     * @param array セッション ID を追加した配列
284     */
285    function sessionIdArray($array = array()) {
286        return array_merge($array, array(session_name() => session_id()));
287    }
288
289    /**
290     * 空メール用のトークンを生成する。
291     *
292     * @return string 生成したトークンを返す。
293     */
294    function lfGenerateKaraMailToken() {
295        $token_chars = '0123456789abcdefghijklmnopqrstuvwxyz';
296        $token_chars_length = strlen($token_chars);
297        $token_length = 10;
298        $token = '';
299
300        while ($token_length > 0) {
301            $token .= $token_chars{mt_rand(0, $token_chars_length - 1)};
302            --$token_length;
303        }
304
305        return $token;
306    }
307
308    /**
309     * 空メール管理テーブルに新規エントリーを登録し、トークンを返す。
310     *
311     * @param string $next_url 空メール受け付け後に遷移させるページ (モバイルサイトトップからの相対URL)
312     * @param string $session_id セッションID (省略した場合は現在のセッションID)
313     * @return string|false トークンを返す。エラーが発生した場合はfalseを返す。
314     */
315    function gfPrepareKaraMail($next_url, $session_id = null) {
316        if (!isset($session_id)) {
317            $session_id = session_id();
318        }
319
320        $objQuery = new SC_Query;
321
322        // GC
323        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
324        $objQuery->delete('dtb_mobile_kara_mail', 'email IS NULL AND create_date < ?', array($time));
325
326        $objQuery->delete('dtb_mobile_kara_mail', 'session_id = ?', array($session_id));
327
328        $arrValues = array('session_id' => $session_id,
329                           'next_url'   => $next_url);
330
331        $try = 10;
332
333        while ($try > 0) {
334            $arrValues['token'] = $token = $this->lfGenerateKaraMailToken();
335
336            $objQuery->insert('dtb_mobile_kara_mail', $arrValues);
337            $count = $objQuery->count('dtb_mobile_kara_mail', 'token = ?', array($token));
338
339            if ($count == 1) {
340                break;
341            }
342
343            $objQuery->delete('dtb_mobile_kara_mail', 'session_id = ?', array($session_id));
344            $token = false;
345            --$try;
346        }
347
348        return $token;
349    }
350
351    /**
352     * 空メールから取得したメールアドレスを空メール管理テーブルに登録する。
353     *
354     * @param string $token トークン
355     * @param string $email メールアドレス
356     * @return boolean 成功した場合はtrue、失敗した場合はfalseを返す。
357     */
358    function gfRegisterKaraMail($token, $email) {
359        $objQuery = new SC_Query;
360
361        // GC
362        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
363        $objQuery->delete('dtb_mobile_kara_mail',
364                          '(email IS NULL AND create_date < ?) OR (email IS NOT NULL AND receive_date < ?)',
365                          array($time, $time));
366
367        $kara_mail_id = $objQuery->get('dtb_mobile_kara_mail', 'kara_mail_id', 'token = ?', array($token));
368        if (!isset($kara_mail_id)) {
369            return false;
370        }
371
372        $arrValues = array('email' => $email);
373        $arrRawValues = array('receive_date' => 'now()');
374        $objQuery->update('dtb_mobile_kara_mail', $arrValues, 'kara_mail_id = ?', array($kara_mail_id), $arrRawValues);
375
376        return true;
377    }
378
379    /**
380     * 空メール管理テーブルからトークンが一致する行を削除し、
381     * 次に遷移させるページのURLを返す。 
382     *
383     * メールアドレスは $_SESSION['mobile']['kara_mail_from'] に登録される。
384     *
385     * @param string $token トークン
386     * @return string|false URLを返す。エラーが発生した場合はfalseを返す。
387     */
388    function gfFinishKaraMail($token) {
389        $objQuery = new SC_Query;
390
391        $arrRow = $objQuery->getRow(
392             'dtb_mobile_kara_mail'
393            ,'session_id, next_url, email'
394            ,'token = ? AND email IS NOT NULL AND receive_date >= ?'
395            ,array($token, date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME))
396            ,DB_FETCHMODE_ORDERED
397        );
398       
399        if (!isset($arrRow)) {
400            return false;
401        }
402
403        $objQuery->delete('dtb_mobile_kara_mail', 'token = ?', array($token));
404
405        list($session_id, $next_url, $email) = $arrRow;
406        $objURL = new Net_URL(MOBILE_SITE_URL . $next_url);
407        $objURL->addQueryString(session_name(), $session_id);
408        $url = $objURL->getURL();
409
410        session_id($session_id);
411        session_start();
412        $_SESSION['mobile']['kara_mail_from'] = $email;
413        session_write_close();
414
415        return $url;
416    }
417
418    /**
419     * 外部サイト連携用にセッションIDとパラメーターの組み合わせを保存する。
420     *
421     * @param string $param_key パラメーター名
422     * @param string $param_value パラメーター値
423     * @param string $url URL
424     * @return void
425     */
426    function sfMobileSetExtSessionId($param_key, $param_value, $url) {
427        $objQuery = new SC_Query;
428
429        // GC
430        $time = date('Y-m-d H:i:s', time() - MOBILE_SESSION_LIFETIME);
431        $objQuery->delete('dtb_mobile_ext_session_id', 'create_date < ?', array($time));
432
433        $arrValues = array('session_id'  => session_id(),
434                           'param_key'   => $param_key,
435                           'param_value' => $param_value,
436                           'url'         => $url);
437
438        $objQuery->insert('dtb_mobile_ext_session_id', $arrValues);
439    }
440
441    /**
442     * メールアドレスが携帯のものかどうかを判別する。
443     *
444     * @param string $address メールアドレス
445     * @return boolean 携帯のメールアドレスの場合はtrue、それ以外の場合はfalseを返す。
446     */
447    function gfIsMobileMailAddress($address) {
448        $masterData = new SC_DB_MasterData_Ex();
449        $arrMobileMailDomains = $masterData->getMasterData("mtb_mobile_domain");
450
451        if (defined('MOBILE_ADDITIONAL_MAIL_DOMAINS')) {
452            $arrMobileMailDomains = array_merge($arrMobileMailDomains, split('[ ,]+', MOBILE_ADDITIONAL_MAIL_DOMAINS));
453        }
454
455        foreach ($arrMobileMailDomains as $domain) {
456            $domain = str_replace('.', '\\.', $domain);
457            if (preg_match("/@([^@]+\\.)?$domain\$/", $address)) {
458                return true;
459            }
460        }
461
462        return false;
463    }
464}
465?>
Note: See TracBrowser for help on using the repository browser.