]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/UnfoldSubpages.php
Test 'limit' argument is numeric to avoid SQL injection
[SourceForge/phpwiki.git] / lib / plugin / UnfoldSubpages.php
1 <?php // -*-php-*-
2 rcs_id('$Id$');
3 /*
4  Copyright 2002,2004,2005 $ThePhpWikiProgrammingTeam
5
6  This file is part of PhpWiki.
7
8  PhpWiki is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  PhpWiki is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /**
24  * UnfoldSubpages:  Lists the content of all SubPages of the current page.
25  *   This is e.g. useful for the CalendarPlugin, to see all entries at once.
26  *   Warning: Better don't use it with non-existant sections!
27  *            The section extractor is currently quite unstable.
28  * Usage:   <?plugin UnfoldSubpages sortby=-mtime words=50 maxpages=5 ?>
29  * Author:  Reini Urban <rurban@x-ray.at>
30  * 
31  * Todo: follow RedirectTo
32  */
33
34 require_once("lib/PageList.php");
35 require_once("lib/TextSearchQuery.php");
36 require_once("lib/plugin/IncludePage.php");
37
38 class WikiPlugin_UnfoldSubpages
39 extends WikiPlugin_IncludePage
40 {
41     function getName() {
42         return _("UnfoldSubpages");
43     }
44
45     function getDescription () {
46         return _("Includes the content of all SubPages of the current page.");
47     }
48
49     function getVersion() {
50         return preg_replace("/[Revision: $]/", '',
51                             "\$Revision$");
52     }
53
54     function getDefaultArguments() {
55         return array_merge
56             (
57              PageList::supportedArgs(),
58              array(
59                    'pagename' => '[pagename]', // default: current page
60                    //'header'  => '',  // expandable string
61                    'quiet'   => false, // print no header
62                    'sortby'   => '',    // [+|-]pagename, [+|-]mtime, [+|-]hits
63                    'maxpages' => false, // maximum number of pages to include (== limit)
64                    'smalltitle' => false, // if set, hide transclusion-title,
65                                         //  just have a small link at the start of 
66                                         //  the page.
67                    'words'   => false,  // maximum number of words
68                                         //  per page to include
69                    'lines'   => false,  // maximum number of lines
70                                         //  per page to include
71                    'bytes'   => false,  // maximum number of bytes
72                                         //  per page to include
73                    'sections' => false, // maximum number of sections per page to include
74                    'section' => false,  // this named section per page only
75                    'sectionhead' => false // when including a named
76                                         //  section show the heading
77                    ));
78     }
79
80     function run($dbi, $argstr, &$request, $basepage) {
81         static $included_pages = false;
82         if (!$included_pages) $included_pages = array($basepage);
83         
84         $args = $this->getArgs($argstr, $request);
85
86         if (!empty($args['limit']) && !is_numeric($args['limit'])) {
87             return $this->error(_("Illegal 'limit' argument: must be numeric"));
88         }
89
90         extract($args);
91         $query = new TextSearchQuery($pagename . SUBPAGE_SEPARATOR . '*', true, 'glob');
92         $subpages = $dbi->titleSearch($query, $sortby, $limit, $exclude);
93         //if ($sortby)
94         //    $subpages = $subpages->applyFilters(array('sortby' => $sortby, 'limit' => $limit, 'exclude' => $exclude));
95         //$subpages = explodePageList($pagename . SUBPAGE_SEPARATOR . '*', false, 
96         //                            $sortby, $limit, $exclude);
97         if (is_string($exclude) and !is_array($exclude))
98             $exclude = PageList::explodePageList($exclude, false, false, $limit);
99         $content = HTML();
100
101         include_once('lib/BlockParser.php');
102         $i = 0;
103         while ($page = $subpages->next()) {
104             $cpagename = $page->getName();
105             if ($maxpages and ($i++ > $maxpages)) {
106                 return $content;
107             }
108             if (in_array($cpagename, $exclude))
109                 continue;
110             // A page cannot include itself. Avoid doublettes.
111             if (in_array($cpagename, $included_pages)) {
112                 $content->pushContent(HTML::p(sprintf(_("recursive inclusion of page %s ignored"),
113                                                       $cpagename)));
114                 continue;
115             }
116
117             // Check if user is allowed to get the Page.
118             if (!mayAccessPage ('view', $cpagename)) {
119                 return $this->error(sprintf(_("Illegal inclusion of page %s: no read access"),
120                 $cpagename));
121             }
122
123             // trap any remaining nonexistant subpages
124             if ($page->exists()) {
125                 $r = $page->getCurrentRevision();
126                 $c = $r->getContent();   // array of lines
127                 // follow redirects
128                 if (preg_match('/<'.'\?plugin\s+RedirectTo\s+page=(\w+)\s+\?'.'>/', 
129                                implode("\n", $c), $m)) 
130                 {
131                     // trap recursive redirects
132                     if (in_array($m[1], $included_pages)) {
133                         if (!$quiet)
134                             $content->pushContent(
135                                 HTML::p(sprintf(_("recursive inclusion of page %s ignored"),
136                                                 $cpagename.' => '.$m[1])));
137                         continue;
138                     }
139                         $cpagename = $m[1];
140                     
141                         // Check if user is allowed to get the Page.
142                         if (!mayAccessPage ('view', $cpagename)) {
143                                 return $this->error(sprintf(_("Illegal inclusion of page %s: no read access"),
144                                 $cpagename));
145                         }
146
147                         $page = $dbi->getPage($cpagename);
148                     $r = $page->getCurrentRevision();
149                     $c = $r->getContent();   // array of lines
150                 }
151
152                 // moved to IncludePage
153                 $ct = $this->extractParts ($c, $cpagename, $args);
154
155                 array_push($included_pages, $cpagename);
156                 if ($smalltitle) {
157                     $pname = array_pop(explode(SUBPAGE_SEPARATOR, $cpagename)); // get last subpage name
158                     // Use _("%s: %s") instead of .": ". for French punctuation
159                     $ct = TransformText(sprintf(_("%s: %s"), "[$pname|$cpagename]",
160                                                 $ct),
161                                         $r->get('markup'), $cpagename);
162                 }
163                 else {
164                     $ct = TransformText($ct, $r->get('markup'), $cpagename);
165                 }
166                 array_pop($included_pages);
167                 if (! $smalltitle) {
168                     $content->pushContent(HTML::p(array('class' => $quiet ?
169                                                         '' : 'transclusion-title'),
170                                                   fmt("Included from %s:",
171                                                       WikiLink($cpagename))));
172                 }
173                 $content->pushContent(HTML(HTML::div(array('class' => $quiet ?
174                                                            '' : 'transclusion'),
175                                                      false, $ct)));
176             }
177         }
178         if (! $cpagename ) {
179             return $this->error(sprintf(_("%s has no subpages defined."), $pagename));
180         }
181         return $content;
182     }
183 };
184
185 // For emacs users
186 // Local Variables:
187 // mode: php
188 // tab-width: 8
189 // c-basic-offset: 4
190 // c-hanging-comment-ender-p: nil
191 // indent-tabs-mode: nil
192 // End:
193 ?>