source: trunk/include/functions_url.inc.php @ 30353

Last change on this file since 30353 was 27388, checked in by rvelices, 11 years ago

more query2array and remove unnecessary tests in often called url functions

  • Property svn:eol-style set to LF
File size: 19.1 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24
25/**
26 * returns a prefix for each url link on displayed page
27 * and return an empty string for current path
28 * @return string
29 */
30function get_root_url()
31{
32  global $page;
33  if ( ($root_url = @$page['root_path']) == null )
34  {// TODO - add HERE the possibility to call PWG functions from external scripts
35    $root_url = PHPWG_ROOT_PATH;
36    if ( strncmp($root_url, './', 2) == 0 )
37    {
38      return substr($root_url, 2);
39    }
40  }
41  return $root_url;
42}
43
44/**
45 * returns the absolute url to the root of PWG
46 * @param boolean with_scheme if false - does not add http://toto.com
47 */
48function get_absolute_root_url($with_scheme=true)
49{
50  // TODO - add HERE the possibility to call PWG functions from external scripts
51  $url = '';
52  if ($with_scheme)
53  {
54    $is_https = false;
55    if (isset($_SERVER['HTTPS']) &&
56      ((strtolower($_SERVER['HTTPS']) == 'on') or ($_SERVER['HTTPS'] == 1)))
57    {
58      $is_https = true;
59      $url .= 'https://';
60    }
61    else
62    {
63      $url .= 'http://';
64    }
65    $url .= $_SERVER['HTTP_HOST'];
66    if ( (!$is_https && $_SERVER['SERVER_PORT'] != 80)
67          ||($is_https && $_SERVER['SERVER_PORT'] != 443))
68    {
69      $url_port = ':'.$_SERVER['SERVER_PORT'];
70      if (strrchr($url, ':') != $url_port)
71      {
72        $url .= $url_port;
73      }
74    }
75  }
76  $url .= cookie_path();
77  return $url;
78}
79
80/**
81 * adds one or more _GET style parameters to an url
82 * example: add_url_params('/x', array('a'=>'b')) returns /x?a=b
83 * add_url_params('/x?cat_id=10', array('a'=>'b')) returns /x?cat_id=10&amp;a=b
84 * @param string url
85 * @param array params
86 * @return string
87 */
88function add_url_params($url, $params, $arg_separator='&amp;' )
89{
90  if ( !empty($params) )
91  {
92    assert( is_array($params) );
93    $is_first = true;
94    foreach($params as $param=>$val)
95    {
96      if ($is_first)
97      {
98        $is_first = false;
99        $url .= ( strpos($url, '?')===false ) ? '?' : $arg_separator;
100      }
101      else
102      {
103        $url .= $arg_separator;
104      }
105      $url .= $param;
106      if (isset($val))
107      {
108        $url .= '='.$val;
109      }
110    }
111  }
112  return $url;
113}
114
115/**
116 * build an index URL for a specific section
117 *
118 * @param array
119 * @return string
120 */
121function make_index_url($params = array())
122{
123  global $conf;
124  $url = get_root_url().'index';
125  if ($conf['php_extension_in_urls'])
126  {
127    $url .= '.php';
128  }
129  if ($conf['question_mark_in_urls'])
130  {
131    $url .= '?';
132  }
133
134  $url_before_params = $url;
135
136  $url.= make_section_in_url($params);
137  $url = add_well_known_params_in_url($url, $params);
138
139  if ($url == $url_before_params)
140  {
141    $url = get_absolute_root_url( url_is_remote($url) );
142  }
143
144  return $url;
145}
146
147/**
148 * build an index URL with current page parameters, but with redefinitions
149 * and removes.
150 *
151 * duplicate_index_url( array(
152 *   'category' => array('id'=>12, 'name'=>'toto'),
153 *   array('start')
154 * ) will create an index URL on the current section (categories), but on
155 * a redefined category and without the start URL parameter.
156 *
157 * @param array redefined keys
158 * @param array removed keys
159 * @return string
160 */
161function duplicate_index_url($redefined = array(), $removed = array())
162{
163  return make_index_url(
164    params_for_duplication($redefined, $removed)
165    );
166}
167
168/**
169 * returns $page global array with key redefined and key removed
170 *
171 * @param array redefined keys
172 * @param array removed keys
173 * @return array
174 */
175function params_for_duplication($redefined, $removed)
176{
177  global $page;
178
179  $params = $page;
180
181  foreach ($removed as $param_key)
182  {
183    unset($params[$param_key]);
184  }
185
186  foreach ($redefined as $redefined_param => $redefined_value)
187  {
188    $params[$redefined_param] = $redefined_value;
189  }
190
191  return $params;
192}
193
194/**
195 * create a picture URL with current page parameters, but with redefinitions
196 * and removes. See duplicate_index_url.
197 *
198 * @param array redefined keys
199 * @param array removed keys
200 * @return string
201 */
202function duplicate_picture_url($redefined = array(), $removed = array())
203{
204  return make_picture_url(
205    params_for_duplication($redefined, $removed)
206    );
207}
208
209/**
210 * create a picture URL on a specific section for a specific picture
211 *
212 * @param array
213 * @return string
214 */
215function make_picture_url($params)
216{
217  global $conf;
218
219  $url = get_root_url().'picture';
220  if ($conf['php_extension_in_urls'])
221  {
222    $url .= '.php';
223  }
224  if ($conf['question_mark_in_urls'])
225  {
226    $url .= '?';
227  }
228  $url.= '/';
229  switch ( $conf['picture_url_style'] )
230  {
231    case 'id-file':
232      $url .= $params['image_id'];
233      if ( isset($params['image_file']) )
234      {
235        $url .= '-'.str2url(get_filename_wo_extension($params['image_file']));
236      }
237      break;
238    case 'file':
239      if ( isset($params['image_file']) )
240      {
241        $fname_wo_ext = get_filename_wo_extension($params['image_file']);
242        if ( ord($fname_wo_ext)>ord('9') or !preg_match('/^\d+(-|$)/', $fname_wo_ext) )
243        {
244          $url .= $fname_wo_ext;
245          break;
246        }
247      }
248    default:
249      $url .= $params['image_id'];
250  }
251  if ( !isset($params['category'] ) )
252  {// make urls shorter ...
253    unset( $params['flat'] );
254  }
255  $url .= make_section_in_url($params);
256  $url = add_well_known_params_in_url($url, $params);
257  return $url;
258}
259
260/**
261 *adds to the url the chronology and start parameters
262*/
263function add_well_known_params_in_url($url, $params)
264{
265  if ( isset($params['chronology_field']) )
266  {
267    $url .= '/'. $params['chronology_field'];
268    $url .= '-'. $params['chronology_style'];
269    if ( isset($params['chronology_view']) )
270    {
271      $url .= '-'. $params['chronology_view'];
272    }
273    if ( !empty($params['chronology_date']) )
274    {
275      $url .= '-'. implode('-', $params['chronology_date'] );
276    }
277  }
278
279  if (isset($params['flat']))
280  {
281    $url.= '/flat';
282  }
283
284  if (isset($params['start']) and $params['start'] > 0)
285  {
286    $url.= '/start-'.$params['start'];
287  }
288  return $url;
289}
290
291/**
292 * return the section token of an index or picture URL.
293 *
294 * Depending on section, other parameters are required (see function code
295 * for details)
296 *
297 * @param array
298 * @return string
299 */
300function make_section_in_url($params)
301{
302  global $conf;
303  $section_string = '';
304  $section = @$params['section'];
305  if (!isset($section))
306  {
307    $section_of = array(
308      'category' => 'categories',
309      'tags'     => 'tags',
310      'list'     => 'list',
311      'search'   => 'search',
312      );
313
314    foreach ($section_of as $param => $s)
315    {
316      if (isset($params[$param]))
317      {
318        $section = $s;
319      }
320    }
321
322    if (!isset($section))
323    {
324      $section = 'none';
325    }
326  }
327
328  switch($section)
329  {
330    case 'categories' :
331    {
332      if (!isset($params['category']))
333      {
334        $section_string.= '/categories';
335      }
336      else
337      {
338        isset($params['category']['name']) or trigger_error(
339            'make_section_in_url category name not set', E_USER_WARNING
340            );
341
342        array_key_exists('permalink', $params['category']) or trigger_error(
343            'make_section_in_url category permalink not set', E_USER_WARNING
344            );
345
346        $section_string.= '/category/';
347        if ( empty($params['category']['permalink']) )
348        {
349          $section_string.= $params['category']['id'];
350          if ( $conf['category_url_style']=='id-name' )
351          {
352            $section_string.= '-'.str2url($params['category']['name']);
353          }
354        }
355        else
356        {
357          $section_string.= $params['category']['permalink'];
358        }
359      }
360
361      break;
362    }
363    case 'tags' :
364    {
365      $section_string.= '/tags';
366
367      foreach ($params['tags'] as $tag)
368      {
369        switch ( $conf['tag_url_style'] )
370        {
371          case 'id':
372            $section_string.= '/'.$tag['id'];
373            break;
374          case 'tag':
375            if (isset($tag['url_name']) and !is_numeric($tag['url_name']) )
376            {
377              $section_string.= '/'.$tag['url_name'];
378              break;
379            }
380          default:
381            $section_string.= '/'.$tag['id'];
382            if (isset($tag['url_name']))
383            {
384              $section_string.= '-'.$tag['url_name'];
385            }
386        }
387      }
388
389      break;
390    }
391    case 'search' :
392    {
393      $section_string.= '/search/'.$params['search'];
394      break;
395    }
396    case 'list' :
397    {
398      $section_string.= '/list/'.implode(',', $params['list']);
399      break;
400    }
401    case 'none' :
402    {
403      break;
404    }
405    default :
406    {
407      $section_string.= '/'.$section;
408    }
409  }
410
411  return $section_string;
412}
413
414/**
415 * the reverse of make_section_in_url
416 * returns the 'section' (categories/tags/...) and the data associated with it
417 *
418 * Depending on section, other parameters are returned (category/tags/list/...)
419 *
420 * @param array of url tokens to parse
421 * @param int the index in the array of url tokens; in/out
422 * @return array
423 */
424function parse_section_url( $tokens, &$next_token)
425{
426  $page=array();
427  if (strncmp(@$tokens[$next_token], 'categor', 7)==0 )
428  {
429    $page['section'] = 'categories';
430    $next_token++;
431
432    if (isset($tokens[$next_token]) )
433    {
434      if (preg_match('/^(\d+)(?:-(.+))?$/', $tokens[$next_token], $matches))
435      {
436        if ( isset($matches[2]) )
437          $page['hit_by']['cat_url_name'] = $matches[2];
438        $page['category'] = $matches[1];
439        $next_token++;
440      }
441      else
442      {// try a permalink
443        $maybe_permalinks = array();
444        $current_token = $next_token;
445        while ( isset($tokens[$current_token])
446            and strpos($tokens[$current_token], 'created-')!==0
447            and strpos($tokens[$current_token], 'posted-')!==0
448            and strpos($tokens[$next_token], 'start-')!==0
449            and strpos($tokens[$next_token], 'startcat-')!==0
450            and $tokens[$current_token] != 'flat')
451        {
452          if (empty($maybe_permalinks))
453          {
454            $maybe_permalinks[] = $tokens[$current_token];
455          }
456          else
457          {
458            $maybe_permalinks[] =
459                $maybe_permalinks[count($maybe_permalinks)-1]
460                . '/' . $tokens[$current_token];
461          }
462          $current_token++;
463        }
464
465        if ( count($maybe_permalinks) )
466        {
467          $cat_id = get_cat_id_from_permalinks($maybe_permalinks, $perma_index);
468          if ( isset($cat_id) )
469          {
470            $next_token += $perma_index+1;
471            $page['category'] = $cat_id;
472            $page['hit_by']['cat_permalink'] = $maybe_permalinks[$perma_index];
473          }
474          else
475          {
476            page_not_found(l10n('Permalink for album not found'));
477          }
478        }
479      }
480    }
481
482    if (isset($page['category']))
483    {
484      $result = get_cat_info($page['category']);
485      if (empty($result))
486      {
487         page_not_found(l10n('Requested album does not exist'));
488      }
489      $page['category']=$result;
490    }
491  }
492  elseif ( 'tags' == @$tokens[$next_token] )
493  {
494    global $conf;
495
496    $page['section'] = 'tags';
497    $page['tags'] = array();
498
499    $next_token++;
500    $i = $next_token;
501
502    $requested_tag_ids = array();
503    $requested_tag_url_names = array();
504
505    while (isset($tokens[$i]))
506    {
507      if (strpos($tokens[$i], 'created-')===0
508           or strpos($tokens[$i], 'posted-')===0
509           or strpos($tokens[$i], 'start-')===0 )
510        break;
511
512      if ( $conf['tag_url_style'] != 'tag' and preg_match('/^(\d+)(?:-(.*)|)$/', $tokens[$i], $matches) )
513      {
514        $requested_tag_ids[] = $matches[1];
515      }
516      else
517      {
518        $requested_tag_url_names[] = $tokens[$i];
519      }
520      $i++;
521    }
522    $next_token = $i;
523
524    if ( empty($requested_tag_ids) && empty($requested_tag_url_names) )
525    {
526      bad_request('at least one tag required');
527    }
528
529    $page['tags'] = find_tags($requested_tag_ids, $requested_tag_url_names);
530    if ( empty($page['tags']) )
531    {
532      page_not_found(l10n('Requested tag does not exist'), get_root_url().'tags.php' );
533    }
534  }
535  elseif ( 'favorites' == @$tokens[$next_token] )
536  {
537    $page['section'] = 'favorites';
538    $next_token++;
539  }
540  elseif ('most_visited' == @$tokens[$next_token])
541  {
542    $page['section'] = 'most_visited';
543    $next_token++;
544  }
545  elseif ('best_rated' == @$tokens[$next_token])
546  {
547    $page['section'] = 'best_rated';
548    $next_token++;
549  }
550  elseif ('recent_pics' == @$tokens[$next_token])
551  {
552    $page['section'] = 'recent_pics';
553    $next_token++;
554  }
555  elseif ('recent_cats' == @$tokens[$next_token])
556  {
557    $page['section'] = 'recent_cats';
558    $next_token++;
559  }
560  elseif ('search' == @$tokens[$next_token])
561  {
562    $page['section'] = 'search';
563    $next_token++;
564
565    preg_match('/(\d+)/', @$tokens[$next_token], $matches);
566    if (!isset($matches[1]))
567    {
568      bad_request('search identifier is missing');
569    }
570    $page['search'] = $matches[1];
571    $next_token++;
572  }
573  elseif ('list' == @$tokens[$next_token])
574  {
575    $page['section'] = 'list';
576    $next_token++;
577
578    $page['list'] = array();
579
580    // No pictures
581    if (empty($tokens[$next_token]))
582    {
583      // Add dummy element list
584      $page['list'][] = -1;
585    }
586    // With pictures list
587    else
588    {
589      if (!preg_match('/^\d+(,\d+)*$/', $tokens[$next_token]))
590      {
591        bad_request('wrong format on list GET parameter');
592      }
593      foreach (explode(',', $tokens[$next_token]) as $image_id)
594      {
595        $page['list'][] = $image_id;
596      }
597    }
598    $next_token++;
599  }
600  return $page;
601}
602
603/**
604 * the reverse of add_well_known_params_in_url
605 * parses start, flat and chronology from url tokens
606*/
607function parse_well_known_params_url($tokens, &$i)
608{
609  $page = array();
610  while (isset($tokens[$i]))
611  {
612    if ( 'flat' == $tokens[$i] )
613    {
614      // indicate a special list of images
615      $page['flat'] = true;
616    }
617    elseif (strpos($tokens[$i], 'created-')===0 or strpos($tokens[$i], 'posted-')===0)
618    {
619      $chronology_tokens = explode('-', $tokens[$i] );
620
621      $page['chronology_field'] = $chronology_tokens[0];
622
623      array_shift($chronology_tokens);
624      $page['chronology_style'] = $chronology_tokens[0];
625
626      array_shift($chronology_tokens);
627      if ( count($chronology_tokens)>0 )
628      {
629        if ('list'==$chronology_tokens[0] or
630            'calendar'==$chronology_tokens[0])
631        {
632          $page['chronology_view'] = $chronology_tokens[0];
633          array_shift($chronology_tokens);
634        }
635        $page['chronology_date'] = $chronology_tokens;
636      }
637    }
638    elseif (preg_match('/^start-(\d+)/', $tokens[$i], $matches))
639    {
640      $page['start'] = $matches[1];
641    }
642    elseif (preg_match('/^startcat-(\d+)/', $tokens[$i], $matches))
643    {
644      $page['startcat'] = $matches[1];
645    }
646    $i++;
647  }
648  return $page;
649}
650
651
652/**
653 * @param id image id
654 * @param what_part string one of 'e' (element), 'r' (representative)
655 */
656function get_action_url($id, $what_part, $download)
657{
658  $params = array(
659        'id' => $id,
660        'part' => $what_part,
661      );
662  if ($download)
663  {
664    $params['download'] = null;
665  }
666
667  return add_url_params(get_root_url().'action.php', $params);
668}
669
670/*
671 * @param element_info array containing element information from db;
672 * at least 'id', 'path' should be present
673 */
674function get_element_url($element_info)
675{
676  $url = $element_info['path'];
677  if ( !url_is_remote($url) )
678  {
679    $url = embellish_url(get_root_url().$url);
680  }
681  return $url;
682}
683
684
685/**
686 * Indicate to build url with full path
687 *
688 * @param null
689 * @return null
690 */
691function set_make_full_url()
692{
693  global $page;
694
695  if (!isset($page['save_root_path']))
696  {
697    if (isset($page['root_path']))
698    {
699      $page['save_root_path']['path'] = $page['root_path'];
700    }
701    $page['save_root_path']['count'] = 1;
702    $page['root_path'] = get_absolute_root_url();
703  }
704  else
705  {
706    $page['save_root_path']['count'] += 1;
707  }
708}
709
710/**
711 * Restore old parameter to build url with full path
712 *
713 * @param null
714 * @return null
715 */
716function unset_make_full_url()
717{
718  global $page;
719
720  if (isset($page['save_root_path']))
721  {
722    if ($page['save_root_path']['count'] == 1)
723    {
724      if (isset($page['save_root_path']['path']))
725      {
726        $page['root_path'] = $page['save_root_path']['path'];
727      }
728      else
729      {
730        unset($page['root_path']);
731      }
732      unset($page['save_root_path']);
733    }
734    else
735    {
736      $page['save_root_path']['count'] -= 1;
737    }
738  }
739}
740
741/**
742 * Embellish the url argument
743 *
744 * @param $url
745 * @return $url embellished
746 */
747function embellish_url($url)
748{
749  $url = str_replace('/./', '/', $url);
750  while ( ($dotdot = strpos($url, '/../', 1) ) !== false )
751  {
752    $before = strrpos($url, '/', -(strlen($url)-$dotdot+1) );
753    if ($before !== false)
754    {
755      $url = substr_replace($url, '', $before, $dotdot-$before+3);
756    }
757    else
758      break;
759  }
760  return $url;
761}
762
763/**
764 * Returns the 'home page' of this gallery
765 */
766function get_gallery_home_url()
767{
768  global $conf;
769  if (!empty($conf['gallery_url']))
770  {
771    if (url_is_remote($conf['gallery_url']) or $conf['gallery_url'][0]=='/' )
772    {
773      return $conf['gallery_url'];
774    }
775    return get_root_url().$conf['gallery_url'];
776  }
777  else
778  {
779    return make_index_url();
780  }
781}
782
783/**
784 * returns $_SERVER['QUERY_STRING'] whithout keys given in parameters
785 *
786 * @param string[] $rejects
787 * @param boolean $escape escape *&* to *&amp;*
788 * @returns string
789 */
790function get_query_string_diff($rejects=array(), $escape=true)
791{
792  if (empty($_SERVER['QUERY_STRING']))
793  {
794    return '';
795  }
796
797  parse_str($_SERVER['QUERY_STRING'], $vars);
798
799  $vars = array_diff_key($vars, array_flip($rejects));
800
801  return '?' . http_build_query($vars, '', $escape ? '&amp;' : '&');
802}
803
804/**
805 * returns true if the url is absolute (begins with http)
806 *
807 * @param string $url
808 * @returns boolean
809 */
810function url_is_remote($url)
811{
812  if ( strncmp($url, 'http://', 7)==0
813    or strncmp($url, 'https://', 8)==0 )
814  {
815    return true;
816  }
817  return false;
818}
819
820?>
Note: See TracBrowser for help on using the repository browser.