]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/UnfoldSubpages.php
Critical security fix: it was possible to see the content of pages protected by ACLs...
[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         extract($args);
86         $query = new TextSearchQuery($pagename . SUBPAGE_SEPARATOR . '*', true, 'glob');
87         $subpages = $dbi->titleSearch($query, $sortby, $limit, $exclude);
88         //if ($sortby)
89         //    $subpages = $subpages->applyFilters(array('sortby' => $sortby, 'limit' => $limit, 'exclude' => $exclude));
90         //$subpages = explodePageList($pagename . SUBPAGE_SEPARATOR . '*', false, 
91         //                            $sortby, $limit, $exclude);
92         if (is_string($exclude) and !is_array($exclude))
93             $exclude = PageList::explodePageList($exclude, false, false, $limit);
94         $content = HTML();
95
96         include_once('lib/BlockParser.php');
97         $i = 0;
98         while ($page = $subpages->next()) {
99             $cpagename = $page->getName();
100             if ($maxpages and ($i++ > $maxpages)) {
101                 return $content;
102             }
103             if (in_array($cpagename, $exclude))
104                 continue;
105             // A page cannot include itself. Avoid doublettes.
106             if (in_array($cpagename, $included_pages)) {
107                 $content->pushContent(HTML::p(sprintf(_("recursive inclusion of page %s ignored"),
108                                                       $cpagename)));
109                 continue;
110             }
111
112             // Check if user is allowed to get the Page.
113             if (!mayAccessPage ('view', $cpagename)) {
114                 return $this->error(sprintf(_("Illegal inclusion of page %s: no read access"),
115                 $cpagename));
116             }
117
118             // trap any remaining nonexistant subpages
119             if ($page->exists()) {
120                 $r = $page->getCurrentRevision();
121                 $c = $r->getContent();   // array of lines
122                 // follow redirects
123                 if (preg_match('/<'.'\?plugin\s+RedirectTo\s+page=(\w+)\s+\?'.'>/', 
124                                implode("\n", $c), $m)) 
125                 {
126                     // trap recursive redirects
127                     if (in_array($m[1], $included_pages)) {
128                         if (!$quiet)
129                             $content->pushContent(
130                                 HTML::p(sprintf(_("recursive inclusion of page %s ignored"),
131                                                 $cpagename.' => '.$m[1])));
132                         continue;
133                     }
134                         $cpagename = $m[1];
135                     
136                         // Check if user is allowed to get the Page.
137                         if (!mayAccessPage ('view', $cpagename)) {
138                                 return $this->error(sprintf(_("Illegal inclusion of page %s: no read access"),
139                                 $cpagename));
140                         }
141
142                         $page = $dbi->getPage($cpagename);
143                     $r = $page->getCurrentRevision();
144                     $c = $r->getContent();   // array of lines
145                 }
146
147                 // moved to IncludePage
148                 $ct = $this->extractParts ($c, $cpagename, $args);
149
150                 array_push($included_pages, $cpagename);
151                 if ($smalltitle) {
152                     $pname = array_pop(explode(SUBPAGE_SEPARATOR, $cpagename)); // get last subpage name
153                     // Use _("%s: %s") instead of .": ". for French punctuation
154                     $ct = TransformText(sprintf(_("%s: %s"), "[$pname|$cpagename]",
155                                                 $ct),
156                                         $r->get('markup'), $cpagename);
157                 }
158                 else {
159                     $ct = TransformText($ct, $r->get('markup'), $cpagename);
160                 }
161                 array_pop($included_pages);
162                 if (! $smalltitle) {
163                     $content->pushContent(HTML::p(array('class' => $quiet ?
164                                                         '' : 'transclusion-title'),
165                                                   fmt("Included from %s:",
166                                                       WikiLink($cpagename))));
167                 }
168                 $content->pushContent(HTML(HTML::div(array('class' => $quiet ?
169                                                            '' : 'transclusion'),
170                                                      false, $ct)));
171             }
172         }
173         if (! $cpagename ) {
174             return $this->error(sprintf(_("%s has no subpages defined."), $pagename));
175         }
176         return $content;
177     }
178 };
179
180 // For emacs users
181 // Local Variables:
182 // mode: php
183 // tab-width: 8
184 // c-basic-offset: 4
185 // c-hanging-comment-ender-p: nil
186 // indent-tabs-mode: nil
187 // End:
188 ?>