source: branches/version-2_12-dev/data/class/helper/SC_Helper_Mobile.php @ 21420

Revision 21420, 19.1 KB checked in by Seasoft, 12 years ago (diff)

#1613 (ソース整形・ソースコメントの改善)

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