Dotclear

source: inc/public/lib.urlhandlers.php @ 878:8e606f8cf38c

Revision 878:8e606f8cf38c, 12.1 KB checked in by Dsls <dsls@…>, 13 years ago (diff)

Multiple DC_PLUGINS_ROOT paths support in plugin urlhandler.

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14class dcUrlHandlers extends urlHandler
15{
16     public $args;
17     
18     public function getURLFor($type,$value='') {
19          $core =& $GLOBALS['core'];
20          $url = $core->callBehavior("publicGetURLFor",$type,$value);
21          if (!$url) {
22               $url = $this->getBase($type);
23               if ($value) {
24                    if ($url) {
25                         $url .= '/';
26                    }
27                    $url .= $value;
28               }
29          }
30          return $url;
31     }
32     
33     public function register($type,$url,$representation,$handler)
34     {
35          $core =& $GLOBALS['core'];
36          $t = new ArrayObject(array($type,$url,$representation,$handler));
37          $core->callBehavior("publicRegisterURL",$t);
38          parent::register($t[0],$t[1],$t[2],$t[3]);
39     }
40     
41     public static function p404()
42     {
43          throw new Exception ("Page not found",404);
44     }
45     
46     public static function default404($args,$type,$e)
47     {
48          if ($e->getCode() != 404) {
49               throw $e;
50          }
51          $_ctx =& $GLOBALS['_ctx'];
52          $core = $GLOBALS['core'];
53         
54          header('Content-Type: text/html; charset=UTF-8');
55          http::head(404,'Not Found');
56          $core->url->type = '404';
57          $_ctx->current_tpl = '404.html';
58          $_ctx->content_type = 'text/html';
59         
60          echo $core->tpl->getData($_ctx->current_tpl);
61         
62          # --BEHAVIOR-- publicAfterDocument
63          $core->callBehavior('publicAfterDocument',$core);
64          exit;
65     }
66     
67     protected static function getPageNumber(&$args)
68     {
69          if (preg_match('#(^|/)page/([0-9]+)$#',$args,$m)) {
70               $n = (integer) $m[2];
71               if ($n > 0) {
72                    $args = preg_replace('#(^|/)page/([0-9]+)$#','',$args);
73                    return $n;
74               }
75          }
76         
77          return false;
78     }
79     
80     protected static function serveDocument($tpl,$content_type='text/html',$http_cache=true,$http_etag=true)
81     {
82          $_ctx =& $GLOBALS['_ctx'];
83          $core =& $GLOBALS['core'];
84         
85          if ($_ctx->nb_entry_per_page === null) {
86               $_ctx->nb_entry_per_page = $core->blog->settings->system->nb_post_per_page;
87          }
88         
89          $tpl_file = $core->tpl->getFilePath($tpl);
90         
91          if (!$tpl_file) {
92               throw new Exception('Unable to find template ');
93          }
94         
95          $result = new ArrayObject;
96         
97          $_ctx->current_tpl = $tpl;
98          $_ctx->content_type = $content_type;
99          $_ctx->http_cache = $http_cache;
100          $_ctx->http_etag = $http_etag;
101          $core->callBehavior('urlHandlerBeforeGetData',$_ctx);
102         
103          if ($_ctx->http_cache) {
104               $GLOBALS['mod_files'][] = $tpl_file;
105               http::cache($GLOBALS['mod_files'],$GLOBALS['mod_ts']);
106          }
107
108          header('Content-Type: '.$_ctx->content_type.'; charset=UTF-8');
109          $result['content'] = $core->tpl->getData($_ctx->current_tpl);
110          $result['content_type'] = $_ctx->content_type;
111          $result['tpl'] = $_ctx->current_tpl;
112          $result['blogupddt'] = $core->blog->upddt;
113         
114          # --BEHAVIOR-- urlHandlerServeDocument
115          $core->callBehavior('urlHandlerServeDocument',$result);
116         
117          if ($_ctx->http_cache && $_ctx->http_etag) {
118               http::etag($result['content'],http::getSelfURI());
119          }
120          echo $result['content'];
121     }
122     
123     public function getDocument()
124     {
125          $core =& $GLOBALS['core'];
126         
127          $type = $args = '';
128         
129          if ($this->mode == 'path_info')
130          {
131               $part = substr($_SERVER['PATH_INFO'],1);
132          }
133          else
134          {
135               $part = '';
136               
137               $qs = $this->parseQueryString();
138               
139               # Recreates some _GET and _REQUEST pairs
140               if (!empty($qs))
141               {
142                    foreach ($_GET as $k => $v) {
143                         if (isset($_REQUEST[$k])) {
144                              unset($_REQUEST[$k]);
145                         }
146                    }
147                    $_GET = $qs;
148                    $_REQUEST = array_merge($qs,$_REQUEST);
149                   
150                    list($k,$v) = each($qs);
151                    if ($v === null) {
152                         $part = $k;
153                         unset($_GET[$k]);
154                         unset($_REQUEST[$k]);
155                    }
156               }
157          }
158         
159          $_SERVER['URL_REQUEST_PART'] = $part;
160         
161          $this->getArgs($part,$type,$this->args);
162         
163          # --BEHAVIOR-- urlHandlerGetArgsDocument
164          $core->callBehavior('urlHandlerGetArgsDocument',$this);
165         
166          if (!$type)
167          {
168               $this->type = 'default';
169               $this->callDefaultHandler($this->args);
170          }
171          else
172          {
173               $this->type = $type;
174               $this->callHandler($type,$this->args);
175          }
176     }
177     
178     public static function home($args)
179     {
180          $n = self::getPageNumber($args);
181         
182          if ($args && !$n)
183          {
184               # "Then specified URL went unrecognized by all URL handlers and
185               # defaults to the home page, but is not a page number.
186               self::p404();
187          }
188          else
189          {
190               $core =& $GLOBALS['core'];
191               
192               if ($n) {
193                    $GLOBALS['_page_number'] = $n;
194                    $core->url->type = $n > 1 ? 'default-page' : 'default';
195               }
196               
197               if (empty($_GET['q'])) {
198                    self::serveDocument('home.html');
199                    $core->blog->publishScheduledEntries();
200               } else {
201                    self::search();
202               }
203          }
204     }
205     
206     public static function search()
207     {
208          $_ctx =& $GLOBALS['_ctx'];
209          $core =& $GLOBALS['core'];
210         
211          $core->url->type='search';
212         
213          $GLOBALS['_search'] = !empty($_GET['q']) ? rawurldecode($_GET['q']) : '';
214          if ($GLOBALS['_search']) {
215               $params = new ArrayObject(array('search' => $GLOBALS['_search']));
216               $core->callBehavior('publicBeforeSearchCount',$params);
217               $GLOBALS['_search_count'] = $core->blog->getPosts($params,true)->f(0);
218          }
219         
220          self::serveDocument('search.html');
221     }
222     
223     public static function lang($args)
224     {
225          $_ctx =& $GLOBALS['_ctx'];
226          $core =& $GLOBALS['core'];
227         
228          $n = self::getPageNumber($args);
229          $params = new ArrayObject(array(
230               'lang' => $args));
231         
232          $core->callBehavior('publicLangBeforeGetLangs',$params,$args);
233         
234          $_ctx->langs = $core->blog->getLangs($params);
235         
236          if ($_ctx->langs->isEmpty()) {
237               # The specified language does not exist.
238               self::p404();
239          }
240          else
241          {
242               if ($n) {
243                    $GLOBALS['_page_number'] = $n;
244               }
245               $_ctx->cur_lang = $args;
246               self::home(null);
247          }
248     }
249     
250     public static function archive($args)
251     {
252          $_ctx =& $GLOBALS['_ctx'];
253          $core =& $GLOBALS['core'];
254         
255          $year = $month = $cat_url = null;
256          # Nothing or year and month
257          if ($args == '')
258          {
259               self::serveDocument('archive.html');
260          }
261          elseif (preg_match('|^/([0-9]{4})/([0-9]{2})$|',$args,$m))
262          {
263               $params = new ArrayObject(array(
264                    'year' => $m[1],
265                    'month' => $m[2],
266                    'type' => 'month'));
267               
268               $core->callBehavior('publicArchiveBeforeGetDates',$params,$args);
269               
270               $_ctx->archives = $core->blog->getDates($params);
271               
272               if ($_ctx->archives->isEmpty()) {
273                    # There is no entries for the specified period.
274                    self::p404();
275               }
276               else
277               {
278                    self::serveDocument('archive_month.html');
279               }
280          }
281          else {
282               # The specified URL is not a date.
283               self::p404();
284          }
285     }
286     
287     public static function post($args)
288     {
289          if ($args == '') {
290               # No entry was specified.
291               self::p404();
292          }
293          else
294          {
295               $_ctx =& $GLOBALS['_ctx'];
296               $core =& $GLOBALS['core'];
297               
298               $core->blog->withoutPassword(false);
299               
300               $params = new ArrayObject(array(
301                    'post_url' => $args));
302               
303               $core->callBehavior('publicPostBeforeGetPosts',$params,$args);
304
305               $_ctx->posts = $core->blog->getPosts($params);
306               
307               $core->blog->withoutPassword(true);
308               
309               if ($_ctx->posts->isEmpty())
310               {
311                    # The specified entry does not exist.
312                    self::p404();
313               }
314               else
315               {
316                    $post_id = $_ctx->posts->post_id;
317                    # The entry
318                    self::serveDocument('post.html');
319               }
320          }
321     }
322     
323     public static function preview($args)
324     {
325          $core = $GLOBALS['core'];
326          $_ctx = $GLOBALS['_ctx'];
327         
328          if (!preg_match('#^(.+?)/([0-9a-z]{40})/(.+?)$#',$args,$m)) {
329               # The specified Preview URL is malformed.
330               self::p404();
331          }
332          else
333          {
334               $user_id = $m[1];
335               $user_key = $m[2];
336               $post_url = $m[3];
337               if (!$core->auth->checkUser($user_id,null,$user_key)) {
338                    # The user has no access to the entry.
339                    self::p404();
340               }
341               else
342               {
343                    $_ctx->preview = true;
344                    self::post($post_url);
345               }
346          }
347     }
348     
349     public static function feed($args)
350     {
351          $type = null;
352          $cat_url = false;
353          $post_id = null;
354          $subtitle = '';
355         
356          $mime = 'application/xml';
357         
358          $_ctx =& $GLOBALS['_ctx'];
359          $core =& $GLOBALS['core'];
360         
361          if (preg_match('!^([a-z]{2}(-[a-z]{2})?)/(.*)$!',$args,$m)) {
362               $params = new ArrayObject(array('lang' => $m[1]));
363               
364               $args = $m[3];
365               
366               $core->callBehavior('publicFeedBeforeGetLangs',$params,$args);
367               
368               $_ctx->langs = $core->blog->getLangs($params);
369               
370               if ($_ctx->langs->isEmpty()) {
371                    # The specified language does not exist.
372                    self::p404();
373                    return;
374               } else {
375                    $_ctx->cur_lang = $m[1];
376               }
377          }
378         
379          if (preg_match('#^rss2/xslt$#',$args,$m))
380          {
381               # RSS XSLT stylesheet
382               self::serveDocument('rss2.xsl','text/xml');
383               return;
384          }
385          elseif (preg_match('#^(?:category/(.+)/)?(atom|rss2)(/comments)?$#',$args,$m))
386          {
387               # All posts or comments feed
388               $type = $m[2];
389               if (!empty($m[1])) {
390                    $cat_url = $m[1];
391               }
392          }
393          else
394          {
395               # The specified Feed URL is malformed.
396               self::p404();
397               return;
398          }
399         
400          if ($cat_url)
401          {
402               $params = new ArrayObject(array(
403                    'cat_url' => $cat_url,
404                    'post_type' => 'post'));
405               
406               $core->callBehavior('publicFeedBeforeGetCategories',$params,$args);
407               
408               $_ctx->categories = $core->blog->getCategories($params);
409               
410               if ($_ctx->categories->isEmpty()) {
411                    # The specified category does no exist.
412                    self::p404();
413                    return;
414               }
415               
416               $subtitle = ' - '.$_ctx->categories->cat_title;
417          }
418          elseif ($post_id)
419          {
420               $params = new ArrayObject(array(
421                    'post_id' => $post_id,
422                    'post_type' => ''));
423                   
424               $core->callBehavior('publicFeedBeforeGetPosts',$params,$args);
425               
426               $_ctx->posts = $core->blog->getPosts($params);
427               
428               if ($_ctx->posts->isEmpty()) {
429                    # The specified post does not exist.
430                    self::p404();
431                    return;
432               }
433               
434               $subtitle = ' - '.$_ctx->posts->post_title;
435          }
436         
437          $tpl = $type;
438          $_ctx->nb_entry_per_page = $core->blog->settings->system->nb_post_per_feed;
439          $_ctx->short_feed_items = $core->blog->settings->system->short_feed_items;
440          $tpl .= '.xml';
441         
442          if ($type == 'atom') {
443               $mime = 'application/atom+xml';
444          }
445         
446          $_ctx->feed_subtitle = $subtitle;
447         
448          header('X-Robots-Tag: '.context::robotsPolicy($core->blog->settings->system->robots_policy,''));
449          self::serveDocument($tpl,$mime);
450          if (!$comments && !$cat_url) {
451               $core->blog->publishScheduledEntries();
452          }
453     }
454     
455     public static function rsd($args)
456     {
457          $core =& $GLOBALS['core'];
458          http::cache($GLOBALS['mod_files'],$GLOBALS['mod_ts']);
459         
460          header('Content-Type: text/xml; charset=UTF-8');
461          echo
462          '<?xml version="1.0" encoding="UTF-8"?>'."\n".
463          '<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">'."\n".
464          "<service>\n".
465          "  <engineName>Dotclear</engineName>\n".
466          "  <engineLink>http://www.dotclear.org/</engineLink>\n".
467          '  <homePageLink>'.html::escapeHTML($core->blog->url)."</homePageLink>\n";
468         
469          if ($core->blog->settings->system->enable_xmlrpc)
470          {
471               $u = sprintf(DC_XMLRPC_URL,$core->blog->url,$core->blog->id);
472               
473               echo
474               "  <apis>\n".
475               '    <api name="WordPress" blogID="1" preferred="true" apiLink="'.$u.'"/>'."\n".
476               '    <api name="Movable Type" blogID="1" preferred="false" apiLink="'.$u.'"/>'."\n".
477               '    <api name="MetaWeblog" blogID="1" preferred="false" apiLink="'.$u.'"/>'."\n".
478               '    <api name="Blogger" blogID="1" preferred="false" apiLink="'.$u.'"/>'."\n".
479               "  </apis>\n";
480          }
481         
482          echo
483          "</service>\n".
484          "</rsd>\n";
485     }
486     
487     public static function xmlrpc($args)
488     {
489          $core =& $GLOBALS['core'];
490          $blog_id = preg_replace('#^([^/]*).*#','$1',$args);
491          $server = new dcXmlRpc($core,$blog_id);
492          $server->serve();
493     }
494     
495     public static function pluginInclude($args)
496     {
497          preg_match('#^([^/]+)/(.+)$#',$args,$m);
498          if (count($m) < 3) {
499               self::p404();
500               exit;
501          }
502          $p = $m[1];
503          $file = $m[2];
504          $allow_types = array('png','jpg','jpeg','gif','css','js','swf');
505          $rel_file = path::clean('public/'.$file);
506          $paths = explode(PATH_SEPARATOR, DC_PLUGINS_ROOT);
507          $p_dir = '';
508          foreach ($paths as $path) {
509               if (is_dir($path.'/'.$p)) {
510                    $p_dir = $path.'/'.$p;
511                    break;
512               }
513          }
514          $pf = $p_dir.'/'.$rel_file;
515          if ($p_dir == '' ||
516               !$GLOBALS['core']->plugins->moduleExists($p) ||
517               $pf === false || !is_file($pf) || !is_readable($pf)) {
518               self::p404();
519               exit;
520          }
521
522          if (!in_array(files::getExtension($pf),$allow_types)) {
523               header('Content-Type: text/plain');
524               http::head(404,'Not Found');
525               exit;
526          }
527
528          http::$cache_max_age = 7200;
529          http::cache(array_merge(array($pf),get_included_files()));
530
531          header('Content-Type: '.files::getMimeType($pf));
532          header('Content-Length: '.filesize($pf));
533          readfile($pf);
534          exit;
535
536     }
537}
538?>
Note: See TracBrowser for help on using the repository browser.

Sites map