Dotclear

source: inc/public/lib.urlhandlers.php @ 2585:59b040fa9a75

Revision 2585:59b040fa9a75, 16.7 KB checked in by franck <carnet.franck.paul@…>, 12 years ago (diff)

Allow alternative syntaxes for comments, fixes #1840

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

Sites map