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

/system/expressionengine/third_party/freeform/addon_builder/addon_builder.php

https://bitbucket.org/studiobreakfast/sync
PHP | 3658 lines | 1978 code | 657 blank | 1023 comment | 314 complexity | 4d86a6c53174d9e28ba4d142a9a303b1 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php if ( ! defined('EXT')) exit('No direct script access allowed');
  2. /**
  3. * Solspace - Add-On Builder Framework
  4. *
  5. * @package Add-On Builder Framework
  6. * @author Solspace DevTeam
  7. * @copyright Copyright (c) 2008-2011, Solspace, Inc.
  8. * @link http://solspace.com/docs/
  9. * @version 1.2.4
  10. */
  11. /**
  12. * Add-On Builder - Base Class
  13. *
  14. * A class that helps with the building of ExpressionEngine Add-Ons by allowing the automating of certain
  15. * tasks.
  16. *
  17. * @package Add-On Builder Framework
  18. * @subpackage Solspace:Add-On Builder
  19. * @author Solspace DevTeam
  20. * @link http://solspace.com/docs/
  21. */
  22. //--------------------------------------------
  23. // Alias to get_instance()
  24. //--------------------------------------------
  25. if ( ! function_exists('ee') )
  26. {
  27. function ee()
  28. {
  29. return get_instance();
  30. }
  31. }
  32. //--------------------------------------------
  33. // need the bridge adaptor in 1.x
  34. //--------------------------------------------
  35. if (APP_VER < 2.0)
  36. {
  37. require_once PATH . "bridge/codeigniter/ci_bridge_adaptor.php";
  38. }
  39. class Addon_builder_freeform {
  40. static $bridge_version = '1.2.4';
  41. public $cache = array(); // Internal cache
  42. public $ob_level = 0;
  43. public $cached_vars = array();
  44. public $switches = array();
  45. // The general class name (ucfirst with underscores), used in database and class instantiation
  46. public $class_name = '';
  47. // The lowercased class name, used for referencing module files and in URLs
  48. public $lower_name = '';
  49. // The name that we put into the Extensions DB table, different for 2.x and 1.x
  50. public $extension_name = '';
  51. // Module disabled? Typically used when an update is in progress.
  52. public $disabled = FALSE;
  53. public $addon_path = '';
  54. public $theme = 'default';
  55. public $version = '';
  56. public $crumbs = array();
  57. public $document = FALSE;
  58. public $data = FALSE;
  59. public $actions = FALSE;
  60. public $module_preferences = array();
  61. public $remote_data = ''; // For remote file retrieving and storage
  62. public $sc;
  63. //this will house items that might not always be set when called.
  64. public $constants;
  65. //holder for the json object if ever
  66. public $json;
  67. public $json_array;
  68. //for upper right link building
  69. public $right_links = array();
  70. // Member Fields array
  71. public $mfields = array();
  72. public $updater;
  73. public $aob_path = '';
  74. public $auto_paginate = FALSE;
  75. // --------------------------------------------------------------------
  76. /**
  77. * Constructor
  78. *
  79. * @access public
  80. * @return null
  81. */
  82. public function Addon_builder_freeform ($name='')
  83. {
  84. //path to this folder
  85. $this->aob_path = rtrim(realpath(dirname(__FILE__)), '/') . '/';
  86. $this->EE =& get_instance();
  87. if ( APP_VER < 2.0)
  88. {
  89. ee()->localize = $GLOBALS['LOC'];
  90. ee()->stats = ( ! isset($GLOBALS['STAT'])) ? FALSE : $GLOBALS['STAT'];
  91. //need a symbolic link to extension->last_call and end_script
  92. if ( isset($GLOBALS['EXT']) AND is_object($GLOBALS['EXT']))
  93. {
  94. ee()->extensions->last_call =& $GLOBALS['EXT']->last_call;
  95. ee()->extensions->end_script =& $GLOBALS['EXT']->end_script;
  96. }
  97. }
  98. // --------------------------------------------
  99. // Session Global
  100. // - Add-On Builder might be called for an Extension using the 'session_' hooks,
  101. // - so we need to check for that object first.
  102. // --------------------------------------------
  103. if ( ! isset(ee()->session) OR ! is_object(ee()->session))
  104. {
  105. if ( APP_VER < 2.0)
  106. {
  107. //Have to check for ->userdata too because a REAL session instance has it always
  108. //Some other addon devs are creating $SESS->cache even when $SESS is null
  109. //That autocreates the session object before the real one clobbers it,
  110. //that in turn fools addons into thinking that $SESSION has already fired :/
  111. //assume its still not there
  112. ee()->session = FALSE;
  113. //if it is, lets grab it changed to pass by reference
  114. if ( isset($GLOBALS['SESS']) AND isset($GLOBALS['SESS']->userdata))
  115. {
  116. ee()->session =& $GLOBALS['SESS'];
  117. }
  118. }
  119. elseif (file_exists(APPPATH.'libraries/Session.php'))
  120. {
  121. ee()->load->library('session');
  122. }
  123. }
  124. // --------------------------------------------
  125. // PAGE Request? Check for $TMPL global
  126. // --------------------------------------------
  127. if (APP_VER < 2.0 AND
  128. ( ! isset(ee()->TMPL) OR ! is_object(ee()->TMPL)) AND
  129. isset($GLOBALS['TMPL']) AND
  130. is_object($GLOBALS['TMPL']))
  131. {
  132. ee()->TMPL =& $GLOBALS['TMPL'];
  133. }
  134. //--------------------------------------------
  135. // CP Request? Check for $DSP global
  136. //--------------------------------------------
  137. if (APP_VER < 2.0 AND
  138. REQ == 'CP' AND
  139. isset($GLOBALS['DSP']) AND
  140. is_object($GLOBALS['DSP']))
  141. {
  142. ee()->cp =& $GLOBALS['DSP'];
  143. }
  144. //--------------------------------------------
  145. // Required CONSTANTs
  146. //--------------------------------------------
  147. if ( ! defined('QUERY_MARKER'))
  148. {
  149. define('QUERY_MARKER', (ee()->config->item('force_query_string') == 'y') ? '' : '?');
  150. }
  151. if ( ! defined('SLASH'))
  152. {
  153. define('SLASH', '&#47;'); // Seems this constant is the same for both EE 1.x and EE 2.x
  154. }
  155. if ( ! defined('T_SLASH')) // Template Parsing Slash
  156. {
  157. define('T_SLASH', (APP_VER < '2.0') ? '&#47;' : "/");
  158. }
  159. if ( ! defined('NL'))
  160. {
  161. define('NL', "\n");
  162. }
  163. if (APP_VER < 2.0 AND ! defined('PATH_THIRD') AND defined('PATH_MOD'))
  164. {
  165. define('PATH_THIRD', PATH_MOD);
  166. }
  167. if ( ! defined('PATH_CP_IMG') AND defined('PATH_CP_GBL_IMG'))
  168. {
  169. define('PATH_CP_IMG', PATH_CP_GBL_IMG);
  170. }
  171. //just in case we need them early
  172. if ( ! defined('AMP'))
  173. {
  174. define('AMP', '&amp;');
  175. }
  176. if ( ! defined('BR'))
  177. {
  178. define('BR', '<br />');
  179. }
  180. if ( ! defined('NBS'))
  181. {
  182. define('NBS', "&nbsp;");
  183. }
  184. // EE 1.x does not have this constant,
  185. // but it adds it to every form automatically.
  186. // EE 2.x sets it all the time now.
  187. $constants = array(
  188. 'XID_SECURE_HASH' => (APP_VER < 2.0 OR ! defined('XID_SECURE_HASH')) ?
  189. '' : XID_SECURE_HASH,
  190. );
  191. $this->constants = (object) $constants;
  192. //--------------------------------------------
  193. // Auto-Detect Name
  194. //--------------------------------------------
  195. if ($name == '')
  196. {
  197. $name = get_class($this);
  198. $ends = array(
  199. '_cp_base',
  200. '_mcp',
  201. '_CP',
  202. '_ext',
  203. '_extension',
  204. '_extension_base',
  205. '_updater_base',
  206. '_updater',
  207. '_upd',
  208. '_actions',
  209. '_data',
  210. '_ft',
  211. '_acc'
  212. );
  213. foreach($ends as $remove)
  214. {
  215. if (substr($name, -strlen($remove)) == $remove)
  216. {
  217. $name = substr($name, 0, -strlen($remove));
  218. break;
  219. }
  220. }
  221. }
  222. //--------------------------------------------
  223. // Important Class Vars
  224. //--------------------------------------------
  225. //this should always be loaded after EE 2.1.4
  226. if ( ! isset(ee()->security) OR
  227. ! is_object(ee()->security))
  228. {
  229. ee()->load->library('security');
  230. }
  231. $this->lower_name = strtolower(ee()->security->sanitize_filename($name));
  232. $this->class_name = ucfirst($this->lower_name);
  233. $this->extension_name = $this->class_name . ((APP_VER < 2.0) ? '_extension' : '_ext');
  234. // -------------------------------------
  235. // set short cuts (must be done after lowername)
  236. // -------------------------------------
  237. $this->sc = $this->generate_shortcuts();
  238. //--------------------------------------------
  239. // Prepare Caching
  240. //--------------------------------------------
  241. //no sessions? lets use global until we get here again
  242. if ( ! isset(ee()->session) OR ! is_object(ee()->session))
  243. {
  244. if ( ! isset($GLOBALS['solspace']['cache']['addon_builder']['addon'][$this->lower_name]))
  245. {
  246. $GLOBALS['solspace']['cache']['addon_builder']['addon'][$this->lower_name] = array();
  247. }
  248. $this->cache =& $GLOBALS['solspace']['cache']['addon_builder']['addon'][$this->lower_name];
  249. if ( ! isset($GLOBALS['solspace']['cache']['addon_builder']['global']) )
  250. {
  251. $GLOBALS['solspace']['cache']['addon_builder']['global'] = array();
  252. }
  253. $this->global_cache =& $GLOBALS['solspace']['cache']['addon_builder']['global'];
  254. }
  255. //sessions?
  256. else
  257. {
  258. //been here before?
  259. if ( ! isset(ee()->session->cache['solspace']['addon_builder']['addon'][$this->lower_name]))
  260. {
  261. //grab pre-session globals, and only unset the ones for this addon
  262. if ( isset($GLOBALS['solspace']['cache']['addon_builder']['addon'][$this->lower_name]))
  263. {
  264. ee()->session->cache['solspace']['addon_builder']['addon'][$this->lower_name] = $GLOBALS['solspace']['cache']['addon_builder']['addon'][$this->lower_name];
  265. //cleanup, isle 5
  266. unset($GLOBALS['solspace']['cache']['addon_builder']['addon'][$this->lower_name]);
  267. }
  268. else
  269. {
  270. ee()->session->cache['solspace']['addon_builder']['addon'][$this->lower_name] = array();
  271. }
  272. }
  273. //check for solspace-wide globals
  274. if ( ! isset(ee()->session->cache['solspace']['addon_builder']['global']) )
  275. {
  276. if (isset($GLOBALS['solspace']['cache']['addon_builder']['global']))
  277. {
  278. ee()->session->cache['solspace']['addon_builder']['global'] = $GLOBALS['solspace']['cache']['addon_builder']['global'];
  279. unset($GLOBALS['solspace']['cache']['addon_builder']['global']);
  280. }
  281. else
  282. {
  283. ee()->session->cache['solspace']['addon_builder']['global'] = array();
  284. }
  285. }
  286. $this->global_cache =& ee()->session->cache['solspace']['addon_builder']['global'];
  287. $this->cache =& ee()->session->cache['solspace']['addon_builder']['addon'][$this->lower_name];
  288. }
  289. //--------------------------------------------
  290. // Add-On Path
  291. //--------------------------------------------
  292. if (APP_VER < 2.0)
  293. {
  294. // Because of Bridge Magic with eval() and parents, we might have to go one or two levels up
  295. $parent_class = get_parent_class($this);
  296. $super_parent_class = get_parent_class($parent_class);
  297. if (($parent_class == 'Extension_builder_freeform' OR
  298. $super_parent_class == 'Extension_builder_freeform') AND
  299. is_dir(PATH_EXT.$this->lower_name.'/'))
  300. {
  301. $this->extension_name = $this->class_name;
  302. $this->addon_path = PATH_EXT . $this->lower_name.'/';
  303. }
  304. else
  305. {
  306. $this->addon_path = PATH_MOD . $this->lower_name . '/';
  307. }
  308. }
  309. else
  310. {
  311. $this->addon_path = PATH_THIRD . $this->lower_name . '/';
  312. }
  313. //--------------------------------------------
  314. // Language Override
  315. //--------------------------------------------
  316. if (isset(ee()->lang) AND is_object(ee()->lang))
  317. {
  318. ee()->lang->loadfile($this->lower_name);
  319. }
  320. //--------------------------------------------
  321. // Module Constants
  322. //--------------------------------------------
  323. if ( defined(strtoupper($this->lower_name).'_VERSION') == FALSE AND
  324. file_exists($this->addon_path.'constants.'.$this->lower_name.'.php'))
  325. {
  326. require_once $this->addon_path.'constants.'.$this->lower_name.'.php';
  327. }
  328. if (defined(strtoupper($this->lower_name).'_VERSION') !== FALSE)
  329. {
  330. $this->version = constant(strtoupper($this->lower_name).'_VERSION');
  331. }
  332. //--------------------------------------------
  333. // Data Object - Used Cached Version, if Available
  334. //--------------------------------------------
  335. if ( isset($this->cache['objects']['data']) AND
  336. is_object($this->cache['objects']['data']))
  337. {
  338. $this->data =& $this->cache['objects']['data'];
  339. }
  340. else
  341. {
  342. if ( file_exists($this->addon_path . 'data.' . $this->lower_name.'.php'))
  343. {
  344. $name = $this->class_name . '_data';
  345. if ( ! class_exists($name))
  346. {
  347. require_once $this->addon_path . 'data.' . $this->lower_name.'.php';
  348. }
  349. $this->data = new $name($this);
  350. $this->data->sc = $this->sc;
  351. }
  352. else
  353. {
  354. if ( ! class_exists('Addon_builder_data_freeform'))
  355. {
  356. require_once $this->aob_path . 'data.addon_builder.php';
  357. }
  358. $this->data = new Addon_builder_data_freeform($this);
  359. }
  360. $this->cache['objects']['data'] =& $this->data;
  361. }
  362. $this->data->parent_aob_instance =& $this;
  363. //--------------------------------------------
  364. // documentDOM_freeform instantiated, might move this.
  365. //--------------------------------------------
  366. if (REQ == 'CP' AND file_exists($this->aob_path . 'document_dom.php'))
  367. {
  368. if ( ! class_exists('documentDOM_freeform'))
  369. {
  370. require_once $this->aob_path . 'document_dom.php';
  371. }
  372. $this->document = new documentDOM_freeform();
  373. }
  374. //--------------------------------------------
  375. // Important Cached Vars - Used in Both Extensions and Modules
  376. //--------------------------------------------
  377. $this->cached_vars['XID_SECURE_HASH'] = $this->constants->XID_SECURE_HASH;
  378. $this->cached_vars['page_crumb'] = '';
  379. $this->cached_vars['page_title'] = '';
  380. $this->cached_vars['text_direction'] = 'ltr';
  381. $this->cached_vars['onload_events'] = '';
  382. $this->cached_vars['message'] = '';
  383. $this->cached_vars['caller'] =& $this;
  384. $this->cached_vars['theme_url'] = $this->sc->addon_theme_url;
  385. $this->cached_vars['addon_theme_url'] = $this->sc->addon_theme_url;
  386. //--------------------------------------------
  387. // Determine View Path for Add-On
  388. //--------------------------------------------
  389. if ( isset($this->cache['view_path']))
  390. {
  391. $this->view_path = $this->cache['view_path'];
  392. }
  393. else
  394. {
  395. $possible_paths = array();
  396. $this->theme = ee()->security->sanitize_filename($this->theme);
  397. if (APP_VER < 2.0)
  398. {
  399. if (trim($this->theme, '/') != '')
  400. {
  401. $possible_paths[] = $this->addon_path.'views/1.x/'.trim($this->theme, '/').'/';
  402. }
  403. $possible_paths[] = $this->addon_path.'views/1.x/default/';
  404. $possible_paths[] = $this->addon_path.'views/1.x/';
  405. }
  406. else
  407. {
  408. if (trim($this->theme, '/') != '')
  409. {
  410. $possible_paths[] = $this->addon_path.'views/2.x/'.trim($this->theme, '/').'/';
  411. }
  412. $possible_paths[] = $this->addon_path.'views/2.x/default/';
  413. $possible_paths[] = $this->addon_path.'views/2.x/';
  414. }
  415. if (trim($this->theme, '/') != '')
  416. {
  417. $possible_paths[] = $this->addon_path.'views/'.trim($this->theme, '/').'/';
  418. }
  419. $possible_paths[] = $this->addon_path.'views/default/';
  420. $possible_paths[] = $this->addon_path.'views/';
  421. foreach(array_unique($possible_paths) as $path)
  422. {
  423. if ( is_dir($path))
  424. {
  425. $this->view_path = $path;
  426. break;
  427. }
  428. }
  429. }
  430. }
  431. // END Addon_builder_freeform()
  432. // --------------------------------------------------------------------
  433. /**
  434. * Creates shortcuts for common changed items between versions.
  435. *
  436. * @access public
  437. * @return object
  438. */
  439. public function generate_shortcuts ()
  440. {
  441. $is2 = ! (APP_VER < 2.0);
  442. if (defined('URL_THIRD_THEMES'))
  443. {
  444. $theme_url = URL_THIRD_THEMES;
  445. }
  446. else
  447. {
  448. $theme_url = (
  449. rtrim(ee()->config->item('theme_folder_url'), '/') .
  450. '/' . ($is2 ? 'third_party/' : '')
  451. );
  452. }
  453. if (defined('PATH_THIRD_THEMES'))
  454. {
  455. $theme_path = PATH_THIRD_THEMES;
  456. }
  457. else
  458. {
  459. $theme_path = (
  460. rtrim(ee()->config->item('theme_folder_path'), '/') .
  461. '/' . ($is2 ? 'third_party/' : '')
  462. );
  463. }
  464. return (object) array(
  465. 'db' => (object) array(
  466. 'channel_name' => $is2 ? 'channel_name' : 'blog_name',
  467. 'channel_url' => $is2 ? 'channel_url' : 'blog_url',
  468. 'channel_title' => $is2 ? 'channel_title' : 'blog_title',
  469. 'channels' => $is2 ? 'exp_channels' : 'exp_weblogs',
  470. 'data' => $is2 ? 'exp_channel_data' : 'exp_weblog_data',
  471. 'channel_data' => $is2 ? 'exp_channel_data' : 'exp_weblog_data',
  472. 'fields' => $is2 ? 'exp_channel_fields' : 'exp_weblog_fields',
  473. 'channel_fields' => $is2 ? 'exp_channel_fields' : 'exp_weblog_fields',
  474. 'id' => $is2 ? 'channel_id' : 'weblog_id',
  475. 'channel_id' => $is2 ? 'channel_id' : 'weblog_id',
  476. 'member_groups' => $is2 ? 'exp_channel_member_groups' : 'exp_weblog_member_groups',
  477. 'channel_member_groups' => $is2 ? 'exp_channel_member_groups' : 'exp_weblog_member_groups',
  478. 'titles' => $is2 ? 'exp_channel_titles' : 'exp_weblog_titles',
  479. 'channel_titles' => $is2 ? 'exp_channel_titles' : 'exp_weblog_titles'
  480. ),
  481. 'channel' => $is2 ? 'channel' : 'weblog',
  482. 'channels' => $is2 ? 'channels' : 'weblogs',
  483. 'theme_url' => $theme_url,
  484. 'theme_path' => $theme_path,
  485. 'addon_theme_url' => $theme_url . $this->lower_name . '/',
  486. 'addon_theme_path' => $theme_path . $this->lower_name . '/',
  487. );
  488. }
  489. /* END generate_shortcuts() */
  490. // --------------------------------------------------------------------
  491. /**
  492. * Instantiates an Object and Returns It
  493. *
  494. * Tired of having the same code duplicate everywhere for calling Typography, Email, Et Cetera.
  495. *
  496. * @access public
  497. * @return object|NULL
  498. */
  499. public function instantiate ( $name , $variables = array())
  500. {
  501. $lower_name = strtolower($name);
  502. $class_name = ucfirst($lower_name);
  503. // I am embarrassed by this exception -Paul
  504. if ($lower_name == 'email')
  505. {
  506. $class_name == 'EEmail';
  507. }
  508. if ( ! class_exists($class_name))
  509. {
  510. // We only load classes from the CP or CORE directories
  511. if (file_exists(PATH_CP.'core.'.$lower_name.EXT))
  512. {
  513. $location = PATH_CP.'core.'.$lower_name.EXT;
  514. }
  515. elseif (file_exists(PATH_CORE.'cp.'.$lower_name.EXT))
  516. {
  517. $location = PATH_CORE.'cp.'.$lower_name.EXT;
  518. }
  519. else
  520. {
  521. return NULL;
  522. }
  523. require_once $location;
  524. }
  525. $NEW = new $class_name();
  526. foreach($variables AS $key => $value)
  527. {
  528. $NEW->$key = $value;
  529. }
  530. return $NEW;
  531. }
  532. /* END instantiate() */
  533. // --------------------------------------------------------------------
  534. /**
  535. * Module's Action Object
  536. *
  537. * intantiates the actions object and sticks it to $this->actions
  538. *
  539. * @access public
  540. * @return object
  541. */
  542. public function actions ()
  543. {
  544. if ( ! is_object($this->actions))
  545. {
  546. $name = $this->class_name.'_actions';
  547. if ( ! class_exists($name))
  548. {
  549. require_once $this->addon_path . 'act.'.$this->lower_name.'.php';
  550. }
  551. $this->actions = new $name();
  552. $this->actions->data =& $this->data;
  553. }
  554. return $this->actions;
  555. }
  556. // END actions()
  557. // --------------------------------------------------------------------
  558. /**
  559. * Database Version
  560. *
  561. * Returns the version of the module in the database
  562. *
  563. * @access public
  564. * @param bool ignore all caches and get version from database
  565. * @return string
  566. */
  567. public function database_version ($ignore_cache = FALSE)
  568. {
  569. if ( ! $ignore_cache AND
  570. isset($this->cache['database_version']))
  571. {
  572. return $this->cache['database_version'];
  573. }
  574. // ----------------------------------------
  575. // Use Template object variable, if available
  576. // ----------------------------------------
  577. //EE1
  578. if ( ! $ignore_cache AND
  579. APP_VER < 2.0 AND
  580. isset($GLOBALS['TMPL']) AND
  581. is_object($GLOBALS['TMPL']) AND
  582. count($GLOBALS['TMPL']->module_data) > 0)
  583. {
  584. if ( ! isset($GLOBALS['TMPL']->module_data[$this->class_name]))
  585. {
  586. $this->cache['database_version'] = FALSE;
  587. }
  588. else
  589. {
  590. $this->cache['database_version'] = $GLOBALS['TMPL']->module_data[$this->class_name]['version'];
  591. }
  592. }
  593. //EE2
  594. elseif ( ! $ignore_cache AND
  595. APP_VER >= 2.0 AND
  596. isset(ee()->TMPL) AND
  597. is_object(ee()->TMPL) AND
  598. count(ee()->TMPL->module_data) > 0)
  599. {
  600. if ( ! isset(ee()->TMPL->module_data[$this->class_name]))
  601. {
  602. $this->cache['database_version'] = FALSE;
  603. }
  604. else
  605. {
  606. $this->cache['database_version'] = ee()->TMPL->module_data[$this->class_name]['version'];
  607. }
  608. }
  609. //global cache
  610. elseif ( ! $ignore_cache AND
  611. isset($this->global_cache['module_data']) AND
  612. isset($this->global_cache['module_data'][$this->lower_name]['database_version']))
  613. {
  614. $this->cache['database_version'] = $this->global_cache['module_data'][$this->lower_name]['database_version'];
  615. }
  616. //fill global with last resort
  617. else
  618. {
  619. // ----------------------------------------
  620. // Retrieve all Module Versions from the Database
  621. // - By retrieving all of them at once,
  622. // we can limit it to a max of one query per
  623. // page load for all Bridge Add-Ons
  624. // ----------------------------------------
  625. $query = $this->cacheless_query(
  626. "SELECT module_version, module_name
  627. FROM exp_modules"
  628. );
  629. foreach($query->result_array() as $row)
  630. {
  631. if ( isset(ee()->session) AND is_object(ee()->session))
  632. {
  633. $this->global_cache['module_data'][strtolower($row['module_name'])]['database_version'] = $row['module_version'];
  634. }
  635. if ($this->class_name == $row['module_name'])
  636. {
  637. $this->cache['database_version'] = $row['module_version'];
  638. }
  639. }
  640. }
  641. //did get anything?
  642. return isset($this->cache['database_version']) ? $this->cache['database_version'] : FALSE;
  643. }
  644. // END database_version()
  645. // --------------------------------------------------------------------
  646. /**
  647. * Find and return preference
  648. *
  649. * Any number of possible arguments, although typically I expect there will be only one or two
  650. *
  651. * @access public
  652. * @param string Preference to retrieve
  653. * @return null|string If preference does not exist, NULL is returned, else the value
  654. */
  655. public function preference ()
  656. {
  657. $s = func_num_args();
  658. if ($s == 0)
  659. {
  660. return NULL;
  661. }
  662. //--------------------------------------------
  663. // Fetch Module Preferences
  664. //--------------------------------------------
  665. if (count($this->module_preferences) == 0 AND $this->database_version() !== FALSE)
  666. {
  667. if ( method_exists($this->actions(), 'module_preferences'))
  668. {
  669. $this->module_preferences = $this->actions()->module_preferences();
  670. }
  671. elseif ( method_exists($this->data, 'get_module_preferences'))
  672. {
  673. $this->module_preferences = $this->data->get_module_preferences();
  674. }
  675. else
  676. {
  677. return NULL;
  678. }
  679. }
  680. //--------------------------------------------
  681. // Find Our Value, If It Exists
  682. //--------------------------------------------
  683. $value = (isset($this->module_preferences[func_get_arg(0)])) ?
  684. $this->module_preferences[func_get_arg(0)] : NULL;
  685. for($i = 1; $i < $s; ++$i)
  686. {
  687. if ( ! isset($value[func_get_arg($i)]))
  688. {
  689. return NULL;
  690. }
  691. $value = $value[func_get_arg($i)];
  692. }
  693. return $value;
  694. }
  695. // END preference()
  696. // --------------------------------------------------------------------
  697. /**
  698. * Checks to see if extensions are allowed
  699. *
  700. *
  701. * @access public
  702. * @return bool Whether the extensions are allowed
  703. */
  704. public function extensions_allowed ()
  705. {
  706. return $this->check_yes(ee()->config->item('allow_extensions'));
  707. }
  708. //END extensions_allowed
  709. // --------------------------------------------------------------------
  710. /**
  711. * Homegrown Version of Version Compare
  712. *
  713. * Compared two versions in the form of 1.1.1.d12 <= 1.2.3.f0
  714. *
  715. * @access public
  716. * @param string First Version
  717. * @param string Operator for Comparison
  718. * @param string Second Version
  719. * @return bool Whether the comparison is TRUE or FALSE
  720. */
  721. public function version_compare ($v1, $operator, $v2)
  722. {
  723. // Allowed operators
  724. if ( ! in_array($operator, array('>', '<', '>=', '<=', '==', '!=')))
  725. {
  726. trigger_error("Invalid Operator in Add-On Library - Version Compare", E_USER_WARNING);
  727. return FALSE;
  728. }
  729. // Normalize and Fix Invalid Values
  730. foreach(array('v1', 'v2') as $var)
  731. {
  732. $x = array_slice(preg_split("/\./", trim($$var), -1, PREG_SPLIT_NO_EMPTY), 0, 4);
  733. for($i=0; $i < 4; $i++)
  734. {
  735. if ( ! isset($x[$i]))
  736. {
  737. $x[$i] = ($i == 3) ? 'f0' : '0';
  738. }
  739. elseif ($i < 3 AND ctype_digit($x[$i]) == FALSE)
  740. {
  741. $x[$i] = '0';
  742. }
  743. elseif($i == 3 AND ! preg_match("/^[abdf]{1}[0-9]+$/", $x[$i]))
  744. {
  745. $x[$i] = 'f0';
  746. }
  747. // Set up for PHP's version_compare
  748. if ($i == 3)
  749. {
  750. $letter = substr($x[3], 0, 1);
  751. $sans_letter = substr($x[3], 1);
  752. if ($letter == 'd')
  753. {
  754. $letter = 'dev';
  755. }
  756. elseif($letter == 'f')
  757. {
  758. $letter = 'RC';
  759. }
  760. $x[3] = $letter.'.'.$sans_letter;
  761. }
  762. }
  763. $$var = implode('.', $x);
  764. }
  765. // echo $v1.' - '.$v2;
  766. //this is a php built in function,
  767. //self::version_compare is just prep work
  768. return version_compare($v1, $v2, $operator);
  769. }
  770. // END version_compare()
  771. // --------------------------------------------------------------------
  772. /**
  773. * ExpressionEngine CP View Request
  774. *
  775. * Just like a typical view request but we do a few EE CP related things too
  776. *
  777. * @access public
  778. * @param array
  779. * @return void
  780. */
  781. public function ee_cp_view ($view)
  782. {
  783. //--------------------------------------------
  784. // Build Crumbs!
  785. //--------------------------------------------
  786. $this->build_crumbs();
  787. $this->build_right_links();
  788. //--------------------------------------------
  789. // EE 1.x Code for Calling Certain CP Hooks
  790. //--------------------------------------------
  791. if (APP_VER < 2.0)
  792. {
  793. // -------------------------------------------
  794. // 'show_full_control_panel_start' hook.
  795. // - Full Control over CP
  796. // - Modify any $DSP class variable (JS, headers, etc.)
  797. // - Override any $DSP method and use their own
  798. //
  799. $edata = ee()->extensions->call('show_full_control_panel_start');
  800. if (ee()->extensions->end_script === TRUE) return;
  801. //
  802. // -------------------------------------------
  803. }
  804. //--------------------------------------------
  805. // Load View Path, Call View File
  806. //--------------------------------------------
  807. $output = $this->view($view, array(), TRUE);
  808. //--------------------------------------------
  809. // EE 1.x Code for Calling Certain CP Hooks
  810. //--------------------------------------------
  811. if (APP_VER < 2.0)
  812. {
  813. // -------------------------------------------
  814. // 'show_full_control_panel_end' hook.
  815. // - Rewrite CP's HTML
  816. // - Find/Replace Stuff, etc.
  817. //
  818. if (ee()->extensions->active_hook('show_full_control_panel_end') === TRUE)
  819. {
  820. $output = ee()->extensions->call('show_full_control_panel_end', $output);
  821. if (ee()->extensions->end_script === TRUE) return;
  822. }
  823. //
  824. // -------------------------------------------
  825. }
  826. //--------------------------------------------
  827. // EE 1.x, We Add Secure Form Hashes and Output Content to Browser
  828. //--------------------------------------------
  829. if (APP_VER < 2.0)
  830. {
  831. if (stristr($output, '{XID_HASH}'))
  832. {
  833. $output = ee()->functions->add_form_security_hash($output);
  834. }
  835. ee()->output->_display(ee()->cp->secure_hash($output));
  836. exit;
  837. }
  838. //--------------------------------------------
  839. // In EE 2.x, we return the Output and Let EE Continue Building the CP
  840. //--------------------------------------------
  841. return $output;
  842. }
  843. // END ee_cp_view()
  844. // --------------------------------------------------------------------
  845. /**
  846. * Javascript/CSS File View Request
  847. *
  848. * Outputs a View file as if it were a Javascript file
  849. *
  850. * @access public
  851. * @param array
  852. * @return void
  853. */
  854. public function file_view ($view, $modification_time = '')
  855. {
  856. //--------------------------------------------
  857. // Auto-detect the Type
  858. //--------------------------------------------
  859. if (preg_match("/\.([cjs]{2,3})$/i", $view, $match) AND
  860. in_array($match[1], array('css', 'js')))
  861. {
  862. switch($match[1])
  863. {
  864. case 'css' :
  865. $type = 'css';
  866. break;
  867. case 'js' :
  868. $type = 'javascript';
  869. break;
  870. }
  871. }
  872. else
  873. {
  874. exit;
  875. }
  876. //--------------------------------------------
  877. // Load View Path, Call View File
  878. //--------------------------------------------
  879. $output = $this->view($view, array(), TRUE);
  880. //--------------------------------------------
  881. // EE 1.x, We Add Secure Form Hashes and Output Content to Browser
  882. //--------------------------------------------
  883. if ($type == 'javascript' AND stristr($output, '{XID_SECURE_HASH}'))
  884. {
  885. $output = str_replace('{XID_SECURE_HASH}', '{XID_HASH}', $output);
  886. }
  887. if ($type == 'javascript')
  888. {
  889. $output = ee()->functions->add_form_security_hash($output);
  890. }
  891. //----------------------------------------
  892. // Generate HTTP headers
  893. //----------------------------------------
  894. if (ee()->config->item('send_headers') == 'y')
  895. {
  896. $ext = pathinfo($view, PATHINFO_EXTENSION);
  897. $file = ($ext == '') ? $view.EXT : $view;
  898. $path = $this->view_path.$file;
  899. $max_age = 5184000;
  900. $modification_time = ($modification_time != '') ? $modification_time : filemtime($path);
  901. $modified_since = ee()->input->server('HTTP_IF_MODIFIED_SINCE');
  902. if ( ! ctype_digit($modification_time))
  903. {
  904. $modification_time = filemtime($path);
  905. }
  906. // Remove anything after the semicolon
  907. if ($pos = strrpos($modified_since, ';') !== FALSE)
  908. {
  909. $modified_since = substr($modified_since, 0, $pos);
  910. }
  911. // Send a custom ETag to maintain a useful cache in
  912. // load-balanced environments
  913. header("ETag: ".md5($modification_time.$path));
  914. // If the file is in the client cache, we'll
  915. // send a 304 and be done with it.
  916. if ($modified_since AND (strtotime($modified_since) == $modification_time))
  917. {
  918. ee()->output->set_status_header(304);
  919. exit;
  920. }
  921. ee()->output->set_status_header(200);
  922. @header("Cache-Control: max-age={$max_age}, must-revalidate");
  923. @header('Vary: Accept-Encoding');
  924. @header('Last-Modified: '.gmdate('D, d M Y H:i:s', $modification_time).' GMT');
  925. @header('Expires: '.gmdate('D, d M Y H:i:s', time() + $max_age).' GMT');
  926. @header('Content-Length: '.strlen($output));
  927. }
  928. //----------------------------------------
  929. // Send JavaScript/CSS Header and Output
  930. //----------------------------------------
  931. @header("Content-type: text/".$type);
  932. exit($output);
  933. }
  934. // END ee_cp_view()
  935. // --------------------------------------------------------------------
  936. /**
  937. * View File Loader
  938. *
  939. * Takes a file from the filesystem and loads it so that we can parse PHP within it just
  940. *
  941. *
  942. * @access public
  943. * @param string $view - The view file to be located
  944. * @param array $vars - Array of data variables to be parsed in the file system
  945. * @param bool $return - Return file as string or put into buffer
  946. * @param string $path - Override path for the file rather than using $this->view_path
  947. * @return string
  948. */
  949. public function view ($view, $vars = array(), $return = FALSE, $path='')
  950. {
  951. //have to keep this for legacy footers
  952. global $DSP, $LANG, $PREFS;
  953. //--------------------------------------------
  954. // Determine File Name and Extension for Requested File
  955. //--------------------------------------------
  956. if ($path == '')
  957. {
  958. $ext = pathinfo($view, PATHINFO_EXTENSION);
  959. $file = ($ext == '') ? $view.EXT : $view;
  960. $path = $this->view_path.$file;
  961. }
  962. else
  963. {
  964. $x = explode('/', $path);
  965. $file = end($x);
  966. }
  967. //--------------------------------------------
  968. // Make Sure the File Actually Exists
  969. //--------------------------------------------
  970. if ( ! file_exists($path))
  971. {
  972. trigger_error("Invalid View File Request of '".$path."'");
  973. return FALSE;
  974. }
  975. // All variables sent to the function are cached, which allows us to use them
  976. // within embedded view files within this file.
  977. if (is_array($vars))
  978. {
  979. $this->cached_vars = array_merge($this->cached_vars, $vars);
  980. }
  981. extract($this->cached_vars, EXTR_PREFIX_SAME, 'var_');
  982. //print_r($this->cached_vars);
  983. //--------------------------------------------
  984. // Buffer Output
  985. // - Increases Speed
  986. // - Allows Views to be Nested Within Views
  987. //--------------------------------------------
  988. ob_start();
  989. //--------------------------------------------
  990. // Load File and Rewrite Short Tags
  991. //--------------------------------------------
  992. $rewrite_short_tags = TRUE; // Hard coded setting for now...
  993. if ((bool) @ini_get('short_open_tag') === FALSE AND $rewrite_short_tags == TRUE)
  994. {
  995. echo eval('?'.'>'.preg_replace("/;*\s*\?".">/", "; ?".">",
  996. str_replace('<'.'?=', '<?php echo ',
  997. file_get_contents($path))).'<'.'?php ');
  998. }
  999. else
  1000. {
  1001. include($path);
  1002. }
  1003. //--------------------------------------------
  1004. // Return Parsed File as String
  1005. //--------------------------------------------
  1006. if ($return === TRUE)
  1007. {
  1008. $buffer = ob_get_contents();
  1009. @ob_end_clean();
  1010. return $buffer;
  1011. }
  1012. //--------------------------------------------
  1013. // Flush Buffer
  1014. //--------------------------------------------
  1015. if (ob_get_level() > $this->ob_level + 1)
  1016. {
  1017. ob_end_flush();
  1018. }
  1019. else
  1020. {
  1021. $buffer = ob_get_contents();
  1022. @ob_end_clean();
  1023. return $buffer;
  1024. }
  1025. }
  1026. // END view()
  1027. // --------------------------------------------------------------------
  1028. /**
  1029. * Fetch the CP Stylesheet
  1030. *
  1031. * Had to build this because it was not abstracted well enough for us to simply call EE methods
  1032. *
  1033. * @access public
  1034. * @param array An array of find/replace values to perform in the stylesheet
  1035. * @return string
  1036. */
  1037. public function fetch_stylesheet ()
  1038. {
  1039. // Change CSS on the click so it works like the hover until they unclick?
  1040. $ptb = ee()->config->item('publish_tab_behavior');
  1041. $stb = ee()->config->item('sites_tab_behavior');
  1042. $tab_behaviors = array(
  1043. 'publish_tab_selector' => ($ptb == 'hover') ? 'hover' : 'active',
  1044. 'publish_tab_display' => ($ptb == 'none') ? '' : 'display:block; visibility: visible;',
  1045. 'publish_tab_ul_display' => ($ptb == 'none') ? '' : 'display:none;',
  1046. 'sites_tab_selector' => ($stb == 'hover') ? 'hover' : 'active',
  1047. 'sites_tab_display' => ($stb == 'none') ? '' : 'display:block; visibility: visible;',
  1048. 'sites_tab_ul_display' => ($stb == 'none') ? '' : 'display:none;'
  1049. );
  1050. $stylesheet = $GLOBALS['DSP']->fetch_stylesheet();
  1051. foreach ($tab_behaviors as $key => $val)
  1052. {
  1053. $stylesheet = str_replace(LD.$key.RD, $val, $stylesheet);
  1054. }
  1055. return $stylesheet;
  1056. }
  1057. // END fetch_stylesheet()
  1058. // --------------------------------------------------------------------
  1059. /**
  1060. * Add Array of Breadcrumbs for a Page
  1061. *
  1062. * @access public
  1063. * @param array
  1064. * @return null
  1065. */
  1066. public function add_crumbs ($array)
  1067. {
  1068. if ( is_array($array))
  1069. {
  1070. foreach($array as $value)
  1071. {
  1072. if ( is_array($value))
  1073. {
  1074. $this->add_crumb($value[0], $value[1]);
  1075. }
  1076. else
  1077. {
  1078. $this->add_crumb($value);
  1079. }
  1080. }
  1081. }
  1082. }
  1083. /* END add_crumbs */
  1084. // --------------------------------------------------------------------
  1085. /**
  1086. * Add Single Crumb to List of Breadcrumbs
  1087. *
  1088. * @access public
  1089. * @param string Text of breacrumb
  1090. * @param string Link, if any for breadcrumb
  1091. * @return null
  1092. */
  1093. public function add_crumb ($text, $link='')
  1094. {
  1095. $this->crumbs[] = ($link == '') ? array($text) : array($text, $link);
  1096. }
  1097. /* END add_crumb() */
  1098. // --------------------------------------------------------------------
  1099. /**
  1100. * Takes Our Crumbs and Builds them into the Breadcrumb List
  1101. *
  1102. * @access public
  1103. * @return null
  1104. */
  1105. public function build_crumbs ()
  1106. {
  1107. global $DSP, $OUT;
  1108. if ( is_string($this->crumbs))
  1109. {
  1110. if (APP_VER < 2.0) $DSP->title = $this->crumbs;
  1111. $this->cached_vars['page_crumb'] = $this->crumbs;
  1112. $this->cached_vars['page_title'] = $this->crumbs;
  1113. return;
  1114. }
  1115. if (APP_VER < 2.0) $DSP->crumb = '';
  1116. $this->cached_vars['page_crumb'] = '';
  1117. $this->cached_vars['page_title'] = '';
  1118. $item = (count($this->crumbs) == 1) ? TRUE : FALSE;
  1119. ee()->load->helper('url');
  1120. foreach($this->crumbs as $key => $value)
  1121. {
  1122. if (is_array($value))
  1123. {
  1124. $name = $value[0];
  1125. if (isset($value[1]))
  1126. {
  1127. $name = "<a href='{$value[1]}'>{$value[0]}</a>";
  1128. }
  1129. $this->cached_vars['page_title'] = $value[0];
  1130. }
  1131. else
  1132. {
  1133. $name = $value;
  1134. $this->cached_vars['page_title'] = $value;
  1135. }
  1136. if (APP_VER < 2.0)
  1137. {
  1138. if ($item === FALSE)
  1139. {
  1140. $this->cached_vars['page_crumb'] .= $name;
  1141. $item = TRUE;
  1142. }
  1143. else
  1144. {
  1145. $this->cached_vars['page_crumb'] .= $DSP->crumb_item($name);
  1146. }
  1147. }
  1148. else
  1149. {
  1150. if (is_array($value) AND isset($value[1]))
  1151. {
  1152. ee()->cp->set_breadcrumb($value[1], $value[0]);
  1153. }
  1154. }
  1155. }
  1156. /** --------------------------------------------
  1157. /** 2.0 Specific Code
  1158. /** --------------------------------------------*/
  1159. $this->cached_vars['cp_page_title'] = $this->cached_vars['page_title'];
  1160. if (APP_VER >= 2.0)
  1161. {
  1162. ee()->cp->set_variable('cp_page_title', $this->cached_vars['cp_page_title'] );
  1163. }
  1164. /** --------------------------------------------
  1165. /** 1.x Breadcrumb View Variable
  1166. /** --------------------------------------------*/
  1167. if (APP_VER < 2.0) $DSP->crumb = $this->cached_vars['page_crumb'];
  1168. }
  1169. /* END build_crumbs() */
  1170. // --------------------------------------------------------------------
  1171. /**
  1172. * Field Output Prep for arrays and strings
  1173. *
  1174. *
  1175. * @access public
  1176. * @param string|array The item that needs to be prepped for output
  1177. * @return string|array
  1178. */
  1179. function output ($item)
  1180. {
  1181. if (is_array($item))
  1182. {
  1183. $array = array();
  1184. foreach($item as $key => $value)
  1185. {
  1186. $array[$this->output($key)] = $this->output($value);
  1187. }
  1188. return $array;
  1189. }
  1190. elseif(is_string($item))
  1191. {
  1192. return htmlspecialchars($item, ENT_QUOTES);
  1193. }
  1194. else
  1195. {
  1196. return $item;
  1197. }
  1198. }
  1199. /* END output() */
  1200. // --------------------------------------------------------------------
  1201. /**
  1202. * Cycles Between Values
  1203. *
  1204. * Takes a list of arguments and cycles through them on each call
  1205. *
  1206. * @access public
  1207. * @param string|array The items that need to be cycled through
  1208. * @return string|array
  1209. */
  1210. function cycle ($items)
  1211. {
  1212. if ( ! is_array($items))
  1213. {
  1214. $items = func_get_args();
  1215. }
  1216. $hash = md5(implode('|', $items));
  1217. if ( ! isset($this->switches[$hash]) OR ! isset($items[$this->switches[$hash] + 1]))
  1218. {
  1219. $this->switches[$hash] = 0;
  1220. }
  1221. else
  1222. {
  1223. $this->switches[$hash]++;
  1224. }
  1225. return $items[$this->switches[$hash]];
  1226. }
  1227. /* END cycle() */
  1228. // --------------------------------------------------------------------
  1229. /**
  1230. * Order Array
  1231. *
  1232. * Takes an array and reorders it based on the value of a key
  1233. *
  1234. * @access public
  1235. * @param array $array The array needing to be reordered
  1236. * @param string $key The key being used to reorder
  1237. * @param string $order The order for the values asc/desc
  1238. * @return array
  1239. */
  1240. function order_array ($array, $key, $order = 'desc')
  1241. {
  1242. // http://us2.php.net/manual/en/function.array-multisort.php
  1243. }
  1244. /* END order_array() */
  1245. // --------------------------------------------------------------------
  1246. /**
  1247. * Column Exists in DB Table
  1248. *
  1249. * @access public
  1250. * @param string $column The column whose existence we are looking for
  1251. * @param string $table In which table?
  1252. * @return array
  1253. */
  1254. public function column_exists ( $column, $table, $cache = TRUE )
  1255. {
  1256. if ($cache === TRUE AND isset($this->cache['column_exists'][$table][$column]))
  1257. {
  1258. return $this->cache['column_exists'][$table][$column];
  1259. }
  1260. /** ----------------------------------------
  1261. /** Check for columns in tags table
  1262. /** ----------------------------------------*/
  1263. $query = ee()->db->query( "DESCRIBE `".ee()->db->escape_str( $table )."` `".ee()->db->escape_str( $column )."`" );
  1264. if ( $query->num_rows > 0 )
  1265. {
  1266. return $this->cache['column_exists'][$table][$column] = TRUE;
  1267. }
  1268. return $this->cache['column_exists'][$table][$column] = FALSE;
  1269. }
  1270. /* END column_exists() */
  1271. // --------------------------------------------------------------------
  1272. /**
  1273. * Retrieve Remote File and Cache It
  1274. *
  1275. * @access public
  1276. * @param string $url - URL to be retrieved
  1277. * @param integer $cache_length - How long to cache the result, if successful retrieval
  1278. * @return bool Success or failure. Data result stored in $this->remote_data
  1279. */
  1280. public function retrieve_remote_file ($url, $cache_length = 24, $path='', $file='')
  1281. {
  1282. global $FNS;
  1283. $path = ($path == '') ? PATH_CACHE.'addon_builder/' : rtrim($path, '/').'/';
  1284. $file = ($file == '') ? md5($url).'.txt' : $file;
  1285. $file_path = $path.$file;
  1286. /** --------------------------------------------
  1287. /** Check for Cached File
  1288. /** --------------------------------------------*/
  1289. if ( ! file_exists($file_path) OR (time() - filemtime($file_path)) > (60 * 60 * round($cache_length)))
  1290. {
  1291. @unlink($file_path);
  1292. }
  1293. elseif (($this->remote_data = file_get_contents($file_path)) === FALSE)
  1294. {
  1295. @unlink($file_path);
  1296. }
  1297. else
  1298. {
  1299. return TRUE;
  1300. }
  1301. /** --------------------------------------------
  1302. /** Validate and Create Cache Directory
  1303. /** --------------------------------------------*/
  1304. if ( ! is_dir($path))
  1305. {
  1306. $dirs = explode('/', trim(ee()->functions->remove_double_slashes($path), '/'));
  1307. $path = '/';
  1308. foreach ($dirs as $dir)
  1309. {
  1310. if ( ! @is_dir($path.$dir))
  1311. {
  1312. if ( ! @mkdir($path.$dir, 0777))
  1313. {
  1314. $this->errors[] = 'Unable to Create Directory: '.$path.$dir;
  1315. return;
  1316. }
  1317. @chmod($path.$dir, 0777);
  1318. }
  1319. $path .= $dir.'/';
  1320. }
  1321. }
  1322. if ($this->is_really_writable($path) === FALSE)
  1323. {
  1324. $this->errors[] = 'Cache Directory is Not Writable: '.$path;
  1325. return FALSE;
  1326. }
  1327. /** --------------------------------------------
  1328. /** Retrieve Our URL
  1329. /** --------------------------------------------*/
  1330. $this->remote_data = $this->fetch_url($url);
  1331. if ($this->remote_data == '')
  1332. {
  1333. $this->errors[] = 'Unable to Retrieve URL: '.$url;
  1334. return FALSE;
  1335. }
  1336. /** --------------------------------------------
  1337. /** Write Cache File
  1338. /** --------------------------------------------*/
  1339. if ( ! $this->write_file($file_path, $this->remote_data))
  1340. {
  1341. $this->errors[] = 'Unable to Write File to Cache';
  1342. return FALSE;
  1343. }
  1344. return TRUE;
  1345. }
  1346. /* END retrieve_remote_file() */
  1347. // --------------------------------------------------------------------
  1348. /**
  1349. * Fetch the Data for a URL
  1350. *
  1351. * @access public
  1352. * @param string $url - The URI that we are fetching
  1353. * @param array $post - The POST array we are sending
  1354. * @param string|bool $username - Possible username required
  1355. * @param string|bool $password - Password to go with the username
  1356. * @return string
  1357. */
  1358. public function fetch_url ($url, $post = array(), $username = FALSE, $password = FALSE)
  1359. {
  1360. $data = '';
  1361. $user_agent = ini_get('user_agent');
  1362. if ( empty($user_agent))
  1363. {
  1364. $user_agent = $this->class_name.'/1.0';
  1365. }
  1366. /** --------------------------------------------
  1367. /** file_get_contents()
  1368. /** --------------------------------------------*/
  1369. if ((bool) @ini_get('allow_url_fopen') !== FALSE && empty($post) && $username == FALSE)
  1370. {
  1371. $opts = array('http' => array('header' => "User-Agent:".$user_agent."\r\n"),
  1372. 'https' => array('header' => "User-Agent:".$user_agent."\r\n"));
  1373. $context = stream_context_create($opts);
  1374. if ($data = @file_get_contents($url, FALSE, $context))
  1375. {
  1376. return $data;
  1377. }
  1378. }
  1379. /** --------------------------------------------
  1380. /** cURL
  1381. /** --------------------------------------------*/
  1382. if (function_exists('curl_init') === TRUE AND ($ch = @curl_init()) !== FALSE)
  1383. {
  1384. curl_setopt($ch, CURLOPT_URL, $url);
  1385. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  1386. curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
  1387. // prevent a PHP warning on certain servers
  1388. if (! ini_get('safe_mode') AND ! ini_get('open_basedir'))
  1389. {
  1390. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
  1391. }
  1392. // Are we posting?
  1393. if ( ! empty( $post ) )
  1394. {
  1395. $str = '';
  1396. foreach ( $post as $key => $val )
  1397. {
  1398. $str .= urlencode( $key ) . "=" . urlencode( $val ) . "&";
  1399. }
  1400. $str = substr( $str, 0, -1 );
  1401. curl_setopt( $ch, CURLOPT_POST, TRUE );
  1402. curl_setopt( $ch, CURLOPT_POSTFIELDS, $str );
  1403. }
  1404. curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
  1405. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  1406. curl_setopt($ch, CURLOPT_TIMEOUT, 15);
  1407. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  1408. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1409. if ($username != FALSE)
  1410. {
  1411. curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
  1412. if (defined('CURLOPT_HTTPAUTH')) curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
  1413. }
  1414. $data = curl_exec($ch);
  1415. curl_close($ch);
  1416. if ($data !== FALSE)
  1417. {
  1418. return $data;
  1419. }
  1420. }
  1421. // --------------------------------------------
  1422. // fsockopen() - Last but only slightly least...
  1423. // --------------------------------------------
  1424. $parts = parse_url($url);
  1425. $host = $parts['host'];
  1426. $path = (!isset($parts['path'])) ? '/' : $parts['path'];
  1427. $port = ($parts['scheme'] == "https") ? '443' : '80';
  1428. $ssl = ($parts['scheme'] == "https") ? 'ssl://' : '';
  1429. if (isset($parts['query']) AND $parts['query'] != '')
  1430. {
  1431. $path .= '?'.$parts['query'];
  1432. }
  1433. $data = '';
  1434. $fp = @fsockopen($ssl.$host, $port, $error_num, $error_str, 7);
  1435. if (is_resource($fp))
  1436. {
  1437. $getpost = ( ! empty( $post ) ) ? 'POST ': 'GET ';
  1438. fputs($fp, $getpost.$path." HTTP/1.0\r\n" );
  1439. fputs($fp, "Host: ".$host . "\r\n" );
  1440. if ( ! empty( $post ) )
  1441. {
  1442. $str = '';
  1443. foreach ( $post as $key => $val )
  1444. {
  1445. $str .= urlencode( $key ) . "=" . urlencode( $val ) . "&";
  1446. }
  1447. $str = substr( $str, 0, -1 );
  1448. fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
  1449. fputs($fp, "Content-length: " . strlen( $str ) . "\r\n");
  1450. }
  1451. fputs($fp, "User-Agent: ".$user_agent."r\n");
  1452. if ($username != FALSE)
  1453. {
  1454. fputs ($fp, "Authorization: Basic ".base64_encode($username.':'.$password)."\r\n");
  1455. }
  1456. fputs($fp, "Connection: close\r\n\r\n");
  1457. if ( ! empty( $post ) )
  1458. {
  1459. fputs($fp, $str . "\r\n\r\n");
  1460. }
  1461. /* ------------------------------
  1462. /* This error suppression has to do with a PHP bug involving
  1463. /* SSL connections: http://bugs.php.net/bug.php?id=23220
  1464. /* ------------------------------*/
  1465. $old_level = error_reporting(0);
  1466. $headers = '';
  1467. while ( ! feof($fp))
  1468. {
  1469. $bit = fgets($fp, 128);
  1470. $headers .= $bit;
  1471. if(preg_match("/^\r?\n$/", $bit)) break;
  1472. }
  1473. while ( ! feof($fp))
  1474. {
  1475. $data .= fgets($fp, 128);
  1476. }
  1477. error_reporting($old_level);
  1478. fclose($fp);
  1479. }
  1480. return trim($data);
  1481. }
  1482. /* END fetch_url() */
  1483. // --------------------------------------------------------------------
  1484. /**
  1485. * Write File
  1486. *
  1487. * @access public
  1488. * @param $file Full location of final file
  1489. * @param $data Data to put into file
  1490. * @return bool
  1491. */
  1492. function write_file ($file, $data)
  1493. {
  1494. $temp_file = $file.'.tmp';
  1495. if ( ! file_exists($temp_file))
  1496. {
  1497. // Remove old cache file, prevents rename problem on Windows
  1498. // http://bugs.php.net/bug.php?id=44805
  1499. @unlink($file);
  1500. if (file_exists($file))
  1501. {
  1502. $this->errors[] = "Unable to Delete Old Cache File: ".$file;
  1503. return FALSE;
  1504. }
  1505. if ( ! $fp = @fopen($temp_file, 'wb'))
  1506. {
  1507. $this->errors[] = "Unable to Write Temporary Cache File: ".$temp_file;
  1508. return FALSE;
  1509. }
  1510. if ( ! flock($fp, LOCK_EX | LOCK_NB))
  1511. {
  1512. $this->errors[] = "Locking Error when Writing Cache File";
  1513. return FALSE;
  1514. }
  1515. fwrite($fp, $data);
  1516. flock($fp, LOCK_UN);
  1517. fclose($fp);
  1518. // Write, then rename...
  1519. @rename($temp_file, $file);
  1520. // Double check permissions
  1521. @chmod($file, 0777);
  1522. // Just in case the rename did not work
  1523. @unlink($temp_file);
  1524. }
  1525. return TRUE;
  1526. }
  1527. /* END write_file() */
  1528. // --------------------------------------------------------------------
  1529. /**
  1530. * Check that File is Really Writable, Even on Windows
  1531. *
  1532. * is_writable() returns TRUE on Windows servers when you really cannot write to the file
  1533. * as the OS reports to PHP as FALSE only if the read-only attribute is marked. Ugh!
  1534. *
  1535. * Oh, and there is some silly thing with
  1536. *
  1537. * @access public
  1538. * @param string $path - Path to be written to.
  1539. * @param bool $remove - If writing a file, remove it after testing?
  1540. * @return bool
  1541. */
  1542. public function is_really_writable ($file, $remove = FALSE)
  1543. {
  1544. // is_writable() returns TRUE on Windows servers
  1545. // when you really can't write to the file
  1546. // as the OS reports to PHP as FALSE only if the
  1547. // read-only attribute is marked. Ugh?
  1548. if (substr($file, -1) == '/' OR is_dir($file))
  1549. {
  1550. return self::is_really_writable(rtrim($file, '/').'/'.uniqid(mt_rand()), TRUE);
  1551. }
  1552. if (($fp = @fopen($file, 'ab')) === FALSE)
  1553. {
  1554. return FALSE;
  1555. }
  1556. else
  1557. {
  1558. if ($remove === TRUE)
  1559. {
  1560. @unlink($file);
  1561. }
  1562. fclose($fp);
  1563. return TRUE;
  1564. }
  1565. }
  1566. /* END is_really_writable() */
  1567. // --------------------------------------------------------------------
  1568. /**
  1569. * Check Captcha
  1570. *
  1571. * If Captcha is required by a module, we simply do all the work
  1572. *
  1573. * @access public
  1574. * @return bool
  1575. */
  1576. public function check_captcha ()
  1577. {
  1578. if ( ee()->config->item('captcha_require_members') == 'y' OR
  1579. (ee()->config->item('captcha_require_members') == 'n' AND
  1580. ee()->session->userdata['member_id'] == 0))
  1581. {
  1582. if ( empty($_POST['captcha']))
  1583. {
  1584. return FALSE;
  1585. }
  1586. else
  1587. {
  1588. $res = ee()->db->query(
  1589. "SELECT COUNT(*) AS count
  1590. FROM exp_captcha
  1591. WHERE word = '" . ee()->db->escape_str($_POST['captcha']) . "'
  1592. AND ip_address = '" . ee()->db->escape_str(ee()->input->ip_address()) . "'
  1593. AND date > UNIX_TIMESTAMP()-7200"
  1594. );
  1595. if ($res->row('count') == 0)
  1596. {
  1597. return FALSE;
  1598. }
  1599. ee()->db->query(
  1600. "DELETE FROM exp_captcha
  1601. WHERE (
  1602. word = '" . ee()->db->escape_str($_POST['captcha']) . "'
  1603. AND ip_address = '" . ee()->db->escape_str(ee()->input->ip_address()) . "'
  1604. )
  1605. OR date < UNIX_TIMESTAMP()-7200"
  1606. );
  1607. }
  1608. }
  1609. return TRUE;
  1610. }
  1611. // END check_captcha()
  1612. // --------------------------------------------------------------------
  1613. /**
  1614. * Check Secure Forms
  1615. *
  1616. * Checks to see if Secure Forms is enabled, and if so sees if the submitted hash is valid
  1617. *
  1618. * @access public
  1619. * @return bool
  1620. */
  1621. public function check_secure_forms ()
  1622. {
  1623. // -----------------------------------…

Large files files are truncated, but you can click here to view the full file