]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/UpLoad.php
Add Open Document Format suffixes: odg, odp, ods, odt
[SourceForge/phpwiki.git] / lib / plugin / UpLoad.php
1 <?php // -*-php-*-
2 rcs_id('$Id: UpLoad.php,v 1.29 2008-08-03 17:06:32 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         }
254         /*else {
255             $message->pushContent(HTML::br(),HTML::br());
256         }*/
257
258         //$result = HTML::div( array( 'class' => 'wikiaction' ) );
259         $result = HTML();
260         $result->pushContent($form);
261         $result->pushContent($message);
262         return $result;
263     }
264
265     function log ($userfile, $upload_log, &$message) {
266         global $WikiTheme;
267         $user = $GLOBALS['request']->_user;
268         if (file_exists($upload_log) and (!is_writable($upload_log))) {
269             trigger_error(_("The upload logfile exists but is not writable."), E_USER_WARNING);
270         }
271         elseif (!$log_handle = fopen ($upload_log, "a")) {
272             trigger_error(_("Can't open the upload logfile."), E_USER_WARNING);
273         }
274         else {        // file size in KB; precision of 0.1
275             $file_size = round(($userfile->getSize())/1024, 1);
276             if ($file_size <= 0) {
277                 $file_size = "&lt; 0.1";
278             }
279             $userfile_name = $userfile->getName();
280             fwrite($log_handle,
281                    "\n"
282                    . "<tr><td><a href=\"$userfile_name\">$userfile_name</a></td>"
283                    . "<td align=\"right\">$file_size kB</td>"
284                    . "<td>&nbsp;&nbsp;" . $WikiTheme->formatDate(time()) . "</td>"
285                    . "<td>&nbsp;&nbsp;<em>" . $user->getId() . "</em></td></tr>");
286             fclose($log_handle);
287         }
288         return;
289     }
290
291 }
292
293 // $Log: not supported by cvs2svn $
294 // Revision 1.28  2008/08/03 15:14:55  vargenau
295 // Add slash to file_dir
296 //
297 // Revision 1.27  2008/05/17 06:53:54  vargenau
298 // Create log file if it does not exist
299 //
300 // Revision 1.26  2007/07/14 12:05:07  rurban
301 // no inlined [] links anymore, edit inclusion, more extensions allowed.
302 //
303 // Revision 1.25  2007/04/18 20:40:48  rurban
304 // added DISABLE_UPLOAD_ONLY_ALLOWED_EXTENSIONS
305 //
306 // Revision 1.24  2007/04/11 17:49:01  rurban
307 // Chgeck against .php\d, i.e. php3
308 //
309 // Revision 1.23  2007/04/08 12:43:45  rurban
310 // Important security fix!
311 // Disallow files like "deface.php.3" also. Those are actually in the wild!
312 //
313 // Revision 1.22  2007/02/17 14:16:56  rurban
314 // allow spaces in filenames
315 //
316 // Revision 1.21  2007/01/04 16:46:50  rurban
317 // Support UPLOAD_USERDIR
318 //
319 // Revision 1.20  2006/08/15 13:40:40  rurban
320 // help finding the file (should not be needed)
321 //
322 // Revision 1.19  2005/04/11 19:40:15  rurban
323 // Simplify upload. See https://sourceforge.net/forum/message.php?msg_id=3093651
324 // Improve UpLoad warnings.
325 // Move auth check before upload.
326 //
327 // Revision 1.18  2005/02/12 17:24:24  rurban
328 // locale update: missing . : fixed. unified strings
329 // proper linebreaks
330 //
331 // Revision 1.17  2004/11/09 08:15:50  rurban
332 // trim filename
333 //
334 // Revision 1.16  2004/10/21 19:03:37  rurban
335 // Be more stricter with uploads: Filenames may only contain alphanumeric
336 // characters. Patch #1037825
337 //
338 // Revision 1.15  2004/09/22 13:46:26  rurban
339 // centralize upload paths.
340 // major WikiPluginCached feature enhancement:
341 //   support _STATIC pages in uploads/ instead of dynamic getimg.php? subrequests.
342 //   mainly for debugging, cache problems and action=pdf
343 //
344 // Revision 1.14  2004/06/16 10:38:59  rurban
345 // Disallow refernces in calls if the declaration is a reference
346 // ("allow_call_time_pass_reference clean").
347 //   PhpWiki is now allow_call_time_pass_reference = Off clean,
348 //   but several external libraries may not.
349 //   In detail these libs look to be affected (not tested):
350 //   * Pear_DB odbc
351 //   * adodb oracle
352 //
353 // Revision 1.13  2004/06/14 11:31:39  rurban
354 // renamed global $Theme to $WikiTheme (gforge nameclash)
355 // inherit PageList default options from PageList
356 //   default sortby=pagename
357 // use options in PageList_Selectable (limit, sortby, ...)
358 // added action revert, with button at action=diff
359 // added option regex to WikiAdminSearchReplace
360 //
361 // Revision 1.12  2004/06/13 11:34:22  rurban
362 // fixed bug #969532 (space in uploaded filenames)
363 // improved upload error messages
364 //
365 // Revision 1.11  2004/06/11 09:07:30  rurban
366 // support theme-specific LinkIconAttr: front or after or none
367 //
368 // Revision 1.10  2004/04/12 10:19:18  rurban
369 // fixed copyright year
370 //
371 // Revision 1.9  2004/04/12 10:18:22  rurban
372 // removed the hairy regex line
373 //
374 // Revision 1.8  2004/04/12 09:12:22  rurban
375 // fix syntax errors
376 //
377 // Revision 1.7  2004/04/09 17:49:03  rurban
378 // Added PhpWiki RssFeed to Sidebar
379 // sidebar formatting
380 // some browser dependant fixes (old-browser support)
381 //
382 // Revision 1.6  2004/02/27 01:36:51  rurban
383 // autolink enabled
384 //
385 // Revision 1.5  2004/02/27 01:24:43  rurban
386 // use IntwerWiki links for uploaded file.
387 // autolink to page prepared, but not yet ready
388 //
389 // Revision 1.4  2004/02/21 19:12:59  rurban
390 // patch by Sascha Carlin
391 //
392 // Revision 1.3  2004/02/17 12:11:36  rurban
393 // 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, ...)
394 //
395 // Revision 1.2  2004/01/26 09:18:00  rurban
396 // * changed stored pref representation as before.
397 //   the array of objects is 1) bigger and 2)
398 //   less portable. If we would import packed pref
399 //   objects and the object definition was changed, PHP would fail.
400 //   This doesn't happen with an simple array of non-default values.
401 // * use $prefs->retrieve and $prefs->store methods, where retrieve
402 //   understands the interim format of array of objects also.
403 // * simplified $prefs->get() and fixed $prefs->set()
404 // * added $user->_userid and class '_WikiUser' portability functions
405 // * fixed $user object ->_level upgrading, mostly using sessions.
406 //   this fixes yesterdays problems with loosing authorization level.
407 // * fixed WikiUserNew::checkPass to return the _level
408 // * fixed WikiUserNew::isSignedIn
409 // * added explodePageList to class PageList, support sortby arg
410 // * fixed UserPreferences for WikiUserNew
411 // * fixed WikiPlugin for empty defaults array
412 // * UnfoldSubpages: added pagename arg, renamed pages arg,
413 //   removed sort arg, support sortby arg
414 //
415 // Revision 1.1  2003/11/04 18:41:41  carstenklapp
416 // New plugin which was submitted to the mailing list some time
417 // ago. (This is the best UpLoad function I have seen for PhpWiki so
418 // far. Cleaned up text formatting and typos from the version on the
419 // mailing list. Still needs a few adjustments.)
420
421 // (c-file-style: "gnu")
422 // Local Variables:
423 // mode: php
424 // tab-width: 8
425 // c-basic-offset: 4
426 // c-hanging-comment-ender-p: nil
427 // indent-tabs-mode: nil
428 // End:
429 ?>