PageRenderTime 72ms CodeModel.GetById 44ms RepoModel.GetById 1ms app.codeStats 0ms

/data/class/helper/SC_Helper_Mobile.php

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