PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/baser/controllers/baser_app_controller.php

https://github.com/miquolone/basercms
PHP | 1490 lines | 812 code | 164 blank | 514 comment | 226 complexity | 4de351c189857bbec4207492831585ec MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Controller 拡張クラス
  5. *
  6. * PHP versions 5
  7. *
  8. * baserCMS : Based Website Development Project <http://basercms.net>
  9. * Copyright 2008 - 2012, baserCMS Users Community <http://sites.google.com/site/baserusers/>
  10. *
  11. * @copyright Copyright 2008 - 2012, baserCMS Users Community
  12. * @link http://basercms.net baserCMS Project
  13. * @package baser.controllers
  14. * @since baserCMS v 0.1.0
  15. * @version $Revision$
  16. * @modifiedby $LastChangedBy$
  17. * @lastmodified $Date$
  18. * @license http://basercms.net/license/index.html
  19. */
  20. /**
  21. * Include files
  22. */
  23. App::import('View', 'AppView');
  24. App::import('Component','BcAuthConfigure');
  25. //App::import('Component', 'Emoji');
  26. /**
  27. * Controller 拡張クラス
  28. *
  29. * @package baser.controllers
  30. */
  31. class BaserAppController extends Controller {
  32. /**
  33. * view
  34. *
  35. * @var string
  36. */
  37. var $view = 'App';
  38. /**
  39. * ページタイトル
  40. *
  41. * @var string
  42. * @access public
  43. */
  44. var $pageTitle = '';
  45. /**
  46. * ヘルパー
  47. *
  48. * @var mixed
  49. * @access public
  50. */
  51. // TODO 見直し
  52. var $helpers = array(
  53. 'Session', 'BcPluginHook', BC_HTML_HELPER, BC_HTML_HELPER, 'Form', BC_FORM_HELPER,
  54. 'Javascript', BC_BASER_HELPER, BC_XML_HELPER, BC_ARRAY_HELPER, BC_BASER_ADMIN_HELPER
  55. );
  56. /**
  57. * レイアウト
  58. *
  59. * @var string
  60. * @access public
  61. */
  62. var $layout = 'default';
  63. /**
  64. * モデル
  65. *
  66. * @var mixed
  67. * @access protected
  68. * TODO メニュー管理を除外後、GlobalMenuを除外する
  69. */
  70. var $uses = array('GlobalMenu', 'Favorite');
  71. /**
  72. * コンポーネント
  73. *
  74. * @var array
  75. * @access public
  76. */
  77. var $components = array('BcPluginHook', 'RequestHandler', 'Security', 'Session');
  78. /**
  79. * サブディレクトリ
  80. *
  81. * @var string
  82. * @access public
  83. */
  84. var $subDir = null;
  85. /**
  86. * サブメニューエレメント
  87. *
  88. * @var string
  89. * @access public
  90. */
  91. var $subMenuElements = '';
  92. /**
  93. * パンくずナビ
  94. *
  95. * @var array
  96. * @access public
  97. */
  98. var $crumbs = array();
  99. /**
  100. * 検索ボックス
  101. *
  102. * @var string
  103. * @access public
  104. */
  105. var $search = '';
  106. /**
  107. * ヘルプ
  108. *
  109. * @var string
  110. * @access public
  111. */
  112. var $help = '';
  113. /**
  114. * ページ説明文
  115. *
  116. * @var string
  117. * @access public
  118. */
  119. var $siteDescription = '';
  120. /**
  121. * コンテンツタイトル
  122. *
  123. * @var string
  124. * @access public
  125. */
  126. var $contentsTitle = '';
  127. /**
  128. * サイトコンフィグデータ
  129. *
  130. * @var array
  131. * @access public
  132. */
  133. var $siteConfigs = array();
  134. /**
  135. * コンストラクタ
  136. *
  137. * @return void
  138. * @access private
  139. */
  140. function __construct() {
  141. parent::__construct();
  142. if(BC_INSTALLED) {
  143. // サイト基本設定の読み込み
  144. $SiteConfig = ClassRegistry::init('SiteConfig','Model');
  145. $this->siteConfigs = $SiteConfig->findExpanded();
  146. if(empty($this->siteConfigs['version'])) {
  147. $this->siteConfigs['version'] = $this->getBaserVersion();
  148. $SiteConfig->saveKeyValue($this->siteConfigs);
  149. }
  150. } elseif($this->name != 'Installations') {
  151. $this->redirect('/');
  152. }
  153. // TODO beforeFilterでも定義しているので整理する
  154. if($this->name == 'CakeError') {
  155. $this->uses = null;
  156. $params = Router::parse(@$_SERVER['REQUEST_URI']);
  157. $this->setTheme($params);
  158. // モバイルのエラー用
  159. if(Configure::read('BcRequest.agent')) {
  160. $this->layoutPath = Configure::read('BcRequest.agentPrefix');
  161. if(Configure::read('BcRequest.agent') == 'mobile') {
  162. $this->helpers[] = BC_MOBILE_HELPER;
  163. }
  164. }
  165. if(!empty($params['admin'])) {
  166. $this->layoutPath = 'admin';
  167. $this->subDir = 'admin';
  168. }
  169. }
  170. if(Configure::read('BcRequest.agent') == 'mobile') {
  171. if(!Configure::read('BcApp.mobile')) {
  172. $this->notFound();
  173. }
  174. }
  175. if(Configure::read('BcRequest.agent') == 'smartphone') {
  176. if(!Configure::read('BcApp.smartphone')) {
  177. $this->notFound();
  178. }
  179. }
  180. /* 携帯用絵文字のモデルとコンポーネントを設定 */
  181. // TODO 携帯をコンポーネントなどで判別し、携帯からのアクセスのみ実行させるようにする
  182. // ※ コンストラクト時点で、$this->params['prefix']を利用できない為。
  183. // TODO 2008/10/08 egashira
  184. // beforeFilterに移動してみた。実際に携帯を使うサイトで使えるかどうか確認する
  185. //$this->uses[] = 'EmojiData';
  186. //$this->components[] = 'Emoji';
  187. }
  188. /**
  189. * beforeFilter
  190. *
  191. * @return void
  192. * @access public
  193. */
  194. function beforeFilter() {
  195. parent::beforeFilter();
  196. if(!BC_INSTALLED || Configure::read('BcRequest.isUpdater')) {
  197. return;
  198. }
  199. // テーマを設定
  200. $this->setTheme($this->params);
  201. // テーマのヘルパーをセット
  202. $this->setThemeHelpers();
  203. if($this->params['controller'] != 'installations') {
  204. // ===============================================================================
  205. // テーマ内プラグインのテンプレートをテーマに梱包できるようにプラグインパスにテーマのパスを追加
  206. // 実際には、プラグインの場合も下記パスがテンプレートの検索対象となっている為不要だが、
  207. // ビューが存在しない場合に、プラグインテンプレートの正規のパスがエラーメッセージに
  208. // 表示されてしまうので明示的に指定している。
  209. // (例)
  210. // [変更後] app/webroot/themed/demo/blog/news/index.php
  211. // [正 規] app/plugins/blog/views/themed/demo/blog/news/index.php
  212. // 但し、CakePHPの仕様としてはテーマ内にプラグインのテンプレートを梱包できる仕様となっていないので
  213. // 将来的には、blog / mail / feed をプラグインではなくコアへのパッケージングを検討する必要あり。
  214. // ※ AppView::_pathsも関連している
  215. // ===============================================================================
  216. $pluginThemePath = WWW_ROOT.'themed' . DS . $this->theme . DS;
  217. $pluginPaths = Configure::read('pluginPaths');
  218. if(!in_array($pluginThemePath, $pluginPaths)) {
  219. Configure::write('pluginPaths', am(array($pluginThemePath), $pluginPaths));
  220. }
  221. }
  222. // 初回アクセスメッセージ表示設定
  223. if(isset($this->params['prefix']) && $this->params['prefix'] == 'admin' && !empty($this->siteConfigs['first_access'])) {
  224. $data = array('SiteConfig' => array('first_access' => false));
  225. $SiteConfig = ClassRegistry::init('SiteConfig','Model');
  226. $SiteConfig->saveKeyValue($data);
  227. }
  228. // メンテナンス
  229. if(!empty($this->siteConfigs['maintenance']) &&
  230. ($this->params['controller'] != 'maintenance' && $this->params['url']['url'] != 'maintenance') &&
  231. (!isset($this->params['prefix']) || $this->params['prefix'] != 'admin') &&
  232. (Configure::read('debug') < 1 && empty($_SESSION['Auth']['User']))){
  233. if(!empty($this->params['return']) && !empty($this->params['requested'])){
  234. return;
  235. }else{
  236. $this->redirect('/maintenance');
  237. }
  238. }
  239. /* 認証設定 */
  240. if(isset($this->BcAuthConfigure) && isset($this->params['prefix'])) {
  241. $configs = Configure::read('BcAuthPrefix');
  242. if(isset($configs[$this->params['prefix']])) {
  243. $config = $configs[$this->params['prefix']];
  244. } else {
  245. $config = array();
  246. }
  247. $this->BcAuthConfigure->setting($config);
  248. }
  249. // 送信データの文字コードを内部エンコーディングに変換
  250. $this->__convertEncodingHttpInput();
  251. // $this->params['url'] の調整
  252. // 環境によって?キーにamp;が付加されてしまうため
  253. if(isset($this->params['url']) && is_array($this->params['url'])) {
  254. foreach ($this->params['url'] as $key => $val ) {
  255. if ( strpos( $key, 'amp;' ) === 0 ) {
  256. $this->params['url'][substr( $key, 4 )] = $val;
  257. unset( $this->params['url'][$key] );
  258. }
  259. }
  260. }
  261. /* レイアウトとビュー用サブディレクトリの設定 */
  262. if(isset($this->params['prefix'])) {
  263. $this->layoutPath = str_replace('_', '/', $this->params['prefix']);
  264. $this->subDir = str_replace('_', '/', $this->params['prefix']);
  265. if(preg_match('/^mobile(|_)/', $this->params['prefix'])) {
  266. $this->helpers[] = BC_MOBILE_HELPER;
  267. }
  268. }
  269. // Ajax
  270. if(isset($this->RequestHandler) && $this->RequestHandler->isAjax() || !empty($this->params['url']['ajax'])) {
  271. // キャッシュ対策
  272. header("Cache-Control: no-cache, must-revalidate");
  273. header("Cache-Control: post-check=0, pre-check=0", false);
  274. header("Pragma: no-cache");
  275. }
  276. // 権限チェック
  277. if(isset($this->BcAuth) && isset($this->params['prefix']) && !Configure::read('BcRequest.agent') && isset($this->params['action']) && empty($this->params['requested'])) {
  278. if(!$this->BcAuth->allowedActions || !in_array($this->params['action'], $this->BcAuth->allowedActions)) {
  279. $user = $this->BcAuth->user();
  280. $Permission = ClassRegistry::init('Permission');
  281. $userModel = Configure::read('BcAuthPrefix.'.$this->params['prefix'].'.userModel');
  282. if(!$Permission->check($this->params['url']['url'],$user[$this->BcAuth->userModel]['user_group_id'])) {
  283. $this->Session->setFlash('指定されたページへのアクセスは許可されていません。');
  284. $this->redirect($this->BcAuth->loginAction);
  285. }
  286. }
  287. }
  288. // SSLリダイレクト設定
  289. if(Configure::read('BcApp.adminSsl') && !empty($this->params['admin'])) {
  290. $adminSslMethods = array_filter(get_class_methods(get_class($this)), array($this, '_adminSslMethods'));
  291. if($adminSslMethods) {
  292. $this->Security->blackHoleCallback = '_sslFail';
  293. $this->Security->requireSecure = $adminSslMethods;
  294. }
  295. } else {
  296. $this->Security->enabled = false;
  297. }
  298. // 管理画面は送信データチェックを行わない(全て対応させるのは大変なので暫定処置)
  299. if($this->Security->enabled && !empty($this->params['admin'])) {
  300. $this->Security->validatePost = false;
  301. }
  302. }
  303. /**
  304. * テーマをセットする
  305. *
  306. * @param array $params
  307. * @return void
  308. * @access public
  309. */
  310. function setTheme($params) {
  311. if(BC_INSTALLED && $params['controller'] != 'installations') {
  312. if(empty($this->siteConfigs['admin_theme']) && Configure::read('Baser.adminTheme')) {
  313. $this->siteConfigs['admin_theme'] = Configure::read('Baser.adminTheme');
  314. }
  315. if(empty($params['admin'])) {
  316. $this->theme = $this->siteConfigs['theme'];
  317. } else {
  318. if(!empty($this->siteConfigs['admin_theme'])) {
  319. $this->theme = $this->siteConfigs['admin_theme'];
  320. } else {
  321. $this->theme = $this->siteConfigs['theme'];
  322. }
  323. }
  324. }
  325. }
  326. /**
  327. * 管理画面用のメソッドを取得(コールバックメソッド)
  328. *
  329. * @param string $var
  330. * @return boolean
  331. * @access public
  332. */
  333. function _adminSslMethods($var) {
  334. return preg_match('/^admin_/', $var);
  335. }
  336. /**
  337. * beforeRender
  338. *
  339. * @return void
  340. * @access public
  341. */
  342. function beforeRender() {
  343. parent::beforeRender();
  344. // テンプレートの拡張子
  345. // RSSの場合、RequestHandlerのstartupで強制的に拡張子を.ctpに切り替えられてしまう為、
  346. // beforeRenderにて設定する仕様にした
  347. $this->ext = Configure::read('BcApp.templateExt');
  348. // モバイルでは、mobileHelper::afterLayout をフックしてSJISへの変換が必要だが、
  349. // エラーが発生した場合には、afterLayoutでは、エラー用のビューを持ったviewクラスを取得できない。
  350. // 原因は、エラーが発生する前のcontrollerがviewを登録してしまっている為。
  351. // エラー時のview登録にフックする場所はここしかないのでここでviewの登録を削除する
  352. if($this->name == 'CakeError') {
  353. ClassRegistry::removeObject('view');
  354. }
  355. $this->__loadDataToView();
  356. $this->set('isSSL', $this->RequestHandler->isSSL());
  357. $this->set('safeModeOn', ini_get('safe_mode'));
  358. $this->set('contentsTitle',$this->contentsTitle);
  359. $this->set('baserVersion',$this->getBaserVersion());
  360. $this->set('siteConfig',$this->siteConfigs);
  361. if(isset($this->siteConfigs['widget_area'])){
  362. $this->set('widgetArea',$this->siteConfigs['widget_area']);
  363. }
  364. }
  365. /**
  366. * SSLエラー処理
  367. *
  368. * SSL通信が必要なURLの際にSSLでない場合、
  369. * SSLのURLにリダイレクトさせる
  370. *
  371. * @param string $err
  372. * @return void
  373. * @access protected
  374. */
  375. function _sslFail($err) {
  376. if ($err === 'secure') {
  377. // 共用SSLの場合、設置URLがサブディレクトリになる場合があるので、$this->here は利用せずURLを生成する
  378. $url = $this->params['url']['url'];
  379. if(Configure::read('App.baseUrl')) {
  380. $url = 'index.php/'.$url;
  381. }
  382. $url = Configure::read('BcEnv.sslUrl').$url;
  383. $this->redirect($url);
  384. exit();
  385. }
  386. }
  387. /**
  388. * NOT FOUNDページを出力する
  389. *
  390. * @return void
  391. * @access public
  392. */
  393. function notFound() {
  394. return $this->cakeError('error404', array(array($this->here)));
  395. }
  396. /**
  397. * 配列の文字コードを変換する
  398. *
  399. * @param array 変換前データ
  400. * @param string 変換後の文字コード
  401. * @return array 変換後データ
  402. * @access protected
  403. */
  404. function _autoConvertEncodingByArray($data, $outenc) {
  405. foreach($data as $key=>$value) {
  406. if(is_array($value)) {
  407. $data[$key] = $this->_autoConvertEncodingByArray($value, $outenc);
  408. } else {
  409. if(isset($this->params['prefix']) && $this->params['prefix'] == 'mobile') {
  410. $inenc = 'SJIS';
  411. }else {
  412. $inenc = mb_detect_encoding($value);
  413. }
  414. if ($inenc != $outenc) {
  415. // 半角カナは一旦全角に変換する
  416. $value = mb_convert_kana($value, "KV",$inenc);
  417. //var_dump($value);
  418. $value = mb_convert_encoding($value, $outenc, $inenc);
  419. //var_dump(mb_convert_encoding($value,'SJIS','UTF-8'));
  420. $data[$key] = $value;
  421. }
  422. }
  423. }
  424. return $data;
  425. }
  426. /**
  427. * View用のデータを読み込む。
  428. * beforeRenderで呼び出される
  429. *
  430. * @return void
  431. * @access private
  432. */
  433. function __loadDataToView() {
  434. $this->set('subMenuElements',$this->subMenuElements); // サブメニューエレメント
  435. $this->set('crumbs',$this->crumbs); // パンくずなび
  436. $this->set('search', $this->search);
  437. $this->set('help', $this->help);
  438. /* ログインユーザー */
  439. if (BC_INSTALLED && isset($_SESSION['Auth']['User']) && $this->name != 'Installations' && !Configure::read('BcRequest.isUpdater') && !Configure::read('BcRequest.isMaintenance') && $this->name != 'CakeError') {
  440. $this->set('user',$_SESSION['Auth']['User']);
  441. if(!empty($this->params['admin'])) {
  442. $this->set('favorites', $this->Favorite->find('all', array('conditions' => array('Favorite.user_id' => $_SESSION['Auth']['User']['id']), 'order' => 'Favorite.sort', 'recursive' => -1)));
  443. }
  444. }
  445. /* 携帯用絵文字データの読込 */
  446. // TODO 実装するかどうか検討する
  447. /*if(isset($this->params['prefix']) && $this->params['prefix'] == 'mobile' && !empty($this->EmojiData)) {
  448. $emojiData = $this->EmojiData->find('all');
  449. $this->set('emoji',$this->Emoji->EmojiData($emojiData));
  450. }*/
  451. }
  452. /**
  453. * baserCMSのバージョンを取得する
  454. *
  455. * @return string Baserバージョン
  456. * @access public
  457. */
  458. function getBaserVersion($plugin = '') {
  459. return getVersion($plugin);
  460. }
  461. /**
  462. * テーマのバージョン番号を取得する
  463. *
  464. * @param string $theme
  465. * @return string
  466. * @access public
  467. */
  468. function getThemeVersion($theme) {
  469. $path = WWW_ROOT.'themed'.DS.$theme.DS.'VERSION.txt';
  470. if(!file_exists($path)) {
  471. return false;
  472. }
  473. App::import('File');
  474. $versionFile = new File($path);
  475. $versionData = $versionFile->read();
  476. $aryVersionData = split("\n",$versionData);
  477. if(!empty($aryVersionData[0])) {
  478. return $aryVersionData[0];
  479. }else {
  480. return false;
  481. }
  482. }
  483. /**
  484. * DBのバージョンを取得する
  485. *
  486. * @return string
  487. * @access public
  488. */
  489. function getSiteVersion($plugin = '') {
  490. if(!$plugin) {
  491. if(isset($this->siteConfigs['version'])) {
  492. return preg_replace("/baserCMS ([0-9\.]+?[\sa-z]*)/is","$1",$this->siteConfigs['version']);
  493. } else {
  494. return '';
  495. }
  496. } else {
  497. $Plugin = ClassRegistry::init('Plugin');
  498. return $Plugin->field('version', array('name'=>$plugin));
  499. }
  500. }
  501. /**
  502. * CakePHPのバージョンを取得する
  503. *
  504. * @return string Baserバージョン
  505. */
  506. function getCakeVersion() {
  507. App::import('File');
  508. $versionFile = new File(CAKE_CORE_INCLUDE_PATH.DS.CAKE.'VERSION.txt');
  509. $versionData = $versionFile->read();
  510. $lines = split("\n",$versionData);
  511. $version = null;
  512. foreach($lines as $line) {
  513. if(preg_match('/^([0-9\.]+)$/', $line, $matches)) {
  514. $version = $matches[1];
  515. break;
  516. }
  517. }
  518. if($version) {
  519. return $version;
  520. }else {
  521. return false;
  522. }
  523. }
  524. /**
  525. * http経由で送信されたデータを変換する
  526. * とりあえず、UTF-8で固定
  527. *
  528. * @return void
  529. * @access private
  530. */
  531. function __convertEncodingHttpInput() {
  532. // TODO Cakeマニュアルに合わせた方がよいかも
  533. if(isset($this->params['form'])) {
  534. $this->params['form'] = $this->_autoConvertEncodingByArray($this->params['form'],'UTF-8');
  535. }
  536. if(isset($this->params['data'])) {
  537. $this->params['data'] = $this->_autoConvertEncodingByArray($this->params['data'],'UTF-8');
  538. }
  539. }
  540. /**
  541. * /app/core.php のデバッグモードを書き換える
  542. * @param int $mode
  543. * @deprecated
  544. */
  545. function writeDebug($mode) {
  546. trigger_error("(Controller::writeDebug) は非推奨です。Controller::writeInstallSetting を利用してください。", E_USER_WARNING);
  547. $file = new File(CONFIGS.'core.php');
  548. $core = $file->read(false,'w');
  549. if($core) {
  550. $core = preg_replace('/Configure::write\(\'debug\',[\s\-0-9]+?\)\;/is',"Configure::write('debug', ".$mode.");",$core);
  551. $file->write($core);
  552. $file->close();
  553. return true;
  554. }else {
  555. $file->close();
  556. return false;
  557. }
  558. }
  559. /**
  560. * /app/core.phpのデバッグモードを取得する
  561. * @return string $mode
  562. * @deprecated
  563. */
  564. function readDebug() {
  565. trigger_error("(Controller::readDebug) は非推奨です。Configure::read('debug') を利用してください。", E_USER_WARNING);
  566. $mode = '';
  567. $file = new File(CONFIGS.'core.php');
  568. $core = $file->read(false,'r');
  569. if(preg_match('/Configure::write\(\'debug\',([\s\-0-9]+?)\)\;/is',$core,$matches)) {
  570. $mode = trim($matches[1]);
  571. }
  572. return $mode;
  573. }
  574. /**
  575. * メールを送信する
  576. *
  577. * @param string $to 送信先アドレス
  578. * @param string $title タイトル
  579. * @param mixed $body 本文
  580. * @options array
  581. * @return boolean 送信結果
  582. * @access public
  583. */
  584. function sendMail($to, $title = '', $body = '', $options = array()) {
  585. $formalName = $email = '';
  586. if(!empty($this->siteConfigs)) {
  587. $formalName = $this->siteConfigs['formal_name'];
  588. $email = $this->siteConfigs['email'];
  589. if(strpos($email, ',') !== false) {
  590. $email = split(',', $email);
  591. $email = $email[0];
  592. }
  593. }
  594. if(!$formalName) {
  595. $formalName = Configure::read('BcApp.title');
  596. }
  597. $_options = array('fromName' => $formalName,
  598. 'reply' => $email,
  599. 'cc' => '',
  600. 'bcc' => '',
  601. 'template' => 'default',
  602. 'from' => $email
  603. );
  604. $options = am($_options, $options);
  605. extract($options);
  606. if(!isset($this->BcEmail)) {
  607. return false;
  608. }
  609. if(strpos($to, ',') !== false) {
  610. $_to = split(',', $to);
  611. $to = $_to[0];
  612. if(count($_to) > 1) {
  613. unset($_to[0]);
  614. if($bcc) {
  615. $bcc .= ',';
  616. }
  617. $bcc .= implode(',', $_to);
  618. }
  619. }
  620. // メール基本設定
  621. $this->_setMail();
  622. if(!empty($options['filePaths'])) {
  623. if(!is_array($options['filePaths'])) {
  624. $this->BcEmail->filePaths = array($options['filePaths']);
  625. } else {
  626. $this->BcEmail->filePaths = $options['filePaths'];
  627. }
  628. }
  629. if(!empty($options['attachments'])) {
  630. if(!is_array($options['attachments'])) {
  631. $this->BcEmail->attachments = array($options['attachments']);
  632. } else {
  633. $this->BcEmail->attachments = $options['attachments'];
  634. }
  635. }
  636. // テンプレート
  637. if(Configure::read('BcRequest.agent')) {
  638. $this->BcEmail->layoutPath = Configure::read('BcRequest.agentPrefix');
  639. $this->BcEmail->subDir = Configure::read('BcRequest.agentPrefix');
  640. $this->BcEmail->template = $template;
  641. }
  642. $this->BcEmail->template = $template;
  643. // データ
  644. if(is_array($body)) {
  645. $this->set($body);
  646. }else {
  647. $this->set('body', $body);
  648. }
  649. // 送信先アドレス
  650. $this->BcEmail->to = $to;
  651. // 件名
  652. $this->BcEmail->subject = $title;
  653. // 送信元・返信先
  654. if($from) {
  655. if(strpos($from, ',') !== false) {
  656. $_from = split(',', $from);
  657. $from = $_from[0];
  658. }
  659. $this->BcEmail->from = $from;
  660. $this->BcEmail->additionalParams = '-f'.$from;
  661. $this->BcEmail->return = $from;
  662. $this->BcEmail->replyTo = $reply;
  663. } else {
  664. $this->BcEmail->from = $to;
  665. $this->BcEmail->additionalParams = '-f'.$to;
  666. $this->BcEmail->return = $to;
  667. $this->BcEmail->replyTo = $to;
  668. }
  669. // 送信元名
  670. if($from && $fromName) {
  671. $this->BcEmail->from = $fromName.' <'.$from.'>';
  672. }
  673. // CC
  674. if($cc) {
  675. if(strpos($cc, ',') !== false) {
  676. $cc = split(',', $cc);
  677. }else{
  678. $cc = array($cc);
  679. }
  680. $this->BcEmail->cc = $cc;
  681. }
  682. // BCC
  683. if($bcc) {
  684. if(strpos($bcc, ',') !== false) {
  685. $bcc = split(',', $bcc);
  686. }else{
  687. $bcc = array($bcc);
  688. }
  689. $this->BcEmail->bcc = $bcc;
  690. }
  691. return $this->BcEmail->send();
  692. }
  693. /**
  694. * メールコンポーネントの初期設定
  695. *
  696. * @return boolean 設定結果
  697. * @access protected
  698. */
  699. function _setMail() {
  700. if(!isset($this->BcEmail)) {
  701. return false;
  702. }
  703. if(!empty($this->siteConfigs['mail_encode'])) {
  704. $encode = $this->siteConfigs['mail_encode'];
  705. } else {
  706. $encode = 'ISO-2022-JP';
  707. }
  708. $this->BcEmail->reset();
  709. $this->BcEmail->charset = $encode;
  710. $this->BcEmail->sendAs = 'text'; // text or html or both
  711. $this->BcEmail->lineLength=105; // TODO ちゃんとした数字にならない大きめの数字で設定する必要がある。
  712. if(!empty($this->siteConfigs['smtp_host'])) {
  713. $this->BcEmail->delivery = 'smtp'; // mail or smtp or debug
  714. $this->BcEmail->smtpOptions = array('host' =>$this->siteConfigs['smtp_host'],
  715. 'port' =>25,
  716. 'timeout' =>30,
  717. 'username'=>($this->siteConfigs['smtp_user'])?$this->siteConfigs['smtp_user']:null,
  718. 'password'=>($this->siteConfigs['smtp_password'])?$this->siteConfigs['smtp_password']:null);
  719. } else {
  720. $this->BcEmail->delivery = "mail";
  721. }
  722. return true;
  723. }
  724. /**
  725. * インストール設定を書き換える
  726. *
  727. * @param string $key
  728. * @param string $value
  729. * @return boolean
  730. * @access public
  731. */
  732. function writeInstallSetting($key, $value) {
  733. /* install.php の編集 */
  734. $setting = "Configure::write('".$key."', ".$value.");\n";
  735. $key = str_replace('.', '\.', $key);
  736. $pattern = '/Configure\:\:write[\s]*\([\s]*\''.$key.'\'[\s]*,[\s]*([^\s]*)[\s]*\);\n/is';
  737. $file = new File(CONFIGS.'install.php');
  738. if(file_exists(CONFIGS.'install.php')) {
  739. $data = $file->read();
  740. }else {
  741. $data = "<?php\n?>";
  742. }
  743. if(preg_match($pattern, $data)) {
  744. $data = preg_replace($pattern, $setting, $data);
  745. } else {
  746. $data = preg_replace("/\n\?>/is", "\n".$setting.'?>', $data);
  747. }
  748. $return = $file->write($data);
  749. $file->close();
  750. return $return;
  751. }
  752. /**
  753. * スマートURLの設定を取得
  754. *
  755. * @return boolean
  756. * @access public
  757. */
  758. function readSmartUrl(){
  759. if (Configure::read('App.baseUrl')) {
  760. return false;
  761. } else {
  762. return true;
  763. }
  764. }
  765. /**
  766. * スマートURLの設定を行う
  767. *
  768. * @param boolean $smartUrl
  769. * @return boolean
  770. * @access public
  771. */
  772. function writeSmartUrl($smartUrl) {
  773. /* install.php の編集 */
  774. if($smartUrl) {
  775. if(!$this->writeInstallSetting('App.baseUrl', "''")){
  776. return false;
  777. }
  778. } else {
  779. if(!$this->writeInstallSetting('App.baseUrl', '$_SERVER[\'SCRIPT_NAME\']')){
  780. return false;
  781. }
  782. }
  783. if(BC_DEPLOY_PATTERN == 2 || BC_DEPLOY_PATTERN == 3) {
  784. $webrootRewriteBase = '/';
  785. } else {
  786. $webrootRewriteBase = '/'.APP_DIR.'/webroot';
  787. }
  788. /* /app/webroot/.htaccess の編集 */
  789. $this->_writeSmartUrlToHtaccess(WWW_ROOT.'.htaccess', $smartUrl, 'webroot', $webrootRewriteBase);
  790. if(BC_DEPLOY_PATTERN == 1) {
  791. /* /.htaccess の編集 */
  792. $this->_writeSmartUrlToHtaccess(ROOT.DS.'.htaccess', $smartUrl, 'root', '/');
  793. }
  794. return true;
  795. }
  796. /**
  797. * .htaccess にスマートURLの設定を書きこむ
  798. *
  799. * @param string $path
  800. * @param array $rewriteSettings
  801. * @return boolean
  802. * @access protected
  803. */
  804. function _writeSmartUrlToHtaccess($path, $smartUrl, $type, $rewriteBase = '/') {
  805. //======================================================================
  806. // WindowsのXAMPP環境では、何故か .htaccess を書き込みモード「w」で開けなかったの
  807. // で、追記モード「a」で開くことにした。そのため、実際の書き込み時は、 ftruncate で、
  808. // 内容をリセットし、ファイルポインタを先頭に戻している。
  809. //======================================================================
  810. $rewritePatterns = array( "/\n[^\n#]*RewriteEngine.+/i",
  811. "/\n[^\n#]*RewriteBase.+/i",
  812. "/\n[^\n#]*RewriteCond.+/i",
  813. "/\n[^\n#]*RewriteRule.+/i");
  814. switch($type) {
  815. case 'root':
  816. $rewriteSettings = array( 'RewriteEngine on',
  817. 'RewriteBase '.$this->getRewriteBase($rewriteBase),
  818. 'RewriteRule ^$ '.APP_DIR.'/webroot/ [L]',
  819. 'RewriteRule (.*) '.APP_DIR.'/webroot/$1 [L]');
  820. break;
  821. case 'webroot':
  822. $rewriteSettings = array( 'RewriteEngine on',
  823. 'RewriteBase '.$this->getRewriteBase($rewriteBase),
  824. 'RewriteCond %{REQUEST_FILENAME} !-d',
  825. 'RewriteCond %{REQUEST_FILENAME} !-f',
  826. 'RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]');
  827. break;
  828. }
  829. $file = new File($path);
  830. $file->open('a+');
  831. $data = $file->read();
  832. foreach ($rewritePatterns as $rewritePattern) {
  833. $data = preg_replace($rewritePattern, '', $data);
  834. }
  835. if($smartUrl) {
  836. $data .= "\n".implode("\n", $rewriteSettings);
  837. }
  838. ftruncate($file->handle,0);
  839. if(!$file->write($data)){
  840. $file->close();
  841. return false;
  842. }
  843. $file->close();
  844. }
  845. /**
  846. * RewriteBase の設定を取得する
  847. *
  848. * @param string $base
  849. * @return string
  850. */
  851. function getRewriteBase($url){
  852. $baseUrl = BC_BASE_URL;
  853. if(preg_match("/index\.php/", $baseUrl)){
  854. $baseUrl = str_replace('index.php/', '', $baseUrl);
  855. }
  856. $baseUrl = preg_replace("/\/$/",'',$baseUrl);
  857. if($url != '/' || !$baseUrl) {
  858. $url = $baseUrl.$url;
  859. }else{
  860. $url = $baseUrl;
  861. }
  862. return $url;
  863. }
  864. /**
  865. * 画面の情報をセットする
  866. *
  867. * @param array $filterModels
  868. * @param string $options
  869. * @return void
  870. * @access public
  871. */
  872. function setViewConditions($filterModels = array(), $options = array()) {
  873. $_options = array('type' => 'post', 'session' => true);
  874. $options = am($_options, $options);
  875. extract($options);
  876. if($type == 'post' && $session == true) {
  877. $this->_saveViewConditions($filterModels, $options);
  878. } elseif ($type == 'get') {
  879. $options['session'] = false;
  880. }
  881. $this->_loadViewConditions($filterModels, $options);
  882. }
  883. /**
  884. * 画面の情報をセッションに保存する
  885. *
  886. * @param string $options
  887. * @return void
  888. * @access protected
  889. */
  890. function _saveViewConditions($filterModels = array(), $options = array()) {
  891. $_options = array('action' => '', 'group' => '');
  892. $options = am($_options, $options);
  893. extract($options);
  894. if(!is_array($filterModels)){
  895. $filterModels = array($filterModels);
  896. }
  897. if(!$action) {
  898. $action = $this->action;
  899. }
  900. $contentsName = $this->name.Inflector::classify($action);
  901. if($group) {
  902. $contentsName .= ".".$group;
  903. }
  904. foreach($filterModels as $model) {
  905. if(isset($this->data[$model])) {
  906. $this->Session->write("{$contentsName}.filter.{$model}",$this->data[$model]);
  907. }
  908. }
  909. if(!empty($this->params['named'])) {
  910. $named = am($this->Session->read("{$contentsName}.named"), $this->params['named']);
  911. $this->Session->write("{$contentsName}.named", $named);
  912. }
  913. }
  914. /**
  915. * 画面の情報をセッションから読み込む
  916. *
  917. * @param string $options
  918. * @access protected
  919. */
  920. function _loadViewConditions($filterModels = array(), $options = array()) {
  921. $_options = array('default'=>array(), 'action' => '', 'group' => '', 'type' => 'post' , 'session' => true);
  922. $options = am($_options, $options);
  923. $named = array();
  924. $filter = array();
  925. extract($options);
  926. if(!is_array($filterModels)){
  927. $model = $filterModels;
  928. $filterModels = array($filterModels);
  929. } else {
  930. $model = $filterModels[0];
  931. }
  932. if(!$action) {
  933. $action = $this->action;
  934. }
  935. $contentsName = $this->name.Inflector::classify($action);
  936. if($group) {
  937. $contentsName .= ".".$group;
  938. }
  939. if($type == 'post' && $session) {
  940. foreach($filterModels as $model) {
  941. if($this->Session->check("{$contentsName}.filter.{$model}")) {
  942. $filter = $this->Session->read("{$contentsName}.filter.{$model}");
  943. } elseif(!empty($default[$model])) {
  944. $filter = $default[$model];
  945. } else {
  946. $filter = array();
  947. }
  948. $this->data[$model] = $filter;
  949. }
  950. $named = array();
  951. if(!empty($default['named'])) {
  952. $named = $default['named'];
  953. }
  954. if($this->Session->check("{$contentsName}.named")) {
  955. $named = am($named, $this->Session->read("{$contentsName}.named"));
  956. }
  957. } elseif($type == 'get') {
  958. if(!empty($this->params['url'])) {
  959. $url = $this->params['url'];
  960. unset($url['url']);
  961. unset($url['ext']);
  962. unset($url['x']);
  963. unset($url['y']);
  964. }
  965. if(!empty($url)) {
  966. $filter = $url;
  967. } elseif(!empty($default[$model])) {
  968. $filter = $default[$model];
  969. }
  970. $this->data[$model] = $filter;
  971. if(!empty($default['named'])) {
  972. $named = $default['named'];
  973. }
  974. $named['?'] = $filter;
  975. }
  976. $this->passedArgs += $named;
  977. }
  978. /**
  979. * Select Text 用の条件を生成する
  980. *
  981. * @param string $fieldName
  982. * @param mixed $values
  983. * @param array $options
  984. * @return string
  985. * @access public
  986. */
  987. function convertSelectTextCondition($fieldName, $values, $options = array()) {
  988. $_options = array('type'=>'string', 'conditionType'=>'or');
  989. $options = am($_options, $options);
  990. $conditions = array();
  991. extract($options);
  992. if($type=='string' && !is_array($value)) {
  993. $values = split(',',str_replace('\'', '', $values));
  994. }
  995. if(!empty($values) && is_array($values)){
  996. foreach($values as $value){
  997. $conditions[$conditionType][] = array($fieldName.' LIKE' => "%'".$value."'%");
  998. }
  999. }
  1000. return $conditions;
  1001. }
  1002. /**
  1003. * BETWEEN 条件を生成
  1004. *
  1005. * @param string $fieldName
  1006. * @param mixed $value
  1007. * @return array
  1008. * @access public
  1009. */
  1010. function convertBetweenCondition($fieldName, $value) {
  1011. if(strpos($value, '-')===false) {
  1012. return false;
  1013. }
  1014. list($start, $end) = split('-', $value);
  1015. if(!$start) {
  1016. $conditions[$fieldName.' <='] = $end;
  1017. }elseif(!$end) {
  1018. $conditions[$fieldName.' >='] = $start;
  1019. }else {
  1020. $conditions[$fieldName.' BETWEEN ? AND ?'] = array($start, $end);
  1021. }
  1022. return $conditions;
  1023. }
  1024. /**
  1025. * ランダムなパスワード文字列を生成する
  1026. *
  1027. * @param int $len
  1028. * @return string $password
  1029. * @access public
  1030. */
  1031. function generatePassword ($len = 8) {
  1032. srand ( (double) microtime () * 1000000);
  1033. $seed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
  1034. $password = "";
  1035. while ($len--) {
  1036. $pos = rand(0,61);
  1037. $password .= $seed[$pos];
  1038. }
  1039. return $password;
  1040. }
  1041. /**
  1042. * 認証完了後処理
  1043. *
  1044. * @return boolean
  1045. */
  1046. function isAuthorized() {
  1047. $requestedPrefix = '';
  1048. $authPrefix = $this->getAuthPreifx($this->BcAuth->user('name'));
  1049. if(!$authPrefix) {
  1050. // 1.6.8 以下の場合は authPrefix が取得できないので true を返して終了
  1051. return true;
  1052. }
  1053. if(!empty($this->params['prefix'])) {
  1054. $requestedPrefix = $this->params['prefix'];
  1055. }
  1056. if($requestedPrefix && ($requestedPrefix != $authPrefix)) {
  1057. // 許可されていないプレフィックスへのアクセスの場合、認証できなかったものとする
  1058. $ref = $this->referer();
  1059. $loginAction = Router::normalize($this->BcAuth->loginAction);
  1060. if($ref == $loginAction) {
  1061. $this->Session->delete('Auth.User');
  1062. $this->Session->delete('Message.flash');
  1063. $this->BcAuth->authError = $this->BcAuth->loginError;
  1064. return false;
  1065. } else {
  1066. $this->Session->setFlash('指定されたページへのアクセスは許可されていません。');
  1067. $this->redirect($ref);
  1068. return;
  1069. }
  1070. }
  1071. return true;
  1072. }
  1073. /**
  1074. * 対象ユーザーの認証コンテンツのプレフィックスを取得
  1075. *
  1076. * TODO 認証完了後は、セッションに保存しておいてもよいのでは?
  1077. *
  1078. * @param string $userName
  1079. * @return string
  1080. */
  1081. function getAuthPreifx($userName) {
  1082. if(isset($this->User)) {
  1083. $UserClass = $this->User;
  1084. } else {
  1085. $UserClass = ClassRegistry::init('User');
  1086. }
  1087. return $UserClass->getAuthPrefix($userName);
  1088. }
  1089. /**
  1090. * Returns the referring URL for this request.
  1091. *
  1092. * @param string $default Default URL to use if HTTP_REFERER cannot be read from headers
  1093. * @param boolean $local If true, restrict referring URLs to local server
  1094. * @return string Referring URL
  1095. * @access public
  1096. * @link http://book.cakephp.org/view/430/referer
  1097. */
  1098. function referer($default = null, $local = false) {
  1099. $ref = env('HTTP_REFERER');
  1100. if (!empty($ref) && defined('FULL_BASE_URL')) {
  1101. // >>> CUSTOMIZE MODIFY 2011/01/18 ryuring
  1102. // スマートURLオフの際、$this->webrootがうまく動作しないので調整
  1103. //$base = FULL_BASE_URL . $this->webroot;
  1104. // ---
  1105. $base = FULL_BASE_URL . $this->base;
  1106. // <<<
  1107. if (strpos($ref, $base) === 0) {
  1108. $return = substr($ref, strlen($base));
  1109. if ($return[0] != '/') {
  1110. $return = '/'.$return;
  1111. }
  1112. return $return;
  1113. } elseif (!$local) {
  1114. return $ref;
  1115. }
  1116. }
  1117. if ($default != null) {
  1118. return $default;
  1119. }
  1120. return '/';
  1121. }
  1122. /**
  1123. * フックメソッドを実行する
  1124. *
  1125. * @param string $hook
  1126. * @return mixed
  1127. */
  1128. function executeHook($hook) {
  1129. $args = func_get_args();
  1130. $args[0] =& $this;
  1131. return call_user_func_array( array( &$this->BcPluginHook, $hook ), $args );
  1132. }
  1133. /**
  1134. * 現在のユーザーのドキュメントルートの書き込み権限確認
  1135. *
  1136. * @return boolean
  1137. * @access public
  1138. */
  1139. function checkRootEditable() {
  1140. if(!isset($this->BcAuth)) {
  1141. return false;
  1142. }
  1143. $user = $this->BcAuth->user();
  1144. $userModel = $this->getUserModel();
  1145. if(!$user || !$userModel) {
  1146. return false;
  1147. }
  1148. if(@$this->siteConfigs['root_owner_id'] == $user[$userModel]['user_group_id'] ||
  1149. !@$this->siteConfigs['root_owner_id'] || $user[$userModel]['user_group_id'] == 1) {
  1150. return true;
  1151. } else {
  1152. return false;
  1153. }
  1154. }
  1155. /**
  1156. * ユーザーモデルを取得する
  1157. *
  1158. * @return mixed string Or false
  1159. */
  1160. function getUserModel() {
  1161. if(!isset($this->BcAuth)) {
  1162. return false;
  1163. }
  1164. return $this->BcAuth->userModel;
  1165. }
  1166. /**
  1167. * Redirects to given $url, after turning off $this->autoRender.
  1168. * Script execution is halted after the redirect.
  1169. *
  1170. * @param mixed $url A string or array-based URL pointing to another location within the app, or an absolute URL
  1171. * @param integer $status Optional HTTP status code (eg: 404)
  1172. * @param boolean $exit If true, exit() will be called after the redirect
  1173. * @return mixed void if $exit = false. Terminates script if $exit = true
  1174. * @access public
  1175. */
  1176. function redirect($url, $status = null, $exit = true) {
  1177. $url = addSessionId($url, true);
  1178. // 管理システムでのURLの生成が CakePHP の標準仕様と違っていたので調整
  1179. // ※ Routing.admin を変更した場合
  1180. if (!isset($url['admin']) && !empty($this->params['admin'])) {
  1181. $url['admin'] = true;
  1182. } elseif (isset($url['admin']) && !$url['admin']) {
  1183. unset($url['admin']);
  1184. }
  1185. parent::redirect($url, $status, $exit);
  1186. }
  1187. /**
  1188. * Calls a controller's method from any location.
  1189. *
  1190. * @param mixed $url String or array-based url.
  1191. * @param array $extra if array includes the key "return" it sets the AutoRender to true.
  1192. * @return mixed Boolean true or false on success/failure, or contents
  1193. * of rendered action if 'return' is set in $extra.
  1194. * @access public
  1195. */
  1196. function requestAction($url, $extra = array()) {
  1197. // >>> CUSTOMIZE ADD 2011/12/16 ryuring
  1198. // 管理システムやプラグインでのURLの生成が CakePHP の標準仕様と違っていたので調整
  1199. // >>> CUSTOMIZE MODIFY 2012/1/28 ryuring
  1200. // 配列でないURLの場合に、間違った値に書きなおされていたので配列チェックを追加
  1201. if(is_array($url)) {
  1202. if ((!isset($url['admin']) && !empty($this->params['admin'])) || !empty($url['admin'])) {
  1203. $url['prefix'] = 'admin';
  1204. }
  1205. if (!isset($url['plugin']) && !empty($this->params['plugin'])) {
  1206. $url['plugin'] = $this->params['plugin'];
  1207. }
  1208. }
  1209. // <<<
  1210. return parent::requestAction($url, $extra);
  1211. }
  1212. /**
  1213. * よく使う項目の表示状態を保存する
  1214. *
  1215. * @param mixed $open 1 Or ''
  1216. */
  1217. function admin_ajax_save_favorite_box($open = '') {
  1218. $this->Session->write('Baser.favorite_box_opened', $open);
  1219. echo true;
  1220. exit();
  1221. }
  1222. /**
  1223. * 一括処理
  1224. *
  1225. * 一括処理としてコントローラーの次のメソッドを呼び出す
  1226. * バッチ処理名は、バッチ処理指定用のコンボボックスで定義する
  1227. *
  1228. * _batch{バッチ処理名}
  1229. *
  1230. * 処理結果として成功の場合は、バッチ処理名を出力する
  1231. *
  1232. * @return void
  1233. * @access public
  1234. */
  1235. function admin_ajax_batch () {
  1236. $method = $this->data['ListTool']['batch'];
  1237. if($this->data['ListTool']['batch_targets']) {
  1238. foreach($this->data['ListTool']['batch_targets'] as $key => $batchTarget) {
  1239. if(!$batchTarget) {
  1240. unset($this->data['ListTool']['batch_targets'][$key]);
  1241. }
  1242. }
  1243. }
  1244. $action = '_batch_'.$method;
  1245. if (method_exists($this, $action)) {
  1246. if($this->{$action}($this->data['ListTool']['batch_targets'])) {
  1247. echo $method;
  1248. }
  1249. }
  1250. exit();
  1251. }
  1252. /**
  1253. * 検索ボックスの表示状態を保存する
  1254. *
  1255. * @param mixed $open 1 Or ''
  1256. */
  1257. function admin_ajax_save_search_box($key, $open = '') {
  1258. $this->Session->write('Baser.searchBoxOpened.'.$key, $open);
  1259. echo true;
  1260. exit();
  1261. }
  1262. /**
  1263. * Internally redirects one action to another. Examples:
  1264. *
  1265. * setAction('another_action');
  1266. * setAction('action_with_parameters', $parameter1);
  1267. *
  1268. * @param string $action The new action to be redirected to
  1269. * @param mixed Any other parameters passed to this method will be passed as
  1270. * parameters to the new action.
  1271. * @return mixed Returns the return value of the called action
  1272. * @access public
  1273. */
  1274. function setAction($action) {
  1275. // CUSTOMIZE ADD 2012/04/22 ryuring
  1276. // >>>
  1277. $_action = $this->action;
  1278. // <<<
  1279. $this->action = $action;
  1280. $args = func_get_args();
  1281. unset($args[0]);
  1282. // CUSTOMIZE MODIFY 2012/04/22 ryuring
  1283. // >>>
  1284. //return call_user_func_array(array(&$this, $action), $args);
  1285. // ---
  1286. $return = call_user_func_array(array(&$this, $action), $args);
  1287. $this->action = $_action;
  1288. return $return;
  1289. // <<<
  1290. }
  1291. /**
  1292. * テーマ用のヘルパーをセットする
  1293. *
  1294. * @return void
  1295. * @access public
  1296. */
  1297. function setThemeHelpers() {
  1298. $themeHelpersPath = WWW_ROOT.'themed'.DS.Configure::read('BcSite.theme').DS.'helpers';
  1299. $Folder = new Folder($themeHelpersPath);
  1300. $files = $Folder->read(true, true);
  1301. if(!empty($files[1])) {
  1302. foreach($files[1] as $file) {
  1303. $this->helpers[] = Inflector::classify(basename($file, '.php'));
  1304. }
  1305. }
  1306. }
  1307. /**
  1308. * Ajax用のエラーを出力する
  1309. *
  1310. * @param int $errorNo
  1311. * @param mixed $message
  1312. * @return void
  1313. * @access public
  1314. */
  1315. function ajaxError($errorNo = 500, $message = '') {
  1316. header('HTTP/1.1 '.$errorNo);
  1317. if($message) {
  1318. if(is_array($message)) {
  1319. $message = implode('<br />', $message);
  1320. }
  1321. echo $message;
  1322. }
  1323. exit();
  1324. }
  1325. }
  1326. ?>