3 * Script to clean up broken, unparseable upload filenames.
5 * Usage: php cleanupImages.php [--fix]
7 * --fix Actually clean up titles; otherwise just checks for them
9 * Copyright (C) 2005-2006 Brion Vibber <brion@pobox.com>
10 * http://www.mediawiki.org/
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 * http://www.gnu.org/copyleft/gpl.html
27 * @author Brion Vibber <brion at pobox.com>
29 * @subpackage maintenance
32 require_once( 'commandLine.inc' );
33 require_once( 'cleanupTable.inc' );
35 class ImageCleanup
extends TableCleanup
{
36 function __construct( $dryrun = false ) {
37 parent
::__construct( 'image', $dryrun );
40 function processPage( $row ) {
43 $source = $row->img_name
;
45 // Ye olde empty rows. Just kill them.
46 $this->killRow( $source );
47 return $this->progress( 1 );
52 // About half of old bad image names have percent-codes
53 $cleaned = urldecode( $cleaned );
55 // Some are old latin-1
56 $cleaned = $wgContLang->checkTitleEncoding( $cleaned );
58 // Many of remainder look like non-normalized unicode
59 $cleaned = UtfNormal
::cleanUp( $cleaned );
61 $title = Title
::makeTitleSafe( NS_IMAGE
, $cleaned );
63 if( is_null( $title ) ) {
64 $this->log( "page $source ($cleaned) is illegal." );
65 $safe = $this->buildSafeTitle( $cleaned );
66 $this->pokeFile( $source, $safe );
67 return $this->progress( 1 );
70 if( $title->getDbKey() !== $source ) {
71 $munged = $title->getDbKey();
72 $this->log( "page $source ($munged) doesn't match self." );
73 $this->pokeFile( $source, $munged );
74 return $this->progress( 1 );
80 function killRow( $name ) {
82 $this->log( "DRY RUN: would delete bogus row '$name'" );
84 $this->log( "deleting bogus row '$name'" );
85 $db = wfGetDB( DB_MASTER
);
87 array( 'img_name' => $name ),
92 function pokeFile( $orig, $new ) {
93 $db = wfGetDB( DB_MASTER
);
97 while( $db->selectField( 'image', 'img_name',
98 array( 'img_name' => $final ), __METHOD__
) ) {
99 $this->log( "Rename conflicts with '$final'..." );
101 $final = $this->appendTitle( $new, $final );
104 if( $this->dryrun
) {
105 $this->log( "DRY RUN: would rename '$orig' to '$final'" );
107 $this->log( "renaming '$orig' to '$final'" );
108 $db->update( 'image',
109 array( 'img_name' => $final ),
110 array( 'img_name' => $orig ),
115 function appendTitle( $name, $suffix ) {
116 return preg_replace( '/^(.*)(\..*?)$/',
117 "\1$suffix\2", $name );
120 function buildSafeTitle( $name ) {
121 $x = preg_replace_callback(
122 "/([^$wgLegalTitleChars])/",
124 array( $this, 'hexChar' ) );
126 $test = Title
::makeTitleSafe( NS_IMAGE
, $x );
127 if( is_null( $test ) ||
$test->getDbKey() !== $x ) {
128 $this->log( "Unable to generate safe title from '$name', got '$x'" );
136 $wgUser->setName( 'Conversion script' );
137 $caps = new ImageCleanup( !isset( $options['fix'] ) );