source: branches/feature-module-update/data/class/helper/SC_Helper_Mobile.php @ 16209

Revision 16209, 15.6 KB checked in by nanasess, 17 years ago (diff)

クラス化に伴う修正

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