From 80991043a9b39124165e2d27f2771e6555df4921 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Sun, 1 Jul 2007 18:24:47 +0000 Subject: [PATCH] * De-crappified JS upload dest check feature. Converted to sajax framework. Comprehensive destination checking like the previous behaviour on submission. 500ms typing delay for rate limiting, response cache. Don't display the warning on submission if the user has already seen it via AJAX. * Added support for static member functions as AJAX callbacks. * Moved all upload-related javascript to upload.js. * Needs artwork, see TODO in upload.js. * Removed UploadForm::showSuccess() as per wikitech-l discussion. Redirect to description page unconditionally. --- includes/AjaxDispatcher.php | 7 +- includes/Setup.php | 1 + includes/SpecialUpload.php | 252 ++++++++++++++++++++---------------- skins/common/upload.js | 122 ++++++++++++++++- skins/common/wikibits.js | 67 ---------- 5 files changed, 262 insertions(+), 187 deletions(-) diff --git a/includes/AjaxDispatcher.php b/includes/AjaxDispatcher.php index 452c3b33fb..7b85ed2054 100644 --- a/includes/AjaxDispatcher.php +++ b/includes/AjaxDispatcher.php @@ -84,8 +84,13 @@ class AjaxDispatcher { wfHttpError( 400, 'Bad Request', "unknown function " . (string) $this->func_name ); } else { + if ( strpos( $this->func_name, '::' ) !== false ) { + $func = explode( '::', $this->func_name, 2 ); + } else { + $func = $this->func_name; + } try { - $result = call_user_func_array($this->func_name, $this->args); + $result = call_user_func_array($func, $this->args); if ( $result === false || $result === NULL ) { wfHttpError( 500, 'Internal Error', diff --git a/includes/Setup.php b/includes/Setup.php index 9e70747276..5a20b860c2 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -257,6 +257,7 @@ $wgPostCommitUpdateList = array(); if ( $wgAjaxSearch ) $wgAjaxExportList[] = 'wfSajaxSearch'; if ( $wgAjaxWatch ) $wgAjaxExportList[] = 'wfAjaxWatch'; +if ( $wgAjaxUploadDestCheck ) $wgAjaxExportList[] = 'UploadForm::ajaxGetExistsWarning'; wfSeedRandom(); diff --git a/includes/SpecialUpload.php b/includes/SpecialUpload.php index 2922d15de7..85579f3cb3 100644 --- a/includes/SpecialUpload.php +++ b/includes/SpecialUpload.php @@ -26,7 +26,7 @@ class UploadForm { var $mDestName, $mTempPath, $mFileSize, $mFileProps; var $mCopyrightStatus, $mCopyrightSource, $mReUpload, $mAction, $mUploadClicked; var $mSrcName, $mSessionKey, $mStashed, $mDesiredDestName, $mRemoveTempFile, $mSourceType; - var $mCurlDestHandle; + var $mDestWarningAck, $mCurlDestHandle; var $mLocalFile; # Placeholders for text injection by hooks (must be HTML) @@ -65,7 +65,7 @@ class UploadForm { $this->mCopyrightSource = $request->getText( 'wpUploadSource' ); $this->mWatchthis = $request->getBool( 'wpWatchthis' ); $this->mSourceType = $request->getText( 'wpSourceType' ); - wfDebug( "UploadForm: watchthis is: '$this->mWatchthis'\n" ); + $this->mDestWarningAck = $request->getText( 'wpDestFileWarningAck' ); $this->mAction = $request->getVal( 'action' ); @@ -411,89 +411,9 @@ class UploadForm { $warning .= '
  • '.wfMsgHtml( 'emptyfile' ).'
  • '; } - global $wgUser; - $sk = $wgUser->getSkin(); - - // Check for uppercase extension. We allow these filenames but check if an image - // with lowercase extension exists already - if ( $finalExt != strtolower( $finalExt ) ) { - $nt_lc = Title::newFromText( $partname . '.' . strtolower( $finalExt ) ); - $image_lc = wfLocalFile( $nt_lc ); - } - - if( $this->mLocalFile->exists() ) { - $dlink = $sk->makeKnownLinkObj( $nt ); - if ( $this->mLocalFile->allowInlineDisplay() ) { - $dlink2 = $sk->makeImageLinkObj( $nt, wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), - $nt->getText(), 'right', array(), false, true ); - } elseif ( !$this->mLocalFile->allowInlineDisplay() && $this->mLocalFile->isSafeFile() ) { - $icon = $this->mLocalFile->iconThumb(); - $dlink2 = '
    ' . - $icon->toHtml() . '
    ' . $dlink . '
    '; - } else { - $dlink2 = ''; - } - - $warning .= '
  • ' . wfMsgExt( 'fileexists', 'parseline', $dlink ) . '
  • ' . $dlink2; - - } elseif ( isset( $image_lc) && $image_lc->exists() ) { - # Check if image with lowercase extension exists. - # It's not forbidden but in 99% it makes no sense to upload the same filename with uppercase extension - $dlink = $sk->makeKnownLinkObj( $nt_lc ); - if ( $image_lc->allowInlineDisplay() ) { - $dlink2 = $sk->makeImageLinkObj( $nt_lc, wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), - $nt_lc->getText(), 'right', array(), false, true ); - } elseif ( !$image_lc->allowInlineDisplay() && $image_lc->isSafeFile() ) { - $icon = $image_lc->iconThumb(); - $dlink2 = '
    ' . - $icon->toHtml() . '
    ' . $dlink . '
    '; - } else { - $dlink2 = ''; - } - - $warning .= '
  • ' . wfMsgExt( 'fileexists-extension', 'parsemag' , $partname . '.' - . $finalExt , $dlink ) . '
  • ' . $dlink2; - - } elseif ( ( substr( $partname , 3, 3 ) == 'px-' || substr( $partname , 2, 3 ) == 'px-' ) - && ereg( "[0-9]{2}" , substr( $partname , 0, 2) ) ) - { - # Check for filenames like 50px- or 180px-, these are mostly thumbnails - $nt_thb = Title::newFromText( substr( $partname , strpos( $partname , '-' ) +1 ) . '.' . $finalExt ); - $image_thb = wfLocalFile( $nt_thb ); - if ($image_thb->exists() ) { - # Check if an image without leading '180px-' (or similiar) exists - $dlink = $sk->makeKnownLinkObj( $nt_thb); - if ( $image_thb->allowInlineDisplay() ) { - $dlink2 = $sk->makeImageLinkObj( $nt_thb, - wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), - $nt_thb->getText(), 'right', array(), false, true ); - } elseif ( !$image_thb->allowInlineDisplay() && $image_thb->isSafeFile() ) { - $icon = $image_thb->iconThumb(); - $dlink2 = '
    ' . $icon->toHtml() . '
    ' . - $dlink . '
    '; - } else { - $dlink2 = ''; - } - - $warning .= '
  • ' . wfMsgExt( 'fileexists-thumbnail-yes', 'parsemag', $dlink ) . - '
  • ' . $dlink2; - } else { - # Image w/o '180px-' does not exists, but we do not like these filenames - $warning .= '
  • ' . wfMsgExt( 'file-thumbnail-no', 'parseinline' , - substr( $partname , 0, strpos( $partname , '-' ) +1 ) ) . '
  • '; - } - } - if ( $this->mLocalFile->wasDeleted() ) { - # If the file existed before and was deleted, warn the user of this - # Don't bother doing so if the image exists now, however - $ltitle = SpecialPage::getTitleFor( 'Log' ); - $llink = $sk->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ), - 'type=delete&page=' . $nt->getPrefixedUrl() ); - $warning .= wfOpenElement( 'li' ) . wfMsgWikiHtml( 'filewasdeleted', $llink ) . - wfCloseElement( 'li' ); + if ( !$this->mDestWarningAck ) { + $warning .= self::getExistsWarning( $this->mLocalFile ); } - if( $warning != '' ) { /** * Stash the file in a temporary location; the user can choose @@ -519,15 +439,122 @@ class UploadForm { global $wgUser; $wgUser->addWatch( $this->mLocalFile->getTitle() ); } - if ( $status === '' ) { - // New upload, redirect to description page - $wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() ); + // Success, redirect to description page + $wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() ); + wfRunHooks( 'UploadComplete', array( &$img ) ); + } + } + + /** + * Do existence checks on a file and produce a warning + * This check is static and can be done pre-upload via AJAX + * Returns an HTML fragment consisting of one or more LI elements if there is a warning + * Returns an empty string if there is no warning + */ + static function getExistsWarning( $file ) { + global $wgUser; + // Check for uppercase extension. We allow these filenames but check if an image + // with lowercase extension exists already + $warning = ''; + $ext = $file->getExtension(); + $sk = $wgUser->getSkin(); + if ( $ext !== '' ) { + $partname = substr( $file->getName(), 0, -strlen( $ext ) - 1 ); + } else { + $partname = $file->getName(); + } + + if ( $ext != strtolower( $ext ) ) { + $nt_lc = Title::newFromText( $partname . '.' . strtolower( $ext ) ); + $file_lc = wfLocalFile( $nt_lc ); + } else { + $file_lc = false; + } + + if( $file->exists() ) { + $dlink = $sk->makeKnownLinkObj( $file->getTitle() ); + if ( $file->allowInlineDisplay() ) { + $dlink2 = $sk->makeImageLinkObj( $file->getTitle(), wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), + $file->getName(), 'right', array(), false, true ); + } elseif ( !$file->allowInlineDisplay() && $file->isSafeFile() ) { + $icon = $file->iconThumb(); + $dlink2 = '
    ' . + $icon->toHtml() . '
    ' . $dlink . '
    '; } else { - // Reupload, show success page - $this->showSuccess(); + $dlink2 = ''; + } + + $warning .= '
  • ' . wfMsgExt( 'fileexists', 'parseline', $dlink ) . '
  • ' . $dlink2; + + } elseif ( $file_lc && $file_lc->exists() ) { + # Check if image with lowercase extension exists. + # It's not forbidden but in 99% it makes no sense to upload the same filename with uppercase extension + $dlink = $sk->makeKnownLinkObj( $nt_lc ); + if ( $file_lc->allowInlineDisplay() ) { + $dlink2 = $sk->makeImageLinkObj( $nt_lc, wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), + $nt_lc->getText(), 'right', array(), false, true ); + } elseif ( !$file_lc->allowInlineDisplay() && $file_lc->isSafeFile() ) { + $icon = $file_lc->iconThumb(); + $dlink2 = '
    ' . + $icon->toHtml() . '
    ' . $dlink . '
    '; + } else { + $dlink2 = ''; + } + + $warning .= '
  • ' . wfMsgExt( 'fileexists-extension', 'parsemag' , $partname . '.' + . $ext , $dlink ) . '
  • ' . $dlink2; + + } elseif ( ( substr( $partname , 3, 3 ) == 'px-' || substr( $partname , 2, 3 ) == 'px-' ) + && ereg( "[0-9]{2}" , substr( $partname , 0, 2) ) ) + { + # Check for filenames like 50px- or 180px-, these are mostly thumbnails + $nt_thb = Title::newFromText( substr( $partname , strpos( $partname , '-' ) +1 ) . '.' . $ext ); + $file_thb = wfLocalFile( $nt_thb ); + if ($file_thb->exists() ) { + # Check if an image without leading '180px-' (or similiar) exists + $dlink = $sk->makeKnownLinkObj( $nt_thb); + if ( $file_thb->allowInlineDisplay() ) { + $dlink2 = $sk->makeImageLinkObj( $nt_thb, + wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), + $nt_thb->getText(), 'right', array(), false, true ); + } elseif ( !$file_thb->allowInlineDisplay() && $file_thb->isSafeFile() ) { + $icon = $file_thb->iconThumb(); + $dlink2 = '
    ' . $icon->toHtml() . '
    ' . + $dlink . '
    '; + } else { + $dlink2 = ''; + } + + $warning .= '
  • ' . wfMsgExt( 'fileexists-thumbnail-yes', 'parsemag', $dlink ) . + '
  • ' . $dlink2; + } else { + # Image w/o '180px-' does not exists, but we do not like these filenames + $warning .= '
  • ' . wfMsgExt( 'file-thumbnail-no', 'parseinline' , + substr( $partname , 0, strpos( $partname , '-' ) +1 ) ) . '
  • '; } - wfRunHooks( 'UploadComplete', array( &$img ) ); } + if ( $file->wasDeleted() ) { + # If the file existed before and was deleted, warn the user of this + # Don't bother doing so if the image exists now, however + $ltitle = SpecialPage::getTitleFor( 'Log' ); + $llink = $sk->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ), + 'type=delete&page=' . $file->getTitle()->getPrefixedUrl() ); + $warning .= '
  • ' . wfMsgWikiHtml( 'filewasdeleted', $llink ) . '
  • '; + } + return $warning; + } + + static function ajaxGetExistsWarning( $filename ) { + $file = wfFindFile( $filename ); + $s = ' '; + if ( $file ) { + $warning = self::getExistsWarning( $file ); + if ( $warning !== '' ) { + $s = ""; + } + } + return $s; } /** @@ -601,24 +628,6 @@ class UploadForm { /* -------------------------------------------------------------- */ - /** - * Show some text and linkage on successful upload. - * @access private - */ - function showSuccess() { - global $wgUser, $wgOut, $wgContLang; - - $sk = $wgUser->getSkin(); - $ilink = $sk->makeMediaLinkObj( $this->mLocalFile->getTitle() ); - $dname = $wgContLang->getNsText( NS_IMAGE ) . ':'.$this->mDestName; - $dlink = $sk->makeKnownLink( $dname, $dname ); - - $wgOut->addHTML( '

    ' . wfMsgHtml( 'successfulupload' ) . "

    \n" ); - $text = wfMsgWikiHtml( 'fileuploaded', $ilink, $dlink ); - $wgOut->addHTML( $text ); - $wgOut->returnToMain( false ); - } - /** * @param string $error as HTML * @access private @@ -703,8 +712,15 @@ class UploadForm { */ function mainUploadForm( $msg='' ) { global $wgOut, $wgUser; - global $wgUseCopyrightUpload; - global $wgRequest, $wgAllowCopyUploads; + global $wgUseCopyrightUpload, $wgAjaxUploadDestCheck; + global $wgRequest, $wgAllowCopyUploads, $wgEnableAPI; + global $wgStylePath; + + $wgOut->addScript( + "\n" . + "\n" + ); if( !wfRunHooks( 'UploadForm:initial', array( &$this ) ) ) { @@ -776,6 +792,14 @@ class UploadForm { "size='40' />" . "" ; } + if ( $wgAjaxUploadDestCheck ) { + $warningRow = " "; + $destOnkeyup = 'onkeyup="wgUploadWarningObj.keypress();"'; + } else { + $warningRow = ''; + $destOnkeyup = ''; + } + $encComment = htmlspecialchars( $this->mComment ); $wgOut->addHTML( << - + @@ -811,7 +836,6 @@ EOT $wgOut->addHTML( " - - @@ -868,6 +891,7 @@ EOT + " ); } diff --git a/skins/common/upload.js b/skins/common/upload.js index 160fbf27a2..7c66e6d832 100644 --- a/skins/common/upload.js +++ b/skins/common/upload.js @@ -11,11 +11,123 @@ function licenseSelectorFixup() { // for MSIE/Mac; non-breaking spaces cause the