]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/UpLoad.php
Activated Revision substitution for Subversion
[SourceForge/phpwiki.git] / lib / plugin / UpLoad.php
1 <?php // -*-php-*-
2 rcs_id('$Id$');
3 /*
4  Copyright 2003,2004,2007 $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 /**
25  * UpLoad:  Allow Administrator to upload files to a special directory,
26  *          which should preferably be added to the InterWikiMap
27  * Usage:   <?plugin UpLoad ?>
28  * Author:  NathanGass <gass@iogram.ch>
29  * Changes: ReiniUrban <rurban@x-ray.at>,
30  *          qubit <rtryon@dartmouth.edu>
31  * Note:    See also Jochen Kalmbach's plugin/UserFileManagement.php
32  */
33
34 class WikiPlugin_UpLoad
35 extends WikiPlugin
36 {
37     var $disallowed_extensions;
38     // TODO: use PagePerms instead
39     var $only_authenticated = true; // allow only authenticated users may upload.
40
41     function getName () {
42         return "UpLoad";
43     }
44
45     function getDescription () {
46         return _("Upload files to the local InterWiki Upload:<filename>");
47     }
48
49     function getVersion() {
50         return preg_replace("/[Revision: $]/", '',
51                             "\$Revision$");
52     }
53
54     function getDefaultArguments() {
55         return array('logfile'  => 'phpwiki-upload.log',
56                      // add a link of the fresh file automatically to the 
57                      // end of the page (or current page)
58                      'autolink' => true, 
59                      'page'     => '[pagename]',
60                      'size'     => 50,
61                      'mode'     => 'actionpage', // or edit
62                      );
63     }
64
65     function run($dbi, $argstr, &$request, $basepage) {
66         $this->allowed_extensions = explode("\n",
67 "7z
68 avi
69 bmp
70 bz2
71 c
72 cfg
73 diff
74 doc
75 gif
76 h
77 ini
78 jpeg
79 jpg
80 kmz
81 mp3
82 odg
83 odp
84 ods
85 odt
86 patch
87 pdf
88 png
89 ppt
90 rar
91 tar
92 tar.gz
93 txt
94 xls
95 zip");
96         $this->disallowed_extensions = explode("\n",
97 "ad[ep]
98 asd
99 ba[st]
100 chm
101 cmd
102 com
103 cgi
104 cpl
105 crt
106 dll
107 eml
108 exe
109 hlp
110 hta
111 in[fs]
112 isp
113 jse?
114 lnk
115 md[betw]
116 ms[cipt]
117 nws
118 ocx
119 ops
120 pcd
121 p[ir]f
122 php\d?
123 phtml
124 pl
125 py
126 reg
127 sc[frt]
128 sh[bsm]?
129 swf
130 url
131 vb[esx]?
132 vxd
133 ws[cfh]");
134         //removed "\{[[:xdigit:]]{8}(?:-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}\}"
135
136         $args = $this->getArgs($argstr, $request);
137         extract($args);
138
139         $file_dir = getUploadFilePath();
140         $file_dir .= "/";
141         $form = HTML::form(array('action'  => $request->getPostURL(),
142                                  'enctype' => 'multipart/form-data',
143                                  'method'  => 'post'));
144         $contents = HTML::div(array('class' => 'wikiaction'));
145         $contents->pushContent(HTML::input(array('type' => 'hidden',
146                                                  'name' => 'MAX_FILE_SIZE',
147                                                  'value'=> MAX_UPLOAD_SIZE)));
148         $contents->pushContent(HTML::input(array('name' => 'userfile',
149                                                  'type' => 'file',
150                                                  'size' => $size)));
151         if ($mode == 'edit') {
152             $contents->pushContent(HTML::input(array('name' => 'action',
153                                                      'type' => 'hidden',
154                                                      'value'=> 'edit')));
155             $contents->pushContent(HTML::raw(" "));
156             $contents->pushContent(HTML::input(array('value' => _("Upload"),
157                                                      'name'  => 'edit[upload]',
158                                                      'type'  => 'submit')));
159         } else {
160             $contents->pushContent(HTML::raw(" "));
161             $contents->pushContent(HTML::input(array('value' => _("Upload"),
162                                                      'type'  => 'submit')));
163         }
164         $form->pushContent($contents);
165
166         $message = HTML();
167         if ($request->isPost() and $this->only_authenticated) {
168             // Make sure that the user is logged in.
169             $user = $request->getUser();
170             if (!$user->isAuthenticated()) {
171                 $message->pushContent(HTML::h2(_("ACCESS DENIED: You must log in to upload files.")),
172                                           HTML::br(),HTML::br());
173                 $result = HTML();
174                 $result->pushContent($form);
175                 $result->pushContent($message);
176                 return $result;
177             }
178         }
179         
180         $userfile = $request->getUploadedFile('userfile');
181         if ($userfile) {
182             $userfile_name = $userfile->getName();
183             $userfile_name = trim(basename($userfile_name));
184             if (UPLOAD_USERDIR) {
185                 $file_dir .= $request->_user->_userid;
186                 if (!file_exists($file_dir))
187                     mkdir($file_dir, 0775);
188                 $file_dir .= "/";
189                 $u_userfile = $request->_user->_userid . "/" . $userfile_name;
190             } else {
191                 $u_userfile = $userfile_name;
192             }
193             $u_userfile = preg_replace("/ /", "%20", $u_userfile);
194             $userfile_tmpname = $userfile->getTmpName();
195             $err_header = HTML::h2(fmt("ERROR uploading '%s': ", $userfile_name));
196             if (preg_match("/(\." . join("|\.", $this->disallowed_extensions) . ")(\.|\$)/i",
197                            $userfile_name))
198             {
199                 $message->pushContent($err_header);
200                 $message->pushContent(fmt("Files with extension %s are not allowed.",
201                                           join(", ", $this->disallowed_extensions)),HTML::br(),HTML::br());
202             }
203             elseif (! DISABLE_UPLOAD_ONLY_ALLOWED_EXTENSIONS and 
204                     ! preg_match("/(\." . join("|\.", $this->allowed_extensions) . ")\$/i", 
205                                $userfile_name))
206             {
207                 $message->pushContent($err_header);
208                 $message->pushContent(fmt("Only files with the extension %s are allowed.",
209                                           join(", ", $this->allowed_extensions)),HTML::br(),HTML::br());
210             }
211             elseif (preg_match("/[^._a-zA-Z0-9- ]/", $userfile_name))
212             {
213                 $message->pushContent($err_header);
214                 $message->pushContent(_("Invalid filename. File names may only contain alphanumeric characters and dot, underscore, space or dash."),
215                                       HTML::br(),HTML::br());
216             }
217             elseif (file_exists($file_dir . $userfile_name)) {
218                 $message->pushContent($err_header);
219                 $message->pushContent(fmt("There is already a file with name %s uploaded.",
220                                           $u_userfile),HTML::br(),HTML::br());
221             }
222             elseif ($userfile->getSize() > (MAX_UPLOAD_SIZE)) {
223                 $message->pushContent($err_header);
224                 $message->pushContent(_("Sorry but this file is too big."),HTML::br(),HTML::br());
225             }
226             elseif (move_uploaded_file($userfile_tmpname, $file_dir . $userfile_name) or
227                     (IsWindows() and rename($userfile_tmpname, $file_dir . $userfile_name))
228                     )
229             {
230                 $interwiki = new PageType_interwikimap();
231                 $link = $interwiki->link("Upload:$u_userfile");
232                 $message->pushContent(HTML::h2(_("File successfully uploaded.")));
233                 $message->pushContent(HTML::ul(HTML::li($link)));
234
235                 // the upload was a success and we need to mark this event in the "upload log"
236                 if ($logfile) { 
237                     $upload_log = $file_dir . basename($logfile);
238                     $this->log($userfile, $upload_log, $message);
239                 }
240                 if ($autolink) {
241                     require_once("lib/loadsave.php");
242                     $pagehandle = $dbi->getPage($page);
243                     if ($pagehandle->exists()) {// don't replace default contents
244                         $current = $pagehandle->getCurrentRevision();
245                         $version = $current->getVersion();
246                         $text = $current->getPackedContent();
247                         $newtext = $text . "\n* Upload:$u_userfile"; // don't inline images
248                         $meta = $current->_data;
249                         $meta['summary'] = sprintf(_("uploaded %s"),$u_userfile);
250                         $pagehandle->save($newtext, $version + 1, $meta);
251                     }
252                 }
253             }
254             else {
255                 $message->pushContent($err_header);
256                 $message->pushContent(HTML::br(),_("Uploading failed."),HTML::br());
257             }
258         } else {
259             $message->pushContent(HTML::br(),_("No file selected. Please select one."),HTML::br());
260         }
261
262         //$result = HTML::div( array( 'class' => 'wikiaction' ) );
263         $result = HTML();
264         $result->pushContent($form);
265         $result->pushContent($message);
266         return $result;
267     }
268
269     function log ($userfile, $upload_log, &$message) {
270         global $WikiTheme;
271         $user = $GLOBALS['request']->_user;
272         if (file_exists($upload_log) and (!is_writable($upload_log))) {
273             trigger_error(_("The upload logfile exists but is not writable."), E_USER_WARNING);
274         }
275         elseif (!$log_handle = fopen ($upload_log, "a")) {
276             trigger_error(_("Can't open the upload logfile."), E_USER_WARNING);
277         }
278         else {        // file size in KB; precision of 0.1
279             $file_size = round(($userfile->getSize())/1024, 1);
280             if ($file_size <= 0) {
281                 $file_size = "&lt; 0.1";
282             }
283             $userfile_name = $userfile->getName();
284             fwrite($log_handle,
285                    "\n"
286                    . "<tr><td><a href=\"$userfile_name\">$userfile_name</a></td>"
287                    . "<td align=\"right\">$file_size kB</td>"
288                    . "<td>&nbsp;&nbsp;" . $WikiTheme->formatDate(time()) . "</td>"
289                    . "<td>&nbsp;&nbsp;<em>" . $user->getId() . "</em></td></tr>");
290             fclose($log_handle);
291         }
292         return;
293     }
294
295 }
296
297 // $Log: not supported by cvs2svn $
298 // Revision 1.30  2008/08/03 17:25:41  vargenau
299 // Add message: "No file selected. Please select one."
300 //
301 // Revision 1.29  2008/08/03 17:06:32  vargenau
302 // Add Open Document Format suffixes: odg, odp, ods, odt
303 //
304 // Revision 1.28  2008/08/03 15:14:55  vargenau
305 // Add slash to file_dir
306 //
307 // Revision 1.27  2008/05/17 06:53:54  vargenau
308 // Create log file if it does not exist
309 //
310 // Revision 1.26  2007/07/14 12:05:07  rurban
311 // no inlined [] links anymore, edit inclusion, more extensions allowed.
312 //
313 // Revision 1.25  2007/04/18 20:40:48  rurban
314 // added DISABLE_UPLOAD_ONLY_ALLOWED_EXTENSIONS
315 //
316 // Revision 1.24  2007/04/11 17:49:01  rurban
317 // Chgeck against .php\d, i.e. php3
318 //
319 // Revision 1.23  2007/04/08 12:43:45  rurban
320 // Important security fix!
321 // Disallow files like "deface.php.3" also. Those are actually in the wild!
322 //
323 // Revision 1.22  2007/02/17 14:16:56  rurban
324 // allow spaces in filenames
325 //
326 // Revision 1.21  2007/01/04 16:46:50  rurban
327 // Support UPLOAD_USERDIR
328 //
329 // Revision 1.20  2006/08/15 13:40:40  rurban
330 // help finding the file (should not be needed)
331 //
332 // Revision 1.19  2005/04/11 19:40:15  rurban
333 // Simplify upload. See https://sourceforge.net/forum/message.php?msg_id=3093651
334 // Improve UpLoad warnings.
335 // Move auth check before upload.
336 //
337 // Revision 1.18  2005/02/12 17:24:24  rurban
338 // locale update: missing . : fixed. unified strings
339 // proper linebreaks
340 //
341 // Revision 1.17  2004/11/09 08:15:50  rurban
342 // trim filename
343 //
344 // Revision 1.16  2004/10/21 19:03:37  rurban
345 // Be more stricter with uploads: Filenames may only contain alphanumeric
346 // characters. Patch #1037825
347 //
348 // Revision 1.15  2004/09/22 13:46:26  rurban
349 // centralize upload paths.
350 // major WikiPluginCached feature enhancement:
351 //   support _STATIC pages in uploads/ instead of dynamic getimg.php? subrequests.
352 //   mainly for debugging, cache problems and action=pdf
353 //
354 // Revision 1.14  2004/06/16 10:38:59  rurban
355 // Disallow refernces in calls if the declaration is a reference
356 // ("allow_call_time_pass_reference clean").
357 //   PhpWiki is now allow_call_time_pass_reference = Off clean,
358 //   but several external libraries may not.
359 //   In detail these libs look to be affected (not tested):
360 //   * Pear_DB odbc
361 //   * adodb oracle
362 //
363 // Revision 1.13  2004/06/14 11:31:39  rurban
364 // renamed global $Theme to $WikiTheme (gforge nameclash)
365 // inherit PageList default options from PageList
366 //   default sortby=pagename
367 // use options in PageList_Selectable (limit, sortby, ...)
368 // added action revert, with button at action=diff
369 // added option regex to WikiAdminSearchReplace
370 //
371 // Revision 1.12  2004/06/13 11:34:22  rurban
372 // fixed bug #969532 (space in uploaded filenames)
373 // improved upload error messages
374 //
375 // Revision 1.11  2004/06/11 09:07:30  rurban
376 // support theme-specific LinkIconAttr: front or after or none
377 //
378 // Revision 1.10  2004/04/12 10:19:18  rurban
379 // fixed copyright year
380 //
381 // Revision 1.9  2004/04/12 10:18:22  rurban
382 // removed the hairy regex line
383 //
384 // Revision 1.8  2004/04/12 09:12:22  rurban
385 // fix syntax errors
386 //
387 // Revision 1.7  2004/04/09 17:49:03  rurban
388 // Added PhpWiki RssFeed to Sidebar
389 // sidebar formatting
390 // some browser dependant fixes (old-browser support)
391 //
392 // Revision 1.6  2004/02/27 01:36:51  rurban
393 // autolink enabled
394 //
395 // Revision 1.5  2004/02/27 01:24:43  rurban
396 // use IntwerWiki links for uploaded file.
397 // autolink to page prepared, but not yet ready
398 //
399 // Revision 1.4  2004/02/21 19:12:59  rurban
400 // patch by Sascha Carlin
401 //
402 // Revision 1.3  2004/02/17 12:11:36  rurban
403 // 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, ...)
404 //
405 // Revision 1.2  2004/01/26 09:18:00  rurban
406 // * changed stored pref representation as before.
407 //   the array of objects is 1) bigger and 2)
408 //   less portable. If we would import packed pref
409 //   objects and the object definition was changed, PHP would fail.
410 //   This doesn't happen with an simple array of non-default values.
411 // * use $prefs->retrieve and $prefs->store methods, where retrieve
412 //   understands the interim format of array of objects also.
413 // * simplified $prefs->get() and fixed $prefs->set()
414 // * added $user->_userid and class '_WikiUser' portability functions
415 // * fixed $user object ->_level upgrading, mostly using sessions.
416 //   this fixes yesterdays problems with loosing authorization level.
417 // * fixed WikiUserNew::checkPass to return the _level
418 // * fixed WikiUserNew::isSignedIn
419 // * added explodePageList to class PageList, support sortby arg
420 // * fixed UserPreferences for WikiUserNew
421 // * fixed WikiPlugin for empty defaults array
422 // * UnfoldSubpages: added pagename arg, renamed pages arg,
423 //   removed sort arg, support sortby arg
424 //
425 // Revision 1.1  2003/11/04 18:41:41  carstenklapp
426 // New plugin which was submitted to the mailing list some time
427 // ago. (This is the best UpLoad function I have seen for PhpWiki so
428 // far. Cleaned up text formatting and typos from the version on the
429 // mailing list. Still needs a few adjustments.)
430
431 // (c-file-style: "gnu")
432 // Local Variables:
433 // mode: php
434 // tab-width: 8
435 // c-basic-offset: 4
436 // c-hanging-comment-ender-p: nil
437 // indent-tabs-mode: nil
438 // End:
439 ?>