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

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

nicer urls when used over https

  • 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-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 .= '-'.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            array_push($maybe_permalinks, $tokens[$current_token]);
470          }
471          else
472          {
473            array_push($maybe_permalinks,
474                $maybe_permalinks[count($maybe_permalinks)-1]
475                . '/' . $tokens[$current_token]
476              );
477          }
478          $current_token++;
479        }
480
481        if ( count($maybe_permalinks) )
482        {
483          $cat_id = get_cat_id_from_permalinks($maybe_permalinks, $perma_index);
484          if ( isset($cat_id) )
485          {
486            $next_token += $perma_index+1;
487            $page['category'] = $cat_id;
488            $page['hit_by']['cat_permalink'] = $maybe_permalinks[$perma_index];
489          }
490          else
491          {
492            page_not_found(l10n('Permalink for album not found'));
493          }
494        }
495      }
496    }
497
498    if (isset($page['category']))
499    {
500      $result = get_cat_info($page['category']);
501      if (empty($result))
502      {
503         page_not_found(l10n('Requested album does not exist'));
504      }
505      $page['category']=$result;
506    }
507  }
508  elseif ( 'tags' == @$tokens[$next_token] )
509  {
510    global $conf;
511
512    $page['section'] = 'tags';
513    $page['tags'] = array();
514
515    $next_token++;
516    $i = $next_token;
517
518    $requested_tag_ids = array();
519    $requested_tag_url_names = array();
520
521    while (isset($tokens[$i]))
522    {
523      if (strpos($tokens[$i], 'created-')===0
524           or strpos($tokens[$i], 'posted-')===0
525           or strpos($tokens[$i], 'start-')===0 )
526        break;
527
528      if ( $conf['tag_url_style'] != 'tag' and preg_match('/^(\d+)(?:-(.*)|)$/', $tokens[$i], $matches) )
529      {
530        array_push($requested_tag_ids, $matches[1]);
531      }
532      else
533      {
534        array_push($requested_tag_url_names, $tokens[$i]);
535      }
536      $i++;
537    }
538    $next_token = $i;
539
540    if ( empty($requested_tag_ids) && empty($requested_tag_url_names) )
541    {
542      bad_request('at least one tag required');
543    }
544
545    $page['tags'] = find_tags($requested_tag_ids, $requested_tag_url_names);
546    if ( empty($page['tags']) )
547    {
548      page_not_found(l10n('Requested tag does not exist'), get_root_url().'tags.php' );
549    }
550  }
551  elseif ( 'favorites' == @$tokens[$next_token] )
552  {
553    $page['section'] = 'favorites';
554    $next_token++;
555  }
556  elseif ('most_visited' == @$tokens[$next_token])
557  {
558    $page['section'] = 'most_visited';
559    $next_token++;
560  }
561  elseif ('best_rated' == @$tokens[$next_token])
562  {
563    $page['section'] = 'best_rated';
564    $next_token++;
565  }
566  elseif ('recent_pics' == @$tokens[$next_token])
567  {
568    $page['section'] = 'recent_pics';
569    $next_token++;
570  }
571  elseif ('recent_cats' == @$tokens[$next_token])
572  {
573    $page['section'] = 'recent_cats';
574    $next_token++;
575  }
576  elseif ('search' == @$tokens[$next_token])
577  {
578    $page['section'] = 'search';
579    $next_token++;
580
581    preg_match('/(\d+)/', @$tokens[$next_token], $matches);
582    if (!isset($matches[1]))
583    {
584      bad_request('search identifier is missing');
585    }
586    $page['search'] = $matches[1];
587    $next_token++;
588  }
589  elseif ('list' == @$tokens[$next_token])
590  {
591    $page['section'] = 'list';
592    $next_token++;
593
594    $page['list'] = array();
595
596    // No pictures
597    if (empty($tokens[$next_token]))
598    {
599      // Add dummy element list
600      array_push($page['list'], -1);
601    }
602    // With pictures list
603    else
604    {
605      if (!preg_match('/^\d+(,\d+)*$/', $tokens[$next_token]))
606      {
607        bad_request('wrong format on list GET parameter');
608      }
609      foreach (explode(',', $tokens[$next_token]) as $image_id)
610      {
611        array_push($page['list'], $image_id);
612      }
613    }
614    $next_token++;
615  }
616  return $page;
617}
618
619/**
620 * the reverse of add_well_known_params_in_url
621 * parses start, flat and chronology from url tokens
622*/
623function parse_well_known_params_url($tokens, &$i)
624{
625  $page = array();
626  while (isset($tokens[$i]))
627  {
628    if ( 'flat' == $tokens[$i] )
629    {
630      // indicate a special list of images
631      $page['flat'] = true;
632    }
633    elseif (strpos($tokens[$i], 'created-')===0 or strpos($tokens[$i], 'posted-')===0)
634    {
635      $chronology_tokens = explode('-', $tokens[$i] );
636
637      $page['chronology_field'] = $chronology_tokens[0];
638
639      array_shift($chronology_tokens);
640      $page['chronology_style'] = $chronology_tokens[0];
641
642      array_shift($chronology_tokens);
643      if ( count($chronology_tokens)>0 )
644      {
645        if ('list'==$chronology_tokens[0] or
646            'calendar'==$chronology_tokens[0])
647        {
648          $page['chronology_view'] = $chronology_tokens[0];
649          array_shift($chronology_tokens);
650        }
651        $page['chronology_date'] = $chronology_tokens;
652      }
653    }
654    elseif (preg_match('/^start-(\d+)/', $tokens[$i], $matches))
655    {
656      $page['start'] = $matches[1];
657    }
658    elseif (preg_match('/^startcat-(\d+)/', $tokens[$i], $matches))
659    {
660      $page['startcat'] = $matches[1];
661    }
662    $i++;
663  }
664  return $page;
665}
666
667
668/**
669 * @param id image id
670 * @param what_part string one of 'e' (element), 'r' (representative)
671 */
672function get_action_url($id, $what_part, $download)
673{
674  $params = array(
675        'id' => $id,
676        'part' => $what_part,
677      );
678  if ($download)
679  {
680    $params['download'] = null;
681  }
682 
683  return add_url_params(get_root_url().'action.php', $params);
684}
685
686/*
687 * @param element_info array containing element information from db;
688 * at least 'id', 'path' should be present
689 */
690function get_element_url($element_info)
691{
692  $url = $element_info['path'];
693  if ( !url_is_remote($url) )
694  {
695    $url = embellish_url(get_root_url().$url);
696  }
697  return $url;
698}
699
700
701/**
702 * Indicate to build url with full path
703 *
704 * @param null
705 * @return null
706 */
707function set_make_full_url()
708{
709  global $page;
710
711  if (!isset($page['save_root_path']))
712  {
713    if (isset($page['root_path']))
714    {
715      $page['save_root_path']['path'] = $page['root_path'];
716    }
717    $page['save_root_path']['count'] = 1;
718    $page['root_path'] = get_absolute_root_url();
719  }
720  else
721  {
722    $page['save_root_path']['count'] += 1;
723  }
724}
725
726/**
727 * Restore old parameter to build url with full path
728 *
729 * @param null
730 * @return null
731 */
732function unset_make_full_url()
733{
734  global $page;
735
736  if (isset($page['save_root_path']))
737  {
738    if ($page['save_root_path']['count'] == 1)
739    {
740      if (isset($page['save_root_path']['path']))
741      {
742        $page['root_path'] = $page['save_root_path']['path'];
743      }
744      else
745      {
746        unset($page['root_path']);
747      }
748      unset($page['save_root_path']);
749    }
750    else
751    {
752      $page['save_root_path']['count'] -= 1;
753    }
754  }
755}
756
757/**
758 * Embellish the url argument
759 *
760 * @param $url
761 * @return $url embellished
762 */
763function embellish_url($url)
764{
765  $url = str_replace('/./', '/', $url);
766  while ( ($dotdot = strpos($url, '/../', 1) ) !== false )
767  {
768    $before = strrpos($url, '/', -(strlen($url)-$dotdot+1) );
769    if ($before !== false)
770    {
771      $url = substr_replace($url, '', $before, $dotdot-$before+3);
772    }
773    else
774      break;
775  }
776  return $url;
777}
778
779/**
780 * Returns the 'home page' of this gallery
781 */
782function get_gallery_home_url()
783{
784  global $conf;
785  if (!empty($conf['gallery_url']))
786  {
787    if (url_is_remote($conf['gallery_url']) or $conf['gallery_url'][0]=='/' )
788    {
789      return $conf['gallery_url'];
790    }
791    return get_root_url().$conf['gallery_url'];
792  }
793  else
794  {
795    return make_index_url();
796  }
797}
798?>
Note: See TracBrowser for help on using the repository browser.