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