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