Index: trunk/phase3/includes/Image.php |
— | — | @@ -90,7 +90,7 @@ |
91 | 91 | $this->dataLoaded = false; |
92 | 92 | } |
93 | 93 | |
94 | | - |
| 94 | + |
95 | 95 | /** |
96 | 96 | * Normalize a file extension to the common form, and ensure it's clean. |
97 | 97 | * Extensions with non-alphanumeric characters will be discarded. |
— | — | @@ -113,7 +113,7 @@ |
114 | 114 | return ''; |
115 | 115 | } |
116 | 116 | } |
117 | | - |
| 117 | + |
118 | 118 | /** |
119 | 119 | * Get the memcached keys |
120 | 120 | * Returns an array, first element is the local cache key, second is the shared cache key, if there is one |
— | — | @@ -477,7 +477,7 @@ |
478 | 478 | } |
479 | 479 | wfProfileOut( __METHOD__ ); |
480 | 480 | } |
481 | | - |
| 481 | + |
482 | 482 | /** |
483 | 483 | * Split an internet media type into its two components; if not |
484 | 484 | * a two-part name, set the minor type to 'unknown'. |
— | — | @@ -964,7 +964,7 @@ |
965 | 965 | */ |
966 | 966 | function validateThumbParams( &$width, &$height ) { |
967 | 967 | global $wgSVGMaxSize, $wgMaxImageArea; |
968 | | - |
| 968 | + |
969 | 969 | $this->load(); |
970 | 970 | |
971 | 971 | if ( ! $this->exists() ) |
— | — | @@ -972,9 +972,9 @@ |
973 | 973 | # If there is no image, there will be no thumbnail |
974 | 974 | return false; |
975 | 975 | } |
976 | | - |
| 976 | + |
977 | 977 | $width = intval( $width ); |
978 | | - |
| 978 | + |
979 | 979 | # Sanity check $width |
980 | 980 | if( $width <= 0 || $this->width <= 0) { |
981 | 981 | # BZZZT |
— | — | @@ -1003,7 +1003,7 @@ |
1004 | 1004 | $height = round( $this->height * $width / $this->width ); |
1005 | 1005 | return true; |
1006 | 1006 | } |
1007 | | - |
| 1007 | + |
1008 | 1008 | /** |
1009 | 1009 | * Create a thumbnail of the image having the specified width. |
1010 | 1010 | * The thumbnail will not be created if the width is larger than the |
— | — | @@ -1035,7 +1035,7 @@ |
1036 | 1036 | wfProfileOut( __METHOD__ ); |
1037 | 1037 | return $thumb; |
1038 | 1038 | } |
1039 | | - |
| 1039 | + |
1040 | 1040 | list( $isScriptUrl, $url ) = $this->thumbUrl( $width ); |
1041 | 1041 | if ( $isScriptUrl && $useScript ) { |
1042 | 1042 | // Use thumb.php to render the image |
— | — | @@ -1074,7 +1074,7 @@ |
1075 | 1075 | @unlink( $thumbDir ); |
1076 | 1076 | } |
1077 | 1077 | wfMkdirParents( $thumbDir ); |
1078 | | - |
| 1078 | + |
1079 | 1079 | $oldThumbPath = wfDeprecatedThumbDir( $thumbName, 'thumb', $this->fromSharedDirectory ). |
1080 | 1080 | '/'.$thumbName; |
1081 | 1081 | $done = false; |
— | — | @@ -1148,7 +1148,7 @@ |
1149 | 1149 | $err = false; |
1150 | 1150 | $cmd = ""; |
1151 | 1151 | $retval = 0; |
1152 | | - |
| 1152 | + |
1153 | 1153 | if( $this->mime === "image/svg" ) { |
1154 | 1154 | #Right now we have only SVG |
1155 | 1155 | |
— | — | @@ -1185,7 +1185,7 @@ |
1186 | 1186 | |
1187 | 1187 | } elseif ( $wgUseImageMagick ) { |
1188 | 1188 | # use ImageMagick |
1189 | | - |
| 1189 | + |
1190 | 1190 | if ( $this->mime == 'image/jpeg' ) { |
1191 | 1191 | $quality = "-quality 80"; // 80% |
1192 | 1192 | } elseif ( $this->mime == 'image/png' ) { |
— | — | @@ -1196,11 +1196,11 @@ |
1197 | 1197 | |
1198 | 1198 | # Specify white background color, will be used for transparent images |
1199 | 1199 | # in Internet Explorer/Windows instead of default black. |
1200 | | - |
| 1200 | + |
1201 | 1201 | # Note, we specify "-size {$width}" and NOT "-size {$width}x{$height}". |
1202 | 1202 | # It seems that ImageMagick has a bug wherein it produces thumbnails of |
1203 | 1203 | # the wrong size in the second case. |
1204 | | - |
| 1204 | + |
1205 | 1205 | $cmd = wfEscapeShellArg($wgImageMagickConvertCommand) . |
1206 | 1206 | " {$quality} -background white -size {$width} ". |
1207 | 1207 | wfEscapeShellArg($this->imagePath) . |
— | — | @@ -1233,7 +1233,7 @@ |
1234 | 1234 | # |
1235 | 1235 | # First find out what kind of file this is, and select the correct |
1236 | 1236 | # input routine for this. |
1237 | | - |
| 1237 | + |
1238 | 1238 | $typemap = array( |
1239 | 1239 | 'image/gif' => array( 'imagecreatefromgif', 'palette', 'imagegif' ), |
1240 | 1240 | 'image/jpeg' => array( 'imagecreatefromjpeg', 'truecolor', array( &$this, 'imageJpegWrapper' ) ), |
— | — | @@ -1319,7 +1319,7 @@ |
1320 | 1320 | |
1321 | 1321 | if ( is_dir( $dir ) ) { |
1322 | 1322 | $handle = opendir( $dir ); |
1323 | | - |
| 1323 | + |
1324 | 1324 | if ( $handle ) { |
1325 | 1325 | while ( false !== ( $file = readdir($handle) ) ) { |
1326 | 1326 | if ( $file{0} != '.' ) { |
— | — | @@ -1376,7 +1376,7 @@ |
1377 | 1377 | wfPurgeSquidServers( $urls ); |
1378 | 1378 | } |
1379 | 1379 | } |
1380 | | - |
| 1380 | + |
1381 | 1381 | /** |
1382 | 1382 | * Purge the image description page, but don't go after |
1383 | 1383 | * pages using the image. Use when modifying file history |
— | — | @@ -1387,7 +1387,7 @@ |
1388 | 1388 | $page->invalidateCache(); |
1389 | 1389 | $page->purgeSquid(); |
1390 | 1390 | } |
1391 | | - |
| 1391 | + |
1392 | 1392 | /** |
1393 | 1393 | * Purge metadata and all affected pages when the image is created, |
1394 | 1394 | * deleted, or majorly updated. A set of additional URLs may be |
— | — | @@ -1398,7 +1398,7 @@ |
1399 | 1399 | // Delete thumbnails and refresh image metadata cache |
1400 | 1400 | $this->purgeCache(); |
1401 | 1401 | $this->purgeDescription(); |
1402 | | - |
| 1402 | + |
1403 | 1403 | // Purge cache of all pages using this image |
1404 | 1404 | $update = new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' ); |
1405 | 1405 | $update->doUpdate(); |
— | — | @@ -1720,7 +1720,7 @@ |
1721 | 1721 | wfProfileOut( __METHOD__ ); |
1722 | 1722 | return $retVal; |
1723 | 1723 | } |
1724 | | - |
| 1724 | + |
1725 | 1725 | /** |
1726 | 1726 | * Retrive Exif data from the file and prune unrecognized tags |
1727 | 1727 | * and/or tags with invalid contents |
— | — | @@ -1730,7 +1730,7 @@ |
1731 | 1731 | */ |
1732 | 1732 | private function retrieveExifData( $filename ) { |
1733 | 1733 | global $wgShowEXIF; |
1734 | | - |
| 1734 | + |
1735 | 1735 | /* |
1736 | 1736 | if ( $this->getMimeType() !== "image/jpeg" ) |
1737 | 1737 | return array(); |
— | — | @@ -1740,7 +1740,7 @@ |
1741 | 1741 | $exif = new Exif( $filename ); |
1742 | 1742 | return $exif->getFilteredData(); |
1743 | 1743 | } |
1744 | | - |
| 1744 | + |
1745 | 1745 | return array(); |
1746 | 1746 | } |
1747 | 1747 | |
— | — | @@ -1800,7 +1800,7 @@ |
1801 | 1801 | function isLocal() { |
1802 | 1802 | return !$this->fromSharedDirectory; |
1803 | 1803 | } |
1804 | | - |
| 1804 | + |
1805 | 1805 | /** |
1806 | 1806 | * Was this image ever deleted from the wiki? |
1807 | 1807 | * |
— | — | @@ -1810,7 +1810,7 @@ |
1811 | 1811 | $title = Title::makeTitle( NS_IMAGE, $this->name ); |
1812 | 1812 | return ( $title->isDeleted() > 0 ); |
1813 | 1813 | } |
1814 | | - |
| 1814 | + |
1815 | 1815 | /** |
1816 | 1816 | * Delete all versions of the image. |
1817 | 1817 | * |
— | — | @@ -1825,34 +1825,34 @@ |
1826 | 1826 | function delete( $reason ) { |
1827 | 1827 | $transaction = new FSTransaction(); |
1828 | 1828 | $urlArr = array( $this->getURL() ); |
1829 | | - |
| 1829 | + |
1830 | 1830 | if( !FileStore::lock() ) { |
1831 | 1831 | wfDebug( __METHOD__.": failed to acquire file store lock, aborting\n" ); |
1832 | 1832 | return false; |
1833 | 1833 | } |
1834 | | - |
| 1834 | + |
1835 | 1835 | try { |
1836 | 1836 | $dbw = wfGetDB( DB_MASTER ); |
1837 | 1837 | $dbw->begin(); |
1838 | | - |
| 1838 | + |
1839 | 1839 | // Delete old versions |
1840 | 1840 | $result = $dbw->select( 'oldimage', |
1841 | 1841 | array( 'oi_archive_name' ), |
1842 | 1842 | array( 'oi_name' => $this->name ) ); |
1843 | | - |
| 1843 | + |
1844 | 1844 | while( $row = $dbw->fetchObject( $result ) ) { |
1845 | 1845 | $oldName = $row->oi_archive_name; |
1846 | | - |
| 1846 | + |
1847 | 1847 | $transaction->add( $this->prepareDeleteOld( $oldName, $reason ) ); |
1848 | | - |
| 1848 | + |
1849 | 1849 | // We'll need to purge this URL from caches... |
1850 | 1850 | $urlArr[] = wfImageArchiveUrl( $oldName ); |
1851 | 1851 | } |
1852 | 1852 | $dbw->freeResult( $result ); |
1853 | | - |
| 1853 | + |
1854 | 1854 | // And the current version... |
1855 | 1855 | $transaction->add( $this->prepareDeleteCurrent( $reason ) ); |
1856 | | - |
| 1856 | + |
1857 | 1857 | $dbw->immediateCommit(); |
1858 | 1858 | } catch( MWException $e ) { |
1859 | 1859 | wfDebug( __METHOD__.": db error, rolling back file transactions\n" ); |
— | — | @@ -1860,22 +1860,22 @@ |
1861 | 1861 | FileStore::unlock(); |
1862 | 1862 | throw $e; |
1863 | 1863 | } |
1864 | | - |
| 1864 | + |
1865 | 1865 | wfDebug( __METHOD__.": deleted db items, applying file transactions\n" ); |
1866 | 1866 | $transaction->commit(); |
1867 | 1867 | FileStore::unlock(); |
1868 | 1868 | |
1869 | | - |
| 1869 | + |
1870 | 1870 | // Update site_stats |
1871 | 1871 | $site_stats = $dbw->tableName( 'site_stats' ); |
1872 | 1872 | $dbw->query( "UPDATE $site_stats SET ss_images=ss_images-1", __METHOD__ ); |
1873 | | - |
| 1873 | + |
1874 | 1874 | $this->purgeEverything( $urlArr ); |
1875 | | - |
| 1875 | + |
1876 | 1876 | return true; |
1877 | 1877 | } |
1878 | | - |
1879 | | - |
| 1878 | + |
| 1879 | + |
1880 | 1880 | /** |
1881 | 1881 | * Delete an old version of the image. |
1882 | 1882 | * |
— | — | @@ -1891,12 +1891,12 @@ |
1892 | 1892 | function deleteOld( $archiveName, $reason ) { |
1893 | 1893 | $transaction = new FSTransaction(); |
1894 | 1894 | $urlArr = array(); |
1895 | | - |
| 1895 | + |
1896 | 1896 | if( !FileStore::lock() ) { |
1897 | 1897 | wfDebug( __METHOD__.": failed to acquire file store lock, aborting\n" ); |
1898 | 1898 | return false; |
1899 | 1899 | } |
1900 | | - |
| 1900 | + |
1901 | 1901 | $transaction = new FSTransaction(); |
1902 | 1902 | try { |
1903 | 1903 | $dbw = wfGetDB( DB_MASTER ); |
— | — | @@ -1909,11 +1909,11 @@ |
1910 | 1910 | FileStore::unlock(); |
1911 | 1911 | throw $e; |
1912 | 1912 | } |
1913 | | - |
| 1913 | + |
1914 | 1914 | wfDebug( __METHOD__.": deleted db items, applying file transaction\n" ); |
1915 | 1915 | $transaction->commit(); |
1916 | 1916 | FileStore::unlock(); |
1917 | | - |
| 1917 | + |
1918 | 1918 | $this->purgeDescription(); |
1919 | 1919 | |
1920 | 1920 | // Squid purging |
— | — | @@ -1926,7 +1926,7 @@ |
1927 | 1927 | } |
1928 | 1928 | return true; |
1929 | 1929 | } |
1930 | | - |
| 1930 | + |
1931 | 1931 | /** |
1932 | 1932 | * Delete the current version of a file. |
1933 | 1933 | * May throw a database error. |
— | — | @@ -2000,12 +2000,12 @@ |
2001 | 2001 | */ |
2002 | 2002 | private function prepareDeleteVersion( $path, $reason, $table, $fieldMap, $where, $fname ) { |
2003 | 2003 | global $wgUser, $wgSaveDeletedFiles; |
2004 | | - |
| 2004 | + |
2005 | 2005 | // Dupe the file into the file store |
2006 | 2006 | if( file_exists( $path ) ) { |
2007 | 2007 | if( $wgSaveDeletedFiles ) { |
2008 | 2008 | $group = 'deleted'; |
2009 | | - |
| 2009 | + |
2010 | 2010 | $store = FileStore::get( $group ); |
2011 | 2011 | $key = FileStore::calculateKey( $path, $this->extension ); |
2012 | 2012 | $transaction = $store->insert( $key, $path, |
— | — | @@ -2021,24 +2021,24 @@ |
2022 | 2022 | $key = null; |
2023 | 2023 | $transaction = new FSTransaction(); // empty |
2024 | 2024 | } |
2025 | | - |
| 2025 | + |
2026 | 2026 | if( $transaction === false ) { |
2027 | 2027 | // Fail to restore? |
2028 | 2028 | wfDebug( __METHOD__.": import to file store failed, aborting\n" ); |
2029 | 2029 | throw new MWException( "Could not archive and delete file $path" ); |
2030 | 2030 | return false; |
2031 | 2031 | } |
2032 | | - |
| 2032 | + |
2033 | 2033 | $dbw = wfGetDB( DB_MASTER ); |
2034 | 2034 | $storageMap = array( |
2035 | 2035 | 'fa_storage_group' => $dbw->addQuotes( $group ), |
2036 | 2036 | 'fa_storage_key' => $dbw->addQuotes( $key ), |
2037 | | - |
| 2037 | + |
2038 | 2038 | 'fa_deleted_user' => $dbw->addQuotes( $wgUser->getId() ), |
2039 | 2039 | 'fa_deleted_timestamp' => $dbw->timestamp(), |
2040 | 2040 | 'fa_deleted_reason' => $dbw->addQuotes( $reason ) ); |
2041 | 2041 | $allFields = array_merge( $storageMap, $fieldMap ); |
2042 | | - |
| 2042 | + |
2043 | 2043 | try { |
2044 | 2044 | if( $wgSaveDeletedFiles ) { |
2045 | 2045 | $dbw->insertSelect( 'filearchive', $table, $allFields, $where, $fname ); |
— | — | @@ -2051,10 +2051,10 @@ |
2052 | 2052 | $transaction->rollback(); |
2053 | 2053 | throw $e; |
2054 | 2054 | } |
2055 | | - |
| 2055 | + |
2056 | 2056 | return $transaction; |
2057 | 2057 | } |
2058 | | - |
| 2058 | + |
2059 | 2059 | /** |
2060 | 2060 | * Restore all or specified deleted revisions to the given file. |
2061 | 2061 | * Permissions and logging are left to the caller. |
— | — | @@ -2071,31 +2071,31 @@ |
2072 | 2072 | wfDebug( __METHOD__." could not acquire filestore lock\n" ); |
2073 | 2073 | return false; |
2074 | 2074 | } |
2075 | | - |
| 2075 | + |
2076 | 2076 | $transaction = new FSTransaction(); |
2077 | 2077 | try { |
2078 | 2078 | $dbw = wfGetDB( DB_MASTER ); |
2079 | 2079 | $dbw->begin(); |
2080 | | - |
| 2080 | + |
2081 | 2081 | // Re-confirm whether this image presently exists; |
2082 | 2082 | // if no we'll need to create an image record for the |
2083 | 2083 | // first item we restore. |
2084 | 2084 | $exists = $dbw->selectField( 'image', '1', |
2085 | 2085 | array( 'img_name' => $this->name ), |
2086 | 2086 | __METHOD__ ); |
2087 | | - |
| 2087 | + |
2088 | 2088 | // Fetch all or selected archived revisions for the file, |
2089 | 2089 | // sorted from the most recent to the oldest. |
2090 | 2090 | $conditions = array( 'fa_name' => $this->name ); |
2091 | 2091 | if( $versions ) { |
2092 | 2092 | $conditions['fa_id'] = $versions; |
2093 | 2093 | } |
2094 | | - |
| 2094 | + |
2095 | 2095 | $result = $dbw->select( 'filearchive', '*', |
2096 | 2096 | $conditions, |
2097 | 2097 | __METHOD__, |
2098 | 2098 | array( 'ORDER BY' => 'fa_timestamp DESC' ) ); |
2099 | | - |
| 2099 | + |
2100 | 2100 | if( $dbw->numRows( $result ) < count( $versions ) ) { |
2101 | 2101 | // There's some kind of conflict or confusion; |
2102 | 2102 | // we can't restore everything we were asked to. |
— | — | @@ -2112,7 +2112,7 @@ |
2113 | 2113 | FileStore::unlock(); |
2114 | 2114 | return true; |
2115 | 2115 | } |
2116 | | - |
| 2116 | + |
2117 | 2117 | $revisions = 0; |
2118 | 2118 | while( $row = $dbw->fetchObject( $result ) ) { |
2119 | 2119 | $revisions++; |
— | — | @@ -2121,20 +2121,20 @@ |
2122 | 2122 | wfDebug( __METHOD__.": skipping row with no file.\n" ); |
2123 | 2123 | continue; |
2124 | 2124 | } |
2125 | | - |
| 2125 | + |
2126 | 2126 | if( $revisions == 1 && !$exists ) { |
2127 | 2127 | $destDir = wfImageDir( $row->fa_name ); |
2128 | 2128 | if ( !is_dir( $destDir ) ) { |
2129 | 2129 | wfMkdirParents( $destDir ); |
2130 | 2130 | } |
2131 | 2131 | $destPath = $destDir . DIRECTORY_SEPARATOR . $row->fa_name; |
2132 | | - |
| 2132 | + |
2133 | 2133 | // We may have to fill in data if this was originally |
2134 | 2134 | // an archived file revision. |
2135 | 2135 | if( is_null( $row->fa_metadata ) ) { |
2136 | 2136 | $tempFile = $store->filePath( $row->fa_storage_key ); |
2137 | 2137 | $metadata = serialize( $this->retrieveExifData( $tempFile ) ); |
2138 | | - |
| 2138 | + |
2139 | 2139 | $magic = MimeMagic::singleton(); |
2140 | 2140 | $mime = $magic->guessMimeType( $tempFile, true ); |
2141 | 2141 | $media_type = $magic->getMediaType( $tempFile, $mime ); |
— | — | @@ -2145,7 +2145,7 @@ |
2146 | 2146 | $minor_mime = $row->fa_minor_mime; |
2147 | 2147 | $media_type = $row->fa_media_type; |
2148 | 2148 | } |
2149 | | - |
| 2149 | + |
2150 | 2150 | $table = 'image'; |
2151 | 2151 | $fields = array( |
2152 | 2152 | 'img_name' => $row->fa_name, |
— | — | @@ -2176,7 +2176,7 @@ |
2177 | 2177 | wfMkdirParents( $destDir ); |
2178 | 2178 | } |
2179 | 2179 | $destPath = $destDir . DIRECTORY_SEPARATOR . $archiveName; |
2180 | | - |
| 2180 | + |
2181 | 2181 | $table = 'oldimage'; |
2182 | 2182 | $fields = array( |
2183 | 2183 | 'oi_name' => $row->fa_name, |
— | — | @@ -2190,13 +2190,13 @@ |
2191 | 2191 | 'oi_user_text' => $row->fa_user_text, |
2192 | 2192 | 'oi_timestamp' => $row->fa_timestamp ); |
2193 | 2193 | } |
2194 | | - |
| 2194 | + |
2195 | 2195 | $dbw->insert( $table, $fields, __METHOD__ ); |
2196 | 2196 | /// @fixme this delete is not totally safe, potentially |
2197 | 2197 | $dbw->delete( 'filearchive', |
2198 | 2198 | array( 'fa_id' => $row->fa_id ), |
2199 | 2199 | __METHOD__ ); |
2200 | | - |
| 2200 | + |
2201 | 2201 | // Check if any other stored revisions use this file; |
2202 | 2202 | // if so, we shouldn't remove the file from the deletion |
2203 | 2203 | // archives so they will still work. |
— | — | @@ -2212,36 +2212,36 @@ |
2213 | 2213 | } else { |
2214 | 2214 | $flags = 0; |
2215 | 2215 | } |
2216 | | - |
| 2216 | + |
2217 | 2217 | $transaction->add( $store->export( $row->fa_storage_key, |
2218 | 2218 | $destPath, $flags ) ); |
2219 | 2219 | } |
2220 | | - |
| 2220 | + |
2221 | 2221 | $dbw->immediateCommit(); |
2222 | 2222 | } catch( MWException $e ) { |
2223 | 2223 | wfDebug( __METHOD__." caught error, aborting\n" ); |
2224 | 2224 | $transaction->rollback(); |
2225 | 2225 | throw $e; |
2226 | 2226 | } |
2227 | | - |
| 2227 | + |
2228 | 2228 | $transaction->commit(); |
2229 | 2229 | FileStore::unlock(); |
2230 | | - |
| 2230 | + |
2231 | 2231 | if( $revisions > 0 ) { |
2232 | 2232 | if( !$exists ) { |
2233 | 2233 | wfDebug( __METHOD__." restored $revisions items, creating a new current\n" ); |
2234 | | - |
| 2234 | + |
2235 | 2235 | // Update site_stats |
2236 | 2236 | $site_stats = $dbw->tableName( 'site_stats' ); |
2237 | 2237 | $dbw->query( "UPDATE $site_stats SET ss_images=ss_images+1", __METHOD__ ); |
2238 | | - |
| 2238 | + |
2239 | 2239 | $this->purgeEverything(); |
2240 | 2240 | } else { |
2241 | 2241 | wfDebug( __METHOD__." restored $revisions as archived versions\n" ); |
2242 | 2242 | $this->purgeDescription(); |
2243 | 2243 | } |
2244 | 2244 | } |
2245 | | - |
| 2245 | + |
2246 | 2246 | return $revisions; |
2247 | 2247 | } |
2248 | 2248 | |
— | — | @@ -2274,7 +2274,7 @@ |
2275 | 2275 | if ( isset( $this->multiPageXML ) ) { |
2276 | 2276 | return true; |
2277 | 2277 | } |
2278 | | - |
| 2278 | + |
2279 | 2279 | # |
2280 | 2280 | # Check for files uploaded prior to DJVU support activation, |
2281 | 2281 | # or damaged. |
— | — | @@ -2328,7 +2328,7 @@ |
2329 | 2329 | return null; |
2330 | 2330 | } |
2331 | 2331 | } |
2332 | | - |
| 2332 | + |
2333 | 2333 | } //class |
2334 | 2334 | |
2335 | 2335 | /** |