]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/PageDump.php
add owner field to mimified dump
[SourceForge/phpwiki.git] / lib / plugin / PageDump.php
1 <?php // -*-php-*-
2 rcs_id('$Id: PageDump.php,v 1.9 2004-06-07 19:50:41 rurban Exp $');
3 /**
4  * PhpWikiPlugin for PhpWiki developers to generate single page dumps
5  * for checking into cvs, or for users or the admin to produce a
6  * downloadable page dump of a single page.
7  * 
8  * This plugin will also be useful to (semi-)automatically sync pages
9  * directly between two wikis. First the LoadFile function of
10  * PhpWikiAdministration needs to be updated to handle URLs again, and
11  * add loading capability from InterWiki addresses.
12  *
13  * TODO: What about multiple revisions in one file? comments/summary
14  * field? quoted-printable?
15  *
16  * Usage:
17  *  Direct URL access:
18  *   http://...phpwiki/PageDump?page=HomePage?format=forcvs
19  *   http://...phpwiki/index.php?PageDump&page=HomePage
20  *   http://...phpwiki/index.php?PageDump&page=HomePage&download=1
21  *  Static:
22  *   <?plugin PageDump page=HomePage?>
23  *  Dynamic form (put both on the page):
24  *   <?plugin PageDump?>
25  *   <?plugin-form PageDump?>
26  */
27
28 class WikiPlugin_PageDump
29 extends WikiPlugin
30 {
31     var $MessageId;
32
33     function getName() {
34         return _("PageDump");
35     }
36     function getDescription() {
37         return _("View a single page dump online.");
38     }
39
40     function getVersion() {
41         return preg_replace("/[Revision: $]/", '',
42                             "\$Revision: 1.9 $");
43     }
44
45     function getDefaultArguments() {
46         return array('s'    => false,
47                      'page' => '[pagename]',
48                      //'encoding' => 'binary', // 'binary', 'quoted-printable'
49                      'format' => false, // 'normal', 'forcvs'
50                      // display within WikiPage or give a downloadable
51                      // raw pgsrc?
52                      'download' => false);
53     }
54
55     function run($dbi, $argstr, &$request, $basepage) {
56         extract($this->getArgs($argstr, $request));
57         // allow plugin-form
58         if (!empty($s))
59             $page = $s;
60         if (!$page)
61             return '';
62         if (! $dbi->isWikiPage($page))
63             return fmt("Page %s not found.",
64                        WikiLink($page, 'unknown'));
65
66         $p = $dbi->getPage($page);
67         include_once("lib/loadsave.php");
68         $mailified = MailifyPage($p);
69
70         // fixup_headers massages the page dump headers depending on
71         // the 'format' argument, 'normal'(default) or 'forcvs'.
72         //
73         // Normal: Don't add X-Rcs-Id, add unique Message-Id, don't
74         // strip any fields from Content-Type.
75         //
76         // ForCVS: Add empty X-Rcs-Id, strip attributes from
77         // Content-Type field: "author", "version", "lastmodified",
78         // "author_id", "hits".
79
80         $this->pagename = $page;
81         $this->generateMessageId($mailified);
82         if ($format == 'forcvs')
83             $this->fixup_headers_forcvs($mailified);
84         else
85             $this->fixup_headers($mailified);
86
87         if ($download) {
88             $request->discardOutput(); // Hijack the http request from PhpWiki.
89             ob_end_clean(); // clean up after hijacking $request
90             //ob_end_flush(); //debugging
91             Header("Content-disposition: attachment; filename=\""
92                    . FilenameForPage($page) . "\"");
93             // TODO: Read charset from generated page itself.
94             // Inconsequential at the moment, since loadsave.php
95             // presently always assumes CHARSET.
96             Header("Content-Type: text/plain; name=\""
97                    . FilenameForPage($page) . "\"; charset=\"" . $GLOBALS['charset']
98                    . "\"");
99             $request->checkValidators();
100             // let $request provide last modifed & etag
101             Header("Content-Id: <" . $this->MessageId . ">");
102             // be nice to http keepalive~s
103             Header("Content-Length: " . strlen($mailified));
104
105             // Here comes our prepared mime file
106             echo $mailified;
107             exit; // noreturn! php exits.
108             return;
109         }
110         // We are displaing inline preview in a WikiPage, so wrap the
111         // text if it is too long--unless quoted-printable (TODO).
112         $mailified = wordwrap($mailified, 70);
113
114         // fixme: what about when not using VIRTUAL_PATH?
115         $dlcvs = Button(array(//'page' => $page,
116                               'action' => $this->getName(),
117                               'format'=> 'forcvs',
118                               'download'=> true),
119                         _("Download for CVS"),
120                         WikiURL($page),
121                         'wikiadmin');
122         $dl = Button(array(//'page' => $page,
123                            'action' => $this->getName(),
124                            'download'=> true),
125                      _("Download for backup"),
126                      WikiURL($page),
127                      'wikiadmin');
128
129         $h2 = HTML::h2(fmt("Preview: Page dump of %s",
130                            WikiLink($page, 'auto')));
131         if ($format == 'forcvs') {
132             $desc = _("(formatted for PhpWiki developers, not for backing up)");
133             $altpreviewbutton = Button(array(//'page' => $page, 
134                                              'action' => $this->getName()),
135                                        _("Preview as backup format"),
136                                        WikiURL($page),
137                                        'wikiadmin');
138         }
139         else {
140             $desc = _("(formatted for backing up)");
141             $altpreviewbutton = Button(array(//'page' => $page,
142                                              'action' => $this->getName(),
143                                              'format'=> 'forcvs'),
144                                        _("Preview as developer format"),
145                                        WikiURL($page),
146                                        'wikiadmin');
147         }
148         $warning = HTML(
149 _("Please use one of the downloadable versions rather than copying and pasting from the above preview.")
150 . " " .
151 _("The wordwrap of the preview doesn't take nested markup or list indentation into consideration!")
152 . " ",
153 HTML::em(
154 _("PhpWiki developers should manually inspect the downloaded file for nested markup before rewrapping with emacs and checking into CVS.")
155          )
156                         );
157
158         global $Theme;
159         if (!$Sep = $Theme->getButtonSeparator())
160             $Sep = " ";
161
162         return HTML($h2, HTML::em($desc),
163                     HTML::pre($mailified),
164                     $altpreviewbutton,
165                     HTML::div(array('class' => 'errors'),
166                               HTML::strong(_("Warning:")),
167                               " ", $warning),
168                     $dl, $Sep, $dlcvs
169                     );
170     }
171
172     // function handle_plugin_args_cruft(&$argstr, &$args) {
173     // }
174
175     function generateMessageId($mailified) {
176         $array = explode("\n", $mailified);
177         // Extract lastmodifed from mailified document for Content-Id
178         // and/or Message-Id header, NOT from DB (page could have been
179         // edited by someone else since we started).
180         $m1 = preg_grep("/^\s+lastmodified\=(.*);/", $array);
181         $m1 = array_values($m1); //reset resulting keys
182         unset($array);
183         $m2 = preg_split("/(^\s+lastmodified\=)|(;)/", $m1[0], 2,
184                          PREG_SPLIT_NO_EMPTY);
185
186         // insert message id into actual message when appropriate, NOT
187         // into http header should be part of fixup_headers, in the
188         // format:
189         // <abbrphpwikiversion.mtimeepochTZ%InterWikiLinktothispage@hostname>
190         // Hopefully this provides a unique enough identifier without
191         // using md5. Even though this particular wiki may not
192         // actually be part of InterWiki, including this info provides
193         // the wiki name and name of the page which is being
194         // represented as a text message.
195         $this->MessageId = implode('', explode('.', PHPWIKI_VERSION))
196             . "-" . $m2[0] . date("O")
197             //. "-". rawurlencode(WIKI_NAME.":" . $request->getURLtoSelf())
198             . "-". rawurlencode(WIKI_NAME.":" . $this->pagename)
199             . "@". rawurlencode(SERVER_NAME);
200     }
201
202     function fixup_headers(&$mailified) {
203         $return = explode("\n", $mailified);
204
205         // Leave message intact for backing up, just add Message-Id header before transmitting.
206         $item_to_insert = "Message-Id: <" . $this->MessageId .">";
207         $insert_into_key_position = 2;
208         $returnval_ignored = array_splice($return,
209                                           $insert_into_key_position,
210                                           0, $item_to_insert);
211
212         $mailified = implode("\n", array_values($return));
213     }
214
215     function fixup_headers_forcvs(&$mailified) {
216         $array = explode("\n", $mailified);
217
218         // Massage headers to prepare for developer checkin to CVS.
219         $item_to_insert = "X-Rcs-Id: \$Id\$";
220         $insert_into_key_position = 2;
221         $returnval_ignored = array_splice($array,
222                                           $insert_into_key_position,
223                                           0, $item_to_insert);
224
225         $item_to_insert = "  pgsrc_version=\"2 \$Revision\$\";";
226         $insert_into_key_position = 5;
227         $returnval_ignored = array_splice($array,
228                                           $insert_into_key_position,
229                                           0, $item_to_insert);
230         /*
231             Strip out all this junk:
232             author=MeMe;
233             version=74;
234             lastmodified=1041561552;
235             author_id=127.0.0.1;
236             hits=146;
237         */
238         $killme = array("author", "version", "lastmodified",
239                         "author_id", "hits", "owner");
240         // UltraNasty, fixme:
241         foreach ($killme as $pattern) {
242             $array = preg_replace("/^\s\s$pattern\=.*;/",
243                                   /*$replacement =*/"zzzjunk", $array);
244         }
245         // remove deleted values from array
246         for ($i = 0; $i < count($array); $i++ ) {
247             if(trim($array[$i]) != "zzzjunk") { //nasty, fixme
248             //trigger_error("'$array[$i]'");//debugging
249                 $return[] =$array[$i];
250             }
251         }
252
253         $mailified = implode("\n", $return);
254     }
255 };
256
257 // $Log: not supported by cvs2svn $
258 // Revision 1.8  2004/05/25 12:43:29  rurban
259 // ViewSource link, better actionpage usage
260 //
261 // Revision 1.7  2004/05/04 17:21:06  rurban
262 // revert previous patch
263 //
264 // Revision 1.6  2004/05/03 20:44:55  rurban
265 // fixed gettext strings
266 // new SqlResult plugin
267 // _WikiTranslation: fixed init_locale
268 //
269 // Revision 1.5  2004/05/03 17:42:44  rurban
270 // fix cvs tags: "$tag$" => "$tag: $"
271 //
272 // Revision 1.4  2004/04/18 01:11:52  rurban
273 // more numeric pagename fixes.
274 // fixed action=upload with merge conflict warnings.
275 // charset changed from constant to global (dynamic utf-8 switching)
276 //
277 // Revision 1.3  2004/02/17 12:11:36  rurban
278 // added missing 4th basepage arg at plugin->run() to almost all plugins. This caused no harm so far, because it was silently dropped on normal usage. However on plugin internal ->run invocations it failed. (InterWikiSearch, IncludeSiteMap, ...)
279 //
280 // Revision 1.2  2003/12/12 01:08:30  carstenklapp
281 // QuickFix for invalid Message-Id header format.
282 //
283 // Revision 1.1  2003/12/12 00:52:55  carstenklapp
284 // New feature: Plugin to download page dumps of individual pages. In the
285 // future this could be used as a rudimentary way to sync pages between
286 // wikis.
287 // Internal changes: enhanced and renamed from the experimental
288 // _MailifyPage plugin.
289 //
290 // Revision 1.3  2003/11/16 00:11:25  carstenklapp
291 // Fixed previous Log comment interfering with PHP (sorry).
292 // Improved error handling.
293 //
294 // Revision 1.2  2003/11/15 23:37:51  carstenklapp
295 // Enhanced plugin to allow invocation with \<\?plugin-form PageDump\?\>.
296 //
297 // Revision 1.1  2003/02/20 18:03:04  carstenklapp
298 // New experimental WikiPlugin for internal use only by PhpWiki developers.
299 //
300
301 // For emacs users
302 // Local Variables:
303 // mode: php
304 // tab-width: 8
305 // c-basic-offset: 4
306 // c-hanging-comment-ender-p: nil
307 // indent-tabs-mode: nil
308 // End:
309 ?>