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

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