Merge "Allow array condition for HAVING in database interface"
authorAaron Schulz <aschulz@wikimedia.org>
Sat, 1 Sep 2012 00:03:47 +0000 (00:03 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sat, 1 Sep 2012 00:03:47 +0000 (00:03 +0000)
31 files changed:
RELEASE-NOTES-1.20
includes/AuthPlugin.php
includes/DefaultSettings.php
includes/Linker.php
includes/Setup.php
includes/User.php
includes/ZhConversion.php
includes/filebackend/FileBackend.php
includes/filebackend/FileBackendStore.php
includes/filebackend/FileOp.php
includes/filebackend/SwiftFileBackend.php
includes/specials/SpecialBlock.php
includes/zhtable/Makefile.py
includes/zhtable/toHK.manual
includes/zhtable/toTW.manual
languages/messages/MessagesBr.php
languages/messages/MessagesBs.php
languages/messages/MessagesCkb.php
languages/messages/MessagesDa.php
languages/messages/MessagesDe.php
languages/messages/MessagesKa.php
languages/messages/MessagesOr.php
languages/messages/MessagesPms.php
languages/messages/MessagesSr_ec.php
languages/messages/MessagesSv.php
languages/messages/MessagesTe.php
languages/messages/MessagesUk.php
skins/common/preview.js
skins/common/shared.css
tests/parser/parserTests.txt
tests/phpunit/includes/specials/SpecialSearchTest.php

index adc6a58..92b4c16 100644 (file)
@@ -24,7 +24,7 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
   This only affects installations which have $wgAllowCopyUploads set to true.
 * Removed f-prot support from $wgAntivirusSetup.
 * New variable $wgDBerrorLogTZ to provide dates in the error log in a
-  different timezone than the wiki timezone set by $wgLocalTimezone.
+  different timezone than the wiki timezone set by $wgLocaltimezone.
 * New variables $wgDBssl and $wgDBcompress to enable SSL and compression for database
   connections, if either are available for the selected DB type.
 
index c7fcf93..2e42439 100644 (file)
@@ -176,6 +176,15 @@ class AuthPlugin {
                return true;
        }
 
+       /**
+        * Should MediaWiki store passwords in its local database?
+        *
+        * @return bool
+        */
+       public function allowSetLocalPassword() {
+               return true;
+       }
+
        /**
         * Set the given password in the authentication database.
         * As a special case, the password may be set to null to request
index bc04f08..6aa15be 100644 (file)
@@ -523,6 +523,8 @@ $wgAllowAsyncCopyUploads = false;
 
 /**
  * A list of domains copy uploads can come from
+ *
+ * @since 1.20
  */
 $wgCopyUploadsDomains = array();
 
@@ -1447,7 +1449,7 @@ $wgDBerrorLog = false;
 
 /**
  * Timezone to use in the error log.
- * Defaults to the wiki timezone ($wgLocalTimezone).
+ * Defaults to the wiki timezone ($wgLocaltimezone).
  *
  * A list of useable timezones can found at:
  * http://php.net/manual/en/timezones.php
@@ -1694,6 +1696,8 @@ $wgSessionCacheType = CACHE_ANYTHING;
  * which are used when parsing certain text and interface messages.
  *
  * For available types see $wgMainCacheType.
+ *
+ * @since 1.20
  */
 $wgLanguageConverterCacheType = CACHE_ANYTHING;
 
@@ -2044,6 +2048,8 @@ $wgMaxSquidPurgeTitles = 400;
  * );
  * @endcode
  *
+ * @since 1.20
+ *
  * @see $wgHTCPMulticastTTL
  */
 $wgHTCPMulticastRouting = array();
@@ -2750,6 +2756,8 @@ $wgSend404Code = true;
  * The $wgShowRollbackEditCount variable is used to show how many edits will be
  * rollback. The numeric value of the varible are the limit up to are counted.
  * If the value is false or 0, the edits are not counted.
+ *
+ * @since 1.20
  */
 $wgShowRollbackEditCount = 10;
 
@@ -4387,6 +4395,8 @@ $wgDebugComments = false;
 
 /**
  * Extensive database transaction state debugging
+ *
+ * @since 1.20
  */
 $wgDebugDBTransactions = false;
 
@@ -4904,6 +4914,8 @@ $wgUpgradeKey = false;
  * The value is the replacement for the key (it can contain $1, etc.)
  * %h will be replaced by the short SHA-1 (7 first chars) and %H by the
  * full SHA-1 of the HEAD revision.
+ *
+ * @since 1.20
  */
 $wgGitRepositoryViewers = array(
     'https://gerrit.wikimedia.org/r/p/(.*)' => 'https://gerrit.wikimedia.org/r/gitweb?p=$1;h=%H',
@@ -5776,11 +5788,6 @@ $wgActions = array(
  */
 $wgDisabledActions = array();
 
-/**
- * Allow the "info" action, very inefficient at the moment
- */
-$wgAllowPageInfo = false;
-
 /** @} */ # end actions }
 
 /*************************************************************************//**
@@ -6208,6 +6215,8 @@ $wgDBtestpassword = '';
 
 /**
  * Whether the user must enter their password to change their e-mail address
+ *
+ * @since 1.20
  */
 $wgRequirePasswordforEmailChange = true;
 
index 7aba444..8e31a1c 100644 (file)
@@ -865,31 +865,31 @@ class Linker {
         * Make a "broken" link to an image
         *
         * @param $title Title object
-        * @param $html String: link label in htmlescaped text form
+        * @param $label String: link label (plain text)
         * @param $query String: query string
-        * @param $trail String: link trail (HTML fragment)
-        * @param $prefix String: link prefix (HTML fragment)
+        * @param $unused1 Unused parameter kept for b/c
+        * @param $unused2 Unused parameter kept for b/c
         * @param $time Boolean: a file of a certain timestamp was requested
         * @return String
         */
-       public static function makeBrokenImageLinkObj( $title, $html = '', $query = '', $trail = '', $prefix = '', $time = false ) {
+       public static function makeBrokenImageLinkObj( $title, $label = '', $query = '', $unused1 = '', $unused2 = '', $time = false ) {
                global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
                if ( ! $title instanceof Title ) {
-                       return "<!-- ERROR -->{$prefix}{$html}{$trail}";
+                       return "<!-- ERROR -->" . htmlspecialchars( $label );
                }
                wfProfileIn( __METHOD__ );
+               if ( $label == '' ) {
+                       $label = $title->getPrefixedText();
+               }
+               $encLabel = htmlspecialchars( $label );
                $currentExists = $time ? ( wfFindFile( $title ) != false ) : false;
 
-               list( $inside, $trail ) = self::splitTrail( $trail );
-               if ( $html == '' )
-                       $html = htmlspecialchars( $title->getPrefixedText() );
-
                if ( ( $wgUploadMissingFileUrl || $wgUploadNavigationUrl || $wgEnableUploads ) && !$currentExists ) {
                        $redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title );
 
                        if ( $redir ) {
                                wfProfileOut( __METHOD__ );
-                               return self::linkKnown( $title, "$prefix$html$inside", array(), wfCgiToArray( $query ) ) . $trail;
+                               return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
                        }
 
                        $href = self::getUploadUrl( $title, $query );
@@ -897,10 +897,10 @@ class Linker {
                        wfProfileOut( __METHOD__ );
                        return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
                                htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
-                               "$prefix$html$inside</a>$trail";
+                               $encLabel . '</a>';
                } else {
                        wfProfileOut( __METHOD__ );
-                       return self::linkKnown( $title, "$prefix$html$inside", array(), wfCgiToArray( $query ) ) . $trail;
+                       return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
                }
        }
 
index baf7b35..924c3c0 100644 (file)
@@ -332,9 +332,6 @@ if ( !$wgEnotifMinorEdits ) {
 foreach( $wgDisabledActions as $action ){
        $wgActions[$action] = false;
 }
-if( !$wgAllowPageInfo ){
-       $wgActions['info'] = false;
-}
 
 if ( !$wgHtml5Version && $wgHtml5 && $wgAllowRdfaAttributes ) {
        # see http://www.w3.org/TR/rdfa-in-html/#document-conformance
index 13748de..0a3db4c 100644 (file)
@@ -2891,11 +2891,16 @@ class User {
         * @todo Only rarely do all these fields need to be set!
         */
        public function saveSettings() {
+               global $wgAuth;
+
                $this->load();
                if ( wfReadOnly() ) { return; }
                if ( 0 == $this->mId ) { return; }
 
                $this->mTouched = self::newTouchedTimestamp();
+               if ( !$wgAuth->allowSetLocalPassword() ) {
+                       $this->mPassword = '';
+               }
 
                $dbw = wfGetDB( DB_MASTER );
                $dbw->update( 'user',
index b98f521..247b193 100644 (file)
@@ -15802,6 +15802,7 @@ $zh2TW = array(
 '彩线' => '綵線',
 '彩船' => '綵船',
 '彩衣' => '綵衣',
+'綫' => '線',
 '缉凶' => '緝凶',
 '緝兇' => '緝凶',
 '緝凶' => '緝凶',
@@ -15937,6 +15938,30 @@ $zh2TW = array(
 );
 
 $zh2HK = array(
+'505線' => '505綫',
+'505线' => '505綫',
+'507線' => '507綫',
+'507线' => '507綫',
+'610線' => '610綫',
+'610线' => '610綫',
+'614P線' => '614P綫',
+'614P线' => '614P綫',
+'614线' => '614綫',
+'614線' => '614綫',
+'615P線' => '615P綫',
+'615P线' => '615P綫',
+'615线' => '615綫',
+'615線' => '615綫',
+'705线' => '705綫',
+'705線' => '705綫',
+'706线' => '706綫',
+'706線' => '706綫',
+'751P線' => '751P綫',
+'751P线' => '751P綫',
+'751線' => '751綫',
+'751线' => '751綫',
+'761P线' => '761P綫',
+'761P線' => '761P綫',
 '“' => '「',
 '”' => '」',
 '‘' => '『',
@@ -16173,6 +16198,8 @@ $zh2HK = array(
 '動著者' => '動著者',
 '動著述' => '動著述',
 '動著錄' => '動著錄',
+'北环线' => '北環綫',
+'北環線' => '北環綫',
 '医院里' => '医院裏',
 '波札那' => '博茨瓦納',
 '珍妮弗·卡普里亚蒂' => '卡佩雅蒂',
@@ -16420,6 +16447,8 @@ $zh2HK = array(
 '寫著者' => '寫著者',
 '寫著述' => '寫著述',
 '寫著錄' => '寫著錄',
+'将军澳线' => '將軍澳綫',
+'將軍澳線' => '將軍澳綫',
 '专辑里' => '專輯裏',
 '專輯裡' => '專輯裏',
 '尋著' => '尋着',
@@ -16950,6 +16979,10 @@ $zh2HK = array(
 '本著錄' => '本著錄',
 '村子里' => '村子裏',
 '村子裡' => '村子裏',
+'东涌线' => '東涌綫',
+'東涌線' => '東涌綫',
+'東鐵線' => '東鐵綫',
+'东铁线' => '東鐵綫',
 '枕著' => '枕着',
 '枕著作' => '枕著作',
 '枕著名' => '枕著名',
@@ -16983,6 +17016,8 @@ $zh2HK = array(
 '樂著錄' => '樂著錄',
 '寶獅' => '標致',
 '標誌著' => '標誌着',
+'機場快線' => '機場快綫',
+'机场快线' => '機場快綫',
 '機器人' => '機械人',
 '机器人' => '機械人',
 '历史里' => '歷史裏',
@@ -17015,8 +17050,12 @@ $zh2HK = array(
 '沉著者' => '沉著者',
 '沉著述' => '沉著述',
 '沉著錄' => '沉著錄',
+'沙中线' => '沙中綫',
+'沙中線' => '沙中綫',
 '沙地阿拉伯' => '沙特阿拉伯',
 '沙烏地阿拉伯' => '沙特阿拉伯',
+'沙田至中環線' => '沙田至中環綫',
+'沙田至中环线' => '沙田至中環綫',
 '马拉特·萨芬' => '沙芬',
 '沿著' => '沿着',
 '沿著作' => '沿著作',
@@ -17074,6 +17113,8 @@ $zh2HK = array(
 '涼著錄' => '涼著錄',
 '深淵裡' => '深淵裏',
 '深渊里' => '深渊裏',
+'港岛线' => '港島綫',
+'港島線' => '港島綫',
 '渴著' => '渴着',
 '渴著作' => '渴著作',
 '渴著名' => '渴著名',
@@ -17114,6 +17155,14 @@ $zh2HK = array(
 '潤著者' => '潤著者',
 '潤著述' => '潤著述',
 '潤著錄' => '潤著錄',
+'無線劇集' => '無綫劇集',
+'无线剧集' => '無綫劇集',
+'無線收費' => '無綫收費',
+'无线收费' => '無綫收費',
+'无线节目' => '無綫節目',
+'無線節目' => '無綫節目',
+'无线电视' => '無綫電視',
+'無線電視' => '無綫電視',
 '菸' => '煙',
 '照著' => '照着',
 '照著作' => '照著作',
@@ -17547,6 +17596,8 @@ $zh2HK = array(
 '苦著錄' => '苦著錄',
 '苦里' => '苦裏',
 '苦裡' => '苦裏',
+'荃湾线' => '荃灣綫',
+'荃灣線' => '荃灣綫',
 '莫三比克' => '莫桑比克',
 '賴索托' => '萊索托',
 '馬自達' => '萬事得',
@@ -17630,6 +17681,8 @@ $zh2HK = array(
 '裹著者' => '裹著者',
 '裹著述' => '裹著述',
 '裹著錄' => '裹著錄',
+'西铁线' => '西鐵綫',
+'西鐵線' => '西鐵綫',
 '見著' => '見着',
 '見著作' => '見著作',
 '見著名' => '見著名',
@@ -17638,6 +17691,8 @@ $zh2HK = array(
 '見著者' => '見著者',
 '見著述' => '見著述',
 '見著錄' => '見著錄',
+'觀塘線' => '觀塘綫',
+'观塘线' => '觀塘綫',
 '記著' => '記着',
 '記著作' => '記著作',
 '記著名' => '記著名',
@@ -17821,6 +17876,8 @@ $zh2HK = array(
 '辦著錄' => '辦著錄',
 '近角聪信' => '近角聰信',
 '近角聰信' => '近角聰信',
+'迪士尼线' => '迪士尼綫',
+'迪士尼線' => '迪士尼綫',
 '迫著' => '迫着',
 '追著' => '追着',
 '追著作' => '追著作',
@@ -18080,6 +18137,8 @@ $zh2HK = array(
 '馬爾地夫' => '馬爾代夫',
 '馬利共和國' => '馬里共和國',
 '土豆' => '馬鈴薯',
+'馬鞍山線' => '馬鞍山綫',
+'马鞍山线' => '馬鞍山綫',
 '駕著' => '駕着',
 '駕著作' => '駕著作',
 '駕著名' => '駕著名',
@@ -18456,4 +18515,4 @@ $zh2SG = array(
 '笨豬跳' => '绑紧跳',
 '蹦极跳' => '绑紧跳',
 '笑星' => '谐星',
-);
+);
\ No newline at end of file
index cb2433a..ab8a327 100644 (file)
@@ -39,8 +39,7 @@
  * All "storage paths" are of the format "mwstore://<backend>/<container>/<path>".
  * The "<path>" portion is a relative path that uses UNIX file system (FS)
  * notation, though any particular backend may not actually be using a local
- * filesystem.
- * Therefore, the relative paths are only virtual.
+ * filesystem. Therefore, the relative paths are only virtual.
  *
  * Backend contents are stored under wiki-specific container names by default.
  * For legacy reasons, this has no effect for the FS backend class, and per-wiki
@@ -171,7 +170,8 @@ abstract class FileBackend {
         *         'dst'                 => <storage path>,
         *         'content'             => <string of new file contents>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     );
         * @endcode
         *
@@ -182,7 +182,8 @@ abstract class FileBackend {
         *         'src'                 => <file system path>,
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         *
@@ -193,7 +194,8 @@ abstract class FileBackend {
         *         'src'                 => <storage path>,
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         *
@@ -204,7 +206,8 @@ abstract class FileBackend {
         *         'src'                 => <storage path>,
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         *
@@ -231,6 +234,10 @@ abstract class FileBackend {
         *   - overwriteSame       : An error will not be given if a file already
         *                           exists at the destination that has the same
         *                           contents as the new contents to be written there.
+        *   - disposition         : When supplied, the backend will add a Content-Disposition
+        *                           header when GETs/HEADs of the destination file are made.
+        *                           Backends that don't support file metadata will ignore this.
+        *                           See http://tools.ietf.org/html/rfc6266 (since 1.20).
         *
         * $opts is an associative of boolean flags, including:
         *   - force               : Operation precondition errors no longer trigger an abort.
@@ -400,7 +407,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'create',
         *         'dst'                 => <storage path>,
-        *         'content'             => <string of new file contents>
+        *         'content'             => <string of new file contents>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * b) Copy a file system file into storage
@@ -408,7 +416,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'store',
         *         'src'                 => <file system path>,
-        *         'dst'                 => <storage path>
+        *         'dst'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * c) Copy a file within storage
@@ -416,7 +425,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'copy',
         *         'src'                 => <storage path>,
-        *         'dst'                 => <storage path>
+        *         'dst'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * d) Move a file within storage
@@ -424,7 +434,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'move',
         *         'src'                 => <storage path>,
-        *         'dst'                 => <storage path>
+        *         'dst'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * e) Delete a file within storage
@@ -445,6 +456,10 @@ abstract class FileBackend {
         * @par Boolean flags for operations (operation-specific):
         *   - ignoreMissingSource : The operation will simply succeed and do
         *                           nothing if the source file does not exist.
+        *   - disposition         : When supplied, the backend will add a Content-Disposition
+        *                           header when GETs/HEADs of the destination file are made.
+        *                           Backends that don't support file metadata will ignore this.
+        *                           See http://tools.ietf.org/html/rfc6266 (since 1.20).
         *
         * $opts is an associative of boolean flags, including:
         *   - bypassReadOnly      : Allow writes in read-only mode (since 1.20)
@@ -1089,6 +1104,19 @@ abstract class FileBackend {
                return ( self::normalizeContainerPath( $path ) !== null );
        }
 
+       /**
+        * Build a Content-Disposition header value per RFC 6266
+        *
+        * @param $type string One of (attachment, inline)
+        * @param $filename string Suggested file name (should not contain slashes)
+        * @return string
+        */
+       final public static function makeContentDisposition( $type, $filename ) {
+               $type = strtolower( $type );
+               $type = in_array( $type, array( 'inline', 'attachment' ) ) ? $type : 'inline';
+               return "$type; filename*=UTF-8''" . rawurlencode( basename( $filename ) );
+       }
+
        /**
         * Validate and normalize a relative storage path.
         * Null is returned if the path involves directory traversal.
index d53f7b3..5771560 100644 (file)
@@ -89,6 +89,7 @@ abstract class FileBackendStore extends FileBackend {
         *   - content       : the raw file contents
         *   - dst           : destination storage path
         *   - overwrite     : overwrite any file that exists at the destination
+        *   - disposition   : Content-Disposition header value for the destination
         *   - async         : Status will be returned immediately if supported.
         *                     If the status is OK, then its value field will be
         *                     set to a FileBackendStoreOpHandle object.
@@ -127,6 +128,7 @@ abstract class FileBackendStore extends FileBackend {
         *   - src           : source path on disk
         *   - dst           : destination storage path
         *   - overwrite     : overwrite any file that exists at the destination
+        *   - disposition   : Content-Disposition header value for the destination
         *   - async         : Status will be returned immediately if supported.
         *                     If the status is OK, then its value field will be
         *                     set to a FileBackendStoreOpHandle object.
@@ -165,6 +167,7 @@ abstract class FileBackendStore extends FileBackend {
         *   - src           : source storage path
         *   - dst           : destination storage path
         *   - overwrite     : overwrite any file that exists at the destination
+        *   - disposition   : Content-Disposition header value for the destination
         *   - async         : Status will be returned immediately if supported.
         *                     If the status is OK, then its value field will be
         *                     set to a FileBackendStoreOpHandle object.
@@ -228,6 +231,7 @@ abstract class FileBackendStore extends FileBackend {
         *   - src           : source storage path
         *   - dst           : destination storage path
         *   - overwrite     : overwrite any file that exists at the destination
+        *   - disposition   : Content-Disposition header value for the destination
         *   - async         : Status will be returned immediately if supported.
         *                     If the status is OK, then its value field will be
         *                     set to a FileBackendStoreOpHandle object.
index fa87c3a..7c43c48 100644 (file)
@@ -431,18 +431,15 @@ abstract class FileOp {
 
 /**
  * Store a file into the backend from a file on the file system.
- * Parameters similar to FileBackendStore::storeInternal(), which include:
- *   - src           : source path on file system
- *   - dst           : destination storage path
- *   - overwrite     : do nothing and pass if an identical file exists at destination
- *   - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
  */
 class StoreFileOp extends FileOp {
        /**
         * @return array
         */
        protected function allowedParams() {
-               return array( array( 'src', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+               return array( array( 'src', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'disposition' ) );
        }
 
        /**
@@ -508,15 +505,12 @@ class StoreFileOp extends FileOp {
 
 /**
  * Create a file in the backend with the given content.
- * Parameters similar to FileBackendStore::createInternal(), which include:
- *   - content       : the raw file contents
- *   - dst           : destination storage path
- *   - overwrite     : do nothing and pass if an identical file exists at destination
- *   - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
  */
 class CreateFileOp extends FileOp {
        protected function allowedParams() {
-               return array( array( 'content', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+               return array( array( 'content', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'disposition' ) );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -571,18 +565,15 @@ class CreateFileOp extends FileOp {
 
 /**
  * Copy a file from one storage path to another in the backend.
- * Parameters similar to FileBackendStore::copyInternal(), which include:
- *   - src           : source storage path
- *   - dst           : destination storage path
- *   - overwrite     : do nothing and pass if an identical file exists at destination
- *   - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
  */
 class CopyFileOp extends FileOp {
        /**
         * @return array
         */
        protected function allowedParams() {
-               return array( array( 'src', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+               return array( array( 'src', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'disposition' ) );
        }
 
        /**
@@ -642,18 +633,15 @@ class CopyFileOp extends FileOp {
 
 /**
  * Move a file from one storage path to another in the backend.
- * Parameters similar to FileBackendStore::moveInternal(), which include:
- *   - src           : source storage path
- *   - dst           : destination storage path
- *   - overwrite     : do nothing and pass if an identical file exists at destination
- *   - overwriteSame : override any existing file at destination
+ * Parameters for this operation are outlined in FileBackend::doOperations().
  */
 class MoveFileOp extends FileOp {
        /**
         * @return array
         */
        protected function allowedParams() {
-               return array( array( 'src', 'dst' ), array( 'overwrite', 'overwriteSame' ) );
+               return array( array( 'src', 'dst' ),
+                       array( 'overwrite', 'overwriteSame', 'disposition' ) );
        }
 
        /**
@@ -719,9 +707,7 @@ class MoveFileOp extends FileOp {
 
 /**
  * Delete a file at the given storage path from the backend.
- * Parameters similar to FileBackendStore::deleteInternal(), which include:
- *   - src                 : source storage path
- *   - ignoreMissingSource : don't return an error if the file does not exist
+ * Parameters for this operation are outlined in FileBackend::doOperations().
  */
 class DeleteFileOp extends FileOp {
        /**
index 4d47302..88727e4 100644 (file)
@@ -210,9 +210,13 @@ class SwiftFileBackend extends FileBackendStore {
                        if ( !strlen( $obj->content_type ) ) { // special case
                                $obj->content_type = 'unknown/unknown';
                        }
+                       // Set the Content-Disposition header if requested
+                       if ( isset( $params['disposition'] ) ) {
+                               $obj->headers['Content-Disposition'] = $params['disposition'];
+                       }
                        if ( !empty( $params['async'] ) ) { // deferred
-                               $handle = $obj->write_async( $params['content'] );
-                               $status->value = new SwiftFileOpHandle( $this, $params, 'Create', $handle );
+                               $op = $obj->write_async( $params['content'] );
+                               $status->value = new SwiftFileOpHandle( $this, $params, 'Create', $op );
                                if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
                                        $status->value->affectedObjects[] = $obj;
                                }
@@ -296,6 +300,10 @@ class SwiftFileBackend extends FileBackendStore {
                        if ( !strlen( $obj->content_type ) ) { // special case
                                $obj->content_type = 'unknown/unknown';
                        }
+                       // Set the Content-Disposition header if requested
+                       if ( isset( $params['disposition'] ) ) {
+                               $obj->headers['Content-Disposition'] = $params['disposition'];
+                       }
                        if ( !empty( $params['async'] ) ) { // deferred
                                wfSuppressWarnings();
                                $fp = fopen( $params['src'], 'rb' );
@@ -303,8 +311,8 @@ class SwiftFileBackend extends FileBackendStore {
                                if ( !$fp ) {
                                        $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
                                } else {
-                                       $handle = $obj->write_async( $fp, filesize( $params['src'] ), true );
-                                       $status->value = new SwiftFileOpHandle( $this, $params, 'Store', $handle );
+                                       $op = $obj->write_async( $fp, filesize( $params['src'] ), true );
+                                       $status->value = new SwiftFileOpHandle( $this, $params, 'Store', $op );
                                        $status->value->resourcesToClose[] = $fp;
                                        if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
                                                $status->value->affectedObjects[] = $obj;
@@ -382,14 +390,18 @@ class SwiftFileBackend extends FileBackendStore {
                // (b) Actually copy the file to the destination
                try {
                        $dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD
+                       $hdrs = array(); // source file headers to override with new values
+                       if ( isset( $params['disposition'] ) ) {
+                               $hdrs['Content-Disposition'] = $params['disposition'];
+                       }
                        if ( !empty( $params['async'] ) ) { // deferred
-                               $handle = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel );
-                               $status->value = new SwiftFileOpHandle( $this, $params, 'Copy', $handle );
+                               $op = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );
+                               $status->value = new SwiftFileOpHandle( $this, $params, 'Copy', $op );
                                if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
                                        $status->value->affectedObjects[] = $dstObj;
                                }
                        } else { // actually write the object in Swift
-                               $sContObj->copy_object_to( $srcRel, $dContObj, $dstRel );
+                               $sContObj->copy_object_to( $srcRel, $dContObj, $dstRel, null, $hdrs );
                                if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
                                        $this->purgeCDNCache( array( $dstObj ) );
                                }
@@ -457,15 +469,19 @@ class SwiftFileBackend extends FileBackendStore {
                try {
                        $srcObj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD
                        $dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD
+                       $hdrs = array(); // source file headers to override with new values
+                       if ( isset( $params['disposition'] ) ) {
+                               $hdrs['Content-Disposition'] = $params['disposition'];
+                       }
                        if ( !empty( $params['async'] ) ) { // deferred
-                               $handle = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel );
-                               $status->value = new SwiftFileOpHandle( $this, $params, 'Move', $handle );
+                               $op = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );
+                               $status->value = new SwiftFileOpHandle( $this, $params, 'Move', $op );
                                $status->value->affectedObjects[] = $srcObj;
                                if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
                                        $status->value->affectedObjects[] = $dstObj;
                                }
                        } else { // actually write the object in Swift
-                               $sContObj->move_object_to( $srcRel, $dContObj, $dstRel );
+                               $sContObj->move_object_to( $srcRel, $dContObj, $dstRel, null, $hdrs );
                                $this->purgeCDNCache( array( $srcObj ) );
                                if ( !empty( $params['overwrite'] ) ) { // file possibly mutated
                                        $this->purgeCDNCache( array( $dstObj ) );
@@ -510,8 +526,8 @@ class SwiftFileBackend extends FileBackendStore {
                        $sContObj = $this->getContainer( $srcCont );
                        $srcObj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD
                        if ( !empty( $params['async'] ) ) { // deferred
-                               $handle = $sContObj->delete_object_async( $srcRel );
-                               $status->value = new SwiftFileOpHandle( $this, $params, 'Delete', $handle );
+                               $op = $sContObj->delete_object_async( $srcRel );
+                               $status->value = new SwiftFileOpHandle( $this, $params, 'Delete', $op );
                                $status->value->affectedObjects[] = $srcObj;
                        } else { // actually write the object in Swift
                                $sContObj->delete_object( $srcRel );
index 504839a..1d6656a 100644 (file)
@@ -106,9 +106,9 @@ class SpecialBlock extends FormSpecialPage {
                $form->setSubmitTextMsg( $msg );
 
                # Don't need to do anything if the form has been posted
-               if( !$this->getRequest()->wasPosted() && $this->preErrors ){
+               if ( !$this->getRequest()->wasPosted() && $this->preErrors ) {
                        $s = HTMLForm::formatErrors( $this->preErrors );
-                       if( $s ){
+                       if ( $s ) {
                                $form->addHeaderText( Html::rawElement(
                                                'div',
                                                array( 'class' => 'error' ),
@@ -122,7 +122,7 @@ class SpecialBlock extends FormSpecialPage {
         * Get the HTMLForm descriptor array for the block form
         * @return Array
         */
-       protected function getFormFields(){
+       protected function getFormFields() {
                global $wgBlockAllowsUTEdit;
 
                $user = $this->getUser();
@@ -158,14 +158,14 @@ class SpecialBlock extends FormSpecialPage {
                        ),
                );
 
-               if( self::canBlockEmail( $user ) ) {
+               if ( self::canBlockEmail( $user ) ) {
                        $a['DisableEmail'] = array(
                                'type' => 'check',
                                'label-message' => 'ipbemailban',
                        );
                }
 
-               if( $wgBlockAllowsUTEdit ){
+               if ( $wgBlockAllowsUTEdit ) {
                        $a['DisableUTEdit'] = array(
                                'type' => 'check',
                                'label-message' => 'ipb-disableusertalk',
@@ -180,7 +180,7 @@ class SpecialBlock extends FormSpecialPage {
                );
 
                # Allow some users to hide name from block log, blocklist and listusers
-               if( $user->isAllowed( 'hideuser' ) ) {
+               if ( $user->isAllowed( 'hideuser' ) ) {
                        $a['HideUser'] = array(
                                'type' => 'check',
                                'label-message' => 'ipbhidename',
@@ -189,7 +189,7 @@ class SpecialBlock extends FormSpecialPage {
                }
 
                # Watchlist their user page? (Only if user is logged in)
-               if( $user->isLoggedIn() ) {
+               if ( $user->isLoggedIn() ) {
                        $a['Watch'] = array(
                                'type' => 'check',
                                'label-message' => 'ipbwatchuser',
@@ -228,7 +228,7 @@ class SpecialBlock extends FormSpecialPage {
         * @return Bool whether fields were altered (that is, whether the target is
         *     already blocked)
         */
-       protected function maybeAlterFormDefaults( &$fields ){
+       protected function maybeAlterFormDefaults( &$fields ) {
                # This will be overwritten by request data
                $fields['Target']['default'] = (string)$this->target;
 
@@ -237,7 +237,7 @@ class SpecialBlock extends FormSpecialPage {
 
                $block = Block::newFromTarget( $this->target );
 
-               if( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock
+               if ( $block instanceof Block && !$block->mAuto # The block exists and isn't an autoblock
                        && ( $this->type != Block::TYPE_RANGE # The block isn't a rangeblock
                          || $block->getTarget() == $this->target ) # or if it is, the range is what we're about to block
                        )
@@ -246,15 +246,15 @@ class SpecialBlock extends FormSpecialPage {
                        $fields['CreateAccount']['default'] = $block->prevents( 'createaccount' );
                        $fields['AutoBlock']['default'] = $block->isAutoblocking();
 
-                       if( isset( $fields['DisableEmail'] ) ){
+                       if ( isset( $fields['DisableEmail'] ) ) {
                                $fields['DisableEmail']['default'] = $block->prevents( 'sendemail' );
                        }
 
-                       if( isset( $fields['HideUser'] ) ){
+                       if ( isset( $fields['HideUser'] ) ) {
                                $fields['HideUser']['default'] = $block->mHideName;
                        }
 
-                       if( isset( $fields['DisableUTEdit'] ) ){
+                       if ( isset( $fields['DisableUTEdit'] ) ) {
                                $fields['DisableUTEdit']['default'] = $block->prevents( 'editownusertalk' );
                        }
 
@@ -266,7 +266,7 @@ class SpecialBlock extends FormSpecialPage {
                                $fields['Reason']['default'] = '';
                        }
 
-                       if( $this->getRequest()->wasPosted() ){
+                       if ( $this->getRequest()->wasPosted() ) {
                                # Ok, so we got a POST submission asking us to reblock a user.  So show the
                                # confirm checkbox; the user will only see it if they haven't previously
                                $fields['Confirm']['type'] = 'check';
@@ -277,7 +277,7 @@ class SpecialBlock extends FormSpecialPage {
                                $fields['Confirm']['default'] = 1;
                        }
 
-                       if( $block->mExpiry == 'infinity' ) {
+                       if ( $block->mExpiry == 'infinity' ) {
                                $fields['Expiry']['default'] = 'infinite';
                        } else {
                                $fields['Expiry']['default'] = wfTimestamp( TS_RFC2822, $block->mExpiry );
@@ -288,14 +288,14 @@ class SpecialBlock extends FormSpecialPage {
                }
 
                # We always need confirmation to do HideUser
-               if( $this->requestedHideUser ){
+               if ( $this->requestedHideUser ) {
                        $fields['Confirm']['type'] = 'check';
                        unset( $fields['Confirm']['default'] );
                        $this->preErrors[] = 'ipb-confirmhideuser';
                }
 
                # Or if the user is trying to block themselves
-               if( (string)$this->target === $this->getUser()->getName() ){
+               if ( (string)$this->target === $this->getUser()->getName() ) {
                        $fields['Confirm']['type'] = 'check';
                        unset( $fields['Confirm']['default'] );
                        $this->preErrors[] = 'ipb-blockingself';
@@ -306,17 +306,17 @@ class SpecialBlock extends FormSpecialPage {
         * Add header elements like block log entries, etc.
         * @return String
         */
-       protected function preText(){
+       protected function preText() {
                $this->getOutput()->addModules( 'mediawiki.special.block' );
 
                $text = $this->msg( 'blockiptext' )->parse();
 
                $otherBlockMessages = array();
-               if( $this->target !== null ) {
+               if ( $this->target !== null ) {
                        # Get other blocks, i.e. from GlobalBlocking or TorBlock extension
                        wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockMessages, $this->target ) );
 
-                       if( count( $otherBlockMessages ) ) {
+                       if ( count( $otherBlockMessages ) ) {
                                $s = Html::rawElement(
                                        'h2',
                                        array(),
@@ -325,7 +325,7 @@ class SpecialBlock extends FormSpecialPage {
 
                                $list = '';
 
-                               foreach( $otherBlockMessages as $link ) {
+                               foreach ( $otherBlockMessages as $link ) {
                                        $list .= Html::rawElement( 'li', array(), $link ) . "\n";
                                }
 
@@ -346,11 +346,11 @@ class SpecialBlock extends FormSpecialPage {
         * Add footer elements to the form
         * @return string
         */
-       protected function postText(){
+       protected function postText() {
                $links = array();
 
                # Link to the user's contributions, if applicable
-               if( $this->target instanceof User ){
+               if ( $this->target instanceof User ) {
                        $contribsPage = SpecialPage::getTitleFor( 'Contributions', $this->target->getName() );
                        $links[] = Linker::link(
                                $contribsPage,
@@ -359,7 +359,7 @@ class SpecialBlock extends FormSpecialPage {
                }
 
                # Link to unblock the specified user, or to a blank unblock form
-               if( $this->target instanceof User ) {
+               if ( $this->target instanceof User ) {
                        $message = $this->msg( 'ipb-unblock-addr', wfEscapeWikiText( $this->target->getName() ) )->parse();
                        $list = SpecialPage::getTitleFor( 'Unblock', $this->target->getName() );
                } else {
@@ -393,7 +393,7 @@ class SpecialBlock extends FormSpecialPage {
                );
 
                $userTitle = self::getTargetUserTitle( $this->target );
-               if( $userTitle ){
+               if ( $userTitle ) {
                        # Get relevant extracts from the block and suppression logs, if possible
                        $out = '';
 
@@ -411,7 +411,7 @@ class SpecialBlock extends FormSpecialPage {
                        $text .= $out;
 
                        # Add suppression block entries if allowed
-                       if( $user->isAllowed( 'suppressionlog' ) ) {
+                       if ( $user->isAllowed( 'suppressionlog' ) ) {
                                LogEventsList::showLogExtract(
                                        $out,
                                        'suppress',
@@ -439,7 +439,7 @@ class SpecialBlock extends FormSpecialPage {
         * @return Title|null
         */
        protected static function getTargetUserTitle( $target ) {
-               if( $target instanceof User ) {
+               if ( $target instanceof User ) {
                        return $target->getUserPage();
                } elseif ( IP::isIPAddress( $target ) ) {
                        return Title::makeTitleSafe( NS_USER, $target );
@@ -455,18 +455,18 @@ class SpecialBlock extends FormSpecialPage {
         * @param $request WebRequest optionally try and get data from a request too
         * @return array( User|string|null, Block::TYPE_ constant|null )
         */
-       public static function getTargetAndType( $par, WebRequest $request = null ){
+       public static function getTargetAndType( $par, WebRequest $request = null ) {
                $i = 0;
                $target = null;
 
-               while( true ){
-                       switch( $i++ ){
+               while( true ) {
+                       switch( $i++ ) {
                                case 0:
                                        # The HTMLForm will check wpTarget first and only if it doesn't get
                                        # a value use the default, which will be generated from the options
                                        # below; so this has to have a higher precedence here than $par, or
                                        # we could end up with different values in $this->target and the HTMLForm!
-                                       if( $request instanceof WebRequest ){
+                                       if ( $request instanceof WebRequest ) {
                                                $target = $request->getText( 'wpTarget', null );
                                        }
                                        break;
@@ -474,13 +474,13 @@ class SpecialBlock extends FormSpecialPage {
                                        $target = $par;
                                        break;
                                case 2:
-                                       if( $request instanceof WebRequest ){
+                                       if ( $request instanceof WebRequest ) {
                                                $target = $request->getText( 'ip', null );
                                        }
                                        break;
                                case 3:
                                        # B/C @since 1.18
-                                       if( $request instanceof WebRequest ){
+                                       if ( $request instanceof WebRequest ) {
                                                $target = $request->getText( 'wpBlockAddress', null );
                                        }
                                        break;
@@ -490,7 +490,7 @@ class SpecialBlock extends FormSpecialPage {
 
                        list( $target, $type ) = Block::parseTarget( $target );
 
-                       if( $type !== null ){
+                       if ( $type !== null ) {
                                return array( $target, $type );
                        }
                }
@@ -511,9 +511,9 @@ class SpecialBlock extends FormSpecialPage {
 
                list( $target, $type ) = self::getTargetAndType( $value );
 
-               if( $type == Block::TYPE_USER ){
+               if ( $type == Block::TYPE_USER ) {
                        # TODO: why do we not have a User->exists() method?
-                       if( !$target->getId() ){
+                       if ( !$target->getId() ) {
                                return $form->msg( 'nosuchusershort',
                                        wfEscapeWikiText( $target->getName() ) );
                        }
@@ -523,31 +523,31 @@ class SpecialBlock extends FormSpecialPage {
                                return $form->msg( 'badaccess', $status );
                        }
 
-               } elseif( $type == Block::TYPE_RANGE ){
+               } elseif ( $type == Block::TYPE_RANGE ) {
                        list( $ip, $range ) = explode( '/', $target, 2 );
 
-                       if( ( IP::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 )
+                       if ( ( IP::isIPv4( $ip ) && $wgBlockCIDRLimit['IPv4'] == 32 )
                                || ( IP::isIPv6( $ip ) && $wgBlockCIDRLimit['IPv6'] == 128 ) )
                        {
                                # Range block effectively disabled
                                return $form->msg( 'range_block_disabled' );
                        }
 
-                       if( ( IP::isIPv4( $ip ) && $range > 32 )
+                       if ( ( IP::isIPv4( $ip ) && $range > 32 )
                                || ( IP::isIPv6( $ip ) && $range > 128 ) )
                        {
                                # Dodgy range
                                return $form->msg( 'ip_range_invalid' );
                        }
 
-                       if( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) {
+                       if ( IP::isIPv4( $ip ) && $range < $wgBlockCIDRLimit['IPv4'] ) {
                                return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv4'] );
                        }
 
-                       if( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) {
+                       if ( IP::isIPv6( $ip ) && $range < $wgBlockCIDRLimit['IPv6'] ) {
                                return $form->msg( 'ip_range_toolarge', $wgBlockCIDRLimit['IPv6'] );
                        }
-               } elseif( $type == Block::TYPE_IP ){
+               } elseif ( $type == Block::TYPE_IP ) {
                        # All is well
                } else {
                        return $form->msg( 'badipaddress' );
@@ -572,7 +572,7 @@ class SpecialBlock extends FormSpecialPage {
         * @param  $context IContextSource
         * @return Bool|String
         */
-       public static function processForm( array $data, IContextSource $context ){
+       public static function processForm( array $data, IContextSource $context ) {
                global $wgBlockAllowsUTEdit;
 
                $performer = $context->getUser();
@@ -585,7 +585,7 @@ class SpecialBlock extends FormSpecialPage {
                $data['Confirm'] = !in_array( $data['Confirm'], array( '', '0', null, false ), true );
 
                list( $target, $type ) = self::getTargetAndType( $data['Target'] );
-               if( $type == Block::TYPE_USER ){
+               if ( $type == Block::TYPE_USER ) {
                        $user = $target;
                        $target = $user->getName();
                        $userId = $user->getId();
@@ -597,14 +597,14 @@ class SpecialBlock extends FormSpecialPage {
                        # since both $data['PreviousTarget'] and $target are normalized
                        # but $data['target'] gets overriden by (non-normalized) request variable
                        # from previous request.
-                       if( $target === $performer->getName() &&
+                       if ( $target === $performer->getName() &&
                                ( $data['PreviousTarget'] !== $target || !$data['Confirm'] ) )
                        {
                                return array( 'ipb-blockingself' );
                        }
-               } elseif( $type == Block::TYPE_RANGE ){
+               } elseif ( $type == Block::TYPE_RANGE ) {
                        $userId = 0;
-               } elseif( $type == Block::TYPE_IP ){
+               } elseif ( $type == Block::TYPE_IP ) {
                        $target = $target->getName();
                        $userId = 0;
                } else {
@@ -612,24 +612,24 @@ class SpecialBlock extends FormSpecialPage {
                        return array( 'badipaddress' );
                }
 
-               if( ( strlen( $data['Expiry'] ) == 0) || ( strlen( $data['Expiry'] ) > 50 )
+               if ( ( strlen( $data['Expiry'] ) == 0) || ( strlen( $data['Expiry'] ) > 50 )
                        || !self::parseExpiryInput( $data['Expiry'] ) )
                {
                        return array( 'ipb_expiry_invalid' );
                }
 
-               if( !isset( $data['DisableEmail'] ) ){
+               if ( !isset( $data['DisableEmail'] ) ) {
                        $data['DisableEmail'] = false;
                }
 
                # If the user has done the form 'properly', they won't even have been given the
                # option to suppress-block unless they have the 'hideuser' permission
-               if( !isset( $data['HideUser'] ) ){
+               if ( !isset( $data['HideUser'] ) ) {
                        $data['HideUser'] = false;
                }
 
-               if( $data['HideUser'] ) {
-                       if( !$performer->isAllowed('hideuser') ){
+               if ( $data['HideUser'] ) {
+                       if ( !$performer->isAllowed('hideuser') ) {
                                # this codepath is unreachable except by a malicious user spoofing forms,
                                # or by race conditions (user has oversight and sysop, loads block form,
                                # and is de-oversighted before submission); so need to fail completely
@@ -638,16 +638,16 @@ class SpecialBlock extends FormSpecialPage {
                        }
 
                        # Recheck params here...
-                       if( $type != Block::TYPE_USER ) {
+                       if ( $type != Block::TYPE_USER ) {
                                $data['HideUser'] = false; # IP users should not be hidden
-                       } elseif( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) {
+                       } elseif ( !in_array( $data['Expiry'], array( 'infinite', 'infinity', 'indefinite' ) ) ) {
                                # Bad expiry.
                                return array( 'ipb_expiry_temp' );
-                       } elseif( $user->getEditCount() > self::HIDEUSER_CONTRIBLIMIT ) {
+                       } elseif ( $user->getEditCount() > self::HIDEUSER_CONTRIBLIMIT ) {
                                # Typically, the user should have a handful of edits.
                                # Disallow hiding users with many edits for performance.
                                return array( 'ipb_hide_invalid' );
-                       } elseif( !$data['Confirm'] ){
+                       } elseif ( !$data['Confirm'] ) {
                                return array( 'ipb-confirmhideuser' );
                        }
                }
@@ -665,15 +665,15 @@ class SpecialBlock extends FormSpecialPage {
                $block->isAutoblocking( $data['AutoBlock'] );
                $block->mHideName = $data['HideUser'];
 
-               if( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) {
+               if ( !wfRunHooks( 'BlockIp', array( &$block, &$performer ) ) ) {
                        return array( 'hookaborted' );
                }
 
                # Try to insert block. Is there a conflicting block?
                $status = $block->insert();
-               if( !$status ) {
+               if ( !$status ) {
                        # Show form unless the user is already aware of this...
-                       if( !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
+                       if ( !$data['Confirm'] || ( array_key_exists( 'PreviousTarget', $data )
                                && $data['PreviousTarget'] !== $target ) )
                        {
                                return array( array( 'ipb_already_blocked', $block->getTarget() ) );
@@ -683,13 +683,13 @@ class SpecialBlock extends FormSpecialPage {
                                # be sure the user is blocked by now it should work for our purposes
                                $currentBlock = Block::newFromTarget( $target );
 
-                               if( $block->equals( $currentBlock ) ) {
+                               if ( $block->equals( $currentBlock ) ) {
                                        return array( array( 'ipb_already_blocked', $block->getTarget() ) );
                                }
 
                                # If the name was hidden and the blocking user cannot hide
                                # names, then don't allow any block changes...
-                               if( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) {
+                               if ( $currentBlock->mHideName && !$performer->isAllowed( 'hideuser' ) ) {
                                        return array( 'cant-see-hidden-user' );
                                }
 
@@ -698,12 +698,12 @@ class SpecialBlock extends FormSpecialPage {
                                $logaction = 'reblock';
 
                                # Unset _deleted fields if requested
-                               if( $currentBlock->mHideName && !$data['HideUser'] ) {
+                               if ( $currentBlock->mHideName && !$data['HideUser'] ) {
                                        RevisionDeleteUser::unsuppressUserName( $target, $userId );
                                }
 
                                # If hiding/unhiding a name, this should go in the private logs
-                               if( (bool)$currentBlock->mHideName ){
+                               if ( (bool)$currentBlock->mHideName ) {
                                        $data['HideUser'] = true;
                                }
                        }
@@ -714,12 +714,12 @@ class SpecialBlock extends FormSpecialPage {
                wfRunHooks( 'BlockIpComplete', array( $block, $performer ) );
 
                # Set *_deleted fields if requested
-               if( $data['HideUser'] ) {
+               if ( $data['HideUser'] ) {
                        RevisionDeleteUser::suppressUserName( $target, $userId );
                }
 
                # Can't watch a rangeblock
-               if( $type != Block::TYPE_RANGE && $data['Watch'] ) {
+               if ( $type != Block::TYPE_RANGE && $data['Watch'] ) {
                        $performer->addWatch( Title::makeTitle( NS_USER, $target ) );
                }
 
@@ -757,18 +757,18 @@ class SpecialBlock extends FormSpecialPage {
         *     the wiki's content language
         * @return Array
         */
-       public static function getSuggestedDurations( $lang = null ){
+       public static function getSuggestedDurations( $lang = null ) {
                $a = array();
                $msg = $lang === null
                        ? wfMessage( 'ipboptions' )->inContentLanguage()->text()
                        : wfMessage( 'ipboptions' )->inLanguage( $lang )->text();
 
-               if( $msg == '-' ){
+               if ( $msg == '-' ) {
                        return array();
                }
 
-               foreach( explode( ',', $msg ) as $option ) {
-                       if( strpos( $option, ':' ) === false ){
+               foreach ( explode( ',', $msg ) as $option ) {
+                       if ( strpos( $option, ':' ) === false ) {
                                $option = "$option:$option";
                        }
 
@@ -787,7 +787,7 @@ class SpecialBlock extends FormSpecialPage {
         */
        public static function parseExpiryInput( $expiry ) {
                static $infinity;
-               if( $infinity == null ){
+               if ( $infinity == null ) {
                        $infinity = wfGetDB( DB_SLAVE )->getInfinity();
                }
 
@@ -832,8 +832,8 @@ class SpecialBlock extends FormSpecialPage {
                        $user = User::newFromName( $user );
                }
 
-               if( $performer->isBlocked() ){
-                       if( $user instanceof User && $user->getId() == $performer->getId() ) {
+               if ( $performer->isBlocked() ) {
+                       if ( $user instanceof User && $user->getId() == $performer->getId() ) {
                                # User is trying to unblock themselves
                                if ( $performer->isAllowed( 'unblockself' ) ) {
                                        return true;
@@ -857,40 +857,41 @@ class SpecialBlock extends FormSpecialPage {
         * reader for this block, to provide more information in the logs
         * @param $data Array from HTMLForm data
         * @param $type Block::TYPE_ constant (USER, RANGE, or IP)
-        * @return array
+        * @return string
         */
        protected static function blockLogFlags( array $data, $type ) {
                global $wgBlockAllowsUTEdit;
                $flags = array();
 
-               # when blocking a user the option 'anononly' is not available/has no effect -> do not write this into log
-               if( !$data['HardBlock'] && $type != Block::TYPE_USER ){
+               # when blocking a user the option 'anononly' is not available/has no effect
+               # -> do not write this into log
+               if ( !$data['HardBlock'] && $type != Block::TYPE_USER ) {
                        // For grepping: message block-log-flags-anononly
                        $flags[] = 'anononly';
                }
 
-               if( $data['CreateAccount'] ){
+               if ( $data['CreateAccount'] ) {
                        // For grepping: message block-log-flags-nocreate
                        $flags[] = 'nocreate';
                }
 
                # Same as anononly, this is not displayed when blocking an IP address
-               if( !$data['AutoBlock'] && $type == Block::TYPE_USER ){
+               if ( !$data['AutoBlock'] && $type == Block::TYPE_USER ) {
                        // For grepping: message block-log-flags-noautoblock
                        $flags[] = 'noautoblock';
                }
 
-               if( $data['DisableEmail'] ){
+               if ( $data['DisableEmail'] ) {
                        // For grepping: message block-log-flags-noemail
                        $flags[] = 'noemail';
                }
 
-               if( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ){
+               if ( $wgBlockAllowsUTEdit && $data['DisableUTEdit'] ) {
                        // For grepping: message block-log-flags-nousertalk
                        $flags[] = 'nousertalk';
                }
 
-               if( $data['HideUser'] ){
+               if ( $data['HideUser'] ) {
                        // For grepping: message block-log-flags-hiddenname
                        $flags[] = 'hiddenname';
                }
index 2bb53ab..fd603ce 100755 (executable)
@@ -31,7 +31,7 @@ def unichr3( *args ):
 
 # DEFINE
 UNIHAN_VER = '5.2.0'
-SF_MIRROR = 'cdnetworks-kr-2'
+SF_MIRROR = 'dfn'
 SCIM_TABLES_VER = '0.5.10'
 SCIM_PINYIN_VER = '0.5.91'
 LIBTABE_VER = '0.2.3'
@@ -370,7 +370,7 @@ $zh2Hant = array(\n'''
         +  PHPArray( toCN ) \
         +  '\n);\n\n$zh2SG = array(\n' \
         +  PHPArray( toSG ) \
-        +  '\n);'
+        +  '\n);\n'
     
     f = open( os.path.join( '..', 'ZhConversion.php' ), 'wb', encoding = 'utf8' )
     print ('Writing ZhConversion.php ... ')
index 2ebb750..1f7fe7d 100644 (file)
 分布于      分佈於
 分布於      分佈於
 想象 想像
+無線電視   無綫電視
+无线电视   無綫電視
+無線收費   無綫收費
+无线收费   無綫收費
+無線節目   無綫節目
+无线节目   無綫節目
+無線劇集   無綫劇集
+无线剧集   無綫劇集
+東鐵線      東鐵綫
+东铁线      東鐵綫
+觀塘線      觀塘綫
+观塘线      觀塘綫
+荃灣線      荃灣綫
+荃湾线      荃灣綫
+港島線      港島綫
+港岛线      港島綫
+東涌線      東涌綫
+东涌线      東涌綫
+將軍澳線   將軍澳綫
+将军澳线   將軍澳綫
+西鐵線      西鐵綫
+西铁线      西鐵綫
+馬鞍山線   馬鞍山綫
+马鞍山线   馬鞍山綫
+迪士尼線   迪士尼綫
+迪士尼线   迪士尼綫
+沙田至中環線     沙田至中環綫
+沙田至中环线     沙田至中環綫
+沙中線      沙中綫
+沙中线      沙中綫
+北環線      北環綫
+北环线      北環綫
+機場快線   機場快綫
+机场快线   機場快綫
+505線 505綫
+505线 505綫
+507線 507綫
+507线 507綫
+610線 610綫
+610线 610綫
+614線 614綫
+614线 614綫
+614P線        614P綫
+614P线        614P綫
+615線 615綫
+615线 615綫
+615P線        615P綫
+615P线        615P綫
+705線 705綫
+705线 705綫
+706線 706綫
+706线 706綫
+751線 751綫
+751线 751綫
+751P線        751P綫
+751P线        751P綫
+761P線        761P綫
+761P线        761P綫
index 35b6268..1a14e99 100644 (file)
 想象 想像
 锎    鉲
 信道 信道
+綫    線
index 71565ae..63f32bf 100644 (file)
@@ -495,9 +495,9 @@ Ur roll eus ar pajennoù dibar reizh a c'hallit kavour war [[Special:SpecialPage
 'databaseerror' => 'Fazi bank roadennoù',
 'dberrortext' => 'C\'hoarvezet ez eus ur fazi ereadur eus ar reked er bank roadennoù, ar pezh a c\'hall talvezout ez eus un draen er meziant.
 Setu ar goulenn bet pledet gantañ da ziwezhañ :
-<blockquote><tt>$1</tt></blockquote>
-adal an arc\'hwel "<tt>$2</tt>".
-Adkaset eo bet ar fazi "<tt>$3: $4</tt>" gant ar bank roadennoù.',
+<blockquote><code>$1</code></blockquote>
+adal an arc\'hwel "<code>$2</code>".
+Adkaset eo bet ar fazi "<samp>$3: $4</samp>" gant ar bank roadennoù.',
 'dberrortextcl' => 'Ur fazi ereadur zo en ur reked savet ouzh ar bank roadennoù.
 Setu ar goulenn bet pledet gantañ da ziwezhañ :
 "$1"
@@ -837,10 +837,10 @@ pe <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}
 'blocked-notice-logextract' => "Stanket eo an implijer-mañ evit poent.
 Dindan emañ merket moned diwezhañ marilh ar stankadennoù, d'ho kelaouiñ :",
 'clearyourcache' => "Notenn :''' Goude bezañ enrollet ho pajenn e rankot freskaat krubuilh ho merdeer a-benn gwelet ar c'hemmoù.
-* '''Firefox / Safari: ''' Derc'hel da bouezañ war ''Pennlizherenn'' en ur glikañ war ''Adkargañ'', pe pouezañ war ''Ctrl-F5'' pe ''Ctrl-R'' (''⌘-R'' war ur Mac); 
-* '''Google Chrome:''' Pouezañ war ''Ctrl-Pennlizh-R'' (''⌘-Shift-R'' war ur Mac)
+* '''Firefox / Safari:''' Derc'hel da bouezañ war ''Pennlizherenn'' en ur glikañ war ''Adkargañ'', pe pouezañ war ''Ctrl-F5'' pe ''Ctrl-R'' (''⌘-R'' war ur Mac); 
+* ''''Google Chrome:''' Pouezañ war ''Ctrl-Pennlizh-R'' (''⌘-Shift-R'' war ur Mac)
 * '''Internet Explorer:''' Derc'hel da bouezañ war ''Ctrl'' en ur glikañ war ''Freskaat,'' pe pouezañ war ''Ctrl-F5''
-* '''Konqueror: '''Klikañ war ''Adkargañ'' pe pouezañ war ''F5;'' 
+* ''''Konqueror: '''Klikañ war ''Adkargañ'' pe pouezañ war ''F5;'' 
 * '''Opera:''' Riñsañ ar grubuilh e ''Ostilhoù → Penndibaboù''",
 'usercssyoucanpreview' => "'''Tun :''' Grit gant ar bouton \"{{int:showpreview}}\" evit testiñ ho follenn CSS nevez a-raok enrollañ anezhi.",
 'userjsyoucanpreview' => "'''Tun :''' Grit gant ar bouton \"{{int:showpreview}}\" evit testiñ ho follenn JS nevez a-raok enrollañ anezhi.",
index d0d6682..263acb9 100644 (file)
@@ -523,7 +523,7 @@ $1',
 'disclaimerpage' => 'Project:Uslovi korištenja, pravne napomene i odricanje odgovornosti',
 'edithelp' => 'Pomoć pri uređivanju stranice',
 'edithelppage' => 'Help:Uređivanje',
-'helppage' => 'Pomoć:Sadržaj',
+'helppage' => 'Help:Sadržaj',
 'mainpage' => 'Početna strana',
 'mainpage-description' => 'Početna strana',
 'policy-url' => 'Project:Pravila',
@@ -666,6 +666,7 @@ $2',
 'ns-specialprotected' => 'Specijalne stranice se ne mogu uređivati.',
 'titleprotected' => 'Naslov stranice je zaštićen od postavljanja od strane korisnika [[User:$1|$1]].
 Iz razloga "\'\'$2\'\'".',
+'exception-nologin' => 'Niste prijavljeni',
 
 # Virus scanner
 'virus-badscanner' => "Loša konfiguracija: nepoznati anti-virus program: ''$1''",
@@ -3022,6 +3023,8 @@ Ovo je vjerovatno izazvao vezom ka vanjskoj nepoželjnoj stranici.',
 # Info page
 'pageinfo-title' => 'Informacije za "$1"',
 'pageinfo-header-edits' => 'Izmjene',
+'pageinfo-header-restrictions' => 'Zaštita stranice',
+'pageinfo-article-id' => 'ID stranice',
 'pageinfo-views' => 'Broj pogleda',
 'pageinfo-watchers' => 'Broj onih koji pregledaju',
 'pageinfo-edits' => 'Broj izmjena',
index 263a0bb..03f45f7 100644 (file)
@@ -413,6 +413,10 @@ $1',
 'youhavenewmessages' => '$1ت ھەیە ($2).',
 'newmessageslink' => 'پەیامی نوێ',
 'newmessagesdifflink' => 'دوا گۆڕانکارییەکان',
+'youhavenewmessagesfromusers' => '$1ت لە {{PLURAL:$3|بەکارھێنەرێکی تر| $3 بەکارھێنەر}} ھەیە ( $2 ).',
+'youhavenewmessagesmanyusers' => '$1ت  لە ژمارەیەک بەکارھێنەر ھەیە ( $2 ).',
+'newmessageslinkplural' => '{{PLURAL:$1|پەیامێکی نوێ|پەیامی نوێ}}',
+'newmessagesdifflinkplural' => 'دوایین {{PLURAL:$1|گۆڕانکاری|گۆڕانکارییەکان}}',
 'youhavenewmessagesmulti' => 'لە $1 دا پەیامی نوێت ھەیە',
 'editsection' => 'دەستکاری',
 'editold' => 'دەستکاری',
@@ -3149,7 +3153,7 @@ $5
 
 # Signatures
 'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|لێدوان]])',
-'timezone-utc' => 'بەکاتی جیهانی',
+'timezone-utc' => 'UTC',
 
 # Core parser functions
 'unknown_extension_tag' => 'تاگی درێژکراوەی نەناسراو "$1"',
index e039978..3985e1e 100644 (file)
@@ -404,7 +404,7 @@ $messages = array(
 'redirectedfrom' => '(Omdirigeret fra $1)',
 'redirectpagesub' => 'Omdirigering',
 'lastmodifiedat' => 'Denne side blev senest ændret $1 kl. $2.',
-'viewcount' => 'Siden er vist {{PLURAL:$1|en gang|$1 gange}}.',
+'viewcount' => 'Siden er vist {{PLURAL:$1|en gang|$1 gange}}.',
 'protectedpage' => 'Beskyttet side',
 'jumpto' => 'Skift til:',
 'jumptonavigation' => 'Navigation',
@@ -858,7 +858,6 @@ Loggen over den seneste blokering ses nedenfor:',
 * '''Firefox / Safari:''' Hold ''shifttasten'' nede og klik på ''reload'', eller tryk enten ''Ctrl-F5'' eller ''Ctrl-Shift-r'' (''⌘-R'' på en Mac).
 * '''Google Chrome:''' Tryk ''Ctrl-Shift-R'' (''⌘-Shift-R'' på en Mac).
 * '''Internet Explorer:''' Hold ''controltasten'' nede og klik på ''refresh'' eller tryk på ''Ctrl-F5''.
-* '''Konqueror:''' Klik på ''reload'' eller tryk på ''F5''.
 * '''Opera:''' Tøm cachen i ''Tools → Preferences''.",
 'usercssyoucanpreview' => "'''Tip:''' Brug \"{{int:showpreview}}\"-knappen for at teste dit nye CSS inden du gemmer.",
 'userjsyoucanpreview' => "'''Tip:''' Brug \"{{int:showpreview}}\"-knappen for at teste dit nye JavaScript inden du gemmer.",
@@ -1836,6 +1835,7 @@ Måske vil du redigere beskrivelsen på dens [$2 filbeskrivelsesside] der.',
 'uploadnewversion-linktext' => 'Læg en ny version af denne fil op',
 'shared-repo-from' => 'fra $1',
 'shared-repo' => 'et delt filarkiv',
+'upload-disallowed-here' => 'Desværre kan du ikke overskrive dette billede.',
 
 # File reversion
 'filerevert' => 'Gendan $1',
@@ -1944,6 +1944,7 @@ Hver linje indeholder henvisninger til den første og den anden omdirigering, s
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|byte|bytes}}',
 'ncategories' => '$1 {{PLURAL:$1|kategori|kategorier}}',
+'ninterwikis' => '$1 {{PLURAL:$1|interwikilink|interwikilinks}}',
 'nlinks' => '{{PLURAL:$1|1 henvisning|$1 henvisninger}}',
 'nmembers' => '$1 {{PLURAL:$1|medlem|medlemmer}}',
 'nrevisions' => '{{PLURAL:$1|1 ændring|$1 ændringer}}',
@@ -1972,6 +1973,7 @@ Hver linje indeholder henvisninger til den første og den anden omdirigering, s
 'mostlinkedtemplates' => 'Hyppigst brugte skabeloner',
 'mostcategories' => 'Mest brugte sider',
 'mostimages' => 'Mest brugte filer',
+'mostinterwikis' => 'Sider med flest interwikilinks',
 'mostrevisions' => 'Sider med de fleste ændringer',
 'prefixindex' => 'Alle sider med præfiks',
 'prefixindex-namespace' => 'Alle sider med præfiks (navnerummet $1)',
@@ -2118,6 +2120,8 @@ Der findes muligvis [[{{MediaWiki:Listgrouprights-helppage}}|yderligere informat
 'mailnologin' => 'Du er ikke logget på',
 'mailnologintext' => 'Du skal være [[Special:UserLogin|logget på]] og have en gyldig e-mailadresse sat i dine [[Special:Preferences|indstillinger]] for at sende e-mail til andre brugere.',
 'emailuser' => 'E-mail til denne bruger',
+'emailuser-title-target' => 'Send email til denne {{GENDER:$1|bruger}}',
+'emailuser-title-notarget' => 'Send email til en bruger',
 'emailpage' => 'E-mail bruger',
 'emailpagetext' => 'Du kan bruge formularen nedenfor til at sende en e-mail til denne bruger.
 Den e-mail-adresse du har angivet i [[Special:Preferences|dine indstillinger]] vil dukke op i "fra"-feltet på e-mailen, så modtageren kan svare dig.',
@@ -2895,11 +2899,27 @@ Dette skyldes sandsynligvis en henvisning til et sortlistet eksternt websted.',
 
 # Info page
 'pageinfo-title' => 'Information om "$1"',
-'pageinfo-header-edits' => 'Redigeringer',
+'pageinfo-header-basic' => 'Grundlæggende oplysninger',
+'pageinfo-header-edits' => 'Redigeringshistorik',
+'pageinfo-header-restrictions' => 'Sidebeskyttelse',
+'pageinfo-header-properties' => 'Sideegenskaber',
+'pageinfo-default-sort' => 'Standardsorteringsnøgle',
+'pageinfo-length' => 'Sidelængde (i bytes)',
+'pageinfo-article-id' => 'Side-ID',
+'pageinfo-robot-index' => 'Indekserbar',
+'pageinfo-robot-noindex' => 'Ikke indekserbar',
 'pageinfo-views' => 'Antal visninger',
 'pageinfo-watchers' => 'Antal brugere, der overvåger siden',
-'pageinfo-edits' => 'Antal redigeringer',
-'pageinfo-authors' => 'Antal forskellige forfattere',
+'pageinfo-redirects-name' => 'Omdirigeringer til denne side',
+'pageinfo-subpages-name' => 'Undersider til denne side',
+'pageinfo-firsttime' => 'Dato for oprettelsen af siden',
+'pageinfo-lasttime' => 'Dato for seneste redigering',
+'pageinfo-edits' => 'Samlet antal redigeringer',
+'pageinfo-authors' => 'Det samlede antal forskellige forfattere',
+'pageinfo-restriction' => 'Sidebeskyttelse (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Magisk|Magiske}} ord ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Skjult kategori|Skjulte kategorier}} ($1)',
+'pageinfo-templates' => '{{PLURAL:$1|Transkluderet skabelon|Transkluderede skabeloner}} ($1)',
 
 # Skin names
 'skinname-standard' => 'Klassik',
@@ -2953,6 +2973,7 @@ Du kan beskadige dit system hvis du udfører den.",
 'file-info-size-pages' => '$1 × $2 punkter, filstørrelse: $3, MIME-type: $4, $5 {{PLURAL:$5|side|sider}}',
 'file-nohires' => 'Ingen højere opløsning fundet.',
 'svg-long-desc' => 'SVG fil, basisstørrelse $1 × $2 punkters, størrelse: $3',
+'svg-long-desc-animated' => 'Animeret SVG-fil, basisstørrelse $1 × $2 punkter, filstørrelse: $3',
 'show-big-image' => 'Version i større opløsning',
 'show-big-image-preview' => 'Størrelse af denne forhåndsvisning: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Anden opløsning|Andre opløsninger}}: $1.',
@@ -2962,6 +2983,8 @@ Du kan beskadige dit system hvis du udfører den.",
 'file-info-png-looped' => 'gentaget',
 'file-info-png-repeat' => 'afspillede $1 {{PLURAL:$1|gang|gange}}',
 'file-info-png-frames' => '$1 {{PLURAL:$1|billede|billeder}}',
+'file-no-thumb-animation' => "'''Bemærk: På grund af tekniske begrænsninger vil miniaturebilleder af denne fil ikke blive animeret.'''",
+'file-no-thumb-animation-gif' => "'''Bemærk: På grund af tekniske begrænsninger vil miniaturebilleder af GIF-filer, der som denne er i høj opløsning, ikke blive animeret.'''",
 
 # Special:NewFiles
 'newimages' => 'Galleri med de nyeste billeder',
index 72f9a97..2dd650f 100644 (file)
@@ -2062,8 +2062,8 @@ Eine [[Special:WhatLinksHere/$2|vollständige Liste]] ist verfügbar.',
 Vielleicht möchtest du die Beschreibung auf der dortigen [$2 Dateibeschreibungsseite] bearbeiten.',
 'sharedupload-desc-create' => 'Diese Datei stammt aus $1 und kann von anderen Projekten verwendet werden.
 Vielleicht möchtest du die Beschreibung auf der dortigen [$2 Dateibeschreibungsseite] bearbeiten.',
-'filepage-nofile' => 'Es ist keine Datei dieses namens vorhanden.',
-'filepage-nofile-link' => 'Es ist keine Datei dieses namens vorhanden. Du kannst jedoch [$1 diese Datei hochladen].',
+'filepage-nofile' => 'Es ist keine Datei dieses Namens vorhanden.',
+'filepage-nofile-link' => 'Es ist keine Datei dieses Namens vorhanden. Du kannst jedoch [$1 diese Datei hochladen].',
 'uploadnewversion-linktext' => 'Eine neue Version dieser Datei hochladen',
 'shared-repo-from' => 'aus $1',
 'shared-repo' => 'einem gemeinsam genutzten Medienarchiv',
index a5bde5a..2308b5c 100644 (file)
@@ -2333,7 +2333,7 @@ $UNWATCHURL
 თქვენ შეგიძლიათ ამ გვერდის დაცვის დონე შეცვალოთ, თუმცა ეს კასკადურ დაცვაზე გავლენას არ იქონიებს.',
 'protect-default' => 'ყველა მომხმარებელი',
 'protect-fallback' => 'საჭიროა „$1-ის“ უფლება',
-'protect-level-autoconfirmed' => 'ახალი და არარეგისტრირებული მომხმარებლების დაბლოკვა',
+'protect-level-autoconfirmed' => 'ახალი და არარეგისტრირებული მომხმარებლებისაგან დაცვა',
 'protect-level-sysop' => 'მხოლოდ ადმინისტრატორები',
 'protect-summary-cascade' => 'იერარქიული',
 'protect-expiring' => 'ვადა გასდის: $1 (UTC)',
@@ -2410,7 +2410,7 @@ $UNWATCHURL
 'undelete-no-results' => 'არ არის ნაპოვნი შესაბამისი გვერდები წაშლათა არქივში.',
 'undelete-filename-mismatch' => 'შეუძლებელია წაშლილი ფაილის აღდგენა $1-ში – განსხვავებები წაშლამდე.',
 'undelete-bad-store-key' => 'შეუძლებელია წაშლილი ფაილის აღდგენა $1-ში – იგი არ არსებობდა წაშლამდე.',
-'undelete-cleanup-error' => 'გამოუყენებელი სარქივო ფაილის «$1» წაშლის შეცდომა:',
+'undelete-cleanup-error' => 'გამოუყენებელი სარქივო ფაილის „$1“ წაშლის შეცდომა:',
 'undelete-missing-filearchive' => 'შეუძლებელია ფაილის აღდგენა არქივის იდენტიფიკატორით $1, რადგანაც ის არ არის მონაცემთა ბაზაში. შესაძლებელია ფაილი უკვე აღდგენილია.',
 'undelete-error' => 'შეცდომა გვერდის აღდგენისას',
 'undelete-error-short' => 'შეცდომა ფაილის წაშლის გაუქმებაში: $1',
@@ -2457,7 +2457,7 @@ $1',
 
 # What links here
 'whatlinkshere' => 'ბმული გვერდზე',
-'whatlinkshere-title' => 'გვერდები, რომლებიც შეიცავენ ბმულებს "$1"-ზე',
+'whatlinkshere-title' => 'გვერდები, რომლებიც შეიცავენ ბმულებს „$1“-ზე',
 'whatlinkshere-page' => 'გვერდი:',
 'linkshere' => "მომდევნო გვერდები შეიცავენ ბმულებს '''[[:$1]]'''-ზე:",
 'nolinkshere' => "'''[[:$1]]'''-ზე ბმული არ არის.",
index 0e59ab4..0005c66 100644 (file)
@@ -3879,6 +3879,11 @@ MediaWiki ଉପଯୋଗୀ ହେବା ଲକ୍ଷରେ ବଣ୍ଟାଯ
 'api-error-verification-error' => 'ଏହି ଫାଇଲଟି ବୋଧ ହୁଏ ନଷ୍ଟ ହୋଇଯାଇଅଛି କିମ୍ବା ଭୁଲ ଏକ୍ସଟେନସନ ଦିଆଯାଇଅଛି ।',
 
 # Durations
+'duration-seconds' => '$1 {{PLURAL:$1|ସେକଣ୍ଡ|ସେକେଣ୍ଡ}}',
+'duration-minutes' => '$1 {{PLURAL:$1|ମିନିଟ|ମିନିଟ}}',
+'duration-hours' => '$1 {{PLURAL:$1|ଘଣ୍ଟା|ଘଣ୍ଟା}}',
+'duration-days' => '$1 {{PLURAL:$1|ଦିନ|ଦିନଗୁଡିକ}}',
+'duration-weeks' => '$1 {{PLURAL: $1|ସପ୍ତାହ|ସପ୍ତାହଗୁଡିକ}}',
 'duration-years' => '$1 {{PLURAL:$1|year|years}}',
 'duration-decades' => '$1 {{PLURAL:$1|decade|decades}',
 'duration-centuries' => '$1 {{PLURAL:$1|century|centuries}}',
index da95401..3b3bf84 100644 (file)
@@ -2760,9 +2760,9 @@ A peul visualisene la sorgiss",
 'tooltip-ca-nstab-image' => "Vardé la pàgina dl'archivi",
 'tooltip-ca-nstab-mediawiki' => 'Vardé ël mëssagi ëd sistema.',
 'tooltip-ca-nstab-template' => 'Vardé lë stamp.',
-'tooltip-ca-nstab-help' => 'Vardé la pàgina d',
+'tooltip-ca-nstab-help' => "Vardé la pàgina d'agiut",
 'tooltip-ca-nstab-category' => 'Vardé la pàgina dla categorìa.',
-'tooltip-minoredit' => 'Marca sossì coma modìfica cita',
+'tooltip-minoredit' => 'Marché sòn coma modìfica cita',
 'tooltip-save' => 'Salva le modìfiche',
 'tooltip-preview' => 'Preuva dle modìfiche (mej sempe fela, prima che fé che salvé!)',
 'tooltip-diff' => "Fame vëdde che modìfiche che i l'hai faje al test.",
index 6a55ec0..60e8121 100644 (file)
@@ -3270,10 +3270,26 @@ $1',
 'pageinfo-header-properties' => 'Својства странице',
 'pageinfo-display-title' => 'Наслов за приказ',
 'pageinfo-default-sort' => 'Подразумевани кључ сортирања',
+'pageinfo-length' => 'Дужина странице (у бајтовима)',
+'pageinfo-article-id' => 'ИД странице',
+'pageinfo-robot-policy' => 'Статус претраживача',
+'pageinfo-robot-index' => 'Може да се попише',
+'pageinfo-robot-noindex' => 'Не може да се попише',
 'pageinfo-views' => 'Број прегледа',
 'pageinfo-watchers' => 'Број надгледача страница',
+'pageinfo-redirects-name' => 'Преусмеравања на страницу',
+'pageinfo-subpages-name' => 'Подстранице ове странице',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|преусмерење|преусмерења|преусмерења}}; $3 {{PLURAL:$3|непреусмерење|непреусмерења|непреусмерења}})',
+'pageinfo-firstuser' => 'Аутор странице',
+'pageinfo-firsttime' => 'Датум стварања странице',
+'pageinfo-lastuser' => 'Последњи уредник',
+'pageinfo-lasttime' => 'Датум последње измене',
 'pageinfo-edits' => 'Број измена',
 'pageinfo-authors' => 'Број засебних аутора',
+'pageinfo-recent-edits' => 'Број скорашњих измена (у последњих $1)',
+'pageinfo-recent-authors' => 'Број скорашњих засебних аутора',
+'pageinfo-restriction' => 'Заштита странице (<code>{{lcfirst:$1}}</code>)',
+'pageinfo-magic-words' => '{{PLURAL:$1|Магична реч|Магичне речи}} ($1)',
 
 # Skin names
 'skinname-standard' => 'Класично',
index c343447..3f4acd2 100644 (file)
@@ -3127,6 +3127,8 @@ Detta orsakades troligen av en länk till en svartlistad webbplats.',
 'pageinfo-lasttime' => 'Datum för senaste redigeringen',
 'pageinfo-edits' => 'Totalt antal redigeringar',
 'pageinfo-authors' => 'Totalt antal olika författare',
+'pageinfo-recent-edits' => 'Antal nyliga redigeringar (inom de senaste $1)',
+'pageinfo-recent-authors' => 'Antal nyliga olika författare',
 'pageinfo-restriction' => 'Sidskydd (<code>{{lcfirst:$1}}</code>)',
 'pageinfo-magic-words' => '{{PLURAL:$1|Magiskt|Magiska}} ord ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Dold kategori|Dolda kategorier}} ($1)',
index 148206a..95d9f23 100644 (file)
@@ -693,7 +693,7 @@ $2
 # Special:ChangeEmail
 'changeemail' => 'ఈ-మెయిలు చిరునామా మార్పు',
 'changeemail-header' => 'ఖాతా ఈ-మెయిల్ చిరునామాని మార్చండి',
-'changeemail-text' => 'à°®à±\80 à°\88à°®à±\86యిలà±\8d à°\9aà°¿à°°à±\81నామా à°®à°¾à°°à±\8dà°\9aà±\81à°\9fà°\95à±\81 à°\88 à°«à°¾à°°à°®à±\81 à°¨à°¿à°\82à°ªà°\82à°¡à°¿. à°\88 à°®à°¾à°°à±\8dà°ªà±\81ని à°\96à°\9aà±\8dà°\9aితపరà°\9aà±\81à°\9fà°\95à±\81 à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82  à°ªà±\8dà°°à°µà±\87శపà±\86à°\9fà±\8dà°\9fాలి.',
+'changeemail-text' => 'à°®à±\80 à°\88à°®à±\86యిలà±\81 à°\9aà°¿à°°à±\81నామాని à°®à°¾à°°à±\8dà°\9aà±\81à°\95à±\8bడానిà°\95à°¿ à°\88 à°«à°¾à°°à°¾à°¨à±\8dని à°¨à°¿à°\82à°ªà°\82à°¡à°¿. à°\88 à°®à°¾à°°à±\8dà°ªà±\81ని à°¨à°¿à°°à±\8dధారిà°\82à°\9aడానిà°\95à°¿ à°®à±\80 à°¸à°\82à°\95à±\87తపదానà±\8dని à°\87à°µà±\8dవాలà±\8dసివసà±\8dà°¤à±\81à°\82à°¦ి.',
 'changeemail-no-info' => 'ఈ పేజీని నేరుగా చూడటానికి మీరు లోనికి ప్రవేశించివుండాలి.',
 'changeemail-oldemail' => 'ప్రస్తుత ఈ-మెయిలు చిరునామా:',
 'changeemail-newemail' => 'కొత్త ఈ-మెయిలు చిరునామా:',
index 9b3b383..973166f 100644 (file)
@@ -620,8 +620,8 @@ $1',
 'youhavenewmessages' => 'Ви отримали $1 ($2).',
 'newmessageslink' => 'нові повідомлення',
 'newmessagesdifflink' => 'остання зміна',
-'newmessageslinkplural' => '{{PLURAL:$1|нове повідомлення|нові повідомлення}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|остання зміна|останні зміни}}',
+'newmessageslinkplural' => '{{PLURAL:$1|нове повідомлення|нові повідомлення|нових повідомлень}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|остання зміна|останні зміни|останніх змін}}',
 'youhavenewmessagesmulti' => 'Ви отримали нові повідомлення на $1',
 'editsection' => 'ред.',
 'editsection-brackets' => '[$1]',
@@ -1026,7 +1026,7 @@ $2
 'userpage-userdoesnotexist-view' => 'Обліковий запис користувача „$1“ не зареєстровано.',
 'blocked-notice-logextract' => 'Цей користувач наразі заблокований.
 Останній запис у журналі блокувань такий:',
-'clearyourcache' => "'''Увага:''' Ð\9fÑ\96Ñ\81лÑ\8f Ð·Ð±ÐµÑ\80еженнÑ\8f Ñ\81лÑ\96д Ð¾Ñ\87иÑ\81Ñ\82иÑ\82и ÐºÐµÑ\88 Ð±Ñ\80аÑ\83зеÑ\80а, щоб побачити зміни.
+'clearyourcache' => "'''Увага:''' Ð\9fÑ\96Ñ\81лÑ\8f Ð·Ð±ÐµÑ\80еженнÑ\8f Ñ\81лÑ\96д Ð¾Ñ\87иÑ\81Ñ\82иÑ\82и ÐºÐµÑ\88 Ð¾Ð³Ð»Ñ\8fдаÑ\87а, щоб побачити зміни.
 * '''Firefox / Safari:''' тримайте ''Shift'', коли натискаєте ''Оновити'', або натисніть ''Ctrl-F5'' чи ''Ctrl-Shift-R'' (''⌘-R'' на Apple Mac)
 * '''Google Chrome:''' натисніть ''Ctrl-Shift-R'' (''⌘-Shift-R'' на Apple Mac)
 * '''Internet Explorer:''' тримайте ''Ctrl'', коли натискаєте ''Оновити'', або натисніть ''Ctrl-F5''
index 823d467..0053b5e 100644 (file)
@@ -3,10 +3,27 @@
  */
 (function( $ ) {
        window.doLivePreview = function( e ) {
+               var previewShowing = false;
+
                e.preventDefault();
 
                $( mw ).trigger( 'LivePreviewPrepare' );
 
+               var $wikiPreview = $( '#wikiPreview' );
+
+               $( '#mw-content-text' ).css( 'position', 'relative' );
+
+               if ( $wikiPreview.is( ':visible' ) ) {
+                       previewShowing = true;
+               }
+
+               // show #wikiPreview if it's hidden (if it is hidden, it's also empty, so nothing changes in the rendering)
+               // to be able to scroll to it
+               $wikiPreview.show();
+
+               // Jump to where the preview will appear
+               $wikiPreview[0].scrollIntoView();
+
                var postData = $('#editform').formToArray();
                postData.push( { 'name' : e.target.name, 'value' : '1' } );
 
                                                        '#catlinks', '#p-lang', '.mw-summary-preview'];
                var copySelector = copyElements.join(',');
 
-               $.each( copyElements, function(k,v) { $(v).fadeOut('fast'); } );
+               $.each( copyElements, function( k, v ) {
+                       $( v ).fadeTo( 'fast', 0.4 );
+               } );
 
                // Display a loading graphic
                var loadSpinner = $('<div class="mw-ajax-loader"/>');
-               $('#wikiPreview').before( loadSpinner );
+               // Move away from header (default is -16px)
+               loadSpinner.css( 'top', '0' );
+
+               // If the preview is already showing, overlay the spinner on top of it.
+               if ( previewShowing ) {
+                       loadSpinner.css( {
+                               'position': 'absolute',
+                               'z-index': '3',
+                               'left': '50%',
+                               'margin-left': '-16px'
+                       } );
+               }
+               $wikiPreview.before( loadSpinner );
 
                var page = $('<div/>');
                var target = $('#editform').attr('action');
                                        $(copyElements[i]).prop( 'class', newClasses );
                                }
 
-                               $.each( copyElements, function(k,v) {
+                               $.each( copyElements, function( k, v ) {
                                        // Don't belligerently show elements that are supposed to be hidden
-                                       $(v).fadeIn( 'fast', function() { $(this).css('display', ''); } );
+                                       $( v ).fadeTo( 'fast', 1, function() {
+                                               $( this ).css( 'display', '' );
+                                       } );
                                } );
 
                                loadSpinner.remove();
index 8c35626..94ed322 100644 (file)
@@ -260,6 +260,7 @@ tr.mw-htmlform-vertical-label td.mw-label {
 
 input#wpSummary {
        width: 80%;
+       margin: 1em 0;
 }
 
 /**
index 5036268..453e88a 100644 (file)
@@ -2442,6 +2442,21 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 </p>
 !! end
 
+!! test
+Broken image links with HTML captions (bug 39700)
+!! input
+[[File:Nonexistent|<script></script>]]
+[[File:Nonexistent|100px|<script></script>]]
+[[File:Nonexistent|&lt;]]
+[[File:Nonexistent|a<i>b</i>c]]
+!! result
+<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
+<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
+<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;</a>
+<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">abc</a>
+</p>
+!! end
+
 !! test
 Plain link to URL
 !! input
index ea9d553..20e42a6 100644 (file)
@@ -87,6 +87,14 @@ class SpecialSearchTest extends MediaWikiTestCase {
                                'advanced', array( 2, 14 ),
                                'Bug 33583: search with no option should honor User search preferences'
                        ),
+                       array(
+                               $EMPTY_REQUEST, array_fill_keys( array_map( function( $ns ) {
+                                       return "searchNs$ns";
+                               }, $defaultNS ), 0 ) + array( 'searchNs2' => 1, 'searchNs14' => 1 ),
+                               'advanced', array( 2, 14 ),
+                               'Bug 33583: search with no option should honor User search preferences'
+                               . 'and have all other namespace disabled'
+                       ),
                );
        }