From: Raimond Spekking Date: Wed, 19 Mar 2008 16:58:56 +0000 (+0000) Subject: * (bug 1459) Search for duplicate files by hash: Special:FileDuplicateSearch X-Git-Tag: 1.31.0-rc.0~48974 X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=commitdiff_plain;h=fd9af62bb5adf652a3cdbe78104dd13ce0c91952;p=lhc%2Fweb%2Fwiklou.git * (bug 1459) Search for duplicate files by hash: Special:FileDuplicateSearch * Add a link on the image description page to Special:FileDuplicateSearch/filename.ext --- diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 63cfdd6d6b..626fd5c3bf 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -48,6 +48,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * Add updatelog table to reliably permit updates that don't change the schema * Add category table to allow better tracking of category membership counts ** (bug 1212) Give correct membership counts on the pages of large categories +* (bug 1459) Search for duplicate files by hash: Special:FileDuplicateSearch === Bug fixes in 1.13 === diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index c702586430..cd315cd279 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -91,6 +91,7 @@ function __autoload($className) { 'FewestrevisionsPage' => 'includes/SpecialFewestrevisions.php', 'FileDeleteForm' => 'includes/FileDeleteForm.php', 'FileDependency' => 'includes/CacheDependency.php', + 'FileDuplicateSearch' => 'includes/SpecialFileDuplicateSearch.php', 'FileRevertForm' => 'includes/FileRevertForm.php', 'FileStore' => 'includes/FileStore.php', 'FormatExif' => 'includes/Exif.php', diff --git a/includes/ImagePage.php b/includes/ImagePage.php index a39da0a501..0ff75d20df 100644 --- a/includes/ImagePage.php +++ b/includes/ImagePage.php @@ -397,7 +397,11 @@ EOT $ulink = $sk->makeExternalLink( $this->getUploadUrl(), wfMsg( 'uploadnewversion-linktext' ) ); $wgOut->addHtml( "
  • " ); } - + + # Link to Special:FileDuplicateSearch + $dupeLink = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'FileDuplicateSearch', $this->mTitle->getDBkey() ), wfMsgHtml( 'imagepage-searchdupe' ) ); + $wgOut->addHtml( "
  • {$dupeLink}
  • " ); + # External editing link $elink = $sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml( 'edit-externally' ), 'action=edit&externaledit=true&mode=file' ); $wgOut->addHtml( '
  • ' . $elink . '
    ' . wfMsgWikiHtml( 'edit-externally-help' ) . '
  • ' ); diff --git a/includes/SpecialFileDuplicateSearch.php b/includes/SpecialFileDuplicateSearch.php new file mode 100644 index 0000000000..c48ffadcda --- /dev/null +++ b/includes/SpecialFileDuplicateSearch.php @@ -0,0 +1,133 @@ +hash = $hash; + $this->filename = $filename; + } + + function getName() { return 'FileDuplicateSearch'; } + function isExpensive() { return false; } + function isSyndicated() { return false; } + + function linkParameters() { + return array( 'filename' => $this->filename ); + } + + function getSQL() { + $dbr = wfGetDB( DB_SLAVE ); + $image = $dbr->tableName( 'image' ); + $hash = $dbr->addQuotes( $this->hash ); + + return "SELECT 'FileDuplicateSearch' AS type, + img_name AS title, + img_sha1 AS value, + img_user_text, + img_timestamp + FROM $image + WHERE img_sha1 = $hash + "; + } + + function formatResult( $skin, $result ) { + global $wgContLang, $wgLang; + + $nt = Title::makeTitle( NS_IMAGE, $result->title ); + $text = $wgContLang->convert( $nt->getText() ); + $plink = $skin->makeLink( $nt->getPrefixedText(), $text ); + + $user = $skin->makeLinkObj( Title::makeTitle( NS_USER, $result->img_user_text ), $result->img_user_text ); + $time = $wgLang->timeanddate( $result->img_timestamp ); + + return "$plink . . $user . . $time"; + } +} + +/** + * Output the HTML search form, and constructs the FileDuplicateSearch object. + */ +function wfSpecialFileDuplicateSearch( $par = null ) { + global $wgRequest, $wgTitle, $wgOut, $wgLang, $wgContLang; + + $hash = ''; + $filename = isset( $par ) ? $par : $wgRequest->getText( 'filename' ); + + $title = Title::newFromText( $filename ); + if( $title && $title->getText() != '' ) { + $dbr = wfGetDB( DB_SLAVE ); + $image = $dbr->tableName( 'image' ); + $encFilename = $dbr->addQuotes( htmlspecialchars( $title->getDbKey() ) ); + $sql = "SELECT img_sha1 from $image where img_name = $encFilename"; + $res = $dbr->query( $sql ); + $row = $dbr->fetchRow( $res ); + if( $row !== false ) { + $hash = $row[0]; + } + $dbr->freeResult( $res ); + } + + # Create the input form + $wgOut->addHTML( + Xml::openElement( 'form', array( 'id' => 'fileduplicatesearch', 'method' => 'get', 'action' => $wgTitle->getLocalUrl() ) ) . + Xml::openElement( 'fieldset' ) . + Xml::element( 'legend', null, wfMsg( 'fileduplicatesearch-legend' ) ) . + Xml::inputLabel( wfMsg( 'fileduplicatesearch-filename' ), 'filename', 'filename', 50, $filename ) . ' ' . + Xml::submitButton( wfMsg( 'fileduplicatesearch-submit' ) ) . + Xml::closeElement( 'fieldset' ) . + Xml::closeElement( 'form' ) + ); + + if( $hash != '' ) { + $align = $wgContLang->isRtl() ? 'left' : 'right'; + + # Show a thumbnail of the file + $img = wfFindFile( $title ); + if ( $img ) { + $thumb = $img->getThumbnail( 120, 120 ); + if( $thumb ) { + $wgOut->addHTML( '
    ' . + $thumb->toHtml( array( 'desc-link' => false ) ) . '
    ' . + wfMsgExt( 'fileduplicatesearch-info', array( 'parse' ), + $wgLang->formatNum( $img->getWidth() ), + $wgLang->formatNum( $img->getHeight() ), + $wgLang->formatSize( $img->getSize() ), + $img->getMimeType() + ) . + '
    ' ); + } + } + + # Do the query + $wpp = new FileDuplicateSearchPage( $hash, $filename ); + list( $limit, $offset ) = wfCheckLimits(); + $count = $wpp->doQuery( $offset, $limit ); + + # Show a short summary + if( $count == 1 ) { + $wgOut->addHTML( '

    ' . + wfMsgHtml( 'fileduplicatesearch-result-1', $filename ) . + '

    ' + ); + } elseif ( $count > 1 ) { + $wgOut->addHTML( '

    ' . + wfMsgExt( 'fileduplicatesearch-result-n', array( 'parseinline' ), $filename, $wgLang->formatNum( $count - 1 ) ) . + '

    ' + ); + } + } +} diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index a1890b904b..c9380bae51 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -134,6 +134,7 @@ class SpecialPage 'Unlockdb' => array( 'SpecialPage', 'Unlockdb', 'siteadmin' ), 'Userrights' => 'UserrightsPage', 'MIMEsearch' => array( 'SpecialPage', 'MIMEsearch' ), + 'FileDuplicateSearch' => array( 'SpecialPage', 'FileDuplicateSearch' ), 'Unwatchedpages' => array( 'SpecialPage', 'Unwatchedpages', 'unwatchedpages' ), 'Listredirects' => array( 'SpecialPage', 'Listredirects' ), 'Revisiondelete' => array( 'UnlistedSpecialPage', 'Revisiondelete', 'deleterevision' ), diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 02da6d3cc2..f8d964862b 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -411,6 +411,7 @@ $specialPageAliases = array( 'Unlockdb' => array( 'UnlockDB' ), 'Userrights' => array( 'UserRights' ), 'MIMEsearch' => array( 'MIMESearch' ), + 'FileDuplicateSearch' => array( 'FileDuplicateSearch' ), 'Unwatchedpages' => array( 'UnwatchedPages' ), 'Listredirects' => array( 'ListRedirects' ), 'Revisiondelete' => array( 'RevisionDelete' ), @@ -1546,6 +1547,7 @@ A click on a column header changes the sorting.', 'noimage' => 'No file by this name exists, you can $1.', 'noimage-linktext' => 'upload it', 'uploadnewversion-linktext' => 'Upload a new version of this file', +'imagepage-searchdupe' => 'Search for duplicate files', # File reversion 'filerevert' => 'Revert $1', @@ -3129,4 +3131,16 @@ Images are shown in full resolution, other file types are started with their ass Enter the file name without the "{{ns:image}}:" prefix.', +# Special:FileDuplicateSearch +'fileduplicatesearch' => 'Search for duplicate files', +'fileduplicatesearch-summary' => 'Search for duplicate files on base of its hash value. + +Enter the filename without the "{{ns:image}}:" prefix.', +'fileduplicatesearch-legend' => 'Search for a duplicate', +'fileduplicatesearch-filename' => 'Filename:', +'fileduplicatesearch-submit' => 'Search', +'fileduplicatesearch-info' => '$1 × $2 pixel
    File size: $3
    MIME type: $4', +'fileduplicatesearch-result-1' => 'The file "$1" has no identical duplication.', +'fileduplicatesearch-result-n' => 'The file "$1" has {{PLURAL:$2|1 identical duplication|$2 identical duplications}}.', + ); diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index 3000b4e403..d653e17e5a 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -958,6 +958,7 @@ $wgMessageStructure = array( 'noimage', 'noimage-linktext', 'uploadnewversion-linktext', + 'imagepage-searchdupe', ), 'filerevert' => array( 'filerevert', @@ -2396,7 +2397,18 @@ $wgMessageStructure = array( 'filepath-submit', 'filepath-summary', ), + 'fileduplicatesearch' => array( + 'fileduplicatesearch', + 'fileduplicatesearch-summary', + 'fileduplicatesearch-legend', + 'fileduplicatesearch-filename', + 'fileduplicatesearch-submit', + 'fileduplicatesearch-info', + 'fileduplicatesearch-result-1', + 'fileduplicatesearch-result-n', + ), ); + /** Comments for each block */ $wgBlockComments = array( 'sidebar' => "The sidebar for MonoBook is generated from this message, lines that do not @@ -2574,6 +2586,7 @@ Variants for Chinese language", 'CoreParserFunctions' => 'Core parser functions', 'version' => 'Special:Version', 'filepath' => 'Special:Filepath', + 'fileduplicate' => 'Special:FileDuplicateSearch', ); /** Short comments for standalone messages */