2 rcs_id('$Id: UpLoad.php,v 1.31 2008-08-21 18:32:23 vargenau Exp $');
4 Copyright 2003,2004,2007 $ThePhpWikiProgrammingTeam
6 This file is part of PhpWiki.
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.
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.
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
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
34 class WikiPlugin_UpLoad
37 var $disallowed_extensions;
38 // TODO: use PagePerms instead
39 var $only_authenticated = true; // allow only authenticated users may upload.
45 function getDescription () {
46 return _("Upload files to the local InterWiki Upload:<filename>");
49 function getVersion() {
50 return preg_replace("/[Revision: $]/", '',
51 "\$Revision: 1.31 $");
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)
59 'page' => '[pagename]',
61 'mode' => 'actionpage', // or edit
65 function run($dbi, $argstr, &$request, $basepage) {
66 $this->allowed_extensions = explode("\n",
96 $this->disallowed_extensions = explode("\n",
134 //removed "\{[[:xdigit:]]{8}(?:-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}\}"
136 $args = $this->getArgs($argstr, $request);
139 $file_dir = getUploadFilePath();
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',
151 if ($mode == 'edit') {
152 $contents->pushContent(HTML::input(array('name' => 'action',
155 $contents->pushContent(HTML::raw(" "));
156 $contents->pushContent(HTML::input(array('value' => _("Upload"),
157 'name' => 'edit[upload]',
158 'type' => 'submit')));
160 $contents->pushContent(HTML::raw(" "));
161 $contents->pushContent(HTML::input(array('value' => _("Upload"),
162 'type' => 'submit')));
164 $form->pushContent($contents);
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());
174 $result->pushContent($form);
175 $result->pushContent($message);
180 $userfile = $request->getUploadedFile('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);
189 $u_userfile = $request->_user->_userid . "/" . $userfile_name;
191 $u_userfile = $userfile_name;
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",
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());
203 elseif (! DISABLE_UPLOAD_ONLY_ALLOWED_EXTENSIONS and
204 ! preg_match("/(\." . join("|\.", $this->allowed_extensions) . ")\$/i",
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());
211 elseif (preg_match("/[^._a-zA-Z0-9- ]/", $userfile_name))
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());
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());
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());
226 elseif (move_uploaded_file($userfile_tmpname, $file_dir . $userfile_name) or
227 (IsWindows() and rename($userfile_tmpname, $file_dir . $userfile_name))
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)));
235 // the upload was a success and we need to mark this event in the "upload log"
237 $upload_log = $file_dir . basename($logfile);
238 $this->log($userfile, $upload_log, $message);
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);
255 $message->pushContent($err_header);
256 $message->pushContent(HTML::br(),_("Uploading failed."),HTML::br());
259 $message->pushContent(HTML::br(),_("No file selected. Please select one."),HTML::br());
262 //$result = HTML::div( array( 'class' => 'wikiaction' ) );
264 $result->pushContent($form);
265 $result->pushContent($message);
269 function log ($userfile, $upload_log, &$message) {
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);
275 elseif (!$log_handle = fopen ($upload_log, "a")) {
276 trigger_error(_("Can't open the upload logfile."), E_USER_WARNING);
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 = "< 0.1";
283 $userfile_name = $userfile->getName();
286 . "<tr><td><a href=\"$userfile_name\">$userfile_name</a></td>"
287 . "<td align=\"right\">$file_size kB</td>"
288 . "<td> " . $WikiTheme->formatDate(time()) . "</td>"
289 . "<td> <em>" . $user->getId() . "</em></td></tr>");
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."
301 // Revision 1.29 2008/08/03 17:06:32 vargenau
302 // Add Open Document Format suffixes: odg, odp, ods, odt
304 // Revision 1.28 2008/08/03 15:14:55 vargenau
305 // Add slash to file_dir
307 // Revision 1.27 2008/05/17 06:53:54 vargenau
308 // Create log file if it does not exist
310 // Revision 1.26 2007/07/14 12:05:07 rurban
311 // no inlined [] links anymore, edit inclusion, more extensions allowed.
313 // Revision 1.25 2007/04/18 20:40:48 rurban
314 // added DISABLE_UPLOAD_ONLY_ALLOWED_EXTENSIONS
316 // Revision 1.24 2007/04/11 17:49:01 rurban
317 // Chgeck against .php\d, i.e. php3
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!
323 // Revision 1.22 2007/02/17 14:16:56 rurban
324 // allow spaces in filenames
326 // Revision 1.21 2007/01/04 16:46:50 rurban
327 // Support UPLOAD_USERDIR
329 // Revision 1.20 2006/08/15 13:40:40 rurban
330 // help finding the file (should not be needed)
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.
337 // Revision 1.18 2005/02/12 17:24:24 rurban
338 // locale update: missing . : fixed. unified strings
341 // Revision 1.17 2004/11/09 08:15:50 rurban
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
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
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):
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
371 // Revision 1.12 2004/06/13 11:34:22 rurban
372 // fixed bug #969532 (space in uploaded filenames)
373 // improved upload error messages
375 // Revision 1.11 2004/06/11 09:07:30 rurban
376 // support theme-specific LinkIconAttr: front or after or none
378 // Revision 1.10 2004/04/12 10:19:18 rurban
379 // fixed copyright year
381 // Revision 1.9 2004/04/12 10:18:22 rurban
382 // removed the hairy regex line
384 // Revision 1.8 2004/04/12 09:12:22 rurban
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)
392 // Revision 1.6 2004/02/27 01:36:51 rurban
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
399 // Revision 1.4 2004/02/21 19:12:59 rurban
400 // patch by Sascha Carlin
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, ...)
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
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.)
431 // (c-file-style: "gnu")
436 // c-hanging-comment-ender-p: nil
437 // indent-tabs-mode: nil