Merge "Improve doPrepareInternal error messages"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 10 Nov 2014 21:03:13 +0000 (21:03 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 10 Nov 2014 21:03:13 +0000 (21:03 +0000)
38 files changed:
includes/AutoLoader.php
includes/ChangeTags.php
includes/WatchedItem.php
includes/api/ApiQueryAllDeletedRevisions.php
includes/api/ApiQueryBlocks.php
includes/api/ApiQueryDeletedRevisions.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQueryRevisionsBase.php
includes/api/i18n/de.json
includes/api/i18n/pt.json
includes/api/i18n/zh-hans.json
includes/cache/MessageCache.php
includes/context/RequestContext.php
includes/libs/cdb/CdbException.php [new file with mode: 0644]
includes/libs/cdb/CdbFunctions.php [new file with mode: 0644]
includes/libs/cdb/CdbReader.php [new file with mode: 0644]
includes/libs/cdb/CdbReaderDBA.php [new file with mode: 0644]
includes/libs/cdb/CdbReaderPHP.php [new file with mode: 0644]
includes/libs/cdb/CdbWriter.php [new file with mode: 0644]
includes/libs/cdb/CdbWriterDBA.php [new file with mode: 0644]
includes/libs/cdb/CdbWriterPHP.php [new file with mode: 0644]
includes/parser/LinkHolderArray.php
includes/parser/Parser.php
includes/utils/Cdb.php [deleted file]
includes/utils/CdbDBA.php [deleted file]
includes/utils/CdbPHP.php [deleted file]
languages/i18n/ang.json
languages/i18n/az.json
languages/i18n/be-tarask.json
languages/i18n/cdo.json
languages/i18n/en.json
languages/i18n/fy.json
languages/i18n/ilo.json
languages/i18n/pl.json
languages/i18n/sah.json
languages/i18n/th.json
tests/phpunit/includes/libs/cdb/CdbTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/CdbTest.php [deleted file]

index bbcce6f..9f9deb7 100644 (file)
@@ -701,6 +701,16 @@ $wgAutoloadLocalClasses = array(
        'VirtualRESTServiceClient' => 'includes/libs/virtualrest/VirtualRESTServiceClient.php',
        'XmlTypeCheck' => 'includes/libs/XmlTypeCheck.php',
 
+       # includes/libs/cdb
+       'CdbException' => 'includes/libs/cdb/CdbException.php',
+       'CdbFunctions' => 'includes/libs/cdb/CdbFunctions.php',
+       'CdbReader' => 'includes/libs/cdb/CdbReader.php',
+       'CdbReaderDBA' => 'includes/libs/cdb/CdbReaderDBA.php',
+       'CdbReaderPHP' => 'includes/libs/cdb/CdbReaderPHP.php',
+       'CdbWriter' => 'includes/libs/cdb/CdbWriter.php',
+       'CdbWriterDBA' => 'includes/libs/cdb/CdbWriterDBA.php',
+       'CdbWriterPHP' => 'includes/libs/cdb/CdbWriterPHP.php',
+
        # includes/libs/lessphp
        'lessc' => 'includes/libs/lessc.inc.php',
        'lessc_parser' => 'includes/libs/lessc.inc.php',
@@ -1151,14 +1161,6 @@ $wgAutoloadLocalClasses = array(
        'UploadStashNoSuchKeyException' => 'includes/upload/UploadStash.php',
 
        # includes/utils
-       'CdbException' => 'includes/utils/Cdb.php',
-       'CdbFunctions' => 'includes/utils/CdbPHP.php',
-       'CdbReader' => 'includes/utils/Cdb.php',
-       'CdbReaderDBA' => 'includes/utils/CdbDBA.php',
-       'CdbReaderPHP' => 'includes/utils/CdbPHP.php',
-       'CdbWriter' => 'includes/utils/Cdb.php',
-       'CdbWriterDBA' => 'includes/utils/CdbDBA.php',
-       'CdbWriterPHP' => 'includes/utils/CdbPHP.php',
        'DoubleReplacer' => 'includes/utils/StringUtils.php',
        'ExplodeIterator' => 'includes/utils/StringUtils.php',
        'HashtableReplacer' => 'includes/utils/StringUtils.php',
index a3c2360..87c6ce5 100644 (file)
@@ -34,13 +34,17 @@ class ChangeTags {
        public static function formatSummaryRow( $tags, $page ) {
                global $wgLang;
 
+               $tags = explode( ',', $tags );
+
+               // XXX(Ori Livneh, 2014-11-08): remove once bug 73181 is resolved.
+               $tags = array_diff( $tags, array( 'HHVM', '' ) );
+
                if ( !$tags ) {
                        return array( '', array() );
                }
 
                $classes = array();
 
-               $tags = explode( ',', $tags );
                $displayTags = array();
                foreach ( $tags as $tag ) {
                        $displayTags[] = Xml::tags(
index ab136b8..fbd6119 100644 (file)
@@ -401,7 +401,8 @@ class WatchedItem {
                $newtitle = $nt->getDBkey();
 
                $dbw = wfGetDB( DB_MASTER );
-               $res = $dbw->select( 'watchlist', 'wl_user',
+               $res = $dbw->select( 'watchlist',
+                       array( 'wl_user', 'wl_notificationtimestamp' ),
                        array( 'wl_namespace' => $oldnamespace, 'wl_title' => $oldtitle ),
                        __METHOD__, 'FOR UPDATE'
                );
@@ -411,7 +412,8 @@ class WatchedItem {
                        $values[] = array(
                                'wl_user' => $s->wl_user,
                                'wl_namespace' => $newnamespace,
-                               'wl_title' => $newtitle
+                               'wl_title' => $newtitle,
+                               'wl_notificationtimestamp' => $s->wl_notificationtimestamp,
                        );
                }
 
index 0292e9a..0b1accb 100644 (file)
@@ -109,7 +109,7 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
                        $this->addWhereFld( 'ct_tag', $params['tag'] );
                }
 
-               if ( $this->fld_content || !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) {
+               if ( $this->fetchContent ) {
                        // Modern MediaWiki has the content for deleted revs in the 'text'
                        // table using fields old_text and old_flags. But revisions deleted
                        // pre-1.5 store the content in the 'archive' table directly using
index 5c44173..b7779a7 100644 (file)
  */
 class ApiQueryBlocks extends ApiQueryBase {
 
-       /**
-        * @var array
-        */
-       protected $usernames;
-
        public function __construct( ApiQuery $query, $moduleName ) {
                parent::__construct( $query, $moduleName, 'bk' );
        }
@@ -102,10 +97,11 @@ class ApiQueryBlocks extends ApiQueryBase {
                        $this->addWhereFld( 'ipb_id', $params['ids'] );
                }
                if ( isset( $params['users'] ) ) {
+                       $usernames = array();
                        foreach ( (array)$params['users'] as $u ) {
-                               $this->prepareUsername( $u );
+                               $usernames[] = $this->prepareUsername( $u );
                        }
-                       $this->addWhereFld( 'ipb_address', $this->usernames );
+                       $this->addWhereFld( 'ipb_address', $usernames );
                        $this->addWhereFld( 'ipb_auto', 0 );
                }
                if ( isset( $params['ip'] ) ) {
@@ -264,7 +260,7 @@ class ApiQueryBlocks extends ApiQueryBase {
                if ( $name === false ) {
                        $this->dieUsage( "User name {$user} is not valid", 'param_user' );
                }
-               $this->usernames[] = $name;
+               return $name;
        }
 
        public function getAllowedParams() {
index 0271037..26ae266 100644 (file)
@@ -94,7 +94,7 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
                        $this->addWhereFld( 'ct_tag', $params['tag'] );
                }
 
-               if ( $this->fld_content || !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) {
+               if ( $this->fetchContent ) {
                        // Modern MediaWiki has the content for deleted revs in the 'text'
                        // table using fields old_text and old_flags. But revisions deleted
                        // pre-1.5 store the content in the 'archive' table directly using
index 2e980f3..32355b9 100644 (file)
@@ -167,7 +167,7 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                        $this->addWhereFld( 'ct_tag', $params['tag'] );
                }
 
-               if ( $this->fld_content || !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) {
+               if ( $this->fetchContent ) {
                        // For each page we will request, the user must have read rights for that page
                        $user = $this->getUser();
                        /** @var $title Title */
index 3879d7b..4d75a20 100644 (file)
@@ -32,7 +32,7 @@
 abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
 
        protected $limit, $diffto, $difftotext, $expandTemplates, $generateXML, $section,
-               $parseContent, $contentFormat, $setParsedLimit = true;
+               $parseContent, $fetchContent, $contentFormat, $setParsedLimit = true;
 
        protected $fld_ids = false, $fld_flags = false, $fld_timestamp = false,
                $fld_size = false, $fld_sha1 = false, $fld_comment = false,
@@ -111,8 +111,11 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
 
                $this->limit = $params['limit'];
 
+               $this->fetchContent = $this->fld_content || !is_null( $this->diffto )
+                       || !is_null( $this->difftotext );
+
                $smallLimit = false;
-               if ( $this->fld_content || !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) {
+               if ( $this->fetchContent ) {
                        $smallLimit = true;
                        $this->expandTemplates = $params['expandtemplates'];
                        $this->generateXML = $params['generatexml'];
@@ -249,7 +252,7 @@ abstract class ApiQueryRevisionsBase extends ApiQueryGeneratorBase {
 
                $content = null;
                global $wgParser;
-               if ( $this->fld_content || !is_null( $this->diffto ) || !is_null( $this->difftotext ) ) {
+               if ( $this->fetchContent ) {
                        $content = $revision->getContent( Revision::FOR_THIS_USER, $this->getUser() );
                        // Expand templates after getting section content because
                        // template-added sections don't count and Parser::preprocess()
index d1551ce..acef17d 100644 (file)
        "apihelp-logout-example-logout": "Meldet den aktuellen Benutzer ab",
        "apihelp-move-description": "Eine Seite verschieben.",
        "apihelp-move-param-from": "Titel der Seite, die du verschieben möchtest. Kann nicht zusammen mit $1fromid verwendet werden.",
+       "apihelp-move-param-fromid": "Seitenkennung der Seite, die du verschieben möchtest. Kann nicht zusammen mit $1from verwendet werden.",
        "apihelp-move-param-to": "Titel, zu dem die Seite umbenannt werden soll.",
        "apihelp-move-param-reason": "Grund für die Verschiebung.",
        "apihelp-move-param-movetalk": "Verschiebt die Diskussionsseite, falls vorhanden.",
index 27eaa94..4dc23e5 100644 (file)
@@ -1,9 +1,12 @@
 {
        "@metadata": {
                "authors": [
-                       "Vitorvicentevalente"
+                       "Vitorvicentevalente",
+                       "Fúlvio"
                ]
        },
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page Documentação]\n* [https://www.mediawiki.org/wiki/API:FAQ FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://bugzilla.wikimedia.org/buglist.cgi?component=API&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&order=bugs.delta_ts Erros e solicitações]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página deveriam estar a funcionar, mas a API ainda está em activo desenvolvimento, e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das actualizações.\n\n<strong>Solicitações erradas:</strong> Quando solicitações erradas são enviadas à API, um cabeçalho em HTTP será enviado com a chave \"MediaWiki-API-Error\" e, em seguida, tanto o valor do cabeçalho quanto o código de erro retornado serão definidos com o mesmo valor. Para mais informação, consulte https://www.mediawiki.org/wiki/API:Errors_and_warnings.",
+       "apihelp-main-param-action": "Qual acção a executar.",
        "apihelp-main-param-format": "O formato de saída.",
        "apihelp-block-description": "Bloquear um utilizador.",
        "apihelp-block-param-user": "Nome de utilizador(a), endereço ou gama de IP que pretende bloquear.",
index b894fee..411a1f3 100644 (file)
        "apihelp-query+allcategories-param-to": "要作为枚举终止点的类别。",
        "apihelp-query+allcategories-param-limit": "要返回多少个类别。",
        "apihelp-query+alldeletedrevisions-param-namespace": "只列出此名字空间的页面。",
+       "apihelp-query+alldeletedrevisions-param-miser-user-namespace": "'''注意:'''由于[https://www.mediawiki.org/wiki/Manual:$wgMiserMode miser模式],同时使用$1user和$1namespace将导致继续前返回少于“$1limit”个结果,在极端条件下可能不返回任何结果。",
        "apihelp-query+allfileusages-param-dir": "罗列所采用的方向。",
        "apihelp-query+allfileusages-example-unique": "列出唯一性的文件标题",
        "apihelp-query+allfileusages-example-unique-generator": "获取所有文件标题,并标记出缺失者",
        "apihelp-query+allimages-param-sha1": "图像的 SHA1 哈希。覆盖$1sha1base36。",
        "apihelp-query+allimages-param-limit": "共计要返回多少图像。",
        "apihelp-query+allimages-example-B": "显示以字母“B”开始的文件列表",
+       "apihelp-query+allimages-example-generator": "显示有关4个以“T”开头的文件的信息",
        "apihelp-query+alllinks-example-generator": "获取包含这些链接的页面",
        "apihelp-query+allmessages-description": "返回来自该站点的消息。",
        "apihelp-query+allmessages-param-messages": "要输出的哪些消息。\"*\" (默认值) 表示所有消息。",
        "apihelp-query+extlinks-param-limit": "返回多少链接。",
        "apihelp-query+exturlusage-param-limit": "返回多少页面。",
        "apihelp-query+exturlusage-example-simple": "显示链接至http://www.mediawiki.org的页面",
+       "apihelp-query+filearchive-param-sha1": "图片的SHA1哈希值。覆盖$1sha1base36。",
+       "apihelp-query+filearchive-param-sha1base36": "基于base 36的图片的SHA1哈希值(用于MediaWiki)。",
        "apihelp-query+filearchive-example-simple": "显示已删除文件列表",
        "apihelp-query+fileusage-param-prop": "要获取的属性:\n;pageid:每个页面的页面ID。\n;title:每个页面的标题。\n;redirect:标记作为重定向的页面。",
        "apihelp-query+fileusage-param-namespace": "只包括这些名字空间的页面。",
        "apihelp-query+recentchanges-description": "枚举最近更改。",
        "apihelp-query+recentchanges-param-user": "只列出此用户的更改。",
        "apihelp-query+recentchanges-param-excludeuser": "不要列出此用户的更改。",
+       "apihelp-query+recentchanges-param-tag": "只列出带此标签的更改。",
        "apihelp-query+recentchanges-param-token": "请改用[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]。",
        "apihelp-query+recentchanges-example-simple": "最近更改列表",
        "apihelp-query+redirects-param-namespace": "只包含这些名字空间的页面。",
        "api-help-param-multi-max": "值的最高数字是{{PLURAL:$1|$1}}(对于机器人则是{{PLURAL:$2|$2}})。",
        "api-help-param-default": "默认:$1",
        "api-help-param-default-empty": "默认:<span class=\"apihelp-empty\">(空)</span>",
+       "api-help-param-token": "从[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]取回的“$1”令牌",
        "api-help-param-disabled-in-miser-mode": "由于[https://www.mediawiki.org/wiki/Manual:$wgMiserMode miser模式]而禁用。",
        "api-help-param-limited-in-miser-mode": "'''注意:'''由于[https://www.mediawiki.org/wiki/Manual:$wgMiserMode miser模式],使用这个可能导致继续前返回少于“$1limit”个结果;极端情况下可能不会返回任何结果。",
        "api-help-param-continue": "什么时候更多结果可用什么时候继续使用。",
index 6face4f..43e00cd 100644 (file)
@@ -1059,6 +1059,7 @@ class MessageCache {
                wfProfileIn( __METHOD__ );
                if ( !$title || !$title instanceof Title ) {
                        global $wgTitle;
+                       wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' . wfGetAllCallers() . ' with no title set.' );
                        $title = $wgTitle;
                }
                // Sometimes $wgTitle isn't set either...
index 059f18c..d620be9 100644 (file)
@@ -140,7 +140,7 @@ class RequestContext implements IContextSource {
                if ( $this->title === null ) {
                        global $wgTitle; # fallback to $wg till we can improve this
                        $this->title = $wgTitle;
-                       wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' . wfGetCaller() . ' with no title set.' );
+                       wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' . wfGetAllCallers() . ' with no title set.' );
                }
 
                return $this->title;
diff --git a/includes/libs/cdb/CdbException.php b/includes/libs/cdb/CdbException.php
new file mode 100644 (file)
index 0000000..6cda529
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Exception for Cdb errors.
+ * This explicitly doesn't subclass MWException to encourage reuse.
+ */
+class CdbException extends Exception {
+}
diff --git a/includes/libs/cdb/CdbFunctions.php b/includes/libs/cdb/CdbFunctions.php
new file mode 100644 (file)
index 0000000..e74924c
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/**
+ * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
+ * appears in PHP 5.3. Changes are:
+ *    * Error returns replaced with exceptions
+ *    * Exception thrown if sizes or offsets are between 2GB and 4GB
+ *    * Some variables renamed
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Common functions for readers and writers
+ */
+class CdbFunctions {
+       /**
+        * Take a modulo of a signed integer as if it were an unsigned integer.
+        * $b must be less than 0x40000000 and greater than 0
+        *
+        * @param int $a
+        * @param int $b
+        *
+        * @return int
+        */
+       public static function unsignedMod( $a, $b ) {
+               if ( $a & 0x80000000 ) {
+                       $m = ( $a & 0x7fffffff ) % $b + 2 * ( 0x40000000 % $b );
+
+                       return $m % $b;
+               } else {
+                       return $a % $b;
+               }
+       }
+
+       /**
+        * Shift a signed integer right as if it were unsigned
+        * @param int $a
+        * @param int $b
+        * @return int
+        */
+       public static function unsignedShiftRight( $a, $b ) {
+               if ( $b == 0 ) {
+                       return $a;
+               }
+               if ( $a & 0x80000000 ) {
+                       return ( ( $a & 0x7fffffff ) >> $b ) | ( 0x40000000 >> ( $b - 1 ) );
+               } else {
+                       return $a >> $b;
+               }
+       }
+
+       /**
+        * The CDB hash function.
+        *
+        * @param string $s
+        *
+        * @return int
+        */
+       public static function hash( $s ) {
+               $h = 5381;
+               $len = strlen( $s );
+               for ( $i = 0; $i < $len; $i++ ) {
+                       $h5 = ( $h << 5 ) & 0xffffffff;
+                       // Do a 32-bit sum
+                       // Inlined here for speed
+                       $sum = ( $h & 0x3fffffff ) + ( $h5 & 0x3fffffff );
+                       $h =
+                               (
+                                       ( $sum & 0x40000000 ? 1 : 0 )
+                                       + ( $h & 0x80000000 ? 2 : 0 )
+                                       + ( $h & 0x40000000 ? 1 : 0 )
+                                       + ( $h5 & 0x80000000 ? 2 : 0 )
+                                       + ( $h5 & 0x40000000 ? 1 : 0 )
+                               ) << 30
+                               | ( $sum & 0x3fffffff );
+                       $h ^= ord( $s[$i] );
+                       $h &= 0xffffffff;
+               }
+
+               return $h;
+       }
+}
diff --git a/includes/libs/cdb/CdbReader.php b/includes/libs/cdb/CdbReader.php
new file mode 100644 (file)
index 0000000..0ca9b9d
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Native CDB file reader and writer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Read from a CDB file.
+ * Native and pure PHP implementations are provided.
+ * http://cr.yp.to/cdb.html
+ */
+abstract class CdbReader {
+       /**
+        * The file handle
+        */
+       protected $handle;
+
+       /**
+        * Open a file and return a subclass instance
+        *
+        * @param string $fileName
+        *
+        * @return CdbReader
+        */
+       public static function open( $fileName ) {
+               return self::haveExtension() ?
+                       new CdbReaderDBA( $fileName ) :
+                       new CdbReaderPHP( $fileName );
+       }
+
+       /**
+        * Returns true if the native extension is available
+        *
+        * @return bool
+        */
+       public static function haveExtension() {
+               if ( !function_exists( 'dba_handlers' ) ) {
+                       return false;
+               }
+               $handlers = dba_handlers();
+               if ( !in_array( 'cdb', $handlers ) || !in_array( 'cdb_make', $handlers ) ) {
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * Create the object and open the file
+        *
+        * @param string $fileName
+        */
+       abstract public function __construct( $fileName );
+
+       /**
+        * Close the file. Optional, you can just let the variable go out of scope.
+        */
+       abstract public function close();
+
+       /**
+        * Get a value with a given key. Only string values are supported.
+        *
+        * @param string $key
+        */
+       abstract public function get( $key );
+}
diff --git a/includes/libs/cdb/CdbReaderDBA.php b/includes/libs/cdb/CdbReaderDBA.php
new file mode 100644 (file)
index 0000000..e0cab73
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * DBA-based CDB reader/writer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Reader class which uses the DBA extension
+ */
+class CdbReaderDBA extends CdbReader {
+       public function __construct( $fileName ) {
+               $this->handle = dba_open( $fileName, 'r-', 'cdb' );
+               if ( !$this->handle ) {
+                       throw new CdbException( 'Unable to open CDB file "' . $fileName . '"' );
+               }
+       }
+
+       public function close() {
+               if ( isset( $this->handle ) ) {
+                       dba_close( $this->handle );
+               }
+               unset( $this->handle );
+       }
+
+       public function get( $key ) {
+               return dba_fetch( $key, $this->handle );
+       }
+}
diff --git a/includes/libs/cdb/CdbReaderPHP.php b/includes/libs/cdb/CdbReaderPHP.php
new file mode 100644 (file)
index 0000000..e448414
--- /dev/null
@@ -0,0 +1,214 @@
+<?php
+/**
+ * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
+ * appears in PHP 5.3. Changes are:
+ *    * Error returns replaced with exceptions
+ *    * Exception thrown if sizes or offsets are between 2GB and 4GB
+ *    * Some variables renamed
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * CDB reader class
+ */
+class CdbReaderPHP extends CdbReader {
+       /** The filename */
+       protected $fileName;
+
+       /* number of hash slots searched under this key */
+       protected $loop;
+
+       /* initialized if loop is nonzero */
+       protected $khash;
+
+       /* initialized if loop is nonzero */
+       protected $kpos;
+
+       /* initialized if loop is nonzero */
+       protected $hpos;
+
+       /* initialized if loop is nonzero */
+       protected $hslots;
+
+       /* initialized if findNext() returns true */
+       protected $dpos;
+
+       /* initialized if cdb_findnext() returns 1 */
+       protected $dlen;
+
+       /**
+        * @param string $fileName
+        * @throws CdbException
+        */
+       public function __construct( $fileName ) {
+               $this->fileName = $fileName;
+               $this->handle = fopen( $fileName, 'rb' );
+               if ( !$this->handle ) {
+                       throw new CdbException( 'Unable to open CDB file "' . $this->fileName . '".' );
+               }
+               $this->findStart();
+       }
+
+       public function close() {
+               if ( isset( $this->handle ) ) {
+                       fclose( $this->handle );
+               }
+               unset( $this->handle );
+       }
+
+       /**
+        * @param mixed $key
+        * @return bool|string
+        */
+       public function get( $key ) {
+               // strval is required
+               if ( $this->find( strval( $key ) ) ) {
+                       return $this->read( $this->dlen, $this->dpos );
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * @param string $key
+        * @param int $pos
+        * @return bool
+        */
+       protected function match( $key, $pos ) {
+               $buf = $this->read( strlen( $key ), $pos );
+
+               return $buf === $key;
+       }
+
+       protected function findStart() {
+               $this->loop = 0;
+       }
+
+       /**
+        * @throws CdbException
+        * @param int $length
+        * @param int $pos
+        * @return string
+        */
+       protected function read( $length, $pos ) {
+               if ( fseek( $this->handle, $pos ) == -1 ) {
+                       // This can easily happen if the internal pointers are incorrect
+                       throw new CdbException(
+                               'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
+               }
+
+               if ( $length == 0 ) {
+                       return '';
+               }
+
+               $buf = fread( $this->handle, $length );
+               if ( $buf === false || strlen( $buf ) !== $length ) {
+                       throw new CdbException(
+                               'Read from CDB file failed, file "' . $this->fileName . '" may be corrupted.' );
+               }
+
+               return $buf;
+       }
+
+       /**
+        * Unpack an unsigned integer and throw an exception if it needs more than 31 bits
+        * @param string $s
+        * @throws CdbException
+        * @return mixed
+        */
+       protected function unpack31( $s ) {
+               $data = unpack( 'V', $s );
+               if ( $data[1] > 0x7fffffff ) {
+                       throw new CdbException(
+                               'Error in CDB file "' . $this->fileName . '", integer too big.' );
+               }
+
+               return $data[1];
+       }
+
+       /**
+        * Unpack a 32-bit signed integer
+        * @param string $s
+        * @return int
+        */
+       protected function unpackSigned( $s ) {
+               $data = unpack( 'va/vb', $s );
+
+               return $data['a'] | ( $data['b'] << 16 );
+       }
+
+       /**
+        * @param string $key
+        * @return bool
+        */
+       protected function findNext( $key ) {
+               if ( !$this->loop ) {
+                       $u = CdbFunctions::hash( $key );
+                       $buf = $this->read( 8, ( $u << 3 ) & 2047 );
+                       $this->hslots = $this->unpack31( substr( $buf, 4 ) );
+                       if ( !$this->hslots ) {
+                               return false;
+                       }
+                       $this->hpos = $this->unpack31( substr( $buf, 0, 4 ) );
+                       $this->khash = $u;
+                       $u = CdbFunctions::unsignedShiftRight( $u, 8 );
+                       $u = CdbFunctions::unsignedMod( $u, $this->hslots );
+                       $u <<= 3;
+                       $this->kpos = $this->hpos + $u;
+               }
+
+               while ( $this->loop < $this->hslots ) {
+                       $buf = $this->read( 8, $this->kpos );
+                       $pos = $this->unpack31( substr( $buf, 4 ) );
+                       if ( !$pos ) {
+                               return false;
+                       }
+                       $this->loop += 1;
+                       $this->kpos += 8;
+                       if ( $this->kpos == $this->hpos + ( $this->hslots << 3 ) ) {
+                               $this->kpos = $this->hpos;
+                       }
+                       $u = $this->unpackSigned( substr( $buf, 0, 4 ) );
+                       if ( $u === $this->khash ) {
+                               $buf = $this->read( 8, $pos );
+                               $keyLen = $this->unpack31( substr( $buf, 0, 4 ) );
+                               if ( $keyLen == strlen( $key ) && $this->match( $key, $pos + 8 ) ) {
+                                       // Found
+                                       $this->dlen = $this->unpack31( substr( $buf, 4 ) );
+                                       $this->dpos = $pos + 8 + $keyLen;
+
+                                       return true;
+                               }
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * @param mixed $key
+        * @return bool
+        */
+       protected function find( $key ) {
+               $this->findStart();
+
+               return $this->findNext( $key );
+       }
+}
+
diff --git a/includes/libs/cdb/CdbWriter.php b/includes/libs/cdb/CdbWriter.php
new file mode 100644 (file)
index 0000000..b0a90c3
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Native CDB file reader and writer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Write to a CDB file.
+ * Native and pure PHP implementations are provided.
+ * http://cr.yp.to/cdb.html
+ */
+abstract class CdbWriter {
+       /**
+        * The file handle
+        */
+       protected $handle;
+
+       /**
+        * File we'll be writing to when we're done
+        * @var string
+        */
+       protected $realFileName;
+
+       /**
+        * File we write to temporarily until we're done
+        * @var string
+        */
+       protected $tmpFileName;
+
+       /**
+        * Open a writer and return a subclass instance.
+        * The user must have write access to the directory, for temporary file creation.
+        *
+        * @param string $fileName
+        *
+        * @return CdbWriterDBA|CdbWriterPHP
+        */
+       public static function open( $fileName ) {
+               return CdbReader::haveExtension() ?
+                       new CdbWriterDBA( $fileName ) :
+                       new CdbWriterPHP( $fileName );
+       }
+
+       /**
+        * Create the object and open the file
+        *
+        * @param string $fileName
+        */
+       abstract public function __construct( $fileName );
+
+       /**
+        * Set a key to a given value. The value will be converted to string.
+        * @param string $key
+        * @param string $value
+        */
+       abstract public function set( $key, $value );
+
+       /**
+        * Close the writer object. You should call this function before the object
+        * goes out of scope, to write out the final hashtables.
+        */
+       abstract public function close();
+
+       /**
+        * If the object goes out of scope, close it for sanity
+        */
+       public function __destruct() {
+               if ( isset( $this->handle ) ) {
+                       $this->close();
+               }
+       }
+
+       /**
+        * Are we running on Windows?
+        * @return bool
+        */
+       protected function isWindows() {
+               return substr( php_uname(), 0, 7 ) == 'Windows';
+       }
+}
diff --git a/includes/libs/cdb/CdbWriterDBA.php b/includes/libs/cdb/CdbWriterDBA.php
new file mode 100644 (file)
index 0000000..1de371d
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/**
+ * DBA-based CDB reader/writer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Writer class which uses the DBA extension
+ */
+class CdbWriterDBA extends CdbWriter {
+       public function __construct( $fileName ) {
+               $this->realFileName = $fileName;
+               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
+               $this->handle = dba_open( $this->tmpFileName, 'n', 'cdb_make' );
+               if ( !$this->handle ) {
+                       throw new CdbException( 'Unable to open CDB file for write "' . $fileName . '"' );
+               }
+       }
+
+       public function set( $key, $value ) {
+               return dba_insert( $key, $value, $this->handle );
+       }
+
+       public function close() {
+               if ( isset( $this->handle ) ) {
+                       dba_close( $this->handle );
+               }
+               if ( $this->isWindows() ) {
+                       unlink( $this->realFileName );
+               }
+               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
+                       throw new CdbException( 'Unable to move the new CDB file into place.' );
+               }
+               unset( $this->handle );
+       }
+}
diff --git a/includes/libs/cdb/CdbWriterPHP.php b/includes/libs/cdb/CdbWriterPHP.php
new file mode 100644 (file)
index 0000000..bfc0d87
--- /dev/null
@@ -0,0 +1,234 @@
+<?php
+/**
+ * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
+ * appears in PHP 5.3. Changes are:
+ *    * Error returns replaced with exceptions
+ *    * Exception thrown if sizes or offsets are between 2GB and 4GB
+ *    * Some variables renamed
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * CDB writer class
+ */
+class CdbWriterPHP extends CdbWriter {
+       protected $hplist;
+
+       protected $numentries;
+
+       protected $pos;
+
+       /**
+        * @param string $fileName
+        */
+       public function __construct( $fileName ) {
+               $this->realFileName = $fileName;
+               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
+               $this->handle = fopen( $this->tmpFileName, 'wb' );
+               if ( !$this->handle ) {
+                       $this->throwException(
+                               'Unable to open CDB file "' . $this->tmpFileName . '" for write.' );
+               }
+               $this->hplist = array();
+               $this->numentries = 0;
+               $this->pos = 2048; // leaving space for the pointer array, 256 * 8
+               if ( fseek( $this->handle, $this->pos ) == -1 ) {
+                       $this->throwException( 'fseek failed in file "' . $this->tmpFileName . '".' );
+               }
+       }
+
+       /**
+        * @param string $key
+        * @param string $value
+        */
+       public function set( $key, $value ) {
+               if ( strval( $key ) === '' ) {
+                       // DBA cross-check hack
+                       return;
+               }
+               $this->addbegin( strlen( $key ), strlen( $value ) );
+               $this->write( $key );
+               $this->write( $value );
+               $this->addend( strlen( $key ), strlen( $value ), CdbFunctions::hash( $key ) );
+       }
+
+       /**
+        * @throws CdbException
+        */
+       public function close() {
+               $this->finish();
+               if ( isset( $this->handle ) ) {
+                       fclose( $this->handle );
+               }
+               if ( $this->isWindows() && file_exists( $this->realFileName ) ) {
+                       unlink( $this->realFileName );
+               }
+               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
+                       $this->throwException( 'Unable to move the new CDB file into place.' );
+               }
+               unset( $this->handle );
+       }
+
+       /**
+        * @throws CdbException
+        * @param string $buf
+        */
+       protected function write( $buf ) {
+               $len = fwrite( $this->handle, $buf );
+               if ( $len !== strlen( $buf ) ) {
+                       $this->throwException( 'Error writing to CDB file "' . $this->tmpFileName . '".' );
+               }
+       }
+
+       /**
+        * @throws CdbException
+        * @param int $len
+        */
+       protected function posplus( $len ) {
+               $newpos = $this->pos + $len;
+               if ( $newpos > 0x7fffffff ) {
+                       $this->throwException(
+                               'A value in the CDB file "' . $this->tmpFileName . '" is too large.' );
+               }
+               $this->pos = $newpos;
+       }
+
+       /**
+        * @param int $keylen
+        * @param int $datalen
+        * @param int $h
+        */
+       protected function addend( $keylen, $datalen, $h ) {
+               $this->hplist[] = array(
+                       'h' => $h,
+                       'p' => $this->pos
+               );
+
+               $this->numentries++;
+               $this->posplus( 8 );
+               $this->posplus( $keylen );
+               $this->posplus( $datalen );
+       }
+
+       /**
+        * @throws CdbException
+        * @param int $keylen
+        * @param int $datalen
+        */
+       protected function addbegin( $keylen, $datalen ) {
+               if ( $keylen > 0x7fffffff ) {
+                       $this->throwException( 'Key length too long in file "' . $this->tmpFileName . '".' );
+               }
+               if ( $datalen > 0x7fffffff ) {
+                       $this->throwException( 'Data length too long in file "' . $this->tmpFileName . '".' );
+               }
+               $buf = pack( 'VV', $keylen, $datalen );
+               $this->write( $buf );
+       }
+
+       /**
+        * @throws CdbException
+        */
+       protected function finish() {
+               // Hack for DBA cross-check
+               $this->hplist = array_reverse( $this->hplist );
+
+               // Calculate the number of items that will be in each hashtable
+               $counts = array_fill( 0, 256, 0 );
+               foreach ( $this->hplist as $item ) {
+                       ++$counts[255 & $item['h']];
+               }
+
+               // Fill in $starts with the *end* indexes
+               $starts = array();
+               $pos = 0;
+               for ( $i = 0; $i < 256; ++$i ) {
+                       $pos += $counts[$i];
+                       $starts[$i] = $pos;
+               }
+
+               // Excessively clever and indulgent code to simultaneously fill $packedTables
+               // with the packed hashtables, and adjust the elements of $starts
+               // to actually point to the starts instead of the ends.
+               $packedTables = array_fill( 0, $this->numentries, false );
+               foreach ( $this->hplist as $item ) {
+                       $packedTables[--$starts[255 & $item['h']]] = $item;
+               }
+
+               $final = '';
+               for ( $i = 0; $i < 256; ++$i ) {
+                       $count = $counts[$i];
+
+                       // The size of the hashtable will be double the item count.
+                       // The rest of the slots will be empty.
+                       $len = $count + $count;
+                       $final .= pack( 'VV', $this->pos, $len );
+
+                       $hashtable = array();
+                       for ( $u = 0; $u < $len; ++$u ) {
+                               $hashtable[$u] = array( 'h' => 0, 'p' => 0 );
+                       }
+
+                       // Fill the hashtable, using the next empty slot if the hashed slot
+                       // is taken.
+                       for ( $u = 0; $u < $count; ++$u ) {
+                               $hp = $packedTables[$starts[$i] + $u];
+                               $where = CdbFunctions::unsignedMod(
+                                       CdbFunctions::unsignedShiftRight( $hp['h'], 8 ), $len );
+                               while ( $hashtable[$where]['p'] ) {
+                                       if ( ++$where == $len ) {
+                                               $where = 0;
+                                       }
+                               }
+                               $hashtable[$where] = $hp;
+                       }
+
+                       // Write the hashtable
+                       for ( $u = 0; $u < $len; ++$u ) {
+                               $buf = pack( 'vvV',
+                                       $hashtable[$u]['h'] & 0xffff,
+                                       CdbFunctions::unsignedShiftRight( $hashtable[$u]['h'], 16 ),
+                                       $hashtable[$u]['p'] );
+                               $this->write( $buf );
+                               $this->posplus( 8 );
+                       }
+               }
+
+               // Write the pointer array at the start of the file
+               rewind( $this->handle );
+               if ( ftell( $this->handle ) != 0 ) {
+                       $this->throwException( 'Error rewinding to start of file "' . $this->tmpFileName . '".' );
+               }
+               $this->write( $final );
+       }
+
+       /**
+        * Clean up the temp file and throw an exception
+        *
+        * @param string $msg
+        * @throws CdbException
+        */
+       protected function throwException( $msg ) {
+               if ( $this->handle ) {
+                       fclose( $this->handle );
+                       unlink( $this->tmpFileName );
+               }
+               throw new CdbException( $msg );
+       }
+}
index 7794fae..6c15993 100644 (file)
@@ -267,17 +267,15 @@ class LinkHolderArray {
         * Replace <!--LINK--> link placeholders with actual links, in the buffer
         *
         * @param string $text
-        * @return array Array of link CSS classes, indexed by PDBK.
         */
        public function replace( &$text ) {
                wfProfileIn( __METHOD__ );
 
-               /** @todo FIXME: replaceInternal doesn't return a value */
-               $colours = $this->replaceInternal( $text );
+               $this->replaceInternal( $text );
                $this->replaceInterwiki( $text );
 
                wfProfileOut( __METHOD__ );
-               return $colours;
+
        }
 
        /**
index 07a104b..cd804b5 100644 (file)
@@ -5317,11 +5317,9 @@ class Parser {
         *
         * @param string $text
         * @param int $options
-        *
-        * @return array Array of link CSS classes, indexed by PDBK.
         */
        public function replaceLinkHolders( &$text, $options = 0 ) {
-               return $this->mLinkHolders->replace( $text );
+               $this->mLinkHolders->replace( $text );
        }
 
        /**
diff --git a/includes/utils/Cdb.php b/includes/utils/Cdb.php
deleted file mode 100644 (file)
index 3ceb620..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-<?php
-/**
- * Native CDB file reader and writer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Read from a CDB file.
- * Native and pure PHP implementations are provided.
- * http://cr.yp.to/cdb.html
- */
-abstract class CdbReader {
-       /**
-        * The file handle
-        */
-       protected $handle;
-
-       /**
-        * Open a file and return a subclass instance
-        *
-        * @param string $fileName
-        *
-        * @return CdbReader
-        */
-       public static function open( $fileName ) {
-               return self::haveExtension() ?
-                       new CdbReaderDBA( $fileName ) :
-                       new CdbReaderPHP( $fileName );
-       }
-
-       /**
-        * Returns true if the native extension is available
-        *
-        * @return bool
-        */
-       public static function haveExtension() {
-               if ( !function_exists( 'dba_handlers' ) ) {
-                       return false;
-               }
-               $handlers = dba_handlers();
-               if ( !in_array( 'cdb', $handlers ) || !in_array( 'cdb_make', $handlers ) ) {
-                       return false;
-               }
-
-               return true;
-       }
-
-       /**
-        * Create the object and open the file
-        *
-        * @param string $fileName
-        */
-       abstract public function __construct( $fileName );
-
-       /**
-        * Close the file. Optional, you can just let the variable go out of scope.
-        */
-       abstract public function close();
-
-       /**
-        * Get a value with a given key. Only string values are supported.
-        *
-        * @param string $key
-        */
-       abstract public function get( $key );
-}
-
-/**
- * Write to a CDB file.
- * Native and pure PHP implementations are provided.
- */
-abstract class CdbWriter {
-       /**
-        * The file handle
-        */
-       protected $handle;
-
-       /**
-        * File we'll be writing to when we're done
-        * @var string
-        */
-       protected $realFileName;
-
-       /**
-        * File we write to temporarily until we're done
-        * @var string
-        */
-       protected $tmpFileName;
-
-       /**
-        * Open a writer and return a subclass instance.
-        * The user must have write access to the directory, for temporary file creation.
-        *
-        * @param string $fileName
-        *
-        * @return CdbWriterDBA|CdbWriterPHP
-        */
-       public static function open( $fileName ) {
-               return CdbReader::haveExtension() ?
-                       new CdbWriterDBA( $fileName ) :
-                       new CdbWriterPHP( $fileName );
-       }
-
-       /**
-        * Create the object and open the file
-        *
-        * @param string $fileName
-        */
-       abstract public function __construct( $fileName );
-
-       /**
-        * Set a key to a given value. The value will be converted to string.
-        * @param string $key
-        * @param string $value
-        */
-       abstract public function set( $key, $value );
-
-       /**
-        * Close the writer object. You should call this function before the object
-        * goes out of scope, to write out the final hashtables.
-        */
-       abstract public function close();
-
-       /**
-        * If the object goes out of scope, close it for sanity
-        */
-       public function __destruct() {
-               if ( isset( $this->handle ) ) {
-                       $this->close();
-               }
-       }
-
-       /**
-        * Are we running on Windows?
-        * @return bool
-        */
-       protected function isWindows() {
-               return substr( php_uname(), 0, 7 ) == 'Windows';
-       }
-}
-
-/**
- * Exception for Cdb errors.
- * This explicitly doesn't subclass MWException to encourage reuse.
- */
-class CdbException extends Exception {
-}
diff --git a/includes/utils/CdbDBA.php b/includes/utils/CdbDBA.php
deleted file mode 100644 (file)
index efcaf21..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-/**
- * DBA-based CDB reader/writer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Reader class which uses the DBA extension
- */
-class CdbReaderDBA extends CdbReader {
-       public function __construct( $fileName ) {
-               $this->handle = dba_open( $fileName, 'r-', 'cdb' );
-               if ( !$this->handle ) {
-                       throw new CdbException( 'Unable to open CDB file "' . $fileName . '"' );
-               }
-       }
-
-       public function close() {
-               if ( isset( $this->handle ) ) {
-                       dba_close( $this->handle );
-               }
-               unset( $this->handle );
-       }
-
-       public function get( $key ) {
-               return dba_fetch( $key, $this->handle );
-       }
-}
-
-/**
- * Writer class which uses the DBA extension
- */
-class CdbWriterDBA extends CdbWriter {
-       public function __construct( $fileName ) {
-               $this->realFileName = $fileName;
-               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
-               $this->handle = dba_open( $this->tmpFileName, 'n', 'cdb_make' );
-               if ( !$this->handle ) {
-                       throw new CdbException( 'Unable to open CDB file for write "' . $fileName . '"' );
-               }
-       }
-
-       public function set( $key, $value ) {
-               return dba_insert( $key, $value, $this->handle );
-       }
-
-       public function close() {
-               if ( isset( $this->handle ) ) {
-                       dba_close( $this->handle );
-               }
-               if ( $this->isWindows() ) {
-                       unlink( $this->realFileName );
-               }
-               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
-                       throw new CdbException( 'Unable to move the new CDB file into place.' );
-               }
-               unset( $this->handle );
-       }
-}
diff --git a/includes/utils/CdbPHP.php b/includes/utils/CdbPHP.php
deleted file mode 100644 (file)
index 19d747a..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-<?php
-/**
- * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
- * appears in PHP 5.3. Changes are:
- *    * Error returns replaced with exceptions
- *    * Exception thrown if sizes or offsets are between 2GB and 4GB
- *    * Some variables renamed
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
-
-/**
- * Common functions for readers and writers
- */
-class CdbFunctions {
-       /**
-        * Take a modulo of a signed integer as if it were an unsigned integer.
-        * $b must be less than 0x40000000 and greater than 0
-        *
-        * @param int $a
-        * @param int $b
-        *
-        * @return int
-        */
-       public static function unsignedMod( $a, $b ) {
-               if ( $a & 0x80000000 ) {
-                       $m = ( $a & 0x7fffffff ) % $b + 2 * ( 0x40000000 % $b );
-
-                       return $m % $b;
-               } else {
-                       return $a % $b;
-               }
-       }
-
-       /**
-        * Shift a signed integer right as if it were unsigned
-        * @param int $a
-        * @param int $b
-        * @return int
-        */
-       public static function unsignedShiftRight( $a, $b ) {
-               if ( $b == 0 ) {
-                       return $a;
-               }
-               if ( $a & 0x80000000 ) {
-                       return ( ( $a & 0x7fffffff ) >> $b ) | ( 0x40000000 >> ( $b - 1 ) );
-               } else {
-                       return $a >> $b;
-               }
-       }
-
-       /**
-        * The CDB hash function.
-        *
-        * @param string $s
-        *
-        * @return int
-        */
-       public static function hash( $s ) {
-               $h = 5381;
-               $len = strlen( $s );
-               for ( $i = 0; $i < $len; $i++ ) {
-                       $h5 = ( $h << 5 ) & 0xffffffff;
-                       // Do a 32-bit sum
-                       // Inlined here for speed
-                       $sum = ( $h & 0x3fffffff ) + ( $h5 & 0x3fffffff );
-                       $h =
-                               (
-                                       ( $sum & 0x40000000 ? 1 : 0 )
-                                       + ( $h & 0x80000000 ? 2 : 0 )
-                                       + ( $h & 0x40000000 ? 1 : 0 )
-                                       + ( $h5 & 0x80000000 ? 2 : 0 )
-                                       + ( $h5 & 0x40000000 ? 1 : 0 )
-                               ) << 30
-                               | ( $sum & 0x3fffffff );
-                       $h ^= ord( $s[$i] );
-                       $h &= 0xffffffff;
-               }
-
-               return $h;
-       }
-}
-
-/**
- * CDB reader class
- */
-class CdbReaderPHP extends CdbReader {
-       /** The filename */
-       protected $fileName;
-
-       /* number of hash slots searched under this key */
-       protected $loop;
-
-       /* initialized if loop is nonzero */
-       protected $khash;
-
-       /* initialized if loop is nonzero */
-       protected $kpos;
-
-       /* initialized if loop is nonzero */
-       protected $hpos;
-
-       /* initialized if loop is nonzero */
-       protected $hslots;
-
-       /* initialized if findNext() returns true */
-       protected $dpos;
-
-       /* initialized if cdb_findnext() returns 1 */
-       protected $dlen;
-
-       /**
-        * @param string $fileName
-        * @throws CdbException
-        */
-       public function __construct( $fileName ) {
-               $this->fileName = $fileName;
-               $this->handle = fopen( $fileName, 'rb' );
-               if ( !$this->handle ) {
-                       throw new CdbException( 'Unable to open CDB file "' . $this->fileName . '".' );
-               }
-               $this->findStart();
-       }
-
-       public function close() {
-               if ( isset( $this->handle ) ) {
-                       fclose( $this->handle );
-               }
-               unset( $this->handle );
-       }
-
-       /**
-        * @param mixed $key
-        * @return bool|string
-        */
-       public function get( $key ) {
-               // strval is required
-               if ( $this->find( strval( $key ) ) ) {
-                       return $this->read( $this->dlen, $this->dpos );
-               } else {
-                       return false;
-               }
-       }
-
-       /**
-        * @param string $key
-        * @param int $pos
-        * @return bool
-        */
-       protected function match( $key, $pos ) {
-               $buf = $this->read( strlen( $key ), $pos );
-
-               return $buf === $key;
-       }
-
-       protected function findStart() {
-               $this->loop = 0;
-       }
-
-       /**
-        * @throws CdbException
-        * @param int $length
-        * @param int $pos
-        * @return string
-        */
-       protected function read( $length, $pos ) {
-               if ( fseek( $this->handle, $pos ) == -1 ) {
-                       // This can easily happen if the internal pointers are incorrect
-                       throw new CdbException(
-                               'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
-               }
-
-               if ( $length == 0 ) {
-                       return '';
-               }
-
-               $buf = fread( $this->handle, $length );
-               if ( $buf === false || strlen( $buf ) !== $length ) {
-                       throw new CdbException(
-                               'Read from CDB file failed, file "' . $this->fileName . '" may be corrupted.' );
-               }
-
-               return $buf;
-       }
-
-       /**
-        * Unpack an unsigned integer and throw an exception if it needs more than 31 bits
-        * @param string $s
-        * @throws CdbException
-        * @return mixed
-        */
-       protected function unpack31( $s ) {
-               $data = unpack( 'V', $s );
-               if ( $data[1] > 0x7fffffff ) {
-                       throw new CdbException(
-                               'Error in CDB file "' . $this->fileName . '", integer too big.' );
-               }
-
-               return $data[1];
-       }
-
-       /**
-        * Unpack a 32-bit signed integer
-        * @param string $s
-        * @return int
-        */
-       protected function unpackSigned( $s ) {
-               $data = unpack( 'va/vb', $s );
-
-               return $data['a'] | ( $data['b'] << 16 );
-       }
-
-       /**
-        * @param string $key
-        * @return bool
-        */
-       protected function findNext( $key ) {
-               if ( !$this->loop ) {
-                       $u = CdbFunctions::hash( $key );
-                       $buf = $this->read( 8, ( $u << 3 ) & 2047 );
-                       $this->hslots = $this->unpack31( substr( $buf, 4 ) );
-                       if ( !$this->hslots ) {
-                               return false;
-                       }
-                       $this->hpos = $this->unpack31( substr( $buf, 0, 4 ) );
-                       $this->khash = $u;
-                       $u = CdbFunctions::unsignedShiftRight( $u, 8 );
-                       $u = CdbFunctions::unsignedMod( $u, $this->hslots );
-                       $u <<= 3;
-                       $this->kpos = $this->hpos + $u;
-               }
-
-               while ( $this->loop < $this->hslots ) {
-                       $buf = $this->read( 8, $this->kpos );
-                       $pos = $this->unpack31( substr( $buf, 4 ) );
-                       if ( !$pos ) {
-                               return false;
-                       }
-                       $this->loop += 1;
-                       $this->kpos += 8;
-                       if ( $this->kpos == $this->hpos + ( $this->hslots << 3 ) ) {
-                               $this->kpos = $this->hpos;
-                       }
-                       $u = $this->unpackSigned( substr( $buf, 0, 4 ) );
-                       if ( $u === $this->khash ) {
-                               $buf = $this->read( 8, $pos );
-                               $keyLen = $this->unpack31( substr( $buf, 0, 4 ) );
-                               if ( $keyLen == strlen( $key ) && $this->match( $key, $pos + 8 ) ) {
-                                       // Found
-                                       $this->dlen = $this->unpack31( substr( $buf, 4 ) );
-                                       $this->dpos = $pos + 8 + $keyLen;
-
-                                       return true;
-                               }
-                       }
-               }
-
-               return false;
-       }
-
-       /**
-        * @param mixed $key
-        * @return bool
-        */
-       protected function find( $key ) {
-               $this->findStart();
-
-               return $this->findNext( $key );
-       }
-}
-
-/**
- * CDB writer class
- */
-class CdbWriterPHP extends CdbWriter {
-       protected $hplist;
-
-       protected $numentries;
-
-       protected $pos;
-
-       /**
-        * @param string $fileName
-        */
-       public function __construct( $fileName ) {
-               $this->realFileName = $fileName;
-               $this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
-               $this->handle = fopen( $this->tmpFileName, 'wb' );
-               if ( !$this->handle ) {
-                       $this->throwException(
-                               'Unable to open CDB file "' . $this->tmpFileName . '" for write.' );
-               }
-               $this->hplist = array();
-               $this->numentries = 0;
-               $this->pos = 2048; // leaving space for the pointer array, 256 * 8
-               if ( fseek( $this->handle, $this->pos ) == -1 ) {
-                       $this->throwException( 'fseek failed in file "' . $this->tmpFileName . '".' );
-               }
-       }
-
-       /**
-        * @param string $key
-        * @param string $value
-        */
-       public function set( $key, $value ) {
-               if ( strval( $key ) === '' ) {
-                       // DBA cross-check hack
-                       return;
-               }
-               $this->addbegin( strlen( $key ), strlen( $value ) );
-               $this->write( $key );
-               $this->write( $value );
-               $this->addend( strlen( $key ), strlen( $value ), CdbFunctions::hash( $key ) );
-       }
-
-       /**
-        * @throws CdbException
-        */
-       public function close() {
-               $this->finish();
-               if ( isset( $this->handle ) ) {
-                       fclose( $this->handle );
-               }
-               if ( $this->isWindows() && file_exists( $this->realFileName ) ) {
-                       unlink( $this->realFileName );
-               }
-               if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
-                       $this->throwException( 'Unable to move the new CDB file into place.' );
-               }
-               unset( $this->handle );
-       }
-
-       /**
-        * @throws CdbException
-        * @param string $buf
-        */
-       protected function write( $buf ) {
-               $len = fwrite( $this->handle, $buf );
-               if ( $len !== strlen( $buf ) ) {
-                       $this->throwException( 'Error writing to CDB file "' . $this->tmpFileName . '".' );
-               }
-       }
-
-       /**
-        * @throws CdbException
-        * @param int $len
-        */
-       protected function posplus( $len ) {
-               $newpos = $this->pos + $len;
-               if ( $newpos > 0x7fffffff ) {
-                       $this->throwException(
-                               'A value in the CDB file "' . $this->tmpFileName . '" is too large.' );
-               }
-               $this->pos = $newpos;
-       }
-
-       /**
-        * @param int $keylen
-        * @param int $datalen
-        * @param int $h
-        */
-       protected function addend( $keylen, $datalen, $h ) {
-               $this->hplist[] = array(
-                       'h' => $h,
-                       'p' => $this->pos
-               );
-
-               $this->numentries++;
-               $this->posplus( 8 );
-               $this->posplus( $keylen );
-               $this->posplus( $datalen );
-       }
-
-       /**
-        * @throws CdbException
-        * @param int $keylen
-        * @param int $datalen
-        */
-       protected function addbegin( $keylen, $datalen ) {
-               if ( $keylen > 0x7fffffff ) {
-                       $this->throwException( 'Key length too long in file "' . $this->tmpFileName . '".' );
-               }
-               if ( $datalen > 0x7fffffff ) {
-                       $this->throwException( 'Data length too long in file "' . $this->tmpFileName . '".' );
-               }
-               $buf = pack( 'VV', $keylen, $datalen );
-               $this->write( $buf );
-       }
-
-       /**
-        * @throws CdbException
-        */
-       protected function finish() {
-               // Hack for DBA cross-check
-               $this->hplist = array_reverse( $this->hplist );
-
-               // Calculate the number of items that will be in each hashtable
-               $counts = array_fill( 0, 256, 0 );
-               foreach ( $this->hplist as $item ) {
-                       ++$counts[255 & $item['h']];
-               }
-
-               // Fill in $starts with the *end* indexes
-               $starts = array();
-               $pos = 0;
-               for ( $i = 0; $i < 256; ++$i ) {
-                       $pos += $counts[$i];
-                       $starts[$i] = $pos;
-               }
-
-               // Excessively clever and indulgent code to simultaneously fill $packedTables
-               // with the packed hashtables, and adjust the elements of $starts
-               // to actually point to the starts instead of the ends.
-               $packedTables = array_fill( 0, $this->numentries, false );
-               foreach ( $this->hplist as $item ) {
-                       $packedTables[--$starts[255 & $item['h']]] = $item;
-               }
-
-               $final = '';
-               for ( $i = 0; $i < 256; ++$i ) {
-                       $count = $counts[$i];
-
-                       // The size of the hashtable will be double the item count.
-                       // The rest of the slots will be empty.
-                       $len = $count + $count;
-                       $final .= pack( 'VV', $this->pos, $len );
-
-                       $hashtable = array();
-                       for ( $u = 0; $u < $len; ++$u ) {
-                               $hashtable[$u] = array( 'h' => 0, 'p' => 0 );
-                       }
-
-                       // Fill the hashtable, using the next empty slot if the hashed slot
-                       // is taken.
-                       for ( $u = 0; $u < $count; ++$u ) {
-                               $hp = $packedTables[$starts[$i] + $u];
-                               $where = CdbFunctions::unsignedMod(
-                                       CdbFunctions::unsignedShiftRight( $hp['h'], 8 ), $len );
-                               while ( $hashtable[$where]['p'] ) {
-                                       if ( ++$where == $len ) {
-                                               $where = 0;
-                                       }
-                               }
-                               $hashtable[$where] = $hp;
-                       }
-
-                       // Write the hashtable
-                       for ( $u = 0; $u < $len; ++$u ) {
-                               $buf = pack( 'vvV',
-                                       $hashtable[$u]['h'] & 0xffff,
-                                       CdbFunctions::unsignedShiftRight( $hashtable[$u]['h'], 16 ),
-                                       $hashtable[$u]['p'] );
-                               $this->write( $buf );
-                               $this->posplus( 8 );
-                       }
-               }
-
-               // Write the pointer array at the start of the file
-               rewind( $this->handle );
-               if ( ftell( $this->handle ) != 0 ) {
-                       $this->throwException( 'Error rewinding to start of file "' . $this->tmpFileName . '".' );
-               }
-               $this->write( $final );
-       }
-
-       /**
-        * Clean up the temp file and throw an exception
-        *
-        * @param string $msg
-        * @throws CdbException
-        */
-       protected function throwException( $msg ) {
-               if ( $this->handle ) {
-                       fclose( $this->handle );
-                       unlink( $this->tmpFileName );
-               }
-               throw new CdbException( $msg );
-       }
-}
index d176033..5025c36 100644 (file)
        "sunday": "Sunnandæg",
        "monday": "Mōnandæg",
        "tuesday": "Tīwesdæg",
-       "wednesday": "Wēdnesdæg",
+       "wednesday": "Wōdnesdæg",
        "thursday": "Þunresdæg",
        "friday": "Frigedæg",
        "saturday": "Sæterndæg",
        "sun": "Sun",
        "mon": "Mōn",
        "tue": "Tīw",
-       "wed": "Wēd",
+       "wed": "Wōd",
        "thu": "Þun",
        "fri": "Fri",
        "sat": "Sæt",
index eb4226a..9420b75 100644 (file)
        "gotaccountlink": "Daxil olun",
        "userlogin-resetlink": "Daxilolma məlumatlarınızı unutmusunuz?",
        "userlogin-resetpassword-link": "Parolu unutdunuzmu?",
-       "userlogin-loggedin": "Siz artıq {{GENDER:$1|$1}} kimi daxil olmusunuz.\nAşağıdakı formadan istifadə edərək, baÄ\9fqa bir istifadÉ\99çi kimi daxil ola bilÉ\99rsiniz.",
+       "userlogin-loggedin": "Siz artıq {{GENDER:$1|$1}} kimi daxil olmusunuz.\nAşağıdakı formadan istifadə edərək, baÅ\9fqa bir istifadÉ\99çi kimi daxil ola bilÉ\99rsiniz.",
        "userlogin-createanother": "Başqa bir istifadəçi hesabı yarat",
        "createacct-emailrequired": "E-poçt ünvanı",
        "createacct-emailoptional": "E-poçt ünvanı (istəyə bağlı)",
index 28bdb68..f64684c 100644 (file)
        "api-error-stashzerolength": "Сэрвэр ня змог схаваць файл, бо ён мае нулявы памер.",
        "api-error-stashnotloggedin": "Вы мусіце ўвайсьці ў сыстэму, каб захоўваць файлы ў схованку загрузкі.",
        "api-error-stashwrongowner": "Файл, да якога вы спрабуеце атрымаць доступ у схованцы, не належыць вам.",
+       "api-error-stashnosuchfilekey": "Ключ файла, да якога вы спрабуеце атрымаць доступ у схованцы, не існуе.",
        "api-error-timeout": "Сэрвэр не адказаў у чаканы тэрмін.",
        "api-error-unclassified": "Узьнікла невядомая памылка",
        "api-error-unknown-code": "Невядомая памылка: «$1».",
index 3cd8d75..91f08a2 100644 (file)
        "recentchanges": "這般其改變",
        "recentchanges-summary": "敆維基茲頁跟蹤這般其改變。",
        "recentchanges-label-newpage": "茲蜀萆修改創建新其蜀頁",
-       "recentchanges-label-minor": "是蜀萆過幼修改",
+       "recentchanges-label-minor": "是蜀萆過幼修改",
        "recentchanges-label-bot": "茲蜀萆修改是機器人做其",
        "rclistfrom": "顯示由$3 $2開始其新其改變",
        "rcshowhideminor": "$1過幼修改",
index 0f7705a..45c7105 100644 (file)
        "movepage-moved-redirect": "A redirect has been created.",
        "movepage-moved-noredirect": "The creation of a redirect has been suppressed.",
        "articleexists": "A page of that name already exists, or the name you have chosen is not valid.\nPlease choose another name.",
-       "cantmove-titleprotected": "You cannot move a page to this location because the new title has been protected from creation",
+       "cantmove-titleprotected": "You cannot move a page to this location because the new title has been protected from creation.",
        "movetalk": "Move associated talk page",
        "move-subpages": "Move subpages (up to $1)",
        "move-talk-subpages": "Move subpages of talk page (up to $1)",
        "delete_and_move_confirm": "Yes, delete the page",
        "delete_and_move_reason": "Deleted to make way for move from \"[[$1]]\"",
        "selfmove": "Source and destination titles are the same;\ncannot move a page over itself.",
-       "immobile-source-namespace": "Cannot move pages in namespace \"$1\"",
-       "immobile-target-namespace": "Cannot move pages into namespace \"$1\"",
+       "immobile-source-namespace": "Cannot move pages in namespace \"$1\".",
+       "immobile-target-namespace": "Cannot move pages into namespace \"$1\".",
        "immobile-target-namespace-iw": "Interwiki link is not a valid target for page move.",
        "immobile-source-page": "This page is not movable.",
        "immobile-target-page": "Cannot move to that destination title.",
        "bad-target-model": "The desired destination uses a different content model. Cannot convert from $1 to $2.",
-       "imagenocrossnamespace": "Cannot move file to non-file namespace",
-       "nonfile-cannot-move-to-file": "Cannot move non-file to file namespace",
-       "imagetypemismatch": "The new file extension does not match its type",
-       "imageinvalidfilename": "The target filename is invalid",
+       "imagenocrossnamespace": "Cannot move file to non-file namespace.",
+       "nonfile-cannot-move-to-file": "Cannot move non-file to file namespace.",
+       "imagetypemismatch": "The new file extension does not match its type.",
+       "imageinvalidfilename": "The target filename is invalid.",
        "fix-double-redirects": "Update any redirects that point to the original title",
        "move-leave-redirect": "Leave a redirect behind",
        "protectedpagemovewarning": "<strong>Warning:</strong> This page has been protected so that only users with administrator privileges can move it.\nThe latest log entry is provided below for reference:",
index 5e3d63e..6adc493 100644 (file)
        "confirmemail_body": "Immen, nei gedachten jo, hat him by {{SITENAME}} oanmelde as \"$2\", mei dit netpostadres ($1).\n\nHjirtroch komme ek de netpostfunksjes fan {{SITENAME}} foar jo beskikber. Iepenje de neikommende keppeling om te befêstigjen dat jo wier josels by {{SITENAME}} mei dit netpostadres oanmelde hawwe:\n\n$3\n\nAt jo dat *net* wienen, brûk dy keppeling dan net, en klik hjir:\n\n$5\n\nDizze befêstigingskoade ferrint dan op $4.",
        "scarytranscludetoolong": "[URL-adres is te lang]",
        "confirmrecreate": "Sûnt jo begûn binne dizze side te bewurkjen, hat meidogger [[User:$1|$1]] ([[User talk:$1|oerlis]]) de side wiske. De reden dy't derfoar jûn waard wie:\n: ''$2''\nWolle jo de side wier op 'e nij skriuwe?",
-       "confirm_purge_button": "Okee",
-       "confirm-watch-button": "Okee",
-       "confirm-unwatch-button": "Okee",
+       "confirm_purge_button": "OK",
+       "confirm-watch-button": "OK",
+       "confirm-unwatch-button": "OK",
        "confirm-unwatch-top": "Dizze side fan myn folchlist ôfhelje",
        "imgmultipageprev": "side werom",
        "imgmultipagenext": "folgjende side →",
        "version-software": "Ynsteld software",
        "version-software-product": "Produkt",
        "version-software-version": "Ferzje",
+       "redirect-value": "Wearde:",
        "redirect-file": "Triemnamme",
        "fileduplicatesearch": "Sykje op duplikaten",
        "fileduplicatesearch-legend": "Sykje op duplikaten",
        "duration-minutes": "$1 {{PLURAL:$1|minút|minuten}}",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|sekonde|sekonden}}",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|sekonde|sekonden}}",
-       "expand_templates_ok": "Okee",
+       "expand_templates_ok": "OK",
        "expand_templates_remove_comments": "Berjochten fuorthelje",
        "pagelang-language": "Taal",
        "mediastatistics-nbytes": "{{PLURAL:$1|$1 byte|$1 bytes}} ($2; $3%)"
index 8a90e4a..685de7b 100644 (file)
        "exif-exposuretime": "Exposure time",
        "exif-exposuretime-format": "$1 sec ($2)",
        "exif-fnumber": "F a Numero",
-       "exif-exposureprogram": "Exposure Program",
-       "exif-spectralsensitivity": "Spectral sensitivity",
-       "exif-isospeedratings": "ISO speed rating",
+       "exif-exposureprogram": "Programa ti panakailatakan",
+       "exif-spectralsensitivity": "Espektral a sensitibidad",
+       "exif-isospeedratings": "Grado ti kapardas ti ISO",
        "exif-shutterspeedvalue": "APEX Shutter speed",
        "exif-aperturevalue": "Apex aperture",
        "exif-brightnessvalue": "Kalawag ti APEX",
        "exif-exposurebiasvalue": "Exposure bias",
-       "exif-maxaperturevalue": "Maximum land aperture",
+       "exif-maxaperturevalue": "Kangato ti apertura ti daga",
        "exif-subjectdistance": "Kaadayo ti suheto",
        "exif-meteringmode": "Panagmetro a moda",
        "exif-lightsource": "Paggapuan ti lawag",
        "exif-focalplaneyresolution": "Focal plane Y resolution",
        "exif-focalplaneresolutionunit": "Focal plane resolution unit",
        "exif-subjectlocation": "Lokasion ti suheto",
-       "exif-exposureindex": "Exposure index",
-       "exif-sensingmethod": "Sensing method",
-       "exif-filesource": "Nagtaudan ti papeles",
-       "exif-scenetype": "Kita i senario",
+       "exif-exposureindex": "Pagsurotan ti panakailatakan",
+       "exif-sensingmethod": "Pamay-an ti panagrikna",
+       "exif-filesource": "Taudan ti papeles",
+       "exif-scenetype": "Kita ti senario",
        "exif-customrendered": "Naiduma a panagproseso ti ladawan",
-       "exif-exposuremode": "Exposure mode",
+       "exif-exposuremode": "Moda ti panakailatakan",
        "exif-whitebalance": "Pagtimbangan ti puraw",
        "exif-digitalzoomratio": "Digital zoom ratio",
        "exif-focallengthin35mmfilm": "Focal length iti 35 mm a film",
-       "exif-scenecapturetype": "Scene capture type",
-       "exif-gaincontrol": "Scene control",
+       "exif-scenecapturetype": "Kita ti panagala iti senario",
+       "exif-gaincontrol": "Panagtengngel ti senario",
        "exif-contrast": "Contrast",
        "exif-saturation": "Saturation",
        "exif-sharpness": "Kalawag",
        "exif-imageuniqueid": "Naisangsangayan nga ID ti ladawan",
        "exif-gpsversionid": "Etiketa a bersion ti GPS",
        "exif-gpslatituderef": "Amianan wenno Abagatan a Latitud",
-       "exif-gpslatitude": "Latitude",
+       "exif-gpslatitude": "Latitud",
        "exif-gpslongituderef": "Daya wenno Laud a Longitud",
        "exif-gpslongitude": "Longitud",
        "exif-gpsaltituderef": "Reperensia ti kangato",
        "exif-gpsdop": "Kasayaat ti panagrukod",
        "exif-gpsspeedref": "Yunit ti kapardas",
        "exif-gpsspeed": "Kapaspas ti pangawat ti GPS",
-       "exif-gpstrackref": "Reperensia iti direksion ti panaggunay",
+       "exif-gpstrackref": "Reperensia iti direksion ti kuti",
        "exif-gpstrack": "Direksion ti kuti",
        "exif-gpsimgdirectionref": "Reperensia iti direksion ti ladawan",
        "exif-gpsimgdirection": "Direksion ti ladawan",
        "exif-rightscertificate": "Sertipikado ti panagtaripato kadagiti karbengan",
        "exif-copyrighted": "Kasasaad ti karbengan ti kopia",
        "exif-copyrightowner": "Akinkukua ti karbengan ti kopia",
-       "exif-usageterms": "Dagiti termino ti panag-usar",
+       "exif-usageterms": "Dagiti termino ti panagusar",
        "exif-webstatement": "Insasao ti karbengan ti kopia nga addaan iti online",
        "exif-originaldocumentid": "Naisangayan nga ID iti kinasigud a dokumento",
        "exif-licenseurl": "URL para iti lisensia ti karbengan ti kopia",
        "exif-subjectdistancerange-1": "Makro",
        "exif-subjectdistancerange-2": "Asideg a pinagkita",
        "exif-subjectdistancerange-3": "Adayo a pinagkita",
-       "exif-gpslatitude-n": "Amianan a latitude",
-       "exif-gpslatitude-s": "Abagatan a latitude",
-       "exif-gpslongitude-e": "Daya a longitude",
-       "exif-gpslongitude-w": "Abagatan a longitude",
+       "exif-gpslatitude-n": "Amianan a latitud",
+       "exif-gpslatitude-s": "Abagatan a latitud",
+       "exif-gpslongitude-e": "Daya a longitud",
+       "exif-gpslongitude-w": "Abagatan a longitud",
        "exif-gpsaltitude-above-sealevel": "$1 {{PLURAL:$1|a metro|kadagiti metro}} a nangatngato ngem ti baybay",
        "exif-gpsaltitude-below-sealevel": "$1 {{PLURAL:$1|a metro|kadagiti metro}} a nababbaba ngem ti baybay",
        "exif-gpsstatus-a": "Agrukrukoden",
-       "exif-gpsstatus-v": "Panag-rukod ken pannakabin ti pang-usar ti sabali",
+       "exif-gpsstatus-v": "Panagrukod ken interoperabilidad",
        "exif-gpsmeasuremode-2": "2-kalawa pagrukod",
        "exif-gpsmeasuremode-3": "3-kalawa pagrukod",
        "exif-gpsspeed-k": "Dagiti kilometro kada oras",
        "exif-gpsdop-good": "Nalaing ($1)",
        "exif-gpsdop-moderate": "Natimbeng ($1)",
        "exif-gpsdop-fair": "Nasayaat ($1)",
-       "exif-gpsdop-poor": "Makukurangan ($1)",
+       "exif-gpsdop-poor": "Makurkurangan ($1)",
        "exif-objectcycle-a": "Agsapa laeng",
        "exif-objectcycle-p": "Rabii laeng",
        "exif-objectcycle-b": "Agsapa ken rabii",
        "logentry-upload-overwrite": "Ni $1 ket {{GENDER:$2|inkargana}} ti baro a bersion ti $3",
        "logentry-upload-revert": "Ni $1 ket {{GENDER:$2|inkargana}} ti $3",
        "rightsnone": "(awan)",
-       "revdelete-summary": "pakabuklan ti panagurnos",
+       "revdelete-summary": "Pakabuklan ti inurnos",
        "feedback-bugornote": "No sisasagakan nga agibaga ti teknikal a pakirut a naisalaysay pangngaasi nga [$1 ireporta ti parikut].\nNupay kasta, mausarmo ti nalaka a porma dita baba. Ti komentario nga itedmo ket mainayon iti panid \"[$3 $2], a mairaman ti naganmo nga agar-aramat ken no ania ti pagbasabasa nga us-sarem.",
        "feedback-subject": "Suheto:",
        "feedback-message": "Mensahe:",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (napakabaelan)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''nabaldado''')",
        "mediastatistics": "Estadistika ti midia",
+       "mediastatistics-summary": "Estadistika a maipanggep dagiti kita ti naikarga a papeles. Daytoy ket mangiraman laeng ti kinaudi a bersion ti papeles. Dagiti bersion ti papeles a daan wenno naikkat ket saan a mairaman.",
        "mediastatistics-nbytes": "{{PLURAL:$1|$1 a byte|$1 kadagiti bytes}} ($2; $3%)",
        "mediastatistics-table-mimetype": "Kita ti MIME",
        "mediastatistics-table-extensions": "Dagiti mabalin pagpaatiddog",
index 0759c08..6e63fc4 100644 (file)
@@ -70,7 +70,8 @@
                        "Darellur",
                        "Michał Sobkowski",
                        "Py64",
-                       "Nanaki"
+                       "Nanaki",
+                       "Alan ffm"
                ]
        },
        "tog-underline": "Podkreślenie linków:",
index cd7d6aa..5556cd9 100644 (file)
        "autosumm-replace": "Сирэй иһэ уларытыллыбыт: '$1'",
        "autoredircomment": "Утаарыы: [[$1]]",
        "autosumm-new": "'$1' ыйааһыннаах саҥа сирэй оҥоһулунна",
+       "autosumm-newblank": "Кураанах сирэй оҥоһулунна",
        "size-bytes": "$1 байт",
        "lag-warn-normal": "$1 {{PLURAL:$1|сөкүүндэ|сөкүүндэ}} иһинэн оҥоһуллубут уларытыылар манна көстүө суохтарын сөп.",
        "lag-warn-high": "Синхронизация лаппа хойутуур буолан кэнники $1 {{PLURAL:$1|сөкүүндэ|сөкүүндэ}} иһинэн оҥоһуллубут уларытыылар манна көстүө суохтарын сөп.",
index 1fa4813..171415c 100644 (file)
        "viewsourcetext": "คุณสามารถดูและคัดลอกโค้ดของหน้านี้:",
        "viewyourtext": "คุณสามารถดูและคัดลอกต้นฉบับ<strong>การแก้ไขของคุณ</strong>มายังหน้านี้ได้:",
        "protectedinterface": "หน้านี้เป็นข้อความส่วนต่อประสานสำหรับซอฟต์แวร์บนวิกินี้ และถูกล็อกเพื่อป้องกันการกระทำผิด\nในการเพิ่มหรือเปลี่ยนแปลงการแปลสำหรับทุกวิกิ โปรดใช้ [//translatewiki.net/ translatewiki.net] โครงการแปลมีเดียวิกิเป็นภาษาถิ่น",
-       "editinginterface": "<strong>คำเตือน:</strong> คุณกำลังแก้ไขหน้าที่ใช้จัดหาข้อความอินเตอร์เฟซให้ซอฟต์แวร์\nการเปลี่ยนแปลงหน้านี้จะกระทบต่อสภาพปรากฏของส่วนต่อประสานผู้ใช้แก่ผู้ใช้อื่นบนวิกินี้\nในการเพิ่มหรือเปลี่ยนแปลงคำแปลสำหรับทุกวิกิ โปรดใช้ [//translatewiki.net/wiki/Main_Page?setlang=th translatewiki.net] โครงการแปลมีเดียวิกิเป็นภาษาถิ่น",
+       "editinginterface": "<strong>คำเตือน:</strong> คุณกำลังแก้ไขหน้าที่ใช้จัดหาข้อความอินเตอร์เฟซให้ซอฟต์แวร์\nการเปลี่ยนแปลงหน้านี้จะมีผลต่อสภาพปรากฏของส่วนต่อประสานผู้ใช้แก่ผู้ใช้อื่นบนวิกินี้",
+       "translateinterface": "ในการเพิ่มหรือเปลี่ยนแปลงคำแปลสำหรับทุกวิกิ โปรดใช้ [//translatewiki.net/ translatewiki.net] โครงการแปลเป็นภาษาถิ่นของมีเดียวิกิ",
        "cascadeprotected": "หน้านี้ถูกป้องกันมิให้แก้ไข เพราะถูกรวมอยู่ในหน้าซึ่งถูกล็อกโดยเปิดตัวเลือก \"ทบทุกลำดับขั้น\":\n$2",
        "namespaceprotected": "คุณไม่มีสิทธิแก้ไขหน้าในเนมสเปซ <strong>$1</strong>",
        "customcssprotected": "คุณไม่มีสิทธิแก้ไขหน้า CSS นี้ เพราะมีการตั้งค่าส่วนบุคคลของผู้ใช้อื่น",
        "createaccount-text": "มีบางคนสร้างบัญชีโดยใช้ที่อยู่อีเมลของคุณบน {{SITENAME}} ($4) โดยใช้ชื่อ \"$2\" และรหัสผ่าน \"$3\" \nคุณควรล็อกอินและเปลี่ยนรหัสผ่านทันที\n\nคุณอาจเพิกเฉยข้อความนี้ หากการสร้างบัญชีนี้เป็นความผิดพลาด",
        "login-throttled": "ที่ผ่านมาคุณพยายามล็อกอินมากครั้งเกินไป\nกรุณารอ $1 ก่อนลองอีกครั้ง",
        "login-abort-generic": "การล็อกอินของคุณไม่สำเร็จ - ล้มเลิกแล้ว",
+       "login-migrated-generic": "บัญชีของคุณถูกย้ายแล้ว และไม่มีชื่อผู้ใช้ของคุณอยู่บนวิกินี้อีก",
        "loginlanguagelabel": "ภาษา: $1",
        "suspicious-userlogout": "คำขอล็อกเอาต์ของคุณถูกปฏิเสธเพราะดูเหมือนส่งมาจากเบราว์เซอร์หรือพร็อกซีแคชที่เสีย",
        "createacct-another-realname-tip": "ไม่จำเป็นต้องใส่ชื่อจริง\nหากคุณเลือกใส่ชื่อจริง จะใช้เพื่อแสดงที่มาสำหรับงานของตน",
        "content-model-text": "ข้อความธรรมดา",
        "content-model-javascript": "จาวาสคริปต์",
        "content-model-css": "CSS",
+       "duplicate-args-category": "หน้าที่ใช้อาร์กิวเมนต์จำลองในการเรียกแม่แบบ",
        "expensive-parserfunction-warning": "<strong>คำเตือน:</strong> หน้านี้มีการเรียกใช้ฟังก์ชันแจงส่วนมากเกินไป\n\nหน้านี้ควรมีการเรียกใช้น้อยกว่า $2  ครั้ง แต่ปัจจุบันมีการเรียกใช้ $1 ครั้ง",
        "expensive-parserfunction-category": "หน้าที่มีการเรียกใช้ฟังก์ชันแจงส่วนมากเกินไป",
        "post-expand-template-inclusion-warning": "<strong>คำเตือน:</strong> แม่แบบที่นำมารวมมีขนาดใหญ่เกินไป\nจะไม่รวมบางแม่แบบเข้ามา",
        "search-result-category-size": "$1 สมาชิก ($2 หมวดหมู่ย่อย, $3 ไฟล์)",
        "search-redirect": "(เปลี่ยนทาง $1)",
        "search-section": "(ส่วน $1)",
+       "search-category": "(หมวดหมู่ $1)",
        "search-file-match": "(เนื้อหาไฟล์ตรง)",
        "search-suggest": "คุณอาจหมายถึง: $1",
        "search-interwiki-caption": "โครงการพี่น้อง",
        "gender-female": "หญิง",
        "prefs-help-gender": "เลือกตั้งค่านี้หรือไม่ก็ได้\nซอฟต์แวร์ใช้ค่านี้เพื่อติดต่อคุณและกล่าวถึงคุณโดยใช้เพศทางไวยากรณ์ที่เหมาะสมเมื่อติดต่อผู้อื่น\nสารสนเทศนี้เปิดเผยต่อสาธารณะ",
        "email": "อีเมล",
-       "prefs-help-realname": "à¹\84มà¹\88à¸\88ำà¹\80à¸\9bà¹\87à¸\99à¸\95à¹\89อà¸\87à¹\83à¸\8aà¹\89à¸\8aืà¹\88อà¸\88ริà¸\87 \nà¸\96à¹\89าà¸\84ุà¸\93à¹\80ลือà¸\81à¹\83à¸\8aà¹\89à¸\8aืà¹\88อà¸\88ริà¸\87 à¸\88ะà¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88อà¹\83หà¹\89à¹\80à¸\81ียรà¸\95ิà¹\81à¸\81à¹\88à¸\87าà¸\99à¸\82อà¸\87คุณ",
+       "prefs-help-realname": "à¹\84มà¹\88à¸\95à¹\89อà¸\87à¹\83à¸\8aà¹\89à¸\8aืà¹\88อà¸\88ริà¸\87 \nหาà¸\81à¹\83à¸\8aà¹\89 à¸\88ะà¹\83à¸\8aà¹\89à¹\80à¸\9eืà¹\88อà¸\9aà¹\88à¸\87à¸\8aีà¹\89à¸\87าà¸\99à¸\82อà¸\87à¸\84ุà¸\93วà¹\88ามาà¸\88าà¸\81คุณ",
        "prefs-help-email": "ไม่จำเป็นต้องใส่ที่อยู่อีเมล แต่จำเป็นสำหรับการตั้งรหัสผ่านใหม่หากคุณลืมรหัสผ่าน",
        "prefs-help-email-others": "คุณยังสามารถเลือกให้ผู้อื่นติดต่อคุณโดยอีเมลผ่านลิงก์บนหน้าผู้ใช้หรือหน้าพูดคุยกับผู้ใช้ของคุณ\nไม่เปิดเผยที่อยู่อีเมลของคุณเมื่อผู้ใช้อื่นติดต่อคุณ",
        "prefs-help-email-required": "ต้องการที่อยู่อีเมล",
        "movepagetalktext": "หน้าพูดคุยของหน้านี้จะถูกเปลี่ยนชื่อตามไปโดยอัตโนมัติ '''เว้นแต่:'''\n*มีหน้าพูดคุยภายใต้ชื่อใหม่อยู่แล้ว หรือ\n*คุณไม่เลือกกล่องด้านล่าง\n\nหากเกิดกรณีเหล่านี้ คุณจะต้องย้ายหรือรวมหน้าเองหากต้องการเปลี่ยนชื่อตามในภายหลัง",
        "movearticle": "เปลี่ยนชื่อ",
        "moveuserpage-warning": "'''คำเตือน''' คุณกำลังย้ายหน้าผู้ใช้ โปรดทราบว่าหน้าผู้ใช้เท่านั้นที่จะถูกเปลี่ยนชื่อ แต่ผู้ใช้จะ'''ไม่'''ถูกเปลี่ยนชื่อ",
+       "movecategorypage-warning": "<strong>คำเตือน:</strong> คุณกำลังย้ายหน้าหมวดหมู่ โปรดทราบว่า จะย้ายเฉพาะหน้าและทุกหน้าในหมวดหมู่เก่าจะ<em>ไม่</em>ถูกจัดเข้าหมวดหมู่ใหม่",
        "movenologintext": "ถ้าต้องการเปลี่ยนชื่อหน้านี้ ต้องเป็นผู้ใช้ลงทะเบียนและ[[Special:UserLogin|ล็อกอิน]]",
        "movenotallowed": "คุณไม่มีสิทธิเปลี่ยนชื่อหน้า",
        "movenotallowedfile": "คุณไม่มีสิทธิย้ายไฟล์",
        "cant-move-user-page": "คุณไม่มีสิทธิย้ายหน้าผู้ใช้ (แยกจากหน้าย่อย)",
        "cant-move-to-user-page": "คุณไม่มีสิทธิย้ายหน้าใด ๆ ไปเป็นหน้าผู้ใช้ (ยกเว้นหน้าย่อยของผู้ใช้)",
+       "cant-move-category-page": "คุณไม่มีสิทธิย้ายหน้าหมวดหมู่",
+       "cant-move-to-category-page": "คุณไม่มีสิทธิย้ายหน้าไปหน้าหมวดหมู่",
        "newtitle": "ไปชื่อเรื่องใหม่:",
        "move-watch": "เฝ้าดูหน้าต้นทางและหน้าปลายทาง",
        "movepagebtn": "เปลี่ยนชื่อ",
        "importlogpage": "ปูมการนำเข้า",
        "importlogpagetext": "นำเข้าไฟล์จากวิกิอื่น โดยผ่านทางผู้ดูแลระบบ",
        "import-logentry-upload": "นำเข้า [[$1]] ผ่านการอัปโหลดแล้ว",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|รุ่นการแก้ไข|รุ่นการแก้ไข}}",
+       "import-logentry-upload-detail": "นำเข้า $1 {{PLURAL:$1|รุ่นการแก้ไข|รุ่นการแก้ไข}}",
        "import-logentry-interwiki": "นำเข้าข้ามวิกิ $1 แล้ว",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|รุ่นการแก้ไข|รุ่นการแก้ไข}}จาก $2",
+       "import-logentry-interwiki-detail": "นำเข้า $1 {{PLURAL:$1|รุ่นการแก้ไข|รุ่นการแก้ไข}}จาก $2",
        "javascripttest": "การทดสอบจาวาสคริปต์",
        "javascripttest-title": "กำลังดำเนินงานทดสอบ $1",
        "javascripttest-pagetext-noframework": "หน้านี้สงวนไว้สำหรับดำเนินงานการทดสอบจาวาสคริปต์",
        "tooltip-pt-mycontris": "รายการหน้าที่คุณเขียน",
        "tooltip-pt-login": "ไม่จำเป็นต้องล็อกอินในการแก้ไข แต่แนะนำอย่างยิ่งให้ล็อกอิน",
        "tooltip-pt-logout": "ล็อกเอาต์",
+       "tooltip-pt-createaccount": "สนับสนุนให้คุณสร้างบัญชีและล็อกอิน แต่ไม่บังคับ",
        "tooltip-ca-talk": "อภิปรายเกี่ยวกับหน้าเนื้อหา",
        "tooltip-ca-edit": "คุณสามารถแก้ไขหน้านี้ได้ โปรดใช้ปุ่มตัวอย่างก่อนบันทึก",
        "tooltip-ca-addsection": "เริ่มส่วนใหม่",
        "tooltip-feed-atom": "ฟีดอะตอม (Atom) ของหน้านี้",
        "tooltip-t-contributions": "รายการเรื่องที่เขียนโดยผู้ใช้นี้",
        "tooltip-t-emailuser": "ส่งอีเมลถึงผู้ใช้นี้",
+       "tooltip-t-info": "สารสนเทศเพิ่มเติมเกี่ยวกับหน้านี้",
        "tooltip-t-upload": "อัปโหลดไฟล์",
        "tooltip-t-specialpages": "รายการหน้าพิเศษทั้งหมด",
        "tooltip-t-print": "รุ่นที่พร้อมพิมพ์ของหน้านี้",
diff --git a/tests/phpunit/includes/libs/cdb/CdbTest.php b/tests/phpunit/includes/libs/cdb/CdbTest.php
new file mode 100644 (file)
index 0000000..487ee1f
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * Test the CDB reader/writer
+ * @covers CdbWriterPHP
+ * @covers CdbWriterDBA
+ */
+class CdbTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+               if ( !CdbReader::haveExtension() ) {
+                       $this->markTestSkipped( 'Native CDB support is not available' );
+               }
+       }
+
+       /**
+        * @group medium
+        */
+       public function testCdb() {
+               $dir = wfTempDir();
+               if ( !is_writable( $dir ) ) {
+                       $this->markTestSkipped( "Temp dir isn't writable" );
+               }
+
+               $phpcdbfile = $this->getNewTempFile();
+               $dbacdbfile = $this->getNewTempFile();
+
+               $w1 = new CdbWriterPHP( $phpcdbfile );
+               $w2 = new CdbWriterDBA( $dbacdbfile );
+
+               $data = array();
+               for ( $i = 0; $i < 1000; $i++ ) {
+                       $key = $this->randomString();
+                       $value = $this->randomString();
+                       $w1->set( $key, $value );
+                       $w2->set( $key, $value );
+
+                       if ( !isset( $data[$key] ) ) {
+                               $data[$key] = $value;
+                       }
+               }
+
+               $w1->close();
+               $w2->close();
+
+               $this->assertEquals(
+                       md5_file( $phpcdbfile ),
+                       md5_file( $dbacdbfile ),
+                       'same hash'
+               );
+
+               $r1 = new CdbReaderPHP( $phpcdbfile );
+               $r2 = new CdbReaderDBA( $dbacdbfile );
+
+               foreach ( $data as $key => $value ) {
+                       if ( $key === '' ) {
+                               // Known bug
+                               continue;
+                       }
+                       $v1 = $r1->get( $key );
+                       $v2 = $r2->get( $key );
+
+                       $v1 = $v1 === false ? '(not found)' : $v1;
+                       $v2 = $v2 === false ? '(not found)' : $v2;
+
+                       # cdbAssert( 'Mismatch', $key, $v1, $v2 );
+                       $this->cdbAssert( "PHP error", $key, $v1, $value );
+                       $this->cdbAssert( "DBA error", $key, $v2, $value );
+               }
+       }
+
+       private function randomString() {
+               $len = mt_rand( 0, 10 );
+               $s = '';
+               for ( $j = 0; $j < $len; $j++ ) {
+                       $s .= chr( mt_rand( 0, 255 ) );
+               }
+
+               return $s;
+       }
+
+       private function cdbAssert( $msg, $key, $v1, $v2 ) {
+               $this->assertEquals(
+                       $v2,
+                       $v1,
+                       $msg . ', k=' . bin2hex( $key )
+               );
+       }
+}
diff --git a/tests/phpunit/includes/utils/CdbTest.php b/tests/phpunit/includes/utils/CdbTest.php
deleted file mode 100644 (file)
index 487ee1f..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-
-/**
- * Test the CDB reader/writer
- * @covers CdbWriterPHP
- * @covers CdbWriterDBA
- */
-class CdbTest extends MediaWikiTestCase {
-
-       protected function setUp() {
-               parent::setUp();
-               if ( !CdbReader::haveExtension() ) {
-                       $this->markTestSkipped( 'Native CDB support is not available' );
-               }
-       }
-
-       /**
-        * @group medium
-        */
-       public function testCdb() {
-               $dir = wfTempDir();
-               if ( !is_writable( $dir ) ) {
-                       $this->markTestSkipped( "Temp dir isn't writable" );
-               }
-
-               $phpcdbfile = $this->getNewTempFile();
-               $dbacdbfile = $this->getNewTempFile();
-
-               $w1 = new CdbWriterPHP( $phpcdbfile );
-               $w2 = new CdbWriterDBA( $dbacdbfile );
-
-               $data = array();
-               for ( $i = 0; $i < 1000; $i++ ) {
-                       $key = $this->randomString();
-                       $value = $this->randomString();
-                       $w1->set( $key, $value );
-                       $w2->set( $key, $value );
-
-                       if ( !isset( $data[$key] ) ) {
-                               $data[$key] = $value;
-                       }
-               }
-
-               $w1->close();
-               $w2->close();
-
-               $this->assertEquals(
-                       md5_file( $phpcdbfile ),
-                       md5_file( $dbacdbfile ),
-                       'same hash'
-               );
-
-               $r1 = new CdbReaderPHP( $phpcdbfile );
-               $r2 = new CdbReaderDBA( $dbacdbfile );
-
-               foreach ( $data as $key => $value ) {
-                       if ( $key === '' ) {
-                               // Known bug
-                               continue;
-                       }
-                       $v1 = $r1->get( $key );
-                       $v2 = $r2->get( $key );
-
-                       $v1 = $v1 === false ? '(not found)' : $v1;
-                       $v2 = $v2 === false ? '(not found)' : $v2;
-
-                       # cdbAssert( 'Mismatch', $key, $v1, $v2 );
-                       $this->cdbAssert( "PHP error", $key, $v1, $value );
-                       $this->cdbAssert( "DBA error", $key, $v2, $value );
-               }
-       }
-
-       private function randomString() {
-               $len = mt_rand( 0, 10 );
-               $s = '';
-               for ( $j = 0; $j < $len; $j++ ) {
-                       $s .= chr( mt_rand( 0, 255 ) );
-               }
-
-               return $s;
-       }
-
-       private function cdbAssert( $msg, $key, $v1, $v2 ) {
-               $this->assertEquals(
-                       $v2,
-                       $v1,
-                       $msg . ', k=' . bin2hex( $key )
-               );
-       }
-}