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