You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

569 lines
14 KiB

7 years ago
  1. <?php
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP
  6. *
  7. * This content is released under the MIT License (MIT)
  8. *
  9. * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in
  19. * all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. * THE SOFTWARE.
  28. *
  29. * @package CodeIgniter
  30. * @author EllisLab Dev Team
  31. * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
  32. * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
  33. * @license http://opensource.org/licenses/MIT MIT License
  34. * @link https://codeigniter.com
  35. * @since Version 1.0.0
  36. * @filesource
  37. */
  38. defined('BASEPATH') OR exit('No direct script access allowed');
  39. /**
  40. * CodeIgniter URL Helpers
  41. *
  42. * @package CodeIgniter
  43. * @subpackage Helpers
  44. * @category Helpers
  45. * @author EllisLab Dev Team
  46. * @link https://codeigniter.com/user_guide/helpers/url_helper.html
  47. */
  48. // ------------------------------------------------------------------------
  49. if ( ! function_exists('site_url'))
  50. {
  51. /**
  52. * Site URL
  53. *
  54. * Create a local URL based on your basepath. Segments can be passed via the
  55. * first parameter either as a string or an array.
  56. *
  57. * @param string $uri
  58. * @param string $protocol
  59. * @return string
  60. */
  61. function site_url($uri = '', $protocol = NULL)
  62. {
  63. return get_instance()->config->site_url($uri, $protocol);
  64. }
  65. }
  66. // ------------------------------------------------------------------------
  67. if ( ! function_exists('base_url'))
  68. {
  69. /**
  70. * Base URL
  71. *
  72. * Create a local URL based on your basepath.
  73. * Segments can be passed in as a string or an array, same as site_url
  74. * or a URL to a file can be passed in, e.g. to an image file.
  75. *
  76. * @param string $uri
  77. * @param string $protocol
  78. * @return string
  79. */
  80. function base_url($uri = '', $protocol = NULL)
  81. {
  82. return get_instance()->config->base_url($uri, $protocol);
  83. }
  84. }
  85. // ------------------------------------------------------------------------
  86. if ( ! function_exists('current_url'))
  87. {
  88. /**
  89. * Current URL
  90. *
  91. * Returns the full URL (including segments) of the page where this
  92. * function is placed
  93. *
  94. * @return string
  95. */
  96. function current_url()
  97. {
  98. $CI =& get_instance();
  99. return $CI->config->site_url($CI->uri->uri_string());
  100. }
  101. }
  102. // ------------------------------------------------------------------------
  103. if ( ! function_exists('uri_string'))
  104. {
  105. /**
  106. * URL String
  107. *
  108. * Returns the URI segments.
  109. *
  110. * @return string
  111. */
  112. function uri_string()
  113. {
  114. return get_instance()->uri->uri_string();
  115. }
  116. }
  117. // ------------------------------------------------------------------------
  118. if ( ! function_exists('index_page'))
  119. {
  120. /**
  121. * Index page
  122. *
  123. * Returns the "index_page" from your config file
  124. *
  125. * @return string
  126. */
  127. function index_page()
  128. {
  129. return get_instance()->config->item('index_page');
  130. }
  131. }
  132. // ------------------------------------------------------------------------
  133. if ( ! function_exists('anchor'))
  134. {
  135. /**
  136. * Anchor Link
  137. *
  138. * Creates an anchor based on the local URL.
  139. *
  140. * @param string the URL
  141. * @param string the link title
  142. * @param mixed any attributes
  143. * @return string
  144. */
  145. function anchor($uri = '', $title = '', $attributes = '')
  146. {
  147. $title = (string) $title;
  148. $site_url = is_array($uri)
  149. ? site_url($uri)
  150. : (preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri));
  151. if ($title === '')
  152. {
  153. $title = $site_url;
  154. }
  155. if ($attributes !== '')
  156. {
  157. $attributes = _stringify_attributes($attributes);
  158. }
  159. return '<a href="'.$site_url.'"'.$attributes.'>'.$title.'</a>';
  160. }
  161. }
  162. // ------------------------------------------------------------------------
  163. if ( ! function_exists('anchor_popup'))
  164. {
  165. /**
  166. * Anchor Link - Pop-up version
  167. *
  168. * Creates an anchor based on the local URL. The link
  169. * opens a new window based on the attributes specified.
  170. *
  171. * @param string the URL
  172. * @param string the link title
  173. * @param mixed any attributes
  174. * @return string
  175. */
  176. function anchor_popup($uri = '', $title = '', $attributes = FALSE)
  177. {
  178. $title = (string) $title;
  179. $site_url = preg_match('#^(\w+:)?//#i', $uri) ? $uri : site_url($uri);
  180. if ($title === '')
  181. {
  182. $title = $site_url;
  183. }
  184. if ($attributes === FALSE)
  185. {
  186. return '<a href="'.$site_url.'" onclick="window.open(\''.$site_url."', '_blank'); return false;\">".$title.'</a>';
  187. }
  188. if ( ! is_array($attributes))
  189. {
  190. $attributes = array($attributes);
  191. // Ref: http://www.w3schools.com/jsref/met_win_open.asp
  192. $window_name = '_blank';
  193. }
  194. elseif ( ! empty($attributes['window_name']))
  195. {
  196. $window_name = $attributes['window_name'];
  197. unset($attributes['window_name']);
  198. }
  199. else
  200. {
  201. $window_name = '_blank';
  202. }
  203. foreach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'menubar' => 'no', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0') as $key => $val)
  204. {
  205. $atts[$key] = isset($attributes[$key]) ? $attributes[$key] : $val;
  206. unset($attributes[$key]);
  207. }
  208. $attributes = _stringify_attributes($attributes);
  209. return '<a href="'.$site_url
  210. .'" onclick="window.open(\''.$site_url."', '".$window_name."', '"._stringify_attributes($atts, TRUE)."'); return false;\""
  211. .$attributes.'>'.$title.'</a>';
  212. }
  213. }
  214. // ------------------------------------------------------------------------
  215. if ( ! function_exists('mailto'))
  216. {
  217. /**
  218. * Mailto Link
  219. *
  220. * @param string the email address
  221. * @param string the link title
  222. * @param mixed any attributes
  223. * @return string
  224. */
  225. function mailto($email, $title = '', $attributes = '')
  226. {
  227. $title = (string) $title;
  228. if ($title === '')
  229. {
  230. $title = $email;
  231. }
  232. return '<a href="mailto:'.$email.'"'._stringify_attributes($attributes).'>'.$title.'</a>';
  233. }
  234. }
  235. // ------------------------------------------------------------------------
  236. if ( ! function_exists('safe_mailto'))
  237. {
  238. /**
  239. * Encoded Mailto Link
  240. *
  241. * Create a spam-protected mailto link written in Javascript
  242. *
  243. * @param string the email address
  244. * @param string the link title
  245. * @param mixed any attributes
  246. * @return string
  247. */
  248. function safe_mailto($email, $title = '', $attributes = '')
  249. {
  250. $title = (string) $title;
  251. if ($title === '')
  252. {
  253. $title = $email;
  254. }
  255. $x = str_split('<a href="mailto:', 1);
  256. for ($i = 0, $l = strlen($email); $i < $l; $i++)
  257. {
  258. $x[] = '|'.ord($email[$i]);
  259. }
  260. $x[] = '"';
  261. if ($attributes !== '')
  262. {
  263. if (is_array($attributes))
  264. {
  265. foreach ($attributes as $key => $val)
  266. {
  267. $x[] = ' '.$key.'="';
  268. for ($i = 0, $l = strlen($val); $i < $l; $i++)
  269. {
  270. $x[] = '|'.ord($val[$i]);
  271. }
  272. $x[] = '"';
  273. }
  274. }
  275. else
  276. {
  277. for ($i = 0, $l = strlen($attributes); $i < $l; $i++)
  278. {
  279. $x[] = $attributes[$i];
  280. }
  281. }
  282. }
  283. $x[] = '>';
  284. $temp = array();
  285. for ($i = 0, $l = strlen($title); $i < $l; $i++)
  286. {
  287. $ordinal = ord($title[$i]);
  288. if ($ordinal < 128)
  289. {
  290. $x[] = '|'.$ordinal;
  291. }
  292. else
  293. {
  294. if (count($temp) === 0)
  295. {
  296. $count = ($ordinal < 224) ? 2 : 3;
  297. }
  298. $temp[] = $ordinal;
  299. if (count($temp) === $count)
  300. {
  301. $number = ($count === 3)
  302. ? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)
  303. : (($temp[0] % 32) * 64) + ($temp[1] % 64);
  304. $x[] = '|'.$number;
  305. $count = 1;
  306. $temp = array();
  307. }
  308. }
  309. }
  310. $x[] = '<'; $x[] = '/'; $x[] = 'a'; $x[] = '>';
  311. $x = array_reverse($x);
  312. $output = "<script type=\"text/javascript\">\n"
  313. ."\t//<![CDATA[\n"
  314. ."\tvar l=new Array();\n";
  315. for ($i = 0, $c = count($x); $i < $c; $i++)
  316. {
  317. $output .= "\tl[".$i."] = '".$x[$i]."';\n";
  318. }
  319. $output .= "\n\tfor (var i = l.length-1; i >= 0; i=i-1) {\n"
  320. ."\t\tif (l[i].substring(0, 1) === '|') document.write(\"&#\"+unescape(l[i].substring(1))+\";\");\n"
  321. ."\t\telse document.write(unescape(l[i]));\n"
  322. ."\t}\n"
  323. ."\t//]]>\n"
  324. .'</script>';
  325. return $output;
  326. }
  327. }
  328. // ------------------------------------------------------------------------
  329. if ( ! function_exists('auto_link'))
  330. {
  331. /**
  332. * Auto-linker
  333. *
  334. * Automatically links URL and Email addresses.
  335. * Note: There's a bit of extra code here to deal with
  336. * URLs or emails that end in a period. We'll strip these
  337. * off and add them after the link.
  338. *
  339. * @param string the string
  340. * @param string the type: email, url, or both
  341. * @param bool whether to create pop-up links
  342. * @return string
  343. */
  344. function auto_link($str, $type = 'both', $popup = FALSE)
  345. {
  346. // Find and replace any URLs.
  347. if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))
  348. {
  349. // Set our target HTML if using popup links.
  350. $target = ($popup) ? ' target="_blank"' : '';
  351. // We process the links in reverse order (last -> first) so that
  352. // the returned string offsets from preg_match_all() are not
  353. // moved as we add more HTML.
  354. foreach (array_reverse($matches) as $match)
  355. {
  356. // $match[0] is the matched string/link
  357. // $match[1] is either a protocol prefix or 'www.'
  358. //
  359. // With PREG_OFFSET_CAPTURE, both of the above is an array,
  360. // where the actual value is held in [0] and its offset at the [1] index.
  361. $a = '<a href="'.(strpos($match[1][0], '/') ? '' : 'http://').$match[0][0].'"'.$target.'>'.$match[0][0].'</a>';
  362. $str = substr_replace($str, $a, $match[0][1], strlen($match[0][0]));
  363. }
  364. }
  365. // Find and replace any emails.
  366. if ($type !== 'url' && preg_match_all('#([\w\.\-\+]+@[a-z0-9\-]+\.[a-z0-9\-\.]+[^[:punct:]\s])#i', $str, $matches, PREG_OFFSET_CAPTURE))
  367. {
  368. foreach (array_reverse($matches[0]) as $match)
  369. {
  370. if (filter_var($match[0], FILTER_VALIDATE_EMAIL) !== FALSE)
  371. {
  372. $str = substr_replace($str, safe_mailto($match[0]), $match[1], strlen($match[0]));
  373. }
  374. }
  375. }
  376. return $str;
  377. }
  378. }
  379. // ------------------------------------------------------------------------
  380. if ( ! function_exists('prep_url'))
  381. {
  382. /**
  383. * Prep URL
  384. *
  385. * Simply adds the http:// part if no scheme is included
  386. *
  387. * @param string the URL
  388. * @return string
  389. */
  390. function prep_url($str = '')
  391. {
  392. if ($str === 'http://' OR $str === '')
  393. {
  394. return '';
  395. }
  396. $url = parse_url($str);
  397. if ( ! $url OR ! isset($url['scheme']))
  398. {
  399. return 'http://'.$str;
  400. }
  401. return $str;
  402. }
  403. }
  404. // ------------------------------------------------------------------------
  405. if ( ! function_exists('url_title'))
  406. {
  407. /**
  408. * Create URL Title
  409. *
  410. * Takes a "title" string as input and creates a
  411. * human-friendly URL string with a "separator" string
  412. * as the word separator.
  413. *
  414. * @todo Remove old 'dash' and 'underscore' usage in 3.1+.
  415. * @param string $str Input string
  416. * @param string $separator Word separator
  417. * (usually '-' or '_')
  418. * @param bool $lowercase Whether to transform the output string to lowercase
  419. * @return string
  420. */
  421. function url_title($str, $separator = '-', $lowercase = FALSE)
  422. {
  423. if ($separator === 'dash')
  424. {
  425. $separator = '-';
  426. }
  427. elseif ($separator === 'underscore')
  428. {
  429. $separator = '_';
  430. }
  431. $q_separator = preg_quote($separator, '#');
  432. $trans = array(
  433. '&.+?;' => '',
  434. '[^\w\d _-]' => '',
  435. '\s+' => $separator,
  436. '('.$q_separator.')+' => $separator
  437. );
  438. $str = strip_tags($str);
  439. foreach ($trans as $key => $val)
  440. {
  441. $str = preg_replace('#'.$key.'#i'.(UTF8_ENABLED ? 'u' : ''), $val, $str);
  442. }
  443. if ($lowercase === TRUE)
  444. {
  445. $str = strtolower($str);
  446. }
  447. return trim(trim($str, $separator));
  448. }
  449. }
  450. // ------------------------------------------------------------------------
  451. if ( ! function_exists('redirect'))
  452. {
  453. /**
  454. * Header Redirect
  455. *
  456. * Header redirect in two flavors
  457. * For very fine grained control over headers, you could use the Output
  458. * Library's set_header() function.
  459. *
  460. * @param string $uri URL
  461. * @param string $method Redirect method
  462. * 'auto', 'location' or 'refresh'
  463. * @param int $code HTTP Response status code
  464. * @return void
  465. */
  466. function redirect($uri = '', $method = 'auto', $code = NULL)
  467. {
  468. if ( ! preg_match('#^(\w+:)?//#i', $uri))
  469. {
  470. $uri = site_url($uri);
  471. }
  472. // IIS environment likely? Use 'refresh' for better compatibility
  473. if ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== FALSE)
  474. {
  475. $method = 'refresh';
  476. }
  477. elseif ($method !== 'refresh' && (empty($code) OR ! is_numeric($code)))
  478. {
  479. if (isset($_SERVER['SERVER_PROTOCOL'], $_SERVER['REQUEST_METHOD']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1')
  480. {
  481. $code = ($_SERVER['REQUEST_METHOD'] !== 'GET')
  482. ? 303 // reference: http://en.wikipedia.org/wiki/Post/Redirect/Get
  483. : 307;
  484. }
  485. else
  486. {
  487. $code = 302;
  488. }
  489. }
  490. switch ($method)
  491. {
  492. case 'refresh':
  493. header('Refresh:0;url='.$uri);
  494. break;
  495. default:
  496. header('Location: '.$uri, TRUE, $code);
  497. break;
  498. }
  499. exit;
  500. }
  501. }