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

Last change on this file since 26197 was 25615, checked in by mistic100, 11 years ago

move get_query_string_diff and url_is_remote to functions_url.inc.php

  • Property svn:eol-style set to LF
File size: 19.8 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2013 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  isset($params['image_id']) or fatal_error('make_picture_url: image_id is a required parameter');
220
221  $url = get_root_url().'picture';
222  if ($conf['php_extension_in_urls'])
223  {
224    $url .= '.php';
225  }
226  if ($conf['question_mark_in_urls'])
227  {
228    $url .= '?';
229  }
230  $url.= '/';
231  switch ( $conf['picture_url_style'] )
232  {
233    case 'id-file':
234      $url .= $params['image_id'];
235      if ( isset($params['image_file']) )
236      {
237        $url .= '-'.str2url(get_filename_wo_extension($params['image_file']));
238      }
239      break;
240    case 'file':
241      if ( isset($params['image_file']) )
242      {
243        $fname_wo_ext = get_filename_wo_extension($params['image_file']);
244        if ( ord($fname_wo_ext)>ord('9') or !preg_match('/^\d+(-|$)/', $fname_wo_ext) )
245        {
246          $url .= $fname_wo_ext;
247          break;
248        }
249      }
250    default:
251      $url .= $params['image_id'];
252  }
253  if ( !isset($params['category'] ) )
254  {// make urls shorter ...
255    unset( $params['flat'] );
256  }
257  $url .= make_section_in_url($params);
258  $url = add_well_known_params_in_url($url, $params);
259  return $url;
260}
261
262/**
263 *adds to the url the chronology and start parameters
264*/
265function add_well_known_params_in_url($url, $params)
266{
267  if ( isset($params['chronology_field']) )
268  {
269    $url .= '/'. $params['chronology_field'];
270    $url .= '-'. $params['chronology_style'];
271    if ( isset($params['chronology_view']) )
272    {
273      $url .= '-'. $params['chronology_view'];
274    }
275    if ( !empty($params['chronology_date']) )
276    {
277      $url .= '-'. implode('-', $params['chronology_date'] );
278    }
279  }
280
281  if (isset($params['flat']))
282  {
283    $url.= '/flat';
284  }
285
286  if (isset($params['start']) and $params['start'] > 0)
287  {
288    $url.= '/start-'.$params['start'];
289  }
290  return $url;
291}
292
293/**
294 * return the section token of an index or picture URL.
295 *
296 * Depending on section, other parameters are required (see function code
297 * for details)
298 *
299 * @param array
300 * @return string
301 */
302function make_section_in_url($params)
303{
304  global $conf;
305  $section_string = '';
306  $section = @$params['section'];
307  if (!isset($section))
308  {
309    $section_of = array(
310      'category' => 'categories',
311      'tags'     => 'tags',
312      'list'     => 'list',
313      'search'   => 'search',
314      );
315
316    foreach ($section_of as $param => $s)
317    {
318      if (isset($params[$param]))
319      {
320        $section = $s;
321      }
322    }
323
324    if (!isset($section))
325    {
326      $section = 'none';
327    }
328  }
329
330  switch($section)
331  {
332    case 'categories' :
333    {
334      if (!isset($params['category']))
335      {
336        $section_string.= '/categories';
337      }
338      else
339      {
340        is_array($params['category']) or trigger_error(
341            'make_section_in_url wrong type for category', E_USER_WARNING
342            );
343        is_numeric($params['category']['id']) or trigger_error(
344            'make_section_in_url category id not numeric', E_USER_WARNING
345            );
346        isset($params['category']['name']) or trigger_error(
347            'make_section_in_url category name not set', E_USER_WARNING
348            );
349
350        array_key_exists('permalink', $params['category']) or trigger_error(
351            'make_section_in_url category permalink not set', E_USER_WARNING
352            );
353
354        $section_string.= '/category/';
355        if ( empty($params['category']['permalink']) )
356        {
357          $section_string.= $params['category']['id'];
358          if ( $conf['category_url_style']=='id-name' )
359          {
360            $section_string.= '-'.str2url($params['category']['name']);
361          }
362        }
363        else
364        {
365          $section_string.= $params['category']['permalink'];
366        }
367      }
368
369      break;
370    }
371    case 'tags' :
372    {
373      if (!isset($params['tags']) or count($params['tags']) == 0)
374      {
375        fatal_error('make_section_in_url: require at least one tag');
376      }
377
378      $section_string.= '/tags';
379
380      foreach ($params['tags'] as $tag)
381      {
382        switch ( $conf['tag_url_style'] )
383        {
384          case 'id':
385            $section_string.= '/'.$tag['id'];
386            break;
387          case 'tag':
388            if (isset($tag['url_name']) and !is_numeric($tag['url_name']) )
389            {
390              $section_string.= '/'.$tag['url_name'];
391              break;
392            }
393          default:
394            $section_string.= '/'.$tag['id'];
395            if (isset($tag['url_name']))
396            {
397              $section_string.= '-'.$tag['url_name'];
398            }
399        }
400      }
401
402      break;
403    }
404    case 'search' :
405    {
406      isset($params['search']) or fatal_error('make_section_in_url: require a search identifier');
407      $section_string.= '/search/'.$params['search'];
408      break;
409    }
410    case 'list' :
411    {
412      isset($params['list']) or fatal_error('make_section_in_url: require a list of items');
413      $section_string.= '/list/'.implode(',', $params['list']);
414      break;
415    }
416    case 'none' :
417    {
418      break;
419    }
420    default :
421    {
422      $section_string.= '/'.$section;
423    }
424  }
425
426  return $section_string;
427}
428
429/**
430 * the reverse of make_section_in_url
431 * returns the 'section' (categories/tags/...) and the data associated with it
432 *
433 * Depending on section, other parameters are returned (category/tags/list/...)
434 *
435 * @param array of url tokens to parse
436 * @param int the index in the array of url tokens; in/out
437 * @return array
438 */
439function parse_section_url( $tokens, &$next_token)
440{
441  $page=array();
442  if (strncmp(@$tokens[$next_token], 'categor', 7)==0 )
443  {
444    $page['section'] = 'categories';
445    $next_token++;
446
447    if (isset($tokens[$next_token]) )
448    {
449      if (preg_match('/^(\d+)(?:-(.+))?$/', $tokens[$next_token], $matches))
450      {
451        if ( isset($matches[2]) )
452          $page['hit_by']['cat_url_name'] = $matches[2];
453        $page['category'] = $matches[1];
454        $next_token++;
455      }
456      else
457      {// try a permalink
458        $maybe_permalinks = array();
459        $current_token = $next_token;
460        while ( isset($tokens[$current_token])
461            and strpos($tokens[$current_token], 'created-')!==0
462            and strpos($tokens[$current_token], 'posted-')!==0
463            and strpos($tokens[$next_token], 'start-')!==0
464            and strpos($tokens[$next_token], 'startcat-')!==0
465            and $tokens[$current_token] != 'flat')
466        {
467          if (empty($maybe_permalinks))
468          {
469            $maybe_permalinks[] = $tokens[$current_token];
470          }
471          else
472          {
473            $maybe_permalinks[] = 
474                $maybe_permalinks[count($maybe_permalinks)-1]
475                . '/' . $tokens[$current_token];
476          }
477          $current_token++;
478        }
479
480        if ( count($maybe_permalinks) )
481        {
482          $cat_id = get_cat_id_from_permalinks($maybe_permalinks, $perma_index);
483          if ( isset($cat_id) )
484          {
485            $next_token += $perma_index+1;
486            $page['category'] = $cat_id;
487            $page['hit_by']['cat_permalink'] = $maybe_permalinks[$perma_index];
488          }
489          else
490          {
491            page_not_found(l10n('Permalink for album not found'));
492          }
493        }
494      }
495    }
496
497    if (isset($page['category']))
498    {
499      $result = get_cat_info($page['category']);
500      if (empty($result))
501      {
502         page_not_found(l10n('Requested album does not exist'));
503      }
504      $page['category']=$result;
505    }
506  }
507  elseif ( 'tags' == @$tokens[$next_token] )
508  {
509    global $conf;
510
511    $page['section'] = 'tags';
512    $page['tags'] = array();
513
514    $next_token++;
515    $i = $next_token;
516
517    $requested_tag_ids = array();
518    $requested_tag_url_names = array();
519
520    while (isset($tokens[$i]))
521    {
522      if (strpos($tokens[$i], 'created-')===0
523           or strpos($tokens[$i], 'posted-')===0
524           or strpos($tokens[$i], 'start-')===0 )
525        break;
526
527      if ( $conf['tag_url_style'] != 'tag' and preg_match('/^(\d+)(?:-(.*)|)$/', $tokens[$i], $matches) )
528      {
529        $requested_tag_ids[] = $matches[1];
530      }
531      else
532      {
533        $requested_tag_url_names[] = $tokens[$i];
534      }
535      $i++;
536    }
537    $next_token = $i;
538
539    if ( empty($requested_tag_ids) && empty($requested_tag_url_names) )
540    {
541      bad_request('at least one tag required');
542    }
543
544    $page['tags'] = find_tags($requested_tag_ids, $requested_tag_url_names);
545    if ( empty($page['tags']) )
546    {
547      page_not_found(l10n('Requested tag does not exist'), get_root_url().'tags.php' );
548    }
549  }
550  elseif ( 'favorites' == @$tokens[$next_token] )
551  {
552    $page['section'] = 'favorites';
553    $next_token++;
554  }
555  elseif ('most_visited' == @$tokens[$next_token])
556  {
557    $page['section'] = 'most_visited';
558    $next_token++;
559  }
560  elseif ('best_rated' == @$tokens[$next_token])
561  {
562    $page['section'] = 'best_rated';
563    $next_token++;
564  }
565  elseif ('recent_pics' == @$tokens[$next_token])
566  {
567    $page['section'] = 'recent_pics';
568    $next_token++;
569  }
570  elseif ('recent_cats' == @$tokens[$next_token])
571  {
572    $page['section'] = 'recent_cats';
573    $next_token++;
574  }
575  elseif ('search' == @$tokens[$next_token])
576  {
577    $page['section'] = 'search';
578    $next_token++;
579
580    preg_match('/(\d+)/', @$tokens[$next_token], $matches);
581    if (!isset($matches[1]))
582    {
583      bad_request('search identifier is missing');
584    }
585    $page['search'] = $matches[1];
586    $next_token++;
587  }
588  elseif ('list' == @$tokens[$next_token])
589  {
590    $page['section'] = 'list';
591    $next_token++;
592
593    $page['list'] = array();
594
595    // No pictures
596    if (empty($tokens[$next_token]))
597    {
598      // Add dummy element list
599      $page['list'][] = -1;
600    }
601    // With pictures list
602    else
603    {
604      if (!preg_match('/^\d+(,\d+)*$/', $tokens[$next_token]))
605      {
606        bad_request('wrong format on list GET parameter');
607      }
608      foreach (explode(',', $tokens[$next_token]) as $image_id)
609      {
610        $page['list'][] = $image_id;
611      }
612    }
613    $next_token++;
614  }
615  return $page;
616}
617
618/**
619 * the reverse of add_well_known_params_in_url
620 * parses start, flat and chronology from url tokens
621*/
622function parse_well_known_params_url($tokens, &$i)
623{
624  $page = array();
625  while (isset($tokens[$i]))
626  {
627    if ( 'flat' == $tokens[$i] )
628    {
629      // indicate a special list of images
630      $page['flat'] = true;
631    }
632    elseif (strpos($tokens[$i], 'created-')===0 or strpos($tokens[$i], 'posted-')===0)
633    {
634      $chronology_tokens = explode('-', $tokens[$i] );
635
636      $page['chronology_field'] = $chronology_tokens[0];
637
638      array_shift($chronology_tokens);
639      $page['chronology_style'] = $chronology_tokens[0];
640
641      array_shift($chronology_tokens);
642      if ( count($chronology_tokens)>0 )
643      {
644        if ('list'==$chronology_tokens[0] or
645            'calendar'==$chronology_tokens[0])
646        {
647          $page['chronology_view'] = $chronology_tokens[0];
648          array_shift($chronology_tokens);
649        }
650        $page['chronology_date'] = $chronology_tokens;
651      }
652    }
653    elseif (preg_match('/^start-(\d+)/', $tokens[$i], $matches))
654    {
655      $page['start'] = $matches[1];
656    }
657    elseif (preg_match('/^startcat-(\d+)/', $tokens[$i], $matches))
658    {
659      $page['startcat'] = $matches[1];
660    }
661    $i++;
662  }
663  return $page;
664}
665
666
667/**
668 * @param id image id
669 * @param what_part string one of 'e' (element), 'r' (representative)
670 */
671function get_action_url($id, $what_part, $download)
672{
673  $params = array(
674        'id' => $id,
675        'part' => $what_part,
676      );
677  if ($download)
678  {
679    $params['download'] = null;
680  }
681 
682  return add_url_params(get_root_url().'action.php', $params);
683}
684
685/*
686 * @param element_info array containing element information from db;
687 * at least 'id', 'path' should be present
688 */
689function get_element_url($element_info)
690{
691  $url = $element_info['path'];
692  if ( !url_is_remote($url) )
693  {
694    $url = embellish_url(get_root_url().$url);
695  }
696  return $url;
697}
698
699
700/**
701 * Indicate to build url with full path
702 *
703 * @param null
704 * @return null
705 */
706function set_make_full_url()
707{
708  global $page;
709
710  if (!isset($page['save_root_path']))
711  {
712    if (isset($page['root_path']))
713    {
714      $page['save_root_path']['path'] = $page['root_path'];
715    }
716    $page['save_root_path']['count'] = 1;
717    $page['root_path'] = get_absolute_root_url();
718  }
719  else
720  {
721    $page['save_root_path']['count'] += 1;
722  }
723}
724
725/**
726 * Restore old parameter to build url with full path
727 *
728 * @param null
729 * @return null
730 */
731function unset_make_full_url()
732{
733  global $page;
734
735  if (isset($page['save_root_path']))
736  {
737    if ($page['save_root_path']['count'] == 1)
738    {
739      if (isset($page['save_root_path']['path']))
740      {
741        $page['root_path'] = $page['save_root_path']['path'];
742      }
743      else
744      {
745        unset($page['root_path']);
746      }
747      unset($page['save_root_path']);
748    }
749    else
750    {
751      $page['save_root_path']['count'] -= 1;
752    }
753  }
754}
755
756/**
757 * Embellish the url argument
758 *
759 * @param $url
760 * @return $url embellished
761 */
762function embellish_url($url)
763{
764  $url = str_replace('/./', '/', $url);
765  while ( ($dotdot = strpos($url, '/../', 1) ) !== false )
766  {
767    $before = strrpos($url, '/', -(strlen($url)-$dotdot+1) );
768    if ($before !== false)
769    {
770      $url = substr_replace($url, '', $before, $dotdot-$before+3);
771    }
772    else
773      break;
774  }
775  return $url;
776}
777
778/**
779 * Returns the 'home page' of this gallery
780 */
781function get_gallery_home_url()
782{
783  global $conf;
784  if (!empty($conf['gallery_url']))
785  {
786    if (url_is_remote($conf['gallery_url']) or $conf['gallery_url'][0]=='/' )
787    {
788      return $conf['gallery_url'];
789    }
790    return get_root_url().$conf['gallery_url'];
791  }
792  else
793  {
794    return make_index_url();
795  }
796}
797
798/**
799 * returns $_SERVER['QUERY_STRING'] whithout keys given in parameters
800 *
801 * @param string[] $rejects
802 * @param boolean $escape escape *&* to *&amp;*
803 * @returns string
804 */
805function get_query_string_diff($rejects=array(), $escape=true)
806{
807  if (empty($_SERVER['QUERY_STRING']))
808  {
809    return '';
810  }
811
812  parse_str($_SERVER['QUERY_STRING'], $vars);
813
814  $vars = array_diff_key($vars, array_flip($rejects));
815 
816  return '?' . http_build_query($vars, '', $escape ? '&amp;' : '&');
817}
818
819/**
820 * returns true if the url is absolute (begins with http)
821 *
822 * @param string $url
823 * @returns boolean
824 */
825function url_is_remote($url)
826{
827  if ( strncmp($url, 'http://', 7)==0
828    or strncmp($url, 'https://', 8)==0 )
829  {
830    return true;
831  }
832  return false;
833}
834
835?>
Note: See TracBrowser for help on using the repository browser.