PageRenderTime 53ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/system/expressionengine/libraries/Functions.php

https://bitbucket.org/tdevonshire/hoolux
PHP | 2996 lines | 1909 code | 430 blank | 657 comment | 380 complexity | cd7db8c4a9364fdf434e3b3da1c42de8 MD5 | raw file

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

  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * ExpressionEngine - by EllisLab
  4. *
  5. * @package ExpressionEngine
  6. * @author EllisLab Dev Team
  7. * @copyright Copyright (c) 2003 - 2012, EllisLab, Inc.
  8. * @license http://ellislab.com/expressionengine/user-guide/license.html
  9. * @link http://ellislab.com
  10. * @since Version 2.0
  11. * @filesource
  12. */
  13. // ------------------------------------------------------------------------
  14. /**
  15. * ExpressionEngine Core Functions Class
  16. *
  17. * @package ExpressionEngine
  18. * @subpackage Core
  19. * @category Core
  20. * @author EllisLab Dev Team
  21. * @link http://ellislab.com
  22. */
  23. class EE_Functions {
  24. var $seed = FALSE; // Whether we've seeded our rand() function. We only seed once per script execution
  25. var $cached_url = array();
  26. var $cached_path = array();
  27. var $cached_index = array();
  28. var $cached_captcha = '';
  29. var $template_map = array();
  30. var $template_type = '';
  31. var $action_ids = array();
  32. var $file_paths = array();
  33. var $conditional_debug = FALSE;
  34. var $catfields = array();
  35. /**
  36. * Constructor
  37. */
  38. function __construct()
  39. {
  40. // Make a local reference to the ExpressionEngine super object
  41. $this->EE =& get_instance();
  42. }
  43. // --------------------------------------------------------------------
  44. /**
  45. * Fetch base site index
  46. *
  47. * @access public
  48. * @param bool
  49. * @param bool
  50. * @return string
  51. */
  52. function fetch_site_index($add_slash = FALSE, $sess_id = TRUE)
  53. {
  54. if (isset($this->cached_index[$add_slash.$sess_id.$this->template_type]))
  55. {
  56. return $this->cached_index[$add_slash.$sess_id.$this->template_type];
  57. }
  58. $url = $this->EE->config->slash_item('site_url');
  59. $url .= $this->EE->config->item('site_index');
  60. if ($this->EE->config->item('force_query_string') == 'y')
  61. {
  62. $url .= '?';
  63. }
  64. if (is_object($this->EE->session) && $this->EE->session->userdata('session_id') != '' && REQ != 'CP' && $sess_id == TRUE &&
  65. $this->EE->config->item('user_session_type') != 'c' && $this->template_type == 'webpage')
  66. {
  67. $url .= "/S=".$this->EE->session->userdata('session_id')."/";
  68. }
  69. if ($add_slash == TRUE)
  70. {
  71. if (substr($url, -1) != '/')
  72. {
  73. $url .= "/";
  74. }
  75. }
  76. $this->cached_index[$add_slash.$sess_id.$this->template_type] = $url;
  77. return $url;
  78. }
  79. // --------------------------------------------------------------------
  80. /**
  81. * Create a custom URL
  82. *
  83. * The input to this function is parsed and added to the
  84. * full site URL to create a full URL/URI
  85. *
  86. * @access public
  87. * @param string
  88. * @param bool
  89. * @return string
  90. */
  91. function create_url($segment, $sess_id = TRUE)
  92. {
  93. // Since this function can be used via a callback
  94. // we'll fetch the segment if it's an array
  95. if (is_array($segment))
  96. {
  97. $segment = $segment[1];
  98. }
  99. if (isset($this->cached_url[$segment]))
  100. {
  101. return $this->cached_url[$segment];
  102. }
  103. $full_segment = $segment;
  104. $segment = str_replace(array("'", '"'), '', $segment);
  105. $segment = preg_replace("/(.+?(\/))index(\/)(.*?)/", "\\1\\2", $segment);
  106. $segment = preg_replace("/(.+?(\/))index$/", "\\1", $segment);
  107. // These are exceptions to the normal path rules
  108. if ($segment == '' OR strtolower($segment) == 'site_index')
  109. {
  110. return $this->fetch_site_index();
  111. }
  112. if (strtolower($segment) == 'logout')
  113. {
  114. $qs = ($this->EE->config->item('force_query_string') == 'y') ? '' : '?';
  115. return $this->fetch_site_index(0, 0).$qs.'ACT='.$this->fetch_action_id('Member', 'member_logout');
  116. }
  117. // END Specials
  118. // Load the string helper
  119. $this->EE->load->helper('string');
  120. $base = $this->fetch_site_index(0, $sess_id).'/'.trim_slashes($segment);
  121. $out = $this->remove_double_slashes($base);
  122. $this->cached_url[$full_segment] = $out;
  123. return $out;
  124. }
  125. // --------------------------------------------------------------------
  126. /**
  127. * Creates a url for Pages links
  128. *
  129. * @access public
  130. * @return string
  131. */
  132. function create_page_url($base_url, $segment, $trailing_slash = FALSE)
  133. {
  134. // Load the string helper
  135. $this->EE->load->helper('string');
  136. if ($this->EE->config->item('force_query_string') == 'y')
  137. {
  138. if (strpos($base_url, $this->EE->config->item('index_page') . '/') !== FALSE)
  139. {
  140. $base_url = rtrim($base_url, '/');
  141. }
  142. $base_url .= '?';
  143. }
  144. $base = $base_url.'/'.trim_slashes($segment);
  145. if (substr($base, -1) != '/' && $trailing_slash == TRUE)
  146. {
  147. $base .= '/';
  148. }
  149. $out = $this->remove_double_slashes($base);
  150. return $out;
  151. }
  152. // --------------------------------------------------------------------
  153. /**
  154. * Fetch site index with URI query string
  155. *
  156. * @access public
  157. * @return string
  158. */
  159. function fetch_current_uri()
  160. {
  161. return rtrim($this->remove_double_slashes($this->fetch_site_index(1).$this->EE->uri->uri_string), '/');
  162. }
  163. // --------------------------------------------------------------------
  164. /**
  165. * Prep Query String
  166. *
  167. * This function checks to see if "Force Query Strings" is on.
  168. * If so it adds a question mark to the URL if needed
  169. *
  170. * @access public
  171. * @param string
  172. * @return string
  173. */
  174. function prep_query_string($str)
  175. {
  176. if (stristr($str, '.php') && substr($str, -7) == '/index/')
  177. {
  178. $str = substr($str, 0, -6);
  179. }
  180. if (strpos($str, '?') === FALSE && $this->EE->config->item('force_query_string') == 'y')
  181. {
  182. if (stristr($str, '.php'))
  183. {
  184. $str = preg_replace("#(.+?)\.php(.*?)#", "\\1.php?\\2", $str);
  185. }
  186. else
  187. {
  188. $str .= "?";
  189. }
  190. }
  191. return $str;
  192. }
  193. // --------------------------------------------------------------------
  194. /**
  195. * Convert EE Tags to Entities
  196. *
  197. * @access public
  198. * @param string
  199. * @param bool
  200. * @return string
  201. */
  202. function encode_ee_tags($str, $convert_curly = FALSE)
  203. {
  204. if ($str != '' && strpos($str, '{') !== FALSE)
  205. {
  206. if ($convert_curly === TRUE)
  207. {
  208. $str = str_replace(array('{', '}'), array('&#123;', '&#125;'), $str);
  209. }
  210. else
  211. {
  212. $str = preg_replace("/\{(\/){0,1}exp:(.+?)\}/", "&#123;\\1exp:\\2&#125;", $str);
  213. $str = str_replace(array('{exp:', '{/exp'), array('&#123;exp:', '&#123;\exp'), $str);
  214. $str = preg_replace("/\{embed=(.+?)\}/", "&#123;embed=\\1&#125;", $str);
  215. $str = preg_replace("/\{path:(.+?)\}/", "&#123;path:\\1&#125;", $str);
  216. $str = preg_replace("/\{redirect=(.+?)\}/", "&#123;redirect=\\1&#125;", $str);
  217. }
  218. }
  219. return $str;
  220. }
  221. // --------------------------------------------------------------------
  222. /**
  223. * Remove duplicate slashes from URL
  224. *
  225. * With all the URL/URI parsing/building, there is the potential
  226. * to end up with double slashes. This is a clean-up function.
  227. *
  228. * Will likely be deprecated in 2.6, use string helper instead
  229. *
  230. * @access public
  231. * @param string
  232. * @return string
  233. */
  234. function remove_double_slashes($str)
  235. {
  236. $this->EE->load->helper('string_helper');
  237. return reduce_double_slashes($str);
  238. }
  239. // --------------------------------------------------------------------
  240. /**
  241. * Extract path info
  242. *
  243. * We use this to extract the template group/template name
  244. * from path variables, like {some_var path="channel/index"}
  245. *
  246. * @access public
  247. * @param string
  248. * @return string
  249. */
  250. function extract_path($str)
  251. {
  252. if (preg_match("#=(.*)#", $str, $match))
  253. {
  254. $match[1] = trim($match[1], '}');
  255. if (isset($this->cached_path[$match[1]]))
  256. {
  257. return $this->cached_path[$match[1]];
  258. }
  259. // Load the string helper
  260. $this->EE->load->helper('string');
  261. $path = trim_slashes(str_replace(array("'",'"'), "", $match[1]));
  262. if (substr($path, -6) == 'index/')
  263. {
  264. $path = str_replace('/index', '', $path);
  265. }
  266. if (substr($path, -5) == 'index')
  267. {
  268. $path = str_replace('/index', '', $path);
  269. }
  270. $this->cached_path[$match[1]] = $path;
  271. return $path;
  272. }
  273. else
  274. {
  275. return 'SITE_INDEX';
  276. }
  277. }
  278. // --------------------------------------------------------------------
  279. /**
  280. * Replace variables
  281. *
  282. * @access public
  283. * @param string
  284. * @param string
  285. * @return string
  286. */
  287. function var_swap($str, $data)
  288. {
  289. if ( ! is_array($data))
  290. {
  291. return FALSE;
  292. }
  293. foreach ($data as $key => $val)
  294. {
  295. $str = str_replace('{'.$key.'}', $val, $str);
  296. }
  297. return $str;
  298. }
  299. // --------------------------------------------------------------------
  300. /**
  301. * Redirect
  302. *
  303. * @access public
  304. * @param string
  305. * @return void
  306. */
  307. function redirect($location, $method = FALSE)
  308. {
  309. // Remove hard line breaks and carriage returns
  310. $location = str_replace(array("\n", "\r"), '', $location);
  311. // Remove any and all line breaks
  312. while (stripos($location, '%0d') !== FALSE OR stripos($location, '%0a') !== FALSE)
  313. {
  314. $location = str_ireplace(array('%0d', '%0a'), '', $location);
  315. }
  316. $location = str_replace('&amp;', '&', $this->insert_action_ids($location));
  317. if (count($this->EE->session->flashdata))
  318. {
  319. // Ajax requests don't redirect - serve the flashdata
  320. if ($this->EE->input->is_ajax_request())
  321. {
  322. // We want the data that would be available for the next request
  323. $this->EE->session->_age_flashdata();
  324. $this->EE->load->library('javascript');
  325. die($this->EE->javascript->generate_json(
  326. $this->EE->session->flashdata));
  327. }
  328. }
  329. if ($method === FALSE)
  330. {
  331. $method = $this->EE->config->item('redirect_method');
  332. }
  333. switch($method)
  334. {
  335. case 'refresh' : header("Refresh: 0;url=$location");
  336. break;
  337. default : header("Location: $location");
  338. break;
  339. }
  340. exit;
  341. }
  342. // --------------------------------------------------------------------
  343. /**
  344. * Convert a string into an encrypted hash
  345. * DEPRECATED 2.0
  346. *
  347. * @access public
  348. * @param string
  349. * @return string
  350. */
  351. function hash($str)
  352. {
  353. $this->EE->load->library('logger');
  354. $this->EE->logger->deprecated('2.0', 'Security_helper::do_hash');
  355. $this->EE->load->helper('security');
  356. return do_hash($str);
  357. }
  358. // --------------------------------------------------------------------
  359. /**
  360. * Random number/password generator
  361. *
  362. * @access public
  363. * @param string
  364. * @param int
  365. * @return string
  366. */
  367. function random($type = 'encrypt', $len = 8)
  368. {
  369. $this->EE->load->helper('string');
  370. return random_string($type, $len);
  371. }
  372. // --------------------------------------------------------------------
  373. /**
  374. * Form declaration
  375. *
  376. * This function is used by modules when they need to create forms
  377. *
  378. * @access public
  379. * @param string
  380. * @return string
  381. */
  382. function form_declaration($data)
  383. {
  384. // Load the form helper
  385. $this->EE->load->helper('form');
  386. $deft = array(
  387. 'hidden_fields' => array(),
  388. 'action' => '',
  389. 'id' => '',
  390. 'class' => '',
  391. 'secure' => TRUE,
  392. 'enctype' => '',
  393. 'onsubmit' => '',
  394. );
  395. foreach ($deft as $key => $val)
  396. {
  397. if ( ! isset($data[$key]))
  398. {
  399. $data[$key] = $val;
  400. }
  401. }
  402. if (is_array($data['hidden_fields']) && ! isset($data['hidden_fields']['site_id']))
  403. {
  404. $data['hidden_fields']['site_id'] = $this->EE->config->item('site_id');
  405. }
  406. // Add the CSRF Protection Hash
  407. if ($this->EE->config->item('csrf_protection') == TRUE )
  408. {
  409. $data['hidden_fields'][$this->EE->security->get_csrf_token_name()] = $this->EE->security->get_csrf_hash();
  410. }
  411. // -------------------------------------------
  412. // 'form_declaration_modify_data' hook.
  413. // - Modify the $data parameters before they are processed
  414. // - Added EE 1.4.0
  415. //
  416. if ($this->EE->extensions->active_hook('form_declaration_modify_data') === TRUE)
  417. {
  418. $data = $this->EE->extensions->call('form_declaration_modify_data', $data);
  419. }
  420. //
  421. // -------------------------------------------
  422. // -------------------------------------------
  423. // 'form_declaration_return' hook.
  424. // - Take control of the form_declaration function
  425. // - Added EE 1.4.0
  426. //
  427. if ($this->EE->extensions->active_hook('form_declaration_return') === TRUE)
  428. {
  429. $form = $this->EE->extensions->call('form_declaration_return', $data);
  430. if ($this->EE->extensions->end_script === TRUE) return $form;
  431. }
  432. //
  433. // -------------------------------------------
  434. if ($data['action'] == '')
  435. {
  436. $data['action'] = $this->fetch_site_index();
  437. }
  438. if ($data['onsubmit'] != '')
  439. {
  440. $data['onsubmit'] = 'onsubmit="'.trim($data['onsubmit']).'"';
  441. }
  442. if (substr($data['action'], -1) == '?')
  443. {
  444. $data['action'] = substr($data['action'], 0, -1);
  445. }
  446. $data['name'] = (isset($data['name']) && $data['name'] != '') ? 'name="'.$data['name'].'" ' : '';
  447. $data['id'] = ($data['id'] != '') ? 'id="'.$data['id'].'" ' : '';
  448. $data['class'] = ($data['class'] != '') ? 'class="'.$data['class'].'" ' : '';
  449. if ($data['enctype'] == 'multi' OR strtolower($data['enctype']) == 'multipart/form-data')
  450. {
  451. $data['enctype'] = 'enctype="multipart/form-data" ';
  452. }
  453. $form = '<form '.$data['id'].$data['class'].$data['name'].'method="post" action="'.$data['action'].'" '.$data['onsubmit'].' '.$data['enctype'].">\n";
  454. if ($data['secure'] == TRUE)
  455. {
  456. if ($this->EE->config->item('secure_forms') == 'y')
  457. {
  458. if ( ! isset($data['hidden_fields']['XID']))
  459. {
  460. $data['hidden_fields'] = array_merge(array('XID' => '{XID_HASH}'), $data['hidden_fields']);
  461. }
  462. elseif ($data['hidden_fields']['XID'] == '')
  463. {
  464. $data['hidden_fields']['XID'] = '{XID_HASH}';
  465. }
  466. }
  467. }
  468. if (is_array($data['hidden_fields']))
  469. {
  470. $form .= "<div class='hiddenFields'>\n";
  471. foreach ($data['hidden_fields'] as $key => $val)
  472. {
  473. $form .= '<input type="hidden" name="'.$key.'" value="'.form_prep($val).'" />'."\n";
  474. }
  475. $form .= "</div>\n\n";
  476. }
  477. return $form;
  478. }
  479. // --------------------------------------------------------------------
  480. /**
  481. * Form backtrack
  482. *
  483. * This function lets us return a user to a previously
  484. * visited page after submitting a form. The page
  485. * is determined by the offset that the admin
  486. * places in each form
  487. *
  488. * @access public
  489. * @param string
  490. * @return string
  491. */
  492. function form_backtrack($offset = '')
  493. {
  494. $ret = $this->fetch_site_index();
  495. if ($offset != '')
  496. {
  497. if (isset($this->EE->session->tracker[$offset]))
  498. {
  499. if ($this->EE->session->tracker[$offset] != 'index')
  500. {
  501. return $this->remove_double_slashes($this->fetch_site_index().'/'.$this->EE->session->tracker[$offset]);
  502. }
  503. }
  504. }
  505. if (isset($_POST['RET']))
  506. {
  507. if (strncmp($_POST['RET'], '-', 1) == 0)
  508. {
  509. $return = str_replace("-", "", $_POST['RET']);
  510. if (isset($this->EE->session->tracker[$return]))
  511. {
  512. if ($this->EE->session->tracker[$return] != 'index')
  513. {
  514. $ret = $this->fetch_site_index().'/'.$this->EE->session->tracker[$return];
  515. }
  516. }
  517. }
  518. else
  519. {
  520. if (strpos($_POST['RET'], '/') !== FALSE)
  521. {
  522. if (strncasecmp($_POST['RET'], 'http://', 7) == 0 OR
  523. strncasecmp($_POST['RET'], 'https://', 8) == 0 OR
  524. strncasecmp($_POST['RET'], 'www.', 4) == 0)
  525. {
  526. $ret = $_POST['RET'];
  527. }
  528. else
  529. {
  530. $ret = $this->create_url($_POST['RET']);
  531. }
  532. }
  533. else
  534. {
  535. $ret = $_POST['RET'];
  536. }
  537. }
  538. // We need to slug in the session ID if the admin is running
  539. // their site using sessions only. Normally the $this->EE->functions->fetch_site_index()
  540. // function adds the session ID automatically, except in cases when the
  541. // $_POST['RET'] variable is set. Since the login routine relies on the RET
  542. // info to know where to redirect back to we need to sandwich in the session ID.
  543. if ($this->EE->config->item('user_session_type') != 'c')
  544. {
  545. if ($this->EE->session->userdata['session_id'] != '' && ! stristr($ret, $this->EE->session->userdata['session_id']))
  546. {
  547. $url = $this->EE->config->slash_item('site_url');
  548. $url .= $this->EE->config->item('site_index');
  549. if ($this->EE->config->item('force_query_string') == 'y')
  550. {
  551. $url .= '?';
  552. }
  553. $sess_id = "/S=".$this->EE->session->userdata['session_id']."/";
  554. $ret = str_replace($url, $url.$sess_id, $ret);
  555. }
  556. }
  557. }
  558. return $this->remove_double_slashes($ret);
  559. }
  560. // --------------------------------------------------------------------
  561. /**
  562. * eval()
  563. *
  564. * Evaluates a string as PHP
  565. *
  566. * @access public
  567. * @param string
  568. * @return mixed
  569. */
  570. function evaluate($str)
  571. {
  572. return eval('?'.'>'.$str.'<?php ');
  573. }
  574. // --------------------------------------------------------------------
  575. /**
  576. * Encode email from template callback
  577. *
  578. * @access public
  579. * @param string
  580. * @return string
  581. */
  582. function encode_email($str)
  583. {
  584. if (isset($this->EE->session->cache['functions']['emails'][$str]))
  585. {
  586. return preg_replace("/(eeEncEmail_)\w+/", '\\1'.$this->EE->functions->random('alpha', 10), $this->EE->session->cache['functions']['emails'][$str]);
  587. }
  588. $email = (is_array($str)) ? trim($str[1]) : trim($str);
  589. $title = '';
  590. $email = str_replace(array('"', "'"), '', $email);
  591. if ($p = strpos($email, "title="))
  592. {
  593. $title = substr($email, $p + 6);
  594. $email = trim(substr($email, 0, $p));
  595. }
  596. $this->EE->load->library('typography');
  597. $this->EE->typography->initialize();
  598. $encoded = $this->EE->typography->encode_email($email, $title, TRUE);
  599. $this->EE->session->cache['functions']['emails'][$str] = $encoded;
  600. return $encoded;
  601. }
  602. // --------------------------------------------------------------------
  603. /**
  604. * Delete spam prevention hashes
  605. *
  606. * @access public
  607. * @return void
  608. */
  609. function clear_spam_hashes()
  610. {
  611. if ($this->EE->config->item('secure_forms') == 'y')
  612. {
  613. $this->EE->security->garbage_collect_xids();
  614. }
  615. }
  616. // --------------------------------------------------------------------
  617. /**
  618. * Set Cookie
  619. *
  620. * @access public
  621. * @param string
  622. * @param string
  623. * @param string
  624. * @return void
  625. */
  626. function set_cookie($name = '', $value = '', $expire = '')
  627. {
  628. $data['name'] = $name;
  629. if ( ! is_numeric($expire))
  630. {
  631. $data['expire'] = time() - 86500;
  632. }
  633. else
  634. {
  635. if ($expire > 0)
  636. {
  637. $data['expire'] = time() + $expire;
  638. }
  639. else
  640. {
  641. $data['expire'] = 0;
  642. }
  643. }
  644. $data['prefix'] = ( ! $this->EE->config->item('cookie_prefix')) ? 'exp_' : $this->EE->config->item('cookie_prefix').'_';
  645. $data['path'] = ( ! $this->EE->config->item('cookie_path')) ? '/' : $this->EE->config->item('cookie_path');
  646. if (REQ == 'CP' && $this->EE->config->item('multiple_sites_enabled') == 'y')
  647. {
  648. $data['domain'] = $this->EE->config->cp_cookie_domain;
  649. }
  650. else
  651. {
  652. $data['domain'] = ( ! $this->EE->config->item('cookie_domain')) ? '' : $this->EE->config->item('cookie_domain');
  653. }
  654. $data['value'] = stripslashes($value);
  655. $data['secure_cookie'] = ($this->EE->config->item('cookie_secure') === TRUE) ? 1 : 0;
  656. if ($data['secure_cookie'])
  657. {
  658. $req = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : FALSE;
  659. if ( ! $req OR $req == 'off')
  660. {
  661. return FALSE;
  662. }
  663. }
  664. /* -------------------------------------------
  665. /* 'set_cookie_end' hook.
  666. /* - Take control of Cookie setting routine
  667. /* - Added EE 2.5.0
  668. */
  669. $this->EE->extensions->call('set_cookie_end', $data);
  670. if ($this->EE->extensions->end_script === TRUE) return;
  671. /*
  672. /* -------------------------------------------*/
  673. setcookie($data['prefix'].$data['name'], $data['value'], $data['expire'],
  674. $data['path'], $data['domain'], $data['secure_cookie']);
  675. }
  676. // --------------------------------------------------------------------
  677. /**
  678. * Character limiter
  679. *
  680. * @access public
  681. * @param string
  682. * @return string
  683. */
  684. function char_limiter($str, $num = 500)
  685. {
  686. if (strlen($str) < $num)
  687. {
  688. return $str;
  689. }
  690. $str = str_replace("\n", " ", $str);
  691. $str = preg_replace("/\s+/", " ", $str);
  692. if (strlen($str) <= $num)
  693. {
  694. return $str;
  695. }
  696. $str = trim($str);
  697. $out = "";
  698. foreach (explode(" ", trim($str)) as $val)
  699. {
  700. $out .= $val;
  701. if (strlen($out) >= $num)
  702. {
  703. return (strlen($out) == strlen($str)) ? $out : $out.'&#8230;';
  704. }
  705. $out .= ' ';
  706. }
  707. }
  708. // --------------------------------------------------------------------
  709. /**
  710. * Word limiter
  711. *
  712. * @access public
  713. * @param string
  714. * @return string
  715. */
  716. function word_limiter($str, $num = 100)
  717. {
  718. if (strlen($str) < $num)
  719. {
  720. return $str;
  721. }
  722. // allows the split to work properly with multi-byte Unicode characters
  723. if (is_php('4.3.2') === TRUE)
  724. {
  725. $word = preg_split('/\s/u', $str, -1, PREG_SPLIT_NO_EMPTY);
  726. }
  727. else
  728. {
  729. $word = preg_split('/\s/', $str, -1, PREG_SPLIT_NO_EMPTY);
  730. }
  731. if (count($word) <= $num)
  732. {
  733. return $str;
  734. }
  735. $str = "";
  736. for ($i = 0; $i < $num; $i++)
  737. {
  738. $str .= $word[$i]." ";
  739. }
  740. return trim($str).'&#8230;';
  741. }
  742. // --------------------------------------------------------------------
  743. /**
  744. * Fetch Email Template
  745. *
  746. * @access public
  747. * @param string
  748. * @return string
  749. */
  750. function fetch_email_template($name)
  751. {
  752. $query = $this->EE->db->query("SELECT template_name, data_title, template_data, enable_template FROM exp_specialty_templates WHERE site_id = '".$this->EE->db->escape_str($this->EE->config->item('site_id'))."' AND template_name = '".$this->EE->db->escape_str($name)."'");
  753. // Unlikely that this is necessary but it's possible a bad template request could
  754. // happen if a user hasn't run the update script.
  755. if ($query->num_rows() == 0)
  756. {
  757. return array('title' => '', 'data' => '');
  758. }
  759. if ($query->row('enable_template') == 'y')
  760. {
  761. return array('title' => $query->row('data_title') , 'data' => $query->row('template_data') );
  762. }
  763. if ($this->EE->session->userdata['language'] != '')
  764. {
  765. $user_lang = $this->EE->session->userdata['language'];
  766. }
  767. else
  768. {
  769. if ($this->EE->input->cookie('language'))
  770. {
  771. $user_lang = $this->EE->input->cookie('language');
  772. }
  773. elseif ($this->EE->config->item('deft_lang') != '')
  774. {
  775. $user_lang = $this->EE->config->item('deft_lang');
  776. }
  777. else
  778. {
  779. $user_lang = 'english';
  780. }
  781. }
  782. $user_lang = $this->EE->security->sanitize_filename($user_lang);
  783. if ( function_exists($name))
  784. {
  785. $title = $name.'_title';
  786. return array('title' => $title(), 'data' => $name());
  787. }
  788. else
  789. {
  790. if ( ! @include(APPPATH.'language/'.$user_lang.'/email_data.php'))
  791. {
  792. return array('title' => $query->row('data_title') , 'data' => $query->row('template_data') );
  793. }
  794. if (function_exists($name))
  795. {
  796. $title = $name.'_title';
  797. return array('title' => $title(), 'data' => $name());
  798. }
  799. else
  800. {
  801. return array('title' => $query->row('data_title') , 'data' => $query->row('template_data') );
  802. }
  803. }
  804. }
  805. // --------------------------------------------------------------------
  806. /**
  807. * Create character encoding menu
  808. *
  809. * DEPRECATED IN 2.0
  810. *
  811. * @access public
  812. * @param string
  813. * @param string
  814. * @param string
  815. * @return string
  816. */
  817. function encoding_menu($name, $selected = '')
  818. {
  819. $this->EE->load->library('logger');
  820. $this->EE->logger->deprecated('2.0');
  821. $file = APPPATH.'config/languages.php';
  822. if ( ! file_exists($file))
  823. {
  824. return FALSE;
  825. }
  826. require_once $file;
  827. $languages = array_flip($languages);
  828. $this->EE->load->helper('form');
  829. return form_dropdown($name, $languages, $selected);
  830. }
  831. // --------------------------------------------------------------------
  832. /**
  833. * Create Directory Map
  834. *
  835. * DEPRECATED IN 2.2
  836. *
  837. * @access public
  838. * @param string
  839. * @param bool
  840. * @return array
  841. */
  842. function create_directory_map($source_dir, $top_level_only = FALSE)
  843. {
  844. $this->EE->load->library('logger');
  845. $this->EE->logger->deprecated('2.2');
  846. if ( ! isset($filedata))
  847. $filedata = array();
  848. if ($fp = @opendir($source_dir))
  849. {
  850. while (FALSE !== ($file = readdir($fp)))
  851. {
  852. if (@is_dir($source_dir.$file) && substr($file, 0, 1) != '.' AND $top_level_only == FALSE)
  853. {
  854. $temp_array = array();
  855. $temp_array = $this->create_directory_map($source_dir.$file."/");
  856. $filedata[$file] = $temp_array;
  857. }
  858. elseif (substr($file, 0, 1) != "." && $file != 'index.html')
  859. {
  860. $filedata[] = $file;
  861. }
  862. }
  863. return $filedata;
  864. }
  865. }
  866. // --------------------------------------------------------------------
  867. /**
  868. * Create pull-down optios from dirctory map
  869. *
  870. * @access public
  871. * @param array
  872. * @param string
  873. * @return string
  874. */
  875. function render_map_as_select_options($zarray, $array_name = '')
  876. {
  877. foreach ($zarray as $key => $val)
  878. {
  879. if ( is_array($val))
  880. {
  881. if ($array_name != '')
  882. {
  883. $key = $array_name.'/'.$key;
  884. }
  885. $this->render_map_as_select_options($val, $key);
  886. }
  887. else
  888. {
  889. if ($array_name != '')
  890. {
  891. $val = $array_name.'/'.$val;
  892. }
  893. if (substr($val, -4) == '.php')
  894. {
  895. if ($val != 'theme_master.php')
  896. {
  897. $this->template_map[] = $val;
  898. }
  899. }
  900. }
  901. }
  902. }
  903. // --------------------------------------------------------------------
  904. /**
  905. * Fetch names of installed language packs
  906. *
  907. * DEPRECATED IN 2.0
  908. *
  909. * @access public
  910. * @param string
  911. * @return string
  912. */
  913. function language_pack_names($default)
  914. {
  915. $source_dir = APPPATH.'language/';
  916. $dirs = array();
  917. if ($fp = @opendir($source_dir))
  918. {
  919. while (FALSE !== ($file = readdir($fp)))
  920. {
  921. if (is_dir($source_dir.$file) && substr($file, 0, 1) != ".")
  922. {
  923. $dirs[] = $file;
  924. }
  925. }
  926. closedir($fp);
  927. }
  928. sort($dirs);
  929. $r = "<div class='default'>";
  930. $r .= "<select name='deft_lang' class='select'>\n";
  931. foreach ($dirs as $dir)
  932. {
  933. $selected = ($dir == $default) ? " selected='selected'" : '';
  934. $r .= "<option value='{$dir}'{$selected}>".ucfirst($dir)."</option>\n";
  935. }
  936. $r .= "</select>";
  937. $r .= "</div>";
  938. return $r;
  939. }
  940. // --------------------------------------------------------------------
  941. /**
  942. * Delete cache files
  943. *
  944. * @access public
  945. * @param string
  946. * @return string
  947. */
  948. function clear_caching($which, $sub_dir = '', $relationships=FALSE)
  949. {
  950. $actions = array('page', 'tag', 'db', 'sql', 'relationships', 'all');
  951. if ( ! in_array($which, $actions))
  952. {
  953. return;
  954. }
  955. /* -------------------------------------
  956. /* Disable Tag Caching
  957. /*
  958. /* All for you, Nevin! Disables tag caching, which if used unwisely
  959. /* on a high traffic site can lead to disastrous disk i/o
  960. /* This setting allows quick thinking admins to temporarily disable
  961. /* it without hacking or modifying folder permissions
  962. /*
  963. /* Hidden Configuration Variable
  964. /* - disable_tag_caching => Disable tag caching? (y/n)
  965. /* -------------------------------------*/
  966. if ($which == 'tag' && $this->EE->config->item('disable_tag_caching') == 'y')
  967. {
  968. return;
  969. }
  970. $db_path = '';
  971. if ($sub_dir != '')
  972. {
  973. if ($which == 'all' OR $which == 'db')
  974. {
  975. $segs = explode('/', str_replace($this->fetch_site_index(), '', $sub_dir));
  976. $segment_one = (isset($segs['0'])) ? $segs['0'] : 'default';
  977. $segment_two = (isset($segs['1'])) ? $segs['1'] : 'index';
  978. $db_path = '/'.$segment_one.'+'.$segment_two.'/';
  979. }
  980. $sub_dir = '/'.md5($sub_dir).'/';
  981. }
  982. switch ($which)
  983. {
  984. case 'page' : $this->delete_directory(APPPATH.'cache/page_cache'.$sub_dir);
  985. break;
  986. case 'db' : $this->delete_directory(APPPATH.'cache/db_cache_'.$this->EE->config->item('site_id').$db_path);
  987. break;
  988. case 'tag' : $this->delete_directory(APPPATH.'cache/tag_cache'.$sub_dir);
  989. break;
  990. case 'sql' : $this->delete_directory(APPPATH.'cache/sql_cache'.$sub_dir);
  991. break;
  992. case 'relationships' : $this->EE->db->query("UPDATE exp_relationships SET rel_data = '', reverse_rel_data = ''");
  993. break;
  994. case 'all' :
  995. $this->delete_directory(APPPATH.'cache/page_cache'.$sub_dir);
  996. $this->delete_directory(APPPATH.'cache/db_cache_'.$this->EE->config->item('site_id').$db_path);
  997. $this->delete_directory(APPPATH.'cache/sql_cache'.$sub_dir);
  998. if ($this->EE->config->item('disable_tag_caching') != 'y')
  999. {
  1000. $this->delete_directory(APPPATH.'cache/tag_cache'.$sub_dir);
  1001. }
  1002. if ($relationships === TRUE)
  1003. {
  1004. $this->EE->db->query("UPDATE exp_relationships SET rel_data = '', reverse_rel_data = ''");
  1005. }
  1006. break;
  1007. }
  1008. }
  1009. // --------------------------------------------------------------------
  1010. /**
  1011. * Delete Direcories
  1012. *
  1013. * @access public
  1014. * @param string
  1015. * @param bool
  1016. * @return void
  1017. */
  1018. function delete_directory($path, $del_root = FALSE)
  1019. {
  1020. $path = rtrim($path, '/');
  1021. $path_delete = $path.'_delete';
  1022. if ( ! is_dir($path))
  1023. {
  1024. return FALSE;
  1025. }
  1026. // Delete temporary directory if it happens to exist from a previous attempt
  1027. if (is_dir($path_delete))
  1028. {
  1029. @exec("rm -r -f {$path_delete}");
  1030. }
  1031. // let's try this the sane way first
  1032. @exec("mv {$path} {$path_delete}", $out, $ret);
  1033. if (isset($ret) && $ret == 0)
  1034. {
  1035. if ($del_root === FALSE)
  1036. {
  1037. @mkdir($path, 0777);
  1038. if ($fp = @fopen($path.'/index.html', FOPEN_WRITE_CREATE_DESTRUCTIVE))
  1039. {
  1040. fclose($fp);
  1041. }
  1042. }
  1043. @exec("rm -r -f {$path_delete}");
  1044. }
  1045. else
  1046. {
  1047. if ( ! $current_dir = @opendir($path))
  1048. {
  1049. return;
  1050. }
  1051. while($filename = @readdir($current_dir))
  1052. {
  1053. if (@is_dir($path.'/'.$filename) and ($filename != "." and $filename != ".."))
  1054. {
  1055. $this->delete_directory($path.'/'.$filename, TRUE);
  1056. }
  1057. elseif($filename != "." and $filename != "..")
  1058. {
  1059. @unlink($path.'/'.$filename);
  1060. }
  1061. }
  1062. @closedir($current_dir);
  1063. if (substr($path, -6) == '_cache' && $fp = @fopen($path.'/index.html', FOPEN_WRITE_CREATE_DESTRUCTIVE))
  1064. {
  1065. fclose($fp);
  1066. }
  1067. if ($del_root == TRUE)
  1068. {
  1069. @rmdir($path);
  1070. }
  1071. }
  1072. }
  1073. // --------------------------------------------------------------------
  1074. /**
  1075. * Fetch allowed channels
  1076. *
  1077. * This function fetches the ID numbers of the
  1078. * channels assigned to the currently logged in user.
  1079. *
  1080. * @access public
  1081. * @param bool
  1082. * @return array
  1083. */
  1084. function fetch_assigned_channels($all_sites = FALSE)
  1085. {
  1086. $allowed_channels = array();
  1087. if (REQ == 'CP' AND isset($this->EE->session->userdata['assigned_channels']) && $all_sites === FALSE)
  1088. {
  1089. $allowed_channels = array_keys($this->EE->session->userdata['assigned_channels']);
  1090. }
  1091. elseif ($this->EE->session->userdata['group_id'] == 1)
  1092. {
  1093. if ($all_sites === TRUE)
  1094. {
  1095. $this->EE->db->select('channel_id');
  1096. $query = $this->EE->db->get('channels');
  1097. }
  1098. else
  1099. {
  1100. $this->EE->db->select('channel_id');
  1101. $this->EE->db->where('site_id', $this->EE->config->item('site_id'));
  1102. $query = $this->EE->db->get('channels');
  1103. }
  1104. if ($query->num_rows() > 0)
  1105. {
  1106. foreach ($query->result_array() as $row)
  1107. {
  1108. $allowed_channels[] = $row['channel_id'];
  1109. }
  1110. }
  1111. }
  1112. else
  1113. {
  1114. if ($all_sites === TRUE)
  1115. {
  1116. $result = $this->EE->db->query("SELECT exp_channel_member_groups.channel_id FROM exp_channel_member_groups
  1117. WHERE exp_channel_member_groups.group_id = '".$this->EE->db->escape_str($this->EE->session->userdata['group_id'])."'");
  1118. }
  1119. else
  1120. {
  1121. $result = $this->EE->db->query("SELECT exp_channels.channel_id FROM exp_channels, exp_channel_member_groups
  1122. WHERE exp_channels.channel_id = exp_channel_member_groups.channel_id
  1123. AND exp_channels.site_id = '".$this->EE->db->escape_str($this->EE->config->item('site_id'))."'
  1124. AND exp_channel_member_groups.group_id = '".$this->EE->db->escape_str($this->EE->session->userdata['group_id'])."'");
  1125. }
  1126. if ($result->num_rows() > 0)
  1127. {
  1128. foreach ($result->result_array() as $row)
  1129. {
  1130. $allowed_channels[] = $row['channel_id'];
  1131. }
  1132. }
  1133. }
  1134. return array_values($allowed_channels);
  1135. }
  1136. // --------------------------------------------------------------------
  1137. /**
  1138. * Log Search terms
  1139. *
  1140. * @access public
  1141. * @param string
  1142. * @param string
  1143. * @return void
  1144. */
  1145. function log_search_terms($terms = '', $type = 'site')
  1146. {
  1147. if ($terms == '' OR $this->EE->db->table_exists('exp_search_log') === FALSE)
  1148. return;
  1149. if ($this->EE->config->item('enable_search_log') == 'n')
  1150. return;
  1151. $this->EE->load->helper('xml');
  1152. $search_log = array(
  1153. 'member_id' => $this->EE->session->userdata('member_id'),
  1154. 'screen_name' => $this->EE->session->userdata('screen_name'),
  1155. 'ip_address' => $this->EE->input->ip_address(),
  1156. 'search_date' => $this->EE->localize->now,
  1157. 'search_type' => $type,
  1158. 'search_terms' => xml_convert($this->EE->functions->encode_ee_tags($this->EE->security->xss_clean($terms), TRUE)),
  1159. 'site_id' => $this->EE->config->item('site_id')
  1160. );
  1161. $this->EE->db->query($this->EE->db->insert_string('exp_search_log', $search_log));
  1162. // Prune Database
  1163. srand(time());
  1164. if ((rand() % 100) < 5)
  1165. {
  1166. $max = ( ! is_numeric($this->EE->config->item('max_logged_searches'))) ? 500 : $this->EE->config->item('max_logged_searches');
  1167. $query = $this->EE->db->query("SELECT MAX(id) as search_id FROM exp_search_log WHERE site_id = '".$this->EE->db->escape_str($this->EE->config->item('site_id'))."'");
  1168. $row = $query->row_array();
  1169. if (isset($row['search_id'] ) && $row['search_id'] > $max)
  1170. {
  1171. $this->EE->db->query("DELETE FROM exp_search_log WHERE site_id = '".$this->EE->db->escape_str($this->EE->config->item('site_id'))."' AND id < ".($row['search_id'] -$max)."");
  1172. }
  1173. }
  1174. }
  1175. // --------------------------------------------------------------------
  1176. /**
  1177. * Fetch Action ID
  1178. *
  1179. * @access public
  1180. * @param string
  1181. * @param string
  1182. * @return string
  1183. */
  1184. function fetch_action_id($class, $method)
  1185. {
  1186. if ($class == '' OR $method == '')
  1187. {
  1188. return FALSE;
  1189. }
  1190. $this->action_ids[ucfirst($class)][$method] = $method;
  1191. return LD.'AID:'.ucfirst($class).':'.$method.RD;
  1192. }
  1193. // --------------------------------------------------------------------
  1194. /**
  1195. * Insert Action IDs
  1196. *
  1197. * @access public
  1198. * @param string
  1199. * @return string
  1200. */
  1201. function insert_action_ids($str)
  1202. {
  1203. if (count($this->action_ids) == 0)
  1204. {
  1205. return $str;
  1206. }
  1207. $sql = "SELECT action_id, class, method FROM exp_actions WHERE";
  1208. foreach($this->action_ids as $key => $value)
  1209. {
  1210. foreach($value as $k => $v)
  1211. {
  1212. $sql .= " (class= '".$this->EE->db->escape_str($key)."' AND method = '".$this->EE->db->escape_str($v)."') OR";
  1213. }
  1214. }
  1215. $query = $this->EE->db->query(substr($sql, 0, -3));
  1216. if ($query->num_rows() > 0)
  1217. {
  1218. foreach($query->result_array() as $row)
  1219. {
  1220. $str = str_replace(LD.'AID:'.$row['class'].':'.$row['method'].RD, $row['action_id'], $str);
  1221. }
  1222. }
  1223. return $str;
  1224. }
  1225. // --------------------------------------------------------------------
  1226. /**
  1227. * Compile and cache relationship data
  1228. *
  1229. * This is used when submitting new channel entries or gallery posts.
  1230. * It serializes the related entry data. The reason it's in this
  1231. * file is because it gets called from the publish class and the
  1232. * gallery class so we need it somewhere that is accessible to both.
  1233. *
  1234. * @access public
  1235. * @param string
  1236. * @param bool
  1237. * @param bool
  1238. * @return void
  1239. */
  1240. function compile_relationship($data, $parent_entry = TRUE, $reverse = FALSE)
  1241. {
  1242. if ($data['type'] == 'channel' OR ($reverse === TRUE && $parent_entry === FALSE))
  1243. {
  1244. $sql = "SELECT t.entry_id, t.channel_id, t.forum_topic_id, t.author_id, t.ip_address, t.title, t.url_title, t.status, t.dst_enabled, t.view_count_one, t.view_count_two, t.view_count_three, t.view_count_four, t.allow_comments, t.comment_expiration_date, t.sticky, t.entry_date, t.year, t.month, t.day, t.entry_date, t.edit_date, t.expiration_date, t.recent_comment_date, t.comment_total, t.site_id as entry_site_id,
  1245. w.channel_title, w.channel_name, w.channel_url, w.comment_url, w.comment_moderate, w.channel_html_formatting, w.channel_allow_img_urls, w.channel_auto_link_urls,
  1246. m.username, m.email, m.url, m.screen_name, m.location, m.occupation, m.interests, m.aol_im, m.yahoo_im, m.msn_im, m.icq, m.signature, m.sig_img_filename, m.sig_img_width, m.sig_img_height, m.avatar_filename, m.avatar_width, m.avatar_height, m.photo_filename, m.photo_width, m.photo_height, m.group_id, m.member_id, m.bday_d, m.bday_m, m.bday_y, m.bio,
  1247. md.*,
  1248. wd.*
  1249. FROM exp_channel_titles AS t
  1250. LEFT JOIN exp_channels AS w ON t.channel_id = w.channel_id
  1251. LEFT JOIN exp_channel_data AS wd ON t.entry_id = wd.entry_id
  1252. LEFT JOIN exp_members AS m ON m.member_id = t.author_id
  1253. LEFT JOIN exp_member_data AS md ON md.member_id = m.member_id
  1254. WHERE t.entry_id = '".(($reverse === TRUE && $parent_entry === FALSE) ? $data['parent_id'] : $data['child_id'])."'";
  1255. $entry_query = $this->EE->db->query($sql);
  1256. // Is there a category group associated with this channel?
  1257. $query = $this->EE->db->query("SELECT cat_group FROM exp_channels WHERE channel_id = '".$entry_query->row('channel_id') ."'");
  1258. $cat_group = (trim($query->row('cat_group')) == '') ? FALSE : $query->row('cat_group');
  1259. $this->cat_array = array();
  1260. $cat_array = array();
  1261. if ($cat_group !== FALSE)
  1262. {
  1263. $this->get_categories($cat_group, ($reverse === TRUE && $parent_entry === FALSE) ? $data['parent_id'] : $data['child_id']);
  1264. }
  1265. $cat_array = $this->cat_array;
  1266. if ($parent_entry == TRUE)
  1267. {
  1268. $this->EE->db->query("INSERT INTO exp_relationships (rel_parent_id, rel_child_id, rel_type, rel_data, reverse_rel_data)
  1269. VALUES ('".$data['parent_id']."', '".$data['child_id']."', '".$data['type']."',
  1270. '".addslashes(serialize(array('query' => $entry_query, 'cats_fixed' => '1', 'categories' => $cat_array)))."', '')");
  1271. return $this->EE->db->insert_id();
  1272. }
  1273. else
  1274. {
  1275. if ($reverse === TRUE)
  1276. {
  1277. $this->EE->db->query("UPDATE exp_relationships
  1278. SET reverse_rel_data = '".addslashes(serialize(array('query' => $entry_query, 'cats_fixed' => '1', 'categories' => $cat_array)))."'
  1279. WHERE rel_type = '".$this->EE->db->escape_str($data['type'])."' AND rel_parent_id = '".$data['parent_id']."'");
  1280. }
  1281. else
  1282. {
  1283. $this->EE->db->query("UPDATE exp_relationships
  1284. SET rel_data = '".addslashes(serialize(array('query' => $entry_query, 'cats_fixed' => '1', 'categories' => $cat_array)))."'
  1285. WHERE rel_type = 'channel' AND rel_child_id = '".$data['child_id']."'");
  1286. }
  1287. }
  1288. }
  1289. }
  1290. // --------------------------------------------------------------------
  1291. /**
  1292. * Get Categories for Channel Entry/Entries
  1293. *
  1294. * @access public
  1295. * @param string
  1296. * @param string
  1297. * @return array
  1298. */
  1299. function get_categories($cat_group, $entry_id)
  1300. {
  1301. // fetch the custom category fields
  1302. $field_sqla = '';
  1303. $field_sqlb = '';
  1304. $query = $this->EE->db->query("SELECT field_id, field_name FROM exp_category_fields WHERE group_id IN ('".str_replace('|', "','", $this->EE->db->escape_str($cat_group))."')");
  1305. if ($query->num_rows() > 0)
  1306. {
  1307. foreach ($query->result_array() as $row)
  1308. {
  1309. $this->catfields[] = array('field_name' => $row['field_name'], 'field_id' => $row['field_id']);
  1310. }
  1311. $field_sqla = ", cg.field_html_formatting, fd.* ";
  1312. $field_sqlb = " LEFT JOIN exp_category_field_data AS fd ON fd.cat_id = c.cat_id
  1313. LEFT JOIN exp_category_groups AS cg ON cg.group_id = c.group_id";
  1314. }
  1315. $sql = "SELECT c.cat_name, c.cat_url_title, c.cat_id, c.cat_image, p.cat_id, c.parent_id, c.cat_description, c.group_id
  1316. {$field_sqla}
  1317. FROM (exp_categories AS c, exp_category_posts AS p)
  1318. {$field_sqlb}
  1319. WHERE c.group_id IN ('".str_replace('|', "','", $this->EE->db->escape_str($cat_group))."')
  1320. AND p.entry_id = '".$entry_id."'
  1321. AND c.cat_id = p.cat_id
  1322. ORDER BY c.parent_id, c.cat_order";
  1323. $sql = str_replace("\t", " ", $sql);
  1324. $query = $this->EE->db->query($sql);
  1325. $this->cat_array = array();
  1326. $parents = array();
  1327. if ($query->num_rows() > 0)
  1328. {
  1329. $this->temp_array = array();
  1330. foreach ($query->result_array() as $row)
  1331. {
  1332. $this->temp_array[$row['cat_id']] = array($row['cat_id'], $row['parent_id'], $row['cat_name'], $row['cat_image'], $row['cat_description'], $row['group_id'], $row['cat_url_title']);
  1333. if ($field_sqla != '')
  1334. {
  1335. foreach ($row as $k => $v)
  1336. {
  1337. if (strpos($k, 'field') !== FALSE)
  1338. {
  1339. $this->temp_array[$row['cat_id']][$k] = $v;
  1340. }
  1341. }
  1342. }
  1343. if ($row['parent_id'] > 0 && ! isset($this->temp_array[$row['parent_id']])) $parents[$row['parent_id']] = '';
  1344. unset($parents[$row['cat_id']]);
  1345. }
  1346. foreach($this->temp_array as $k => $v)
  1347. {
  1348. if (isset($parents[$v[1]])) $v[1] = 0;
  1349. if (0 == $v[1])
  1350. {
  1351. $this->cat_array[] = $v;
  1352. $this->process_subcategories($k);
  1353. }
  1354. }
  1355. unset($this->temp_array);
  1356. }
  1357. }
  1358. // --------------------------------------------------------------------
  1359. /**
  1360. * Process Subcategories
  1361. *
  1362. * @access public
  1363. * @param string
  1364. * @return void
  1365. */
  1366. function process_subcategories($parent_id)
  1367. {
  1368. foreach($this->temp_array as $key => $val)
  1369. {
  1370. if ($parent_id == $val[1])
  1371. {
  1372. $this->cat_array[] = $val;
  1373. $this->process_subcategories($key);
  1374. }
  1375. }
  1376. }
  1377. // --------------------------------------------------------------------
  1378. /**
  1379. * Add security hashes to forms
  1380. *
  1381. * @access public
  1382. * @param string
  1383. * @return string
  1384. */
  1385. function add_form_security_hash($str)
  1386. {
  1387. if ($this->EE->config->item('secure_forms') == 'y')
  1388. {
  1389. if (preg_match_all("/({XID_HASH})/", $str, $matches))
  1390. {
  1391. $db_reset = FALSE;
  1392. // Disable DB caching if it's currently set
  1393. if ($this->EE->db->cache_on == TRUE)
  1394. {
  1395. $this->EE->db->cache_off();
  1396. $db_reset = TRUE;
  1397. }
  1398. // Add security hashes
  1399. $hashes = $this->EE->security->generate_xid(count($matches[1]), TRUE);
  1400. foreach ($hashes as $hash)
  1401. {
  1402. $str = preg_replace("/{XID_HASH}/", $hash, $str, 1);
  1403. }
  1404. // Re-enable DB caching
  1405. if ($db_reset == TRUE)
  1406. {
  1407. $this->EE->db->cache_on();
  1408. }
  1409. }
  1410. }
  1411. return $str;
  1412. }
  1413. // --------------------------------------------------------------------
  1414. /**
  1415. * Generate CAPTCHA
  1416. *
  1417. * @access public
  1418. * @param string
  1419. * @return string
  1420. */
  1421. function create_captcha($old_word = '')
  1422. {
  1423. if ($this->EE->config->item('captcha_require_members') == 'n' AND $this->EE->session->userdata['member_id'] != 0)
  1424. {
  1425. return '';
  1426. }
  1427. // -------------------------------------------
  1428. // 'create_captcha_start' hook.
  1429. // - Allows rewrite of how CAPTCHAs are created
  1430. //
  1431. if ($this->EE->extensions->active_hook('create_captcha_start') === TRUE)
  1432. {
  1433. $edata = $this->EE->extensions->call('create_captcha_start', $old_word);
  1434. if ($this->EE->extensions->end_script === TRUE) return $edata;
  1435. }
  1436. // -------------------------------------------
  1437. $img_path = $this->EE->config->slash_item('captcha_path', 1);
  1438. $img_url = $this->EE->config->slash_item('captcha_url');
  1439. $use_font = ($this->EE->config->item('captcha_font') == 'y') ? TRUE : FALSE;
  1440. $font_face = "texb.ttf";
  1441. $font_size = 16;
  1442. $expiration = 60*60*2; // 2 hours
  1443. $img_width = 140; // Image width
  1444. $img_height = 30; // Image height
  1445. if ($img_path == '' OR $img_url == '')
  1446. {
  1447. return FALSE;
  1448. }
  1449. if ( ! @is_dir($img_path))
  1450. {
  1451. return FALSE;
  1452. }
  1453. if ( ! is_really_writable($img_path))
  1454. {
  1455. return FALSE;
  1456. }
  1457. if ( ! file_exists(APPPATH.'config/captcha.php'))
  1458. {
  1459. return FALSE;
  1460. }
  1461. if ( ! extension_loaded('gd'))
  1462. {
  1463. return FALSE;
  1464. }
  1465. if (substr($img_url, -1) != '/') $img_url .= '/';
  1466. // Disable DB caching if it's currently set
  1467. $db_reset = FALSE;
  1468. if ($this->EE->db->cache_on == TRUE)
  1469. {
  1470. $this->EE->db->cache_off();
  1471. $db_reset = TRUE;
  1472. }
  1473. // Remove old images - add a bit of randomness so we aren't doing this every page access
  1474. list($usec, $sec) = explode(" ", microtime());
  1475. $now = ((float)$usec + (float)$sec);
  1476. if ((mt_rand() % 100) < $this->EE->session->gc_probability)
  1477. {
  1478. $old = time() - $expiration;
  1479. $this->EE->db->query("DELETE FROM exp_captcha WHERE date < ".$old);
  1480. $current_dir = @opendir($img_path);
  1481. while($filename = @readdir($current_dir))
  1482. {
  1483. if ($filename != "." and $filename != ".." and $filename != "index.html")
  1484. {
  1485. $name = str_replace(".jpg", "", $filename);
  1486. if (($name + $expiration) < $now)
  1487. {
  1488. @unlink($img_path.$filename);
  1489. }
  1490. }
  1491. }
  1492. @closedir($current_dir);
  1493. }
  1494. // Fetch and insert word
  1495. if ($old_word == '')
  1496. {
  1497. require APPPATH.'config/captcha.php';
  1498. $word = $words[array_rand($words)];
  1499. if ($this->EE->config->item('captcha_rand') == 'y')
  1500. {
  1501. $word .= $this->random('nozero', 2);
  1502. }
  1503. $this->EE->db->query("INSERT INTO exp_captcha (date, ip_address, word) VALUES (UNIX_TIMESTAMP(), '".$this->EE->input->ip_address()."', '".$this->EE->db->escape_str($word)."')");
  1504. }
  1505. else
  1506. {
  1507. $word = $old_word;
  1508. }
  1509. $this->cached_captcha = $word;
  1510. // Determine angle and position
  1511. $length = strlen($word);
  1512. $angle = ($length >= 6) ? rand(-($length-6), ($length-6)) : 0;
  1513. $x_axis = rand(6, (360/$length)-16);
  1514. $y_axis = ($angle >= 0 ) ? rand($img_height, $img_width) : rand(6, $img_height);
  1515. // Create image
  1516. $im = ImageCreate($img_width, $img_height);
  1517. // Assign colors
  1518. $bg_color = ImageColorAllocate($im, 255, 255, 255);
  1519. $border_color = ImageColorAllocate($im, 153, 102, 102);
  1520. $text_color = ImageColorAllocate($im, 204, 153, 153);
  1521. $grid_color = imagecolorallocate($im, 255, 182, 182);
  1522. $shadow_color = imagecolorallocate($im, 255, 240, 240);
  1523. // Create the rectangle
  1524. ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $bg_color);
  1525. // Create the spiral pattern
  1526. $theta = 1;
  1527. $thetac = 6;
  1528. $radius = 12;
  1529. $circles = 20;
  1530. $points = 36;
  1531. for ($i = 0; $i < ($circles * $points) - 1; $i++)
  1532. {
  1533. $theta = $theta + $thetac;
  1534. $rad = $radius * ($i / $points );
  1535. $x = ($rad * cos($theta)) + $x_axis;
  1536. $y = ($rad * sin($theta)) + $y_axis;
  1537. $theta = $theta + $thetac;
  1538. $rad1 = $radius * (($i + 1) / $points);
  1539. $x1 = ($rad1 * cos($theta)) + $x_axis;
  1540. $y1 = ($rad1 * sin($theta )) + $y_axis;
  1541. imageline($im, $x, $y, $x1, $y1, $grid_color);
  1542. $theta = $theta - $thetac;
  1543. }
  1544. //imageline($im, $img_width, $img_height, 0, 0, $grid_color);
  1545. // Write the text
  1546. $font_path = APPPATH.'fonts/'.$font_face;
  1547. if ($use_font == TRUE)
  1548. {
  1549. if ( ! file_exists($font_path))
  1550. {
  1551. $use_font = FALSE;
  1552. }
  1553. }
  1554. if ($use_font == FALSE OR ! function_exists('imagettftext'))
  1555. {
  1556. $font_size = 5;
  1557. ImageString($im, $font_size, $x_axis, $img_height/3.8, $word, $text_color);
  1558. }
  1559. else
  1560. {
  1561. imagettftext($im, $font_size, $angle, $x_axis, $img_height/1.5, $text_color, $font_path, $word);
  1562. }
  1563. // Create the border
  1564. imagerectangle($im, 0, 0, $img_width-1, $img_height-1, $border_color);
  1565. // Generate the image
  1566. $img_name = $now.'.jpg';
  1567. ImageJPEG($im, $img_path.$img_name);
  1568. $img = "<img src=\"$img_url$img_name\" width=\"$img_width\" height=\"$img_height\" style=\"border:0;\" alt=\" \" />";
  1569. ImageDestroy($im);
  1570. // Re-enable DB caching
  1571. if ($db_reset == TRUE)
  1572. {
  1573. $this->EE->db->cache_on();
  1574. }
  1575. return $img;
  1576. }
  1577. // --------------------------------------------------------------------
  1578. /**
  1579. * SQL "AND" or "OR" string for conditional tag parameters
  1580. *
  1581. * This function lets us build a specific type of query
  1582. * needed when tags have conditional parameters:
  1583. *
  1584. * {exp:some_tag param="value1|value2|value3"}
  1585. *
  1586. * Or the parameter can contain "not":
  1587. *
  1588. * {exp:some_tag param="not value1|value2|value3"}
  1589. *
  1590. * This function explodes the pipes and constructs a series of AND
  1591. * conditions or OR conditions
  1592. *
  1593. * We should probably put this in the DB class but it's not
  1594. * something that is typically used
  1595. *
  1596. * @access public
  1597. * @param string
  1598. * @param string
  1599. * @param string
  1600. * @param bool
  1601. * @return string
  1602. */
  1603. function sql_andor_string($str, $field, $prefix = '', $null=FALSE)
  1604. {
  1605. if ($str == "" OR $field == "")
  1606. {
  1607. return '';
  1608. }
  1609. $str = trim($str);
  1610. $sql = '';
  1611. $not = '';
  1612. if ($prefix != '')
  1613. {
  1614. $prefix .= '.';
  1615. }
  1616. if (strpos($str, '|') !== FALSE)
  1617. {
  1618. $parts = preg_split('/\|/', $str, -1, PREG_SPLIT_NO_EMPTY);
  1619. $parts = array_map('trim', array_map(array($this->EE->db, 'escape_str'), $parts));
  1620. if (count($parts) > 0)
  1621. {
  1622. if (strncasecmp($parts[0], 'not ', 4) == 0)
  1623. {
  1624. $parts[0] = substr($parts[0], 4);
  1625. $not = 'NOT';
  1626. }
  1627. if ($null === TRUE)
  1628. {
  1629. $sql .= "AND ({$prefix}{$field} {$not} IN ('".implode("','", $parts)."') OR {$prefix}{$field} IS NULL)";
  1630. }
  1631. else
  1632. {
  1633. $sql .= "AND {$prefix}{$field} {$not} IN ('".implode("','", $parts)."')";
  1634. }
  1635. }
  1636. }
  1637. else
  1638. {
  1639. if (strncasecmp($str, 'not ', 4) == 0)
  1640. {
  1641. $str = trim(substr($str, 3));
  1642. $not = '!';
  1643. }
  1644. if ($null === TRUE)
  1645. {
  1646. $sql .= "AND ({$prefix}{$field} {$not}= '".$this->EE->db->escape_str($str)."' OR {$prefix}{$field} IS NULL)";
  1647. }
  1648. else
  1649. {
  1650. $sql .= "AND {$prefix}{$field} {$not}= '".$this->EE->db->escape_str($str)."'";
  1651. }
  1652. }
  1653. return $sql;
  1654. }
  1655. // --------------------------------------------------------------------
  1656. /**
  1657. * AR "AND" or "OR" string for conditional tag parameters
  1658. *
  1659. * This function lets us build a specific type of query
  1660. * needed when tags have conditional parameters:
  1661. *
  1662. * {exp:some_tag param="value1|value2|value3"}
  1663. *
  1664. * Or the parameter can contain "not":
  1665. *
  1666. * {exp:some_tag param="not value1|value2|value3"}
  1667. *

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