PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/baser/controllers/baser_app_controller.php

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