r105915 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105914‎ | r105915 | r105916 >
Date:18:59, 12 December 2011
Author:cneubauer
Status:deferred
Tags:
Comment:
Rename to UploadLocal.
Modified paths:
  • /trunk/extensions/SpecialUploadLocal (deleted) (history)
  • /trunk/extensions/UploadLocal (added) (history)
  • /trunk/extensions/UploadLocal/SpecialUploadLocal.i18n.php (deleted) (history)
  • /trunk/extensions/UploadLocal/SpecialUploadLocal.php (deleted) (history)
  • /trunk/extensions/UploadLocal/SpecialUploadLocal_body.php (deleted) (history)
  • /trunk/extensions/UploadLocal/UploadLocal.i18n.php (added) (history)
  • /trunk/extensions/UploadLocal/UploadLocal.php (added) (history)
  • /trunk/extensions/UploadLocal/UploadLocalDirectory.php (modified) (history)
  • /trunk/extensions/UploadLocal/UploadLocal_body.php (added) (history)

Diff [purge]

Index: trunk/extensions/UploadLocal/UploadLocal_body.php
@@ -0,0 +1,20 @@
 2+<?php
 3+
 4+class UploadLocal extends SpecialPage {
 5+ function __construct() {
 6+ parent::__construct( 'UploadLocal', 'uploadlocal' );
 7+ wfLoadExtensionMessages( 'UploadLocal' );
 8+ }
 9+
 10+ function execute( $par ) {
 11+ global $wgRequest, $wgUploadLocalDirectory, $wgMessageCache;
 12+ wfLoadExtensionMessages( 'UploadLocal' );
 13+
 14+ $prefix = 'extensions/UploadLocal/';
 15+ require($prefix . 'UploadLocalDirectory.php');
 16+ require($prefix . 'UploadLocalForm.php');
 17+
 18+ $directory = new UploadLocalDirectory($wgRequest, $wgUploadLocalDirectory);
 19+ $directory->execute();
 20+ }
 21+}
Property changes on: trunk/extensions/UploadLocal/UploadLocal_body.php
___________________________________________________________________
Added: svn:eol-style
122 + native
Index: trunk/extensions/UploadLocal/UploadLocal.i18n.php
@@ -0,0 +1,46 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for SpecialUploadLocal extension.
 5+ *
 6+ * @package MediaWiki
 7+ * @subpackage Extensions
 8+*/
 9+$messages = array();
 10+
 11+$messages['en'] = array(
 12+ 'specialuploadlocal' => 'Upload Local Files',
 13+ 'uploadlocal' => 'Upload local files',
 14+ 'uploadlocal_directory_readonly' => 'The local upload directory ($1) is'.
 15+ ' not writeable by the webserver.',
 16+ 'uploadlocaltext' => 'Use this form to mass upload files already on the'.
 17+ ' server in the upload local directory. You can find out more'.
 18+ ' general information at [[Special:Upload|the regular upload file'.
 19+ ' page]].',
 20+ 'uploadlocalbtn' => 'Upload local files',
 21+ 'nolocalfiles' => 'There are no files in the local upload folder. Try'.
 22+ ' placing some files in "<code>$1</code>."',
 23+ 'uploadednolocalfiles' => 'You did not upload any files.',
 24+ 'allfilessuccessful' => 'All files uploaded successfully',
 25+ 'uploadlocalerrors' => 'Some files had errors',
 26+ 'allfilessuccessfultext' => 'All files uploaded successfully. Return to'.
 27+ ' [[Main Page]].',
 28+ 'uploadlocal_descriptions_append' => 'Append to description: ',
 29+ 'uploadlocal_descriptions_prepend' => 'Prepend to description: ',
 30+ 'uploadlocal_dest_file_append' => 'Append to dest. filename: ',
 31+ 'uploadlocal_dest_file_prepend' => 'Prepend to dest. filename: ',
 32+ 'uploadlocal_file_list' => 'Files ready for upload',
 33+ 'uploadlocal_file_list_explanation' => '\'\'\'X\'\'\' indicates'.
 34+ ' whether or not you want the file to be uploaded (uncheck to'.
 35+ ' prevent a file from being processed). \'\'\'W\'\'\' indicates'.
 36+ ' whether you want the file added to your watchlist.',
 37+ 'uploadlocal_global_params' => 'Global parameters',
 38+ 'uploadlocal_global_params_explanation' => 'What is entered here will'.
 39+ ' automatically get added to the entries listed above. This helps'.
 40+ ' remove repetitive text such as categories and metadata. To \'\'\''.
 41+ 'append\'\'\' is to add to the end of text, while to \'\'\'prepend'.
 42+ '\'\'\' means to add to the beginning of text. Especially for'.
 43+ ' descriptions, make sure you give a few linebreaks before/after'.
 44+ ' the text.',
 45+
 46+ 'right-uploadlocal' => 'Upload files from the local machine'
 47+);
Property changes on: trunk/extensions/UploadLocal/UploadLocal.i18n.php
___________________________________________________________________
Added: svn:eol-style
148 + native
Index: trunk/extensions/UploadLocal/UploadLocal.php
@@ -0,0 +1,36 @@
 2+<?php
 3+if (!defined('MEDIAWIKI')) die();
 4+
 5+/*
 6+
 7+TODO:
 8+ * Considered more advanced file scanning regexps/recursive searching
 9+ * Allow unzipping without ssh'ing (need a tar library or shell)
 10+ * Migrate repository to Mercurial so we can easily push changes
 11+
 12+BUGS:
 13+ * Figure out how to get image overwrites to work properly or fail gracefully
 14+ * Warn when filename contains ampersand. (Apache doesn't like that)
 15+
 16+ENHANCEMENTS:
 17+ * Mute extra output from the new page function.
 18+ * Remove debugging info.
 19+ * Dry run capability.
 20+
 21+*/
 22+
 23+$wgExtensionCredits['specialpage'][] = array(
 24+ 'name' => 'UploadLocal',
 25+ 'description' => 'allows users to link in files already on the server'
 26+);
 27+$wgSpecialPages['UploadLocal'] = 'UploadLocal';
 28+$wgExtensionMessagesFiles['UploadLocal'] = dirname( __FILE__ ) . '/UploadLocal.i18n.php';
 29+$wgAutoloadClasses[ 'UploadLocal' ] = dirname( __FILE__ ) . '/UploadLocal_body.php';
 30+$wgAutoloadClasses[ 'WebRequestUploadLocal' ] = dirname( __FILE__ ) . '/WebRequestUploadLocal.php';
 31+
 32+$wgUploadLocalDirectory = $IP . '/extensions/UploadLocal/data';
 33+
 34+$wgAvailableRights[] = 'uploadlocal';
 35+$wgGroupPermissions['uploader']['uploadlocal'] = true;
 36+$wgGroupPermissions['sysop'] ['uploadlocal'] = true;
 37+$wgSpecialPageGroups['UploadLocal'] = 'media';
Property changes on: trunk/extensions/UploadLocal/UploadLocal.php
___________________________________________________________________
Added: svn:eol-style
138 + native
Index: trunk/extensions/UploadLocal/UploadLocalForm.php
@@ -0,0 +1,93 @@
 2+<?php
 3+class UploadLocalForm {
 4+
 5+ var $_error = '';
 6+ var $_filename;
 7+
 8+ /**
 9+ * With our parameters, simulate a request
 10+ */
 11+ function UploadLocalForm($filename, $description, $watch, $dest) {
 12+ global $wgUploadLocalDirectory;
 13+
 14+ // Prepare our directory
 15+ $dir = $wgUploadLocalDirectory;
 16+ if ($dir[strlen($dir)-1] !== '/') $dir .= '/';
 17+
 18+ $this->_filename = $filename;
 19+ $this->comment = $description;
 20+ $this->watch = $watch;
 21+ $this->mDesiredDestName = $dest;
 22+ $name = $dir . $filename;
 23+
 24+ $this->upload = new UploadFromFile();
 25+ $fileInfo = array(
 26+ 'name' => $dest,
 27+ 'size' => filesize( $name ),
 28+ 'tmp_name' => $name,
 29+ 'error' => 0
 30+ );
 31+ $this->upload->initialize( $name, new WebRequestUploadLocal( true, $fileInfo ) );
 32+ }
 33+
 34+ function processUpload( $user ) {
 35+ # Have to call this line to set the extension to avoid a VERIFICATION_ERROR
 36+ $title = $this->upload->getTitle();
 37+
 38+ # Check for warnings like the file already exists in the wiki
 39+ $warnings = $this->upload->checkWarnings();
 40+ if ( $warnings && isset( $warnings['exists'] ) && $warnings['exists']['warning'] != 'was-deleted' ) {
 41+ $this->uploadError( 'The file '.$warnings['exists']['file']->getName().' already exists' );
 42+ return;
 43+ }
 44+
 45+ # Check for verificatoins that the upload succeded.
 46+ $verification = $this->upload->verifyUpload();
 47+ if ( $verification['status'] === UploadBase::OK ) {
 48+ $this->upload->performUpload( $this->comment, $this->comment, $this->watch, $user );
 49+
 50+ // Cleanup any temporary mess
 51+ $this->upload->cleanupTempFile();
 52+ } else {
 53+ switch( $verification['status'] ) {
 54+ case UploadBase::EMPTY_FILE:
 55+ $this->uploadError( 'The file you submitted was empty' );
 56+ break;
 57+ case UploadBase::FILETYPE_MISSING:
 58+ $this->uploadError( 'The file is missing an extension' );
 59+ break;
 60+ case UploadBase::FILETYPE_BADTYPE:
 61+ global $wgFileExtensions;
 62+ $this->uploadError( 'This type of file is banned' );
 63+ break;
 64+ case UploadBase::MIN_LENGTH_PARTNAME:
 65+ $this->uploadError( 'The filename is too short' );
 66+ break;
 67+ case UploadBase::ILLEGAL_FILENAME:
 68+ $this->uploadError( 'The filename is not allowed' );
 69+ break;
 70+ case UploadBase::OVERWRITE_EXISTING_FILE:
 71+ $this->uploadError( 'Overwriting an existing file is not allowed' );
 72+ break;
 73+ case UploadBase::VERIFICATION_ERROR:
 74+ $this->uploadError( 'This file did not pass file verification: ' . $verification['details'][0] );
 75+ break;
 76+ case UploadBase::HOOK_ABORTED:
 77+ $this->uploadError( "The modification you tried to make was aborted by an extension hook" );
 78+ break;
 79+ default:
 80+ $this->uploadError( 'An unknown error occurred' );
 81+ break;
 82+ }
 83+ }
 84+ }
 85+
 86+ function getFilename() {return $this->_filename;}
 87+ function getUploadSaveName() {return $this->mDesiredDestName;}
 88+
 89+ function mainUploadForm($msg='') {$this->_error = $msg;}
 90+ function uploadError($error) {$this->_error = $error;}
 91+ function showSuccess() {}
 92+
 93+ function getError() {return $this->_error;}
 94+}
Property changes on: trunk/extensions/UploadLocal/UploadLocalForm.php
___________________________________________________________________
Added: svn:eol-style
195 + native
Index: trunk/extensions/UploadLocal/data/.htaccess
@@ -0,0 +1 @@
 2+Deny from all
Property changes on: trunk/extensions/UploadLocal/data/.htaccess
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: trunk/extensions/UploadLocal/UploadLocalDirectory.php
@@ -0,0 +1,230 @@
 2+<?php
 3+class UploadLocalDirectory {
 4+
 5+ var $_directory;
 6+ var $_was_posted;
 7+ var $_available_files;
 8+
 9+ function UploadLocalDirectory($request, $directory) {
 10+ $this->_directory = $directory;
 11+ $this->_was_posted = $request->wasPosted();
 12+ $this->_available_files = $this->getFilenamesOfFilesInDirectory($directory);
 13+ }
 14+
 15+ function execute() {
 16+ global $wgOut, $wgRequest, $wgUser, $wgEnableUploads,
 17+ $wgUploadDirectory;
 18+
 19+ // a bit of this is stolen from the SpecialUpload code, duplication
 20+ // is bad but there was no way to meaningfully integrate it into
 21+ // this code.
 22+
 23+ if( ! $wgEnableUploads ) {
 24+ $wgOut->addWikiText( wfMsg( 'uploaddisabled' ) );
 25+ return;
 26+ }
 27+
 28+ // uses extension specific permission "uploadlocal"
 29+ if (!$wgUser->isAllowed( 'uploadlocal' ) || $wgUser->isBlocked() ) {
 30+ $wgOut->errorpage( 'uploadnologin', 'uploadnologintext' );
 31+ return;
 32+ }
 33+
 34+ if( wfReadOnly() ) {
 35+ $wgOut->readOnlyPage();
 36+ return;
 37+ }
 38+
 39+ // check if both relevant directories are writeable
 40+ if ( !is_writeable( $wgUploadDirectory ) ) {
 41+ $wgOut->addWikiText( wfMsg( 'upload_directory_read_only', $wgUploadDirectory ) );
 42+ return;
 43+ }
 44+ if ( !is_writeable($this->_directory) ) {
 45+ $wgOut->addWikiText( wfMsg( 'upload_directory_read_only', $this->_directory ) );
 46+ return;
 47+ }
 48+
 49+ // check if there are any files to upload
 50+ if (empty($this->_available_files)) {
 51+ $wgOut->addWikitext( wfMsg( 'uploadlocaltext' ) );
 52+ $wgOut->addWikitext( wfMsg( 'nolocalfiles', htmlentities($this->_directory) ) );
 53+ return;
 54+ }
 55+
 56+ if ($this->_was_posted) {
 57+ $this->processUploads($wgRequest,$wgUser);
 58+ } else {
 59+ $this->showForm();
 60+ }
 61+
 62+ }
 63+
 64+ function showForm() {
 65+ global $wgOut;
 66+
 67+ $wgOut->addWikitext( wfMsg( 'uploadlocaltext' ) );
 68+
 69+ $titleObj = Title::makeTitle( NS_SPECIAL, 'UploadLocal' );
 70+ $action = $titleObj->escapeLocalURL();
 71+
 72+ $wgOut->addHTML('<form id="uploadlocal" method="post"'.
 73+ ' enctype="multipart/form-data" action="'.$action.'">');
 74+
 75+ $wgOut->addWikitext('==' . wfMsg('uploadlocal_file_list') . '==');
 76+ $wgOut->addWikitext(wfMsg('uploadlocal_file_list_explanation'));
 77+
 78+ $html = '';
 79+
 80+ $html .= '<table border="0" cellspacing="0" style="width:100%;">';
 81+ $html .= '<theader>'.
 82+ '<tr><th style="width:1em;">X</th>'.
 83+ '<th style="width:1em;">W</th>'.
 84+ '<th style="width:10em;text-align:left;">'.wfMsg('sourcefilename').'</th>'.
 85+ '<th style="width:10em;text-align:left;">'.wfMsg('destfilename').'</th>'.
 86+ '<th style="text-align:left;">'.wfMsg('filedesc').'</th></tr></theader>';
 87+ $html .= '<tbody>';
 88+ $i = 1;
 89+ foreach ($this->_available_files as $file) {
 90+ $html_file = htmlentities($file);
 91+ $html .= '<tr' .
 92+ ($i % 2 ? ' style="background-color:#EEE;"' : '') .
 93+ '>'.
 94+ '<td><input type="checkbox" checked="checked"'.
 95+ ' name="wpUploadFiles['.$i.']" value="'.$html_file.'" /></td>'.
 96+ '<td><input type="checkbox" checked="checked"'.
 97+ ' name="wpWatchThese['.$i.']" value="'.$html_file.'" /></td>'.
 98+ '<td>'.$html_file.'</td>'.
 99+ '<td><input type="text" name="wpDestFiles['.$i.']"'.
 100+ ' value="'.$html_file.'" /></td>'.
 101+ '<td style="width:50%;">'.
 102+ '<textarea name="wpUploadDescriptions['.$i.']" cols="60" '.
 103+ 'rows="2" style="width:100%;"></textarea></td>'.
 104+ '</tr>';
 105+ $i++;
 106+ }
 107+ $html .= '</tbody></table>';
 108+
 109+ $wgOut->addHTML($html);
 110+ $wgOut->addWikitext('==' . wfMsg('uploadlocal_global_params') . '==');
 111+ $wgOut->addWikitext(wfMsg('uploadlocal_global_params_explanation'));
 112+ $html = '';
 113+
 114+ $html .= '<table border="0" style="width:100%;">';
 115+ $html .= '<tbody>'.
 116+ '<tr><th style="text-align:right;width:25%;">'.wfMsg('uploadlocal_descriptions_prepend').'</th>'.
 117+ '<td><textarea cols="70" rows="3" style="width:100%;" name="wpUploadDescriptionsPrepend"></textarea></td></tr>'.
 118+
 119+ '<tr><th style="text-align:right;">'.wfMsg('uploadlocal_descriptions_append').'</th>'.
 120+ '<td><textarea cols="70" rows="3" style="width:100%;" name="wpUploadDescriptionsAppend"></textarea></td></tr>'.
 121+
 122+ '<tr><th style="text-align:right;">'.wfMsg('uploadlocal_dest_file_prepend').'</th>'.
 123+ '<td><input type="text" style="width:100%;" name="wpDestFilesPrepend" /></td></tr>'.
 124+
 125+ '<tr><th style="text-align:right;">'.wfMsg('uploadlocal_dest_file_append').'</th>'.
 126+ '<td><input type="text" style="width:100%;" name="wpDestFilesAppend" /></td></tr>'.
 127+
 128+ '</tbody>';
 129+ $html .= '</table>';
 130+
 131+ $html .= '<input type="submit" name="wpUploadLocal" value="'.wfMsg('uploadlocalbtn').'" /></form>';
 132+
 133+ $wgOut->addHTML($html);
 134+ }
 135+
 136+ function getFilenamesOfFilesInDirectory($directory) {
 137+ if (!is_dir($directory)) return array();
 138+ if ($directory[strlen($directory)-1] !== '/') $directory .= '/';
 139+ $dh = opendir($directory);
 140+ $filenames = array();
 141+ while (($file = readdir($dh)) !== false) {
 142+ if ($file == '.' || $file == '..') continue;
 143+ // check if it's a directory
 144+ if (is_dir($directory . $file)) continue;
 145+ // check if it's a hidden file - regexp: /\.[^.]+/
 146+ if ($file[0] == '.' && strpos($file,'.',1) === false) {
 147+ continue;
 148+ }
 149+ $filenames[] = $file;
 150+ }
 151+ closedir($dh);
 152+ return $filenames;
 153+ }
 154+
 155+ function processUploads( $request, $user ) {
 156+ global $wgOut, $wgContLang;
 157+
 158+ $r_files = $request->getArray('wpUploadFiles', array());
 159+ $r_descriptions = $request->getArray('wpUploadDescriptions', array());
 160+ $r_watch_these = $request->getArray('wpWatchThese', array());
 161+ $r_dest_files = $request->getArray('wpDestFiles', array());
 162+
 163+ $r_descriptions_prepend = $request->getVal('wpUploadDescriptionsPrepend' , '');
 164+ $r_descriptions_append = $request->getVal('wpUploadDescriptionsAppend', '');
 165+ $r_dest_files_prepend = $request->getVal('wpDestFilesPrepend', '');
 166+ $r_dest_files_append = $request->getVal('wpDestFilesAppend', '');
 167+
 168+ $files_to_process = array();
 169+ $forms = array();
 170+
 171+ foreach ($r_files as $i => $file) {
 172+ if (!in_array($file, $this->_available_files)) continue;
 173+ // Build destination filename
 174+ $r_dest_file = $r_dest_files_prepend . (isset($r_dest_files[$i]) ?
 175+ $r_dest_files[$i] : $file);
 176+ $p = strrpos($r_dest_file, '.');
 177+ if ($p !== false) {
 178+ $r_dest_file = substr($r_dest_file, 0, $p) . $r_dest_files_append
 179+ . substr($r_dest_file, $p);
 180+ } else {
 181+ $r_dest_file = $r_dest_file . $r_dest_files_append;
 182+ }
 183+
 184+ $forms[] = new UploadLocalForm(
 185+ $file,
 186+ $r_descriptions_prepend . ($r_descriptions_prepend ? "\n" : '') .
 187+ (isset($r_descriptions[$i]) ? $r_descriptions[$i] : '') .
 188+ ($r_descriptions_append ? "\n" : '') . $r_descriptions_append,
 189+ in_array($file, $r_watch_these),
 190+ $r_dest_file
 191+ );
 192+
 193+ }
 194+
 195+ if (empty($forms)) {
 196+ $wgOut->addWikitext( wfMsg( 'uploadednolocalfiles' ) );
 197+ return;
 198+ }
 199+ $no_error = true;
 200+ $errors = array();
 201+
 202+ foreach($forms as $key => $value) {
 203+ $forms[$key]->processUpload( $user );
 204+ if ($forms[$key]->getError()) {
 205+ $errors[$forms[$key]->getFilename()] = $forms[$key]->getError();
 206+ unset($forms[$key]);
 207+ }
 208+ }
 209+ //ugly hack to stop the thing from redirecting. Really annoying.
 210+ $wgOut->redirect('');
 211+
 212+ if (empty($errors)) {
 213+ $wgOut->setPageTitle(wfMsg('allfilessuccessful'));
 214+ $wgOut->addWikitext(wfMsg('allfilessuccessfultext'));
 215+ } else {
 216+ $wgOut->setPageTitle(wfMsg('uploadlocalerrors'));
 217+ $wgOut->addHTML('<ul>');
 218+ foreach ($errors as $name => $error) {
 219+ $wgOut->addHTML('<li>'.$name.' - '.$error.'</li>');
 220+ }
 221+ $wgOut->addHTML('</ul>');
 222+ }
 223+
 224+ $links_to_images = '';
 225+ foreach($forms as $key => $form) {
 226+ // language-neutral namespacing thanks to Eric Lemoine
 227+ $links_to_images .= '* [[:'.$wgContLang->getNsText( NS_IMAGE ).':'.$forms[$key]->getUploadSaveName().']]'."\n";
 228+ }
 229+ $wgOut->addWikitext($links_to_images);
 230+ }
 231+}
Property changes on: trunk/extensions/UploadLocal/UploadLocalDirectory.php
___________________________________________________________________
Added: svn:eol-style
1232 + native
Index: trunk/extensions/UploadLocal/WebRequestUploadLocal.php
@@ -0,0 +1,23 @@
 2+<?php
 3+class WebRequestUploadLocal extends WebRequestUpload {
 4+ /**
 5+ * Constructor.
 6+ *
 7+ * @param $doesExist Boolean True if the file exists.
 8+ * @param $fileInfo Array The file information object.
 9+ */
 10+ public function __construct( $doesExist, $fileInfo ) {
 11+ $this->doesExist = $doesExist;
 12+ $this->fileInfo = $fileInfo;
 13+ }
 14+
 15+ /**
 16+ * Returns whether this upload failed because of overflow of a maximum set
 17+ * in php.ini. Always false when uploading locally.
 18+ *
 19+ * @return bool
 20+ */
 21+ public function isIniSizeOverflow() {
 22+ return false;
 23+ }
 24+}
Property changes on: trunk/extensions/UploadLocal/WebRequestUploadLocal.php
___________________________________________________________________
Added: svn:eol-style
125 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r106644r105915: Some consistency tweaks:...raymond11:43, 19 December 2011

Status & tagging log