Dotclear

source: inc/public/lib.urlhandlers.php @ 1128:9e868a6c21c3

Revision 1128:9e868a6c21c3, 16.4 KB checked in by JcDenis, 11 years ago (diff)

Yet another more flexible method to create template environment and context.

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          // Break public template here for now
90          // just to check if template engine is well loaded.
91          $core->tpl->display($tpl.'.twig');
92          // To be continued...
93         
94          $tpl_file = $core->tpl->getFilePath($tpl);
95         
96          if (!$tpl_file) {
97               throw new Exception('Unable to find template ');
98          }
99         
100          $result = new ArrayObject;
101         
102          $_ctx->current_tpl = $tpl;
103          $_ctx->content_type = $content_type;
104          $_ctx->http_cache = $http_cache;
105          $_ctx->http_etag = $http_etag;
106          $core->callBehavior('urlHandlerBeforeGetData',$_ctx);
107         
108          if ($_ctx->http_cache) {
109               $GLOBALS['mod_files'][] = $tpl_file;
110               http::cache($GLOBALS['mod_files'],$GLOBALS['mod_ts']);
111          }
112
113          header('Content-Type: '.$_ctx->content_type.'; charset=UTF-8');
114          $result['content'] = $core->tpl->getData($_ctx->current_tpl);
115          $result['content_type'] = $_ctx->content_type;
116          $result['tpl'] = $_ctx->current_tpl;
117          $result['blogupddt'] = $core->blog->upddt;
118         
119          # --BEHAVIOR-- urlHandlerServeDocument
120          $core->callBehavior('urlHandlerServeDocument',$result);
121         
122          if ($_ctx->http_cache && $_ctx->http_etag) {
123               http::etag($result['content'],http::getSelfURI());
124          }
125          echo $result['content'];
126     }
127     
128     public function getDocument()
129     {
130          $core =& $GLOBALS['core'];
131         
132          $type = $args = '';
133         
134          if ($this->mode == 'path_info')
135          {
136               $part = substr($_SERVER['PATH_INFO'],1);
137          }
138          else
139          {
140               $part = '';
141               
142               $qs = $this->parseQueryString();
143               
144               # Recreates some _GET and _REQUEST pairs
145               if (!empty($qs))
146               {
147                    foreach ($_GET as $k => $v) {
148                         if (isset($_REQUEST[$k])) {
149                              unset($_REQUEST[$k]);
150                         }
151                    }
152                    $_GET = $qs;
153                    $_REQUEST = array_merge($qs,$_REQUEST);
154                   
155                    list($k,$v) = each($qs);
156                    if ($v === null) {
157                         $part = $k;
158                         unset($_GET[$k]);
159                         unset($_REQUEST[$k]);
160                    }
161               }
162          }
163         
164          $_SERVER['URL_REQUEST_PART'] = $part;
165         
166          $this->getArgs($part,$type,$this->args);
167         
168          # --BEHAVIOR-- urlHandlerGetArgsDocument
169          $core->callBehavior('urlHandlerGetArgsDocument',$this);
170         
171          if (!$type)
172          {
173               $this->type = 'default';
174               $this->callDefaultHandler($this->args);
175          }
176          else
177          {
178               $this->type = $type;
179               $this->callHandler($type,$this->args);
180          }
181     }
182     
183     public static function home($args)
184     {
185          $n = self::getPageNumber($args);
186         
187          if ($args && !$n)
188          {
189               # "Then specified URL went unrecognized by all URL handlers and
190               # defaults to the home page, but is not a page number.
191               self::p404();
192          }
193          else
194          {
195               $core =& $GLOBALS['core'];
196               
197               if ($n) {
198                    $GLOBALS['_page_number'] = $n;
199                    $core->url->type = $n > 1 ? 'default-page' : 'default';
200               }
201               
202               if (empty($_GET['q'])) {
203                    self::serveDocument('home.html');
204                    $core->blog->publishScheduledEntries();
205               } else {
206                    self::search();
207               }
208          }
209     }
210     
211     public static function search()
212     {
213          $_ctx =& $GLOBALS['_ctx'];
214          $core =& $GLOBALS['core'];
215         
216          $core->url->type='search';
217         
218          $GLOBALS['_search'] = !empty($_GET['q']) ? rawurldecode($_GET['q']) : '';
219          if ($GLOBALS['_search']) {
220               $params = new ArrayObject(array('search' => $GLOBALS['_search']));
221               $core->callBehavior('publicBeforeSearchCount',$params);
222               $GLOBALS['_search_count'] = $core->blog->getPosts($params,true)->f(0);
223          }
224         
225          self::serveDocument('search.html');
226     }
227     
228     public static function lang($args)
229     {
230          $_ctx =& $GLOBALS['_ctx'];
231          $core =& $GLOBALS['core'];
232         
233          $n = self::getPageNumber($args);
234          $params = new ArrayObject(array(
235               'lang' => $args));
236         
237          $core->callBehavior('publicLangBeforeGetLangs',$params,$args);
238         
239          $_ctx->langs = $core->blog->getLangs($params);
240         
241          if ($_ctx->langs->isEmpty()) {
242               # The specified language does not exist.
243               self::p404();
244          }
245          else
246          {
247               if ($n) {
248                    $GLOBALS['_page_number'] = $n;
249               }
250               $_ctx->cur_lang = $args;
251               self::home(null);
252          }
253     }
254     
255     public static function category($args)
256     {
257          $_ctx =& $GLOBALS['_ctx'];
258          $core =& $GLOBALS['core'];
259         
260          $n = self::getPageNumber($args);
261         
262          if ($args == '' && !$n) {
263               # No category was specified.
264               self::p404();
265          }
266          else
267          {
268               $params = new ArrayObject(array(
269                    'cat_url' => $args,
270                    'post_type' => 'post'));
271               
272               $core->callBehavior('publicCategoryBeforeGetCategories',$params,$args);
273               
274               $_ctx->categories = $core->blog->getCategories($params);
275               
276               if ($_ctx->categories->isEmpty()) {
277                    # The specified category does no exist.
278                    self::p404();
279               }
280               else
281               {
282                    if ($n) {
283                         $GLOBALS['_page_number'] = $n;
284                    }
285                    self::serveDocument('category.html');
286               }
287          }
288     }
289     
290     public static function archive($args)
291     {
292          $_ctx =& $GLOBALS['_ctx'];
293          $core =& $GLOBALS['core'];
294         
295          $year = $month = $cat_url = null;
296          # Nothing or year and month
297          if ($args == '')
298          {
299               self::serveDocument('archive.html');
300          }
301          elseif (preg_match('|^/([0-9]{4})/([0-9]{2})$|',$args,$m))
302          {
303               $params = new ArrayObject(array(
304                    'year' => $m[1],
305                    'month' => $m[2],
306                    'type' => 'month'));
307               
308               $core->callBehavior('publicArchiveBeforeGetDates',$params,$args);
309               
310               $_ctx->archives = $core->blog->getDates($params);
311               
312               if ($_ctx->archives->isEmpty()) {
313                    # There is no entries for the specified period.
314                    self::p404();
315               }
316               else
317               {
318                    self::serveDocument('archive_month.html');
319               }
320          }
321          else {
322               # The specified URL is not a date.
323               self::p404();
324          }
325     }
326     
327     public static function post($args)
328     {
329          if ($args == '') {
330               # No entry was specified.
331               self::p404();
332          }
333          else
334          {
335               $_ctx =& $GLOBALS['_ctx'];
336               $core =& $GLOBALS['core'];
337               
338               $core->blog->withoutPassword(false);
339               
340               $params = new ArrayObject(array(
341                    'post_url' => $args));
342               
343               $core->callBehavior('publicPostBeforeGetPosts',$params,$args);
344
345               $_ctx->posts = $core->blog->getPosts($params);
346               
347               $_ctx->comment_preview = new ArrayObject();
348               $_ctx->comment_preview['content'] = '';
349               $_ctx->comment_preview['rawcontent'] = '';
350               $_ctx->comment_preview['name'] = '';
351               $_ctx->comment_preview['mail'] = '';
352               $_ctx->comment_preview['site'] = '';
353               $_ctx->comment_preview['preview'] = false;
354               $_ctx->comment_preview['remember'] = false;
355               
356               $core->blog->withoutPassword(true);
357               
358               if ($_ctx->posts->isEmpty())
359               {
360                    # The specified entry does not exist.
361                    self::p404();
362               }
363               else
364               {
365                    $post_id = $_ctx->posts->post_id;
366                    $post_password = $_ctx->posts->post_password;
367                   
368                    # Password protected entry
369                    if ($post_password != '' && !$_ctx->preview)
370                    {
371                         # Get passwords cookie
372                         if (isset($_COOKIE['dc_passwd'])) {
373                              $pwd_cookie = unserialize($_COOKIE['dc_passwd']);
374                         } else {
375                              $pwd_cookie = array();
376                         }
377                         
378                         # Check for match
379                         if ((!empty($_POST['password']) && $_POST['password'] == $post_password)
380                         || (isset($pwd_cookie[$post_id]) && $pwd_cookie[$post_id] == $post_password))
381                         {
382                              $pwd_cookie[$post_id] = $post_password;
383                              setcookie('dc_passwd',serialize($pwd_cookie),0,'/');
384                         }
385                         else
386                         {
387                              self::serveDocument('password-form.html','text/html',false);
388                              return;
389                         }
390                    }
391                   
392                    $post_comment =
393                         isset($_POST['c_name']) && isset($_POST['c_mail']) &&
394                         isset($_POST['c_site']) && isset($_POST['c_content']) &&
395                         $_ctx->posts->commentsActive();
396                   
397                    # Posting a comment
398                    if ($post_comment)
399                    {
400                         # Spam trap
401                         if (!empty($_POST['f_mail'])) {
402                              http::head(412,'Precondition Failed');
403                              header('Content-Type: text/plain');
404                              echo "So Long, and Thanks For All the Fish";
405                              # Exits immediately the application to preserve the server.
406                              exit;
407                         }
408                         
409                         $name = $_POST['c_name'];
410                         $mail = $_POST['c_mail'];
411                         $site = $_POST['c_site'];
412                         $content = $_POST['c_content'];
413                         $preview = !empty($_POST['preview']);
414                         
415                         if ($content != '')
416                         {
417                              if ($core->blog->settings->system->wiki_comments) {
418                                   $core->initWikiComment();
419                              } else {
420                                   $core->initWikiSimpleComment();
421                              }
422                              $content = $core->wikiTransform($content);
423                              $content = $core->HTMLfilter($content);
424                         }
425                         
426                         $_ctx->comment_preview['content'] = $content;
427                         $_ctx->comment_preview['rawcontent'] = $_POST['c_content'];
428                         $_ctx->comment_preview['name'] = $name;
429                         $_ctx->comment_preview['mail'] = $mail;
430                         $_ctx->comment_preview['site'] = $site;
431                         
432                         if ($preview)
433                         {
434                              # --BEHAVIOR-- publicBeforeCommentPreview
435                              $core->callBehavior('publicBeforeCommentPreview',$_ctx->comment_preview);
436                             
437                              $_ctx->comment_preview['preview'] = true;
438                         }
439                         else
440                         {
441                              # Post the comment
442                              $cur = $core->con->openCursor($core->prefix.'comment');
443                              $cur->comment_author = $name;
444                              $cur->comment_site = html::clean($site);
445                              $cur->comment_email = html::clean($mail);
446                              $cur->comment_content = $content;
447                              $cur->post_id = $_ctx->posts->post_id;
448                              $cur->comment_status = $core->blog->settings->system->comments_pub ? 1 : -1;
449                              $cur->comment_ip = http::realIP();
450                             
451                              $redir = $_ctx->posts->getURL();
452                              $redir .= $core->blog->settings->system->url_scan == 'query_string' ? '&' : '?';
453                             
454                              try
455                              {
456                                   if (!text::isEmail($cur->comment_email)) {
457                                        throw new Exception(__('You must provide a valid email address.'));
458                                   }
459                                   
460                                   # --BEHAVIOR-- publicBeforeCommentCreate
461                                   $core->callBehavior('publicBeforeCommentCreate',$cur);
462                                   if ($cur->post_id) {                         
463                                        $comment_id = $core->blog->addComment($cur);
464                                       
465                                        # --BEHAVIOR-- publicAfterCommentCreate
466                                        $core->callBehavior('publicAfterCommentCreate',$cur,$comment_id);
467                                   }
468                                   
469                                   if ($cur->comment_status == 1) {
470                                        $redir_arg = 'pub=1';
471                                   } else {
472                                        $redir_arg = 'pub=0';
473                                   }
474                                   
475                                   header('Location: '.$redir.$redir_arg);
476                              }
477                              catch (Exception $e)
478                              {
479                                   $_ctx->form_error = $e->getMessage();
480                                   $_ctx->form_error;
481                              }
482                         }
483                    }
484                   
485                    # The entry
486                    self::serveDocument('post.html');
487               }
488          }
489     }
490     
491     public static function preview($args)
492     {
493          $core = $GLOBALS['core'];
494          $_ctx = $GLOBALS['_ctx'];
495         
496          if (!preg_match('#^(.+?)/([0-9a-z]{40})/(.+?)$#',$args,$m)) {
497               # The specified Preview URL is malformed.
498               self::p404();
499          }
500          else
501          {
502               $user_id = $m[1];
503               $user_key = $m[2];
504               $post_url = $m[3];
505               if (!$core->auth->checkUser($user_id,null,$user_key)) {
506                    # The user has no access to the entry.
507                    self::p404();
508               }
509               else
510               {
511                    $_ctx->preview = true;
512                    self::post($post_url);
513               }
514          }
515     }
516     
517     public static function feed($args)
518     {
519          $type = null;
520          $comments = false;
521          $cat_url = false;
522          $post_id = null;
523          $subtitle = '';
524         
525          $mime = 'application/xml';
526         
527          $_ctx =& $GLOBALS['_ctx'];
528          $core =& $GLOBALS['core'];
529         
530          if (preg_match('!^([a-z]{2}(-[a-z]{2})?)/(.*)$!',$args,$m)) {
531               $params = new ArrayObject(array('lang' => $m[1]));
532               
533               $args = $m[3];
534               
535               $core->callBehavior('publicFeedBeforeGetLangs',$params,$args);
536               
537               $_ctx->langs = $core->blog->getLangs($params);
538               
539               if ($_ctx->langs->isEmpty()) {
540                    # The specified language does not exist.
541                    self::p404();
542                    return;
543               } else {
544                    $_ctx->cur_lang = $m[1];
545               }
546          }
547         
548          if (preg_match('#^rss2/xslt$#',$args,$m))
549          {
550               # RSS XSLT stylesheet
551               self::serveDocument('rss2.xsl','text/xml');
552               return;
553          }
554          elseif (preg_match('#^(atom|rss2)/comments/([0-9]+)$#',$args,$m))
555          {
556               # Post comments feed
557               $type = $m[1];
558               $comments = true;
559               $post_id = (integer) $m[2];
560          }
561          elseif (preg_match('#^(?:category/(.+)/)?(atom|rss2)(/comments)?$#',$args,$m))
562          {
563               # All posts or comments feed
564               $type = $m[2];
565               $comments = !empty($m[3]);
566               if (!empty($m[1])) {
567                    $cat_url = $m[1];
568               }
569          }
570          else
571          {
572               # The specified Feed URL is malformed.
573               self::p404();
574               return;
575          }
576         
577          if ($cat_url)
578          {
579               $params = new ArrayObject(array(
580                    'cat_url' => $cat_url,
581                    'post_type' => 'post'));
582               
583               $core->callBehavior('publicFeedBeforeGetCategories',$params,$args);
584               
585               $_ctx->categories = $core->blog->getCategories($params);
586               
587               if ($_ctx->categories->isEmpty()) {
588                    # The specified category does no exist.
589                    self::p404();
590                    return;
591               }
592               
593               $subtitle = ' - '.$_ctx->categories->cat_title;
594          }
595          elseif ($post_id)
596          {
597               $params = new ArrayObject(array(
598                    'post_id' => $post_id,
599                    'post_type' => ''));
600                   
601               $core->callBehavior('publicFeedBeforeGetPosts',$params,$args);
602               
603               $_ctx->posts = $core->blog->getPosts($params);
604               
605               if ($_ctx->posts->isEmpty()) {
606                    # The specified post does not exist.
607                    self::p404();
608                    return;
609               }
610               
611               $subtitle = ' - '.$_ctx->posts->post_title;
612          }
613         
614          $tpl = $type;
615          if ($comments) {
616               $tpl .= '-comments';
617               $_ctx->nb_comment_per_page = $core->blog->settings->system->nb_comment_per_feed;
618          } else {
619               $_ctx->nb_entry_per_page = $core->blog->settings->system->nb_post_per_feed;
620               $_ctx->short_feed_items = $core->blog->settings->system->short_feed_items;
621          }
622          $tpl .= '.xml';
623         
624          if ($type == 'atom') {
625               $mime = 'application/atom+xml';
626          }
627         
628          $_ctx->feed_subtitle = $subtitle;
629         
630          header('X-Robots-Tag: '.context::robotsPolicy($core->blog->settings->system->robots_policy,''));
631          self::serveDocument($tpl,$mime);
632          if (!$comments && !$cat_url) {
633               $core->blog->publishScheduledEntries();
634          }
635     }
636     
637     public static function trackback($args)
638     {
639          if (!preg_match('/^[0-9]+$/',$args)) {
640               # The specified trackback URL is not an number
641               self::p404();
642          } else {
643               $tb = new dcTrackback($GLOBALS['core']);
644               $tb->receive($args);
645          }
646     }
647     
648     public static function rsd($args)
649     {
650          $core =& $GLOBALS['core'];
651          http::cache($GLOBALS['mod_files'],$GLOBALS['mod_ts']);
652         
653          header('Content-Type: text/xml; charset=UTF-8');
654          echo
655          '<?xml version="1.0" encoding="UTF-8"?>'."\n".
656          '<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">'."\n".
657          "<service>\n".
658          "  <engineName>Dotclear</engineName>\n".
659          "  <engineLink>http://www.dotclear.org/</engineLink>\n".
660          '  <homePageLink>'.html::escapeHTML($core->blog->url)."</homePageLink>\n";
661         
662          if ($core->blog->settings->system->enable_xmlrpc)
663          {
664               $u = sprintf(DC_XMLRPC_URL,$core->blog->url,$core->blog->id);
665               
666               echo
667               "  <apis>\n".
668               '    <api name="WordPress" blogID="1" preferred="true" apiLink="'.$u.'"/>'."\n".
669               '    <api name="Movable Type" blogID="1" preferred="false" apiLink="'.$u.'"/>'."\n".
670               '    <api name="MetaWeblog" blogID="1" preferred="false" apiLink="'.$u.'"/>'."\n".
671               '    <api name="Blogger" blogID="1" preferred="false" apiLink="'.$u.'"/>'."\n".
672               "  </apis>\n";
673          }
674         
675          echo
676          "</service>\n".
677          "</rsd>\n";
678     }
679     
680     public static function xmlrpc($args)
681     {
682          $core =& $GLOBALS['core'];
683          $blog_id = preg_replace('#^([^/]*).*#','$1',$args);
684          $server = new dcXmlRpc($core,$blog_id);
685          $server->serve();
686     }
687}
688?>
Note: See TracBrowser for help on using the repository browser.

Sites map