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

Last change on this file since 14952 was 14180, checked in by rvelices, 13 years ago

"home url" is not always absolute with host name + html compaction - through removal of unused attributes, some white spaces ...

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