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

Last change on this file since 29468 was 27388, checked in by rvelices, 10 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
RevLine 
[1109]1<?php
2// +-----------------------------------------------------------------------+
[8728]3// | Piwigo - a PHP based photo gallery                                    |
[2297]4// +-----------------------------------------------------------------------+
[26461]5// | Copyright(C) 2008-2014 Piwigo Team                  http://piwigo.org |
[2297]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// +-----------------------------------------------------------------------+
[1109]23
24
25/**
26 * returns a prefix for each url link on displayed page
[1374]27 * and return an empty string for current path
[1109]28 * @return string
29 */
30function get_root_url()
31{
32  global $page;
[13240]33  if ( ($root_url = @$page['root_path']) == null )
[1750]34  {// TODO - add HERE the possibility to call PWG functions from external scripts
[1374]35    $root_url = PHPWG_ROOT_PATH;
[13258]36    if ( strncmp($root_url, './', 2) == 0 )
37    {
38      return substr($root_url, 2);
39    }
[1374]40  }
[13258]41  return $root_url;
[1109]42}
43
44/**
[1750]45 * returns the absolute url to the root of PWG
46 * @param boolean with_scheme if false - does not add http://toto.com
[1566]47 */
[1750]48function get_absolute_root_url($with_scheme=true)
[1566]49{
[1750]50  // TODO - add HERE the possibility to call PWG functions from external scripts
51  $url = '';
52  if ($with_scheme)
[1566]53  {
[23187]54    $is_https = false;
[6411]55    if (isset($_SERVER['HTTPS']) &&
[23187]56      ((strtolower($_SERVER['HTTPS']) == 'on') or ($_SERVER['HTTPS'] == 1)))
[2229]57    {
[23187]58      $is_https = true;
[3403]59      $url .= 'https://';
[2229]60    }
61    else
62    {
[3403]63      $url .= 'http://';
[2229]64    }
65    $url .= $_SERVER['HTTP_HOST'];
[23187]66    if ( (!$is_https && $_SERVER['SERVER_PORT'] != 80)
67          ||($is_https && $_SERVER['SERVER_PORT'] != 443))
[1750]68    {
[2083]69      $url_port = ':'.$_SERVER['SERVER_PORT'];
70      if (strrchr($url, ':') != $url_port)
71      {
72        $url .= $url_port;
73      }
[1750]74    }
[1566]75  }
[1750]76  $url .= cookie_path();
[1566]77  return $url;
78}
79
80/**
[1109]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 */
[8079]88function add_url_params($url, $params, $arg_separator='&amp;' )
[1109]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;
[8079]99        $url .= ( strpos($url, '?')===false ) ? '?' : $arg_separator;
[1109]100      }
101      else
102      {
[8079]103        $url .= $arg_separator;
[1109]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 */
[1503]121function make_index_url($params = array())
[1109]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  }
[9353]133
134  $url_before_params = $url;
[27388]135
[1503]136  $url.= make_section_in_url($params);
[1109]137  $url = add_well_known_params_in_url($url, $params);
[9353]138
139  if ($url == $url_before_params)
140  {
[14180]141    $url = get_absolute_root_url( url_is_remote($url) );
[9353]142  }
[27388]143
[1109]144  return $url;
145}
146
147/**
148 * build an index URL with current page parameters, but with redefinitions
149 * and removes.
150 *
[1861]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.
[1109]156 *
157 * @param array redefined keys
158 * @param array removed keys
159 * @return string
160 */
[1503]161function duplicate_index_url($redefined = array(), $removed = array())
[1109]162{
[1503]163  return make_index_url(
[1109]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
[3126]179  $params = $page;
[1109]180
[3126]181  foreach ($removed as $param_key)
[1109]182  {
[3126]183    unset($params[$param_key]);
[1109]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
[1503]196 * and removes. See duplicate_index_url.
[1109]197 *
198 * @param array redefined keys
199 * @param array removed keys
200 * @return string
201 */
[1503]202function duplicate_picture_url($redefined = array(), $removed = array())
[1109]203{
[1503]204  return make_picture_url(
[1109]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 */
[1503]215function make_picture_url($params)
[1109]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      {
[23822]235        $url .= '-'.str2url(get_filename_wo_extension($params['image_file']));
[1109]236      }
237      break;
238    case 'file':
[1562]239      if ( isset($params['image_file']) )
[1109]240      {
[1562]241        $fname_wo_ext = get_filename_wo_extension($params['image_file']);
[2773]242        if ( ord($fname_wo_ext)>ord('9') or !preg_match('/^\d+(-|$)/', $fname_wo_ext) )
[1562]243        {
244          $url .= $fname_wo_ext;
245          break;
246        }
[1109]247      }
248    default:
249      $url .= $params['image_id'];
250  }
[1956]251  if ( !isset($params['category'] ) )
252  {// make urls shorter ...
[2155]253    unset( $params['flat'] );
[1956]254  }
[1503]255  $url .= make_section_in_url($params);
[1109]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
[1800]279  if (isset($params['flat']))
[1677]280  {
[1789]281    $url.= '/flat';
[1677]282  }
283
[1109]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 */
[1503]300function make_section_in_url($params)
[1109]301{
[1131]302  global $conf;
[1109]303  $section_string = '';
[13258]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      );
[1109]313
[13258]314    foreach ($section_of as $param => $s)
315    {
316      if (isset($params[$param]))
317      {
318        $section = $s;
319      }
320    }
[1119]321
[13258]322    if (!isset($section))
323    {
324      $section = 'none';
325    }
326  }
[1109]327
[13240]328  switch($section)
[1109]329  {
330    case 'categories' :
331    {
332      if (!isset($params['category']))
333      {
[1119]334        $section_string.= '/categories';
[1109]335      }
336      else
337      {
[1861]338        isset($params['category']['name']) or trigger_error(
339            'make_section_in_url category name not set', E_USER_WARNING
340            );
341
[1866]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']) )
[1131]348        {
[1866]349          $section_string.= $params['category']['id'];
350          if ( $conf['category_url_style']=='id-name' )
351          {
352            $section_string.= '-'.str2url($params['category']['name']);
353          }
[1131]354        }
[1866]355        else
356        {
357          $section_string.= $params['category']['permalink'];
358        }
[1109]359      }
360
361      break;
362    }
363    case 'tags' :
364    {
365      $section_string.= '/tags';
366
367      foreach ($params['tags'] as $tag)
368      {
[1131]369        switch ( $conf['tag_url_style'] )
[1119]370        {
[1131]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            }
[1119]386        }
[1109]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    }
[1788]401    case 'none' :
402    {
403      break;
404    }
[1109]405    default :
406    {
[13240]407      $section_string.= '/'.$section;
[1109]408    }
409  }
410
411  return $section_string;
412}
[1676]413
414/**
[1980]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();
[2773]427  if (strncmp(@$tokens[$next_token], 'categor', 7)==0 )
[1980]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
[2047]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
[1980]448            and strpos($tokens[$next_token], 'start-')!==0
[18462]449            and strpos($tokens[$next_token], 'startcat-')!==0
[2047]450            and $tokens[$current_token] != 'flat')
451        {
452          if (empty($maybe_permalinks))
453          {
[25018]454            $maybe_permalinks[] = $tokens[$current_token];
[1980]455          }
[2047]456          else
457          {
[27388]458            $maybe_permalinks[] =
[2047]459                $maybe_permalinks[count($maybe_permalinks)-1]
[25018]460                . '/' . $tokens[$current_token];
[2047]461          }
462          $current_token++;
463        }
464
465        if ( count($maybe_permalinks) )
466        {
467          $cat_id = get_cat_id_from_permalinks($maybe_permalinks, $perma_index);
[1980]468          if ( isset($cat_id) )
469          {
[2047]470            $next_token += $perma_index+1;
[1980]471            $page['category'] = $cat_id;
[2047]472            $page['hit_by']['cat_permalink'] = $maybe_permalinks[$perma_index];
[1980]473          }
474          else
475          {
[15383]476            page_not_found(l10n('Permalink for album not found'));
[1980]477          }
478        }
[2047]479      }
[1980]480    }
481
482    if (isset($page['category']))
483    {
484      $result = get_cat_info($page['category']);
485      if (empty($result))
486      {
[15383]487         page_not_found(l10n('Requested album does not exist'));
[1980]488      }
489      $page['category']=$result;
490    }
491  }
[2773]492  elseif ( 'tags' == @$tokens[$next_token] )
[1980]493  {
[11831]494    global $conf;
495
[1980]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    {
[2773]507      if (strpos($tokens[$i], 'created-')===0
508           or strpos($tokens[$i], 'posted-')===0
509           or strpos($tokens[$i], 'start-')===0 )
[1980]510        break;
511
[11831]512      if ( $conf['tag_url_style'] != 'tag' and preg_match('/^(\d+)(?:-(.*)|)$/', $tokens[$i], $matches) )
[1980]513      {
[25018]514        $requested_tag_ids[] = $matches[1];
[1980]515      }
516      else
517      {
[25018]518        $requested_tag_url_names[] = $tokens[$i];
[1980]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    {
[15383]532      page_not_found(l10n('Requested tag does not exist'), get_root_url().'tags.php' );
[1980]533    }
534  }
[2773]535  elseif ( 'favorites' == @$tokens[$next_token] )
[1980]536  {
537    $page['section'] = 'favorites';
538    $next_token++;
539  }
[2773]540  elseif ('most_visited' == @$tokens[$next_token])
[1980]541  {
542    $page['section'] = 'most_visited';
543    $next_token++;
544  }
[2773]545  elseif ('best_rated' == @$tokens[$next_token])
[1980]546  {
547    $page['section'] = 'best_rated';
548    $next_token++;
549  }
[2773]550  elseif ('recent_pics' == @$tokens[$next_token])
[1980]551  {
552    $page['section'] = 'recent_pics';
553    $next_token++;
554  }
[2773]555  elseif ('recent_cats' == @$tokens[$next_token])
[1980]556  {
557    $page['section'] = 'recent_cats';
558    $next_token++;
559  }
[2773]560  elseif ('search' == @$tokens[$next_token])
[1980]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  }
[2773]573  elseif ('list' == @$tokens[$next_token])
[1980]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
[25018]584      $page['list'][] = -1;
[1980]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      {
[25018]595        $page['list'][] = $image_id;
[1980]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*/
[2155]607function parse_well_known_params_url($tokens, &$i)
[1980]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    }
[2773]617    elseif (strpos($tokens[$i], 'created-')===0 or strpos($tokens[$i], 'posted-')===0)
[1980]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    }
[2773]638    elseif (preg_match('/^start-(\d+)/', $tokens[$i], $matches))
639    {
640      $page['start'] = $matches[1];
641    }
[18462]642    elseif (preg_match('/^startcat-(\d+)/', $tokens[$i], $matches))
[18165]643    {
[18462]644      $page['startcat'] = $matches[1];
[18165]645    }
[1980]646    $i++;
647  }
648  return $page;
649}
650
[12855]651
[1980]652/**
[12855]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  }
[27388]666
[12855]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/**
[1676]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;
[1750]702    $page['root_path'] = get_absolute_root_url();
[1676]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
[2026]741/**
742 * Embellish the url argument
743 *
744 * @param $url
745 * @return $url embellished
746 */
747function embellish_url($url)
748{
[3126]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;
[2026]761}
762
[6411]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  {
[8247]771    if (url_is_remote($conf['gallery_url']) or $conf['gallery_url'][0]=='/' )
[6411]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}
[25615]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));
[27388]800
[25615]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
[3126]820?>
Note: See TracBrowser for help on using the repository browser.