diff options
257 files changed, 7675 insertions, 4911 deletions
diff --git a/.github/workflows/testLinux.yml b/.github/workflows/testLinux.yml index fc4ea350b..4523938e6 100644 --- a/.github/workflows/testLinux.yml +++ b/.github/workflows/testLinux.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - php-versions: ['7.2', '7.3', '7.4', '8.0'] + php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1'] fail-fast: false services: @@ -35,6 +35,7 @@ jobs: with: php-version: ${{ matrix.php-versions }} extensions: mbstring, intl, PDO, pdo_sqlite, pdo_mysql, pdo_pgsql, bz2 + ini-values: pcre.jit=0 - name: Setup problem matchers run: | diff --git a/.github/workflows/testWindows.yml b/.github/workflows/testWindows.yml index 7787e3c46..43fe624c5 100644 --- a/.github/workflows/testWindows.yml +++ b/.github/workflows/testWindows.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: - php-versions: ['7.2', '7.3', '7.4', '8.0'] + php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1'] fail-fast: false steps: diff --git a/.gitignore b/.gitignore index bc00b7f20..1fa9b1cdc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ /data/cache/* /data/index/* /data/locks/* +/data/log/* /data/media/* /data/media_meta/* /data/media_attic/* @@ -95,5 +96,5 @@ vendor/splitbrain/php-cli/apigen.neon # PHPUnit tests phpunit.phar -.phpunit.result.cache +*.phpunit.result.cache _test/data/ diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..321935a0e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,16 @@ +# Security Policy + +Security vulnerabilities can be reported for the current stable release (branch `stable`) and the `master` branch. + +We try to fix vulnerabilites as fast as possible, but please keep in mind that this is a project run by volunteers. Depending on the severity we may release hotfixes for the current stable release or may simply incorporate the fix in the next proper release. + +**This policy only applies to DokuWiki and the bundled plugins. Do not report issues about 3rd party plugins here.** + +## Reporting a Vulnerability + +You have multiple options on reporting vulnerabilities + +* Use [huntr.dev](https://www.huntr.dev/bounties/disclose/?target=https%3A%2F%2Fgithub.com%2Fsplitbrain%2Fdokuwiki%2F) +* Send an e-mail to [Andi](mailto:andi@splitbrain.org) +* Open a [Github Issue](https://github.com/splitbrain/dokuwiki/issues) +* Send a mail to the [Mailing List](https://www.dokuwiki.org/mailinglist) diff --git a/_test/core/DokuWikiTest.php b/_test/core/DokuWikiTest.php index e785e3b18..553353af8 100644 --- a/_test/core/DokuWikiTest.php +++ b/_test/core/DokuWikiTest.php @@ -195,7 +195,7 @@ abstract class DokuWikiTest extends PHPUnit\Framework\TestCase { * Waits until a new second has passed * * This tried to be clever about the passing of time and return early if possible. Unfortunately - * this never worked reliably fo unknown reasons. To avoid flaky tests, this now always simply + * this never worked reliably for unknown reasons. To avoid flaky tests, this now always simply * sleeps for a full second on every call. * * @param bool $init no longer used diff --git a/_test/core/phpQuery-onefile.php b/_test/core/phpQuery-onefile.php index 96083f9c2..377a7858c 100644 --- a/_test/core/phpQuery-onefile.php +++ b/_test/core/phpQuery-onefile.php @@ -1022,20 +1022,7 @@ class Callback // return new Callback($this->callback, $this->params+$params); // } } -/** - * Shorthand for new Callback(create_function(...), ...); - * - * @author Tobiasz Cudnik <tobiasz.cudnik/gmail.com> - */ -class CallbackBody extends Callback { - public function __construct($paramList, $code, $param1 = null, $param2 = null, - $param3 = null) { - $params = func_get_args(); - $params = array_slice($params, 2); - $this->callback = create_function($paramList, $code); - $this->params = $params; - } -} + /** * Callback type which on execution returns reference passed during creation. * @@ -2083,16 +2070,18 @@ class phpQueryObject break; case 'parent': $this->elements = $this->map( - create_function('$node', ' + function ($node) { return $node instanceof DOMELEMENT && $node->childNodes->length - ? $node : null;') + ? $node : null; + } )->elements; break; case 'empty': $this->elements = $this->map( - create_function('$node', ' + function ($node) { return $node instanceof DOMELEMENT && $node->childNodes->length - ? null : $node;') + ? null : $node; + } )->elements; break; case 'disabled': @@ -2105,19 +2094,21 @@ class phpQueryObject break; case 'enabled': $this->elements = $this->map( - create_function('$node', ' - return pq($node)->not(":disabled") ? $node : null;') + function ($node) { + return pq($node)->not(":disabled") ? $node : null; + } )->elements; break; case 'header': $this->elements = $this->map( - create_function('$node', - '$isHeader = isset($node->tagName) && in_array($node->tagName, array( - "h1", "h2", "h3", "h4", "h5", "h6", "h7" - )); + function ($node) { + $isHeader = isset($node->tagName) && in_array($node->tagName, array( + "h1", "h2", "h3", "h4", "h5", "h6", "h7" + )); return $isHeader ? $node - : null;') + : null; + } )->elements; // $this->elements = $this->map( // create_function('$node', '$node = pq($node); @@ -2134,18 +2125,23 @@ class phpQueryObject break; case 'only-child': $this->elements = $this->map( - create_function('$node', - 'return pq($node)->siblings()->size() == 0 ? $node : null;') + function ($node) { + return pq($node)->siblings()->size() == 0 ? $node : null; + } )->elements; break; case 'first-child': $this->elements = $this->map( - create_function('$node', 'return pq($node)->prevAll()->size() == 0 ? $node : null;') + function ($node) { + return pq($node)->prevAll()->size() == 0 ? $node : null; + } )->elements; break; case 'last-child': $this->elements = $this->map( - create_function('$node', 'return pq($node)->nextAll()->size() == 0 ? $node : null;') + function ($node) { + return pq($node)->nextAll()->size() == 0 ? $node : null; + } )->elements; break; case 'nth-child': @@ -2158,45 +2154,46 @@ class phpQueryObject // :nth-child(index/even/odd/equation) if ($param == 'even' || $param == 'odd') $mapped = $this->map( - create_function('$node, $param', - '$index = pq($node)->prevAll()->size()+1; - if ($param == "even" && ($index%2) == 0) + function ($node, $param) { + $index = pq($node)->prevAll()->size() + 1; + if ($param == "even" && ($index % 2) == 0) return $node; - else if ($param == "odd" && $index%2 == 1) + else if ($param == "odd" && $index % 2 == 1) return $node; else - return null;'), - new CallbackParam(), $param + return null; + }, new CallbackParam(), $param ); else if (mb_strlen($param) > 1 && $param[1] == 'n') // an+b $mapped = $this->map( - create_function('$node, $param', - '$prevs = pq($node)->prevAll()->size(); - $index = 1+$prevs; + function ($node, $param) { + $prevs = pq($node)->prevAll()->size(); + $index = 1 + $prevs; $b = mb_strlen($param) > 3 - ? $param{3} + ? $param[3] : 0; - $a = $param{0}; - if ($b && $param{2} == "-") + $a = $param[0]; + if ($b && $param[2] == "-") $b = -$b; if ($a > 0) { - return ($index-$b)%$a == 0 + return ($index - $b) % $a == 0 ? $node : null; - phpQuery::debug($a."*".floor($index/$a)."+$b-1 == ".($a*floor($index/$a)+$b-1)." ?= $prevs"); - return $a*floor($index/$a)+$b-1 == $prevs - ? $node - : null; - } else if ($a == 0) + phpQuery::debug($a . "*" . floor($index / $a) . "+$b-1 == " . ($a * floor($index / $a) + $b - 1) . " ?= $prevs"); + return $a * floor($index / $a) + $b - 1 == $prevs + ? $node + : null; + } else if ($a == 0) { return $index == $b - ? $node - : null; - else + ? $node + : null; + } else { // negative value return $index <= $b - ? $node - : null; + ? $node + : null; + } // if (! $b) // return $index%$a == 0 // ? $node @@ -2205,20 +2202,21 @@ class phpQueryObject // return ($index-$b)%$a == 0 // ? $node // : null; - '), + }, new CallbackParam(), $param ); else // index $mapped = $this->map( - create_function('$node, $index', - '$prevs = pq($node)->prevAll()->size(); - if ($prevs && $prevs == $index-1) + function ($node, $index) { + $prevs = pq($node)->prevAll()->size(); + if ($prevs && $prevs == $index - 1) return $node; - else if (! $prevs && $index == 1) + else if (!$prevs && $index == 1) return $node; else - return null;'), + return null; + }, new CallbackParam(), $param ); $this->elements = $mapped->elements; @@ -2230,7 +2228,7 @@ class phpQueryObject /** * @access private */ - protected function __pseudoClassParam($paramsString) { + protected function pseudoClassParam($paramsString) { // TODO; } /** @@ -2456,7 +2454,7 @@ class phpQueryObject 'type' => $data ? 'POST' : 'GET', 'data' => $data, 'complete' => $callback, - 'success' => array($this, '__loadSuccess') + 'success' => array($this, 'loadSuccess') ); phpQuery::ajax($ajax); return $this; @@ -2466,7 +2464,7 @@ class phpQueryObject * @param $html * @return unknown_type */ - public function __loadSuccess($html) { + public function loadSuccess($html) { if ($this->_loadSelector) { $html = phpQuery::newDocument($html)->find($this->_loadSelector); unset($this->_loadSelector); @@ -4267,21 +4265,21 @@ class phpQueryObject $debug = phpQuery::$debug; phpQuery::$debug = false; foreach($this->stack() as $node) - $output .= $this->__dumpTree($node); + $output .= $this->dumpTreeInternal($node); phpQuery::$debug = $debug; print $html ? nl2br(str_replace(' ', ' ', $output)) : $output; return $this; } - private function __dumpTree($node, $intend = 0) { + private function dumpTreeInternal($node, $intend = 0) { $whois = $this->whois($node); $return = ''; if ($whois) $return .= str_repeat(' - ', $intend).$whois."\n"; if (isset($node->childNodes)) foreach($node->childNodes as $chNode) - $return .= $this->__dumpTree($chNode, $intend+1); + $return .= $this->dumpTreeInternal($chNode, $intend+1); return $return; } /** @@ -4742,15 +4740,15 @@ abstract class phpQuery { while (preg_match($regex, $content)) $content = preg_replace_callback( $regex, - create_function('$m', - 'return $m[1].$m[2].$m[3]."<?php " - .str_replace( + function ($m) { + return $m[1] . $m[2] . $m[3] . '<?php ' + . str_replace( array("%20", "%3E", "%09", " ", "	", "%7B", "%24", "%7D", "%22", "%5B", "%5D"), - array(" ", ">", " ", "\n", " ", "{", "$", "}", \'"\', "[", "]"), + array(" ", ">", " ", "\n", " ", "{", "$", "}", '"', "[", "]"), htmlspecialchars_decode($m[4]) ) - ." ?>".$m[5].$m[2];' - ), + . " ?>" . $m[5] . $m[2]; + }, $content ); return $content; diff --git a/_test/phpcs_MigrationAdjustments.xml b/_test/phpcs_MigrationAdjustments.xml index d9d11832b..b56ffc12b 100644 --- a/_test/phpcs_MigrationAdjustments.xml +++ b/_test/phpcs_MigrationAdjustments.xml @@ -67,6 +67,7 @@ <exclude name="PSR2.Namespaces.UseDeclaration.SpaceAfterLastUse"/> <exclude name="PSR12.Classes.ClassInstantiation.MissingParentheses"/> + <exclude name="PSR12.Classes.OpeningBraceSpace.Found"/> <exclude name="PSR12.ControlStructures.BooleanOperatorPlacement.FoundMixed"/> <exclude name="PSR12.ControlStructures.ControlStructureSpacing.FirstExpressionLine"/> <exclude name="PSR12.ControlStructures.ControlStructureSpacing.CloseParenthesisLine"/> @@ -76,7 +77,6 @@ <exclude name="PSR12.Files.FileHeader.SpacingAfterBlock"/> <exclude name="PSR12.Operators.OperatorSpacing.NoSpaceBefore"/> <exclude name="PSR12.Operators.OperatorSpacing.NoSpaceAfter"/> - <exclude name="PSR12.Properties.ConstantVisibility.NotFound"/> </rule> diff --git a/_test/tests/inc/File/PageResolverTest.php b/_test/tests/inc/File/PageResolverTest.php new file mode 100644 index 000000000..7d93fddf7 --- /dev/null +++ b/_test/tests/inc/File/PageResolverTest.php @@ -0,0 +1,203 @@ +<?php + +namespace tests\inc\File; + +use dokuwiki\File\PageResolver; + +/** + * @todo tests that make use of revisions might be wanted + */ +class PageResolverTest extends \DokuWikiTest +{ + /** + * @return \Generator|array + * @see testResolveID + */ + public function provideResolveData() + { + $data = [ + // relative current in root + ['context', 'page', 'page'], + ['context', '.page', 'page'], + ['context', '.:page', 'page'], + + // relative current in namespace + ['lev1:lev2:context', 'page', 'lev1:lev2:page'], + ['lev1:lev2:context', '.page', 'lev1:lev2:page'], + ['lev1:lev2:context', '.:page', 'lev1:lev2:page'], + + // relative upper in root + ['context', '..page', 'page'], + ['context', '..:page', 'page'], + + // relative upper in namespace + ['lev1:lev2:context', '..page', 'lev1:page'], + ['lev1:lev2:context', '..:page', 'lev1:page'], + ['lev1:lev2:context', '..:..:page', 'page'], + ['lev1:lev2:context', '..:..:..:page', 'page'], + + // deeper nesting + ['lev1:lev2:lev3:context', '..page', 'lev1:lev2:page'], + ['lev1:lev2:lev3:context', '..:page', 'lev1:lev2:page'], + ['lev1:lev2:lev3:context', '..:..page', 'lev1:page'], + ['lev1:lev2:lev3:context', '..:..:page', 'lev1:page'], + ['lev1:lev2:lev3:context', '..:..:..page', 'page'], + ['lev1:lev2:lev3:context', '..:..:..:page', 'page'], + ['lev1:lev2:lev3:context', '..:..:..:..page', 'page'], + ['lev1:lev2:lev3:context', '..:..:..:..:page', 'page'], + + // strange and broken ones + ['lev1:lev2:context', '....:....:page', 'lev1:lev2:page'], + ['lev1:lev2:context', '..:..:lev3:page', 'lev3:page'], + ['lev1:lev2:context', '..:..:lev3:..:page', 'page'], + ['lev1:lev2:context', '..:..:lev3:..:page:....:...', 'page'], + + // relative to current page + ['context', '~page', 'context:page'], + ['context', '~:page', 'context:page'], + ['lev1:lev2:context', '~page', 'lev1:lev2:context:page'], + ['lev1:lev2:context', '~:page', 'lev1:lev2:context:page'], + + // start pages + ['context', '.:', 'start'], + ['foo:context', '.:', 'foo:start'], + ['context', 'foo:', 'foo:start'], + ['foo:context', 'foo:', 'foo:start'], + ['context', '~foo:', 'context:foo:start'], + ['foo:context', '~foo:', 'foo:context:foo:start'], + + // empty page links to itself + ['context', '', 'context'], + ['foo:context', '', 'foo:context'], + ]; + + // run each test without a hash + foreach ($data as $row) { + yield $row; + } + + // run each test with a hash + foreach ($data as $row) { + $row[1] .= '#somehash'; + $row[2] .= '#somehash'; + yield $row; + } + } + + /** + * @dataProvider provideResolveData + * @param string $context + * @param string $id + * @param string $expected + */ + public function testResolveID($context, $id, $expected) + { + $resolver = new PageResolver($context); + $this->assertEquals($expected, $resolver->resolveId($id)); + } + + /** + * Tilde start page bahaviour + * + * Please note that a ~ alone is the same as ~: + */ + public function testTildeStartPage() { + $context = 'foo:context'; + $resolver = new PageResolver($context); + + // the $context page itself does not exist + // a link like that is usually not possible, but we fall back to standard start + // page behaviour + $this->assertEquals("$context:start", $resolver->resolveId('~:')); + $this->assertEquals("$context:start", $resolver->resolveId('~')); + + // now $context has become the start page + saveWikiText($context, 'test', 'test'); + $this->assertEquals($context, $resolver->resolveId('~:')); + + // now we have a startpage named like the namespace + saveWikiText("$context:context", 'test', 'test'); + $this->assertEquals("$context:context", $resolver->resolveId('~:')); + $this->assertEquals("$context:context", $resolver->resolveId('~')); + + // now we have a dedicated start page + saveWikiText("$context:start", 'test', 'test'); + $this->assertEquals("$context:start", $resolver->resolveId('~:')); + $this->assertEquals("$context:start", $resolver->resolveId('~')); + } + + public function testResolveStartPage() { + + $resolver = new PageResolver('arbitrary'); + + $expect = 'foo:start'; + $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]); + $this->assertEquals($expect, $actual, 'default non-existing'); + + saveWikiText('foo', 'test', 'test'); + $expect = 'foo'; + $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]); + $this->assertEquals($expect, $actual, 'page like namespace outside'); + + saveWikiText('foo:foo', 'test', 'test'); + $expect = 'foo:foo'; + $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]); + $this->assertEquals($expect, $actual, 'page like namespace inside'); + + saveWikiText('foo:start', 'test', 'test'); + $expect = 'foo:start'; + $actual = $this->callInaccessibleMethod($resolver, 'resolveStartPage', ['foo:', false, false]); + $this->assertEquals($expect, $actual, 'default existing'); + } + + /** + * @return array + * @see testResolveRelatives + */ + public function provideResolveRelatives() { + return [ + ['foo', 'foo'], + ['foo:bar', 'foo:bar'], + ['foo:..:bar', 'bar'], + ['foo:..:..:bar', 'bar'], + ['foo:.:bar', 'foo:bar'], + ['foo:.:..:.:bar', 'bar'], + ['foo:.:.:.:bar', 'foo:bar'], + ['foo::::bar', 'foo:bar'], + ['foo::::bar:', 'foo:bar:'], + ['foo:bar:', 'foo:bar:'], + ]; + } + + /** + * @dataProvider provideResolveRelatives + * @param string $input + * @param string $expected + */ + public function testResolveRelatives($input, $expected) { + $resolver = new PageResolver('arbitrary'); + + $actual = $this->callInaccessibleMethod($resolver, 'resolveRelatives', [$input]); + $this->assertEquals($expected, $actual); + } + + public function testAutoPlural() + { + $resolver = new PageResolver('arbitrary'); + + $singular = 'some:page'; + $plural = 'some:pages'; + + + $actual = $this->callInaccessibleMethod($resolver, 'resolveAutoPlural', [$singular, '', false]); + $this->assertEquals($singular, $actual); // no pages exist + + saveWikiText($plural, 'plural', 'plural'); + $actual = $this->callInaccessibleMethod($resolver, 'resolveAutoPlural', [$singular, '', false]); + $this->assertEquals($plural, $actual); // plural exists + + saveWikiText($singular, 'singular', 'singular'); + $actual = $this->callInaccessibleMethod($resolver, 'resolveAutoPlural', [$singular, '', false]); + $this->assertEquals($singular, $actual); // requested singular has preference + } +} diff --git a/_test/tests/inc/XmlRpcServer.test.php b/_test/tests/inc/XmlRpcServer.test.php index 6d5dffc76..c0cdfac3a 100644 --- a/_test/tests/inc/XmlRpcServer.test.php +++ b/_test/tests/inc/XmlRpcServer.test.php @@ -33,13 +33,14 @@ class XmlRpcServerTest extends DokuWikiTest $pageName = ":wiki:dokuwiki"; $file = wikiFN($pageName); $timestamp = filemtime($file); - $ixrModifiedTime = (new DateTime('@' . $timestamp))->format(IXR_Date::XMLRPC_ISO8601); + $ixrModifiedTime = (new DateTime('@' . $timestamp))->format(DateTime::ATOM); + $author = '127.0.0.1'; // read from changelog, $info['user'] or $info['ip'] $request = <<<EOD <?xml version="1.0"?> <methodCall> <methodName>wiki.getPageInfo</methodName> - <param> + <param> <value> <string>$pageName</string> </value> @@ -54,7 +55,7 @@ EOD; <struct> <member><name>name</name><value><string>wiki:dokuwiki</string></value></member> <member><name>lastModified</name><value><dateTime.iso8601>$ixrModifiedTime</dateTime.iso8601></value></member> - <member><name>author</name><value><string></string></value></member> + <member><name>author</name><value><string>$author</string></value></member> <member><name>version</name><value><int>$timestamp</int></value></member> </struct> </value> @@ -64,6 +65,6 @@ EOD; EOD; $this->server->serve($request); - $this->assertEquals(trim($expected), trim($this->server->output)); + $this->assertXmlStringEqualsXmlString(trim($expected), trim($this->server->output)); } } diff --git a/_test/tests/inc/auth_browseruid.test.php b/_test/tests/inc/auth_browseruid.test.php deleted file mode 100644 index d33552582..000000000 --- a/_test/tests/inc/auth_browseruid.test.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -class auth_browseruid_test extends DokuWikiTest { - - - /** - * regression test to ensure correct browser id on IE9. - * - * IE9 send different HTTP_ACCEPT_LANGUAGE header on ajax request. - */ - function testIE9JsVsDefault() { - - // javascript request - $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'; - $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip, deflate'; - $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de'; - unset($_SERVER['HTTP_ACCEPT_CHARSET']); - $javascriptId = auth_browseruid(); - - // default request - $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'; - $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip, deflate'; - $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-DE'; - $normalId = auth_browseruid(); - - $this->assertEquals($normalId, $javascriptId); - - } - -}
\ No newline at end of file diff --git a/_test/tests/inc/auth_loadacl.test.php b/_test/tests/inc/auth_loadacl.test.php index 7fae2e90e..a44d9b4a7 100644 --- a/_test/tests/inc/auth_loadacl.test.php +++ b/_test/tests/inc/auth_loadacl.test.php @@ -93,7 +93,7 @@ ACL; // FS#2867, '\s' in php regular expressions may match non-space characters utf8 strings // this is due to locale setting on the server, which may match bytes '\xA0' and '\x85' // these two bytes are present in valid multi-byte UTF-8 characters. - // this test will use one, 'ठ' (DEVANAGARI LETTER TTHA, e0 a4 a0). There are many others. + // this test will use one, 'ठ' (DEVANAGARI LETTER TTHA, e0 a4 a0). There are many others. function test_FS2867() { global $USERINFO; diff --git a/_test/tests/inc/changelog_getRevisionsAround.test.php b/_test/tests/inc/changelog_getRevisionsAround.test.php index 2504487cc..c42edf0ef 100644 --- a/_test/tests/inc/changelog_getRevisionsAround.test.php +++ b/_test/tests/inc/changelog_getRevisionsAround.test.php @@ -35,12 +35,10 @@ class changelog_getrevisionsaround_test extends DokuWikiTest { parent::setup(); global $cache_revinfo; $cache =& $cache_revinfo; - if(isset($cache['nonexist'])) { - unset($cache['nonexist']); - } - if(isset($cache['mailinglist'])) { - unset($cache['mailinglist']); - } + unset($cache['nonexist']); + unset($cache['mailinglist']); + // fix filemtime of page source + touch(wikiFN($this->pageid), $this->revsexpected[0]); } /** diff --git a/_test/tests/inc/changelog_getlastrevisionat.test.php b/_test/tests/inc/changelog_getlastrevisionat.test.php index 49b3b2415..ff5392dbe 100644 --- a/_test/tests/inc/changelog_getlastrevisionat.test.php +++ b/_test/tests/inc/changelog_getlastrevisionat.test.php @@ -18,12 +18,8 @@ class changelog_getlastrevisionat_test extends DokuWikiTest { parent::setup(); global $cache_revinfo; $cache =& $cache_revinfo; - if(isset($cache['nonexist'])) { - unset($cache['nonexist']); - } - if(isset($cache['mailinglist'])) { - unset($cache['mailinglist']); - } + unset($cache['nonexist']); + unset($cache['mailinglist']); } diff --git a/_test/tests/inc/changelog_getrelativerevision.test.php b/_test/tests/inc/changelog_getrelativerevision.test.php index 4268e702f..b51aacdb2 100644 --- a/_test/tests/inc/changelog_getrelativerevision.test.php +++ b/_test/tests/inc/changelog_getrelativerevision.test.php @@ -18,12 +18,8 @@ class changelog_getrelativerevision_test extends DokuWikiTest { parent::setup(); global $cache_revinfo; $cache =& $cache_revinfo; - if(isset($cache['nonexist'])) { - unset($cache['nonexist']); - } - if(isset($cache['mailinglist'])) { - unset($cache['mailinglist']); - } + unset($cache['nonexist']); + unset($cache['mailinglist']); } /** diff --git a/_test/tests/inc/changelog_getrevisioninfo.test.php b/_test/tests/inc/changelog_getrevisioninfo.test.php index 3decad0ef..8003f61e2 100644 --- a/_test/tests/inc/changelog_getrevisioninfo.test.php +++ b/_test/tests/inc/changelog_getrevisioninfo.test.php @@ -19,12 +19,8 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest { parent::setup(); global $cache_revinfo; $cache =& $cache_revinfo; - if(isset($cache['nonexist'])) { - unset($cache['nonexist']); - } - if(isset($cache['mailinglist'])) { - unset($cache['mailinglist']); - } + unset($cache['nonexist']); + unset($cache['mailinglist']); } /** diff --git a/_test/tests/inc/changelog_getrevisions.test.php b/_test/tests/inc/changelog_getrevisions.test.php index 0bd378c3c..827240468 100644 --- a/_test/tests/inc/changelog_getrevisions.test.php +++ b/_test/tests/inc/changelog_getrevisions.test.php @@ -35,12 +35,10 @@ class changelog_getrevisions_test extends DokuWikiTest { parent::setup(); global $cache_revinfo; $cache =& $cache_revinfo; - if(isset($cache['nonexist'])) { - unset($cache['nonexist']); - } - if(isset($cache['mailinglist'])) { - unset($cache['mailinglist']); - } + unset($cache['nonexist']); + unset($cache['mailinglist']); + // fix filemtime of page source + touch(wikiFN($this->pageid), $this->revsexpected[0]); } /** diff --git a/_test/tests/inc/changelog_hasrevisions.test.php b/_test/tests/inc/changelog_hasrevisions.test.php index cace7b244..32f4fdf30 100644 --- a/_test/tests/inc/changelog_hasrevisions.test.php +++ b/_test/tests/inc/changelog_hasrevisions.test.php @@ -13,7 +13,7 @@ class changelog_hasrevisions_test extends DokuWikiTest { */ function test_hasrevisions() { $id = 'mailinglist'; - + $pagelog = new PageChangeLog($id); $result = $pagelog->hasRevisions(); $this->assertTrue($result); @@ -24,7 +24,7 @@ class changelog_hasrevisions_test extends DokuWikiTest { */ function test_norevisions() { $id = 'nonexist'; - + $pagelog = new PageChangeLog($id); $result = $pagelog->hasRevisions(); $this->assertFalse($result); diff --git a/_test/tests/inc/common_clientip.test.php b/_test/tests/inc/common_clientip.test.php index a546d4faf..212d8cfbc 100644 --- a/_test/tests/inc/common_clientip.test.php +++ b/_test/tests/inc/common_clientip.test.php @@ -201,6 +201,25 @@ class common_clientIP_test extends DokuWikiTest { $this->assertEquals($out, clientIP()); } + + // IPv6 + + function test_simple_single_ipv6(){ + $_SERVER['REMOTE_ADDR'] = '1234:1234:1234:1234:1234:1234:1234:1234'; + $_SERVER['HTTP_X_REAL_IP'] = ''; + $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; + $out = '1234:1234:1234:1234:1234:1234:1234:1234'; + $this->assertEquals($out, clientIP(true)); + } + + function test_proxyhops_garbage_all_ipv4_and_ipv6(){ + $_SERVER['REMOTE_ADDR'] = '1234:1234:1234:1234:1234:1234:1234:1234'; + $_SERVER['HTTP_X_REAL_IP'] = '1.1.1.1'; + $_SERVER['HTTP_X_FORWARDED_FOR'] = '777:777:777:777:777:777:777:777,::1,skipme,66.66.66.66'; + $out = '1234:1234:1234:1234:1234:1234:1234:1234,777:777:777:777:777:777:777:777,::1,66.66.66.66,1.1.1.1'; + $this->assertEquals($out, clientIP()); + } + } //Setup VIM: ex: et ts=4 : diff --git a/_test/tests/inc/common_mediainfo.test.php b/_test/tests/inc/common_mediainfo.test.php index 685a36be9..5127d1a7a 100644 --- a/_test/tests/inc/common_mediainfo.test.php +++ b/_test/tests/inc/common_mediainfo.test.php @@ -5,7 +5,7 @@ class common_basicinfo_test extends DokuWikiTest { function setup() : void { parent::setup(); - global $USERINFO; + global $USERINFO; $USERINFO = array( 'pass' => '179ad45c6ce2cb97cf1029e212046e81', 'name' => 'Arthur Dent', @@ -15,7 +15,7 @@ class common_basicinfo_test extends DokuWikiTest { $_SERVER['REMOTE_USER'] = 'testuser'; $_SERVER['REMOTE_ADDR'] = '1.2.3.4'; } - + function _get_info() { global $USERINFO; $info = array ( @@ -27,10 +27,10 @@ class common_basicinfo_test extends DokuWikiTest { 'ismobile' => false, 'client' => 'testuser', ); - + return $info; } - + /** * We're interested in the extra keys for $INFO when its a media request */ @@ -38,10 +38,10 @@ class common_basicinfo_test extends DokuWikiTest { global $NS, $IMG; $NS = ''; $IMG = 'testimage.png'; - + $info = $this->_get_info(); $info['image'] = 'testimage.png'; - + $this->assertEquals(mediainfo(),$info); } } diff --git a/_test/tests/inc/common_pageinfo.test.php b/_test/tests/inc/common_pageinfo.test.php index 47651240f..ac16b8561 100644 --- a/_test/tests/inc/common_pageinfo.test.php +++ b/_test/tests/inc/common_pageinfo.test.php @@ -51,7 +51,7 @@ class common_pageinfo_test extends DokuWikiTest { /** * check info keys and values for a non-existent page & admin user */ - function test_basic_nonexistentpage(){ + function test_basic_nonexistentpage() { global $ID,$conf; $ID = 'wiki:start'; @@ -66,12 +66,16 @@ class common_pageinfo_test extends DokuWikiTest { /** * check info keys and values for a existing page & admin user */ - function test_basic_existingpage(){ + function test_basic_existingpage() { global $ID,$conf; $ID = 'wiki:syntax'; $filename = $conf['datadir'].'/wiki/syntax.txt'; $rev = filemtime($filename); + // run once to prepare meta/wiki/syntax.change file for existing page + // because pageinfo() set $info['meta']['last_change'] entry + pageinfo(); + $info = $this->_get_expected_pageinfo(); $info['id'] = 'wiki:syntax'; $info['namespace'] = 'wiki'; @@ -80,6 +84,13 @@ class common_pageinfo_test extends DokuWikiTest { $info['lastmod'] = $rev; $info['currentrev'] = $rev; $info['meta'] = p_get_metadata($ID); + // set from revinfo, $pagelog->getRevisionInfo($info['lastmod']) + $info = array_merge($info, array( + 'ip' => '127.0.0.1', + 'user' => '', + 'sum' => 'created - external edit', + )); + $info['editor'] = '127.0.0.1'; $this->assertEquals($info, pageinfo()); } @@ -87,7 +98,7 @@ class common_pageinfo_test extends DokuWikiTest { /** * check info keys and values for anonymous user */ - function test_anonymoususer(){ + function test_anonymoususer() { global $ID,$conf,$REV; unset($_SERVER['REMOTE_USER']); @@ -106,7 +117,15 @@ class common_pageinfo_test extends DokuWikiTest { $info['currentrev'] = $rev; $info['meta'] = p_get_metadata($ID); $info['rev'] = ''; + // set from revinfo, $pagelog->getRevisionInfo($info['lastmod']) + $info = array_merge($info, array( + 'ip' => '127.0.0.1', + 'user' => '', + 'sum' => 'created - external edit', + )); + $info['editor'] = '127.0.0.1'; + // anonymous user $info = array_merge($info, array( 'isadmin' => false, 'ismanager' => false, @@ -114,6 +133,7 @@ class common_pageinfo_test extends DokuWikiTest { 'client' => '1.2.3.4', )); unset($info['userinfo']); + $this->assertEquals($info, pageinfo()); } @@ -121,7 +141,7 @@ class common_pageinfo_test extends DokuWikiTest { * check info keys and values with $REV * (also see $RANGE tests) */ - function test_rev(){ + function test_rev() { global $ID,$conf,$REV; $ID = 'wiki:syntax'; @@ -129,7 +149,8 @@ class common_pageinfo_test extends DokuWikiTest { $rev = filemtime($filename); $REV = $rev - 100; $ext = '.txt'; - if($conf['compression']) { //compression in $info['filepath'] determined by wikiFN depends also on if the page exist + if ($conf['compression']) { + //compression in $info['filepath'] determined by wikiFN depends also on if the page exist $ext .= "." . $conf['compression']; //.gz or .bz2 } @@ -148,7 +169,7 @@ class common_pageinfo_test extends DokuWikiTest { /** * check info keys and values with $RANGE */ - function test_range(){ + function test_range() { global $ID,$conf,$REV,$RANGE; $ID = 'wiki:syntax'; @@ -164,6 +185,13 @@ class common_pageinfo_test extends DokuWikiTest { $info['currentrev'] = $rev; $info['meta'] = p_get_metadata($ID); $info['filepath'] = $filename; + // set from revinfo, $pagelog->getRevisionInfo($info['lastmod']) + $info = array_merge($info, array( + 'ip' => '127.0.0.1', + 'user' => '', + 'sum' => 'created - external edit', + )); + $info['editor'] = '127.0.0.1'; // check $RANGE without $REV // expected result $RANGE unchanged @@ -171,7 +199,7 @@ class common_pageinfo_test extends DokuWikiTest { $this->assertEquals($info, pageinfo()); $this->assertFalse(isset($REV)); - $this->assertEquals($range,$RANGE); + $this->assertEquals($range, $RANGE); // check $RANGE with $REV = current // expected result: $RANGE unchanged, $REV cleared @@ -180,21 +208,21 @@ class common_pageinfo_test extends DokuWikiTest { $this->assertEquals($info, pageinfo()); $this->assertEquals('',$REV); - $this->assertEquals($range,$RANGE); + $this->assertEquals($range, $RANGE); // check with a real $REV // expected result: $REV and $RANGE are cleared $REV = $rev - 100; $this->assertEquals($info, pageinfo()); - $this->assertEquals('',$REV); - $this->assertEquals('',$RANGE); + $this->assertEquals('', $REV); + $this->assertEquals('', $RANGE); } /** * test editor entry and external edit */ - function test_editor_and_externaledits(){ + function test_editor_and_externaledits() { global $ID,$conf; $ID = 'wiki:syntax'; $filename = $conf['datadir'].'/wiki/syntax.txt'; @@ -216,24 +244,24 @@ class common_pageinfo_test extends DokuWikiTest { addLogEntry($rev, $ID); $info['meta'] = p_get_metadata($ID); - $info['editor'] = $_SERVER['REMOTE_USER']; - $info['user'] = $_SERVER['REMOTE_USER']; $info['ip'] = $_SERVER['REMOTE_ADDR']; + $info['user'] = $_SERVER['REMOTE_USER']; $info['sum'] = ''; + $info['editor'] = $info['user']; // with an editor ... $this->assertEquals($info, pageinfo()); // clear the meta['last_change'] value, pageinfo should restore it - p_set_metadata($ID,array('last_change' => false)); + p_set_metadata($ID, array('last_change' => false)); $this->assertEquals($info, pageinfo()); $this->assertEquals($info['meta']['last_change'], p_get_metadata($ID,'last_change')); // fake an external edit, pageinfo should clear the last change from meta data // and not return any editor data - $now = time()+10; - touch($filename,$now); + $now = time() + 10; + touch($filename, $now); $info['lastmod'] = $now; $info['currentrev'] = $now; @@ -250,12 +278,16 @@ class common_pageinfo_test extends DokuWikiTest { /** * check draft */ - function test_draft(){ + function test_draft() { global $ID,$conf; $ID = 'wiki:syntax'; $filename = $conf['datadir'].'/wiki/syntax.txt'; $rev = filemtime($filename); + // run once to prepare meta/wiki/syntax.change file for existing page + // because pageinfo() set $info['meta']['last_change'] entry + pageinfo(); + $info = $this->_get_expected_pageinfo(); $info['id'] = 'wiki:syntax'; $info['namespace'] = 'wiki'; @@ -264,11 +296,23 @@ class common_pageinfo_test extends DokuWikiTest { $info['lastmod'] = $rev; $info['currentrev'] = $rev; $info['meta'] = p_get_metadata($ID); +// $info['ip'] = $_SERVER['REMOTE_ADDR']; +// $info['user'] = $_SERVER['REMOTE_USER']; +// $info['sum'] = ''; +// $info['editor'] = $info['user']; + // set from revinfo, $pagelog->getRevisionInfo($info['lastmod']) + $info = array_merge($info, array( + 'ip' => '127.0.0.1', + 'user' => '', + 'sum' => 'external edit', + )); + $info['editor'] = '127.0.0.1'; // setup a draft, make it more recent than the current page // - pageinfo should recognise it and keep it - $draft = getCacheName($info['client'].$ID,'.draft'); - touch($draft,$rev + 10); + + $draft = getCacheName($info['client']."\n".$ID,'.draft'); + touch($draft, $rev + 10); $info['draft'] = $draft; @@ -287,7 +331,7 @@ class common_pageinfo_test extends DokuWikiTest { /** * check ismobile */ - function test_ismobile(){ + function test_ismobile() { global $ID,$conf; $ID = 'wiki:start'; diff --git a/_test/tests/inc/common_saveWikiText.test.php b/_test/tests/inc/common_saveWikiText.test.php index 7ae12ca27..80d3e55f4 100644 --- a/_test/tests/inc/common_saveWikiText.test.php +++ b/_test/tests/inc/common_saveWikiText.test.php @@ -2,7 +2,11 @@ use dokuwiki\ChangeLog\PageChangeLog; +/** + * saveWikiText() stores files in pages/, attic/ and adds entries to changelog + */ class common_saveWikiText_test extends DokuWikiTest { + /** Delay writes of old revisions by a second. */ public function handle_write(Doku_Event $event, $param) { if ($event->data[3] !== false) { @@ -11,161 +15,266 @@ class common_saveWikiText_test extends DokuWikiTest { } /** + * assertions against changelog entries and attic after saveWikiText() + */ + private function checkChangeLogAfterNormalSave( + PageChangeLog $pagelog, + $expectedRevs, // @param int + &$expectedLastEntry, // @param array, pass by reference + $expected2ndLastEntry = null // @param array (optional) + ) { + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertCount($expectedRevs, $revisions); + $this->assertCount($expectedRevs, array_unique($revisions), 'date duplicated in changelog'); + // last revision + $lastRevInfo = $pagelog->getRevisionInfo($revisions[0]); + $expectedLastEntry += $lastRevInfo; + $this->assertEquals($expectedLastEntry, $lastRevInfo); + // current revision + $currentRevInfo = $pagelog->getCurrentRevisionInfo(); + $this->assertEquals($currentRevInfo, $lastRevInfo, 'current & last revs should be identical'); + // attic + $attic = wikiFN($lastRevInfo['id'], $lastRevInfo['date']); + $this->assertFileExists($attic, 'file missing in attic'); + $files = count(glob(dirname($attic).'/'.noNS($lastRevInfo['id']).'.*')); + $this->assertLessThanOrEqual($expectedRevs, $files, 'detectExternalEdit() should not add too often old revs'); + + // second to last revision (optional), intended to check logline of previous external edits + if ($expected2ndLastEntry && count($revisions) > 1) { + $prevRevInfo = $pagelog->getRevisionInfo($revisions[1]); + unset($expected2ndLastEntry['timestamp']); // drop timestamp key + $this->assertEquals($expected2ndLastEntry, $prevRevInfo); + } + } + + /** + * assertions against changelog entries and attic after external edit, create or deletion of page + */ + private function checkChangeLogAfterExternalEdit( + PageChangeLog $pagelog, + $expectedRevs, // @param int + $expectedLastEntry, // @param array + &$expectedCurrentEntry // @param array, pass by reference + ) { + $revisions = $pagelog->getRevisions(-1, 200); + $this->assertCount($expectedRevs, $revisions); + $this->assertCount($expectedRevs, array_unique($revisions), 'date duplicated in changelog'); + // last revision + if ($expectedRevs > 0) { + $lastRevInfo = $pagelog->getRevisionInfo($revisions[0]); + $expectedLastEntry += $lastRevInfo; + $this->assertEquals($expectedLastEntry, $lastRevInfo); + } else { + $this->assertFalse($pagelog->lastRevision(), 'changelog file does not yet exist'); + } + // current revision + $currentRevInfo = $pagelog->getCurrentRevisionInfo(); + $this->assertArrayHasKey('timestamp', $currentRevInfo, 'should be external revision'); + $expectedCurrentEntry += $currentRevInfo; + if ($expectedRevs > 0) { + $this->assertEquals($expectedCurrentEntry, $currentRevInfo); + + } + // attic + $attic = wikiFN($currentRevInfo['id'], $currentRevInfo['date']); + $this->assertFileNotExists($attic, 'page does not yet exist in attic'); + } + + + /** * Execute a whole bunch of saves on the same page and check the results + * TEST 1 + * 1.1 create a page + * 1.2 save with same content should be ignored + * 1.3 update the page with new text + * 1.4 add a minor edit (unauthenticated, minor not allowable) + * 1.5 add a minor edit (authenticated) + * 1.6 delete + * 1.7 restore + * 1.8 external edit + * 1.9 edit and save on top of external edit */ - function test_savesequence() { + function test_savesequence1() { global $REV; $page = 'page'; $file = wikiFN($page); - - // create the page $this->assertFileNotExists($file); - saveWikiText($page, 'teststring', 'first save', false); + + // 1.1 create a page + saveWikiText($page, 'teststring', '1st save', false); + clearstatcache(false, $file); $this->assertFileExists($file); $lastmod = filemtime($file); + $expectedRevs = 1; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => '1st save', + 'sizechange' => 10, // = strlen('teststring') + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(1, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('first save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); - $this->assertEquals(10, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(true); // wait for new revision ID - // save with same content should be ignored - saveWikiText($page, 'teststring', 'second save', false); + // 1.2 save with same content should be ignored + saveWikiText($page, 'teststring', '2nd save', false); clearstatcache(false, $file); $this->assertEquals($lastmod, filemtime($file)); $pagelog = new PageChangeLog($page); $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(1, count($revisions)); + $this->assertCount(1, $revisions); - // update the page with new text - saveWikiText($page, 'teststring2long', 'third save', false); + // 1.3 update the page with new text + saveWikiText($page, 'teststring2long', '3rd save', false); clearstatcache(false, $file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; + $expectedRevs = 2; + $expectPrev = $expect; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => '3rd save', + 'sizechange' => 5, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(2, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('third save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(5, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectPrev); $this->waitForTick(); // wait for new revision ID - // add a minor edit (unauthenticated) - saveWikiText($page, 'teststring3long', 'fourth save', true); + // 1.4 add a minor edit (unauthenticated, minor not allowable) + saveWikiText($page, 'teststring3long', '4th save', true); clearstatcache(false, $file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; + $expectedRevs = 3; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => '4th save', + 'sizechange' => 0, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(3, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('fourth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(0, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(); // wait for new revision ID - // add a minor edit (authenticated) + // 1.5 add a minor edit (authenticated) $_SERVER['REMOTE_USER'] = 'user'; - saveWikiText($page, 'teststring4', 'fifth save', true); + saveWikiText($page, 'teststring4', '5th save', true); clearstatcache(false, $file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; + $expectedRevs = 4; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_MINOR_EDIT, + 'sum' => '5th save', + 'sizechange' => -4, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(4, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('fifth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_MINOR_EDIT, $revinfo['type']); - $this->assertEquals(-4, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(); // wait for new revision ID - // delete - saveWikiText($page, '', 'sixth save', false); + // 1.6 delete + saveWikiText($page, '', '6th save', false); clearstatcache(false, $file); $this->assertFileNotExists($file); + $expectedRevs = 5; + $expect = array( + //'date' => $lastmod, // ignore from lastRev assertion, but confirm attic file existence + 'type' => DOKU_CHANGE_TYPE_DELETE, + 'sum' => '6th save', + 'sizechange' => -11, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(5, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('sixth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_DELETE, $revinfo['type']); - $this->assertEquals(-11, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(); // wait for new revision ID - // restore + // 1.7 restore $REV = $lastmod; - saveWikiText($page, 'teststring4', 'seventh save', true); + saveWikiText($page, 'teststring4', '7th save', true); clearstatcache(false, $file); $this->assertFileExists($file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; + $expectedRevs = 6; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_REVERT, + 'sum' => '7th save', + 'sizechange' => 11, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(6, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('seventh save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_REVERT, $revinfo['type']); - $this->assertEquals($REV, $revinfo['extra']); - $this->assertEquals(11, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $REV = ''; $this->waitForTick(); // wait for new revision ID - // create external edit - file_put_contents($file, 'teststring5'); + // 1.8 external edit + file_put_contents($file, 'teststring5 external edit'); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 6; // external edit is not yet in changelog + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'external edit', + 'sizechange' => 14, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); $this->waitForTick(); // wait for new revision ID - // save on top of external edit - saveWikiText($page, 'teststring6', 'eigth save', false); + // 1.9 save on top of external edit + saveWikiText($page, 'teststring6', '8th save', false); clearstatcache(false, $file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; + $expectedRevs = 8; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => '8th save', + 'sizechange' => -14, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(8, count($revisions)); // two more revisions now! - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('eigth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(0, $revinfo['sizechange']); - - $revinfo = $pagelog->getRevisionInfo($revisions[1]); - $this->assertEquals('external edit', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(0, $revinfo['sizechange']); - + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); } /** * Execute a whole bunch of saves on the same page and check the results + * using $this->handle_write() in event IO_WIKIPAGE_WRITE + * TEST 2 - create a page externally in 2.3, while external edit in Test 1.8 + * 2.1 create a page + * 2.2 delete + * 2.3 externally create the page + * 2.4 edit and save on top of external edit + * 2.5 external edit + * 2.6 edit and save on top of external edit, again */ - function test_savesequencedeleteexternalrevision() { + function test_savesequence2() { // add an additional delay when saving files to make sure // nobody relies on the saving happening in the same second /** @var $EVENT_HANDLER \dokuwiki\Extension\EventHandler */ @@ -174,251 +283,405 @@ class common_saveWikiText_test extends DokuWikiTest { $page = 'page2'; $file = wikiFN($page); - - // create the page $this->assertFileNotExists($file); - saveWikiText($page, 'teststring', 'first save', false); + + // 2.1 create a page + saveWikiText($page, 'teststring', 'Test 2, 1st save', false); + clearstatcache(false, $file); $this->assertFileExists($file); $lastmod = filemtime($file); + $expectedRevs = 1; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'Test 2, 1st save', + 'sizechange' => 10, // = strlen('teststring') + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(1, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('first save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); - $this->assertEquals(10, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(true); // wait for new revision ID - // delete - saveWikiText($page, '', 'second save', false); + // 2.2 delete + saveWikiText($page, '', 'Test 2, 2nd save', false); clearstatcache(false, $file); $this->assertFileNotExists($file); + $expectedRevs = 2; + $expect = array( + //'date' => $lastmod, // ignore from lastRev assertion, but confirm attic file existence + 'type' => DOKU_CHANGE_TYPE_DELETE, + 'sum' => 'Test 2, 2nd save', + 'sizechange' => -10, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(2, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('second save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_DELETE, $revinfo['type']); - $this->assertEquals(-10, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(); // wait for new revision ID - // create external edit + // 2.3 externally create the page file_put_contents($file, 'teststring5'); + clearstatcache(false, $file); + $lastmod = filemtime($file); + $expectedRevs = 2; // external edit is not yet in changelog + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'created - external edit', + 'sizechange' => 11, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); $this->waitForTick(); // wait for new revision ID - // save on top of external edit - saveWikiText($page, 'teststring6', 'third save', false); + // 2.4 save on top of external edit + saveWikiText($page, 'teststring6', 'Test 2, 3rd save', false); clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 4; // two more revisions now! + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'Test 2, 3rd save', + 'sizechange' => 0, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(4, count($revisions)); // two more revisions now! - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('third save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(0, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); - - $revinfo = $pagelog->getRevisionInfo($revisions[1]); - $this->assertEquals('external edit', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(11, $revinfo['sizechange']); - $this->assertFileExists(wikiFN($page, $revinfo['date'])); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); + + $this->waitForTick(); // wait for new revision ID + + // 2.5 external edit + file_put_contents($file, 'teststring7 external edit2'); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 4; // external edit is not yet in changelog + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'external edit', + 'sizechange' => 15, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); + + $this->waitForTick(); // wait for new revision ID + // 2.6 save on top of external edit, again + saveWikiText($page, 'teststring8', 'Test 2, 4th save', false); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 6; // two more revisions now! + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'Test 2, 4th save', + 'sizechange' => -15, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); } /** * Execute a whole bunch of saves on the same page and check the results + * TEST 3 - typical page life of bundled page such as wiki:syntax + * 3.1 externally create a page + * 3.2 external edit + * 3.3 edit and save on top of external edit + * 3.4 externally delete the page */ - function test_saveexternalasfirst() { + function test_savesequence3() { $page = 'page3'; $file = wikiFN($page); - // create the page + // 3.1 externally create a page $this->assertFileNotExists($file); - - // create external edit file_put_contents($file, 'teststring'); + clearstatcache(false, $file); + $lastmod = filemtime($file); + $expectedRevs = 0; // external edit is not yet in changelog + $expect = false; + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'created - external edit', + 'sizechange' => 10, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); $this->waitForTick(true); // wait for new revision ID - // save on top of external edit - saveWikiText($page, 'teststring6', 'first save', false); + // 3.2 external edit (repeated, still no changelog exists) + file_put_contents($file, 'teststring external edit'); clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 0; // external edit is not yet in changelog + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, // not DOKU_CHANGE_TYPE_EDIT + 'sum' => 'created - external edit', + 'sizechange' => 24, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(2, count($revisions)); // two more revisions now! - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('first save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(1, $revinfo['sizechange']); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); - $revinfo = $pagelog->getRevisionInfo($revisions[1]); - $this->assertEquals('external edit', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(10, $revinfo['sizechange']); + $this->waitForTick(true); // wait for new revision ID + + // 3.3 save on top of external edit + saveWikiText($page, 'teststring1', 'Test 3, first save', false); + clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 2; // two more revisions now! + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'Test 3, first save', + 'sizechange' => -13, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); + + $this->waitForTick(true); // wait for new revision ID + + // 3.4 externally delete the page + unlink($file); + $expectedRevs = 2; + $expectExternal = array( + //'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_DELETE, + 'sum' => 'removed - external edit (Unknown date)', + 'sizechange' => -11, + ); + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); } /** * Execute a whole bunch of saves on the same page and check the results + * TEST 4 - typical page life of bundled page such as wiki:syntax + * 4.1 externally create a page + * 4.2 edit and save + * 4.3 externally edit as a result of a file which has older timestamp than last revision */ - function test_savesequenceexternaldeleteedit() { + function test_savesequence4() { $page = 'page4'; $file = wikiFN($page); - // create the page + // 4.1 externally create a page $this->assertFileNotExists($file); - saveWikiText($page, 'teststring', 'first save', false); - $this->assertFileExists($file); + file_put_contents($file, 'teststring'); + clearstatcache(false, $file); $lastmod = filemtime($file); + $expectedRevs = 0; // external edit is not yet in changelog + $expect = false; + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'created - external edit', + 'sizechange' => 10, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(1, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('first save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); - $this->assertEquals(10, $revinfo['sizechange']); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); $this->waitForTick(true); // wait for new revision ID - - // create external delete - unlink($file); - clearstatcache(false, $file); - - $this->waitForTick(); // wait for new revision ID - - // save on top of external delete. save is seen as creation - saveWikiText($page, 'teststring6', 'second save', false); + // 4.2 edit and save + saveWikiText($page, 'teststring1', 'Test 4, first save', false); clearstatcache(false, $file); + $newmod = filemtime($file); + $this->assertNotEquals($lastmod, $newmod); + $lastmod = $newmod; + $expectedRevs = 2; // two more revisions now! + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'Test 4, first save', + 'sizechange' => 1, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(2, count($revisions)); // one more revisions now! - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('second save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); - $this->assertEquals(11, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); - $revinfo = $pagelog->getRevisionInfo($revisions[1]); - $this->assertEquals('first save', $revinfo['sum']); + $this->waitForTick(true); // wait for new revision ID + // 4.3 externally edit as a result of a file which has older timestamp than last revision + unlink($file); + file_put_contents($file, 'teststring fake 1 hout past'); + touch($file, filemtime($file) -3600); // change file modification time to 1 hour past + clearstatcache(); + $newmod = filemtime($file); + $this->assertLessThan($lastmod, $newmod); // file must be older than previous for this test + $expectedRevs = 2; // external edit is not yet in changelog + $expectExternal = array( + 'date' => $lastmod + 1, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'external edit (Unknown date)', + 'sizechange' => 16, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); } /** * Execute a whole bunch of saves on the same page and check the results + * TEST 5 - page creation and deletion + * 5.1 create a page + * 5.2 external edit + * 5.3 edit and save on top of external edit + * 5.4 delete + * 5.5 create a page, second time + * 5.6 externally delete + * 5.7 create a page, third time */ - function test_savesequencerevert() { - global $REV; - + function test_savesequence5() { $page = 'page5'; $file = wikiFN($page); - - // create the page $this->assertFileNotExists($file); - saveWikiText($page, 'teststring', 'first save', false); + + // 5.1 create a page + saveWikiText($page, 'teststring', 'Test 5, 1st save', false); $this->assertFileExists($file); $lastmod = filemtime($file); + $expectedRevs = 1; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'Test 5, 1st save', + 'sizechange' => 10, // = strlen('teststring') + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(1, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('first save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_CREATE, $revinfo['type']); - $this->assertEquals(10, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(true); // wait for new revision ID - // save with same content should be ignored - saveWikiText($page, 'teststring', 'second save', false); - clearstatcache(false, $file); - $this->assertEquals($lastmod, filemtime($file)); - - $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(1, count($revisions)); - - // update the page with new text - saveWikiText($page, 'teststring2long', 'third save', false); + // 5.2 external edit + file_put_contents($file, 'teststring external edit'); clearstatcache(false, $file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; - $revertrev = $newmod; + $expectedRevs = 1; // external edit is not yet in changelog + $expectExternal = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'external edit', + 'sizechange' => 14, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(2, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('third save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(5, $revinfo['sizechange']); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); $this->waitForTick(); // wait for new revision ID - // add a minor edit (unauthenticated) - saveWikiText($page, 'teststring3long', 'fourth save', true); + // 5.3 edit and save on top of external edit + saveWikiText($page, 'teststring normal edit', 'Test 5, 2nd save', false); clearstatcache(false, $file); $newmod = filemtime($file); $this->assertNotEquals($lastmod, $newmod); $lastmod = $newmod; + $expectedRevs = 3; // two more revisions now! + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_EDIT, + 'sum' => 'Test 5, 2nd save', + 'sizechange' => -2, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(3, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('fourth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_EDIT, $revinfo['type']); - $this->assertEquals(0, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); $this->waitForTick(); // wait for new revision ID - // add a minor edit (authenticated) - $_SERVER['REMOTE_USER'] = 'user'; - saveWikiText($page, 'teststring4', 'fifth save', true); + // 5.4 delete + saveWikiText($page, '', 'Test 5 3rd save', false); clearstatcache(false, $file); - $newmod = filemtime($file); - $this->assertNotEquals($lastmod, $newmod); - $lastmod = $newmod; + $this->assertFileNotExists($file); + $expectedRevs = 4; + $expect = array( + //'date' => $lastmod, // ignore from lastRev assertion, but confirm attic file existence + 'type' => DOKU_CHANGE_TYPE_DELETE, + 'sum' => 'Test 5 3rd save', + 'sizechange' => -22, + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(4, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('fifth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_MINOR_EDIT, $revinfo['type']); - $this->assertEquals(-4, $revinfo['sizechange']); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); $this->waitForTick(); // wait for new revision ID - // restore - $REV = $revertrev; - saveWikiText($page, 'teststring2long', 'sixth save', true); + // 5.5 create a page, second time + $this->assertFileNotExists($file); + saveWikiText($page, 'teststring revived', 'Test 5, 4th save', false); + $this->assertFileExists($file); + $lastmod = filemtime($file); + $expectedRevs = 5; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'Test 5, 4th save', + 'sizechange' => 18, // = strlen('teststring revived') + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect); + + $this->waitForTick(true); // wait for new revision ID + + // 5.6 externally delete + unlink($file); + $this->assertFileNotExists($file); + $expectedRevs = 5; + $expectExternal = array( + //'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_DELETE, + 'sum' => 'removed - external edit (Unknown date)', + 'sizechange' => -18, + ); + + $pagelog = new PageChangeLog($page); + $this->checkChangeLogAfterExternalEdit($pagelog, $expectedRevs, $expect, $expectExternal); + + $this->waitForTick(true); // wait for new revision ID + + // 5.7 create a page, third time + $this->assertFileNotExists($file); + saveWikiText($page, 'teststring revived 2', 'Test 5, 5th save', false); clearstatcache(false, $file); $this->assertFileExists($file); - $newmod = filemtime($file); - $this->assertNotEquals($lastmod, $newmod); + $lastmod = filemtime($file); + $expectedRevs = 7; + $expect = array( + 'date' => $lastmod, + 'type' => DOKU_CHANGE_TYPE_CREATE, + 'sum' => 'Test 5, 5th save', + 'sizechange' => 20, // = strlen('teststring revived 2') + ); $pagelog = new PageChangeLog($page); - $revisions = $pagelog->getRevisions(-1, 200); - $this->assertEquals(5, count($revisions)); - $revinfo = $pagelog->getRevisionInfo($revisions[0]); - $this->assertEquals('sixth save', $revinfo['sum']); - $this->assertEquals(DOKU_CHANGE_TYPE_REVERT, $revinfo['type']); - $this->assertEquals($REV, $revinfo['extra']); - $this->assertEquals(4, $revinfo['sizechange']); - $REV = ''; + $this->checkChangeLogAfterNormalSave($pagelog, $expectedRevs, $expect, $expectExternal); } } diff --git a/_test/tests/inc/indexer_indexing.test.php b/_test/tests/inc/indexer_indexing.test.php index 8c28cfb63..ce1ed5e5e 100644 --- a/_test/tests/inc/indexer_indexing.test.php +++ b/_test/tests/inc/indexer_indexing.test.php @@ -76,4 +76,4 @@ class indexer_indexing_test extends DokuWikiTest { sort($result); $this->assertEquals(array('0'), $result); } -}
\ No newline at end of file +} diff --git a/_test/tests/inc/ixr_library_date.test.php b/_test/tests/inc/ixr_library_date.test.php deleted file mode 100644 index 0c81e6741..000000000 --- a/_test/tests/inc/ixr_library_date.test.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -require_once DOKU_INC.'inc/IXR_Library.php'; - -/** - * Class ixr_library_date_test - */ -class ixr_library_date_test extends DokuWikiTest { - - - function test_parseIso(){ - // multiple tests - $tests = array( - // full datetime, different formats - array('2010-08-17T09:23:14', 1282036994), - array('20100817T09:23:14', 1282036994), - array('2010-08-17 09:23:14', 1282036994), - array('20100817 09:23:14', 1282036994), - array('2010-08-17T09:23:14Z', 1282036994), - array('20100817T09:23:14Z', 1282036994), - - // with timezone - array('2010-08-17 09:23:14+0000', 1282036994), - array('2010-08-17 09:23:14+00:00', 1282036994), - array('2010-08-17 12:23:14+03:00', 1282036994), - - // no seconds - array('2010-08-17T09:23', 1282036980), - array('20100817T09:23', 1282036980), - - // no time - array('2010-08-17', 1282003200), - array(1282036980, 1282036980), -// array('20100817', 1282003200), #this will NOT be parsed, but is assumed to be timestamp - ); - - foreach($tests as $test){ - $dt = new IXR_Date($test[0]); - $this->assertEquals($test[1], $dt->getTimeStamp()); - } - } - -} -//Setup VIM: ex: et ts=4 : diff --git a/_test/tests/inc/ixr_library_ixr_message.test.php b/_test/tests/inc/ixr_library_ixr_message.test.php deleted file mode 100644 index b8afd607e..000000000 --- a/_test/tests/inc/ixr_library_ixr_message.test.php +++ /dev/null @@ -1,134 +0,0 @@ -<?php - -class ixr_library_ixr_message_test extends DokuWikiTest { - - function test_untypedvalue1(){ - $xml = '<?xml version="1.0" encoding="UTF-8"?><methodCall><methodName>wiki.getBackLinks</methodName><params><param><value> change </value></param></params></methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.getBackLinks'); - $this->assertEquals($ixrmsg->params,array(' change ')); - } - - function test_untypedvalue2(){ - $xml = '<?xml version="1.0" encoding="UTF-8"?> - <methodCall> - <methodName>wiki.getBackLinks</methodName> - <params> - <param> - <value> change </value> - </param> - </params> - </methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.getBackLinks'); - $this->assertEquals($ixrmsg->params,array(' change ')); - } - - function test_stringvalue1(){ - $xml = '<?xml version="1.0" encoding="UTF-8"?><methodCall><methodName>wiki.getBackLinks</methodName><params><param><value><string> change </string></value></param></params></methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.getBackLinks'); - $this->assertEquals($ixrmsg->params,array(' change ')); - } - - function test_stringvalue2(){ - $xml = '<?xml version="1.0" encoding="UTF-8"?> - <methodCall> - <methodName>wiki.getBackLinks</methodName> - <params> - <param> - <value> - <string> change </string> - </value> - </param> - </params> - </methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.getBackLinks'); - $this->assertEquals($ixrmsg->params,array(' change ')); - } - - function test_emptyvalue1(){ - $xml = '<?xml version="1.0" encoding="UTF-8"?><methodCall><methodName>wiki.getBackLinks</methodName><params><param><value><string></string></value></param></params></methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.getBackLinks'); - $this->assertEquals($ixrmsg->params,array('')); - } - - function test_emptyvalue2(){ - $xml = '<?xml version="1.0" encoding="UTF-8"?> - <methodCall> - <methodName>wiki.getBackLinks</methodName> - <params> - <param> - <value> - <string></string> - </value> - </param> - </params> - </methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.getBackLinks'); - $this->assertEquals($ixrmsg->params,array('')); - } - - function test_struct(){ - $xml = '<?xml version=\'1.0\'?> - <methodCall> - <methodName>wiki.putPage</methodName> - <params> - <param> - <value><string>start</string></value> - </param> - <param> - <value><string>test text</string></value> - </param> - <param> - <value><struct> - <member> - <name>sum</name> - <value><string>xmlrpc edit</string></value> - </member> - <member> - <name>minor</name> - <value><string>1</string></value> - </member> - </struct></value> - </param> - </params> - </methodCall>'; - - $ixrmsg = new IXR_Message($xml); - $ixrmsg->parse(); - - $this->assertEquals($ixrmsg->messageType,'methodCall'); - $this->assertEquals($ixrmsg->methodName,'wiki.putPage'); - $this->assertEquals($ixrmsg->params,array('start','test text',array('sum'=>'xmlrpc edit','minor'=>'1'))); - } - -} -//Setup VIM: ex: et ts=4 : diff --git a/_test/tests/inc/media_searchlist.test.php b/_test/tests/inc/media_searchlist.test.php index 234c2f521..2163aa196 100644 --- a/_test/tests/inc/media_searchlist.test.php +++ b/_test/tests/inc/media_searchlist.test.php @@ -28,7 +28,7 @@ class media_searchlist_test extends DokuWikiTest function setUp() : void { parent::setUp(); - + //create some files to search $png = mediaFN('wiki:kind_zu_katze.png'); $ogv = mediaFN('wiki:kind_zu_katze.ogv'); diff --git a/_test/tests/inc/pageutils_resolve_pageid.test.php b/_test/tests/inc/pageutils_resolve_pageid.test.php index 41a441658..f8486e74e 100644 --- a/_test/tests/inc/pageutils_resolve_pageid.test.php +++ b/_test/tests/inc/pageutils_resolve_pageid.test.php @@ -57,22 +57,4 @@ class init_resolve_pageid_test extends DokuWikiTest { } } - /** - * Empty page on homepage should resolve to start page - */ - function test_resolve_pageid_empty_homepage() { - global $ID; - $ID = ''; - global $conf; - $conf['start'] = 'someverystrangestartname'; - - $ns = ''; - $page = ''; - $exist = true; - - resolve_pageid($ns, $page, $exist); - $this->assertEquals($page, $conf['start']); - } - } -//Setup VIM: ex: et ts=4 : diff --git a/_test/tests/inc/parser/parser_code.test.php b/_test/tests/inc/parser/parser_code.test.php index c700ed10a..bcb5a86f8 100644 --- a/_test/tests/inc/parser/parser_code.test.php +++ b/_test/tests/inc/parser/parser_code.test.php @@ -353,4 +353,3 @@ class TestOfDoku_Parser_Code extends TestOfDoku_Parser { } } - diff --git a/_test/tests/inc/parser/parser_file.test.php b/_test/tests/inc/parser/parser_file.test.php index 23aa8ef5b..11417eb26 100644 --- a/_test/tests/inc/parser/parser_file.test.php +++ b/_test/tests/inc/parser/parser_file.test.php @@ -56,4 +56,3 @@ class TestOfDoku_Parser_File extends TestOfDoku_Parser { } } - diff --git a/_test/tests/inc/parser/parser_footnote.test.php b/_test/tests/inc/parser/parser_footnote.test.php index d7b78cb64..d2c9b11a8 100644 --- a/_test/tests/inc/parser/parser_footnote.test.php +++ b/_test/tests/inc/parser/parser_footnote.test.php @@ -398,4 +398,3 @@ class TestOfDoku_Parser_Footnote extends TestOfDoku_Parser { $this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls); } } - diff --git a/_test/tests/inc/parser/parser_media.test.php b/_test/tests/inc/parser/parser_media.test.php index fdb9c0fc4..edb635acd 100644 --- a/_test/tests/inc/parser/parser_media.test.php +++ b/_test/tests/inc/parser/parser_media.test.php @@ -136,12 +136,12 @@ class TestOfDoku_Parser_Media extends TestOfDoku_Parser { function testVideoInternalTitle() { $file = 'wiki:kind_zu_katze.ogv'; $title = 'Single quote: \' Ampersand: &'; - + $Renderer = new Doku_Renderer_xhtml(); $url = $Renderer->externalmedia($file, $title, null, null, null, 'cache', 'details', true); - + // make sure the title is escaped just once - $this->assertEquals(htmlspecialchars($title), substr($url, 28, 32)); + $this->assertEquals(hsc($title), substr($url, 28, 37)); } function testSimpleLinkText() { diff --git a/_test/tests/inc/parser/parser_quotes.test.php b/_test/tests/inc/parser/parser_quotes.test.php index 73291c201..601cd37f0 100644 --- a/_test/tests/inc/parser/parser_quotes.test.php +++ b/_test/tests/inc/parser/parser_quotes.test.php @@ -359,4 +359,3 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser { } } - diff --git a/_test/tests/inc/remote.test.php b/_test/tests/inc/remote.test.php index efe18d7ef..39d3c62a1 100644 --- a/_test/tests/inc/remote.test.php +++ b/_test/tests/inc/remote.test.php @@ -7,7 +7,7 @@ use dokuwiki\Remote\RemoteException; class RemoteAPICoreTest { - function __getRemoteInfo() { + function getRemoteInfo() { return array( 'wiki.stringTestMethod' => array( 'args' => array(), diff --git a/_test/tests/inc/sort_without_collator.test.php b/_test/tests/inc/sort_without_collator.test.php index f882a67e8..8451a3f4d 100644 --- a/_test/tests/inc/sort_without_collator.test.php +++ b/_test/tests/inc/sort_without_collator.test.php @@ -108,7 +108,7 @@ class sort_without_collator_test extends sort_with_collator_test /** * Provide WRONG sorted sequences of all characters used in the languages * being tested, as the fallback sort simply follows character codes. - * + * * The sorted sequences given in class "sort_with_collator" are simply * reordered here, starting with A-Z and continuing with accented characters * ordered by character codes. diff --git a/_test/tests/lib/exe/fetch_imagetoken.test.php b/_test/tests/lib/exe/fetch_imagetoken.test.php index c3371ca71..5360fec3f 100644 --- a/_test/tests/lib/exe/fetch_imagetoken.test.php +++ b/_test/tests/lib/exe/fetch_imagetoken.test.php @@ -51,11 +51,11 @@ class fetch_imagetoken_test extends DokuWikiTest { $response = $this->fetchResponse($valid_token); $this->assertTrue((bool)$response->getHeader('Content-Type')); $this->assertTrue((bool)($response->getContent())); - + $status_code = $response->getStatusCode(); $this->assertTrue(is_null($status_code) || (200 == $status_code)); } - + /** * modified image request with invalid token * expect: 412 status code @@ -64,7 +64,7 @@ class fetch_imagetoken_test extends DokuWikiTest { $invalid_token = 'tok='.media_get_token('junk',200,100).'&'; $this->assertEquals(412,$this->fetchResponse($invalid_token)->getStatusCode()); } - + /** * modified image request with no token * expect: 412 status code diff --git a/bin/wantedpages.php b/bin/wantedpages.php index 5d626bada..3eb03349a 100755 --- a/bin/wantedpages.php +++ b/bin/wantedpages.php @@ -1,9 +1,10 @@ #!/usr/bin/env php <?php +use dokuwiki\Utf8\Sort; +use dokuwiki\File\PageResolver; use splitbrain\phpcli\CLI; use splitbrain\phpcli\Options; -use dokuwiki\Utf8\Sort; if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/'); define('NOSESSION', 1); @@ -161,14 +162,12 @@ class WantedPagesCLI extends CLI { protected function internalLinks($page) { global $conf; $instructions = p_get_instructions(file_get_contents($page['file'])); - $cns = getNS($page['id']); - $exists = false; + $resolver = new PageResolver($page['id']); $pid = $page['id']; foreach($instructions as $ins) { if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink')) { - $mid = $ins[1][0]; - resolve_pageid($cns, $mid, $exists); - if(!$exists) { + $mid = $resolver->resolveId($ins[1][0]); + if(!page_exists($mid)) { list($mid) = explode('#', $mid); //record pages without hashes if($this->sort == 'origin') { diff --git a/composer.json b/composer.json index 8e0aa40c6..4a46d7768 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "aziraphale/email-address-validator": "^2", "marcusschwarz/lesserphp": "^0.5.1", "splitbrain/php-cli": "^1.1", - "splitbrain/slika": "^1.0" + "splitbrain/slika": "^1.0", + "kissifrot/php-ixr": "^1.8" }, "config": { "platform": { diff --git a/composer.lock b/composer.lock index b7edcabc9..0a3aeb449 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cd951937a517d2f058327d0429efe7ff", + "content-hash": "09f5f3726c3993d80980df99ab2a59dc", "packages": [ { "name": "aziraphale/email-address-validator", @@ -99,6 +99,53 @@ "time": "2020-06-22T15:46:04+00:00" }, { + "name": "kissifrot/php-ixr", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/kissifrot/php-ixr.git", + "reference": "4477cd1a67416ce5b6a2080f9a79d9eb50a965c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kissifrot/php-ixr/zipball/4477cd1a67416ce5b6a2080f9a79d9eb50a965c1", + "reference": "4477cd1a67416ce5b6a2080f9a79d9eb50a965c1", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "IXR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Incutio Ltd 2010 - Simon Willison", + "homepage": "http://scripts.incutio.com/xmlrpc/" + } + ], + "description": "Incutio XML-RPC library (IXR)", + "homepage": "http://scripts.incutio.com/xmlrpc/", + "keywords": [ + "remote procedure call", + "rpc", + "xlm-rpc", + "xmlrpc" + ], + "support": { + "issues": "https://github.com/kissifrot/php-ixr/issues", + "source": "https://github.com/kissifrot/php-ixr/tree/master" + }, + "time": "2016-11-17T12:00:18+00:00" + }, + { "name": "marcusschwarz/lesserphp", "version": "v0.5.5", "source": { @@ -504,20 +551,20 @@ }, { "name": "splitbrain/slika", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/splitbrain/slika.git", - "reference": "fda87e816eb150f3608282da962788b4ad509c11" + "reference": "be0785cb6b7def847df5d92e0e5fde57def7220f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/splitbrain/slika/zipball/fda87e816eb150f3608282da962788b4ad509c11", - "reference": "fda87e816eb150f3608282da962788b4ad509c11", + "url": "https://api.github.com/repos/splitbrain/slika/zipball/be0785cb6b7def847df5d92e0e5fde57def7220f", + "reference": "be0785cb6b7def847df5d92e0e5fde57def7220f", "shasum": "" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-gd": "PHP's builtin image manipulation library. Alternatively use an installation of ImageMagick" @@ -525,8 +572,8 @@ "type": "library", "autoload": { "psr-4": { - "splitbrain\\slika\\tests\\": "tests", - "splitbrain\\slika\\": "src" + "splitbrain\\slika\\": "src", + "splitbrain\\slika\\tests\\": "tests" } }, "notification-url": "https://packagist.org/downloads/", @@ -542,9 +589,9 @@ "description": "Simple image resizing", "support": { "issues": "https://github.com/splitbrain/slika/issues", - "source": "https://github.com/splitbrain/slika/tree/master" + "source": "https://github.com/splitbrain/slika/tree/1.0.5" }, - "time": "2020-09-07T18:35:00+00:00" + "time": "2022-02-04T22:41:26+00:00" } ], "packages-dev": [], @@ -1,4 +1,5 @@ <?php + /** * XML feed export * @@ -15,14 +16,14 @@ use dokuwiki\ChangeLog\PageChangeLog; use dokuwiki\Extension\AuthPlugin; use dokuwiki\Extension\Event; -if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/'); -require_once(DOKU_INC.'inc/init.php'); +if (!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__) . '/'); +require_once(DOKU_INC . 'inc/init.php'); //close session session_write_close(); //feed disabled? -if(!actionOK('rss')) { +if (!actionOK('rss')) { http_status(404); echo '<error>RSS feed is disabled.</error>'; exit; @@ -33,7 +34,8 @@ $opt = rss_parseOptions(); // the feed is dynamic - we need a cache for each combo // (but most people just use the default feed so it's still effective) -$key = join('', array_values($opt)).'$'.$_SERVER['REMOTE_USER'].'$'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT']; +$key = join('', array_values($opt)) . '$' . $_SERVER['REMOTE_USER'] + . '$' . $_SERVER['HTTP_HOST'] . $_SERVER['SERVER_PORT']; $cache = new Cache($key, '.feed'); // prepare cache depends @@ -47,9 +49,9 @@ header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Type: application/xml; charset=utf-8'); header('X-Robots-Tag: noindex'); -if($cache->useCache($depends)) { +if ($cache->useCache($depends)) { http_conditionalRequest($cache->getTime()); - if($conf['allowdebug']) header("X-CacheUsed: $cache->cache"); + if ($conf['allowdebug']) header("X-CacheUsed: $cache->cache"); print $cache->retrieveCache(); exit; } else { @@ -58,32 +60,33 @@ if($cache->useCache($depends)) { // create new feed $rss = new UniversalFeedCreator(); -$rss->title = $conf['title'].(($opt['namespace']) ? ' '.$opt['namespace'] : ''); +$rss->title = $conf['title'] . (($opt['namespace']) ? ' ' . $opt['namespace'] : ''); $rss->link = DOKU_URL; -$rss->syndicationURL = DOKU_URL.'feed.php'; -$rss->cssStyleSheet = DOKU_URL.'lib/exe/css.php?s=feed'; +$rss->syndicationURL = DOKU_URL . 'feed.php'; +$rss->cssStyleSheet = DOKU_URL . 'lib/exe/css.php?s=feed'; $image = new FeedImage(); $image->title = $conf['title']; -$image->url = tpl_getMediaFile(array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'), true); +$image->url = tpl_getMediaFile([':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'], true); $image->link = DOKU_URL; $rss->image = $image; $data = null; -$modes = array( +$modes = [ 'list' => 'rssListNamespace', 'search' => 'rssSearch', 'recent' => 'rssRecentChanges' -); -if(isset($modes[$opt['feed_mode']])) { +]; + +if (isset($modes[$opt['feed_mode']])) { $data = $modes[$opt['feed_mode']]($opt); } else { - $eventData = array( + $eventData = [ 'opt' => &$opt, 'data' => &$data, - ); + ]; $event = new Event('FEED_MODE_UNKNOWN', $eventData); - if($event->advise_before(true)) { + if ($event->advise_before(true)) { echo sprintf('<error>Unknown feed mode %s</error>', hsc($opt['feed_mode'])); exit; } @@ -106,59 +109,62 @@ print $feed; * * @author Andreas Gohr <andi@splitbrain.org> */ -function rss_parseOptions() { +function rss_parseOptions() +{ global $conf; global $INPUT; - $opt = array(); - - foreach(array( - // Basic feed properties - // Plugins may probably want to add new values to these - // properties for implementing own feeds - - // One of: list, search, recent - 'feed_mode' => array('str', 'mode', 'recent'), - // One of: diff, page, rev, current - 'link_to' => array('str', 'linkto', $conf['rss_linkto']), - // One of: abstract, diff, htmldiff, html - 'item_content' => array('str', 'content', $conf['rss_content']), - - // Special feed properties - // These are only used by certain feed_modes - - // String, used for feed title, in list and rc mode - 'namespace' => array('str', 'ns', null), - // Positive integer, only used in rc mode - 'items' => array('int', 'num', $conf['recent']), - // Boolean, only used in rc mode - 'show_minor' => array('bool', 'minor', false), - // Boolean, only used in rc mode - 'only_new' => array('bool', 'onlynewpages', false), - // String, only used in list mode - 'sort' => array('str', 'sort', 'natural'), - // String, only used in search mode - 'search_query' => array('str', 'q', null), - // One of: pages, media, both - 'content_type' => array('str', 'view', $conf['rss_media']) - - ) as $name => $val) { + $opt = []; + + foreach ( + [ + // Basic feed properties + // Plugins may probably want to add new values to these + // properties for implementing own feeds + + // One of: list, search, recent + 'feed_mode' => ['str', 'mode', 'recent'], + // One of: diff, page, rev, current + 'link_to' => ['str', 'linkto', $conf['rss_linkto']], + // One of: abstract, diff, htmldiff, html + 'item_content' => ['str', 'content', $conf['rss_content']], + + // Special feed properties + // These are only used by certain feed_modes + + // String, used for feed title, in list and rc mode + 'namespace' => ['str', 'ns', null], + // Positive integer, only used in rc mode + 'items' => ['int', 'num', $conf['recent']], + // Boolean, only used in rc mode + 'show_minor' => ['bool', 'minor', false], + // Boolean, only used in rc mode + 'only_new' => ['bool', 'onlynewpages', false], + // String, only used in list mode + 'sort' => ['str', 'sort', 'natural'], + // String, only used in search mode + 'search_query' => ['str', 'q', null], + // One of: pages, media, both + 'content_type' => ['str', 'view', $conf['rss_media']] + + ] as $name => $val + ) { $opt[$name] = $INPUT->{$val[0]}($val[1], $val[2], true); } $opt['items'] = max(0, (int) $opt['items']); $opt['show_minor'] = (bool) $opt['show_minor']; $opt['only_new'] = (bool) $opt['only_new']; - $opt['sort'] = valid_input_set('sort', array('default' => 'natural', 'date'), $opt); + $opt['sort'] = valid_input_set('sort', ['default' => 'natural', 'date'], $opt); $opt['guardmail'] = ($conf['mailguard'] != '' && $conf['mailguard'] != 'none'); $type = $INPUT->valid( 'type', - array( 'rss', 'rss2', 'atom', 'atom1', 'rss1'), + ['rss', 'rss2', 'atom', 'atom1', 'rss1'], $conf['rss_type'] ); - switch($type) { + switch ($type) { case 'rss': $opt['feed_type'] = 'RSS0.91'; $opt['mime_type'] = 'text/xml'; @@ -180,9 +186,9 @@ function rss_parseOptions() { $opt['mime_type'] = 'application/xml'; } - $eventData = array( + $eventData = [ 'opt' => &$opt, - ); + ]; Event::createAndTrigger('FEED_OPTS_POSTPROCESS', $eventData); return $opt; } @@ -190,98 +196,105 @@ function rss_parseOptions() { /** * Add recent changed pages to a feed object * + * @param FeedCreator $rss the FeedCreator Object + * @param array $data the items to add + * @param array $opt the feed options * @author Andreas Gohr <andi@splitbrain.org> - * @param FeedCreator $rss the FeedCreator Object - * @param array $data the items to add - * @param array $opt the feed options */ -function rss_buildItems(&$rss, &$data, $opt) { +function rss_buildItems(&$rss, &$data, $opt) +{ global $conf; global $lang; /* @var AuthPlugin $auth */ global $auth; - $eventData = array( + $eventData = [ 'rss' => &$rss, 'data' => &$data, 'opt' => &$opt, - ); + ]; $event = new Event('FEED_DATA_PROCESS', $eventData); - if($event->advise_before(false)) { - foreach($data as $ditem) { - if(!is_array($ditem)) { + if ($event->advise_before(false)) { + foreach ($data as $ditem) { + if (!is_array($ditem)) { // not an array? then only a list of IDs was given - $ditem = array('id' => $ditem); + $ditem = ['id' => $ditem]; } $item = new FeedItem(); $id = $ditem['id']; - if(!$ditem['media']) { + if (!$ditem['media']) { $meta = p_get_metadata($id); } else { - $meta = array(); + $meta = []; } // add date - if($ditem['date']) { + if ($ditem['date']) { $date = $ditem['date']; } elseif ($ditem['media']) { $date = @filemtime(mediaFN($id)); } elseif (file_exists(wikiFN($id))) { $date = @filemtime(wikiFN($id)); - } elseif($meta['date']['modified']) { + } elseif ($meta['date']['modified']) { $date = $meta['date']['modified']; } else { $date = 0; } - if($date) $item->date = date('r', $date); + if ($date) $item->date = date('r', $date); // add title - if($conf['useheading'] && $meta['title']) { + if ($conf['useheading'] && $meta['title']) { $item->title = $meta['title']; } else { $item->title = $ditem['id']; } - if($conf['rss_show_summary'] && !empty($ditem['sum'])) { - $item->title .= ' - '.strip_tags($ditem['sum']); + if ($conf['rss_show_summary'] && !empty($ditem['sum'])) { + $item->title .= ' - ' . strip_tags($ditem['sum']); } // add item link - switch($opt['link_to']) { + switch ($opt['link_to']) { case 'page': - if($ditem['media']) { + if ($ditem['media']) { $item->link = media_managerURL( - array( - 'image' => $id, - 'ns' => getNS($id), - 'rev' => $date - ), '&', true + [ + 'image' => $id, + 'ns' => getNS($id), + 'rev' => $date + ], + '&', + true ); } else { - $item->link = wl($id, 'rev='.$date, true, '&'); + $item->link = wl($id, 'rev=' . $date, true, '&'); } break; case 'rev': - if($ditem['media']) { + if ($ditem['media']) { $item->link = media_managerURL( - array( - 'image' => $id, - 'ns' => getNS($id), - 'rev' => $date, - 'tab_details' => 'history' - ), '&', true + [ + 'image' => $id, + 'ns' => getNS($id), + 'rev' => $date, + 'tab_details' => 'history' + ], + '&', + true ); } else { - $item->link = wl($id, 'do=revisions&rev='.$date, true, '&'); + $item->link = wl($id, 'do=revisions&rev=' . $date, true, '&'); } break; case 'current': - if($ditem['media']) { + if ($ditem['media']) { $item->link = media_managerURL( - array( - 'image' => $id, - 'ns' => getNS($id) - ), '&', true + [ + 'image' => $id, + 'ns' => getNS($id) + ], + '&', + true ); } else { $item->link = wl($id, '', true, '&'); @@ -289,85 +302,91 @@ function rss_buildItems(&$rss, &$data, $opt) { break; case 'diff': default: - if($ditem['media']) { + if ($ditem['media']) { $item->link = media_managerURL( - array( - 'image' => $id, - 'ns' => getNS($id), - 'rev' => $date, - 'tab_details' => 'history', - 'mediado' => 'diff' - ), '&', true + [ + 'image' => $id, + 'ns' => getNS($id), + 'rev' => $date, + 'tab_details' => 'history', + 'mediado' => 'diff' + ], + '&', + true ); } else { - $item->link = wl($id, 'rev='.$date.'&do=diff', true, '&'); + $item->link = wl($id, 'rev=' . $date . '&do=diff', true, '&'); } } // add item content - switch($opt['item_content']) { + switch ($opt['item_content']) { case 'diff': case 'htmldiff': - if($ditem['media']) { + if ($ditem['media']) { $medialog = new MediaChangeLog($id); - $revs = $medialog->getRevisions(0, 1); - $rev = $revs[0]; - $src_r = ''; - $src_l = ''; + $revs = $medialog->getRevisions(0, 1); + $rev = $revs[0]; + $src_r = ''; + $src_l = ''; - if($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)), 300)) { - $more = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id)); + if ($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)), 300)) { + $more = 'w=' . $size[0] . '&h=' . $size[1] . '&t=' . @filemtime(mediaFN($id)); $src_r = ml($id, $more, true, '&', true); } - if($rev && $size = media_image_preview_size($id, $rev, new JpegMeta(mediaFN($id, $rev)), 300)) { - $more = 'rev='.$rev.'&w='.$size[0].'&h='.$size[1]; + if ($rev && $size = media_image_preview_size($id, $rev, new JpegMeta(mediaFN($id, $rev)), + 300)) { + $more = 'rev=' . $rev . '&w=' . $size[0] . '&h=' . $size[1]; $src_l = ml($id, $more, true, '&', true); } $content = ''; - if($src_r) { + if ($src_r) { $content = '<table>'; - $content .= '<tr><th width="50%">'.$rev.'</th>'; - $content .= '<th width="50%">'.$lang['current'].'</th></tr>'; - $content .= '<tr align="center"><td><img src="'.$src_l.'" alt="" /></td><td>'; - $content .= '<img src="'.$src_r.'" alt="'.$id.'" /></td></tr>'; + $content .= '<tr><th width="50%">' . $rev . '</th>'; + $content .= '<th width="50%">' . $lang['current'] . '</th></tr>'; + $content .= '<tr align="center"><td><img src="' . $src_l . '" alt="" /></td><td>'; + $content .= '<img src="' . $src_r . '" alt="' . $id . '" /></td></tr>'; $content .= '</table>'; } - } else { - require_once(DOKU_INC.'inc/DifferenceEngine.php'); + require_once(DOKU_INC . 'inc/DifferenceEngine.php'); $pagelog = new PageChangeLog($id); - $revs = $pagelog->getRevisions(0, 1); - $rev = $revs[0]; - - if($rev) { - $df = new Diff(explode("\n", rawWiki($id, $rev)), - explode("\n", rawWiki($id, ''))); + $revs = $pagelog->getRevisions(0, 1); + $rev = $revs[0]; + + if ($rev) { + $df = new Diff( + explode("\n", rawWiki($id, $rev)), + explode("\n", rawWiki($id, '')) + ); } else { - $df = new Diff(array(''), - explode("\n", rawWiki($id, ''))); + $df = new Diff( + [''], + explode("\n", rawWiki($id, '')) + ); } - if($opt['item_content'] == 'htmldiff') { + if ($opt['item_content'] == 'htmldiff') { // note: no need to escape diff output, TableDiffFormatter provides 'safe' html $tdf = new TableDiffFormatter(); $content = '<table>'; - $content .= '<tr><th colspan="2" width="50%">'.$rev.'</th>'; - $content .= '<th colspan="2" width="50%">'.$lang['current'].'</th></tr>'; + $content .= '<tr><th colspan="2" width="50%">' . $rev . '</th>'; + $content .= '<th colspan="2" width="50%">' . $lang['current'] . '</th></tr>'; $content .= $tdf->format($df); $content .= '</table>'; } else { // note: diff output must be escaped, UnifiedDiffFormatter provides plain text $udf = new UnifiedDiffFormatter(); - $content = "<pre>\n".hsc($udf->format($df))."\n</pre>"; + $content = "<pre>\n" . hsc($udf->format($df)) . "\n</pre>"; } } break; case 'html': - if($ditem['media']) { - if($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) { - $more = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id)); - $src = ml($id, $more, true, '&', true); - $content = '<img src="'.$src.'" alt="'.$id.'" />'; + if ($ditem['media']) { + if ($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) { + $more = 'w=' . $size[0] . '&h=' . $size[1] . '&t=' . @filemtime(mediaFN($id)); + $src = ml($id, $more, true, '&', true); + $content = '<img src="' . $src . '" alt="' . $id . '" />'; } else { $content = ''; } @@ -385,20 +404,23 @@ function rss_buildItems(&$rss, &$data, $opt) { $content = preg_replace('/(<img .*?class="mediaright")/s', '\\1 align="right"', $content); // make URLs work when canonical is not set, regexp instead of rerendering! - if(!$conf['canonical']) { + if (!$conf['canonical']) { $base = preg_quote(DOKU_REL, '/'); - $content = preg_replace('/(<a href|<img src)="('.$base.')/s', '$1="'.DOKU_URL, $content); + $content = preg_replace( + '/(<a href|<img src)="(' . $base . ')/s', '$1="' . DOKU_URL, + $content + ); } } break; case 'abstract': default: - if($ditem['media']) { - if($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) { - $more = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id)); - $src = ml($id, $more, true, '&', true); - $content = '<img src="'.$src.'" alt="'.$id.'" />'; + if ($ditem['media']) { + if ($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) { + $more = 'w=' . $size[0] . '&h=' . $size[1] . '&t=' . @filemtime(mediaFN($id)); + $src = ml($id, $more, true, '&', true); + $content = '<img src="' . $src . '" alt="' . $id . '" />'; } else { $content = ''; } @@ -410,19 +432,19 @@ function rss_buildItems(&$rss, &$data, $opt) { // add user # FIXME should the user be pulled from metadata as well? - $user = @$ditem['user']; // the @ spares time repeating lookup - if(blank($user)) { - $item->author = 'Anonymous'; + $user = @$ditem['user']; // the @ spares time repeating lookup + if (blank($user)) { + $item->author = 'Anonymous'; $item->authorEmail = 'anonymous@undisclosed.example.com'; } else { - $item->author = $user; + $item->author = $user; $item->authorEmail = $user . '@undisclosed.example.com'; // get real user name if configured - if($conf['useacl'] && $auth) { + if ($conf['useacl'] && $auth) { $userInfo = $auth->getUserData($user); - if($userInfo) { - switch($conf['showuseras']) { + if ($userInfo) { + switch ($conf['showuseras']) { case 'username': case 'username_link': $item->author = $userInfo['name']; @@ -438,22 +460,22 @@ function rss_buildItems(&$rss, &$data, $opt) { } // add category - if(isset($meta['subject'])) { + if (isset($meta['subject'])) { $item->category = $meta['subject']; } else { $cat = getNS($id); - if($cat) $item->category = $cat; + if ($cat) $item->category = $cat; } // finally add the item to the feed object, after handing it to registered plugins - $evdata = array( + $evdata = [ 'item' => &$item, 'opt' => &$opt, 'ditem' => &$ditem, 'rss' => &$rss - ); + ]; $evt = new Event('FEED_ITEM_ADD', $evdata); - if($evt->advise_before()) { + if ($evt->advise_before()) { $rss->addItem($item); } $evt->advise_after(); // for completeness @@ -467,14 +489,15 @@ function rss_buildItems(&$rss, &$data, $opt) { * * @author Andreas Gohr <andi@splitbrain.org> */ -function rssRecentChanges($opt) { +function rssRecentChanges($opt) +{ global $conf; $flags = 0; - if(!$conf['rss_show_deleted']) $flags += RECENTS_SKIP_DELETED; - if(!$opt['show_minor']) $flags += RECENTS_SKIP_MINORS; - if($opt['only_new']) $flags += RECENTS_ONLY_CREATION; - if($opt['content_type'] == 'media' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_CHANGES; - if($opt['content_type'] == 'both' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_PAGES_MIXED; + if (!$conf['rss_show_deleted']) $flags += RECENTS_SKIP_DELETED; + if (!$opt['show_minor']) $flags += RECENTS_SKIP_MINORS; + if ($opt['only_new']) $flags += RECENTS_ONLY_CREATION; + if ($opt['content_type'] == 'media' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_CHANGES; + if ($opt['content_type'] == 'both' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_PAGES_MIXED; $recents = getRecents(0, $opt['items'], $opt['namespace'], $flags); return $recents; @@ -485,19 +508,20 @@ function rssRecentChanges($opt) { * * @author Andreas Gohr <andi@splitbrain.org> */ -function rssListNamespace($opt) { - require_once(DOKU_INC.'inc/search.php'); +function rssListNamespace($opt) +{ + require_once(DOKU_INC . 'inc/search.php'); global $conf; - $ns = ':'.cleanID($opt['namespace']); + $ns = ':' . cleanID($opt['namespace']); $ns = utf8_encodeFN(str_replace(':', '/', $ns)); - $data = array(); - $search_opts = array( - 'depth' => 1, + $data = []; + $search_opts = [ + 'depth' => 1, 'pagesonly' => true, 'listfiles' => true - ); + ]; search($data, $conf['datadir'], 'search_universal', $search_opts, $ns, $lvl = 1, $opt['sort']); return $data; @@ -508,10 +532,11 @@ function rssListNamespace($opt) { * * @author Andreas Gohr <andi@splitbrain.org> */ -function rssSearch($opt) { - if(!$opt['search_query']) return array(); +function rssSearch($opt) +{ + if (!$opt['search_query'] || !actionOK('search')) return []; - require_once(DOKU_INC.'inc/fulltext.php'); + require_once(DOKU_INC . 'inc/fulltext.php'); $data = ft_pageSearch($opt['search_query'], $poswords); $data = array_keys($data); diff --git a/inc/Action/AbstractAction.php b/inc/Action/AbstractAction.php index ea862386e..37eab3a8e 100644 --- a/inc/Action/AbstractAction.php +++ b/inc/Action/AbstractAction.php @@ -2,7 +2,6 @@ namespace dokuwiki\Action; -use dokuwiki\Action\Exception\ActionDisabledException; use dokuwiki\Action\Exception\ActionException; use dokuwiki\Action\Exception\FatalException; @@ -69,6 +68,7 @@ abstract class AbstractAction { * Output whatever content is wanted within tpl_content(); * * @fixme we may want to return a Ui class here + * @throws FatalException */ public function tplContent() { throw new FatalException('No content for Action ' . $this->actionname); diff --git a/inc/Action/AbstractAliasAction.php b/inc/Action/AbstractAliasAction.php index 7240f5edf..771664a37 100644 --- a/inc/Action/AbstractAliasAction.php +++ b/inc/Action/AbstractAliasAction.php @@ -21,6 +21,9 @@ abstract class AbstractAliasAction extends AbstractAction { return AUTH_NONE; } + /** + * @throws FatalException + */ public function preProcess() { throw new FatalException('Alias Actions need to implement preProcess to load the aliased action'); } diff --git a/inc/Action/Admin.php b/inc/Action/Admin.php index aefa228e0..7a884b5b5 100644 --- a/inc/Action/Admin.php +++ b/inc/Action/Admin.php @@ -3,6 +3,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\ActionException; +use dokuwiki\Extension\AdminPlugin; /** * Class Admin @@ -21,11 +22,10 @@ class Admin extends AbstractUserAction { /** @inheritDoc */ public function preProcess() { global $INPUT; - global $INFO; // retrieve admin plugin name from $_REQUEST['page'] - if(($page = $INPUT->str('page', '', true)) != '') { - /** @var $plugin \dokuwiki\Extension\AdminPlugin */ + if($INPUT->str('page', '', true) != '') { + /** @var AdminPlugin $plugin */ if($plugin = plugin_getRequestAdminPlugin()) { // FIXME this method does also permission checking if(!$plugin->isAccessibleByCurrentUser()) { throw new ActionException('denied'); diff --git a/inc/Action/Cancel.php b/inc/Action/Cancel.php index d4d8277cd..d7505e4cc 100644 --- a/inc/Action/Cancel.php +++ b/inc/Action/Cancel.php @@ -13,7 +13,10 @@ use dokuwiki\Action\Exception\ActionAbort; */ class Cancel extends AbstractAliasAction { - /** @inheritdoc */ + /** + * @inheritdoc + * @throws ActionAbort + */ public function preProcess() { global $ID; unlock($ID); diff --git a/inc/Action/Denied.php b/inc/Action/Denied.php index 794fe0c0f..ab2f0d8f4 100644 --- a/inc/Action/Denied.php +++ b/inc/Action/Denied.php @@ -2,6 +2,7 @@ namespace dokuwiki\Action; +use dokuwiki\Extension\Event; use dokuwiki\Ui; /** @@ -11,7 +12,7 @@ use dokuwiki\Ui; * * @package dokuwiki\Action */ -class Denied extends AbstractAclAction +class Denied extends AbstractAction { /** @inheritdoc */ public function minimumPermission() @@ -22,11 +23,17 @@ class Denied extends AbstractAclAction /** @inheritdoc */ public function tplContent() { - global $INPUT; $this->showBanner(); - if (empty($INPUT->server->str('REMOTE_USER')) && actionOK('login')) { - (new Ui\Login)->show(); + + $data = null; + $event = new Event('ACTION_DENIED_TPLCONTENT', $data); + if ($event->advise_before()) { + global $INPUT; + if (empty($INPUT->server->str('REMOTE_USER')) && actionOK('login')) { + (new Ui\Login)->show(); + } } + $event->advise_after(); } /** diff --git a/inc/Action/Diff.php b/inc/Action/Diff.php index 1409b246b..31024b6cd 100644 --- a/inc/Action/Diff.php +++ b/inc/Action/Diff.php @@ -34,7 +34,8 @@ class Diff extends AbstractAction /** @inheritdoc */ public function tplContent() { - (new Ui\Diff())->show(); + global $INFO; + (new Ui\PageDiff($INFO['id']))->preference('showIntro', true)->show(); } } diff --git a/inc/Action/Draftdel.php b/inc/Action/Draftdel.php index 756c0e8cd..1fb796601 100644 --- a/inc/Action/Draftdel.php +++ b/inc/Action/Draftdel.php @@ -28,7 +28,7 @@ class Draftdel extends AbstractAction { public function preProcess() { global $INFO, $ID; $draft = new \dokuwiki\Draft($ID, $INFO['client']); - if ($draft->isDraftAvailable()) { + if ($draft->isDraftAvailable() && checkSecurityToken()) { $draft->deleteDraft(); } diff --git a/inc/Action/Edit.php b/inc/Action/Edit.php index 20faa3928..417fdb075 100644 --- a/inc/Action/Edit.php +++ b/inc/Action/Edit.php @@ -83,7 +83,7 @@ class Edit extends AbstractAction $lockedby = checklock($ID); if ($lockedby) { throw new ActionAbort('locked'); - }; + } lock($ID); } diff --git a/inc/Action/Logout.php b/inc/Action/Logout.php index 28e8fee58..d9aead529 100644 --- a/inc/Action/Logout.php +++ b/inc/Action/Logout.php @@ -4,6 +4,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\ActionDisabledException; use dokuwiki\Action\Exception\ActionException; +use dokuwiki\Extension\AuthPlugin; /** * Class Logout @@ -23,7 +24,7 @@ class Logout extends AbstractUserAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \dokuwiki\Extension\AuthPlugin $auth */ + /** @var AuthPlugin $auth */ global $auth; if(!$auth->canDo('logout')) throw new ActionDisabledException(); } @@ -33,6 +34,8 @@ class Logout extends AbstractUserAction { global $ID; global $INPUT; + if (!checkSecurityToken()) throw new ActionException(); + // when logging out during an edit session, unlock the page $lockedby = checklock($ID); if($lockedby == $INPUT->server->str('REMOTE_USER')) { diff --git a/inc/Action/Plugin.php b/inc/Action/Plugin.php index 43964cf39..cbc407839 100644 --- a/inc/Action/Plugin.php +++ b/inc/Action/Plugin.php @@ -2,6 +2,8 @@ namespace dokuwiki\Action; +use dokuwiki\Extension\Event; + /** * Class Plugin * @@ -23,7 +25,7 @@ class Plugin extends AbstractAction { * @triggers TPL_ACT_UNKNOWN */ public function tplContent() { - $evt = new \dokuwiki\Extension\Event('TPL_ACT_UNKNOWN', $this->actionname); + $evt = new Event('TPL_ACT_UNKNOWN', $this->actionname); if($evt->advise_before()) { msg('Failed to handle action: ' . hsc($this->actionname), -1); } diff --git a/inc/Action/Profile.php b/inc/Action/Profile.php index 926b1a26d..0ffcb260b 100644 --- a/inc/Action/Profile.php +++ b/inc/Action/Profile.php @@ -4,6 +4,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\ActionAbort; use dokuwiki\Action\Exception\ActionDisabledException; +use dokuwiki\Extension\AuthPlugin; use dokuwiki\Ui; /** @@ -26,7 +27,7 @@ class Profile extends AbstractUserAction { parent::checkPreconditions(); - /** @var \dokuwiki\Extension\AuthPlugin $auth */ + /** @var AuthPlugin $auth */ global $auth; if(!$auth->canDo('Profile')) throw new ActionDisabledException(); } diff --git a/inc/Action/ProfileDelete.php b/inc/Action/ProfileDelete.php index 89c58edb5..d8e434011 100644 --- a/inc/Action/ProfileDelete.php +++ b/inc/Action/ProfileDelete.php @@ -4,6 +4,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\ActionAbort; use dokuwiki\Action\Exception\ActionDisabledException; +use dokuwiki\Extension\AuthPlugin; /** * Class ProfileDelete @@ -23,7 +24,7 @@ class ProfileDelete extends AbstractUserAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \dokuwiki\Extension\AuthPlugin $auth */ + /** @var AuthPlugin $auth */ global $auth; if(!$auth->canDo('delUser')) throw new ActionDisabledException(); } diff --git a/inc/Action/Recent.php b/inc/Action/Recent.php index 38167f02b..203c91d81 100644 --- a/inc/Action/Recent.php +++ b/inc/Action/Recent.php @@ -39,7 +39,7 @@ class Recent extends AbstractAction public function tplContent() { global $INPUT; - (new Ui\Recent((int) $INPUT->extract('first')->int('first'), $this->showType))->show(); + (new Ui\Recent($INPUT->extract('first')->int('first'), $this->showType))->show(); } } diff --git a/inc/Action/Recover.php b/inc/Action/Recover.php index 7966396b9..c0e744663 100644 --- a/inc/Action/Recover.php +++ b/inc/Action/Recover.php @@ -13,7 +13,10 @@ use dokuwiki\Action\Exception\ActionAbort; */ class Recover extends AbstractAliasAction { - /** @inheritdoc */ + /** + * @inheritdoc + * @throws ActionAbort + */ public function preProcess() { throw new ActionAbort('edit'); } diff --git a/inc/Action/Register.php b/inc/Action/Register.php index feb4076ea..4c3da19bb 100644 --- a/inc/Action/Register.php +++ b/inc/Action/Register.php @@ -4,6 +4,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\ActionAbort; use dokuwiki\Action\Exception\ActionDisabledException; +use dokuwiki\Extension\AuthPlugin; use dokuwiki\Ui; /** @@ -26,7 +27,7 @@ class Register extends AbstractAclAction { parent::checkPreconditions(); - /** @var \dokuwiki\Extension\AuthPlugin $auth */ + /** @var AuthPlugin $auth */ global $auth; global $conf; if (isset($conf['openregister']) && !$conf['openregister']) throw new ActionDisabledException(); diff --git a/inc/Action/Resendpwd.php b/inc/Action/Resendpwd.php index f28d9975f..5af02a9fb 100644 --- a/inc/Action/Resendpwd.php +++ b/inc/Action/Resendpwd.php @@ -4,6 +4,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\ActionAbort; use dokuwiki\Action\Exception\ActionDisabledException; +use dokuwiki\Extension\AuthPlugin; use dokuwiki\Ui; /** @@ -26,7 +27,7 @@ class Resendpwd extends AbstractAclAction { parent::checkPreconditions(); - /** @var \dokuwiki\Extension\AuthPlugin $auth */ + /** @var AuthPlugin $auth */ global $auth; global $conf; if (isset($conf['resendpasswd']) && !$conf['resendpasswd']) @@ -66,7 +67,7 @@ class Resendpwd extends AbstractAclAction { global $lang; global $conf; - /* @var \dokuwiki\Extension\AuthPlugin $auth */ + /* @var AuthPlugin $auth */ global $auth; global $INPUT; diff --git a/inc/Action/Revisions.php b/inc/Action/Revisions.php index 27b20ec29..4b2f82275 100644 --- a/inc/Action/Revisions.php +++ b/inc/Action/Revisions.php @@ -22,7 +22,7 @@ class Revisions extends AbstractAction /** @inheritdoc */ public function tplContent() { - global $INPUT; - (new Ui\Revisions($INPUT->int('first')))->show(); + global $INFO, $INPUT; + (new Ui\PageRevisions($INFO['id']))->show($INPUT->int('first')); } } diff --git a/inc/Action/Sitemap.php b/inc/Action/Sitemap.php index 370bcf065..eba9c2813 100644 --- a/inc/Action/Sitemap.php +++ b/inc/Action/Sitemap.php @@ -4,6 +4,7 @@ namespace dokuwiki\Action; use dokuwiki\Action\Exception\FatalException; use dokuwiki\Sitemap\Mapper; +use dokuwiki\Utf8\PhpString; /** * Class Sitemap @@ -48,7 +49,7 @@ class Sitemap extends AbstractAction { if(is_readable($sitemap)) { // Send headers header('Content-Type: ' . $mime); - header('Content-Disposition: attachment; filename=' . \dokuwiki\Utf8\PhpString::basename($sitemap)); + header('Content-Disposition: attachment; filename=' . PhpString::basename($sitemap)); http_conditionalRequest(filemtime($sitemap)); diff --git a/inc/Action/Subscribe.php b/inc/Action/Subscribe.php index c206c82ad..5aa3cf1fc 100644 --- a/inc/Action/Subscribe.php +++ b/inc/Action/Subscribe.php @@ -7,6 +7,7 @@ use dokuwiki\Action\Exception\ActionDisabledException; use dokuwiki\Subscriptions\SubscriberManager; use dokuwiki\Extension\Event; use dokuwiki\Ui; +use Exception; /** * Class Subscribe @@ -39,7 +40,7 @@ class Subscribe extends AbstractUserAction $this->handleSubscribeData(); } catch (ActionAbort $e) { throw $e; - } catch (\Exception $e) { + } catch (Exception $e) { msg($e->getMessage(), -1); } } @@ -54,7 +55,7 @@ class Subscribe extends AbstractUserAction * Handle page 'subscribe' * * @author Adrian Lang <lang@cosmocode.de> - * @throws \Exception if (un)subscribing fails + * @throws Exception if (un)subscribing fails * @throws ActionAbort when (un)subscribing worked */ protected function handleSubscribeData() @@ -99,7 +100,7 @@ class Subscribe extends AbstractUserAction throw new ActionAbort('redirect'); } - throw new \Exception( + throw new Exception( sprintf( $lang["subscr_{$action}_error"], hsc($INFO['userinfo']['name']), @@ -117,7 +118,7 @@ class Subscribe extends AbstractUserAction * @author Adrian Lang <lang@cosmocode.de> * * @param array &$params the parameters: target, style and action - * @throws \Exception + * @throws Exception */ public function handlePostData(&$params) { @@ -127,7 +128,7 @@ class Subscribe extends AbstractUserAction // Get and validate parameters. if (!isset($params['target'])) { - throw new \Exception('no subscription target given'); + throw new Exception('no subscription target given'); } $target = $params['target']; $valid_styles = array('every', 'digest'); @@ -147,7 +148,7 @@ class Subscribe extends AbstractUserAction // Check other conditions. if ($action === 'subscribe') { if ($INFO['userinfo']['mail'] === '') { - throw new \Exception($lang['subscr_subscribe_noaddress']); + throw new Exception($lang['subscr_subscribe_noaddress']); } } elseif ($action === 'unsubscribe') { $is = false; @@ -157,7 +158,7 @@ class Subscribe extends AbstractUserAction } } if ($is === false) { - throw new \Exception( + throw new Exception( sprintf( $lang['subscr_not_subscribed'], $INPUT->server->str('REMOTE_USER'), diff --git a/inc/ActionRouter.php b/inc/ActionRouter.php index 7d8a72acf..300a56cd0 100644 --- a/inc/ActionRouter.php +++ b/inc/ActionRouter.php @@ -156,6 +156,7 @@ class ActionRouter { if(defined('DOKU_UNITTEST')) { throw $e; } + ErrorHandler::logException($e); $msg = 'Something unforeseen has happened: ' . $e->getMessage(); nice_die(hsc($msg)); } diff --git a/inc/Ajax.php b/inc/Ajax.php index f1aea7d93..76d9dd5fb 100644 --- a/inc/Ajax.php +++ b/inc/Ajax.php @@ -168,8 +168,10 @@ class Ajax { $client = $_SERVER['REMOTE_USER']; if(!$client) $client = clientIP(true); - $cname = getCacheName($client . $id, '.draft'); - @unlink($cname); + $draft = new Draft($id, $client); + if ($draft->isDraftAvailable() && checkSecurityToken()) { + $draft->deleteDraft(); + } } /** @@ -241,14 +243,11 @@ class Ajax { * @author Kate Arzamastseva <pshns@ukr.net> */ protected function callMediadiff() { - global $NS; global $INPUT; $image = ''; if($INPUT->has('image')) $image = cleanID($INPUT->str('image')); - $NS = getNS($image); - $auth = auth_quickaclcheck("$NS:*"); - media_diff($image, $NS, $auth, true); + (new Ui\MediaDiff($image))->preference('fromAjax', true)->show(); } /** diff --git a/inc/Cache/CacheImageMod.php b/inc/Cache/CacheImageMod.php new file mode 100644 index 000000000..5883f7842 --- /dev/null +++ b/inc/Cache/CacheImageMod.php @@ -0,0 +1,56 @@ +<?php + +namespace dokuwiki\Cache; + +/** + * Handle the caching of modified (resized/cropped) images + */ +class CacheImageMod extends Cache +{ + + /** @var string source file */ + protected $file; + + /** + * @param string $file Original source file + * @param int $w new width in pixel + * @param int $h new height in pixel + * @param string $ext Image extension - no leading dot + * @param bool $crop Is this a crop? + */ + public function __construct($file, $w, $h, $ext, $crop) + { + $fullext = '.media.' . $w . 'x' . $h; + $fullext .= $crop ? '.crop' : ''; + $fullext .= ".$ext"; + + $this->file = $file; + + $this->setEvent('IMAGEMOD_CACHE_USE'); + parent::__construct($file, $fullext); + } + + /** @inheritdoc */ + public function makeDefaultCacheDecision() + { + if (!file_exists($this->file)) { + return false; + } + return parent::makeDefaultCacheDecision(); + } + + /** + * Caching depends on the source and the wiki config + * @inheritdoc + */ + protected function addDependencies() + { + parent::addDependencies(); + + $this->depends['files'] = array_merge( + [$this->file], + getConfigFiles('main') + ); + } + +} diff --git a/inc/ChangeLog/ChangeLog.php b/inc/ChangeLog/ChangeLog.php index 16b5cc285..66a84484c 100644 --- a/inc/ChangeLog/ChangeLog.php +++ b/inc/ChangeLog/ChangeLog.php @@ -2,16 +2,19 @@ namespace dokuwiki\ChangeLog; +use dokuwiki\Logger; + /** - * methods for handling of changelog of pages or media files + * ChangeLog Prototype; methods for handling changelog */ abstract class ChangeLog { + use ChangeLogTrait; /** @var string */ protected $id; - /** @var int */ - protected $chunk_size; + /** @var false|int */ + protected $currentRevision; /** @var array */ protected $cache; @@ -32,44 +35,92 @@ abstract class ChangeLog $this->id = $id; $this->setChunkSize($chunk_size); + } + /** + * Returns path to current page/media + * + * @return string path to file + */ + abstract protected function getFilename(); + + /** + * Check whether given revision is the current page + * + * @param int $rev timestamp of current page + * @return bool true if $rev is current revision, otherwise false + */ + public function isCurrentRevision($rev) + { + return $rev == $this->currentRevision(); } /** - * Set chunk size for file reading - * Chunk size zero let read whole file at once + * Checks if the revision is last revision * - * @param int $chunk_size maximum block size read from file + * @param int $rev revision timestamp + * @return bool true if $rev is last revision, otherwise false */ - public function setChunkSize($chunk_size) + public function isLastRevision($rev = null) { - if (!is_numeric($chunk_size)) $chunk_size = 0; + return $rev === $this->lastRevision(); + } - $this->chunk_size = (int)max($chunk_size, 0); + /** + * Return the current revision identifer + * + * The "current" revision means current version of the page or media file. It is either + * identical with or newer than the "last" revision, that depends on whether the file + * has modified, created or deleted outside of DokuWiki. + * The value of identifier can be determined by timestamp as far as the file exists, + * otherwise it must be assigned larger than any other revisions to keep them sortable. + * + * @return int|false revision timestamp + */ + public function currentRevision() + { + if (!isset($this->currentRevision)) { + // set ChangeLog::currentRevision property + $this->getCurrentRevisionInfo(); + } + return $this->currentRevision; } /** - * Returns path to changelog + * Return the last revision identifer, date value of the last entry of the changelog * - * @return string path to file + * @return int|false revision timestamp */ - abstract protected function getChangelogFilename(); + public function lastRevision() + { + $revs = $this->getRevisions(-1, 1); + return empty($revs) ? false : $revs[0]; + } /** - * Returns path to current page/media + * Save revision info to the cache pool * - * @return string path to file + * @param array $info Revision info structure + * @return bool */ - abstract protected function getFilename(); + protected function cacheRevisionInfo($info) + { + if (!is_array($info)) return false; + //$this->cache[$this->id][$info['date']] ??= $info; // since php 7.4 + $this->cache[$this->id][$info['date']] = $this->cache[$this->id][$info['date']] ?? $info; + return true; + } /** - * Get the changelog information for a specific page id and revision (timestamp) + * Get the changelog information for a specific revision (timestamp) * * Adjacent changelog lines are optimistically parsed and cached to speed up * consecutive calls to getRevisionInfo. For large changelog files, only the chunk * containing the requested changelog line is read. * * @param int $rev revision timestamp + * @param bool $retrieveCurrentRevInfo allows to skip for getting other revision info in the + * getCurrentRevisionInfo() where $currentRevision is not yet determined * @return bool|array false or array with entries: * - date: unix timestamp * - ip: IPv4 address (127.0.0.1) @@ -78,13 +129,20 @@ abstract class ChangeLog * - user: user name * - sum: edit summary (or action reason) * - extra: extra data (varies by line type) + * - sizechange: change of filesize * * @author Ben Coburn <btcoburn@silicodon.net> * @author Kate Arzamastseva <pshns@ukr.net> */ - public function getRevisionInfo($rev) + public function getRevisionInfo($rev, $retrieveCurrentRevInfo = true) { - $rev = max($rev, 0); + $rev = max(0, $rev); + if (!$rev) return false; + + //ensure the external edits are cached as well + if (!isset($this->currentRevision) && $retrieveCurrentRevInfo) { + $this->getCurrentRevisionInfo(); + } // check if it's already in the memory cache if (isset($this->cache[$this->id]) && isset($this->cache[$this->id][$rev])) { @@ -100,10 +158,8 @@ abstract class ChangeLog // parse and cache changelog lines foreach ($lines as $value) { - $tmp = parseChangelogLine($value); - if ($tmp !== false) { - $this->cache[$this->id][$tmp['date']] = $tmp; - } + $info = $this->parseLogLine($value); + $this->cacheRevisionInfo($info); } if (!isset($this->cache[$this->id][$rev])) { return false; @@ -140,6 +196,9 @@ abstract class ChangeLog $lines = array(); $count = 0; + $logfile = $this->getChangelogFilename(); + if (!file_exists($logfile)) return $revs; + $num = max($num, 0); if ($num == 0) { return $revs; @@ -148,26 +207,22 @@ abstract class ChangeLog if ($first < 0) { $first = 0; } else { - if (file_exists($this->getFilename())) { - // skip current revision if the page exists + $fileLastMod = $this->getFilename(); + if (file_exists($fileLastMod) && $this->isLastRevision(filemtime($fileLastMod))) { + // skip last revision if the page exists $first = max($first + 1, 0); } } - $file = $this->getChangelogFilename(); - - if (!file_exists($file)) { - return $revs; - } - if (filesize($file) < $this->chunk_size || $this->chunk_size == 0) { + if (filesize($logfile) < $this->chunk_size || $this->chunk_size == 0) { // read whole file - $lines = file($file); + $lines = file($logfile); if ($lines === false) { return $revs; } } else { // read chunks backwards - $fp = fopen($file, 'rb'); // "file pointer" + $fp = fopen($logfile, 'rb'); // "file pointer" if ($fp === false) { return $revs; } @@ -221,20 +276,17 @@ abstract class ChangeLog $num = max(min(count($lines) - $first, $num), 0); if ($first > 0 && $num > 0) { $lines = array_slice($lines, max(count($lines) - $first - $num, 0), $num); - } else { - if ($first > 0 && $num == 0) { - $lines = array_slice($lines, 0, max(count($lines) - $first, 0)); - } elseif ($first == 0 && $num > 0) { - $lines = array_slice($lines, max(count($lines) - $num, 0)); - } + } elseif ($first > 0 && $num == 0) { + $lines = array_slice($lines, 0, max(count($lines) - $first, 0)); + } elseif ($first == 0 && $num > 0) { + $lines = array_slice($lines, max(count($lines) - $num, 0)); } // handle lines in reverse order for ($i = count($lines) - 1; $i >= 0; $i--) { - $tmp = parseChangelogLine($lines[$i]); - if ($tmp !== false) { - $this->cache[$this->id][$tmp['date']] = $tmp; - $revs[] = $tmp['date']; + $info = $this->parseLogLine($lines[$i]); + if ($this->cacheRevisionInfo($info)) { + $revs[] = $info['date']; } } @@ -250,8 +302,10 @@ abstract class ChangeLog * Adjacent changelog lines are optimistically parsed and cached to speed up * consecutive calls to getRevisionInfo. * - * @param int $rev revision timestamp used as startdate (doesn't need to be revisionnumber) - * @param int $direction give position of returned revision with respect to $rev; positive=next, negative=prev + * @param int $rev revision timestamp used as startdate + * (doesn't need to be exact revision number) + * @param int $direction give position of returned revision with respect to $rev; + positive=next, negative=prev * @return bool|int * timestamp of the requested revision * otherwise false @@ -270,13 +324,13 @@ abstract class ChangeLog list($fp, $lines, $head, $tail, $eof) = $this->readloglines($rev); if (empty($lines)) return false; - // look for revisions later/earlier then $rev, when founded count till the wanted revision is reached + // look for revisions later/earlier than $rev, when founded count till the wanted revision is reached // also parse and cache changelog lines for getRevisionInfo(). $revcounter = 0; $relativerev = false; $checkotherchunck = true; //always runs once while (!$relativerev && $checkotherchunck) { - $tmp = array(); + $info = array(); //parse in normal or reverse order $count = count($lines); if ($direction > 0) { @@ -287,14 +341,13 @@ abstract class ChangeLog $step = -1; } for ($i = $start; $i >= 0 && $i < $count; $i = $i + $step) { - $tmp = parseChangelogLine($lines[$i]); - if ($tmp !== false) { - $this->cache[$this->id][$tmp['date']] = $tmp; + $info = $this->parseLogLine($lines[$i]); + if ($this->cacheRevisionInfo($info)) { //look for revs older/earlier then reference $rev and select $direction-th one - if (($direction > 0 && $tmp['date'] > $rev) || ($direction < 0 && $tmp['date'] < $rev)) { + if (($direction > 0 && $info['date'] > $rev) || ($direction < 0 && $info['date'] < $rev)) { $revcounter++; if ($revcounter == abs($direction)) { - $relativerev = $tmp['date']; + $relativerev = $info['date']; } } } @@ -302,7 +355,7 @@ abstract class ChangeLog //true when $rev is found, but not the wanted follow-up. $checkotherchunck = $fp - && ($tmp['date'] == $rev || ($revcounter > 0 && !$relativerev)) + && ($info['date'] == $rev || ($revcounter > 0 && !$relativerev)) && !(($tail == $eof && $direction > 0) || ($head == 0 && $direction < 0)); if ($checkotherchunck) { @@ -329,7 +382,7 @@ abstract class ChangeLog */ public function getRevisionsAround($rev1, $rev2, $max = 50) { - $max = floor(abs($max) / 2) * 2 + 1; + $max = intval(abs($max) / 2) * 2 + 1; $rev1 = max($rev1, 0); $rev2 = max($rev2, 0); @@ -341,8 +394,7 @@ abstract class ChangeLog } } else { //empty right side means a removed page. Look up last revision. - $revs = $this->getRevisions(-1, 1); - $rev2 = $revs[0]; + $rev2 = $this->currentRevision(); } //collect revisions around rev2 list($revs2, $allrevs, $fp, $lines, $head, $tail) = $this->retrieveRevisionsAround($rev2, $max); @@ -357,171 +409,31 @@ abstract class ChangeLog if (empty($revs1)) $revs1 = array(); } else { //revisions overlaps, reuse revisions around rev2 + $lastrev = array_pop($allrevs); //keep last entry that could be external edit $revs1 = $allrevs; while ($head > 0) { for ($i = count($lines) - 1; $i >= 0; $i--) { - $tmp = parseChangelogLine($lines[$i]); - if ($tmp !== false) { - $this->cache[$this->id][$tmp['date']] = $tmp; - $revs1[] = $tmp['date']; + $info = $this->parseLogLine($lines[$i]); + if ($this->cacheRevisionInfo($info)) { + $revs1[] = $info['date']; $index++; - if ($index > floor($max / 2)) break 2; + if ($index > intval($max / 2)) break 2; } } list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1); } sort($revs1); + $revs1[] = $lastrev; //push back last entry + //return wanted selection - $revs1 = array_slice($revs1, max($index - floor($max / 2), 0), $max); + $revs1 = array_slice($revs1, max($index - intval($max / 2), 0), $max); } return array(array_reverse($revs1), array_reverse($revs2)); } - - /** - * Checks if the ID has old revisons - * @return boolean - */ - public function hasRevisions() { - $file = $this->getChangelogFilename(); - return file_exists($file); - } - - /** - * Returns lines from changelog. - * If file larger than $chuncksize, only chunck is read that could contain $rev. - * - * @param int $rev revision timestamp - * @return array|false - * if success returns array(fp, array(changeloglines), $head, $tail, $eof) - * where fp only defined for chuck reading, needs closing. - * otherwise false - */ - protected function readloglines($rev) - { - $file = $this->getChangelogFilename(); - - if (!file_exists($file)) { - return false; - } - - $fp = null; - $head = 0; - $tail = 0; - $eof = 0; - - if (filesize($file) < $this->chunk_size || $this->chunk_size == 0) { - // read whole file - $lines = file($file); - if ($lines === false) { - return false; - } - } else { - // read by chunk - $fp = fopen($file, 'rb'); // "file pointer" - if ($fp === false) { - return false; - } - $head = 0; - fseek($fp, 0, SEEK_END); - $eof = ftell($fp); - $tail = $eof; - - // find chunk - while ($tail - $head > $this->chunk_size) { - $finger = $head + floor(($tail - $head) / 2.0); - $finger = $this->getNewlinepointer($fp, $finger); - $tmp = fgets($fp); - if ($finger == $head || $finger == $tail) { - break; - } - $tmp = parseChangelogLine($tmp); - $finger_rev = $tmp['date']; - - if ($finger_rev > $rev) { - $tail = $finger; - } else { - $head = $finger; - } - } - - if ($tail - $head < 1) { - // cound not find chunk, assume requested rev is missing - fclose($fp); - return false; - } - - $lines = $this->readChunk($fp, $head, $tail); - } - return array( - $fp, - $lines, - $head, - $tail, - $eof, - ); - } - - /** - * Read chunk and return array with lines of given chunck. - * Has no check if $head and $tail are really at a new line - * - * @param resource $fp resource filepointer - * @param int $head start point chunck - * @param int $tail end point chunck - * @return array lines read from chunck - */ - protected function readChunk($fp, $head, $tail) - { - $chunk = ''; - $chunk_size = max($tail - $head, 0); // found chunk size - $got = 0; - fseek($fp, $head); - while ($got < $chunk_size && !feof($fp)) { - $tmp = @fread($fp, max(min($this->chunk_size, $chunk_size - $got), 0)); - if ($tmp === false) { //error state - break; - } - $got += strlen($tmp); - $chunk .= $tmp; - } - $lines = explode("\n", $chunk); - array_pop($lines); // remove trailing newline - return $lines; - } - - /** - * Set pointer to first new line after $finger and return its position - * - * @param resource $fp filepointer - * @param int $finger a pointer - * @return int pointer - */ - protected function getNewlinepointer($fp, $finger) - { - fseek($fp, $finger); - $nl = $finger; - if ($finger > 0) { - fgets($fp); // slip the finger forward to a new line - $nl = ftell($fp); - } - return $nl; - } - - /** - * Check whether given revision is the current page - * - * @param int $rev timestamp of current page - * @return bool true if $rev is current revision, otherwise false - */ - public function isCurrentRevision($rev) - { - return $rev == @filemtime($this->getFilename()); - } - /** * Return an existing revision for a specific date which is * the current one or younger or equal then the date @@ -531,8 +443,9 @@ abstract class ChangeLog */ public function getLastRevisionAt($date_at) { + $fileLastMod = $this->getFilename(); //requested date_at(timestamp) younger or equal then modified_time($this->id) => load current - if (file_exists($this->getFilename()) && $date_at >= @filemtime($this->getFilename())) { + if (file_exists($fileLastMod) && $date_at >= @filemtime($fileLastMod)) { return ''; } else { if ($rev = $this->getRelativeRevision($date_at + 1, -1)) { //+1 to get also the requested date revision @@ -544,50 +457,12 @@ abstract class ChangeLog } /** - * Returns the next lines of the changelog of the chunck before head or after tail - * - * @param resource $fp filepointer - * @param int $head position head of last chunk - * @param int $tail position tail of last chunk - * @param int $direction positive forward, negative backward - * @return array with entries: - * - $lines: changelog lines of readed chunk - * - $head: head of chunk - * - $tail: tail of chunk - */ - protected function readAdjacentChunk($fp, $head, $tail, $direction) - { - if (!$fp) return array(array(), $head, $tail); - - if ($direction > 0) { - //read forward - $head = $tail; - $tail = $head + floor($this->chunk_size * (2 / 3)); - $tail = $this->getNewlinepointer($fp, $tail); - } else { - //read backward - $tail = $head; - $head = max($tail - $this->chunk_size, 0); - while (true) { - $nl = $this->getNewlinepointer($fp, $head); - // was the chunk big enough? if not, take another bite - if ($nl > 0 && $tail <= $nl) { - $head = max($head - $this->chunk_size, 0); - } else { - $head = $nl; - break; - } - } - } - - //load next chunck - $lines = $this->readChunk($fp, $head, $tail); - return array($lines, $head, $tail); - } - - /** * Collect the $max revisions near to the timestamp $rev * + * Ideally, half of retrieved timestamps are older than $rev, another half are newer. + * The returned array $requestedrevs may not contain the reference timestamp $rev + * when it does not match any revision value recorded in changelog. + * * @param int $rev revision timestamp * @param int $max maximum number of revisions to be returned * @return bool|array @@ -602,38 +477,49 @@ abstract class ChangeLog */ protected function retrieveRevisionsAround($rev, $max) { + $revs = array(); + $aftercount = $beforecount = 0; + //get lines from changelog - list($fp, $lines, $starthead, $starttail, /* $eof */) = $this->readloglines($rev); + list($fp, $lines, $starthead, $starttail, $eof) = $this->readloglines($rev); if (empty($lines)) return false; - //parse chunk containing $rev, and read forward more chunks until $max/2 is reached + //parse changelog lines in chunk, and read forward more chunks until $max/2 is reached $head = $starthead; $tail = $starttail; - $revs = array(); - $aftercount = $beforecount = 0; while (count($lines) > 0) { foreach ($lines as $line) { - $tmp = parseChangelogLine($line); - if ($tmp !== false) { - $this->cache[$this->id][$tmp['date']] = $tmp; - $revs[] = $tmp['date']; - if ($tmp['date'] >= $rev) { + $info = $this->parseLogLine($line); + if ($this->cacheRevisionInfo($info)) { + $revs[] = $info['date']; + if ($info['date'] >= $rev) { //count revs after reference $rev $aftercount++; if ($aftercount == 1) $beforecount = count($revs); } //enough revs after reference $rev? - if ($aftercount > floor($max / 2)) break 2; + if ($aftercount > intval($max / 2)) break 2; } } //retrieve next chunk list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, 1); } - if ($aftercount == 0) return false; - $lasttail = $tail; - //read additional chuncks backward until $max/2 is reached and total number of revs is equal to $max + // add a possible revision of external edit, create or deletion + if ($lasttail == $eof && $aftercount <= intval($max / 2) && + count($revs) && !$this->isCurrentRevision($revs[count($revs)-1]) + ) { + $revs[] = $this->currentRevision; + $aftercount++; + } + + if ($aftercount == 0) { + //given timestamp $rev is newer than the most recent line in chunk + return false; //FIXME: or proceed to collect older revisions? + } + + //read more chunks backward until $max/2 is reached and total number of revs is equal to $max $lines = array(); $i = 0; if ($aftercount > 0) { @@ -643,24 +529,138 @@ abstract class ChangeLog list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1); for ($i = count($lines) - 1; $i >= 0; $i--) { - $tmp = parseChangelogLine($lines[$i]); - if ($tmp !== false) { - $this->cache[$this->id][$tmp['date']] = $tmp; - $revs[] = $tmp['date']; + $info = $this->parseLogLine($lines[$i]); + if ($this->cacheRevisionInfo($info)) { + $revs[] = $info['date']; $beforecount++; //enough revs before reference $rev? - if ($beforecount > max(floor($max / 2), $max - $aftercount)) break 2; + if ($beforecount > max(intval($max / 2), $max - $aftercount)) break 2; } } } } - sort($revs); - //keep only non-parsed lines $lines = array_slice($lines, 0, $i); + + sort($revs); + //trunk desired selection $requestedrevs = array_slice($revs, -$max, $max); return array($requestedrevs, $revs, $fp, $lines, $head, $lasttail); } + + /** + * Get the current revision information, considering external edit, create or deletion + * + * When the file has not modified since its last revision, the infomation of the last + * change that had already recorded in the changelog is returned as current change info. + * Otherwise, the change infomation since the last revision caused outside DokuWiki + * should be returned, which is referred as "external revision". + * + * The change date of the file can be determined by timestamp as far as the file exists, + * however this is not possible when the file has already deleted outside of DokuWiki. + * In such case we assign 1 sec before current time() for the external deletion. + * As a result, the value of current revision identifier may change each time because: + * 1) the file has again modified outside of DokuWiki, or + * 2) the value is essentially volatile for deleted but once existed files. + * + * @return bool|array false when page had never existed or array with entries: + * - date: revision identifier (timestamp or last revision +1) + * - ip: IPv4 address (127.0.0.1) + * - type: log line type + * - id: id of page or media + * - user: user name + * - sum: edit summary (or action reason) + * - extra: extra data (varies by line type) + * - sizechange: change of filesize + * - timestamp: unix timestamp or false (key set only for external edit occurred) + * + * @author Satoshi Sahara <sahara.satoshi@gmail.com> + */ + public function getCurrentRevisionInfo() + { + global $lang; + + if (isset($this->currentRevision)) return $this->getRevisionInfo($this->currentRevision); + + // get revision id from the item file timestamp and chagelog + $fileLastMod = $this->getFilename(); + $fileRev = @filemtime($fileLastMod); // false when the file not exist + $lastRev = $this->lastRevision(); // false when no changelog + + if (!$fileRev && !$lastRev) { // has never existed + $this->currentRevision = false; + return false; + } elseif ($fileRev === $lastRev) { // not external edit + $this->currentRevision = $lastRev; + return $this->getRevisionInfo($lastRev); + } + + if (!$fileRev && $lastRev) { // item file does not exist + // check consistency against changelog + $revInfo = $this->getRevisionInfo($lastRev, false); + if ($revInfo['type'] == DOKU_CHANGE_TYPE_DELETE) { + $this->currentRevision = $lastRev; + return $revInfo; + } + + // externally deleted, set revision date as late as possible + $revInfo = [ + 'date' => max($lastRev +1, time() -1), // 1 sec before now or new page save + 'ip' => '127.0.0.1', + 'type' => DOKU_CHANGE_TYPE_DELETE, + 'id' => $this->id, + 'user' => '', + 'sum' => $lang['deleted'].' - '.$lang['external_edit'].' ('.$lang['unknowndate'].')', + 'extra' => '', + 'sizechange' => -io_getSizeFile($this->getFilename($lastRev)), + 'timestamp' => false, + ]; + + } else { // item file exists, with timestamp $fileRev + // here, file timestamp $fileRev is different with last revision timestamp $lastRev in changelog + $isJustCreated = $lastRev === false || ( + $fileRev > $lastRev && + $this->getRevisionInfo($lastRev, false)['type'] == DOKU_CHANGE_TYPE_DELETE + ); + $filesize_new = filesize($this->getFilename()); + $filesize_old = $isJustCreated ? 0 : io_getSizeFile($this->getFilename($lastRev)); + $sizechange = $filesize_new - $filesize_old; + + if ($isJustCreated) { + $timestamp = $fileRev; + $sum = $lang['created'].' - '.$lang['external_edit']; + } elseif ($fileRev > $lastRev) { + $timestamp = $fileRev; + $sum = $lang['external_edit']; + } else { + // $fileRev is older than $lastRev, that is erroneous/incorrect occurence. + $msg = "Warning: current file modification time is older than last revision date"; + $details = 'File revision: '.$fileRev.' '.strftime("%Y-%m-%d %H:%M:%S", $fileRev)."\n" + .'Last revision: '.$lastRev.' '.strftime("%Y-%m-%d %H:%M:%S", $lastRev); + Logger::error($msg, $details, $this->getFilename()); + $timestamp = false; + $sum = $lang['external_edit'].' ('.$lang['unknowndate'].')'; + } + + // externally created or edited + $revInfo = [ + 'date' => $timestamp ?: $lastRev +1, + 'ip' => '127.0.0.1', + 'type' => $isJustCreated ? DOKU_CHANGE_TYPE_CREATE : DOKU_CHANGE_TYPE_EDIT, + 'id' => $this->id, + 'user' => '', + 'sum' => $sum, + 'extra' => '', + 'sizechange' => $sizechange, + 'timestamp' => $timestamp, + ]; + } + + // cache current revision information of external edition + $this->currentRevision = $revInfo['date']; + $this->cache[$this->id][$this->currentRevision] = $revInfo; + return $this->getRevisionInfo($this->currentRevision); + } } diff --git a/inc/ChangeLog/ChangeLogTrait.php b/inc/ChangeLog/ChangeLogTrait.php new file mode 100644 index 000000000..3b7f8ca51 --- /dev/null +++ b/inc/ChangeLog/ChangeLogTrait.php @@ -0,0 +1,269 @@ +<?php + +namespace dokuwiki\ChangeLog; + +use dokuwiki\Utf8\PhpString; + +/** + * Provides methods for handling of changelog + */ +trait ChangeLogTrait +{ + /** + * Adds an entry to the changelog file + * + * @return array added logline as revision info + */ + abstract public function addLogEntry(array $info, $timestamp = null); + + /** + * Parses a changelog line into it's components + * + * @author Ben Coburn <btcoburn@silicodon.net> + * + * @param string $line changelog line + * @return array|bool parsed line or false + */ + public static function parseLogLine($line) + { + $info = explode("\t", rtrim($line, "\n")); + if ($info !== false && count($info) > 1) { + return [ + 'date' => (int)$info[0], // unix timestamp + 'ip' => $info[1], // IPv4 address (127.0.0.1) + 'type' => $info[2], // log line type + 'id' => $info[3], // page id + 'user' => $info[4], // user name + 'sum' => $info[5], // edit summary (or action reason) + 'extra' => $info[6], // extra data (varies by line type) + 'sizechange' => (isset($info[7]) && $info[7] !== '') ? (int)$info[7] : null, // + ]; + } else { + return false; + } + } + + /** + * Build a changelog line from it's components + * + * @param array $info Revision info structure + * @param int $timestamp logline date (optional) + * @return string changelog line + */ + public static function buildLogLine(array &$info, $timestamp = null) + { + $strip = ["\t", "\n"]; + $entry = array( + 'date' => $timestamp ?? $info['date'], + 'ip' => $info['ip'], + 'type' => str_replace($strip, '', $info['type']), + 'id' => $info['id'], + 'user' => $info['user'], + 'sum' => PhpString::substr(str_replace($strip, '', $info['sum']), 0, 255), + 'extra' => str_replace($strip, '', $info['extra']), + 'sizechange' => $info['sizechange'], + ); + $info = $entry; + return implode("\t", $entry) ."\n"; + } + + /** + * Returns path to changelog + * + * @return string path to file + */ + abstract protected function getChangelogFilename(); + + /** + * Checks if the ID has old revisons + * @return boolean + */ + public function hasRevisions() + { + $logfile = $this->getChangelogFilename(); + return file_exists($logfile); + } + + + /** @var int */ + protected $chunk_size; + + /** + * Set chunk size for file reading + * Chunk size zero let read whole file at once + * + * @param int $chunk_size maximum block size read from file + */ + public function setChunkSize($chunk_size) + { + if (!is_numeric($chunk_size)) $chunk_size = 0; + + $this->chunk_size = (int)max($chunk_size, 0); + } + + /** + * Returns lines from changelog. + * If file larger than $chuncksize, only chunck is read that could contain $rev. + * + * When reference timestamp $rev is outside time range of changelog, readloglines() will return + * lines in first or last chunk, but they obviously does not contain $rev. + * + * @param int $rev revision timestamp + * @return array|false + * if success returns array(fp, array(changeloglines), $head, $tail, $eof) + * where fp only defined for chuck reading, needs closing. + * otherwise false + */ + protected function readloglines($rev) + { + $file = $this->getChangelogFilename(); + + if (!file_exists($file)) { + return false; + } + + $fp = null; + $head = 0; + $tail = 0; + $eof = 0; + + if (filesize($file) < $this->chunk_size || $this->chunk_size == 0) { + // read whole file + $lines = file($file); + if ($lines === false) { + return false; + } + } else { + // read by chunk + $fp = fopen($file, 'rb'); // "file pointer" + if ($fp === false) { + return false; + } + fseek($fp, 0, SEEK_END); + $eof = ftell($fp); + $tail = $eof; + + // find chunk + while ($tail - $head > $this->chunk_size) { + $finger = $head + intval(($tail - $head) / 2); + $finger = $this->getNewlinepointer($fp, $finger); + $tmp = fgets($fp); + if ($finger == $head || $finger == $tail) { + break; + } + $info = $this->parseLogLine($tmp); + $finger_rev = $info['date']; + + if ($finger_rev > $rev) { + $tail = $finger; + } else { + $head = $finger; + } + } + + if ($tail - $head < 1) { + // cound not find chunk, assume requested rev is missing + fclose($fp); + return false; + } + + $lines = $this->readChunk($fp, $head, $tail); + } + return array( + $fp, + $lines, + $head, + $tail, + $eof, + ); + } + + /** + * Read chunk and return array with lines of given chunck. + * Has no check if $head and $tail are really at a new line + * + * @param resource $fp resource filepointer + * @param int $head start point chunck + * @param int $tail end point chunck + * @return array lines read from chunck + */ + protected function readChunk($fp, $head, $tail) + { + $chunk = ''; + $chunk_size = max($tail - $head, 0); // found chunk size + $got = 0; + fseek($fp, $head); + while ($got < $chunk_size && !feof($fp)) { + $tmp = @fread($fp, max(min($this->chunk_size, $chunk_size - $got), 0)); + if ($tmp === false) { //error state + break; + } + $got += strlen($tmp); + $chunk .= $tmp; + } + $lines = explode("\n", $chunk); + array_pop($lines); // remove trailing newline + return $lines; + } + + /** + * Set pointer to first new line after $finger and return its position + * + * @param resource $fp filepointer + * @param int $finger a pointer + * @return int pointer + */ + protected function getNewlinepointer($fp, $finger) + { + fseek($fp, $finger); + $nl = $finger; + if ($finger > 0) { + fgets($fp); // slip the finger forward to a new line + $nl = ftell($fp); + } + return $nl; + } + + /** + * Returns the next lines of the changelog of the chunck before head or after tail + * + * @param resource $fp filepointer + * @param int $head position head of last chunk + * @param int $tail position tail of last chunk + * @param int $direction positive forward, negative backward + * @return array with entries: + * - $lines: changelog lines of readed chunk + * - $head: head of chunk + * - $tail: tail of chunk + */ + protected function readAdjacentChunk($fp, $head, $tail, $direction) + { + if (!$fp) return array(array(), $head, $tail); + + if ($direction > 0) { + //read forward + $head = $tail; + $tail = $head + intval($this->chunk_size * (2 / 3)); + $tail = $this->getNewlinepointer($fp, $tail); + } else { + //read backward + $tail = $head; + $head = max($tail - $this->chunk_size, 0); + while (true) { + $nl = $this->getNewlinepointer($fp, $head); + // was the chunk big enough? if not, take another bite + if ($nl > 0 && $tail <= $nl) { + $head = max($head - $this->chunk_size, 0); + } else { + $head = $nl; + break; + } + } + } + + //load next chunck + $lines = $this->readChunk($fp, $head, $tail); + return array($lines, $head, $tail); + } + +} diff --git a/inc/ChangeLog/MediaChangeLog.php b/inc/ChangeLog/MediaChangeLog.php index 0d7d8d390..8cbea23f9 100644 --- a/inc/ChangeLog/MediaChangeLog.php +++ b/inc/ChangeLog/MediaChangeLog.php @@ -3,7 +3,7 @@ namespace dokuwiki\ChangeLog; /** - * handles changelog of a media file + * Class MediaChangeLog; handles changelog of a media file */ class MediaChangeLog extends ChangeLog { @@ -21,10 +21,40 @@ class MediaChangeLog extends ChangeLog /** * Returns path to current page/media * + * @param string|int $rev empty string or revision timestamp * @return string path to file */ - protected function getFilename() + protected function getFilename($rev = '') { - return mediaFN($this->id); + return mediaFN($this->id, $rev); } + + + + /** + * Adds an entry to the changelog + * + * @param array $info Revision info structure of a media file + * @param int $timestamp logline date (optional) + * @return array revision info of added logline + * + * @see also addMediaLogEntry() in inc/changelog.php file + */ + public function addLogEntry(array $info, $timestamp = null) + { + global $conf; + + if (isset($timestamp)) unset($this->cache[$this->id][$info['date']]); + + // add changelog lines + $logline = $this->buildLogLine($info, $timestamp); + io_saveFile(mediaMetaFN($this->id,'.changes'), $logline, $append = true); + io_saveFile($conf['media_changelog'], $logline, $append = true); //global changelog cache + + // update cache + $this->currentRevision = $info['date']; + $this->cache[$this->id][$this->currentRevision] = $info; + return $info; + } + } diff --git a/inc/ChangeLog/PageChangeLog.php b/inc/ChangeLog/PageChangeLog.php index f1b91dee6..8a67234a6 100644 --- a/inc/ChangeLog/PageChangeLog.php +++ b/inc/ChangeLog/PageChangeLog.php @@ -3,7 +3,7 @@ namespace dokuwiki\ChangeLog; /** - * handles changelog of a wiki page + * Class PageChangeLog; handles changelog of a wiki page */ class PageChangeLog extends ChangeLog { @@ -21,10 +21,40 @@ class PageChangeLog extends ChangeLog /** * Returns path to current page/media * + * @param string|int $rev empty string or revision timestamp * @return string path to file */ - protected function getFilename() + protected function getFilename($rev = '') { - return wikiFN($this->id); + return wikiFN($this->id, $rev); } + + + + /** + * Adds an entry to the changelog + * + * @param array $info Revision info structure of a page + * @param int $timestamp logline date (optional) + * @return array revision info of added logline + * + * @see also addLogEntry() in inc/changelog.php file + */ + public function addLogEntry(array $info, $timestamp = null) + { + global $conf; + + if (isset($timestamp)) unset($this->cache[$this->id][$info['date']]); + + // add changelog lines + $logline = $this->buildLogLine($info, $timestamp); + io_saveFile(metaFN($this->id,'.changes'), $logline, true); + io_saveFile($conf['changelog'], $logline, true); //global changelog cache + + // update cache + $this->currentRevision = $info['date']; + $this->cache[$this->id][$this->currentRevision] = $info; + return $info; + } + } diff --git a/inc/ChangeLog/RevisionInfo.php b/inc/ChangeLog/RevisionInfo.php new file mode 100644 index 000000000..97257693f --- /dev/null +++ b/inc/ChangeLog/RevisionInfo.php @@ -0,0 +1,300 @@ +<?php + +namespace dokuwiki\ChangeLog; + +/** + * Class RevisionInfo + * + * Provides methods to show Revision Information in DokuWiki Ui compoments: + * - Ui\Recent + * - Ui\PageRevisions + * - Ui\MediaRevisions + */ +class RevisionInfo +{ + protected $info; + + /** + * Constructor + * + * @param array $info Revision Infomation structure with entries: + * - date: unix timestamp + * - ip: IPv4 or IPv6 address + * - type: change type (log line type) + * - id: page id + * - user: user name + * - sum: edit summary (or action reason) + * - extra: extra data (varies by line type) + * - sizechange: change of filesize + * additionally, + * - current: (optional) whether current revision or not + * - timestamp: (optional) set only when external edits occurred + */ + public function __construct(array $info) + { + $info['item'] = strrpos($info['id'], '.') ? 'media' : 'page'; + // current is always true for items shown in Ui\Recents + $info['current'] = $info['current'] ?? true; + // revision info may have timestamp key when external edits occurred + $info['timestamp'] = $info['timestamp'] ?? true; + + $this->info = $info; + } + + /** + * fileicon of the page or media file + * used in [Ui\recent] + * + * @return string + */ + public function itemIcon() + { + $id = $this->info['id']; + $html = ''; + switch ($this->info['item']) { + case 'media': // media file revision + $html = media_printicon($id); + break; + case 'page': // page revision + $html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />'; + } + return $html; + } + + /** + * edit date and time of the page or media file + * used in [Ui\recent, Ui\Revisions] + * + * @param bool $checkTimestamp enable timestamp check, alter formatted string when timestamp is false + * @return string + */ + public function editDate($checkTimestamp = false) + { + $formatted = dformat($this->info['date']); + if ($checkTimestamp && $this->info['timestamp'] === false) { + // exact date is unknown for item has externally deleted or older file restored + // when unknown, alter formatted string "YYYY-mm-DD HH:MM" to "____-__-__ __:__" + $formatted = preg_replace('/[0-9a-zA-Z]/','_', $formatted); + } + return '<span class="date">'. $formatted .'</span>'; + } + + /** + * edit summary + * used in [Ui\recent, Ui\Revisions] + * + * @return string + */ + public function editSummary() + { + return '<span class="sum">'.' – '. hsc($this->info['sum']).'</span>'; + } + + /** + * editor of the page or media file + * used in [Ui\recent, Ui\Revisions] + * + * @return string + */ + public function editor() + { + $html = '<span class="user">'; + if ($this->info['user']) { + $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>'; + if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>'; + } else { + $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>'; + } + $html.= '</span>'; + return $html; + } + + /** + * name of the page or media file + * used in [Ui\recent, Ui\Revisions] + * + * @return string + */ + public function itemName() + { + $id = $this->info['id']; + $rev = ($this->info['current']) ? '' : $this->info['date']; + + switch ($this->info['item']) { + case 'media': // media file revision + $params = ['tab_details'=> 'view', 'ns'=> getNS($id), 'image'=> $id]; + if ($rev) $params += ['rev'=> $rev]; + $href = media_managerURL($params, '&'); + if(file_exists(mediaFN($id, $rev))) { + $class = 'wikilink1'; + } else { + $class = 'wikilink2'; + if(!$this->info['current']) { + //revision is not in attic + return $id; + } + } + return '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>'; + case 'page': // page revision + $params = $rev ? ['rev'=> $rev] : []; + $href = wl($id, $params, false, '&'); + $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id; + if (!$display_name) $display_name = $id; + if(page_exists($id, $rev)) { + $class = 'wikilink1'; + } else { + $class = 'wikilink2'; + if(!$this->info['current']) { + //revision is not in attic + return $display_name; + } + } + return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>'; + } + + return ''; + } + + /** + * difflink icon in recents list + * all items in the recents are "current" revision of the page or media + * + * @return string + */ + public function difflinkRecent() + { + global $lang; + $id = $this->info['id']; + + $href = ''; + switch ($this->info['item']) { + case 'media': // media file revision + $revs = (new MediaChangeLog($id))->getRevisions(0, 1); + $showLink = (count($revs) && file_exists(mediaFN($id))); + if ($showLink) { + $href = media_managerURL( + ['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&' + ); + } + break; + case 'page': // page revision + if($this->info['type'] !== DOKU_CHANGE_TYPE_CREATE) { + $href = wl($id, "do=diff", false, '&'); + } + } + + if ($href) { + $html = '<a href="'.$href.'" class="diff_link">' + . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"' + . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />' + . '</a>'; + } else { + $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />'; + } + return $html; + } + + /** + * difflink icon in revsions list + * the icon does not displayed for the current revision + * + * @return string + */ + public function difflinkRevision() + { + global $lang; + $id = $this->info['id']; + $rev = $this->info['date']; + + switch ($this->info['item']) { + case 'media': // media file revision + if ($this->info['current'] || !file_exists(mediaFN($id, $rev))) { + $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />'; + } else { + $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&'); + $html = '<a href="'.$href.'" class="diff_link">' + . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"' + . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />' + . '</a> '; + } + return $html; + case 'page': // page revision + if ($this->info['current'] || !page_exists($id, $rev)) { + $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />'; + } else { + $href = wl($id, "rev=$rev,do=diff", false, '&'); + $html = '<a href="'.$href.'" class="diff_link">' + . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"' + . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />' + . '</a>'; + } + return $html; + } + return ''; + } + + /** + * icon revision link + * used in [Ui\recent] + * + * @return string + */ + public function revisionlink() + { + global $lang; + + if (!actionOK('revisions')) { + return ''; //FIXME check page, media + } + + $id = $this->info['id']; + $href = ''; + switch ($this->info['item']) { + case 'media': // media file revision + $href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&'); + break; + case 'page': // page revision + $href = wl($id, "do=revisions", false, '&'); + } + return '<a href="'.$href.'" class="revisions_link">' + . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"' + . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />' + . '</a>'; + } + + /** + * size change + * used in [Ui\recent, Ui\Revisions] + * + * @return string + */ + public function sizeChange() + { + $class = 'sizechange'; + $value = filesize_h(abs($this->info['sizechange'])); + if ($this->info['sizechange'] > 0) { + $class .= ' positive'; + $value = '+' . $value; + } elseif ($this->info['sizechange'] < 0) { + $class .= ' negative'; + $value = '-' . $value; + } else { + $value = '±' . $value; + } + return '<span class="'.$class.'">'.$value.'</span>'; + } + + /** + * current indicator, used in revison list + * not used in Ui\Recents because recent items are always current one + * + * @return string + */ + public function currentIndicator() + { + global $lang; + return ($this->info['current']) ? '('.$lang['current'].')' : ''; + } + + +} diff --git a/inc/Debug/DebugHelper.php b/inc/Debug/DebugHelper.php index c813e1aaa..6bdd573e7 100644 --- a/inc/Debug/DebugHelper.php +++ b/inc/Debug/DebugHelper.php @@ -52,8 +52,8 @@ class DebugHelper trim( (!empty($call['class']) ? ($call['class'] . '::') : '') . $call['function'] . '()', ':'), - $call['file'], - $call['line'] + $self['file'], + $self['line'] ); } diff --git a/inc/Draft.php b/inc/Draft.php index f80016c8d..ea9431069 100644 --- a/inc/Draft.php +++ b/inc/Draft.php @@ -25,7 +25,7 @@ class Draft { $this->id = $ID; $this->client = $client; - $this->cname = getCacheName($client.$ID, '.draft'); + $this->cname = getCacheName("$client\n$ID", '.draft'); if(file_exists($this->cname) && file_exists(wikiFN($ID))) { if (filemtime($this->cname) < filemtime(wikiFN($ID))) { // remove stale draft diff --git a/inc/File/MediaFile.php b/inc/File/MediaFile.php index 4c27cc65c..d45822ad7 100644 --- a/inc/File/MediaFile.php +++ b/inc/File/MediaFile.php @@ -2,7 +2,7 @@ namespace dokuwiki\File; -use dokuwiki\Utf8\PhpString; +use JpegMeta; class MediaFile { @@ -157,10 +157,10 @@ class MediaFile return auth_quickaclcheck(getNS($this->id).':*'); } - /** @return \JpegMeta */ + /** @return JpegMeta */ public function getMeta() { - if($this->meta === null) $this->meta = new \JpegMeta($this->path); + if($this->meta === null) $this->meta = new JpegMeta($this->path); return $this->meta; } } diff --git a/inc/File/MediaResolver.php b/inc/File/MediaResolver.php new file mode 100644 index 000000000..098584e72 --- /dev/null +++ b/inc/File/MediaResolver.php @@ -0,0 +1,15 @@ +<?php + +namespace dokuwiki\File; + +/** + * Creates an absolute media ID from a relative one + */ +class MediaResolver extends Resolver { + + /** @inheritDoc */ + public function resolveId($id, $rev = '', $isDateAt = false) + { + return cleanID(parent::resolveId($id, $rev, $isDateAt)); + } +} diff --git a/inc/File/PageFile.php b/inc/File/PageFile.php new file mode 100644 index 000000000..965426185 --- /dev/null +++ b/inc/File/PageFile.php @@ -0,0 +1,334 @@ +<?php + +namespace dokuwiki\File; + +use dokuwiki\Cache\CacheInstructions; +use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\Extension\Event; +use dokuwiki\Input\Input; +use dokuwiki\Logger; +use RuntimeException; + +/** + * Class PageFile : handles wiki text file and its change management for specific page + */ +class PageFile +{ + protected $id; + + /* @var PageChangeLog $changelog */ + public $changelog; + + /* @var array $data initial data when event COMMON_WIKIPAGE_SAVE triggered */ + protected $data; + + /** + * PageFile constructor. + * + * @param string $id + */ + public function __construct($id) + { + $this->id = $id; + $this->changelog = new PageChangeLog($this->id); + } + + /** @return string */ + public function getId() + { + return $this->id; + } + + /** @return string */ + public function getPath($rev = '') + { + return wikiFN($this->id, $rev); + } + + /** + * Get raw WikiText of the page, considering change type at revision date + * similar to function rawWiki($id, $rev = '') + * + * @param int|false $rev timestamp when a revision of wikitext is desired + * @return string + */ + public function rawWikiText($rev = null) + { + if ($rev !== null) { + $revInfo = $rev ? $this->changelog->getRevisionInfo($rev) : false; + return (!$revInfo || $revInfo['type'] == DOKU_CHANGE_TYPE_DELETE) + ? '' // attic stores complete last page version for a deleted page + : io_readWikiPage($this->getPath($rev), $this->id, $rev); // retrieve from attic + } else { + return io_readWikiPage($this->getPath(), $this->id, ''); + } + } + + /** + * Saves a wikitext by calling io_writeWikiPage. + * Also directs changelog and attic updates. + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Ben Coburn <btcoburn@silicodon.net> + * + * @param string $text wikitext being saved + * @param string $summary summary of text update + * @param bool $minor mark this saved version as minor update + * @return array|void data of event COMMON_WIKIPAGE_SAVE + */ + public function saveWikiText($text, $summary, $minor = false) + { + /* Note to developers: + This code is subtle and delicate. Test the behavior of + the attic and changelog with dokuwiki and external edits + after any changes. External edits change the wiki page + directly without using php or dokuwiki. + */ + global $conf; + global $lang; + global $REV; + /* @var Input $INPUT */ + global $INPUT; + + // prevent recursive call + if (isset($this->data)) return; + + $pagefile = $this->getPath(); + $currentRevision = @filemtime($pagefile); // int or false + $currentContent = $this->rawWikiText(); + $currentSize = file_exists($pagefile) ? filesize($pagefile) : 0; + + // prepare data for event COMMON_WIKIPAGE_SAVE + $data = array( + 'id' => $this->id, // should not be altered by any handlers + 'file' => $pagefile, // same above + 'changeType' => null, // set prior to event, and confirm later + 'revertFrom' => $REV, + 'oldRevision' => $currentRevision, + 'oldContent' => $currentContent, + 'newRevision' => 0, // only available in the after hook + 'newContent' => $text, + 'summary' => $summary, + 'contentChanged' => ($text != $currentContent), // confirm later + 'changeInfo' => '', // automatically determined by revertFrom + 'sizechange' => strlen($text) - strlen($currentContent), // TBD + ); + + // determine tentatively change type and relevant elements of event data + if ($data['revertFrom']) { + // new text may differ from exact revert revision + $data['changeType'] = DOKU_CHANGE_TYPE_REVERT; + $data['changeInfo'] = $REV; + } elseif (trim($data['newContent']) == '') { + // empty or whitespace only content deletes + $data['changeType'] = DOKU_CHANGE_TYPE_DELETE; + } elseif (!file_exists($pagefile)) { + $data['changeType'] = DOKU_CHANGE_TYPE_CREATE; + } else { + // minor edits allowable only for logged in users + $is_minor_change = ($minor && $conf['useacl'] && $INPUT->server->str('REMOTE_USER')); + $data['changeType'] = $is_minor_change + ? DOKU_CHANGE_TYPE_MINOR_EDIT + : DOKU_CHANGE_TYPE_EDIT; + } + + $this->data = $data; + $data['page'] = $this; // allow event handlers to use this class methods + + $event = new Event('COMMON_WIKIPAGE_SAVE', $data); + if (!$event->advise_before()) return; + + // if the content has not been changed, no save happens (plugins may override this) + if (!$data['contentChanged']) return; + + // Check whether the pagefile has modified during $event->advise_before() + clearstatcache(); + $fileRev = @filemtime($pagefile); + if ($fileRev === $currentRevision) { + // pagefile has not touched by plugin's event handler + // add a potential external edit entry to changelog and store it into attic + $this->detectExternalEdit(); + $filesize_old = $currentSize; + } else { + // pagefile has modified by plugin's event handler, confirm sizechange + $filesize_old = ( + $data['changeType'] == DOKU_CHANGE_TYPE_CREATE || ( + $data['changeType'] == DOKU_CHANGE_TYPE_REVERT && !file_exists($pagefile)) + ) ? 0 : filesize($pagefile); + } + + // make change to the current file + if ($data['changeType'] == DOKU_CHANGE_TYPE_DELETE) { + // nothing to do when the file has already deleted + if (!file_exists($pagefile)) return; + // autoset summary on deletion + if (blank($data['summary'])) { + $data['summary'] = $lang['deleted']; + } + // send "update" event with empty data, so plugins can react to page deletion + $ioData = array([$pagefile, '', false], getNS($this->id), noNS($this->id), false); + Event::createAndTrigger('IO_WIKIPAGE_WRITE', $ioData); + // pre-save deleted revision + @touch($pagefile); + clearstatcache(); + $data['newRevision'] = $this->saveOldRevision(); + // remove empty file + @unlink($pagefile); + $filesize_new = 0; + // don't remove old meta info as it should be saved, plugins can use + // IO_WIKIPAGE_WRITE for removing their metadata... + // purge non-persistant meta data + p_purge_metadata($this->id); + // remove empty namespaces + io_sweepNS($this->id, 'datadir'); + io_sweepNS($this->id, 'mediadir'); + } else { + // save file (namespace dir is created in io_writeWikiPage) + io_writeWikiPage($pagefile, $data['newContent'], $this->id); + // pre-save the revision, to keep the attic in sync + $data['newRevision'] = $this->saveOldRevision(); + $filesize_new = filesize($pagefile); + } + $data['sizechange'] = $filesize_new - $filesize_old; + + $event->advise_after(); + + unset($data['page']); + + // adds an entry to the changelog and saves the metadata for the page + $logEntry = $this->changelog->addLogEntry([ + 'date' => $data['newRevision'], + 'ip' => clientIP(true), + 'type' => $data['changeType'], + 'id' => $this->id, + 'user' => $INPUT->server->str('REMOTE_USER'), + 'sum' => $data['summary'], + 'extra' => $data['changeInfo'], + 'sizechange' => $data['sizechange'], + ]); + // update metadata + $this->updateMetadata($logEntry); + + // update the purgefile (timestamp of the last time anything within the wiki was changed) + io_saveFile($conf['cachedir'].'/purgefile', time()); + + return $data; + } + + /** + * Checks if the current page version is newer than the last entry in the page's changelog. + * If so, we assume it has been an external edit and we create an attic copy and add a proper + * changelog line. + * + * This check is only executed when the page is about to be saved again from the wiki, + * triggered in @see saveWikiText() + */ + public function detectExternalEdit() + { + $revInfo = $this->changelog->getCurrentRevisionInfo(); + + // only interested in external revision + if (empty($revInfo) || !array_key_exists('timestamp', $revInfo)) return; + + if ($revInfo['type'] != DOKU_CHANGE_TYPE_DELETE && !$revInfo['timestamp']) { + // file is older than last revision, that is erroneous/incorrect occurence. + // try to change file modification time + $fileLastMod = $this->getPath(); + $wrong_timestamp = filemtime($fileLastMod); + if (touch($fileLastMod, $revInfo['date'])) { + clearstatcache(); + $msg = "PageFile($this->id)::detectExternalEdit(): timestamp successfully modified"; + $details = '('.$wrong_timestamp.' -> '.$revInfo['date'].')'; + Logger::error($msg, $details, $fileLastMod); + } else { + // runtime error + $msg = "PageFile($this->id)::detectExternalEdit(): page file should be newer than last revision " + .'('.filemtime($fileLastMod).' < '. $this->changelog->lastRevision() .')'; + throw new RuntimeException($msg); + } + } + + // keep at least 1 sec before new page save + if ($revInfo['date'] == time()) sleep(1); // wait a tick + + // store externally edited file to the attic folder + $this->saveOldRevision(); + // add a changelog entry for externally edited file + $this->changelog->addLogEntry($revInfo); + // remove soon to be stale instructions + $cache = new CacheInstructions($this->id, $this->getPath()); + $cache->removeCache(); + } + + /** + * Moves the current version to the attic and returns its revision date + * + * @author Andreas Gohr <andi@splitbrain.org> + * + * @return int|string revision timestamp + */ + public function saveOldRevision() + { + $oldfile = $this->getPath(); + if (!file_exists($oldfile)) return ''; + $date = filemtime($oldfile); + $newfile = $this->getPath($date); + io_writeWikiPage($newfile, $this->rawWikiText(), $this->id, $date); + return $date; + } + + /** + * Update metadata of changed page + * + * @param array $logEntry changelog entry + */ + public function updateMetadata(array $logEntry) + { + global $INFO; + + list( + 'date' => $date, + 'type' => $changeType, + 'user' => $user, + ) = $logEntry; + + $wasRemoved = ($changeType === DOKU_CHANGE_TYPE_DELETE); + $wasCreated = ($changeType === DOKU_CHANGE_TYPE_CREATE); + $wasReverted = ($changeType === DOKU_CHANGE_TYPE_REVERT); + $wasMinorEdit = ($changeType === DOKU_CHANGE_TYPE_MINOR_EDIT); + + $createdDate = @filectime($this->getPath()); + + if ($wasRemoved) return; + + $oldmeta = p_read_metadata($this->id)['persistent']; + $meta = array(); + + if ($wasCreated && + (empty($oldmeta['date']['created']) || $oldmeta['date']['created'] === $createdDate) + ) { + // newly created + $meta['date']['created'] = $createdDate; + if ($user) { + $meta['creator'] = $INFO['userinfo']['name'] ?? null; + $meta['user'] = $user; + } + } elseif (($wasCreated || $wasReverted) && !empty($oldmeta['date']['created'])) { + // re-created / restored + $meta['date']['created'] = $oldmeta['date']['created']; + $meta['date']['modified'] = $createdDate; // use the files ctime here + $meta['creator'] = $oldmeta['creator'] ?? null; + if ($user) { + $meta['contributor'][$user] = $INFO['userinfo']['name'] ?? null; + } + } elseif (!$wasMinorEdit) { // non-minor modification + $meta['date']['modified'] = $date; + if ($user) { + $meta['contributor'][$user] = $INFO['userinfo']['name'] ?? null; + } + } + $meta['last_change'] = $logEntry; + p_set_metadata($this->id, $meta); + } + +} diff --git a/inc/File/PageResolver.php b/inc/File/PageResolver.php new file mode 100644 index 000000000..7ed5b1cd8 --- /dev/null +++ b/inc/File/PageResolver.php @@ -0,0 +1,98 @@ +<?php + +namespace dokuwiki\File; + +/** + * Creates an absolute page ID from a relative one + */ +class PageResolver extends Resolver +{ + + /** + * Resolves a given ID to be absolute + * + * This handles all kinds of relative shortcuts, startpages and autoplurals + * @inheritDoc + */ + public function resolveId($id, $rev = '', $isDateAt = false) + { + global $conf; + + // pages may have a hash attached, we separate it on resolving + if (strpos($id, '#') !== false) { + list($id, $hash) = explode('#', $id, 2); + $hash = cleanID($hash); + } else { + $hash = ''; + } + + if ($id !== '') { + $id = parent::resolveId($id, $rev, $isDateAt); + $id = $this->resolveStartPage($id, $rev, $isDateAt); + if ($conf['autoplural']) { + $id = $this->resolveAutoPlural($id, $rev, $isDateAt); + } + } else { + $id = $this->contextID; + } + + $id = cleanID($id); // FIXME always? or support parameter + // readd hash if any + if ($hash !== '') $id .= "#$hash"; + return $id; + } + + /** + * IDs ending in : + * + * @param string $id + * @param string|int|false $rev + * @param bool $isDateAt + * @return string + */ + protected function resolveStartPage($id, $rev, $isDateAt) + { + global $conf; + + if ($id[-1] !== ':') return $id; + + if (page_exists($id . $conf['start'], $rev, true, $isDateAt)) { + // start page inside namespace + return $id . $conf['start']; + } elseif (page_exists($id . noNS(cleanID($id)), $rev, true, $isDateAt)) { + // page named like the NS inside the NS + return $id . noNS(cleanID($id)); + } elseif (page_exists(substr($id, 0, -1), $rev, true, $isDateAt)) { + // page named like the NS outside the NS + return substr($id, 0, -1); + } + + // fall back to default start page + return $id . $conf['start']; + } + + /** + * Try alternative plural/singular form + * + * @param string $id + * @param int $rev + * @param bool $isDateAt + * @return string + */ + protected function resolveAutoPlural($id, $rev, $isDateAt) + { + if (page_exists($id, $rev, $isDateAt)) return $id; + + if ($id[-1] === 's') { + $try = substr($id, 0, -1); + } else { + $try = $id . 's'; + } + + if (page_exists($try, $rev, true, $isDateAt)) { + return $try; + } + return $id; + } + +} diff --git a/inc/File/Resolver.php b/inc/File/Resolver.php new file mode 100644 index 000000000..3347a1b42 --- /dev/null +++ b/inc/File/Resolver.php @@ -0,0 +1,104 @@ +<?php + +namespace dokuwiki\File; + +/** + * Resolving relative IDs to absolute ones + */ +abstract class Resolver +{ + + /** @var string context page ID */ + protected $contextID; + /** @var string namespace of context page ID */ + protected $contextNS; + + /** + * @param string $contextID the current pageID that's the context to resolve relative IDs to + */ + public function __construct($contextID) + { + $this->contextID = $contextID; + $this->contextNS = (string)getNS($contextID); + } + + /** + * Resolves a given ID to be absolute + * + * @param string $id The ID to resolve + * @param string|int|false $rev The revision time to use when resolving + * @param bool $isDateAt Is the given revision only a datetime hint not an exact revision? + * @return string + */ + public function resolveId($id, $rev = '', $isDateAt = false) + { + global $conf; + + // some pre cleaning for useslash: + if ($conf['useslash']) $id = str_replace('/', ':', $id); + // on some systems, semicolons might be used instead of colons: + $id = str_replace(';', ':', $id); + + $id = $this->resolvePrefix($id); + return $this->resolveRelatives($id); + } + + /** + * Handle IDs starting with . or ~ and prepend the proper prefix + * + * @param string $id + * @return string + */ + protected function resolvePrefix($id) + { + // relative to current page (makes the current page a start page) + if ($id[0] === '~') { + $id = $this->contextID . ':' . substr($id, 1); + } + + // relative to current namespace + if ($id[0] === '.') { + // normalize initial dots without a colon + $id = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/', '\1\3:', $id); + $id = $this->contextNS . ':' . $id; + } + + // auto-relative, because there is a context namespace but no namespace in the ID + if ($this->contextID !== '' && strpos($id, ':') === false) { + $id = $this->contextNS . ':' . $id; + } + + return $id; + } + + /** + * Handle . and .. within IDs + * + * @param string $id + * @return string + */ + protected function resolveRelatives($id) + { + if ($id === '') return ''; + $trail = ($id[-1] === ':') ? ':' : ''; // keep trailing colon + + $result = []; + $parts = explode(':', $id); + + foreach ($parts as $dir) { + if ($dir === '.') continue; + if ($dir === '') continue; + if ($dir === '..') { + array_pop($result); + continue; + } + array_push($result, $dir); + } + + $id = implode(':', $result); + $id .= $trail; + + return $id; + } + +} diff --git a/inc/HTTP/HTTPClient.php b/inc/HTTP/HTTPClient.php index 7ba95a7b6..5c7491ee9 100644 --- a/inc/HTTP/HTTPClient.php +++ b/inc/HTTP/HTTPClient.php @@ -772,7 +772,7 @@ class HTTPClient { foreach($lines as $line){ @list($key, $val) = explode(':',$line,2); $key = trim($key); - $val = trim($val); + $val = trim($val ?? ''); $key = strtolower($key); if(!$key) continue; if(isset($headers[$key])){ diff --git a/inc/IXR_Library.php b/inc/IXR_Library.php deleted file mode 100644 index bb1655f10..000000000 --- a/inc/IXR_Library.php +++ /dev/null @@ -1,1135 +0,0 @@ -<?php - -use dokuwiki\HTTP\DokuHTTPClient; - -/** - * IXR - The Incutio XML-RPC Library - * - * Copyright (c) 2010, Incutio Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of Incutio Ltd. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @package IXR - * @since 1.5 - * - * @copyright Incutio Ltd 2010 (http://www.incutio.com) - * @version 1.7.4 7th September 2010 - * @author Simon Willison - * @link http://scripts.incutio.com/xmlrpc/ Site/manual - * - * Modified for DokuWiki - * @author Andreas Gohr <andi@splitbrain.org> - */ -class IXR_Value { - - /** @var IXR_Value[]|IXR_Date|IXR_Base64|int|bool|double|string */ - var $data; - /** @var string */ - var $type; - - /** - * @param mixed $data - * @param bool $type - */ - function __construct($data, $type = false) { - $this->data = $data; - if(!$type) { - $type = $this->calculateType(); - } - $this->type = $type; - if($type == 'struct') { - // Turn all the values in the array in to new IXR_Value objects - foreach($this->data as $key => $value) { - $this->data[$key] = new IXR_Value($value); - } - } - if($type == 'array') { - for($i = 0, $j = count($this->data); $i < $j; $i++) { - $this->data[$i] = new IXR_Value($this->data[$i]); - } - } - } - - /** - * @return string - */ - function calculateType() { - if($this->data === true || $this->data === false) { - return 'boolean'; - } - if(is_integer($this->data)) { - return 'int'; - } - if(is_double($this->data)) { - return 'double'; - } - - // Deal with IXR object types base64 and date - if(is_object($this->data) && is_a($this->data, 'IXR_Date')) { - return 'date'; - } - if(is_object($this->data) && is_a($this->data, 'IXR_Base64')) { - return 'base64'; - } - - // If it is a normal PHP object convert it in to a struct - if(is_object($this->data)) { - $this->data = get_object_vars($this->data); - return 'struct'; - } - if(!is_array($this->data)) { - return 'string'; - } - - // We have an array - is it an array or a struct? - if($this->isStruct($this->data)) { - return 'struct'; - } else { - return 'array'; - } - } - - /** - * @return bool|string - */ - function getXml() { - // Return XML for this value - switch($this->type) { - case 'boolean': - return '<boolean>' . (($this->data) ? '1' : '0') . '</boolean>'; - break; - case 'int': - return '<int>' . $this->data . '</int>'; - break; - case 'double': - return '<double>' . $this->data . '</double>'; - break; - case 'string': - return '<string>' . htmlspecialchars($this->data) . '</string>'; - break; - case 'array': - $return = '<array><data>' . "\n"; - foreach($this->data as $item) { - $return .= ' <value>' . $item->getXml() . "</value>\n"; - } - $return .= '</data></array>'; - return $return; - break; - case 'struct': - $return = '<struct>' . "\n"; - foreach($this->data as $name => $value) { - $return .= " <member><name>$name</name><value>"; - $return .= $value->getXml() . "</value></member>\n"; - } - $return .= '</struct>'; - return $return; - break; - case 'date': - case 'base64': - return $this->data->getXml(); - break; - } - return false; - } - - /** - * Checks whether or not the supplied array is a struct or not - * - * @param array $array - * @return boolean - */ - function isStruct($array) { - $expected = 0; - foreach($array as $key => $value) { - if((string) $key != (string) $expected) { - return true; - } - $expected++; - } - return false; - } -} - -/** - * IXR_MESSAGE - * - * @package IXR - * @since 1.5 - * - */ -class IXR_Message { - var $message; - var $messageType; // methodCall / methodResponse / fault - var $faultCode; - var $faultString; - var $methodName; - var $params; - - // Current variable stacks - var $_arraystructs = array(); // The stack used to keep track of the current array/struct - var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array - var $_currentStructName = array(); // A stack as well - var $_param; - var $_value; - var $_currentTag; - var $_currentTagContents; - var $_lastseen; - // The XML parser - var $_parser; - - /** - * @param string $message - */ - function __construct($message) { - $this->message =& $message; - } - - /** - * @return bool - */ - function parse() { - // first remove the XML declaration - // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages - $header = preg_replace('/<\?xml.*?\?' . '>/', '', substr($this->message, 0, 100), 1); - $this->message = substr_replace($this->message, $header, 0, 100); - - // workaround for a bug in PHP/libxml2, see http://bugs.php.net/bug.php?id=45996 - $this->message = str_replace('<', '<', $this->message); - $this->message = str_replace('>', '>', $this->message); - $this->message = str_replace('&', '&', $this->message); - $this->message = str_replace(''', ''', $this->message); - $this->message = str_replace('"', '"', $this->message); - $this->message = str_replace("\x0b", ' ', $this->message); //vertical tab - if(trim($this->message) == '') { - return false; - } - $this->_parser = xml_parser_create(); - // Set XML parser to take the case of tags in to account - xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); - // Set XML parser callback functions - xml_set_object($this->_parser, $this); - xml_set_element_handler($this->_parser, 'tag_open', 'tag_close'); - xml_set_character_data_handler($this->_parser, 'cdata'); - $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages - $final = false; - do { - if(strlen($this->message) <= $chunk_size) { - $final = true; - } - $part = substr($this->message, 0, $chunk_size); - $this->message = substr($this->message, $chunk_size); - if(!xml_parse($this->_parser, $part, $final)) { - return false; - } - if($final) { - break; - } - } while(true); - xml_parser_free($this->_parser); - - // Grab the error messages, if any - if($this->messageType == 'fault') { - $this->faultCode = $this->params[0]['faultCode']; - $this->faultString = $this->params[0]['faultString']; - } - return true; - } - - /** - * @param $parser - * @param string $tag - * @param $attr - */ - function tag_open($parser, $tag, $attr) { - $this->_currentTagContents = ''; - $this->_currentTag = $tag; - - switch($tag) { - case 'methodCall': - case 'methodResponse': - case 'fault': - $this->messageType = $tag; - break; - /* Deal with stacks of arrays and structs */ - case 'data': // data is to all intents and purposes more interesting than array - $this->_arraystructstypes[] = 'array'; - $this->_arraystructs[] = array(); - break; - case 'struct': - $this->_arraystructstypes[] = 'struct'; - $this->_arraystructs[] = array(); - break; - } - $this->_lastseen = $tag; - } - - /** - * @param $parser - * @param string $cdata - */ - function cdata($parser, $cdata) { - $this->_currentTagContents .= $cdata; - } - - /** - * @param $parser - * @param $tag - */ - function tag_close($parser, $tag) { - $value = null; - $valueFlag = false; - switch($tag) { - case 'int': - case 'i4': - $value = (int) trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'double': - $value = (double) trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'string': - $value = (string) $this->_currentTagContents; - $valueFlag = true; - break; - case 'dateTime.iso8601': - $value = new IXR_Date(trim($this->_currentTagContents)); - $valueFlag = true; - break; - case 'value': - // "If no type is indicated, the type is string." - if($this->_lastseen == 'value') { - $value = (string) $this->_currentTagContents; - $valueFlag = true; - } - break; - case 'boolean': - $value = (boolean) trim($this->_currentTagContents); - $valueFlag = true; - break; - case 'base64': - $value = base64_decode($this->_currentTagContents); - $valueFlag = true; - break; - /* Deal with stacks of arrays and structs */ - case 'data': - case 'struct': - $value = array_pop($this->_arraystructs); - array_pop($this->_arraystructstypes); - $valueFlag = true; - break; - case 'member': - array_pop($this->_currentStructName); - break; - case 'name': - $this->_currentStructName[] = trim($this->_currentTagContents); - break; - case 'methodName': - $this->methodName = trim($this->_currentTagContents); - break; - } - - if($valueFlag) { - if(count($this->_arraystructs) > 0) { - // Add value to struct or array - if($this->_arraystructstypes[count($this->_arraystructstypes) - 1] == 'struct') { - // Add to struct - $this->_arraystructs[count($this->_arraystructs) - 1][$this->_currentStructName[count($this->_currentStructName) - 1]] = $value; - } else { - // Add to array - $this->_arraystructs[count($this->_arraystructs) - 1][] = $value; - } - } else { - // Just add as a parameter - $this->params[] = $value; - } - } - $this->_currentTagContents = ''; - $this->_lastseen = $tag; - } -} - -/** - * IXR_Server - * - * @package IXR - * @since 1.5 - */ -class IXR_Server { - var $data; - /** @var array */ - var $callbacks = array(); - var $message; - /** @var array */ - var $capabilities; - - /** - * @param array|bool $callbacks - * @param bool $data - * @param bool $wait - */ - function __construct($callbacks = false, $data = false, $wait = false) { - $this->setCapabilities(); - if($callbacks) { - $this->callbacks = $callbacks; - } - $this->setCallbacks(); - - if(!$wait) { - $this->serve($data); - } - } - - /** - * @param bool|string $data - */ - function serve($data = false) { - if(!$data) { - - $postData = trim(http_get_raw_post_data()); - if(!$postData) { - header('Content-Type: text/plain'); // merged from WP #9093 - die('XML-RPC server accepts POST requests only.'); - } - $data = $postData; - } - $this->message = new IXR_Message($data); - if(!$this->message->parse()) { - $this->error(-32700, 'parse error. not well formed'); - } - if($this->message->messageType != 'methodCall') { - $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); - } - $result = $this->call($this->message->methodName, $this->message->params); - - // Is the result an error? - if(is_a($result, 'IXR_Error')) { - $this->error($result); - } - - // Encode the result - $r = new IXR_Value($result); - $resultxml = $r->getXml(); - - // Create the XML - $xml = <<<EOD -<methodResponse> - <params> - <param> - <value> - $resultxml - </value> - </param> - </params> -</methodResponse> - -EOD; - // Send it - $this->output($xml); - } - - /** - * @param string $methodname - * @param array $args - * @return IXR_Error|mixed - */ - function call($methodname, $args) { - if(!$this->hasMethod($methodname)) { - return new IXR_Error(-32601, 'server error. requested method ' . $methodname . ' does not exist.'); - } - $method = $this->callbacks[$methodname]; - - // Perform the callback and send the response - - # Removed for DokuWiki to have a more consistent interface - # if (count($args) == 1) { - # // If only one parameter just send that instead of the whole array - # $args = $args[0]; - # } - - # Adjusted for DokuWiki to use call_user_func_array - - // args need to be an array - $args = (array) $args; - - // Are we dealing with a function or a method? - if(is_string($method) && substr($method, 0, 5) == 'this:') { - // It's a class method - check it exists - $method = substr($method, 5); - if(!method_exists($this, $method)) { - return new IXR_Error(-32601, 'server error. requested class method "' . $method . '" does not exist.'); - } - // Call the method - #$result = $this->$method($args); - $result = call_user_func_array(array(&$this, $method), $args); - } elseif(substr($method, 0, 7) == 'plugin:') { - list($pluginname, $callback) = explode(':', substr($method, 7), 2); - if(!plugin_isdisabled($pluginname)) { - $plugin = plugin_load('action', $pluginname); - return call_user_func_array(array($plugin, $callback), $args); - } else { - return new IXR_Error(-99999, 'server error'); - } - } else { - // It's a function - does it exist? - if(is_array($method)) { - if(!is_callable(array($method[0], $method[1]))) { - return new IXR_Error(-32601, 'server error. requested object method "' . $method[1] . '" does not exist.'); - } - } else if(!function_exists($method)) { - return new IXR_Error(-32601, 'server error. requested function "' . $method . '" does not exist.'); - } - - // Call the function - $result = call_user_func($method, $args); - } - return $result; - } - - /** - * @param int $error - * @param string|bool $message - */ - function error($error, $message = false) { - // Accepts either an error object or an error code and message - if($message && !is_object($error)) { - $error = new IXR_Error($error, $message); - } - $this->output($error->getXml()); - } - - /** - * @param string $xml - */ - function output($xml) { - header('Content-Type: text/xml; charset=utf-8'); - echo '<?xml version="1.0"?>', "\n", $xml; - exit; - } - - /** - * @param string $method - * @return bool - */ - function hasMethod($method) { - return in_array($method, array_keys($this->callbacks)); - } - - function setCapabilities() { - // Initialises capabilities array - $this->capabilities = array( - 'xmlrpc' => array( - 'specUrl' => 'http://www.xmlrpc.com/spec', - 'specVersion' => 1 - ), - 'faults_interop' => array( - 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', - 'specVersion' => 20010516 - ), - 'system.multicall' => array( - 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', - 'specVersion' => 1 - ), - ); - } - - /** - * @return mixed - */ - function getCapabilities() { - return $this->capabilities; - } - - function setCallbacks() { - $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; - $this->callbacks['system.listMethods'] = 'this:listMethods'; - $this->callbacks['system.multicall'] = 'this:multiCall'; - } - - /** - * @return array - */ - function listMethods() { - // Returns a list of methods - uses array_reverse to ensure user defined - // methods are listed before server defined methods - return array_reverse(array_keys($this->callbacks)); - } - - /** - * @param array $methodcalls - * @return array - */ - function multiCall($methodcalls) { - // See http://www.xmlrpc.com/discuss/msgReader$1208 - $return = array(); - foreach($methodcalls as $call) { - $method = $call['methodName']; - $params = $call['params']; - if($method == 'system.multicall') { - $result = new IXR_Error(-32800, 'Recursive calls to system.multicall are forbidden'); - } else { - $result = $this->call($method, $params); - } - if(is_a($result, 'IXR_Error')) { - $return[] = array( - 'faultCode' => $result->code, - 'faultString' => $result->message - ); - } else { - $return[] = array($result); - } - } - return $return; - } -} - -/** - * IXR_Request - * - * @package IXR - * @since 1.5 - */ -class IXR_Request { - /** @var string */ - var $method; - /** @var array */ - var $args; - /** @var string */ - var $xml; - - /** - * @param string $method - * @param array $args - */ - function __construct($method, $args) { - $this->method = $method; - $this->args = $args; - $this->xml = <<<EOD -<?xml version="1.0"?> -<methodCall> -<methodName>{$this->method}</methodName> -<params> - -EOD; - foreach($this->args as $arg) { - $this->xml .= '<param><value>'; - $v = new IXR_Value($arg); - $this->xml .= $v->getXml(); - $this->xml .= "</value></param>\n"; - } - $this->xml .= '</params></methodCall>'; - } - - /** - * @return int - */ - function getLength() { - return strlen($this->xml); - } - - /** - * @return string - */ - function getXml() { - return $this->xml; - } -} - -/** - * IXR_Client - * - * @package IXR - * @since 1.5 - * - * Changed for DokuWiki to use DokuHTTPClient - * - * This should be compatible to the original class, but uses DokuWiki's - * HTTP client library which will respect proxy settings - * - * Because the XMLRPC client is not used in DokuWiki currently this is completely - * untested - */ -class IXR_Client extends DokuHTTPClient { - var $posturl = ''; - /** @var IXR_Message|bool */ - var $message = false; - - // Storage place for an error message - /** @var IXR_Error|bool */ - var $xmlerror = false; - - /** - * @param string $server - * @param string|bool $path - * @param int $port - * @param int $timeout - */ - function __construct($server, $path = false, $port = 80, $timeout = 15) { - parent::__construct(); - if(!$path) { - // Assume we have been given a URL instead - $this->posturl = $server; - } else { - $this->posturl = 'http://' . $server . ':' . $port . $path; - } - $this->timeout = $timeout; - } - - /** - * parameters: method and arguments - * @return bool success or error - */ - function query() { - $args = func_get_args(); - $method = array_shift($args); - $request = new IXR_Request($method, $args); - $xml = $request->getXml(); - - $this->headers['Content-Type'] = 'text/xml'; - if(!$this->sendRequest($this->posturl, $xml, 'POST')) { - $this->xmlerror = new IXR_Error(-32300, 'transport error - ' . $this->error); - return false; - } - - // Check HTTP Response code - if($this->status < 200 || $this->status > 206) { - $this->xmlerror = new IXR_Error(-32300, 'transport error - HTTP status ' . $this->status); - return false; - } - - // Now parse what we've got back - $this->message = new IXR_Message($this->resp_body); - if(!$this->message->parse()) { - // XML error - $this->xmlerror = new IXR_Error(-32700, 'parse error. not well formed'); - return false; - } - - // Is the message a fault? - if($this->message->messageType == 'fault') { - $this->xmlerror = new IXR_Error($this->message->faultCode, $this->message->faultString); - return false; - } - - // Message must be OK - return true; - } - - /** - * @return mixed - */ - function getResponse() { - // methodResponses can only have one param - return that - return $this->message->params[0]; - } - - /** - * @return bool - */ - function isError() { - return (is_object($this->xmlerror)); - } - - /** - * @return int - */ - function getErrorCode() { - return $this->xmlerror->code; - } - - /** - * @return string - */ - function getErrorMessage() { - return $this->xmlerror->message; - } -} - -/** - * IXR_Error - * - * @package IXR - * @since 1.5 - */ -class IXR_Error { - var $code; - var $message; - - /** - * @param int $code - * @param string $message - */ - function __construct($code, $message) { - $this->code = $code; - $this->message = htmlspecialchars($message); - } - - /** - * @return string - */ - function getXml() { - $xml = <<<EOD -<methodResponse> - <fault> - <value> - <struct> - <member> - <name>faultCode</name> - <value><int>{$this->code}</int></value> - </member> - <member> - <name>faultString</name> - <value><string>{$this->message}</string></value> - </member> - </struct> - </value> - </fault> -</methodResponse> - -EOD; - return $xml; - } -} - -/** - * IXR_Date - * - * @package IXR - * @since 1.5 - */ -class IXR_Date { - - const XMLRPC_ISO8601 = "Ymd\TH:i:sO" ; - /** @var DateTime */ - protected $date; - - /** - * @param int|string $time - */ - public function __construct($time) { - // $time can be a PHP timestamp or an ISO one - if(is_numeric($time)) { - $this->parseTimestamp($time); - } else { - $this->parseIso($time); - } - } - - /** - * Parse unix timestamp - * - * @param int $timestamp - */ - protected function parseTimestamp($timestamp) { - $this->date = new DateTime('@' . $timestamp); - } - - /** - * Parses less or more complete iso dates and much more, if no timezone given assumes UTC - * - * @param string $iso - */ - protected function parseIso($iso) { - $this->date = new DateTime($iso, new DateTimeZone("UTC")); - } - - /** - * Returns date in ISO 8601 format - * - * @return string - */ - public function getIso() { - return $this->date->format(self::XMLRPC_ISO8601); - } - - /** - * Returns date in valid xml - * - * @return string - */ - public function getXml() { - return '<dateTime.iso8601>' . $this->getIso() . '</dateTime.iso8601>'; - } - - /** - * Returns Unix timestamp - * - * @return int - */ - function getTimestamp() { - return $this->date->getTimestamp(); - } -} - -/** - * IXR_Base64 - * - * @package IXR - * @since 1.5 - */ -class IXR_Base64 { - var $data; - - /** - * @param string $data - */ - function __construct($data) { - $this->data = $data; - } - - /** - * @return string - */ - function getXml() { - return '<base64>' . base64_encode($this->data) . '</base64>'; - } -} - -/** - * IXR_IntrospectionServer - * - * @package IXR - * @since 1.5 - */ -class IXR_IntrospectionServer extends IXR_Server { - /** @var array[] */ - var $signatures; - /** @var string[] */ - var $help; - - /** - * Constructor - */ - function __construct() { - $this->setCallbacks(); - $this->setCapabilities(); - $this->capabilities['introspection'] = array( - 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', - 'specVersion' => 1 - ); - $this->addCallback( - 'system.methodSignature', - 'this:methodSignature', - array('array', 'string'), - 'Returns an array describing the return type and required parameters of a method' - ); - $this->addCallback( - 'system.getCapabilities', - 'this:getCapabilities', - array('struct'), - 'Returns a struct describing the XML-RPC specifications supported by this server' - ); - $this->addCallback( - 'system.listMethods', - 'this:listMethods', - array('array'), - 'Returns an array of available methods on this server' - ); - $this->addCallback( - 'system.methodHelp', - 'this:methodHelp', - array('string', 'string'), - 'Returns a documentation string for the specified method' - ); - } - - /** - * @param string $method - * @param string $callback - * @param string[] $args - * @param string $help - */ - function addCallback($method, $callback, $args, $help) { - $this->callbacks[$method] = $callback; - $this->signatures[$method] = $args; - $this->help[$method] = $help; - } - - /** - * @param string $methodname - * @param array $args - * @return IXR_Error|mixed - */ - function call($methodname, $args) { - // Make sure it's in an array - if($args && !is_array($args)) { - $args = array($args); - } - - // Over-rides default call method, adds signature check - if(!$this->hasMethod($methodname)) { - return new IXR_Error(-32601, 'server error. requested method "' . $this->message->methodName . '" not specified.'); - } - $method = $this->callbacks[$methodname]; - $signature = $this->signatures[$methodname]; - $returnType = array_shift($signature); - // Check the number of arguments. Check only, if the minimum count of parameters is specified. More parameters are possible. - // This is a hack to allow optional parameters... - if(count($args) < count($signature)) { - // print 'Num of args: '.count($args).' Num in signature: '.count($signature); - return new IXR_Error(-32602, 'server error. wrong number of method parameters'); - } - - // Check the argument types - $ok = true; - $argsbackup = $args; - for($i = 0, $j = count($args); $i < $j; $i++) { - $arg = array_shift($args); - $type = array_shift($signature); - switch($type) { - case 'int': - case 'i4': - if(is_array($arg) || !is_int($arg)) { - $ok = false; - } - break; - case 'base64': - case 'string': - if(!is_string($arg)) { - $ok = false; - } - break; - case 'boolean': - if($arg !== false && $arg !== true) { - $ok = false; - } - break; - case 'float': - case 'double': - if(!is_float($arg)) { - $ok = false; - } - break; - case 'date': - case 'dateTime.iso8601': - if(!is_a($arg, 'IXR_Date')) { - $ok = false; - } - break; - } - if(!$ok) { - return new IXR_Error(-32602, 'server error. invalid method parameters'); - } - } - // It passed the test - run the "real" method call - return parent::call($methodname, $argsbackup); - } - - /** - * @param string $method - * @return array|IXR_Error - */ - function methodSignature($method) { - if(!$this->hasMethod($method)) { - return new IXR_Error(-32601, 'server error. requested method "' . $method . '" not specified.'); - } - // We should be returning an array of types - $types = $this->signatures[$method]; - $return = array(); - foreach($types as $type) { - switch($type) { - case 'string': - $return[] = 'string'; - break; - case 'int': - case 'i4': - $return[] = 42; - break; - case 'double': - $return[] = 3.1415; - break; - case 'dateTime.iso8601': - $return[] = new IXR_Date(time()); - break; - case 'boolean': - $return[] = true; - break; - case 'base64': - $return[] = new IXR_Base64('base64'); - break; - case 'array': - $return[] = array('array'); - break; - case 'struct': - $return[] = array('struct' => 'struct'); - break; - } - } - return $return; - } - - /** - * @param string $method - * @return mixed - */ - function methodHelp($method) { - return $this->help[$method]; - } -} - -/** - * IXR_ClientMulticall - * - * @package IXR - * @since 1.5 - */ -class IXR_ClientMulticall extends IXR_Client { - - /** @var array[] */ - var $calls = array(); - - /** - * @param string $server - * @param string|bool $path - * @param int $port - */ - function __construct($server, $path = false, $port = 80) { - parent::__construct($server, $path, $port); - //$this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; - } - - /** - * Add a call - */ - function addCall() { - $args = func_get_args(); - $methodName = array_shift($args); - $struct = array( - 'methodName' => $methodName, - 'params' => $args - ); - $this->calls[] = $struct; - } - - /** - * @return bool - */ - function query() { - // Prepare multicall, then call the parent::query() method - return parent::query('system.multicall', $this->calls); - } -} - diff --git a/inc/Logger.php b/inc/Logger.php index a3999a6ea..0772305f3 100644 --- a/inc/Logger.php +++ b/inc/Logger.php @@ -2,6 +2,11 @@ namespace dokuwiki; +use dokuwiki\Extension\Event; + +/** + * Log messages to a daily log file + */ class Logger { const LOG_ERROR = 'error'; @@ -101,11 +106,55 @@ class Logger * @param mixed $details Any details that should be added to the log entry * @param string $file A source filename if this is related to a source position * @param int $line A line number for the above file + * @triggers LOGGER_DATA_FORMAT can be used to change the logged data or intercept it * @return bool has a log been written? */ public function log($message, $details = null, $file = '', $line = 0) { - if(!$this->isLogging) return false; + global $EVENT_HANDLER; + if (!$this->isLogging) return false; + + $datetime = time(); + $data = [ + 'facility' => $this->facility, + 'datetime' => $datetime, + 'message' => $message, + 'details' => $details, + 'file' => $file, + 'line' => $line, + 'loglines' => [], + 'logfile' => $this->getLogfile($datetime), + ]; + + if ($EVENT_HANDLER !== null) { + $event = new Event('LOGGER_DATA_FORMAT', $data); + if ($event->advise_before()) { + $data['loglines'] = $this->formatLogLines($data); + } + $event->advise_after(); + } else { + // The event system is not yet available, to ensure the log isn't lost even on + // fatal errors, the default action is executed + $data['loglines'] = $this->formatLogLines($data); + } + + // only log when any data available + if (count($data['loglines'])) { + return $this->writeLogLines($data['loglines'], $data['logfile']); + } else { + return false; + } + } + + /** + * Formats the given data as loglines + * + * @param array $data Event data from LOGGER_DATA_FORMAT + * @return string[] the lines to log + */ + protected function formatLogLines($data) + { + extract($data); // details are logged indented if ($details) { @@ -123,15 +172,15 @@ class Logger } // datetime, fileline, message - $logline = gmdate('Y-m-d H:i:s') . "\t"; + $logline = gmdate('Y-m-d H:i:s', $datetime) . "\t"; if ($file) { $logline .= $file; if ($line) $logline .= "($line)"; } $logline .= "\t" . $message; - array_unshift($loglines, $logline); - return $this->writeLogLines($loglines); + + return $loglines; } /** @@ -154,11 +203,11 @@ class Logger * Write the given lines to today's facility log * * @param string[] $lines the raw lines to append to the log + * @param string $logfile where to write to * @return bool true if the log was written */ - protected function writeLogLines($lines) + protected function writeLogLines($lines, $logfile) { - $logfile = $this->getLogfile(); return io_saveFile($logfile, join("\n", $lines) . "\n", true); } } diff --git a/inc/Remote/Api.php b/inc/Remote/Api.php index 749c2e6ea..0b406355c 100644 --- a/inc/Remote/Api.php +++ b/inc/Remote/Api.php @@ -344,7 +344,7 @@ class Api $this->coreMethods = $apiCore; } } - return $this->coreMethods->__getRemoteInfo(); + return $this->coreMethods->getRemoteInfo(); } /** diff --git a/inc/Remote/ApiCore.php b/inc/Remote/ApiCore.php index c3275890e..b69080880 100644 --- a/inc/Remote/ApiCore.php +++ b/inc/Remote/ApiCore.php @@ -36,7 +36,7 @@ class ApiCore * * @return array */ - public function __getRemoteInfo() + public function getRemoteInfo() { return array( 'dokuwiki.getVersion' => array( diff --git a/inc/Remote/IXR/Client.php b/inc/Remote/IXR/Client.php new file mode 100644 index 000000000..6c34df5d0 --- /dev/null +++ b/inc/Remote/IXR/Client.php @@ -0,0 +1,88 @@ +<?php + +namespace dokuwiki\Remote\IXR; + +use dokuwiki\HTTP\HTTPClient; +use IXR\Message\Message; +use IXR\Request\Request; + +/** + * This implements a XML-RPC client using our own HTTPClient + * + * Note: this now inherits from the IXR library's client and no longer from HTTPClient. Instead composition + * is used to add the HTTP client. + */ +class Client extends \IXR\Client\Client +{ + + /** @var HTTPClient */ + protected $httpClient; + + /** @var string */ + protected $posturl = ''; + + /** @inheritdoc */ + public function __construct($server, $path = false, $port = 80, $timeout = 15, $timeout_io = null) + { + parent::__construct($server, $path, $port, $timeout, $timeout_io); + if (!$path) { + // Assume we have been given an URL instead + $this->posturl = $server; + } else { + $this->posturl = 'http://' . $server . ':' . $port . $path; + } + + $this->httpClient = new HTTPClient(); + $this->httpClient->timeout = $timeout; + } + + /** @inheritdoc */ + public function query() + { + $args = func_get_args(); + $method = array_shift($args); + $request = new Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + + $this->headers['Content-Type'] = 'text/xml'; + $this->headers['Content-Length'] = $length; + $this->httpClient->headers = array_merge($this->httpClient->headers, $this->headers); + + if (!$this->httpClient->sendRequest($this->posturl, $xml, 'POST')) { + $this->handleError(-32300, 'transport error - ' . $this->httpClient->error); + return false; + } + + // Check HTTP Response code + if ($this->httpClient->status < 200 || $this->httpClient->status > 206) { + $this->handleError(-32300, 'transport error - HTTP status ' . $this->httpClient->status); + return false; + } + + // Now parse what we've got back + $this->message = new Message($this->httpClient->resp_body); + if (!$this->message->parse()) { + // XML error + return $this->handleError(-32700, 'Parse error. Message not well formed'); + } + + // Is the message a fault? + if ($this->message->messageType == 'fault') { + return $this->handleError($this->message->faultCode, $this->message->faultString); + } + + // Message must be OK + return true; + } + + /** + * Direct access to the underlying HTTP client if needed + * + * @return HTTPClient + */ + public function getHTTPClient() + { + return $this->httpClient; + } +} diff --git a/inc/Remote/XmlRpcServer.php b/inc/Remote/XmlRpcServer.php index 0a16af1cc..e1f3918dc 100644 --- a/inc/Remote/XmlRpcServer.php +++ b/inc/Remote/XmlRpcServer.php @@ -2,10 +2,15 @@ namespace dokuwiki\Remote; +use IXR\DataType\Base64; +use IXR\DataType\Date; +use IXR\Exception\ServerException; +use IXR\Server\Server; + /** * Contains needed wrapper functions and registers all available XMLRPC functions. */ -class XmlRpcServer extends \IXR_Server +class XmlRpcServer extends Server { protected $remote; @@ -20,6 +25,16 @@ class XmlRpcServer extends \IXR_Server parent::__construct(false, false, $wait); } + /** @inheritdoc */ + public function serve($data = false) + { + global $conf; + if (!$conf['remote']) { + throw new ServerException("XML-RPC server not enabled.", -32605); + } + parent::serve($data); + } + /** * @inheritdoc */ @@ -28,34 +43,34 @@ class XmlRpcServer extends \IXR_Server try { $result = $this->remote->call($methodname, $args); return $result; - } /** @noinspection PhpRedundantCatchClauseInspection */ catch (AccessDeniedException $e) { + } catch (AccessDeniedException $e) { if (!isset($_SERVER['REMOTE_USER'])) { http_status(401); - return new \IXR_Error(-32603, "server error. not authorized to call method $methodname"); + return new ServerException("server error. not authorized to call method $methodname", -32603); } else { http_status(403); - return new \IXR_Error(-32604, "server error. forbidden to call the method $methodname"); + return new ServerException("server error. forbidden to call the method $methodname", -32604); } } catch (RemoteException $e) { - return new \IXR_Error($e->getCode(), $e->getMessage()); + return new ServerException($e->getMessage(), $e->getCode()); } } /** * @param string|int $data iso date(yyyy[-]mm[-]dd[ hh:mm[:ss]]) or timestamp - * @return \IXR_Date + * @return Date */ public function toDate($data) { - return new \IXR_Date($data); + return new Date($data); } /** * @param string $data - * @return \IXR_Base64 + * @return Base64 */ public function toFile($data) { - return new \IXR_Base64($data); + return new Base64($data); } } diff --git a/inc/Subscriptions/BulkSubscriptionSender.php b/inc/Subscriptions/BulkSubscriptionSender.php index d37c1e000..ac24e9e04 100644 --- a/inc/Subscriptions/BulkSubscriptionSender.php +++ b/inc/Subscriptions/BulkSubscriptionSender.php @@ -87,7 +87,8 @@ class BulkSubscriptionSender extends SubscriptionSender $n = 0; while (!is_null($rev) && $rev['date'] >= $lastupdate && ($INPUT->server->str('REMOTE_USER') === $rev['user'] || - $rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT)) { + $rev['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) + ) { $pagelog = new PageChangeLog($rev['id']); $rev = $pagelog->getRevisions($n++, 1); $rev = (count($rev) > 0) ? $rev[0] : null; diff --git a/inc/TaskRunner.php b/inc/TaskRunner.php index c5de7e303..b641fb174 100644 --- a/inc/TaskRunner.php +++ b/inc/TaskRunner.php @@ -5,6 +5,7 @@ namespace dokuwiki; use dokuwiki\Extension\Event; use dokuwiki\Sitemap\Mapper; use dokuwiki\Subscriptions\BulkSubscriptionSender; +use dokuwiki\ChangeLog\ChangeLog; /** * Class TaskRunner @@ -120,7 +121,7 @@ class TaskRunner $out_lines = []; $old_lines = []; for ($i = 0; $i < count($lines); $i++) { - $log = parseChangelogLine($lines[$i]); + $log = ChangeLog::parseLogLine($lines[$i]); if ($log === false) { continue; // discard junk } diff --git a/inc/Ui/Admin.php b/inc/Ui/Admin.php index d3bbc6503..925eb35e8 100644 --- a/inc/Ui/Admin.php +++ b/inc/Ui/Admin.php @@ -1,6 +1,7 @@ <?php namespace dokuwiki\Ui; +use dokuwiki\Extension\AdminPlugin; use dokuwiki\Utf8\Sort; /** @@ -121,7 +122,7 @@ class Admin extends Ui { $menu = ['admin' => [], 'manager' => [], 'other' => []]; foreach($pluginlist as $p) { - /** @var \dokuwiki\Extension\AdminPlugin $obj */ + /** @var AdminPlugin $obj */ if(($obj = plugin_load('admin', $p)) === null) continue; // check permissions diff --git a/inc/Ui/Backlinks.php b/inc/Ui/Backlinks.php index 8bde96666..9ac99b1b0 100644 --- a/inc/Ui/Backlinks.php +++ b/inc/Ui/Backlinks.php @@ -2,9 +2,6 @@ namespace dokuwiki\Ui; -use dokuwiki\Extension\Event; -use dokuwiki\Form\Form; - /** * DokuWiki Backlinks Interface * diff --git a/inc/Ui/Diff.php b/inc/Ui/Diff.php index 513e0667c..d534016b8 100644 --- a/inc/Ui/Diff.php +++ b/inc/Ui/Diff.php @@ -2,502 +2,120 @@ namespace dokuwiki\Ui; -use dokuwiki\ChangeLog\PageChangeLog; -use dokuwiki\ChangeLog\MediaChangeLog; -use dokuwiki\Extension\Event; -use dokuwiki\Form\Form; +use dokuwiki\ChangeLog\ChangeLog; /** * DokuWiki Diff Interface + * parent class of PageDiff and MediaDiff * * @package dokuwiki\Ui */ -class Diff extends Ui +abstract class Diff extends Ui { - protected $text; - protected $showIntro; - protected $difftype; + /* @var string */ + protected $id; // page id or media id + + /* @var int */ + protected $oldRev; // timestamp of older revision + protected $newRev; // timestamp of newer revision + + /* @var array */ + protected $preference = []; + + /* @var ChangeLog */ + protected $changelog; // PageChangeLog or MediaChangeLog object /** * Diff Ui constructor * - * @param string $text when non-empty: compare with this text with most current version - * @param bool $showIntro display the intro text - * @param string $difftype diff view type (inline or sidebyside) + * @param string $id page id or media id */ - public function __construct($text = '', $showIntro = true, $difftype = null) + public function __construct($id) { - $this->text = $text; - $this->showIntro = $showIntro; - - // determine diff view type - if (isset($difftype)) { - $this->difftype = $difftype; - } else { - global $INPUT; - global $INFO; - $this->difftype = $INPUT->str('difftype') ?: get_doku_pref('difftype', $difftype); - if (empty($this->difftype) && $INFO['ismobile']) { - $this->difftype = 'inline'; - } - } - if ($this->difftype !== 'inline') $this->difftype = 'sidebyside'; + $this->id = $id; + $this->setChangeLog(); } /** - * Show diff - * between current page version and provided $text - * or between the revisions provided via GET or POST - * - * @author Andreas Gohr <andi@splitbrain.org> - * - * @return void + * set class property changelog */ - public function show() - { - global $ID; - global $REV; - global $lang; - global $INPUT; - global $INFO; - $pagelog = new PageChangeLog($ID); - - /* - * Determine requested revision(s) - */ - // we're trying to be clever here, revisions to compare can be either - // given as rev and rev2 parameters, with rev2 being optional. Or in an - // array in rev2. - $rev1 = $REV; + abstract protected function setChangeLog(); - $rev2 = $INPUT->ref('rev2'); - if (is_array($rev2)) { - $rev1 = (int) $rev2[0]; - $rev2 = (int) $rev2[1]; - - if (!$rev1) { - $rev1 = $rev2; - unset($rev2); - } - } else { - $rev2 = $INPUT->int('rev2'); - } - - /* - * Determine left and right revision, its texts and the header - */ - $r_minor = ''; - $l_minor = ''; - - if ($this->text) { // compare text to the most current revision - $l_rev = ''; - $l_text = rawWiki($ID, ''); - $l_head = '<a class="wikilink1" href="'. wl($ID) .'">' - . $ID .' '. dformat((int) @filemtime(wikiFN($ID))) .'</a> ' - . $lang['current']; - - $r_rev = ''; - $r_text = cleanText($this->text); - $r_head = $lang['yours']; - } else { - if ($rev1 && isset($rev2) && $rev2) { // two specific revisions wanted - // make sure order is correct (older on the left) - if ($rev1 < $rev2) { - $l_rev = $rev1; - $r_rev = $rev2; - } else { - $l_rev = $rev2; - $r_rev = $rev1; - } - } elseif ($rev1) { // single revision given, compare to current - $r_rev = ''; - $l_rev = $rev1; - } else { // no revision was given, compare previous to current - $r_rev = ''; - $revs = $pagelog->getRevisions(0, 1); - $l_rev = $revs[0]; - $REV = $l_rev; // store revision back in $REV - } - - // when both revisions are empty then the page was created just now - if (!$l_rev && !$r_rev) { - $l_text = ''; - } else { - $l_text = rawWiki($ID, $l_rev); - } - $r_text = rawWiki($ID, $r_rev); - - list($l_head, $r_head, $l_minor, $r_minor) = $this->diffHead( - $l_rev, $r_rev, null, false, ($this->difftype == 'inline') - ); - } - - /* - * Build navigation - */ - $l_nav = ''; - $r_nav = ''; - if (!$this->text) { - list($l_nav, $r_nav) = $this->diffNavigation($pagelog, $l_rev, $r_rev); - } - /* - * Create diff object and the formatter - */ - $diff = new \Diff(explode("\n", $l_text), explode("\n", $r_text)); - - if ($this->difftype == 'inline') { - $diffformatter = new \InlineDiffFormatter(); - } else { - $diffformatter = new \TableDiffFormatter(); - } - /* - * Display intro - */ - if ($this->showIntro) print p_locale_xhtml('diff'); - - /* - * Display type and exact reference - */ - if (!$this->text) { - print '<div class="diffoptions group">'; - - // create the form to select difftype - $form = new Form(['action' => wl()]); - $form->setHiddenField('id', $ID); - $form->setHiddenField('rev2[0]', $l_rev); - $form->setHiddenField('rev2[1]', $r_rev); - $form->setHiddenField('do', 'diff'); - $options = array( - 'sidebyside' => $lang['diff_side'], - 'inline' => $lang['diff_inline'] - ); - $input = $form->addDropdown('difftype', $options, $lang['diff_type']) - ->val($this->difftype)->addClass('quickselect'); - $input->useInput(false); // inhibit prefillInput() during toHTML() process - $form->addButton('do[diff]', 'Go')->attr('type','submit'); - print $form->toHTML(); - - print '<p>'; - // link to exactly this view FS#2835 - print $this->diffViewlink('difflink', $l_rev, ($r_rev ?: $INFO['currentrev'])); - print '</p>'; - - print '</div>'; // .diffoptions - } - - /* - * Display diff view table - */ - print '<div class="table">'; - print '<table class="diff diff_'. $this->difftype .'">'; + /** + * Prepare revision info of comparison pair + */ + abstract protected function preProcess(); - //navigation and header - if ($this->difftype == 'inline') { - if (!$this->text) { - print '<tr>' - . '<td class="diff-lineheader">-</td>' - . '<td class="diffnav">'. $l_nav .'</td>' - . '</tr>'; - print '<tr>' - . '<th class="diff-lineheader">-</th>' - . '<th '. $l_minor .'>'. $l_head .'</th>' - .'</tr>'; - } - print '<tr>' - . '<td class="diff-lineheader">+</td>' - . '<td class="diffnav">'. $r_nav .'</td>' - .'</tr>'; - print '<tr>' - . '<th class="diff-lineheader">+</th>' - . '<th '. $r_minor .'>'. $r_head .'</th>' - . '</tr>'; + /** + * Set a pair of revisions to be compared + * + * @param int $oldRev + * @param int $newRev + * @return $this + */ + public function compare($oldRev, $newRev) + { + if ($oldRev < $newRev) { + [$this->oldRev, $this->newRev] = [$oldRev, $newRev]; } else { - if (!$this->text) { - print '<tr>' - . '<td colspan="2" class="diffnav">'. $l_nav .'</td>' - . '<td colspan="2" class="diffnav">'. $r_nav .'</td>' - . '</tr>'; - } - print '<tr>' - . '<th colspan="2" '. $l_minor .'>'. $l_head .'</th>' - . '<th colspan="2" '. $r_minor .'>'. $r_head .'</th>' - . '</tr>'; + [$this->oldRev, $this->newRev] = [$newRev, $oldRev]; } - - //diff view - print $this->insertSoftbreaks($diffformatter->format($diff)); - - print '</table>'; - print '</div>'; + return $this; } - /** - * Get header of diff HTML + * Gets or Sets preference of the Ui\Diff object * - * @param string $l_rev Left revisions - * @param string $r_rev Right revision - * @param string $id Page id, if null $ID is used - * @param bool $media If it is for media files - * @param bool $inline Return the header on a single line - * @return string[] HTML snippets for diff header + * @param string|array $prefs a key name or key-value pair(s) + * @param mixed $value value used when the first args is string + * @return array|$this */ - public function diffHead($l_rev, $r_rev, $id = null, $media = false, $inline = false) + public function preference($prefs = null, $value = null) { - global $lang; - if ($id === null) { - global $ID; - $id = $ID; - } - $head_separator = $inline ? ' ' : '<br />'; - $media_or_wikiFN = $media ? 'mediaFN' : 'wikiFN'; - $ml_or_wl = $media ? 'ml' : 'wl'; - $l_minor = $r_minor = ''; - - if ($media) { - $changelog = new MediaChangeLog($id); - } else { - $changelog = new PageChangeLog($id); - } - if (!$l_rev) { - $l_head = '—'; - } else { - $l_info = $changelog->getRevisionInfo($l_rev); - if ($l_info['user']) { - $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>'; - if (auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>'; - } else { - $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>'; + // set + if (is_string($prefs) && isset($value)) { + $this->preference[$prefs] = $value; + return $this; + } elseif (is_array($prefs)) { + foreach ($prefs as $name => $value) { + $this->preference[$name] = $value; } - $l_user = '<span class="user">'.$l_user.'</span>'; - $l_sum = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : ''; - if ($l_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"'; - - $l_head_title = ($media) ? dformat($l_rev) : $id.' ['.dformat($l_rev).']'; - $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">' - . $l_head_title.'</a></bdi>'.$head_separator.$l_user.' '.$l_sum; + return $this; } - - if ($r_rev) { - $r_info = $changelog->getRevisionInfo($r_rev); - if ($r_info['user']) { - $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>'; - if (auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>'; - } else { - $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>'; - } - $r_user = '<span class="user">'.$r_user.'</span>'; - $r_sum = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : ''; - if ($r_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"'; - - $r_head_title = ($media) ? dformat($r_rev) : $id.' ['.dformat($r_rev).']'; - $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">' - . $r_head_title.'</a></bdi>'.$head_separator.$r_user.' '.$r_sum; - } elseif ($_rev = @filemtime($media_or_wikiFN($id))) { - $_info = $changelog->getRevisionInfo($_rev); - if ($_info['user']) { - $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>'; - if (auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>'; - } else { - $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>'; - } - $_user = '<span class="user">'.$_user.'</span>'; - $_sum = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : ''; - if ($_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"'; - - $r_head_title = ($media) ? dformat($_rev) : $id.' ['.dformat($_rev).']'; - $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id).'">' - . $r_head_title.'</a></bdi> '.'('.$lang['current'].')'.$head_separator.$_user.' '.$_sum; - }else{ - $r_head = '— ('.$lang['current'].')'; - } - - return array($l_head, $r_head, $l_minor, $r_minor); + // get + return $this->preference; } /** - * Create html for revision navigation + * Handle requested revision(s) * - * @param PageChangeLog $pagelog changelog object of current page - * @param int $l_rev left revision timestamp - * @param int $r_rev right revision timestamp - * @return string[] html of left and right navigation elements + * @return void */ - protected function diffNavigation($pagelog, $l_rev, $r_rev) + protected function handle() { - global $INFO, $ID; - - // last timestamp is not in changelog, retrieve timestamp from metadata - // note: when page is removed, the metadata timestamp is zero - if (!$r_rev) { - if (isset($INFO['meta']['last_change']['date'])) { - $r_rev = $INFO['meta']['last_change']['date']; - } else { - $r_rev = 0; - } - } - - //retrieve revisions with additional info - list($l_revs, $r_revs) = $pagelog->getRevisionsAround($l_rev, $r_rev); - $l_revisions = array(); - if (!$l_rev) { - //no left revision given, add dummy - $l_revisions[0]= array('label' => '', 'attrs' => []); - } - foreach ($l_revs as $rev) { - $info = $pagelog->getRevisionInfo($rev); - $l_revisions[$rev] = array( - 'label' => dformat($info['date']) .' '. editorinfo($info['user'], true) .' '. $info['sum'], - 'attrs' => ['title' => $rev], - ); - if ($r_rev ? $rev >= $r_rev : false) $l_revisions[$rev]['attrs']['disabled'] = 'disabled'; - } - $r_revisions = array(); - if (!$r_rev) { - //no right revision given, add dummy - $r_revisions[0] = array('label' => '', 'attrs' => []); - } - foreach ($r_revs as $rev) { - $info = $pagelog->getRevisionInfo($rev); - $r_revisions[$rev] = array( - 'label' => dformat($info['date']) .' '. editorinfo($info['user'], true) .' '. $info['sum'], - 'attrs' => ['title' => $rev], - ); - if ($rev <= $l_rev) $r_revisions[$rev]['attrs']['disabled'] = 'disabled'; - } - - //determine previous/next revisions - $l_index = array_search($l_rev, $l_revs); - $l_prev = $l_index < count($l_revs) - 1 ? $l_revs[$l_index + 1] : null; - $l_next = $l_index > 1 ? $l_revs[$l_index - 1] : null; - if ($r_rev) { - $r_index = array_search($r_rev, $r_revs); - $r_prev = $r_index < count($r_revs) - 1 ? $r_revs[$r_index + 1] : null; - $r_next = $r_index > 1 ? $r_revs[$r_index - 1] : null; - } else { - //removed page - if ($l_next) { - $r_prev = $r_revs[0]; - } else { - $r_prev = null; - } - $r_next = null; - } + global $INPUT; - /* - * Left side: - */ - $l_nav = ''; - //move back - if ($l_prev) { - $l_nav .= $this->diffViewlink('diffbothprevrev', $l_prev, $r_prev); - $l_nav .= $this->diffViewlink('diffprevrev', $l_prev, $r_rev); - } - //dropdown - $form = new Form(['action' => wl()]); - $form->setHiddenField('id', $ID); - $form->setHiddenField('difftype', $this->difftype); - $form->setHiddenField('rev2[1]', $r_rev); - $form->setHiddenField('do', 'diff'); - $input = $form->addDropdown('rev2[0]', $l_revisions)->val($l_rev)->addClass('quickselect'); - $input->useInput(false); // inhibit prefillInput() during toHTML() process - $form->addButton('do[diff]', 'Go')->attr('type','submit'); - $l_nav .= $form->toHTML(); - //move forward - if ($l_next && ($l_next < $r_rev || !$r_rev)) { - $l_nav .= $this->diffViewlink('diffnextrev', $l_next, $r_rev); + // difflink icon click, eg. ?rev=123456789&do=diff + if ($INPUT->has('rev')) { + $this->oldRev = $INPUT->int('rev'); + $this->newRev = $this->changelog->currentRevision(); } - /* - * Right side: - */ - $r_nav = ''; - //move back - if ($l_rev < $r_prev) { - $r_nav .= $this->diffViewlink('diffprevrev', $l_rev, $r_prev); - } - //dropdown - $form = new Form(['action' => wl()]); - $form->setHiddenField('id', $ID); - $form->setHiddenField('rev2[0]', $l_rev); - $form->setHiddenField('difftype', $this->difftype); - $form->setHiddenField('do', 'diff'); - $input = $form->addDropdown('rev2[1]', $r_revisions)->val($r_rev)->addClass('quickselect'); - $input->useInput(false); // inhibit prefillInput() during toHTML() process - $form->addButton('do[diff]', 'Go')->attr('type','submit'); - $r_nav .= $form->toHTML(); - //move forward - if ($r_next) { - if ($pagelog->isCurrentRevision($r_next)) { - //last revision is diff with current page - $r_nav .= $this->diffViewlink('difflastrev', $l_rev); + // submit button with two checked boxes + $rev2 = $INPUT->arr('rev2', []); + if (count($rev2) > 1) { + if ($rev2[0] < $rev2[1]) { + [$this->oldRev, $this->newRev] = [$rev2[0], $rev2[1]]; } else { - $r_nav .= $this->diffViewlink('diffnextrev', $l_rev, $r_next); + [$this->oldRev, $this->newRev] = [$rev2[1], $rev2[0]]; } - } else { - $r_nav .= $this->diffViewlink('diffbothnextrev', $l_next, $r_next); } - return array($l_nav, $r_nav); - } - /** - * Create html link to a diff view defined by two revisions - * - * @param string $linktype - * @param int $lrev oldest revision - * @param int $rrev newest revision or null for diff with current revision - * @return string html of link to a diff view - */ - protected function diffViewlink($linktype, $lrev, $rrev = null) - { - global $ID, $lang; - if ($rrev === null) { - $urlparam = array( - 'do' => 'diff', - 'rev' => $lrev, - 'difftype' => $this->difftype, - ); - } else { - $urlparam = array( - 'do' => 'diff', - 'rev2[0]' => $lrev, - 'rev2[1]' => $rrev, - 'difftype' => $this->difftype, - ); + if (!isset($this->oldRev, $this->newRev)) { + // no revision was given, compare previous to current + $revs = $this->changelog->getRevisions(-1, 2); + $this->newRev = $this->changelog->currentRevision(); + $this->oldRev = ($revs[0] == $this->newRev) ? $revs[1] : $revs[0]; } - return '<a class="'. $linktype .'" href="'. wl($ID, $urlparam) .'" title="'. $lang[$linktype] .'">' - . '<span>'. $lang[$linktype] .'</span>' - . '</a>'; - } - - - /** - * Insert soft breaks in diff html - * - * @param string $diffhtml - * @return string - */ - public function insertSoftbreaks($diffhtml) - { - // search the diff html string for both: - // - html tags, so these can be ignored - // - long strings of characters without breaking characters - return preg_replace_callback('/<[^>]*>|[^<> ]{12,}/', function ($match) { - // if match is an html tag, return it intact - if ($match[0][0] == '<') return $match[0]; - // its a long string without a breaking character, - // make certain characters into breaking characters by inserting a - // word break opportunity (<wbr> tag) in front of them. - $regex = <<< REGEX -(?(?= # start a conditional expression with a positive look ahead ... -&\#?\\w{1,6};) # ... for html entities - we don't want to split them (ok to catch some invalid combinations) -&\#?\\w{1,6}; # yes pattern - a quicker match for the html entity, since we know we have one -| -[?/,&\#;:] # no pattern - any other group of 'special' characters to insert a breaking character after -)+ # end conditional expression -REGEX; - return preg_replace('<'.$regex.'>xu', '\0<wbr>', $match[0]); - }, $diffhtml); } - } diff --git a/inc/Ui/Editor.php b/inc/Ui/Editor.php index 3d4d7b680..67ad081ff 100644 --- a/inc/Ui/Editor.php +++ b/inc/Ui/Editor.php @@ -2,6 +2,7 @@ namespace dokuwiki\Ui; +use dokuwiki\Draft; use dokuwiki\Extension\Event; use dokuwiki\Form\Form; @@ -138,7 +139,7 @@ class Editor extends Ui 'href' => $license[$conf['license']]['url'], 'rel' => 'license', 'class' => 'urlextern', - 'target' => $conf['target']['extern'] ? $conf['target']['extern'] : '', + 'target' => $conf['target']['extern'] ?: '', ); $form->addTagOpen('div')->addClass('license'); $form->addHTML($lang['licenseok'] @@ -171,7 +172,7 @@ class Editor extends Ui echo '</div>'; echo '<div id="draft__status" class="draft__status">'; - $draft = new \dokuwiki\Draft($ID, $INFO['client']); + $draft = new Draft($ID, $INFO['client']); if ($draft->isDraftAvailable()) { echo $draft->getDraftMessage(); } @@ -187,7 +188,7 @@ class Editor extends Ui * * the default action for EDIT_FORM_ADDTEXTAREA * - * @param mixed[] $data + * @param array{wr: bool, media_manager: bool, target: string, intro_locale: string, form: Form} $data */ public function addTextarea(&$data) { @@ -204,7 +205,6 @@ class Editor extends Ui $attr['cols'] = '80'; $attr['rows'] = '10'; - /** @var dokuwiki\Form\Form $data['form'] */ $data['form']->addTextarea('wikitext','')->attrs($attr)->val($TEXT) ->id('wiki__text')->addClass('edit'); } diff --git a/inc/Ui/Index.php b/inc/Ui/Index.php index d2cbfccb1..f7920f1ff 100644 --- a/inc/Ui/Index.php +++ b/inc/Ui/Index.php @@ -2,9 +2,6 @@ namespace dokuwiki\Ui; -use dokuwiki\Extension\Event; -use dokuwiki\Form\Form; - /** * DokuWiki Index Interface * @@ -14,7 +11,7 @@ class Index extends Ui { protected $ns; - /** + /** * Index Ui constructor * * @param string $ns namespace @@ -59,10 +56,9 @@ class Index extends Ui $data = array(); search($data, $conf['datadir'], 'search_index', array('ns' => $ns)); - $html = '<div id="index__tree" class="index__tree">' + return '<div id="index__tree" class="index__tree">' . html_buildlist($data, 'idx', [$this,'formatListItem'], [$this,'tagListItem']) . '</div>'; - return $html; } /** diff --git a/inc/Ui/MediaDiff.php b/inc/Ui/MediaDiff.php new file mode 100644 index 000000000..61cd0341f --- /dev/null +++ b/inc/Ui/MediaDiff.php @@ -0,0 +1,350 @@ +<?php + +namespace dokuwiki\Ui; + +use dokuwiki\ChangeLog\MediaChangeLog; +use dokuwiki\ChangeLog\RevisionInfo; +use dokuwiki\Form\Form; +use InvalidArgumentException; +use JpegMeta; + +/** + * DokuWiki MediaDiff Interface + * + * @package dokuwiki\Ui + */ +class MediaDiff extends Diff +{ + /* @var MediaChangeLog */ + protected $changelog; + + /* @var array */ + protected $oldRevInfo; + protected $newRevInfo; + + /* @var bool */ + protected $is_img; + + /** + * MediaDiff Ui constructor + * + * @param string $id media id + */ + public function __construct($id) + { + if (!isset($id)) { + throw new InvalidArgumentException('media id should not be empty!'); + } + + // init preference + $this->preference['fromAjax'] = false; // see dokuwiki\Ajax::callMediadiff() + $this->preference['showIntro'] = false; + $this->preference['difftype'] = 'both'; // diff view type: both, opacity or portions + + parent::__construct($id); + } + + /** @inheritdoc */ + protected function setChangeLog() + { + $this->changelog = new MediaChangeLog($this->id); + } + + /** + * Handle requested revision(s) and diff view preferences + * + * @return void + */ + protected function handle() + { + global $INPUT; + + // requested rev or rev2 + parent::handle(); + + // requested diff view type + if ($INPUT->has('difftype')) { + $this->preference['difftype'] = $INPUT->str('difftype'); + } + } + + /** + * Prepare revision info of comparison pair + */ + protected function preProcess() + { + $changelog =& $this->changelog; + + // revision info of older file (left side) + $this->oldRevInfo = $changelog->getRevisionInfo($this->oldRev); + // revision info of newer file (right side) + $this->newRevInfo = $changelog->getRevisionInfo($this->newRev); + + $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); + + foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) { + // use timestamp and '' properly as $rev for the current file + $isCurrent = $changelog->isCurrentRevision($revInfo['date']); + $revInfo += [ + 'current' => $isCurrent, + 'rev' => $isCurrent ? '' : $revInfo['date'], + ]; + + // headline in the Diff view navigation + $revInfo['navTitle'] = $this->revisionTitle($revInfo); + + if ($this->is_img) { + $rev = $revInfo['rev']; + $meta = new JpegMeta(mediaFN($this->id, $rev)); + // get image width and height for the mediamanager preview panel + $revInfo['previewSize'] = media_image_preview_size($this->id, $rev, $meta); + } + } + unset($revInfo); + + // re-check image, ensure minimum image width for showImageDiff() + $this->is_img = ($this->is_img + && ($this->oldRevInfo['previewSize'][0] ?? 0) >= 30 + && ($this->newRevInfo['previewSize'][0] ?? 0) >= 30 + ); + // adjust requested diff view type + if (!$this->is_img) { + $this->preference['difftype'] = 'both'; + } + } + + + /** + * Shows difference between two revisions of media + * + * @author Kate Arzamastseva <pshns@ukr.net> + */ + public function show() + { + global $conf; + + $ns = getNS($this->id); + $auth = auth_quickaclcheck("$ns:*"); + + if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return; + + // retrieve form parameters: rev, rev2, difftype + $this->handle(); + // prepare revision info of comparison pair + $this->preProcess(); + + // display intro + if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); + + // print form to choose diff view type + if ($this->is_img && !$this->preference['fromAjax']) { + $this->showDiffViewSelector(); + echo '<div id="mediamanager__diff" >'; + } + + switch ($this->preference['difftype']) { + case 'opacity': + case 'portions': + $this->showImageDiff(); + break; + case 'both': + default: + $this->showFileDiff(); + break; + } + + if ($this->is_img && !$this->preference['fromAjax']) { + echo '</div>'; + } + } + + /** + * Print form to choose diff view type + * the dropdown is to be added through JavaScript, see lib/scripts/media.js + */ + protected function showDiffViewSelector() + { + // use timestamp for current revision + [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; + + echo '<div class="diffoptions group">'; + + $form = new Form([ + 'id' => 'mediamanager__form_diffview', + 'action' => media_managerURL([], '&'), + 'method' => 'get', + 'class' => 'diffView', + ]); + $form->addTagOpen('div')->addClass('no'); + $form->setHiddenField('sectok', null); + $form->setHiddenField('mediado', 'diff'); + $form->setHiddenField('rev2[0]', $oldRev); + $form->setHiddenField('rev2[1]', $newRev); + $form->addTagClose('div'); + echo $form->toHTML(); + + echo '</div>'; // .diffoptions + } + + /** + * Prints two images side by side + * and slider + * + * @author Kate Arzamastseva <pshns@ukr.net> + */ + protected function showImageDiff() + { + // diff view type: opacity or portions + $type = $this->preference['difftype']; + + // use '' for current revision + [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; + + // adjust image width, right side (newer) has priority + $oldRevSize = $this->oldRevInfo['previewSize']; + $newRevSize = $this->newRevInfo['previewSize']; + if ($oldRevSize != $newRevSize) { + if ($newRevSize[0] > $oldRevSize[0]) { + $oldRevSize = $newRevSize; + } + } + + $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); + $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); + + // slider + echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>'; + + // two images in divs + echo '<div class="imageDiff '.$type.'">'; + echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">'; + echo '<img src="'.$oldRevSrc.'" alt="" />'; + echo '</div>'; + echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">'; + echo '<img src="'.$newRevSrc.'" alt="" />'; + echo '</div>'; + echo '</div>'; + } + + /** + * Shows difference between two revisions of media file + * + * @author Kate Arzamastseva <pshns@ukr.net> + */ + protected function showFileDiff() + { + global $lang; + + $ns = getNS($this->id); + $auth = auth_quickaclcheck("$ns:*"); + + // use '' for current revision + [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; + + $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev)); + $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev)); + + // display diff view table + echo '<div class="table">'; + echo '<table>'; + echo '<tr>'; + echo '<th>'. $this->oldRevInfo['navTitle'] .'</th>'; + echo '<th>'. $this->newRevInfo['navTitle'] .'</th>'; + echo '</tr>'; + + echo '<tr class="image">'; + echo '<td>'; + media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()? + echo '</td>'; + + echo '<td>'; + media_preview($this->id, $auth, $newRev, $newRevMeta); + echo '</td>'; + echo '</tr>'; + + echo '<tr class="actions">'; + echo '<td>'; + media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons() + echo '</td>'; + + echo '<td>'; + media_preview_buttons($this->id, $auth, $newRev); + echo '</td>'; + echo '</tr>'; + + $l_tags = media_file_tags($oldRevMeta); + $r_tags = media_file_tags($newRevMeta); + // FIXME r_tags-only stuff + foreach ($l_tags as $key => $l_tag) { + if ($l_tag['value'] != $r_tags[$key]['value']) { + $r_tags[$key]['highlighted'] = true; + $l_tags[$key]['highlighted'] = true; + } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) { + unset($r_tags[$key]); + unset($l_tags[$key]); + } + } + + echo '<tr>'; + foreach (array($l_tags, $r_tags) as $tags) { + echo '<td>'; + + echo '<dl class="img_tags">'; + foreach ($tags as $tag) { + $value = cleanText($tag['value']); + if (!$value) $value = '-'; + echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; + echo '<dd>'; + if ($tag['highlighted']) echo '<strong>'; + if ($tag['tag'][2] == 'date') { + echo dformat($value); + } else { + echo hsc($value); + } + if ($tag['highlighted']) echo '</strong>'; + echo '</dd>'; + } + echo '</dl>'; + + echo '</td>'; + } + echo '</tr>'; + + echo '</table>'; + echo '</div>'; + } + + /** + * Revision Title for MediaDiff table headline + * + * @param array $info Revision info structure of a media file + * @return string + */ + protected function revisionTitle(array $info) + { + global $lang, $INFO; + + if (isset($info['date'])) { + $rev = $info['date']; + $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">' + . dformat($rev).'</a></bdi>'; + } else { + $rev = false; + $title = '—'; + } + if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) { + $title .= ' ('.$lang['current'].')'; + } + + // append separator + $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; + + // supplement + if (isset($info['date'])) { + $RevInfo = new RevisionInfo($info); + $title .= $RevInfo->editSummary().' '.$RevInfo->editor(); + } + return $title; + } + +} diff --git a/inc/Ui/MediaRevisions.php b/inc/Ui/MediaRevisions.php new file mode 100644 index 000000000..c562401ba --- /dev/null +++ b/inc/Ui/MediaRevisions.php @@ -0,0 +1,120 @@ +<?php + +namespace dokuwiki\Ui; + +use dokuwiki\ChangeLog\MediaChangeLog; +use dokuwiki\ChangeLog\RevisionInfo; +use dokuwiki\Form\Form; +use InvalidArgumentException; + +/** + * DokuWiki MediaRevisions Interface + * + * @package dokuwiki\Ui + */ +class MediaRevisions extends Revisions +{ + /* @var MediaChangeLog */ + protected $changelog; + + /** + * MediaRevisions Ui constructor + * + * @param string $id id of media + */ + public function __construct($id) + { + if (!$id) { + throw new InvalidArgumentException('media id should not be empty!'); + } + parent::__construct($id); + } + + /** @inheritdoc */ + protected function setChangeLog() + { + $this->changelog = new MediaChangeLog($this->id); + } + + /** + * Display a list of Media Revisions in the MediaManager + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Ben Coburn <btcoburn@silicodon.net> + * @author Kate Arzamastseva <pshns@ukr.net> + * @author Satoshi Sahara <sahara.satoshi@gmail.com> + * + * @param int $first skip the first n changelog lines + * @return void + */ + public function show($first = 0) + { + global $lang; + $changelog =& $this->changelog; + + // get revisions, and set correct pagenation parameters (first, hasNext) + if ($first === null) $first = 0; + $hasNext = false; + $revisions = $this->getRevisions($first, $hasNext); + + // create the form + $form = new Form([ + 'id' => 'page__revisions', // must not be "media__revisions" + 'action' => media_managerURL(['image' => $this->id], '&'), + 'class' => 'changes', + ]); + $form->setHiddenField('mediado', 'diff'); // required for media revisions + $form->addTagOpen('div')->addClass('no'); + + // start listing + $form->addTagOpen('ul'); + foreach ($revisions as $info) { + $rev = $info['date']; + $info['current'] = $changelog->isCurrentRevision($rev); + + $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : ''; + $form->addTagOpen('li')->addClass($class); + $form->addTagOpen('div')->addClass('li'); + + if (isset($info['current'])) { + $form->addCheckbox('rev2[]')->val($rev); + } elseif (file_exists(mediaFN($this->id, $rev))) { + $form->addCheckbox('rev2[]')->val($rev); + } else { + $form->addCheckbox('')->val($rev)->attr('disabled','disabled'); + } + $form->addHTML(' '); + + $RevInfo = new RevisionInfo($info); + $html = implode(' ', [ + $RevInfo->editDate(), // edit date and time + $RevInfo->difflinkRevision(), // link to diffview icon + $RevInfo->itemName(), // name of page or media + '<div>', + $RevInfo->editSummary(), // edit summary + $RevInfo->editor(), // editor info + $RevInfo->sizechange(), // size change indicator + $RevInfo->currentIndicator(), // current indicator (only when k=1) + '</div>', + ]); + $form->addHTML($html); + + $form->addTagClose('div'); + $form->addTagClose('li'); + } + $form->addTagClose('ul'); // end of revision list + + // show button for diff view + $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit'); + + $form->addTagClose('div'); // close div class=no + + print $form->toHTML('Revisions'); + + // provide navigation for pagenated revision list (of pages and/or media files) + print $this->navigation($first, $hasNext, function ($n) { + return media_managerURL(['first' => $n], '&', false, true); + }); + } + +} diff --git a/inc/Ui/PageConflict.php b/inc/Ui/PageConflict.php index fcab37e8f..584860100 100644 --- a/inc/Ui/PageConflict.php +++ b/inc/Ui/PageConflict.php @@ -35,7 +35,7 @@ class PageConflict extends Ui */ public function show() { - global $ID; + global $INFO; global $lang; // print intro @@ -44,7 +44,7 @@ class PageConflict extends Ui // create the form $form = new Form(['id' => 'dw__editform']); $form->addTagOpen('div')->addClass('no'); - $form->setHiddenField('id', $ID); + $form->setHiddenField('id', $INFO['id']); $form->setHiddenField('wikitext', $this->text); $form->setHiddenField('summary', $this->summary); @@ -56,7 +56,8 @@ class PageConflict extends Ui print '<br /><br /><br /><br />'; - (new Diff($this->text, false))->show(); + // print difference + (new PageDiff($INFO['id']))->compareWith($this->text)->preference('showIntro', false)->show(); } } diff --git a/inc/Ui/PageDiff.php b/inc/Ui/PageDiff.php new file mode 100644 index 000000000..08b830e4b --- /dev/null +++ b/inc/Ui/PageDiff.php @@ -0,0 +1,577 @@ +<?php + +namespace dokuwiki\Ui; + +use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\ChangeLog\RevisionInfo; +use dokuwiki\Form\Form; +use InlineDiffFormatter; +use TableDiffFormatter; + +/** + * DokuWiki PageDiff Interface + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Satoshi Sahara <sahara.satoshi@gmail.com> + * @package dokuwiki\Ui + */ +class PageDiff extends Diff +{ + /* @var PageChangeLog */ + protected $changelog; + + /* @var array */ + protected $oldRevInfo; + protected $newRevInfo; + + /* @var string */ + protected $text; + + /** + * PageDiff Ui constructor + * + * @param string $id page id + */ + public function __construct($id = null) + { + global $INFO; + if (!isset($id)) $id = $INFO['id']; + + // init preference + $this->preference['showIntro'] = true; + $this->preference['difftype'] = 'sidebyside'; // diff view type: inline or sidebyside + + parent::__construct($id); + } + + /** @inheritdoc */ + protected function setChangeLog() + { + $this->changelog = new PageChangeLog($this->id); + } + + /** + * Set text to be compared with most current version + * when it has been externally edited + * exclusively use of the compare($old, $new) method + * + * @param string $text + * @return $this + */ + public function compareWith($text = null) + { + global $lang; + + if (isset($text)) { + $this->text = $text; + $changelog =& $this->changelog; + + // revision info of older file (left side) + $this->oldRevInfo = $changelog->getCurrentRevisionInfo() + [ + 'current' => true, + 'rev' => '', + 'navTitle' => $this->revisionTitle($changelog->getCurrentRevisionInfo()), + 'text' => rawWiki($this->id), + ]; + + // revision info of newer file (right side) + $this->newRevInfo = [ + 'date' => null, + //'ip' => '127.0.0.1', + //'type' => DOKU_CHANGE_TYPE_CREATE, + 'id' => $this->id, + //'user' => '', + //'sum' => '', + //'extra' => '', + 'sizechange' => strlen($this->text) - io_getSizeFile(wikiFN($this->id)), + 'timestamp' => false, + 'current' => false, + 'rev' => false, + 'navTitle' => $lang['yours'], + 'text' => cleanText($this->text), + ]; + } + return $this; + } + + /** + * Handle requested revision(s) and diff view preferences + * + * @return void + */ + protected function handle() + { + global $INPUT; + + // requested rev or rev2 + if (!isset($this->oldRevInfo, $this->newRevInfo)) { + parent::handle(); + } + + // requested diff view type + if ($INPUT->has('difftype')) { + $this->preference['difftype'] = $INPUT->str('difftype'); + } else { + // read preference from DokuWiki cookie. PageDiff only + $mode = get_doku_pref('difftype', null); + if (isset($mode)) $this->preference['difftype'] = $mode; + } + + if (!$INPUT->has('rev') && !$INPUT->has('rev2')) { + global $INFO, $REV; + if ($this->id == $INFO['id']) + $REV = $this->oldRev; // store revision back in $REV + } + } + + /** + * Prepare revision info of comparison pair + */ + protected function preProcess() + { + global $lang; + + $changelog =& $this->changelog; + + // check validity of $this->{oldRev, newRev} + foreach (['oldRev','newRev'] as $rev) { + $revInfo = $rev.'Info'; + $this->$revInfo = $changelog->getRevisionInfo((int)$this->$rev); + if (!$this->$revInfo) { + // invalid revision number, set dummy revInfo + $this->$revInfo = array( + 'date' => time(), + 'type' => '', + 'timestamp' => false, + 'rev' => false, + 'text' => '', + 'navTitle' => '—', + ); + } + } + if ($this->newRev === false) { + msg(sprintf($lang['page_nonexist_rev'], + $this->id, + wl($this->id, ['do'=>'edit']), + $this->id), -1); + } elseif ($this->oldRevInfo == $this->newRevInfo) { + msg('no way to compare when less than two revisions', -1); + } + + foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) { + // use timestamp and '' properly as $rev for the current file + $isCurrent = $changelog->isCurrentRevision($revInfo['date']); + $revInfo += [ + 'current' => $isCurrent, + 'rev' => $isCurrent ? '' : $revInfo['date'], + ]; + + // headline in the Diff view navigation + if (!isset($revInfo['navTitle'])) { + $revInfo['navTitle'] = $this->revisionTitle($revInfo); + } + + if ($revInfo['type'] == DOKU_CHANGE_TYPE_DELETE) { + //attic stores complete last page version for a deleted page + $revInfo['text'] = ''; + } else { + $revInfo['text'] = rawWiki($this->id, $revInfo['rev']); + } + } + } + + /** + * Show diff + * between current page version and provided $text + * or between the revisions provided via GET or POST + * + * @author Andreas Gohr <andi@splitbrain.org> + * + * @return void + */ + public function show() + { + if (!isset($this->oldRevInfo, $this->newRevInfo)) { + // retrieve form parameters: rev, rev2, difftype + $this->handle(); + // prepare revision info of comparison pair, except PageConfrict or PageDraft + $this->preProcess(); + } + + // create difference engine object + $Difference = new \Diff( + explode("\n", $this->oldRevInfo['text']), + explode("\n", $this->newRevInfo['text']) + ); + + // build paired navigation + [$navOlderRevisions, $navNewerRevisions] = $this->buildRevisionsNavigation(); + + // display intro + if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); + + // print form to choose diff view type, and exact url reference to the view + if ($this->newRevInfo['rev'] !== false) { + $this->showDiffViewSelector(); + } + + // assign minor edit checker to the variable + $classEditType = function ($info) { + return ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? ' class="minor"' : ''; + }; + + // display diff view table + echo '<div class="table">'; + echo '<table class="diff diff_'.$this->preference['difftype'] .'">'; + + //navigation and header + switch ($this->preference['difftype']) { + case 'inline': + if ($this->newRevInfo['rev'] !== false) { + echo '<tr>' + .'<td class="diff-lineheader">-</td>' + .'<td class="diffnav">'. $navOlderRevisions .'</td>' + .'</tr>'; + echo '<tr>' + .'<th class="diff-lineheader">-</th>' + .'<th'.$classEditType($this->oldRevInfo).'>'.$this->oldRevInfo['navTitle'].'</th>' + .'</tr>'; + } + echo '<tr>' + .'<td class="diff-lineheader">+</td>' + .'<td class="diffnav">'. $navNewerRevisions .'</td>' + .'</tr>'; + echo '<tr>' + .'<th class="diff-lineheader">+</th>' + .'<th'.$classEditType($this->newRevInfo).'>'.$this->newRevInfo['navTitle'].'</th>' + .'</tr>'; + // create formatter object + $DiffFormatter = new InlineDiffFormatter(); + break; + + case 'sidebyside': + default: + if ($this->newRevInfo['rev'] !== false) { + echo '<tr>' + .'<td colspan="2" class="diffnav">'. $navOlderRevisions .'</td>' + .'<td colspan="2" class="diffnav">'. $navNewerRevisions .'</td>' + .'</tr>'; + } + echo '<tr>' + .'<th colspan="2"'.$classEditType($this->oldRevInfo).'>'.$this->oldRevInfo['navTitle'].'</th>' + .'<th colspan="2"'.$classEditType($this->newRevInfo).'>'.$this->newRevInfo['navTitle'].'</th>' + .'</tr>'; + // create formatter object + $DiffFormatter = new TableDiffFormatter(); + break; + } + + // output formatted difference + echo $this->insertSoftbreaks($DiffFormatter->format($Difference)); + + echo '</table>'; + echo '</div>'; + } + + /** + * Revision Title for PageDiff table headline + * + * @param array $info Revision info structure of a page + * @return string + */ + protected function revisionTitle(array $info) + { + global $lang; + + // use designated title when compare current page source with given text + if (array_key_exists('date', $info) && is_null($info['date'])) { + return $lang['yours']; + } + + // revision info may have timestamp key when external edits occurred + $info['timestamp'] = $info['timestamp'] ?? true; + + if (isset($info['date'])) { + $rev = $info['date']; + if ($info['timestamp'] === false) { + // exteranlly deleted or older file restored + $title = '<bdi><a class="wikilink2" href="'.wl($this->id).'">' + . $this->id .' ['. $lang['unknowndate'] .']'.'</a></bdi>'; + } else { + $title = '<bdi><a class="wikilink1" href="'.wl($this->id, ['rev' => $rev]).'">' + . $this->id .' ['. dformat($rev) .']'.'</a></bdi>'; + } + } else { + $title = '—'; + } + if ($info['current']) { + $title .= ' ('.$lang['current'].')'; + } + + // append separator + $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; + + // supplement + if (isset($info['date'])) { + $RevInfo = new RevisionInfo($info); + $title .= $RevInfo->editSummary().' '.$RevInfo->editor(); + } + return $title; + } + + /** + * Print form to choose diff view type, and exact url reference to the view + */ + protected function showDiffViewSelector() + { + global $lang; + + // use timestamp for current revision + [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; + + echo '<div class="diffoptions group">'; + + // create the form to select difftype + $form = new Form(['action' => wl()]); + $form->setHiddenField('id', $this->id); + $form->setHiddenField('rev2[0]', $oldRev); + $form->setHiddenField('rev2[1]', $newRev); + $form->setHiddenField('do', 'diff'); + $options = array( + 'sidebyside' => $lang['diff_side'], + 'inline' => $lang['diff_inline'], + ); + $input = $form->addDropdown('difftype', $options, $lang['diff_type']) + ->val($this->preference['difftype']) + ->addClass('quickselect'); + $input->useInput(false); // inhibit prefillInput() during toHTML() process + $form->addButton('do[diff]', 'Go')->attr('type','submit'); + echo $form->toHTML(); + + // show exact url reference to the view when it is meaningful + echo '<p>'; + if ($oldRev && $newRev) { + // link to exactly this view FS#2835 + $viewUrl = $this->diffViewlink('difflink', $oldRev, $newRev); + } + echo $viewUrl ?? '<br />'; + echo '</p>'; + + echo '</div>'; // .diffoptions + } + + /** + * Create html for revision navigation + * + * The navigation consists of older and newer revisions selectors, each + * state mutually depends on the selected revision of opposite side. + * + * @return string[] html of navigation for both older and newer sides + */ + protected function buildRevisionsNavigation() + { + $changelog =& $this->changelog; + + if ($this->newRevInfo['rev'] === false) { + // no revisions selector for PageConflict or PageDraft + return array('', ''); + } + + // use timestamp for current revision + [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; + + // retrieve revisions with additional info + [$oldRevs, $newRevs] = $changelog->getRevisionsAround($oldRev, $newRev); + + // build options for dropdown selector + $olderRevisions = $this->buildRevisionOptions('older', $oldRevs); + $newerRevisions = $this->buildRevisionOptions('newer', $newRevs); + + // determine previous/next revisions + $index = array_search($oldRev, $oldRevs); + $oldPrevRev = ($index +1 < count($oldRevs)) ? $oldRevs[$index +1] : false; + $oldNextRev = ($index > 0) ? $oldRevs[$index -1] : false; + $index = array_search($newRev, $newRevs); + $newPrevRev = ($index +1 < count($newRevs)) ? $newRevs[$index +1] : false; + $newNextRev = ($index > 0) ? $newRevs[$index -1] : false; + + /* + * navigation UI for older revisions / Left side: + */ + $navOlderRevs = ''; + // move backward both side: ◀◀ + if ($oldPrevRev && $newPrevRev) + $navOlderRevs .= $this->diffViewlink('diffbothprevrev', $oldPrevRev, $newPrevRev); + // move backward left side: â—€ + if ($oldPrevRev) + $navOlderRevs .= $this->diffViewlink('diffprevrev', $oldPrevRev, $newRev); + // dropdown + $navOlderRevs .= $this->buildDropdownSelector('older', $olderRevisions); + // move forward left side: â–¶ + if ($oldNextRev && ($oldNextRev < $newRev)) + $navOlderRevs .= $this->diffViewlink('diffnextrev', $oldNextRev, $newRev); + + /* + * navigation UI for newer revisions / Right side: + */ + $navNewerRevs = ''; + // move backward right side: â—€ + if ($newPrevRev && ($oldRev < $newPrevRev)) + $navNewerRevs .= $this->diffViewlink('diffprevrev', $oldRev, $newPrevRev); + // dropdown + $navNewerRevs .= $this->buildDropdownSelector('newer', $newerRevisions); + // move forward right side: â–¶ + if ($newNextRev) { + if ($changelog->isCurrentRevision($newNextRev)) { + $navNewerRevs .= $this->diffViewlink('difflastrev', $oldRev, $newNextRev); + } else { + $navNewerRevs .= $this->diffViewlink('diffnextrev', $oldRev, $newNextRev); + } + } + // move forward both side: â–¶â–¶ + if ($oldNextRev && $newNextRev) + $navNewerRevs .= $this->diffViewlink('diffbothnextrev', $oldNextRev, $newNextRev); + + return array($navOlderRevs, $navNewerRevs); + } + + /** + * prepare options for dropdwon selector + * + * @params string $side "older" or "newer" + * @params array $revs list of revsion + * @return array + */ + protected function buildRevisionOptions($side, $revs) + { + $changelog =& $this->changelog; + $revisions = array(); + + // use timestamp for current revision + [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; + + foreach ($revs as $rev) { + $info = $changelog->getRevisionInfo($rev); + // revision info may have timestamp key when external edits occurred + $info['timestamp'] = $info['timestamp'] ?? true; + $date = dformat($info['date']); + if ($info['timestamp'] === false) { + // exteranlly deleted or older file restored + $date = preg_replace('/[0-9a-zA-Z]/','_', $date); + } + $revisions[$rev] = array( + 'label' => implode(' ', [ + $date, + editorinfo($info['user'], true), + $info['sum'], + ]), + 'attrs' => ['title' => $rev], + ); + if (($side == 'older' && ($newRev && $rev >= $newRev)) + ||($side == 'newer' && ($rev <= $oldRev)) + ) { + $revisions[$rev]['attrs']['disabled'] = 'disabled'; + } + } + return $revisions; + } + + /** + * build Dropdown form for revisions navigation + * + * @params string $side "older" or "newer" + * @params array $options dropdown options + * @return string + */ + protected function buildDropdownSelector($side, $options) + { + $form = new Form(['action' => wl($this->id)]); + $form->setHiddenField('id', $this->id); + $form->setHiddenField('do', 'diff'); + $form->setHiddenField('difftype', $this->preference['difftype']); + + // use timestamp for current revision + [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; + + switch ($side) { + case 'older': // left side + $form->setHiddenField('rev2[1]', $newRev); + $input = $form->addDropdown('rev2[0]', $options) + ->val($oldRev)->addClass('quickselect'); + $input->useInput(false); // inhibit prefillInput() during toHTML() process + break; + case 'newer': // right side + $form->setHiddenField('rev2[0]', $oldRev); + $input = $form->addDropdown('rev2[1]', $options) + ->val($newRev)->addClass('quickselect'); + $input->useInput(false); // inhibit prefillInput() during toHTML() process + break; + } + $form->addButton('do[diff]', 'Go')->attr('type','submit'); + return $form->toHTML(); + } + + /** + * Create html link to a diff view defined by two revisions + * + * @param string $linktype + * @param int $oldRev older revision + * @param int $newRev newer revision or null for diff with current revision + * @return string html of link to a diff view + */ + protected function diffViewlink($linktype, $oldRev, $newRev = null) + { + global $lang; + if ($newRev === null) { + $urlparam = array( + 'do' => 'diff', + 'rev' => $oldRev, + 'difftype' => $this->preference['difftype'], + ); + } else { + $urlparam = array( + 'do' => 'diff', + 'rev2[0]' => $oldRev, + 'rev2[1]' => $newRev, + 'difftype' => $this->preference['difftype'], + ); + } + $attr = array( + 'class' => $linktype, + 'href' => wl($this->id, $urlparam, true, '&'), + 'title' => $lang[$linktype], + ); + return '<a '. buildAttributes($attr) .'><span>'. $lang[$linktype] .'</span></a>'; + } + + + /** + * Insert soft breaks in diff html + * + * @param string $diffhtml + * @return string + */ + public function insertSoftbreaks($diffhtml) + { + // search the diff html string for both: + // - html tags, so these can be ignored + // - long strings of characters without breaking characters + return preg_replace_callback('/<[^>]*>|[^<> ]{12,}/', function ($match) { + // if match is an html tag, return it intact + if ($match[0][0] == '<') return $match[0]; + // its a long string without a breaking character, + // make certain characters into breaking characters by inserting a + // word break opportunity (<wbr> tag) in front of them. + $regex = <<< REGEX +(?(?= # start a conditional expression with a positive look ahead ... +&\#?\\w{1,6};) # ... for html entities - we don't want to split them (ok to catch some invalid combinations) +&\#?\\w{1,6}; # yes pattern - a quicker match for the html entity, since we know we have one +| +[?/,&\#;:] # no pattern - any other group of 'special' characters to insert a breaking character after +)+ # end conditional expression +REGEX; + return preg_replace('<'.$regex.'>xu', '\0<wbr>', $match[0]); + }, $diffhtml); + } + +} diff --git a/inc/Ui/PageDraft.php b/inc/Ui/PageDraft.php index 609ee508d..c4c4f5261 100644 --- a/inc/Ui/PageDraft.php +++ b/inc/Ui/PageDraft.php @@ -2,6 +2,7 @@ namespace dokuwiki\Ui; +use dokuwiki\Draft; use dokuwiki\Form\Form; /** @@ -22,21 +23,21 @@ class PageDraft extends Ui public function show() { global $INFO; - global $ID; global $lang; - $draft = new \dokuwiki\Draft($ID, $INFO['client']); + $draft = new Draft($INFO['id'], $INFO['client']); $text = $draft->getDraftText(); // print intro print p_locale_xhtml('draft'); - (new Diff($text, false))->show(); + // print difference + (new PageDiff($INFO['id']))->compareWith($text)->preference('showIntro', false)->show(); // create the draft form $form = new Form(['id' => 'dw__editform']); $form->addTagOpen('div')->addClass('no'); - $form->setHiddenField('id', $ID); + $form->setHiddenField('id', $INFO['id']); $form->setHiddenField('date', $draft->getDraftDate()); $form->setHiddenField('wikitext', $text); diff --git a/inc/Ui/PageRevisions.php b/inc/Ui/PageRevisions.php new file mode 100644 index 000000000..a702b50e9 --- /dev/null +++ b/inc/Ui/PageRevisions.php @@ -0,0 +1,117 @@ +<?php + +namespace dokuwiki\Ui; + +use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\ChangeLog\RevisionInfo; +use dokuwiki\Form\Form; + +/** + * DokuWiki PageRevisions Interface + * + * @package dokuwiki\Ui + */ +class PageRevisions extends Revisions +{ + /* @var PageChangeLog */ + protected $changelog; + + /** + * PageRevisions Ui constructor + * + * @param string $id id of page + */ + public function __construct($id = null) + { + global $INFO; + if (!isset($id)) $id = $INFO['id']; + parent::__construct($id); + } + + /** @inheritdoc */ + protected function setChangeLog() + { + $this->changelog = new PageChangeLog($this->id); + } + + /** + * Display list of old revisions of the page + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Ben Coburn <btcoburn@silicodon.net> + * @author Kate Arzamastseva <pshns@ukr.net> + * @author Satoshi Sahara <sahara.satoshi@gmail.com> + * + * @param int $first skip the first n changelog lines + * @return void + */ + public function show($first = 0) + { + global $lang, $REV; + $changelog =& $this->changelog; + + // get revisions, and set correct pagenation parameters (first, hasNext) + if ($first === null) $first = 0; + $hasNext = false; + $revisions = $this->getRevisions($first, $hasNext); + + // print intro + print p_locale_xhtml('revisions'); + + // create the form + $form = new Form([ + 'id' => 'page__revisions', + 'class' => 'changes', + ]); + $form->addTagOpen('div')->addClass('no'); + + // start listing + $form->addTagOpen('ul'); + foreach ($revisions as $info) { + $rev = $info['date']; + $info['current'] = $changelog->isCurrentRevision($rev); + + $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : ''; + $form->addTagOpen('li')->addClass($class); + $form->addTagOpen('div')->addClass('li'); + + if (isset($info['current'])) { + $form->addCheckbox('rev2[]')->val($rev); + } elseif ($rev == $REV) { + $form->addCheckbox('rev2[]')->val($rev)->attr('checked','checked'); + } elseif (page_exists($this->id, $rev)) { + $form->addCheckbox('rev2[]')->val($rev); + } else { + $form->addCheckbox('')->val($rev)->attr('disabled','disabled'); + } + $form->addHTML(' '); + + $RevInfo = new RevisionInfo($info); + $html = implode(' ', [ + $RevInfo->editDate(true), // edit date and time + $RevInfo->difflinkRevision(), // link to diffview icon + $RevInfo->itemName(), // name of page or media + $RevInfo->editSummary(), // edit summary + $RevInfo->editor(), // editor info + $RevInfo->sizechange(), // size change indicator + $RevInfo->currentIndicator(), // current indicator (only when k=1) + ]); + $form->addHTML($html); + $form->addTagClose('div'); + $form->addTagClose('li'); + } + $form->addTagClose('ul'); // end of revision list + + // show button for diff view + $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit'); + + $form->addTagClose('div'); // close div class=no + + print $form->toHTML('Revisions'); + + // provide navigation for paginated revision list (of pages and/or media files) + print $this->navigation($first, $hasNext, function ($n) { + return array('do' => 'revisions', 'first' => $n); + }); + } +} diff --git a/inc/Ui/Recent.php b/inc/Ui/Recent.php index f6fe6a3f6..14c786cf0 100644 --- a/inc/Ui/Recent.php +++ b/inc/Ui/Recent.php @@ -2,7 +2,9 @@ namespace dokuwiki\Ui; +use dokuwiki\ChangeLog\PageChangeLog; use dokuwiki\ChangeLog\MediaChangeLog; +use dokuwiki\ChangeLog\RevisionInfo; use dokuwiki\Form\Form; /** @@ -15,7 +17,7 @@ class Recent extends Ui protected $first; protected $show_changes; - /** + /** * Recent Ui constructor * * @param int $first skip the first n changelog lines @@ -72,19 +74,23 @@ class Recent extends Ui // start listing of recent items $form->addTagOpen('ul'); foreach ($recents as $recent) { - $objRevInfo = $this->getObjRevInfo($recent); + // check possible external edition for current page or media + $this->checkCurrentRevision($recent); + $recent['current'] = true; + + $RevInfo = new RevisionInfo($recent); $class = ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor': ''; $form->addTagOpen('li')->addClass($class); $form->addTagOpen('div')->addClass('li'); $html = implode(' ', [ - $objRevInfo->itemIcon(), // filetype icon - $objRevInfo->editDate(), // edit date and time - $objRevInfo->difflink(), // link to diffview icon - $objRevInfo->revisionlink(), // linkto revisions icon - $objRevInfo->itemName(), // name of page or media - $objRevInfo->editSummary(), // edit summary - $objRevInfo->editor(), // editor info - $objRevInfo->sizechange(), // size change indicator + $RevInfo->itemIcon(), // filetype icon + $RevInfo->editDate(), // edit date and time + $RevInfo->difflinkRecent(), // link to diffview icon + $RevInfo->revisionlink(), // linkto revisions icon + $RevInfo->itemName(), // name of page or media + $RevInfo->editSummary(), // edit summary + $RevInfo->editor(), // editor info + $RevInfo->sizechange(), // size change indicator ]); $form->addHTML($html); $form->addTagClose('div'); @@ -141,11 +147,37 @@ class Recent extends Ui } /** + * Check possible external deletion for current page or media + * + * To keep sort order in the recent list, we ignore externally modification. + * It is not possible to know when external deletion had happened, + * $info['date'] is to be incremented 1 second when such deletion detected. + */ + protected function checkCurrentRevision(array &$info) + { + $itemType = strrpos($info['id'], '.') ? 'media' : 'page'; + if ($itemType == 'page') { + $changelog = new PageChangelog($info['id']); + } else { + $changelog = new MediaChangelog($info['id']); + } + if (!$changelog->isCurrentRevision($info['date'])) { + $currentRevInfo = $changelog->getCurrentRevisionInfo(); + if ($currentRevInfo['type'] == DOKU_CHANGE_TYPE_DELETE) { + // the page or media file was externally deleted, updated info because the link is already red + // externally created and edited not updated because sorting by date is not worth so much changes + $info = array_merge($info, $currentRevInfo); + } + } + unset($changelog); + } + + /** * Navigation buttons for Pagenation (prev/next) * * @param int $first * @param bool $hasNext - * @return array html + * @return string html */ protected function htmlNavigation($first, $hasNext) { @@ -196,139 +228,4 @@ class Recent extends Ui $form->addTagClose('div'); } - /** - * Returns instance of objRevInfo - * @param array $info Revision info structure of page or media - * @return objRevInfo object (anonymous class) - */ - protected function getObjRevInfo(array $info) - { - return new class ($info) // anonymous class (objRevInfo) - { - protected $info; - - public function __construct(array $info) - { - $this->info = $info; - } - - // fileicon of the page or media file - public function itemIcon() - { - $id = $this->info['id']; - if (isset($this->info['media'])) { - $html = media_printicon($id); - } else { - $html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />'; - } - return $html; - } - - // edit date and time of the page or media file - public function editDate() - { - return '<span class="date">'. dformat($this->info['date']) .'</span>'; - } - - // edit summary - public function editSummary() - { - return '<span class="sum">'.' – '. hsc($this->info['sum']).'</span>'; - } - - // editor of the page or media file - public function editor() - { - $html = '<span class="user">'; - if ($this->info['user']) { - $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>'; - if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>'; - } else { - $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>'; - } - $html.= '</span>'; - return $html; - } - - // name of the page or media file - public function itemName() - { - $id = $this->info['id']; - if (isset($this->info['media'])) { - $href = media_managerURL(['tab_details'=>'view', 'image'=> $id, 'ns'=> getNS($id)], '&'); - $class = file_exists(mediaFN($id)) ? 'wikilink1' : 'wikilink2'; - $html = '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>'; - } else { - $html = html_wikilink(':'.$id, (useHeading('navigation') ? null : $id)); - } - return $html; - } - - // icon difflink - public function difflink() - { - global $lang; - $id = $this->info['id']; - - if (isset($this->info['media'])) { - $revs = (new MediaChangeLog($id))->getRevisions(0, 1); - $diff = (count($revs) && file_exists(mediaFN($id))); - if ($diff) { - $href = media_managerURL( - ['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&' - ); - } else { - $href = ''; - } - } else { - $href = wl($id, "do=diff", false, '&'); - } - - if ($href) { - $html = '<a href="'.$href.'" class="diff_link">' - . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"' - . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />' - . '</a>'; - } else { - $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />'; - } - return $html; - } - - // icon revision link - public function revisionlink() - { - global $lang; - $id = $this->info['id']; - if (isset($this->info['media'])) { - $href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&'); - } else { - $href = wl($id, "do=revisions", false, '&'); - } - $html = '<a href="'.$href.'" class="revisions_link">' - . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"' - . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />' - . '</a>'; - return $html; - } - - // size change - public function sizeChange() - { - $class = 'sizechange'; - $value = filesize_h(abs($this->info['sizechange'])); - if ($this->info['sizechange'] > 0) { - $class .= ' positive'; - $value = '+' . $value; - } elseif ($this->info['sizechange'] < 0) { - $class .= ' negative'; - $value = '-' . $value; - } else { - $value = '±' . $value; - } - return '<span class="'.$class.'">'.$value.'</span>'; - } - }; // end of anonymous class (objRevInfo) - } - } diff --git a/inc/Ui/Revisions.php b/inc/Ui/Revisions.php index c027244f8..2e8f8d30b 100644 --- a/inc/Ui/Revisions.php +++ b/inc/Ui/Revisions.php @@ -2,193 +2,40 @@ namespace dokuwiki\Ui; -use dokuwiki\ChangeLog\PageChangeLog; -use dokuwiki\ChangeLog\MediaChangeLog; -use dokuwiki\Form\Form; +use dokuwiki\ChangeLog\ChangeLog; /** * DokuWiki Revisions Interface + * parent class of PageRevisions and MediaRevisions * * @package dokuwiki\Ui */ -class Revisions extends Ui +abstract class Revisions extends Ui { - protected $first; - protected $media_id; + /* @var string */ + protected $id; // page id or media id + + /* @var ChangeLog */ + protected $changelog; // PageChangeLog or MediaChangeLog object /** * Revisions Ui constructor * - * @param int $first skip the first n changelog lines - * @param bool|string $media_id id of media, or false for current page + * @param string $id page id or media id */ - public function __construct($first = 0, $media_id = false) + public function __construct($id) { - $this->first = $first; - $this->media_id = $media_id; + $this->id = $id; + $this->setChangeLog(); } /** - * Display list of old revisions - * - * @author Andreas Gohr <andi@splitbrain.org> - * @author Ben Coburn <btcoburn@silicodon.net> - * @author Kate Arzamastseva <pshns@ukr.net> - * @author Satoshi Sahara <sahara.satoshi@gmail.com> - * - * @return void + * set class property changelog */ - public function show() - { - global $ID; - - if ($this->media_id) { - return $this->showMediaRevisions($this->media_id); - } else { - return $this->showPageRevisions($ID); - } - } - - /** - * Display a list of Media Revisions in the MediaManager - * - * @param string $id media id - * @return void - */ - protected function showMediaRevisions($id) - { - global $lang; - - // get revisions, and set correct pagenation parameters (first, hasNext) - $first = $this->first; - $hasNext = false; - $revisions = $this->getRevisions($first, $hasNext); - - // create the form - $form = new Form([ - 'id' => 'page__revisions', // must not be "media__revisions" - 'action' => media_managerURL(['image' => $id], '&'), - 'class' => 'changes', - ]); - $form->setHiddenField('mediado', 'diff'); // required for media revisions - $form->addTagOpen('div')->addClass('no'); - - // start listing - $form->addTagOpen('ul'); - foreach ($revisions as $info) { - $rev = $info['date']; - $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : ''; - $form->addTagOpen('li')->addClass($class); - $form->addTagOpen('div')->addClass('li'); - - if (isset($info['current'])) { - $form->addCheckbox('rev2[]')->val('current'); - } elseif (file_exists(mediaFN($id, $rev))) { - $form->addCheckbox('rev2[]')->val($rev); - } else { - $form->addCheckbox('')->val($rev)->attr('disabled','disabled'); - } - $form->addHTML(' '); - - $objRevInfo = $this->getObjRevInfo($info); - $html = implode(' ', [ - $objRevInfo->editDate(), // edit date and time - $objRevInfo->difflink(), // link to diffview icon - $objRevInfo->itemName(), // name of page or media - '<div>', - $objRevInfo->editSummary(), // edit summary - $objRevInfo->editor(), // editor info - html_sizechange($info['sizechange']), // size change indicator - $objRevInfo->currentIndicator(), // current indicator (only when k=1) - '</div>', - ]); - $form->addHTML($html); - - $form->addTagClose('div'); - $form->addTagClose('li'); - } - $form->addTagClose('ul'); // end of revision list - - // show button for diff view - $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit'); - - $form->addTagClose('div'); // close div class=no - - print $form->toHTML('Revisions'); - - // provide navigation for pagenated revision list (of pages and/or media files) - print $this->htmlNavigation($id, $first, $hasNext); - } + abstract protected function setChangeLog(); /** - * Display a list of Page Revisions - * - * @return void - */ - protected function showPageRevisions($id) - { - global $lang; - - // get revisions, and set correct pagenation parameters (first, hasNext) - $first = $this->first; - $hasNext = false; - $revisions = $this->getRevisions($first, $hasNext); - - // print intro - print p_locale_xhtml('revisions'); - - // create the form - $form = new Form([ - 'id' => 'page__revisions', - 'class' => 'changes', - ]); - $form->addTagOpen('div')->addClass('no'); - - // start listing - $form->addTagOpen('ul'); - foreach ($revisions as $info) { - $rev = $info['date']; - $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : ''; - $form->addTagOpen('li')->addClass($class); - $form->addTagOpen('div')->addClass('li'); - - if (page_exists($id, $rev)) { - $form->addCheckbox('rev2[]')->val($rev); - } else { - $form->addCheckbox('')->val($rev)->attr('disabled','disabled'); - } - $form->addHTML(' '); - - $objRevInfo = $this->getObjRevInfo($info); - $html = implode(' ', [ - $objRevInfo->editDate(), // edit date and time - $objRevInfo->difflink(), // link to diffview icon - $objRevInfo->itemName(), // name of page or media - $objRevInfo->editSummary(), // edit summary - $objRevInfo->editor(), // editor info - $objRevInfo->sizechange(), // size change indicator - $objRevInfo->currentIndicator(), // current indicator (only when k=1) - ]); - $form->addHTML($html); - $form->addTagClose('div'); - $form->addTagClose('li'); - } - $form->addTagClose('ul'); // end of revision list - - // show button for diff view - $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit'); - - $form->addTagClose('div'); // close div class=no - - print $form->toHTML('Revisions'); - - // provide navigation for pagenated revision list (of pages and/or media files) - print $this->htmlNavigation($id, $first, $hasNext); - } - - - /** - * Get revisions, and set correct pagenation parameters (first, hasNext) + * Get revisions, and set correct pagination parameters (first, hasNext) * * @param int $first * @param bool $hasNext @@ -197,81 +44,46 @@ class Revisions extends Ui */ protected function getRevisions(&$first, &$hasNext) { - global $INFO, $conf; - - if ($this->media_id) { - $changelog = new MediaChangeLog($this->media_id); - } else { - $changelog = new PageChangeLog($INFO['id']); - } + global $conf; + $changelog =& $this->changelog; $revisions = []; + $currentRevInfo = $changelog->getCurrentRevisionInfo(); + if (!$currentRevInfo) return $revisions; + + $num = $conf['recent']; + if ($first == 0) { + // add extrenal or existing last revision that is excluded from $changelog->getRevisions() + if (array_key_exists('timestamp', $currentRevInfo) || ( + $currentRevInfo['type'] != DOKU_CHANGE_TYPE_DELETE && + $currentRevInfo['date'] == $changelog->lastRevision() ) + ) { + $revisions[] = $currentRevInfo; + $num = $num - 1; + } + } /* we need to get one additional log entry to be able to * decide if this is the last page or is there another one. * see also Ui\Recent::getRecents() */ - $revlist = $changelog->getRevisions($first, $conf['recent'] +1); - if (count($revlist) == 0 && $first != 0) { + $revlist = $changelog->getRevisions($first, $num + 1); + if (count($revlist) == 0 && $first > 0) { + // resets to zero if $first requested a too high number $first = 0; - $revlist = $changelog->getRevisions($first, $conf['recent'] +1); - } - $exists = ($this->media_id) ? file_exists(mediaFN($this->media_id)) : $INFO['exists']; - if ($first === 0 && $exists) { - // add current page or media as revision[0] - if ($this->media_id) { - $rev = filemtime(fullpath(mediaFN($this->media_id))); - $changelog->setChunkSize(1024); - $revinfo = $changelog->getRevisionInfo($rev) ?: array( - 'date' => $rev, - 'ip' => null, - 'type' => null, - 'id' => $this->media_id, - 'user' => null, - 'sum' => null, - 'extra' => null, - 'sizechange' => null, - ); - $revisions[] = $revinfo + array( - 'media' => true, - 'current' => true, - ); - } else { - if (isset($INFO['meta']['last_change'])) { - $type = $INFO['meta']['last_change']['type']; - $sizechange = $INFO['meta']['last_change']['sizechange']; - } else { - $type = $sizechange = null; - } - - $revisions[] = array( - 'date' => $INFO['lastmod'], - 'ip' => null, - 'type' => $type, - 'id' => $INFO['id'], - 'user' => $INFO['editor'], - 'sum' => $INFO['sum'], - 'extra' => null, - 'sizechange' => $sizechange, - 'current' => true, - ); - } + return $this->getRevisions($first, $hasNext); } // decide if this is the last page or is there another one $hasNext = false; - if (count($revlist) > $conf['recent']) { + if (count($revlist) > $num) { $hasNext = true; array_pop($revlist); // remove one additional log entry } // append each revison info array to the revisions foreach ($revlist as $rev) { - if ($this->media_id) { - $revisions[] = $changelog->getRevisionInfo($rev) + array('media' => true); - } else { - $revisions[] = $changelog->getRevisionInfo($rev); - } + $revisions[] = $changelog->getRevisionInfo($rev); } return $revisions; } @@ -279,12 +91,12 @@ class Revisions extends Ui /** * Navigation buttons for Pagenation (prev/next) * - * @param string $id page id or media id * @param int $first * @param bool $hasNext - * @return array html + * @param callable $callback returns array of hidden fields for the form button + * @return string html */ - protected function htmlNavigation($id, $first, $hasNext) + protected function navigation($first, $hasNext, $callback) { global $conf; @@ -293,167 +105,16 @@ class Revisions extends Ui if ($first > 0) { $first = max($first - $conf['recent'], 0); $html.= '<div class="pagenav-prev">'; - if ($this->media_id) { - $html.= html_btn('newer', $id, "p", media_managerURL(['first' => $first], '&', false, true)); - } else { - $html.= html_btn('newer', $id, "p" ,['do' => 'revisions', 'first' => $first]); - } + $html.= html_btn('newer', $this->id, "p", $callback($first)); $html.= '</div>'; } if ($hasNext) { $html.= '<div class="pagenav-next">'; - if ($this->media_id) { - $html.= html_btn('older', $id, "n", media_managerURL(['first' => $last], '&', false, true)); - } else { - $html.= html_btn('older', $id, "n", ['do' => 'revisions', 'first' => $last]); - } + $html.= html_btn('older', $this->id, "n", $callback($last)); $html.= '</div>'; } $html.= '</div>'; return $html; } - /** - * Returns instance of objRevInfo - * - * @param array $info Revision info structure of a page or media file - * @return objRevInfo object (anonymous class) - */ - protected function getObjRevInfo(array $info) - { - return new class ($info) // anonymous class (objRevInfo) - { - protected $info; - - public function __construct(array $info) - { - if (!isset($info['current'])) { - $info['current'] = false; - } - $this->info = $info; - } - - // current indicator - public function currentIndicator() - { - global $lang; - return ($this->info['current']) ? '('.$lang['current'].')' : ''; - } - - // edit date and time of the page or media file - public function editDate() - { - return '<span class="date">'. dformat($this->info['date']) .'</span>'; - } - - // edit summary - public function editSummary() - { - return '<span class="sum">'.' – '. hsc($this->info['sum']).'</span>'; - } - - // editor of the page or media file - public function editor() - { - // slightly different with display of Ui\Recent, i.e. external edit - global $lang; - $html = '<span class="user">'; - if (!$this->info['user'] && !$this->info['ip']) { - $html.= '('.$lang['external_edit'].')'; - } elseif ($this->info['user']) { - $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>'; - if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>'; - } else { - $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>'; - } - $html.= '</span>'; - return $html; - } - - // name of the page or media file - public function itemName() - { - // slightly different with display of Ui\Recent, i.e. revison may not exists - $id = $this->info['id']; - $rev = $this->info['date']; - - if (isset($this->info['media'])) { - // media file revision - if (isset($this->info['current'])) { - $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view'], '&'); - $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>'; - } elseif (file_exists(mediaFN($id, $rev))) { - $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view', 'rev'=> $rev], '&'); - $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>'; - } else { - $html = $id; - } - return $html; - } else { - // page revision - $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id; - if (!$display_name) $display_name = $id; - if ($this->info['current'] || page_exists($id, $rev)) { - $href = wl($id, "rev=$rev", false, '&'); - $html = '<a href="'.$href.'" class="wikilink1">'.$display_name.'</a>'; - } else { - $html = $display_name; - } - return $html; - } - } - - // icon difflink - public function difflink() - { - global $lang; - $id = $this->info['id']; - $rev = $this->info['date']; - - if (isset($this->info['media'])) { - // media file revision - if (isset($this->info['current']) || !file_exists(mediaFN($id, $rev))) { - $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />'; - } else { - $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&'); - $html = '<a href="'.$href.'" class="diff_link">' - . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"' - . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />' - . '</a> '; - } - return $html; - } else { - // page revision - if ($this->info['current'] || !page_exists($id, $rev)) { - $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />'; - } else { - $href = wl($id, "rev=$rev,do=diff", false, '&'); - $html = '<a href="'.$href.'" class="diff_link">' - . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"' - . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />' - . '</a>'; - } - return $html; - } - } - - // size change - public function sizeChange() - { - $class = 'sizechange'; - $value = filesize_h(abs($this->info['sizechange'])); - if ($this->info['sizechange'] > 0) { - $class .= ' positive'; - $value = '+' . $value; - } elseif ($this->info['sizechange'] < 0) { - $class .= ' negative'; - $value = '-' . $value; - } else { - $value = '±' . $value; - } - return '<span class="'.$class.'">'.$value.'</span>'; - } - }; // end of anonymous class (objRevInfo) - } - } diff --git a/inc/Ui/Search.php b/inc/Ui/Search.php index 9e4e5c3ce..e32101fb5 100644 --- a/inc/Ui/Search.php +++ b/inc/Ui/Search.php @@ -4,6 +4,7 @@ namespace dokuwiki\Ui; use dokuwiki\Extension\Event; use dokuwiki\Form\Form; +use dokuwiki\Utf8\PhpString; use dokuwiki\Utf8\Sort; class Search extends Ui @@ -43,9 +44,7 @@ class Search extends Ui */ public function show() { - $searchHTML = ''; - - $searchHTML .= $this->getSearchIntroHTML($this->query); + $searchHTML = $this->getSearchIntroHTML($this->query); $searchHTML .= $this->getSearchFormHTML($this->query); @@ -480,13 +479,11 @@ class Search extends Ui if (auth_quickaclcheck($queryPagename) >= AUTH_CREATE) { $pagecreateinfo = sprintf($lang['searchcreatepage'], $createQueryPageLink); } - $intro = str_replace( + return str_replace( array('@QUERY@', '@SEARCH@', '@CREATEPAGEINFO@'), array(hsc(rawurlencode($query)), hsc($query), $pagecreateinfo), $intro ); - - return $intro; } /** @@ -499,7 +496,7 @@ class Search extends Ui public function createPagenameFromQuery($parsedQuery) { $cleanedQuery = cleanID($parsedQuery['query']); // already strtolowered - if ($cleanedQuery === \dokuwiki\Utf8\PhpString::strtolower($parsedQuery['query'])) { + if ($cleanedQuery === PhpString::strtolower($parsedQuery['query'])) { return ':' . $cleanedQuery; } $pagename = ''; diff --git a/inc/Ui/UserProfile.php b/inc/Ui/UserProfile.php index 300f1b384..0e46312c6 100644 --- a/inc/Ui/UserProfile.php +++ b/inc/Ui/UserProfile.php @@ -2,6 +2,7 @@ namespace dokuwiki\Ui; +use dokuwiki\Extension\AuthPlugin; use dokuwiki\Form\Form; /** diff --git a/inc/Utf8/PhpString.php b/inc/Utf8/PhpString.php index 5bcd601a4..adc6f0c4f 100644 --- a/inc/Utf8/PhpString.php +++ b/inc/Utf8/PhpString.php @@ -268,6 +268,7 @@ class PhpString */ public static function strtolower($string) { + if($string === null) return ''; // pre-8.1 behaviour if (UTF8_MBSTRING) { if (class_exists('Normalizer', $autoload = false)) { return \Normalizer::normalize(mb_strtolower($string, 'utf-8')); diff --git a/inc/actions.php b/inc/actions.php index 4ea529dcd..8c993ef98 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -52,6 +52,9 @@ function act_clean($act){ list($act) = array_keys($act); } + // no action given + if($act === null) return 'show'; + //remove all bad chars $act = strtolower($act); $act = preg_replace('/[^1-9a-z_]+/','',$act); diff --git a/inc/auth.php b/inc/auth.php index bb0ad57dc..2fad03e8e 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -56,7 +56,7 @@ function auth_setup() { if ($auth->success == false) { // degrade to unauthenticated user - unset($auth); + $auth = null; auth_logoff(); msg($lang['authtempfail'], -1); return false; @@ -281,19 +281,23 @@ function auth_login($user, $pass, $sticky = false, $silent = false) { * * @author Andreas Gohr <andi@splitbrain.org> * - * @return string a MD5 sum of various browser headers + * @return string a SHA256 sum of various browser headers */ function auth_browseruid() { /* @var Input $INPUT */ global $INPUT; - $ip = clientIP(true); - $uid = ''; - $uid .= $INPUT->server->str('HTTP_USER_AGENT'); - $uid .= $INPUT->server->str('HTTP_ACCEPT_CHARSET'); - $uid .= substr($ip, 0, strpos($ip, '.')); - $uid = \dokuwiki\Utf8\PhpString::strtolower($uid); - return md5($uid); + $ip = clientIP(true); + // convert IP string to packed binary representation + $pip = inet_pton($ip); + + $uid = implode("\n", [ + $INPUT->server->str('HTTP_USER_AGENT'), + $INPUT->server->str('HTTP_ACCEPT_LANGUAGE'), + $INPUT->server->str('HTTP_ACCEPT_ENCODING'), + substr($pip, 0, strlen($pip) / 2), // use half of the IP address (works for both IPv4 and IPv6) + ]); + return hash('sha256', $uid); } /** @@ -596,7 +600,7 @@ function auth_quickaclcheck($id) { */ function auth_aclcheck($id, $user, $groups) { $data = array( - 'id' => $id, + 'id' => $id ?? '', 'user' => $user, 'groups' => $groups ); @@ -627,6 +631,7 @@ function auth_aclcheck_cb($data) { // if no ACL is used always return upload rights if(!$conf['useacl']) return AUTH_UPLOAD; if(!$auth) return AUTH_NONE; + if(!is_array($AUTH_ACL)) return AUTH_NONE; //make sure groups is an array if(!is_array($groups)) $groups = array(); diff --git a/inc/changelog.php b/inc/changelog.php index d40b80432..a9b06abc5 100644 --- a/inc/changelog.php +++ b/inc/changelog.php @@ -6,6 +6,9 @@ * @author Andreas Gohr <andi@splitbrain.org> */ +use dokuwiki\ChangeLog\ChangeLog; +use dokuwiki\File\PageFile; + /** * parses a changelog line into it's components * @@ -15,31 +18,15 @@ * @return array|bool parsed line or false */ function parseChangelogLine($line) { - $line = rtrim($line, "\n"); - $tmp = explode("\t", $line); - if ($tmp!==false && count($tmp)>1) { - $info = array(); - $info['date'] = (int)$tmp[0]; // unix timestamp - $info['ip'] = $tmp[1]; // IPv4 address (127.0.0.1) - $info['type'] = $tmp[2]; // log line type - $info['id'] = $tmp[3]; // page id - $info['user'] = $tmp[4]; // user name - $info['sum'] = $tmp[5]; // edit summary (or action reason) - $info['extra'] = $tmp[6]; // extra data (varies by line type) - if(isset($tmp[7]) && $tmp[7] !== '') { //last item has line-end|| - $info['sizechange'] = (int) $tmp[7]; - } else { - $info['sizechange'] = null; - } - return $info; - } else { - return false; - } + return ChangeLog::parseLogLine($line); } /** * Adds an entry to the changelog and saves the metadata for the page * + * Note: timestamp of the change might not be unique especially after very quick + * repeated edits (e.g. change checkbox via do plugin) + * * @param int $date Timestamp of the change * @param String $id Name of the affected page * @param String $type Type of the change see DOKU_CHANGE_TYPE_* @@ -53,79 +40,49 @@ function parseChangelogLine($line) { * @author Andreas Gohr <andi@splitbrain.org> * @author Esther Brunner <wikidesign@gmail.com> * @author Ben Coburn <btcoburn@silicodon.net> + * @deprecated 2021-11-28 */ -function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null, $sizechange = null){ - global $conf, $INFO; +function addLogEntry( + $date, + $id, + $type = DOKU_CHANGE_TYPE_EDIT, + $summary = '', + $extra = '', + $flags = null, + $sizechange = null) +{ + // no more used in DokuWiki core, but left for third-party plugins + dbg_deprecated('see '. PageFile::class .'::saveWikiText()'); + /** @var Input $INPUT */ global $INPUT; // check for special flags as keys - if (!is_array($flags)) { $flags = array(); } + if (!is_array($flags)) $flags = array(); $flagExternalEdit = isset($flags['ExternalEdit']); $id = cleanid($id); - $file = wikiFN($id); - $created = @filectime($file); - $minor = ($type===DOKU_CHANGE_TYPE_MINOR_EDIT); - $wasRemoved = ($type===DOKU_CHANGE_TYPE_DELETE); - - if(!$date) $date = time(); //use current time if none supplied - $remote = (!$flagExternalEdit)?clientIP(true):'127.0.0.1'; - $user = (!$flagExternalEdit)?$INPUT->server->str('REMOTE_USER'):''; - if($sizechange === null) { - $sizechange = ''; - } else { - $sizechange = (int) $sizechange; - } - $strip = array("\t", "\n"); - $logline = array( + if (!$date) $date = time(); //use current time if none supplied + $remote = (!$flagExternalEdit) ? clientIP(true) : '127.0.0.1'; + $user = (!$flagExternalEdit) ? $INPUT->server->str('REMOTE_USER') : ''; + $sizechange = ($sizechange === null) ? '' : (int)$sizechange; + + // update changelog file and get the added entry that is also to be stored in metadata + $pageFile = new PageFile($id); + $logEntry = $pageFile->changelog->addLogEntry([ 'date' => $date, 'ip' => $remote, - 'type' => str_replace($strip, '', $type), + 'type' => $type, 'id' => $id, 'user' => $user, - 'sum' => \dokuwiki\Utf8\PhpString::substr(str_replace($strip, '', $summary), 0, 255), - 'extra' => str_replace($strip, '', $extra), - 'sizechange' => $sizechange - ); + 'sum' => $summary, + 'extra' => $extra, + 'sizechange' => $sizechange, + ]); - $wasCreated = ($type===DOKU_CHANGE_TYPE_CREATE); - $wasReverted = ($type===DOKU_CHANGE_TYPE_REVERT); // update metadata - if (!$wasRemoved) { - $oldmeta = p_read_metadata($id)['persistent']; - $meta = array(); - if ( - $wasCreated && ( - empty($oldmeta['date']['created']) || - $oldmeta['date']['created'] === $created - ) - ){ - // newly created - $meta['date']['created'] = $created; - if ($user){ - $meta['creator'] = isset($INFO) ? $INFO['userinfo']['name'] : null; - $meta['user'] = $user; - } - } elseif (($wasCreated || $wasReverted) && !empty($oldmeta['date']['created'])) { - // re-created / restored - $meta['date']['created'] = $oldmeta['date']['created']; - $meta['date']['modified'] = $created; // use the files ctime here - $meta['creator'] = isset($oldmeta['creator']) ? $oldmeta['creator'] : null; - if ($user) $meta['contributor'][$user] = isset($INFO) ? $INFO['userinfo']['name'] : null; - } elseif (!$minor) { // non-minor modification - $meta['date']['modified'] = $date; - if ($user) $meta['contributor'][$user] = isset($INFO) ? $INFO['userinfo']['name'] : null; - } - $meta['last_change'] = $logline; - p_set_metadata($id, $meta); - } - - // add changelog lines - $logline = implode("\t", $logline)."\n"; - io_saveFile(metaFN($id,'.changes'),$logline,true); //page changelog - io_saveFile($conf['changelog'],$logline,true); //global changelog cache + $pageFile->updateMetadata($logEntry); } /** @@ -149,48 +106,41 @@ function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extr function addMediaLogEntry( $date, $id, - $type=DOKU_CHANGE_TYPE_EDIT, - $summary='', - $extra='', - $flags=null, + $type = DOKU_CHANGE_TYPE_EDIT, + $summary = '', + $extra = '', + $flags = null, $sizechange = null) { - global $conf; /** @var Input $INPUT */ global $INPUT; + // check for special flags as keys + if (!is_array($flags)) $flags = array(); + $flagExternalEdit = isset($flags['ExternalEdit']); + $id = cleanid($id); - if(!$date) $date = time(); //use current time if none supplied - $remote = clientIP(true); - $user = $INPUT->server->str('REMOTE_USER'); - if($sizechange === null) { - $sizechange = ''; - } else { - $sizechange = (int) $sizechange; - } + if (!$date) $date = time(); //use current time if none supplied + $remote = (!$flagExternalEdit) ? clientIP(true) : '127.0.0.1'; + $user = (!$flagExternalEdit) ? $INPUT->server->str('REMOTE_USER') : ''; + $sizechange = ($sizechange === null) ? '' : (int)$sizechange; - $strip = array("\t", "\n"); - $logline = array( + // update changelog file and get the added entry + (new \dokuwiki\ChangeLog\MediaChangeLog($id, 1024))->addLogEntry([ 'date' => $date, 'ip' => $remote, - 'type' => str_replace($strip, '', $type), + 'type' => $type, 'id' => $id, 'user' => $user, - 'sum' => \dokuwiki\Utf8\PhpString::substr(str_replace($strip, '', $summary), 0, 255), - 'extra' => str_replace($strip, '', $extra), - 'sizechange' => $sizechange - ); - - // add changelog lines - $logline = implode("\t", $logline)."\n"; - io_saveFile($conf['media_changelog'],$logline,true); //global media changelog cache - io_saveFile(mediaMetaFN($id,'.changes'),$logline,true); //media file's changelog + 'sum' => $summary, + 'extra' => $extra, + 'sizechange' => $sizechange, + ]); } /** - * returns an array of recently changed files using the - * changelog + * returns an array of recently changed files using the changelog * * The following constants can be used to control which changes are * included. Add them together as needed. @@ -211,12 +161,12 @@ function addMediaLogEntry( * @author Ben Coburn <btcoburn@silicodon.net> * @author Kate Arzamastseva <pshns@ukr.net> */ -function getRecents($first,$num,$ns='',$flags=0){ +function getRecents($first, $num, $ns = '', $flags = 0) { global $conf; $recent = array(); $count = 0; - if(!$num) + if (!$num) return $recent; // read all recent changes. (kept short) @@ -228,7 +178,7 @@ function getRecents($first,$num,$ns='',$flags=0){ if (!is_array($lines)) { $lines = array(); } - $lines_position = count($lines)-1; + $lines_position = count($lines) - 1; $media_lines_position = 0; $media_lines = array(); @@ -237,13 +187,13 @@ function getRecents($first,$num,$ns='',$flags=0){ if (!is_array($media_lines)) { $media_lines = array(); } - $media_lines_position = count($media_lines)-1; + $media_lines_position = count($media_lines) - 1; } $seen = array(); // caches seen lines, _handleRecent() skips them // handle lines - while ($lines_position >= 0 || (($flags & RECENTS_MEDIA_PAGES_MIXED) && $media_lines_position >=0)) { + while ($lines_position >= 0 || (($flags & RECENTS_MEDIA_PAGES_MIXED) && $media_lines_position >= 0)) { if (empty($rec) && $lines_position >= 0) { $rec = _handleRecent(@$lines[$lines_position], $ns, $flags, $seen); if (!$rec) { @@ -274,11 +224,11 @@ function getRecents($first,$num,$ns='',$flags=0){ if ($flags & RECENTS_MEDIA_CHANGES) $x['media'] = true; $rec = false; } - if(--$first >= 0) continue; // skip first entries + if (--$first >= 0) continue; // skip first entries $recent[] = $x; $count++; // break when we have enough entries - if($count >= $num){ break; } + if ($count >= $num) { break; } } return $recent; } @@ -305,11 +255,11 @@ function getRecents($first,$num,$ns='',$flags=0){ * @author Michael Hamann <michael@content-space.de> * @author Ben Coburn <btcoburn@silicodon.net> */ -function getRecentsSince($from,$to=null,$ns='',$flags=0){ +function getRecentsSince($from, $to = null, $ns = '', $flags = 0) { global $conf; $recent = array(); - if($to && $to < $from) + if ($to && $to < $from) return $recent; // read all recent changes. (kept short) @@ -318,7 +268,7 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){ } else { $lines = @file($conf['changelog']); } - if(!$lines) return $recent; + if (!$lines) return $recent; // we start searching at the end of the list $lines = array_reverse($lines); @@ -326,9 +276,9 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){ // handle lines $seen = array(); // caches seen lines, _handleRecent() skips them - foreach($lines as $line){ + foreach ($lines as $line) { $rec = _handleRecent($line, $ns, $flags, $seen); - if($rec !== false) { + if ($rec !== false) { if ($rec['date'] >= $from) { if (!$to || $rec['date'] <= $to) { $recent[] = $rec; @@ -357,30 +307,30 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){ * @param array $seen listing of seen pages * @return array|bool false or array with info about a change */ -function _handleRecent($line,$ns,$flags,&$seen){ - if(empty($line)) return false; //skip empty lines +function _handleRecent($line, $ns, $flags, &$seen) { + if (empty($line)) return false; //skip empty lines // split the line into parts - $recent = parseChangelogLine($line); - if ($recent===false) { return false; } + $recent = ChangeLog::parseLogLine($line); + if ($recent === false) return false; // skip seen ones - if(isset($seen[$recent['id']])) return false; + if (isset($seen[$recent['id']])) return false; // skip changes, of only new items are requested - if($recent['type']!==DOKU_CHANGE_TYPE_CREATE && ($flags & RECENTS_ONLY_CREATION)) return false; + if ($recent['type'] !== DOKU_CHANGE_TYPE_CREATE && ($flags & RECENTS_ONLY_CREATION)) return false; // skip minors - if($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT && ($flags & RECENTS_SKIP_MINORS)) return false; + if ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT && ($flags & RECENTS_SKIP_MINORS)) return false; // remember in seen to skip additional sights $seen[$recent['id']] = 1; // check if it's a hidden page - if(isHiddenPage($recent['id'])) return false; + if (isHiddenPage($recent['id'])) return false; // filter namespace - if (($ns) && (strpos($recent['id'],$ns.':') !== 0)) return false; + if (($ns) && (strpos($recent['id'], $ns.':') !== 0)) return false; // exclude subnamespaces if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false; @@ -394,9 +344,9 @@ function _handleRecent($line,$ns,$flags,&$seen){ if ($recent['perms'] < AUTH_READ) return false; // check existance - if($flags & RECENTS_SKIP_DELETED){ + if ($flags & RECENTS_SKIP_DELETED) { $fn = (($flags & RECENTS_MEDIA_CHANGES) ? mediaFN($recent['id']) : wikiFN($recent['id'])); - if(!file_exists($fn)) return false; + if (!file_exists($fn)) return false; } return $recent; diff --git a/inc/common.php b/inc/common.php index c56240a93..b18a7e4fa 100644 --- a/inc/common.php +++ b/inc/common.php @@ -9,6 +9,8 @@ use dokuwiki\Cache\CacheInstructions; use dokuwiki\Cache\CacheRenderer; use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\File\PageFile; +use dokuwiki\Logger; use dokuwiki\Subscriptions\PageSubscriptionSender; use dokuwiki\Subscriptions\SubscriberManager; use dokuwiki\Extension\AuthPlugin; @@ -24,7 +26,7 @@ use dokuwiki\Extension\Event; * @return string converted string */ function hsc($string) { - return htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8'); } /** @@ -166,7 +168,7 @@ function basicinfo($id, $htmlClient=true){ } // if some outside auth were used only REMOTE_USER is set - if(!$info['userinfo']['name']) { + if(empty($info['userinfo']['name'])) { $info['userinfo']['name'] = $INPUT->server->str('REMOTE_USER'); } @@ -215,11 +217,12 @@ function pageinfo() { $info['filepath'] = wikiFN($ID); $info['exists'] = file_exists($info['filepath']); $info['currentrev'] = @filemtime($info['filepath']); - if($REV) { + + if ($REV) { //check if current revision was meant - if($info['exists'] && ($info['currentrev'] == $REV)) { + if ($info['exists'] && ($info['currentrev'] == $REV)) { $REV = ''; - } elseif($RANGE) { + } elseif ($RANGE) { //section editing does not work with old revisions! $REV = ''; $RANGE = ''; @@ -231,9 +234,8 @@ function pageinfo() { } } $info['rev'] = $REV; - if($info['exists']) { - $info['writable'] = (is_writable($info['filepath']) && - ($info['perm'] >= AUTH_EDIT)); + if ($info['exists']) { + $info['writable'] = (is_writable($info['filepath']) && $info['perm'] >= AUTH_EDIT); } else { $info['writable'] = ($info['perm'] >= AUTH_CREATE); } @@ -245,41 +247,37 @@ function pageinfo() { //who's the editor $pagelog = new PageChangeLog($ID, 1024); - if($REV) { + if ($REV) { $revinfo = $pagelog->getRevisionInfo($REV); } else { - if(!empty($info['meta']['last_change']) && is_array($info['meta']['last_change'])) { + if (!empty($info['meta']['last_change']) && is_array($info['meta']['last_change'])) { $revinfo = $info['meta']['last_change']; } else { $revinfo = $pagelog->getRevisionInfo($info['lastmod']); // cache most recent changelog line in metadata if missing and still valid - if($revinfo !== false) { + if ($revinfo !== false) { $info['meta']['last_change'] = $revinfo; p_set_metadata($ID, array('last_change' => $revinfo)); } } } //and check for an external edit - if($revinfo !== false && $revinfo['date'] != $info['lastmod']) { + if ($revinfo !== false && $revinfo['date'] != $info['lastmod']) { // cached changelog line no longer valid $revinfo = false; $info['meta']['last_change'] = $revinfo; p_set_metadata($ID, array('last_change' => $revinfo)); } - if($revinfo !== false){ + if ($revinfo !== false) { $info['ip'] = $revinfo['ip']; $info['user'] = $revinfo['user']; $info['sum'] = $revinfo['sum']; // See also $INFO['meta']['last_change'] which is the most recent log line for page $ID. // Use $INFO['meta']['last_change']['type']===DOKU_CHANGE_TYPE_MINOR_EDIT in place of $info['minor']. - if($revinfo['user']) { - $info['editor'] = $revinfo['user']; - } else { - $info['editor'] = $revinfo['ip']; - } - }else{ + $info['editor'] = $revinfo['user'] ?: $revinfo['ip']; + } else { $info['ip'] = null; $info['user'] = null; $info['sum'] = null; @@ -317,7 +315,7 @@ function jsinfo() { * * @return array with info about current media item */ -function mediainfo(){ +function mediainfo() { global $NS; global $IMG; @@ -369,7 +367,7 @@ function buildAttributes($params, $skipEmptyStrings = false) { if($white) $url .= ' '; $url .= $key.'="'; - $url .= htmlspecialchars($val); + $url .= hsc($val); $url .= '"'; $white = true; } @@ -452,6 +450,8 @@ function idfilter($id, $ue = true) { /* @var Input $INPUT */ global $INPUT; + $id = (string) $id; + if($conf['useslash'] && $conf['userewrite']) { $id = strtr($id, ':', '/'); } elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && @@ -790,36 +790,12 @@ function clientIP($single = false) { $ip = array_merge($ip, explode(',', str_replace(' ', '', $INPUT->server->str('HTTP_X_REAL_IP')))); } - // some IPv4/v6 regexps borrowed from Feyd - // see: http://forums.devnetwork.net/viewtopic.php?f=38&t=53479 - $dec_octet = '(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|[0-9])'; - $hex_digit = '[A-Fa-f0-9]'; - $h16 = "{$hex_digit}{1,4}"; - $IPv4Address = "$dec_octet\\.$dec_octet\\.$dec_octet\\.$dec_octet"; - $ls32 = "(?:$h16:$h16|$IPv4Address)"; - $IPv6Address = - "(?:(?:{$IPv4Address})|(?:". - "(?:$h16:){6}$ls32". - "|::(?:$h16:){5}$ls32". - "|(?:$h16)?::(?:$h16:){4}$ls32". - "|(?:(?:$h16:){0,1}$h16)?::(?:$h16:){3}$ls32". - "|(?:(?:$h16:){0,2}$h16)?::(?:$h16:){2}$ls32". - "|(?:(?:$h16:){0,3}$h16)?::(?:$h16:){1}$ls32". - "|(?:(?:$h16:){0,4}$h16)?::$ls32". - "|(?:(?:$h16:){0,5}$h16)?::$h16". - "|(?:(?:$h16:){0,6}$h16)?::". - ")(?:\\/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))?)"; - // remove any non-IP stuff $cnt = count($ip); - $match = array(); for($i = 0; $i < $cnt; $i++) { - if(preg_match("/^$IPv4Address$/", $ip[$i], $match) || preg_match("/^$IPv6Address$/", $ip[$i], $match)) { - $ip[$i] = $match[0]; - } else { - $ip[$i] = ''; + if(filter_var($ip[$i], FILTER_VALIDATE_IP) === false) { + unset($ip[$i]); } - if(empty($ip[$i])) unset($ip[$i]); } $ip = array_values(array_unique($ip)); if(empty($ip) || !$ip[0]) $ip[0] = '0.0.0.0'; // for some strange reason we don't have a IP @@ -944,7 +920,7 @@ function checklock($id) { //my own lock @list($ip, $session) = explode("\n", io_readFile($lock)); - if($ip == $INPUT->server->str('REMOTE_USER') || $ip == clientIP() || (session_id() && $session == session_id())) { + if($ip == $INPUT->server->str('REMOTE_USER') || (session_id() && $session == session_id())) { return false; } @@ -990,7 +966,7 @@ function unlock($id) { $lock = wikiLockFN($id); if(file_exists($lock)) { @list($ip, $session) = explode("\n", io_readFile($lock)); - if($ip == $INPUT->server->str('REMOTE_USER') || $ip == clientIP() || $session == session_id()) { + if($ip == $INPUT->server->str('REMOTE_USER') || $session == session_id()) { @unlink($lock); return true; } @@ -1268,45 +1244,11 @@ function con($pre, $text, $suf, $pretty = false) { * wiki, triggered in @see saveWikiText() * * @param string $id the page ID + * @deprecated 2021-11-28 */ function detectExternalEdit($id) { - global $lang; - - $fileLastMod = wikiFN($id); - $lastMod = @filemtime($fileLastMod); // from page - $pagelog = new PageChangeLog($id, 1024); - $lastRev = $pagelog->getRevisions(-1, 1); // from changelog - $lastRev = (int) (empty($lastRev) ? 0 : $lastRev[0]); - - if(!file_exists(wikiFN($id, $lastMod)) && file_exists($fileLastMod) && $lastMod >= $lastRev) { - // add old revision to the attic if missing - saveOldRevision($id); - // add a changelog entry if this edit came from outside dokuwiki - if($lastMod > $lastRev) { - $fileLastRev = wikiFN($id, $lastRev); - $revinfo = $pagelog->getRevisionInfo($lastRev); - if(empty($lastRev) || !file_exists($fileLastRev) || $revinfo['type'] == DOKU_CHANGE_TYPE_DELETE) { - $filesize_old = 0; - } else { - $filesize_old = io_getSizeFile($fileLastRev); - } - $filesize_new = filesize($fileLastMod); - $sizechange = $filesize_new - $filesize_old; - - addLogEntry( - $lastMod, - $id, - DOKU_CHANGE_TYPE_EDIT, - $lang['external_edit'], - '', - array('ExternalEdit' => true), - $sizechange - ); - // remove soon to be stale instructions - $cache = new CacheInstructions($id, $fileLastMod); - $cache->removeCache(); - } - } + dbg_deprecated(PageFile::class .'::detectExternalEdit()'); + (new PageFile($id))->detectExternalEdit(); } /** @@ -1322,117 +1264,19 @@ function detectExternalEdit($id) { * @param bool $minor mark this saved version as minor update */ function saveWikiText($id, $text, $summary, $minor = false) { - /* Note to developers: - This code is subtle and delicate. Test the behavior of - the attic and changelog with dokuwiki and external edits - after any changes. External edits change the wiki page - directly without using php or dokuwiki. - */ - global $conf; - global $lang; - global $REV; - /* @var Input $INPUT */ - global $INPUT; - - // prepare data for event - $svdta = array(); - $svdta['id'] = $id; - $svdta['file'] = wikiFN($id); - $svdta['revertFrom'] = $REV; - $svdta['oldRevision'] = @filemtime($svdta['file']); - $svdta['newRevision'] = 0; - $svdta['newContent'] = $text; - $svdta['oldContent'] = rawWiki($id); - $svdta['summary'] = $summary; - $svdta['contentChanged'] = ($svdta['newContent'] != $svdta['oldContent']); - $svdta['changeInfo'] = ''; - $svdta['changeType'] = DOKU_CHANGE_TYPE_EDIT; - $svdta['sizechange'] = null; - - // select changelog line type - if($REV) { - $svdta['changeType'] = DOKU_CHANGE_TYPE_REVERT; - $svdta['changeInfo'] = $REV; - } else if(!file_exists($svdta['file'])) { - $svdta['changeType'] = DOKU_CHANGE_TYPE_CREATE; - } else if(trim($text) == '') { - // empty or whitespace only content deletes - $svdta['changeType'] = DOKU_CHANGE_TYPE_DELETE; - // autoset summary on deletion - if(blank($svdta['summary'])) { - $svdta['summary'] = $lang['deleted']; - } - } else if($minor && $conf['useacl'] && $INPUT->server->str('REMOTE_USER')) { - //minor edits only for logged in users - $svdta['changeType'] = DOKU_CHANGE_TYPE_MINOR_EDIT; - } - $event = new Event('COMMON_WIKIPAGE_SAVE', $svdta); - if(!$event->advise_before()) return; - - // if the content has not been changed, no save happens (plugins may override this) - if(!$svdta['contentChanged']) return; - - detectExternalEdit($id); - - if( - $svdta['changeType'] == DOKU_CHANGE_TYPE_CREATE || - ($svdta['changeType'] == DOKU_CHANGE_TYPE_REVERT && !file_exists($svdta['file'])) - ) { - $filesize_old = 0; - } else { - $filesize_old = filesize($svdta['file']); - } - if($svdta['changeType'] == DOKU_CHANGE_TYPE_DELETE) { - // Send "update" event with empty data, so plugins can react to page deletion - $data = array(array($svdta['file'], '', false), getNS($id), noNS($id), false); - Event::createAndTrigger('IO_WIKIPAGE_WRITE', $data); - // pre-save deleted revision - @touch($svdta['file']); - clearstatcache(); - $svdta['newRevision'] = saveOldRevision($id); - // remove empty file - @unlink($svdta['file']); - $filesize_new = 0; - // don't remove old meta info as it should be saved, plugins can use - // IO_WIKIPAGE_WRITE for removing their metadata... - // purge non-persistant meta data - p_purge_metadata($id); - // remove empty namespaces - io_sweepNS($id, 'datadir'); - io_sweepNS($id, 'mediadir'); - } else { - // save file (namespace dir is created in io_writeWikiPage) - io_writeWikiPage($svdta['file'], $svdta['newContent'], $id); - // pre-save the revision, to keep the attic in sync - $svdta['newRevision'] = saveOldRevision($id); - $filesize_new = filesize($svdta['file']); - } - $svdta['sizechange'] = $filesize_new - $filesize_old; - - $event->advise_after(); - - addLogEntry( - $svdta['newRevision'], - $svdta['id'], - $svdta['changeType'], - $svdta['summary'], - $svdta['changeInfo'], - null, - $svdta['sizechange'] - ); + // get COMMON_WIKIPAGE_SAVE event data + $data = (new PageFile($id))->saveWikiText($text, $summary, $minor); // send notify mails - notify($svdta['id'], 'admin', $svdta['oldRevision'], $svdta['summary'], $minor, $svdta['newRevision']); - notify($svdta['id'], 'subscribers', $svdta['oldRevision'], $svdta['summary'], $minor, $svdta['newRevision']); - - // update the purgefile (timestamp of the last time anything within the wiki was changed) - io_saveFile($conf['cachedir'].'/purgefile', time()); + list('oldRevision' => $rev, 'newRevision' => $new_rev, 'summary' => $summary) = $data; + notify($id, 'admin', $rev, $summary, $minor, $new_rev); + notify($id, 'subscribers', $rev, $summary, $minor, $new_rev); // if useheading is enabled, purge the cache of all linking pages - if(useHeading('content')) { + if (useHeading('content')) { $pages = ft_backlinks($id, true); - foreach($pages as $page) { + foreach ($pages as $page) { $cache = new CacheRenderer($page, wikiFN($page), 'xhtml'); $cache->removeCache(); } @@ -1440,21 +1284,17 @@ function saveWikiText($id, $text, $summary, $minor = false) { } /** - * moves the current version to the attic and returns its - * revision date + * moves the current version to the attic and returns its revision date * * @author Andreas Gohr <andi@splitbrain.org> * * @param string $id page id * @return int|string revision timestamp + * @deprecated 2021-11-28 */ function saveOldRevision($id) { - $oldf = wikiFN($id); - if(!file_exists($oldf)) return ''; - $date = filemtime($oldf); - $newf = wikiFN($id, $date); - io_writeWikiPage($newf, rawWiki($id), $id, $date); - return $date; + dbg_deprecated(PageFile::class .'::saveOldRevision()'); + return (new PageFile($id))->saveOldRevision(); } /** @@ -1462,7 +1302,7 @@ function saveOldRevision($id) { * * @param string $id The changed page * @param string $who Who to notify (admin|subscribers|register) - * @param int|string $rev Old page revision + * @param int|string $rev Old page revision * @param string $summary What changed * @param boolean $minor Is this a minor edit? * @param string[] $replace Additional string substitutions, @KEY@ to be replaced by value @@ -1477,20 +1317,20 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = global $INPUT; // decide if there is something to do, eg. whom to mail - if($who == 'admin') { - if(empty($conf['notify'])) return false; //notify enabled? + if ($who == 'admin') { + if (empty($conf['notify'])) return false; //notify enabled? $tpl = 'mailtext'; $to = $conf['notify']; - } elseif($who == 'subscribers') { - if(!actionOK('subscribe')) return false; //subscribers enabled? - if($conf['useacl'] && $INPUT->server->str('REMOTE_USER') && $minor) return false; //skip minors + } elseif ($who == 'subscribers') { + if (!actionOK('subscribe')) return false; //subscribers enabled? + if ($conf['useacl'] && $INPUT->server->str('REMOTE_USER') && $minor) return false; //skip minors $data = array('id' => $id, 'addresslist' => '', 'self' => false, 'replacements' => $replace); Event::createAndTrigger( 'COMMON_NOTIFY_ADDRESSLIST', $data, array(new SubscriberManager(), 'notifyAddresses') ); $to = $data['addresslist']; - if(empty($to)) return false; + if (empty($to)) return false; $tpl = 'subscr_single'; } else { return false; //just to be safe @@ -2066,7 +1906,7 @@ function set_doku_pref($pref, $val) { if ($parts[$i] == $enc_pref) { if (!$seen){ if ($val !== false) { - $parts[$i + 1] = rawurlencode($val); + $parts[$i + 1] = rawurlencode($val ?? ''); } else { unset($parts[$i]); unset($parts[$i + 1]); diff --git a/inc/html.php b/inc/html.php index e8cfed872..f2862a1f1 100644 --- a/inc/html.php +++ b/inc/html.php @@ -6,10 +6,25 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -use dokuwiki\ChangeLog\MediaChangeLog; +use dokuwiki\Action\Denied; +use dokuwiki\Action\Locked; use dokuwiki\ChangeLog\PageChangeLog; use dokuwiki\Extension\AuthPlugin; use dokuwiki\Extension\Event; +use dokuwiki\Ui\Backlinks; +use dokuwiki\Ui\Editor; +use dokuwiki\Ui\Index; +use dokuwiki\Ui\Login; +use dokuwiki\Ui\PageConflict; +use dokuwiki\Ui\PageDiff; +use dokuwiki\Ui\PageDraft; +use dokuwiki\Ui\PageRevisions; +use dokuwiki\Ui\PageView; +use dokuwiki\Ui\Recent; +use dokuwiki\Ui\UserProfile; +use dokuwiki\Ui\UserRegister; +use dokuwiki\Ui\UserResendPwd; +use dokuwiki\Utf8\Clean; if (!defined('SEC_EDIT_PATTERN')) { define('SEC_EDIT_PATTERN', '#<!-- EDIT({.*?}) -->#'); @@ -44,7 +59,7 @@ function html_wikilink($id, $name = null, $search = '') { * @deprecated 2020-07-18 */ function html_login($svg = false) { - dbg_deprecated(\dokuwiki\Ui\Login::class .'::show()'); + dbg_deprecated(Login::class .'::show()'); (new dokuwiki\Ui\Login($svg))->show(); } @@ -52,11 +67,10 @@ function html_login($svg = false) { /** * Denied page content * - * @return string html * @deprecated 2020-07-18 not called anymore, see inc/Action/Denied::tplContent() */ function html_denied() { - dbg_deprecated(\dokuwiki\Action\Denied::class .'::showBanner()'); + dbg_deprecated(Denied::class .'::showBanner()'); (new dokuwiki\Action\Denied())->showBanner(); } @@ -94,7 +108,7 @@ function html_secedit_button($matches){ $json = htmlspecialchars_decode($matches[1], ENT_QUOTES); $data = json_decode($json, true); if ($data == NULL) { - return; + return ''; } $data ['target'] = strtolower($data['target']); $data ['hid'] = strtolower($data['hid']); @@ -145,11 +159,10 @@ function html_secedit_get_button($data) { function html_topbtn() { global $lang; - $html = '<a class="nolink" href="#dokuwiki__top">' + return '<a class="nolink" href="#dokuwiki__top">' .'<button class="button" onclick="window.scrollTo(0, 0)" title="'. $lang['btn_top'] .'">' . $lang['btn_top'] .'</button></a>'; - return $html; } /** @@ -161,7 +174,7 @@ function html_topbtn() { * @param string $name * @param string $id * @param string $akey access key - * @param string[] $params key-value pairs added as hidden inputs + * @param string[] $params key-value pairs added as hidden inputs * @param string $method * @param string $tooltip * @param bool|string $label label text, false: lookup btn_$name in localization @@ -221,7 +234,7 @@ function html_btn($name, $id, $akey, $params, $method = 'get', $tooltip = '', $l * @deprecated 2020-07-18 */ function html_showrev() { - dbg_deprecated(\dokuwiki\Ui\PageView::class .'::showrev()'); + dbg_deprecated(PageView::class .'::showrev()'); } /** @@ -233,7 +246,7 @@ function html_showrev() { * @deprecated 2020-07-18 */ function html_show($txt=null) { - dbg_deprecated(\dokuwiki\Ui\PageView::class .'::show()'); + dbg_deprecated(PageView::class .'::show()'); (new dokuwiki\Ui\PageView($txt))->show(); } @@ -244,8 +257,8 @@ function html_show($txt=null) { * @deprecated 2020-07-18 */ function html_draft() { - dbg_deprecated(\dokuwiki\Ui\Draft::class .'::show()'); - (new dokuwiki\Ui\Draft)->show(); + dbg_deprecated(PageDraft::class .'::show()'); + (new dokuwiki\Ui\PageDraft)->show(); } /** @@ -266,16 +279,15 @@ function html_hilight($html, $phrases) { $regex = join('|',$phrases); if ($regex === '') return $html; - if (!\dokuwiki\Utf8\Clean::isUtf8($regex)) return $html; + if (!Clean::isUtf8($regex)) return $html; - $html = @preg_replace_callback("/((<[^>]*)|$regex)/ui", function ($match) { + return @preg_replace_callback("/((<[^>]*)|$regex)/ui", function ($match) { $hlight = unslash($match[0]); if (!isset($match[2])) { $hlight = '<span class="search_hit">'.$hlight.'</span>'; } return $hlight; }, $html); - return $html; } /** @@ -285,7 +297,7 @@ function html_hilight($html, $phrases) { * @deprecated 2020-07-18 not called anymore, see inc/Action/Locked::tplContent() */ function html_locked() { - dbg_deprecated(\dokuwiki\Action\Locked::class .'::showBanner()'); + dbg_deprecated(Locked::class .'::showBanner()'); (new dokuwiki\Action\Locked())->showBanner(); } @@ -297,12 +309,17 @@ function html_locked() { * @author Kate Arzamastseva <pshns@ukr.net> * * @param int $first skip the first n changelog lines - * @param bool|string $media_id id of media, or false for current page + * @param string $media_id id of media, or empty for current page * @deprecated 2020-07-18 */ -function html_revisions($first=0, $media_id = false) { - dbg_deprecated(\dokuwiki\Ui\Revisions::class .'::show()'); - (new dokuwiki\Ui\Revisions($first, $media_id))->show(); +function html_revisions($first = 0, $media_id = '') { + dbg_deprecated(PageRevisions::class .'::show()'); + if ($media_id) { + (new dokuwiki\Ui\MediaRevisions($media_id))->show($first); + } else { + global $INFO; + (new dokuwiki\Ui\PageRevisions($INFO['id']))->show($first); + } } /** @@ -318,7 +335,7 @@ function html_revisions($first=0, $media_id = false) { * @deprecated 2020-07-18 */ function html_recent($first = 0, $show_changes = 'both') { - dbg_deprecated(\dokuwiki\Ui\Recent::class .'::show()'); + dbg_deprecated(Recent::class .'::show()'); (new dokuwiki\Ui\Recent($first, $show_changes))->show(); } @@ -331,7 +348,7 @@ function html_recent($first = 0, $show_changes = 'both') { * @deprecated 2020-07-18 */ function html_index($ns) { - dbg_deprecated(\dokuwiki\Ui\Index::class .'::show()'); + dbg_deprecated(Index::class .'::show()'); (new dokuwiki\Ui\Index($ns))->show(); } @@ -347,7 +364,7 @@ function html_index($ns) { * @deprecated 2020-07-18 */ function html_list_index($item) { - dbg_deprecated(\dokuwiki\Ui\Index::class .'::formatListItem()'); + dbg_deprecated(Index::class .'::formatListItem()'); return (new dokuwiki\Ui\Index)->formatListItem($item); } @@ -365,7 +382,7 @@ function html_list_index($item) { * @deprecated 2020-07-18 */ function html_li_index($item) { - dbg_deprecated(\dokuwiki\Ui\Index::class .'::tagListItem()'); + dbg_deprecated(Index::class .'::tagListItem()'); return (new dokuwiki\Ui\Index)->tagListItem($item); } @@ -478,7 +495,7 @@ function html_buildlist($data, $class, $func, $lifunc = null, $forcewrapper = fa * @deprecated 2020-07-18 */ function html_backlinks() { - dbg_deprecated(\dokuwiki\Ui\Backlinks::class .'::show()'); + dbg_deprecated(Backlinks::class .'::show()'); (new dokuwiki\Ui\Backlinks)->show(); } @@ -494,7 +511,8 @@ function html_backlinks() { * @deprecated 2020-07-18 */ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = false) { - dbg_deprecated('see '. \dokuwiki\Ui\Diff::class .'::diffHead()'); + dbg_deprecated('see '. PageDiff::class .'::buildDiffHead()'); + return ['', '', '', '']; } /** @@ -509,8 +527,12 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa * @deprecated 2020-07-18 */ function html_diff($text = '', $intro = true, $type = null) { - dbg_deprecated(\dokuwiki\Ui\Diff::class .'::show()'); - (new dokuwiki\Ui\Diff($text, $intro, $type))->show(); + dbg_deprecated(PageDiff::class .'::show()'); + global $INFO; + (new dokuwiki\Ui\PageDiff($INFO['id']))->compareWith($text)->preference([ + 'showIntro' => $intro, + 'difftype' => $type, + ])->show(); } /** @@ -524,7 +546,8 @@ function html_diff($text = '', $intro = true, $type = null) { * @deprecated 2020-07-18 */ function html_diff_navigation($pagelog, $type, $l_rev, $r_rev) { - dbg_deprecated('see '. \dokuwiki\Ui\Diff::class .'::diffNavigation()'); + dbg_deprecated('see '. PageDiff::class .'::buildRevisionsNavigation()'); + return ['', '']; } /** @@ -538,7 +561,8 @@ function html_diff_navigation($pagelog, $type, $l_rev, $r_rev) { * @deprecated 2020-07-18 */ function html_diff_navigationlink($difftype, $linktype, $lrev, $rrev = null) { - dbg_deprecated('see '. \dokuwiki\Ui\Diff::class .'::diffViewlink()'); + dbg_deprecated('see '. PageDiff::class .'::diffViewlink()'); + return ''; } /** @@ -549,8 +573,8 @@ function html_diff_navigationlink($difftype, $linktype, $lrev, $rrev = null) { * @deprecated 2020-07-18 */ function html_insert_softbreaks($diffhtml) { - dbg_deprecated(\dokuwiki\Ui\Diff::class .'::insertSoftbreaks()'); - return (new dokuwiki\Ui\Diff())->insertSoftbreaks($diffhtml); + dbg_deprecated(PageDiff::class .'::insertSoftbreaks()'); + return (new dokuwiki\Ui\PageDiff)->insertSoftbreaks($diffhtml); } /** @@ -563,8 +587,8 @@ function html_insert_softbreaks($diffhtml) { * @deprecated 2020-07-18 */ function html_conflict($text, $summary) { - dbg_deprecated(\dokuwiki\Ui\Conflict::class .'::show()'); - (new dokuwiki\Ui\Conflict($text, $summary))->show(); + dbg_deprecated(PageConflict::class .'::show()'); + (new dokuwiki\Ui\PageConflict($text, $summary))->show(); } /** @@ -602,7 +626,7 @@ function html_msgarea() { * @deprecated 2020-07-18 */ function html_register() { - dbg_deprecated(\dokuwiki\Ui\UserRegister::class .'::show()'); + dbg_deprecated(UserRegister::class .'::show()'); (new dokuwiki\Ui\UserRegister)->show(); } @@ -614,7 +638,7 @@ function html_register() { * @deprecated 2020-07-18 */ function html_updateprofile() { - dbg_deprecated(\dokuwiki\Ui\UserProfile::class .'::show()'); + dbg_deprecated(UserProfile::class .'::show()'); (new dokuwiki\Ui\UserProfile)->show(); } @@ -626,7 +650,7 @@ function html_updateprofile() { * @deprecated 2020-07-18 */ function html_edit() { - dbg_deprecated(\dokuwiki\Ui\Editor::class .'::show()'); + dbg_deprecated(Editor::class .'::show()'); (new dokuwiki\Ui\Editor)->show(); } @@ -635,12 +659,12 @@ function html_edit() { * * Is the default action for HTML_EDIT_FORMSELECTION. * - * @param mixed[] $param + * @param array $param * @deprecated 2020-07-18 */ function html_edit_form($param) { - dbg_deprecated(\dokuwiki\Ui\Editor::class .'::addTextarea()'); - return (new dokuwiki\Ui\Editor)->addTextarea($param); + dbg_deprecated(Editor::class .'::addTextarea()'); + (new dokuwiki\Ui\Editor)->addTextarea($param); } /** @@ -749,7 +773,7 @@ function html_debug() { * @deprecated 2020-07-18 */ function html_resendpwd() { - dbg_deprecated(\dokuwiki\Ui\UserResendPwd::class .'::show()'); + dbg_deprecated(UserResendPwd::class .'::show()'); (new dokuwiki\Ui\UserResendPwd)->show(); } diff --git a/inc/lang/ar/lang.php b/inc/lang/ar/lang.php index 7a86edfcf..705ef5b31 100644 --- a/inc/lang/ar/lang.php +++ b/inc/lang/ar/lang.php @@ -213,7 +213,7 @@ $lang['created'] = 'اÙنشئت'; $lang['restored'] = 'استعيدت نسخة قديمة (%s)'; $lang['external_edit'] = 'ØªØØ±ÙŠØ± خارجي'; $lang['summary'] = 'ملخص Ø§Ù„ØªØØ±ÙŠØ±'; -$lang['noflash'] = 'ØªØØªØ§Ø¬ إلى<a href="http://www.adobe.com/products/flashplayer/">ملØÙ‚ Ùلاش أدوبي</a> لعرض هذا Ø§Ù„Ù…ØØªÙˆÙ‰.'; +$lang['noflash'] = 'ØªØØªØ§Ø¬ إلى<a href="http://get.adobe.com/flashplayer">ملØÙ‚ Ùلاش أدوبي</a> لعرض هذا Ø§Ù„Ù…ØØªÙˆÙ‰.'; $lang['download'] = 'نزل Snippet'; $lang['tools'] = 'أدوات'; $lang['user_tools'] = 'أدوات المستخدم'; @@ -294,7 +294,7 @@ $lang['i_enableacl'] = 'ØªÙØ¹ÙŠÙ„ ACL - Ù…ÙØ¶Ù„'; $lang['i_superuser'] = 'مشرÙ'; $lang['i_problems'] = 'وجد برنامج التنصيب المشاكل التالية، لا يمكنك المتابعة قبل ØÙ„ها.'; $lang['i_modified'] = 'لأسباب أمنية هذا البرنامج سيعمل Ùقط مع تنصيب دوكو ويكي جديد Ùˆ غير معدّل. -يجب أن تعيد ÙÙƒ ضغط Ø§Ù„Ù…Ù„ÙØ§Øª مرة أخرى من المكتبة المضغوطة، أو راجع <a href="http://dokuwiki.org/install"> تعليمات تنصيب دوكو ويكي </a> '; +يجب أن تعيد ÙÙƒ ضغط Ø§Ù„Ù…Ù„ÙØ§Øª مرة أخرى من المكتبة المضغوطة، أو راجع <a href="https://www.dokuwiki.org/install"> تعليمات تنصيب دوكو ويكي </a> '; $lang['i_funcna'] = 'دالة PHP التالية غير Ù…ØªÙˆÙØ±Ø©. <code>%s</code> قد يكون مزود خدمة Ø§Ù„Ø§Ø³ØªÙØ§Ø¯Ø© قد ØØ¬Ø¨Ù‡Ø§ لسبب ما.'; diff --git a/inc/lang/az/lang.php b/inc/lang/az/lang.php index f2c9aa662..da4836ebd 100644 --- a/inc/lang/az/lang.php +++ b/inc/lang/az/lang.php @@ -151,7 +151,7 @@ $lang['created'] = 'yaranıb'; $lang['restored'] = 'köhnÉ™ versiya qaytarıldı (%s)'; $lang['external_edit'] = 'bayırdan dÉ™yiÅŸik'; $lang['summary'] = 'DÉ™yiÅŸiklÉ™r xülasÉ™si'; -$lang['noflash'] = 'Bu mÉ™zmuna baxmaq üçün <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> tÉ™lÉ™b olunur.'; +$lang['noflash'] = 'Bu mÉ™zmuna baxmaq üçün <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> tÉ™lÉ™b olunur.'; $lang['download'] = 'Kodu yüklÉ™'; $lang['mail_newpage'] = 'sÉ™hifÉ™ É™lavÉ™ olundu:'; $lang['mail_changed'] = 'sÉ™hifÉ™yÉ™ düzÉ™liÅŸ edildi:'; @@ -203,7 +203,7 @@ $lang['i_enableacl'] = 'Haqlar kontrolu siyahısının istifadÉ™sinÉ™ $lang['i_superuser'] = 'Super-istifadÉ™ci'; $lang['i_problems'] = 'QuraÅŸdırma proqramı aÅŸağıdakı problemlÉ™r ilÉ™ üzləşdi. Davam etmÉ™k üçün onları hÉ™ll etmÉ™k lazımdır. '; $lang['i_modified'] = 'TÉ™hlükÉ™sizlik baxımından bu proqram ancaq yeni, dÉ™yiÅŸmÉ™miÅŸ halda olan DokuWiki üzÉ™rindÉ™ iÅŸlÉ™yir. - Siz ya yüklÉ™nmiÅŸ quraÅŸdırma paketini yenidÉ™n açmalısınız, ya da <a href="http://dokuwiki.org/install">DokuWiki-nin tam quraÅŸdırma instruksiyasına</a> müraciyÉ™t etmÉ™lisiniz'; + Siz ya yüklÉ™nmiÅŸ quraÅŸdırma paketini yenidÉ™n açmalısınız, ya da <a href="https://www.dokuwiki.org/install">DokuWiki-nin tam quraÅŸdırma instruksiyasına</a> müraciyÉ™t etmÉ™lisiniz'; $lang['i_funcna'] = 'PHP-nin <code>%s</code> funksiyası mövcud deyil. BÉ™lkÉ™, o hansı sa sÉ™bÉ™bdÉ™n sizin host-unuz tÉ™rÉ™findÉ™n blok edilib?'; $lang['i_phpver'] = 'Sizin PHP-nin versiyası (<code>%s</code>) tÉ™lÉ™b olunan versiyadan aÅŸagıdır (<code>%s</code>). QuraÅŸdırılmış PHP-nin versiyasını yenilÉ™yin.'; $lang['i_permfail'] = '<code>%s</code> DokuWiki-yÉ™ yazı üçün baÄŸlıdır. Bu qovluÄŸun giriÅŸ haqlarını yoxlamaq lazımdır!'; diff --git a/inc/lang/be/lang.php b/inc/lang/be/lang.php index 2e8e7dd9b..2c016d168 100644 --- a/inc/lang/be/lang.php +++ b/inc/lang/be/lang.php @@ -209,7 +209,7 @@ $lang['created'] = 'Ñтворана'; $lang['restored'] = 'ÑÑ‚Ð°Ñ€Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Ð°Ð´Ð½Ð¾ÑžÐ»ÐµÐ½Ð° (%s)'; $lang['external_edit'] = 'знешнÑе змена'; $lang['summary'] = 'Зводка змÑненнÑÑž'; -$lang['noflash'] = 'Ð”Ð»Ñ Ð¿Ñ€Ð°Ð³Ð»Ñду змеÑціва гÑтага патрабуецца <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'Ð”Ð»Ñ Ð¿Ñ€Ð°Ð³Ð»Ñду змеÑціва гÑтага патрабуецца <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'Спампаваць фрагмент кода'; $lang['tools'] = 'ІнÑтрументы'; $lang['user_tools'] = 'ІнÑтрументы карыÑтальніка'; diff --git a/inc/lang/bg/lang.php b/inc/lang/bg/lang.php index accc4973b..8daeb8a69 100644 --- a/inc/lang/bg/lang.php +++ b/inc/lang/bg/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Alinur <alinur@danwin1210.de> * @author Salif Mehmed <salif13mehmed@gmail.com> * @author Nikolay Vladimirov <nikolay@vladimiroff.com> * @author Viktor Usunov <usun0v@mail.bg> @@ -68,6 +69,7 @@ $lang['badpassconfirm'] = 'За Ñъжаление паролата е г $lang['minoredit'] = 'Промените Ñа незначителни'; $lang['draftdate'] = 'Черновата е автоматично запиÑана на'; $lang['nosecedit'] = 'Страницата бе междувременно променена, презареждане на Ñтраницата поради неактуална информациÑ.'; +$lang['searchcreatepage'] = 'Ðко не Ñи намерил, каквото ти търÑиш, ти можеш да го Ñъздадеш или редактираш Ñтраницата %s, кръÑтена на вашето запитване.'; $lang['js']['willexpire'] = 'Страницата ще бъде отключена за редактиране Ñлед минута.\nЗа предотвратÑване на конфликти, ползвайте бутона "Преглед", за реÑтартиране на броÑча за заключване.'; $lang['js']['notsavedyet'] = 'ÐезапиÑаните промени ще бъдат загубени. Желаете ли да продължите?'; $lang['js']['searchmedia'] = 'ТърÑене на файлове'; @@ -109,6 +111,7 @@ $lang['js']['media_done_btn'] = 'Готово'; $lang['js']['media_drop'] = 'Влачете и пуÑнете файлове тук, за да бъдат качени'; $lang['js']['media_cancel'] = 'премахване'; $lang['js']['media_overwrt'] = 'Презапиши ÑъщеÑтвуващите файлове'; +$lang['search_exact_match'] = 'Точно Ñъвпадение'; $lang['search_starts_with'] = 'започва Ñ'; $lang['search_ends_with'] = 'завършва Ñ'; $lang['search_contains'] = 'Ñъдържа'; @@ -203,7 +206,7 @@ $lang['created'] = 'Ñъздадена'; $lang['restored'] = 'възÑтановена предишна верÑÐ¸Ñ (%s)'; $lang['external_edit'] = 'външна редакциÑ'; $lang['summary'] = 'Обобщение'; -$lang['noflash'] = 'Ðеобходим е <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> за изобразÑване на Ñъдържанието.'; +$lang['noflash'] = 'Ðеобходим е <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> за изобразÑване на Ñъдържанието.'; $lang['download'] = 'ИзтеглÑне на фрагмент'; $lang['tools'] = 'ИнÑтрументи'; $lang['user_tools'] = 'ИнÑтрументи за потребители'; @@ -284,7 +287,7 @@ $lang['i_enableacl'] = 'Ползване на ÑпиÑък за Ð´Ð¾Ñ $lang['i_superuser'] = 'Супер потребител'; $lang['i_problems'] = 'Открити Ñа проблеми, които възпрепÑÑ‚Ñтват инÑталирането. Ще можете да продължите Ñлед като отÑтраните долуизброените проблеми.'; $lang['i_modified'] = 'Поради мерки за ÑигурноÑÑ‚ инÑталаторът работи Ñамо Ñ Ð½Ð¾Ð²Ð¸ и непроменени инÑталационни файлове. - ТрÑбва да разархивирате отново файловете от ÑÐ²Ð°Ð»ÐµÐ½Ð¸Ñ Ð°Ñ€Ñ…Ð¸Ð² или да Ñе поÑъветвате Ñ <a href="http://dokuwiki.org/install">ИнÑтрукциите за инÑталиране на Dokuwiki</a>.'; + ТрÑбва да разархивирате отново файловете от ÑÐ²Ð°Ð»ÐµÐ½Ð¸Ñ Ð°Ñ€Ñ…Ð¸Ð² или да Ñе поÑъветвате Ñ <a href="https://www.dokuwiki.org/install">ИнÑтрукциите за инÑталиране на Dokuwiki</a>.'; $lang['i_funcna'] = 'PHP функциÑта <code>%s</code> не е доÑтъпна. Може би е забранена от доÑтавчика на хоÑтинг.'; $lang['i_phpver'] = 'ИнÑталираната верÑÐ¸Ñ <code>%s</code> на PHP е по-Ñтара от необходимата <code>%s</code>. Ðктуализирайте PHP инÑталациÑта.'; $lang['i_mbfuncoverload'] = 'Ðеобходимо е да изключите mbstring.func_overload в php.ini за да може DokuWiki да Ñтартира.'; @@ -338,6 +341,7 @@ $lang['media_perm_read'] = 'За Ñъжаление нÑмате доÑтР$lang['media_perm_upload'] = 'За Ñъжаление нÑмате доÑтатъчно права, за да можете да качите файла.'; $lang['media_update'] = 'Качване на нова верÑиÑ'; $lang['media_restore'] = 'ВъзÑтановÑване на тази верÑиÑ'; +$lang['email_fail'] = 'PHP mail() липÑва или деактивиран. СледниÑÑ‚ имейл не беше изпратен:'; $lang['currentns'] = 'Текущо именно проÑтранÑтво'; $lang['searchresult'] = 'Резултати от търÑенето'; $lang['plainhtml'] = 'Обикновен HTML'; diff --git a/inc/lang/bg/onceexisted.txt b/inc/lang/bg/onceexisted.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/inc/lang/bg/onceexisted.txt @@ -0,0 +1 @@ + diff --git a/inc/lang/bn/lang.php b/inc/lang/bn/lang.php index 5cb66a853..186e54bff 100644 --- a/inc/lang/bn/lang.php +++ b/inc/lang/bn/lang.php @@ -195,7 +195,7 @@ $lang['created'] = 'তৈরি করা'; $lang['restored'] = 'পà§à¦°à¦¾à¦¨à§‹ সংসà§à¦•রণের পà§à¦¨à¦ƒà¦¸à§à¦¥à¦¾à¦ªà¦¨ (%s)'; $lang['external_edit'] = 'বাহà§à¦¯à¦¿à¦• সমà§à¦ªà¦¾à¦¦à¦¨à¦¾'; $lang['summary'] = 'সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ সারাংশ'; -$lang['noflash'] = 'ঠhref="http://www.adobe.com/products/flashplayer/"> অà§à¦¯à¦¾à¦¡à§‹à¦¬à¦¿ ফà§à¦²à§à¦¯à¦¾à¦¶ পà§à¦²à¦¾à¦—ইন </a> à¦à¦‡ সামগà§à¦°à§€ পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করার জনà§à¦¯ পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨ হয়.'; +$lang['noflash'] = 'ঠhref="http://get.adobe.com/flashplayer"> অà§à¦¯à¦¾à¦¡à§‹à¦¬à¦¿ ফà§à¦²à§à¦¯à¦¾à¦¶ পà§à¦²à¦¾à¦—ইন </a> à¦à¦‡ সামগà§à¦°à§€ পà§à¦°à¦¦à¦°à§à¦¶à¦¨ করার জনà§à¦¯ পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨ হয়.'; $lang['download'] = 'ডাউনলোড সà§à¦¨à¦¿à¦ªà§‡à¦Ÿ '; $lang['tools'] = 'সরঞà§à¦œà¦¾à¦®à¦¸à¦®à§‚হ'; $lang['user_tools'] = 'বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•ারীর সরঞà§à¦œà¦¾à¦®à¦¸à¦®à§‚হ'; diff --git a/inc/lang/ca-valencia/lang.php b/inc/lang/ca-valencia/lang.php index da6bd67c1..6cefa251f 100644 --- a/inc/lang/ca-valencia/lang.php +++ b/inc/lang/ca-valencia/lang.php @@ -138,7 +138,7 @@ $lang['created'] = 'creat'; $lang['restored'] = 'restaurada l\'última versió (%s)'; $lang['external_edit'] = 'edició externa'; $lang['summary'] = 'Editar sumari'; -$lang['noflash'] = 'Necessita el <a href="http://www.adobe.com/products/flashplayer/">plúgin d\'Adobe Flash</a> per a vore este contingut.'; +$lang['noflash'] = 'Necessita el <a href="http://get.adobe.com/flashplayer">plúgin d\'Adobe Flash</a> per a vore este contingut.'; $lang['download'] = 'Descarregar un tros'; $lang['mail_newpage'] = 'pà gina afegida:'; $lang['mail_changed'] = 'pà gina canviada:'; @@ -192,7 +192,7 @@ $lang['i_superuser'] = 'Super-usuari'; $lang['i_problems'] = 'L\'instalador ha trobat els problemes mostrats més avall. No pot continuar fins que no els arregle.'; $lang['i_modified'] = 'Per raons de seguritat, este procés només funcionarà en una instalació nova i verge de DokuWiki. Deuria tornar a extraure els archius del paquet que ha descarregat o consultar les -<a href="http://dokuwiki.org/install">instruccions d\'instalació de Dokuwiki</a> completes'; +<a href="https://www.dokuwiki.org/install">instruccions d\'instalació de Dokuwiki</a> completes'; $lang['i_funcna'] = 'La funció de PHP <code>%s</code> no està disponible. ¿Pot ser que el seu proveïdor d\'hostage l\'haja desactivada per algun motiu?'; $lang['i_phpver'] = 'La versió de PHP <code>%s</code> és menor que la <code>%s</code> que es necessita. Necessita actualitzar PHP.'; diff --git a/inc/lang/ca/lang.php b/inc/lang/ca/lang.php index 4f1dce218..50f69e632 100644 --- a/inc/lang/ca/lang.php +++ b/inc/lang/ca/lang.php @@ -219,7 +219,7 @@ $lang['created'] = 'creat'; $lang['restored'] = 's\'ha restaurat una versió anterior %s'; $lang['external_edit'] = 'edició externa'; $lang['summary'] = 'Resum d\'edició'; -$lang['noflash'] = 'Per a visualitzar aquest contingut necessiteu el <a href="http://www.adobe.com/products/flashplayer/">connector d\'Adobe Flash</a>.'; +$lang['noflash'] = 'Per a visualitzar aquest contingut necessiteu el <a href="http://get.adobe.com/flashplayer">connector d\'Adobe Flash</a>.'; $lang['download'] = 'Baixa el fragment'; $lang['tools'] = 'Eines'; $lang['user_tools'] = 'Eines de l\'usuari'; @@ -299,7 +299,7 @@ $lang['i_wikiname'] = 'Nom del wiki'; $lang['i_enableacl'] = 'Habilita ACL (recomanat)'; $lang['i_superuser'] = 'Superusuari'; $lang['i_problems'] = 'L\'instal·lador ha trobat alguns problemes, que s\'indiquen més avall. No podeu continuar fins que no els hà giu solucionat.'; -$lang['i_modified'] = 'Per raons de seguretat aquesta seqüència només funciona amb una instal·lació nova i no modificada de Dokuwiki. HaurÃeu de tornar a baixar el paquet i/o descomprimir-lo o consultar les <a href="http://dokuwiki.org/install">instruccions d\'instal·lació de Dokuwiki</a> completes'; +$lang['i_modified'] = 'Per raons de seguretat aquesta seqüència només funciona amb una instal·lació nova i no modificada de Dokuwiki. HaurÃeu de tornar a baixar el paquet i/o descomprimir-lo o consultar les <a href="https://www.dokuwiki.org/install">instruccions d\'instal·lació de Dokuwiki</a> completes'; $lang['i_funcna'] = 'La funció PHP <code>%s</code> no està disponible. Potser el vostre proveïdor de serveis l\'ha inhabilitada per alguna raó'; $lang['i_disabled'] = 'El vostre proveïdor l\'ha desactivat.'; $lang['i_phpver'] = 'La vostra versió de PHP <code>%s</code> és inferior a la requerida <code>%s</code>. Necessiteu actualitzar la vostra instal·lació de PHP.'; diff --git a/inc/lang/cs/lang.php b/inc/lang/cs/lang.php index faca38077..b7f0f1697 100644 --- a/inc/lang/cs/lang.php +++ b/inc/lang/cs/lang.php @@ -131,6 +131,7 @@ $lang['js']['media_done_btn'] = 'Hotovo'; $lang['js']['media_drop'] = 'Sem pÅ™etáhnÄ›te soubory pro nahrátÃ'; $lang['js']['media_cancel'] = 'odstranit'; $lang['js']['media_overwrt'] = 'PÅ™epsat existujÃcà soubory'; +$lang['js']['data_insecure'] = 'UPOZORNÄšNÃ: Zdá se, že váš datový adresář nenà správnÄ› zabezpeÄen. ProsÃm, pÅ™eÄtÄ›te si o <a href="https://www.dokuwiki.org/security#web_access_security">zabezpeÄenà pÅ™Ãstupu v DokuWiki</a>.'; $lang['search_exact_match'] = 'PÅ™esná shoda'; $lang['search_starts_with'] = 'ZaÄÃná s'; $lang['search_ends_with'] = 'KonÄà s'; @@ -233,7 +234,7 @@ $lang['created'] = 'vytvoÅ™eno'; $lang['restored'] = 'stará verze byla obnovena (%s)'; $lang['external_edit'] = 'upraveno mimo DokuWiki'; $lang['summary'] = 'Komentář k úpravám'; -$lang['noflash'] = 'Pro pÅ™ehránà obsahu potÅ™ebujete <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'Pro pÅ™ehránà obsahu potÅ™ebujete <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'Stáhnout snippet'; $lang['tools'] = 'Nástroje'; $lang['user_tools'] = 'Uživatelské nástroje'; @@ -313,7 +314,7 @@ $lang['i_wikiname'] = 'Název wiki'; $lang['i_enableacl'] = 'Zapnout ACL (doporuÄeno)'; $lang['i_superuser'] = 'Správce'; $lang['i_problems'] = 'Instalátor narazil na nÞe popsané problémy. Nelze pokraÄovat v instalaci, dokud je neopravÃte.'; -$lang['i_modified'] = 'Instalátor bude z bezpeÄnostnÃch důvodů pracovat pouze s Äistou a jeÅ¡tÄ› neupravenou instalacà DokuWiki. BuÄ znovu rozbalte soubory z instalaÄnÃho balÃÄku, nebo zkuste prostudovat <a href="http://dokuwiki.org/install">instrukce pro instalaci DokuWiki</a>.'; +$lang['i_modified'] = 'Instalátor bude z bezpeÄnostnÃch důvodů pracovat pouze s Äistou a jeÅ¡tÄ› neupravenou instalacà DokuWiki. BuÄ znovu rozbalte soubory z instalaÄnÃho balÃÄku, nebo zkuste prostudovat <a href="https://www.dokuwiki.org/install">instrukce pro instalaci DokuWiki</a>.'; $lang['i_funcna'] = 'PHP funkce <code>%s</code> nenà dostupná. Váš webhosting ji možná z nÄ›jakého důvodu vypnul.'; $lang['i_disabled'] = 'Bylo zakázáno vaÅ¡Ãm poskytovatelem.'; $lang['i_funcnmail'] = '<b>Poznámka:</b> Funkce mail() nenà v PHP dostupná. %s Pokud tento problém pÅ™etrvává, zkuste nainstalovat <a href="https://www.dokuwiki.org/plugin:smtp">smtp plugin</a>.'; diff --git a/inc/lang/cy/lang.php b/inc/lang/cy/lang.php index de407f804..7cdfe2bcc 100644 --- a/inc/lang/cy/lang.php +++ b/inc/lang/cy/lang.php @@ -209,7 +209,7 @@ $lang['created'] = 'crewyd'; $lang['restored'] = 'adferwyd hen adolygiad (%s)'; $lang['external_edit'] = 'golygiad allanol'; $lang['summary'] = 'Crynodeb golygiad'; -$lang['noflash'] = 'Mae angen <a href="http://www.adobe.com/products/flashplayer/">Ategyn Adobe Flash</a> i ddangos y cynnwys hwn.'; +$lang['noflash'] = 'Mae angen <a href="http://get.adobe.com/flashplayer">Ategyn Adobe Flash</a> i ddangos y cynnwys hwn.'; $lang['download'] = 'Lawrlwytho Darn'; $lang['tools'] = 'Teclynnau'; $lang['user_tools'] = 'Teclynnau Defnyddiwr'; @@ -302,7 +302,7 @@ $lang['i_superuser'] = 'Uwchddefnyddiwr'; $lang['i_problems'] = 'Gwnaeth yr arsefydlwr ddod o hyd i broblemau, isod. \'Sdim modd parhau nes i chi eu datrys nhw.'; $lang['i_modified'] = 'Oherwydd rhesymau diogelwch, bydd y sgript hwn dim ond yn gweithio gydag arsefydliad DokuWiki newydd sydd heb ei newid. Dylech chi naill ai ail-echdynnu\'r ffeiliau o\'r pecyn a lawrlwythwyd neu porwch dros y - <a href="http://dokuwiki.org/install">canllawiau arsefydylu Dokuwiki</a> cyfan'; + <a href="https://www.dokuwiki.org/install">canllawiau arsefydylu Dokuwiki</a> cyfan'; $lang['i_funcna'] = 'Swyddogaeth PHP <code>%s</code> ddim ar gael. Posib bod eich gwesteiwr wedi\'i hanalluogi am ryw reswm?'; $lang['i_phpver'] = 'Mae\'ch fersiwn PHP <code>%s</code> yn is na\'r hyn sydd ei angen <code>%s</code>. Mae angen i chi ddiweddaru eich arsefydliad PHP.'; $lang['i_mbfuncoverload'] = 'Mae\'n rhaid analluogi mbstring.func_overload mewn php.ini er mwyn rhedeg DokuWiki.'; diff --git a/inc/lang/da/lang.php b/inc/lang/da/lang.php index 03c367c35..5ab8f999a 100644 --- a/inc/lang/da/lang.php +++ b/inc/lang/da/lang.php @@ -227,7 +227,7 @@ $lang['created'] = 'oprettet'; $lang['restored'] = 'gammel revision gendannet (%s)'; $lang['external_edit'] = 'ekstern redigering'; $lang['summary'] = 'Resumé af ændrigner'; -$lang['noflash'] = 'Du skal installere <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Player</a> for at kunne se dette indhold.'; +$lang['noflash'] = 'Du skal installere <a href="http://get.adobe.com/flashplayer">Adobe Flash Player</a> for at kunne se dette indhold.'; $lang['download'] = 'Hent kodestykke'; $lang['tools'] = 'Værktøjer'; $lang['user_tools'] = 'Brugerværktøjer'; @@ -309,10 +309,10 @@ $lang['i_superuser'] = 'Superbruger'; $lang['i_problems'] = 'Installeren fandt nogle problemer, vist nedenunder. Du kan ikke fortsætte før du har rettet dem.'; $lang['i_modified'] = 'Af sikkerheds hensyn vil dette script kun virke pÃ¥ en ny og umodificeret Dokuwiki installation. Du burde enten gen-udpakke filerne fra den hentede pakke eller tjekke den fuldstændige -<a href="http://dokuwiki.org/install">DokuWiki installations instruktioner</a>'; +<a href="https://www.dokuwiki.org/install">DokuWiki installations instruktioner</a>'; $lang['i_funcna'] = 'PHP funtionen <code>%s</code> er ikke tilgængelig. MÃ¥ske har din udbyder slÃ¥et det fra af en eller anden grund?'; $lang['i_disabled'] = 'Det er blevet slÃ¥et fra af din udbyder.'; -$lang['i_funcnmail'] = '<b>Bemærk:</b> PHP mail funktionen er ikke tilgængelig. %s Hvis den forbliver utilgængelig, kan du installere <a href="http://dokuwiki.org/plugins/smtp">SMTP udvidelsen</a>.'; +$lang['i_funcnmail'] = '<b>Bemærk:</b> PHP mail funktionen er ikke tilgængelig. %s Hvis den forbliver utilgængelig, kan du installere <a href="https://www.dokuwiki.org/plugin:smtp">SMTP udvidelsen</a>.'; $lang['i_phpver'] = 'Din PHP version <code>%s</code> er mindre en den nødvendige <code>%s</code>. Du er nød til at opgradere din PHP installation.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload skal være deaktiveret i php.ini for at køre DokuWiki.'; $lang['i_urandom'] = 'DokuWiki kan ikke oprette kryptografisk sikre numre til cookies. Du bør mÃ¥ske kontrollere dine open_basedir indstillinger i php.ini for korrekt <code>/dev/urandom</code> adgang.'; diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php index 3ce1f222a..261dc8c8b 100644 --- a/inc/lang/de-informal/lang.php +++ b/inc/lang/de-informal/lang.php @@ -234,7 +234,7 @@ $lang['created'] = 'angelegt'; $lang['restored'] = 'alte Version wiederhergestellt (%s)'; $lang['external_edit'] = 'Externe Bearbeitung'; $lang['summary'] = 'Zusammenfassung'; -$lang['noflash'] = 'Das <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> wird benötigt, um diesen Inhalt anzuzeigen.'; +$lang['noflash'] = 'Das <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> wird benötigt, um diesen Inhalt anzuzeigen.'; $lang['download'] = 'Schnipsel herunterladen'; $lang['tools'] = 'Werkzeuge'; $lang['user_tools'] = 'Benutzer-Werkzeuge'; @@ -314,7 +314,7 @@ $lang['i_wikiname'] = 'Wiki-Name'; $lang['i_enableacl'] = 'Zugriffskontrolle (ACL) aktivieren (empfohlen)'; $lang['i_superuser'] = 'Benutzername des Administrators'; $lang['i_problems'] = 'Das Installationsprogramm hat unten aufgeführte Probleme festgestellt, die zunächst behoben werden müssen, bevor du mit der Installation fortfahren kannst.'; -$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Skript nur mit einer neuen bzw. nicht modifizierten DokuWiki-Installation. Du solltest entweder alle Dateien noch einmal frisch installieren oder die <a href="http://dokuwiki.org/install">Dokuwiki-Installationsanleitung</a> konsultieren.'; +$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Skript nur mit einer neuen bzw. nicht modifizierten DokuWiki-Installation. Du solltest entweder alle Dateien noch einmal frisch installieren oder die <a href="https://www.dokuwiki.org/install">Dokuwiki-Installationsanleitung</a> konsultieren.'; $lang['i_funcna'] = 'Die PHP-Funktion <code>%s</code> ist nicht verfügbar. Unter Umständen wurde sie von deinem Hoster deaktiviert?'; $lang['i_disabled'] = 'Es wurde von deinem Provider deaktiviert.'; $lang['i_funcnmail'] = '<b>Hinweis:</b> Die PHP-Funktion "mail()" ist nicht verfügbar. %s Alternativ kansnt du das <a href="https://www.dokuwiki.org/plugin:smtp">SMTP-Plugin</a> installieren.'; diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php index 07fbb3b8f..88ca018b8 100644 --- a/inc/lang/de/lang.php +++ b/inc/lang/de/lang.php @@ -252,7 +252,7 @@ $lang['created'] = 'angelegt'; $lang['restored'] = 'alte Version wiederhergestellt (%s)'; $lang['external_edit'] = 'Externe Bearbeitung'; $lang['summary'] = 'Zusammenfassung'; -$lang['noflash'] = 'Das <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> wird benötigt, um diesen Inhalt anzuzeigen.'; +$lang['noflash'] = 'Das <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> wird benötigt, um diesen Inhalt anzuzeigen.'; $lang['download'] = 'Schnipsel herunterladen'; $lang['tools'] = 'Werkzeuge'; $lang['user_tools'] = 'Benutzer-Werkzeuge'; @@ -332,7 +332,7 @@ $lang['i_wikiname'] = 'Wiki-Name'; $lang['i_enableacl'] = 'Zugangskontrolle (ACL) aktivieren (empfohlen)'; $lang['i_superuser'] = 'Benutzername des Administrators'; $lang['i_problems'] = 'Das Installationsprogramm hat unten aufgeführte Probleme festgestellt, die zunächst behoben werden müssen bevor Sie mit der Installation fortfahren können.'; -$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Skript nur mit einer neuen bzw. nicht modifizierten DokuWiki Installation. Sie sollten entweder alle Dateien noch einmal frisch installieren oder die <a href="http://dokuwiki.org/install">Dokuwiki-Installationsanleitung</a> konsultieren.'; +$lang['i_modified'] = 'Aus Sicherheitsgründen arbeitet dieses Skript nur mit einer neuen bzw. nicht modifizierten DokuWiki Installation. Sie sollten entweder alle Dateien noch einmal frisch installieren oder die <a href="https://www.dokuwiki.org/install">Dokuwiki-Installationsanleitung</a> konsultieren.'; $lang['i_funcna'] = 'Die PHP-Funktion <code>%s</code> ist nicht verfügbar. Unter Umständen wurde sie von Ihrem Hoster deaktiviert?'; $lang['i_disabled'] = 'Es wurde von Ihrem Provider deaktiviert.'; $lang['i_funcnmail'] = '<b>Hinweis:</b> Die PHP-Funktion "mail()" ist nicht verfügbar. %s Alternativ können Sie das <a href="https://www.dokuwiki.org/plugin:smtp">SMTP-Plugin</a> installieren.'; diff --git a/inc/lang/el/lang.php b/inc/lang/el/lang.php index 1a7b29b95..c2abc03d3 100644 --- a/inc/lang/el/lang.php +++ b/inc/lang/el/lang.php @@ -222,7 +222,7 @@ $lang['created'] = 'δημιουÏγήθηκε'; $lang['restored'] = 'παλαιότεÏη Îκδοση επαναφÎÏθηκε (%s)'; $lang['external_edit'] = 'εξωτεÏική Ï„Ïοποποίηση'; $lang['summary'] = 'ΕπεξεÏγασία σÏνοψης'; -$lang['noflash'] = 'Το <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> απαιτείται για την Ï€Ïοβολή Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… στοιχείου.'; +$lang['noflash'] = 'Το <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> απαιτείται για την Ï€Ïοβολή Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… στοιχείου.'; $lang['download'] = 'Λήψη Κώδικα'; $lang['tools'] = 'ΕÏγαλεία'; $lang['user_tools'] = 'ΕÏγαλεία ΧÏήστη'; diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 9e56d6f84..860711d5d 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -226,6 +226,7 @@ $lang['created'] = 'created'; $lang['restored'] = 'old revision restored (%s)'; $lang['external_edit'] = 'external edit'; $lang['summary'] = 'Edit summary'; +$lang['unknowndate'] = 'Unknown date'; $lang['noflash'] = 'The <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> is needed to display this content.'; $lang['download'] = 'Download Snippet'; $lang['tools'] = 'Tools'; diff --git a/inc/lang/eo/lang.php b/inc/lang/eo/lang.php index 4b67e00fd..81cc5c8ec 100644 --- a/inc/lang/eo/lang.php +++ b/inc/lang/eo/lang.php @@ -214,7 +214,7 @@ $lang['created'] = 'kreita'; $lang['restored'] = 'malnova revizio restarigita (%s)'; $lang['external_edit'] = 'ekstera redakto'; $lang['summary'] = 'Bulteno de ÅanÄoj'; -$lang['noflash'] = 'La <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> necesas por montri tiun ĉi enhavon.'; +$lang['noflash'] = 'La <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> necesas por montri tiun ĉi enhavon.'; $lang['download'] = 'ElÅuti eltiraĵon'; $lang['tools'] = 'Iloj'; $lang['user_tools'] = 'Uzantaj iloj'; diff --git a/inc/lang/es/lang.php b/inc/lang/es/lang.php index f157fd5af..d2a0cc324 100644 --- a/inc/lang/es/lang.php +++ b/inc/lang/es/lang.php @@ -256,7 +256,7 @@ $lang['created'] = 'creado'; $lang['restored'] = 'se ha restaurado la vieja versión (%s)'; $lang['external_edit'] = 'editor externo'; $lang['summary'] = 'Resumen de la edición'; -$lang['noflash'] = 'Para mostrar este contenido es necesario el <a href="http://www.adobe.com/products/flashplayer/">Plugin Adobe Flash</a>.'; +$lang['noflash'] = 'Para mostrar este contenido es necesario el <a href="http://get.adobe.com/flashplayer">Plugin Adobe Flash</a>.'; $lang['download'] = 'Descargar trozo de código fuente'; $lang['tools'] = 'Herramientas'; $lang['user_tools'] = 'Herramientas de usuario'; @@ -336,10 +336,10 @@ $lang['i_wikiname'] = 'Nombre del wiki'; $lang['i_enableacl'] = 'Habilitar ACL (recomendado) (ACL: lista de control de acceso)'; $lang['i_superuser'] = 'Super-usuario'; $lang['i_problems'] = 'El instalador encontró algunos problemas, se muestran abajo. No se puede continuar la instalación hasta que usted no los corrija.'; -$lang['i_modified'] = 'Por razones de seguridad este script sólo funcionará con una instalación nueva y no modificada de Dokuwiki. Usted debe extraer nuevamente los ficheros del paquete bajado, o bien consultar las <a href="http://dokuwiki.org/install">instrucciones de instalación de Dokuwiki</a> completas.'; +$lang['i_modified'] = 'Por razones de seguridad este script sólo funcionará con una instalación nueva y no modificada de Dokuwiki. Usted debe extraer nuevamente los ficheros del paquete bajado, o bien consultar las <a href="https://www.dokuwiki.org/install">instrucciones de instalación de Dokuwiki</a> completas.'; $lang['i_funcna'] = 'La función de PHP <code>%s</code> no está disponible. ¿Tal vez su proveedor de hosting la ha deshabilitado por alguna razón?'; $lang['i_disabled'] = 'Ha sido deshabilitado por su proveedor.'; -$lang['i_funcnmail'] = '<b>Nota:</b> La función de PHP mail() no está disponible. %s si no está disponible, puede instalar el <a href="http://dokuwiki.org/plugins/smtp">complemento smtp</a>.'; +$lang['i_funcnmail'] = '<b>Nota:</b> La función de PHP mail() no está disponible. %s si no está disponible, puede instalar el <a href="https://www.dokuwiki.org/plugin:smtp">complemento smtp</a>.'; $lang['i_phpver'] = 'Su versión de PHP <code>%s</code> es menor que la necesaria <code>%s</code>. Es necesario que actualice su instalación de PHP.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload se debe deshabilitar en php.ini para que funcione DokuWiki.'; $lang['i_urandom'] = 'DokuWiki no puede crear números criptográficamente seguros para las cookies. Es posible que desee verificar la configuración de open_basedir en php.ini para obtener el acceso apropiado a <code>/dev/urandom</code>.'; diff --git a/inc/lang/et/lang.php b/inc/lang/et/lang.php index 0320812c9..0556f6254 100644 --- a/inc/lang/et/lang.php +++ b/inc/lang/et/lang.php @@ -195,7 +195,7 @@ $lang['created'] = 'tekitatud'; $lang['restored'] = 'vana versioon taastatud (%s)'; $lang['external_edit'] = 'väline muutmine'; $lang['summary'] = 'kokkuvõte muudatustest'; -$lang['noflash'] = 'Sele sisu vaatamisesks on vajalik <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Laiendus</a>.'; +$lang['noflash'] = 'Sele sisu vaatamisesks on vajalik <a href="http://get.adobe.com/flashplayer">Adobe Flash Laiendus</a>.'; $lang['tools'] = 'Tööriistad'; $lang['user_tools'] = 'Kasutaja tarvikud'; $lang['site_tools'] = 'Lehe tööriistad'; @@ -276,7 +276,7 @@ $lang['i_enableacl'] = 'Kas lubada kasutajate haldus (soovitatav)'; $lang['i_superuser'] = 'Superkasutaja'; $lang['i_problems'] = 'Paigaldaja leidis mõned vead, mis on allpool välja toodud. Enne vigade eemaldamist ei saa jätkata.'; $lang['i_modified'] = 'Õnnetuste vältimiseks läheb see skript käima ainult värskelt paigaldatud ja muutmata Dokuwiki peal. - Sa peaksid ilmselt kogu koodi uuesti lahti pakkima. Vaata ka <a href="http://dokuwiki.org/install">Dokuwiki installeerimis juhendit</a>'; + Sa peaksid ilmselt kogu koodi uuesti lahti pakkima. Vaata ka <a href="https://www.dokuwiki.org/install">Dokuwiki installeerimis juhendit</a>'; $lang['i_funcna'] = 'PHP funktsiooni <code>%s</code> ei ole olemas.võibolla sinu serveri hooldaja on selle mingil põhjusel keelanud?'; $lang['i_phpver'] = 'Sinu PHP versioon <code>%s</code> on vanem nõutavast <code>%s</code>. Pead oma paigaldatud PHP-d uuendama.'; $lang['i_permfail'] = 'Dokuwiki ei saa kirjutada faili <code>%s</code>. Kontrolli serveris failide õigused üle.'; diff --git a/inc/lang/eu/lang.php b/inc/lang/eu/lang.php index 4e074f0e7..ef6fd6e47 100644 --- a/inc/lang/eu/lang.php +++ b/inc/lang/eu/lang.php @@ -199,7 +199,7 @@ $lang['created'] = 'sortua'; $lang['restored'] = 'bertsio zaharra berrezarria (%s)'; $lang['external_edit'] = 'kanpoko aldaketa'; $lang['summary'] = 'Aldatu laburpena'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> beharrezkoa da eduki hau bistaratzeko.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> beharrezkoa da eduki hau bistaratzeko.'; $lang['download'] = 'Deskarga Snippet-a'; $lang['tools'] = 'Tresnak'; $lang['user_tools'] = 'Erabiltzaile Tresnak'; @@ -279,7 +279,7 @@ $lang['i_wikiname'] = 'Wiki Izena'; $lang['i_enableacl'] = 'Gaitu ACL (gomendatua) (ACL: Atzipen Kontrol Lista)'; $lang['i_superuser'] = 'Supererabiltzailea'; $lang['i_problems'] = 'Instalatzaileak arazo batzuk aurkitu ditu, behean azalduak. Ezin duzu horiek konpondu arte jarraitu.'; -$lang['i_modified'] = 'Segurtasun arrazoiengatik, script hau DokuWikiren instalazio berri eta aldatu gabeko batekin bakarrik dabil. Deskargatutako paketetik fitxategiak berriz atera edo <a href="http://dokuwiki.org/install">DokuWikiren instalazio azalpenak</a> osorik irakurri beharko zenituzke.'; +$lang['i_modified'] = 'Segurtasun arrazoiengatik, script hau DokuWikiren instalazio berri eta aldatu gabeko batekin bakarrik dabil. Deskargatutako paketetik fitxategiak berriz atera edo <a href="https://www.dokuwiki.org/install">DokuWikiren instalazio azalpenak</a> osorik irakurri beharko zenituzke.'; $lang['i_funcna'] = 'PHP <code>%s</code> funtzioa ez dago erabilgarri. Agian zure hosting hornitzaileak arrazoiren batengatik ezgaituko zuen?'; $lang['i_phpver'] = 'Zure PHP <code>%s</code> bertsioa behar den <code>%s</code> bertsioa baino zaharragoa da. PHP instalazioa eguneratu beharra daukazu.'; $lang['i_permfail'] = 'DokuWiki ez da <code>%s</code> idazteko gai. Direktorio honen baimenen konfigurazioa konpondu behar duzu!'; diff --git a/inc/lang/fa/draft.txt b/inc/lang/fa/draft.txt index 5653da01d..51898532b 100644 --- a/inc/lang/fa/draft.txt +++ b/inc/lang/fa/draft.txt @@ -1,5 +1,5 @@ ====== ÙØ§ÛŒÙ„ چرک‌نویس ÛŒØ§ÙØª شد ====== -آخرین سشن ویرایش شما با موÙقیت به پایان نرسیده. دوکوویکی به طور خودکار چرک‌نویسی از ØµÙØÙ‡â€ŒÛŒ شما ذخیره می‌کند Ú©Ù‡ شما می‌توانید آن را کامل کنید. در زیر مقادیر موجود در چرک‌نویس را مشاهده می‌کنید. +آخرین ویرایش شما با موÙقیت به پایان نرسیده. دوکوویکی به طور خودکار چرک‌نویسی از ØµÙØÙ‡â€ŒÛŒ شما ذخیره می‌کند Ú©Ù‡ شما می‌توانید آن را کامل کنید. در زیر مقادیر موجود در چرک‌نویس را مشاهده می‌کنید. خواهشمندیم تصمیم بگیرید Ú©Ù‡ می‌خواهید چرک‌نویس را //بازیابی//ØŒ یا آن را //ØØ°Ù// کنید Ùˆ یا ویرایش را //لغو// نمایید. diff --git a/inc/lang/fa/lang.php b/inc/lang/fa/lang.php index 8e432ab06..bfe426518 100644 --- a/inc/lang/fa/lang.php +++ b/inc/lang/fa/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Faramarz Karamizadeh <f.karamizadeh@yahoo.com> * @author علیرضا ایوز <info@alirezaivaz.ir> * @author Masoud Sadrnezhaad <masoud@sadrnezhaad.ir> * @author behrad eslamifar <behrad_es@yahoo.com) @@ -124,6 +125,7 @@ $lang['js']['media_done_btn'] = 'انجام شد'; $lang['js']['media_drop'] = 'ÙØ§ÛŒÙ„‌ها را در اینجا قرار دهید تا آپلود شود'; $lang['js']['media_cancel'] = 'ØØ°Ù'; $lang['js']['media_overwrt'] = 'جاینوشت ÙØ§ÛŒÙ„‌های موجود'; +$lang['js']['data_insecure'] = 'هشدار: به نظر Ù…ÛŒ رسد Ùهرست اطلاعات شما به درستی ایمن نشده است. Ù„Ø·ÙØ§Ù‹ درباره <a href="https://www.dokuwiki.org/security#web_access_security">Web Access Security in DokuWiki</a> بخوانید.'; $lang['search_exact_match'] = 'دقیقا برابر'; $lang['search_starts_with'] = 'شروع بشود با'; $lang['search_ends_with'] = 'پایان یابد با'; @@ -172,6 +174,7 @@ $lang['txt_upload'] = 'ÙØ§ÛŒÙ„ را برای آپلود انتخاب $lang['txt_filename'] = 'ارسال به صورت (اختیاری):'; $lang['txt_overwrt'] = 'بر روی ÙØ§ÛŒÙ„ موجود بنویس'; $lang['maxuploadsize'] = 'ØØ¯Ø§Ú©Ø«Ø± %s برای هر ÙØ§ÛŒÙ„ مجاز است.'; +$lang['allowedmime'] = 'لیست پسوندهای مجاز ÙØ§ÛŒÙ„'; $lang['lockedby'] = 'در ØØ§Ù„ ØØ§Ø¶Ø± Ù‚ÙÙ„ شده است:'; $lang['lockexpire'] = 'Ù‚ÙÙ„ منقضی می‌شود در:'; $lang['rssfailed'] = 'بروز خطا در هنگام واکشی این Ùید:'; @@ -225,7 +228,7 @@ $lang['created'] = 'ایجاد شد'; $lang['restored'] = 'یک نگارش پیشین واگردانی شد. (%s)'; $lang['external_edit'] = 'ویرایش خارجی'; $lang['summary'] = 'پیش‌نمایش'; -$lang['noflash'] = 'برای نمایش Ù…ØØªÙˆÛŒØ§Øª <a href="http://www.adobe.com/products/flashplayer/">Ø§ÙØ²ÙˆÙ†Ù‡â€ŒÛŒ Ùلش</a> مورد نیاز است.'; +$lang['noflash'] = 'برای نمایش Ù…ØØªÙˆÛŒØ§Øª <a href="http://get.adobe.com/flashplayer">Ø§ÙØ²ÙˆÙ†Ù‡â€ŒÛŒ Ùلش</a> مورد نیاز است.'; $lang['download'] = 'Ø¯ÛŒØ§ÙØª ÙØ§ÛŒÙ„ منقطع گردید'; $lang['tools'] = 'ابزار'; $lang['user_tools'] = 'ابزار کاربر'; @@ -305,8 +308,10 @@ $lang['i_wikiname'] = 'نام ویکی'; $lang['i_enableacl'] = 'ÙØ¹Ø§Ù„ بودن کنترل دسترسی‌ها (توصیه شده)'; $lang['i_superuser'] = 'کاربر اصلی'; $lang['i_problems'] = 'نصب کننده با مشکلات زیر مواجه شد. در صورت Ø±ÙØ¹ این مشکلات، امکان ادامه نصب خواهد بود.'; -$lang['i_modified'] = 'به دلایل امنیتی، این اسکریپت Ùقط با نصب تازه Ùˆ بدون تغییر دوکوویکی کار خواهد کرد. شما باید دوباره ÙØ§ÛŒÙ„ ÙØ´Ø±Ø¯Ù‡ را باز کنید <a href="http://dokuwiki.org/install">راهنمای نصب DokuWiki</a> را بررسی کنید.'; +$lang['i_modified'] = 'به دلایل امنیتی، این اسکریپت Ùقط با نصب تازه Ùˆ بدون تغییر دوکوویکی کار خواهد کرد. شما باید دوباره ÙØ§ÛŒÙ„ ÙØ´Ø±Ø¯Ù‡ را باز کنید <a href="https://www.dokuwiki.org/install">راهنمای نصب DokuWiki</a> را بررسی کنید.'; $lang['i_funcna'] = 'تابع <code>%s</code> در پی‌اچ‌پی موجود نیست. ممکن است شرکت خدمات وب شما آن را مسدود کرده باشد.'; +$lang['i_disabled'] = 'توسط ارائه دهنده شما ØºÛŒØ±ÙØ¹Ø§Ù„ شده است.'; +$lang['i_funcnmail'] = '<b>توجه:</b> PHP mail function در دسترس نیست. %s اگر در دسترس نیست، می‌توانید Ø§ÙØ²ÙˆÙ†Ù‡ <a href="https://www.dokuwiki.org/plugin:smtp">smtp</a> را نصب کنید.'; $lang['i_phpver'] = 'نگارش پی‌اچ‌پی <code>%s</code> پایین‌تر از نگارش مورد نیاز، یعنی <code>%s</code> است. خواهشمندیم به روز رسانی کنید.'; $lang['i_mbfuncoverload'] = 'برای اجرای دوکوویکی باید mbstring.func_overload را در php.ini ØºÛŒØ±ÙØ¹Ø§Ù„ کنید.'; $lang['i_permfail'] = 'شاخه‌ی <code>%s</code> قابلیت نوشتن ندارد. شما باید دسترسی‌های این شاخه را تنظیم کنید!'; @@ -359,6 +364,7 @@ $lang['media_perm_upload'] = 'Ù…ØªØ§Ø³ÙØ§Ù†Ù‡ شما دسترسی‌های $lang['media_update'] = 'آپلود نسخه‌ی جدید'; $lang['media_restore'] = 'بازیابی این نسخه'; $lang['media_acl_warning'] = 'این لیست ممکن است به خاطر Ù…ØØ¯ÙˆØ¯ÛŒØªÙ‡Ø§ÛŒ دسترسیهای ACL Ùˆ ØµÙØØ§Øª پنهان کامل نباشد.'; +$lang['email_fail'] = 'PHP Mail() ÛŒØ§ÙØª نشد یا ØºÛŒØ±ÙØ¹Ø§Ù„ است. ایمیل زیر ارسال نشد:'; $lang['currentns'] = 'ÙØ¶Ø§ÛŒ نام جاری'; $lang['searchresult'] = 'نتیجه‌ی جستجو'; $lang['plainhtml'] = 'HTML ساده'; diff --git a/inc/lang/fa/onceexisted.txt b/inc/lang/fa/onceexisted.txt new file mode 100644 index 000000000..f81915d1b --- /dev/null +++ b/inc/lang/fa/onceexisted.txt @@ -0,0 +1,3 @@ +======= این ØµÙØÙ‡ دیگر وجود ندارد ====== + +شما پیوندی را به ØµÙØÙ‡ ای Ú©Ù‡ دیگر وجود ندارد دنبال کرده اید. می‌توانید Ùهرست [[?do=revisions|نسخه‌های قدیمی]] را بررسی کنید تا ببینید Ú†Ù‡ زمانی Ùˆ چرا ØØ°Ù شده است، به نسخه‌های قدیمی دسترسی داشته باشید یا آن را بازیابی کنید.
\ No newline at end of file diff --git a/inc/lang/fi/lang.php b/inc/lang/fi/lang.php index a872b156f..541311c49 100644 --- a/inc/lang/fi/lang.php +++ b/inc/lang/fi/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Pasi <zazuu@zazuu.net> * @author Tuomo Hartikainen <tuomo.hartikainen@heksia.fi> * @author Petteri <petteri@gmail.com> * @author Matti Pöllä <mpo@iki.fi> @@ -72,6 +73,7 @@ $lang['badpassconfirm'] = 'Valitan. Salasana oli väärin'; $lang['minoredit'] = 'Pieni muutos'; $lang['draftdate'] = 'Luonnos tallennettu automaattisesti'; $lang['nosecedit'] = 'Sivu on muuttunut välillä ja kappaleen tiedot olivat vanhentuneet. Koko sivu ladattu.'; +$lang['searchcreatepage'] = 'Jos et löytänyt etsimääsi, voit luoda tai muokata sivua %s, joka on nimetty kyselysi mukaan.'; $lang['js']['willexpire'] = 'Lukituksesi tämän sivun muokkaukseen päättyy minuutin kuluttua.\nRistiriitojen välttämiseksi paina esikatselu-nappia nollataksesi lukitusajan.'; $lang['js']['notsavedyet'] = 'Dokumentissa on tallentamattomia muutoksia, jotka häviävät. Haluatko varmasti jatkaa?'; @@ -201,7 +203,7 @@ $lang['created'] = 'luotu'; $lang['restored'] = 'vanha versio palautettu (%s)'; $lang['external_edit'] = 'ulkoinen muokkaus'; $lang['summary'] = 'Yhteenveto muokkauksesta'; -$lang['noflash'] = 'Tarvitset <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash-liitännäisen</a> nähdäksesi tämän sisällön.'; +$lang['noflash'] = 'Tarvitset <a href="http://get.adobe.com/flashplayer">Adobe Flash-liitännäisen</a> nähdäksesi tämän sisällön.'; $lang['download'] = 'Lataa palanen'; $lang['tools'] = 'Työkalut'; $lang['user_tools'] = 'Käyttäjän työkalut'; @@ -281,7 +283,7 @@ $lang['i_wikiname'] = 'Wikin nimi'; $lang['i_enableacl'] = 'Käytä käyttöoikeuksien hallintaa (ACL) (Suositeltu)'; $lang['i_superuser'] = 'Pääkäyttäjä'; $lang['i_problems'] = 'Asennusohjelma löysi alla listattuja ongelmia ongelmia. Et voi jatkaa ennen kuin ne on korjattu.'; -$lang['i_modified'] = 'Turvallisuussyistä tämä ohjelma toimii vain uusien ja muokkaamattomien Dokuwiki-asennusten kanssa. Pura tiedostot uudestaan asennuspaketista, tai lue <a href="http://dokuwiki.org/install">Dokuwikin asennusohje (englanniksi)</a>'; +$lang['i_modified'] = 'Turvallisuussyistä tämä ohjelma toimii vain uusien ja muokkaamattomien Dokuwiki-asennusten kanssa. Pura tiedostot uudestaan asennuspaketista, tai lue <a href="https://www.dokuwiki.org/install">Dokuwikin asennusohje (englanniksi)</a>'; $lang['i_funcna'] = 'PHP:n funktio <code>%s</code> ei ole käytettävissä. Palveluntarjoajasi on saattanut poistaa sen jostain syystä.'; $lang['i_phpver'] = 'Käyttämäsi PHP-ohjelmiston versio <code>%s</code> on pienempi, kuin tarvitaan <code>%s</code>. PHP-asennuksesi pitää päivittää.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload pitää ottaa pois käytöstä php.ini -tiedostosta käyttääksesi DokuWikiä'; diff --git a/inc/lang/fr/lang.php b/inc/lang/fr/lang.php index 9b3ab9b48..e9f5d8e3f 100644 --- a/inc/lang/fr/lang.php +++ b/inc/lang/fr/lang.php @@ -194,7 +194,7 @@ $lang['licenseok'] = 'Note : En modifiant cette page, vous acceptez $lang['searchmedia'] = 'Chercher le nom de fichier :'; $lang['searchmedia_in'] = 'Chercher dans %s'; $lang['txt_upload'] = 'Sélectionnez un fichier à envoyer :'; -$lang['txt_filename'] = 'Envoyer en tant que (optionnel):'; +$lang['txt_filename'] = 'Envoyer en tant que (optionnel) :'; $lang['txt_overwrt'] = 'Écraser le fichier cible (s\'il existe)'; $lang['maxuploadsize'] = 'Taille d\'envoi maximale : %s par fichier'; $lang['allowedmime'] = 'Liste des extensions de fichier autorisées'; @@ -222,7 +222,7 @@ $lang['mediaview'] = 'Afficher le fichier original'; $lang['mediaroot'] = 'racine'; $lang['mediaupload'] = 'Envoyez un fichier dans la catégorie actuelle. Pour créer des sous-catégories, préfixez en le nom du fichier séparées par un double-point, après avoir choisis le(s) fichier(s). Le(s) fichier(s) peuvent également être envoyé(s) par glisser-déposer (drag & drop)'; $lang['mediaextchange'] = 'Extension du fichier modifiée de .%s en .%s !'; -$lang['reference'] = 'Utilisé par'; +$lang['reference'] = 'Utilisé sur'; $lang['ref_inuse'] = 'Le fichier ne peut être effacé car il est toujours utilisé par les pages suivantes :'; $lang['ref_hidden'] = 'Des références sont présentes dans des pages que vous ne pouvez pas voir (autorisations insuffisantes)'; $lang['hits'] = 'Occurrences trouvées'; @@ -242,16 +242,16 @@ $lang['difflastrev'] = 'Dernière révision'; $lang['diffbothprevrev'] = 'Les deux révisions précédentes'; $lang['diffbothnextrev'] = 'Les deux révisions suivantes'; $lang['line'] = 'Ligne'; -$lang['breadcrumb'] = 'Piste:'; -$lang['youarehere'] = 'Vous êtes ici:'; -$lang['lastmod'] = 'Dernière modification:'; +$lang['breadcrumb'] = 'Piste :'; +$lang['youarehere'] = 'Vous êtes ici :'; +$lang['lastmod'] = 'Dernière modification :'; $lang['by'] = 'de'; $lang['deleted'] = 'supprimée'; $lang['created'] = 'créée'; $lang['restored'] = 'ancienne révision (%s) restaurée'; $lang['external_edit'] = 'modification externe'; $lang['summary'] = 'Résumé'; -$lang['noflash'] = 'L\'<a href="http://www.adobe.com/products/flashplayer/">extension Adobe Flash</a> est nécessaire pour afficher ce contenu.'; +$lang['noflash'] = 'L\'<a href="http://get.adobe.com/flashplayer">extension Adobe Flash</a> est nécessaire pour afficher ce contenu.'; $lang['download'] = 'Télécharger cet extrait'; $lang['tools'] = 'Outils'; $lang['user_tools'] = 'Outils pour utilisateurs'; @@ -296,11 +296,11 @@ $lang['upperns'] = 'Aller à la catégorie parente'; $lang['metaedit'] = 'Modifier les métadonnées'; $lang['metasaveerr'] = 'Erreur lors de l\'enregistrement des métadonnées'; $lang['metasaveok'] = 'Métadonnées enregistrées'; -$lang['img_title'] = 'Titre:'; -$lang['img_caption'] = 'Légende:'; -$lang['img_date'] = 'Date:'; +$lang['img_title'] = 'Titre :'; +$lang['img_caption'] = 'Légende :'; +$lang['img_date'] = 'Date :'; $lang['img_fname'] = 'Nom de fichier :'; -$lang['img_fsize'] = 'Taille:'; +$lang['img_fsize'] = 'Taille :'; $lang['img_artist'] = 'Photographe :'; $lang['img_copyr'] = 'Copyright :'; $lang['img_format'] = 'Format :'; @@ -331,10 +331,10 @@ $lang['i_wikiname'] = 'Nom du wiki'; $lang['i_enableacl'] = 'Activer le contrôle d\'accès (recommandé)'; $lang['i_superuser'] = 'Super-utilisateur'; $lang['i_problems'] = 'L\'installateur a détecté les problèmes indiqués ci-dessous. Vous ne pouvez pas poursuivre l\'installation tant qu\'ils n\'auront pas été corrigés.'; -$lang['i_modified'] = 'Pour des raisons de sécurité, ce script ne fonctionne qu\'avec une installation neuve et non modifiée de DokuWiki. Vous devriez ré-extraire les fichiers depuis le paquet téléchargé ou consulter les <a href="http://dokuwiki.org/install">instructions d\'installation de DokuWiki</a>'; +$lang['i_modified'] = 'Pour des raisons de sécurité, ce script ne fonctionne qu\'avec une installation neuve et non modifiée de DokuWiki. Vous devriez ré-extraire les fichiers depuis le paquet téléchargé ou consulter les <a href="https://www.dokuwiki.org/install">instructions d\'installation de DokuWiki</a>'; $lang['i_funcna'] = 'La fonction PHP <code>%s</code> n\'est pas disponible. Peut-être que votre hébergeur web l\'a désactivée ?'; $lang['i_disabled'] = 'Elle a été désactivée par votre hébergeur'; -$lang['i_funcnmail'] = '<b>Note :</b> La fonction PHP mail n\'est pas disponible. %s Si vous ne pouvez pas l\'activer, vous pourriez installer le <a href="http://dokuwiki.org/plugins/smtp">greffon smtp</a>.'; +$lang['i_funcnmail'] = '<b>Note :</b> La fonction PHP mail n\'est pas disponible. %s Si vous ne pouvez pas l\'activer, vous pourriez installer le <a href="https://www.dokuwiki.org/plugin:smtp">greffon smtp</a>.'; $lang['i_phpver'] = 'Votre version de PHP (%s) est antérieure à la version requise (%s). Vous devez mettre à jour votre installation de PHP.'; $lang['i_mbfuncoverload'] = 'Il faut désactiver mbstring.func_overload dans php.ini pour DokuWiki'; $lang['i_urandom'] = 'DokuWiki ne peut créer de nombres cryptographiquement sûrs pour les cookies. Vous voudrez peut-être vérifier que le réglage open_basedir dans php.ini permet l\'accès à <code>/dev/urandom</code>.'; diff --git a/inc/lang/fr/register.txt b/inc/lang/fr/register.txt index df1d22eee..213664c00 100644 --- a/inc/lang/fr/register.txt +++ b/inc/lang/fr/register.txt @@ -1,3 +1,3 @@ ====== S'enregistrer comme nouvel utilisateur ====== -Remplissez toutes les informations ci-dessous pour vous créer un compte sur ce wiki. Assurez-vous de fournir une **adresse de courriel valide** - s'il ne vous est pas demandé de saisir un mot de passe ici, il vous sera expédié par courriel à cette adresse. Le nom d'utilisateur doit être un [[doku>fr:pagename|nom de page]] valide. +Remplissez toutes les informations ci-dessous pour vous créer un compte sur ce wiki. Assurez-vous de fournir une **adresse de courriel valide** - si vous n'avez pas à saisir un mot de passe ici, il vous sera expédié par courriel à cette adresse. Le nom d'utilisateur doit être un [[doku>fr:pagename|nom de page]] valide. diff --git a/inc/lang/gl/lang.php b/inc/lang/gl/lang.php index a83279e82..a88c0d779 100644 --- a/inc/lang/gl/lang.php +++ b/inc/lang/gl/lang.php @@ -182,7 +182,7 @@ $lang['created'] = 'creado'; $lang['restored'] = 'revisión antiga restaurada (%s)'; $lang['external_edit'] = 'edición externa'; $lang['summary'] = 'Resumo da edición'; -$lang['noflash'] = 'PrecÃsase o <a href="http://www.adobe.com/products/flashplayer/">Extensión Adobe Flash</a> para amosar este contido.'; +$lang['noflash'] = 'PrecÃsase o <a href="http://get.adobe.com/flashplayer">Extensión Adobe Flash</a> para amosar este contido.'; $lang['download'] = 'Descargar Retallo (Snippet)'; $lang['tools'] = 'Ferramentas'; $lang['user_tools'] = 'Ferramentas de usuario'; @@ -264,7 +264,7 @@ $lang['i_superuser'] = 'Super-usuario'; $lang['i_problems'] = 'O instalador atopou algúns problemas, que se amosan de seguido. Non poderás continuar até que os soluciones.'; $lang['i_modified'] = 'Por razóns de seguridade este script só funcionará cunha instalación nova e sen modificar do Dokuwiki. Podes ou ben extraer de novo os arquivos dende o paquete descargado ou consultar as - <a href="http://dokuwiki.org/install">instruccións completas de instalación do Dokuwiki</a>'; + <a href="https://www.dokuwiki.org/install">instruccións completas de instalación do Dokuwiki</a>'; $lang['i_funcna'] = 'A función <code>%s</code> do PHP non está dispoñÃbel. Pode que o teu provedor de hospedaxe a desactivase por algún motivo?'; $lang['i_phpver'] = 'A túa versión <code>%s</code> do PHP é inferior á <code>%s</code> precisa. Debes actualizar a túa instalación do PHP.'; $lang['i_permfail'] = '<code>%s</code> non é escribÃbel polo DokuWiki. Debes corrixir a configuración de permisos deste directorio!'; diff --git a/inc/lang/he/lang.php b/inc/lang/he/lang.php index 655bc5d80..95619e7e4 100644 --- a/inc/lang/he/lang.php +++ b/inc/lang/he/lang.php @@ -208,7 +208,7 @@ $lang['created'] = '× ×•×¦×¨'; $lang['restored'] = 'שוחזר (%s)'; $lang['external_edit'] = 'עריכה ×—×™×¦×•× ×™×ª'; $lang['summary'] = 'תקציר העריכה'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">תוסף פל×ש לדפדפן</a> × ×“×¨×© כדי להציג תוכן ×–×”.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">תוסף פל×ש לדפדפן</a> × ×“×¨×© כדי להציג תוכן ×–×”.'; $lang['download'] = 'הורדת מקטע'; $lang['tools'] = 'כלי×'; $lang['user_tools'] = '×›×œ×™× ×©×œ משתמש'; @@ -290,7 +290,7 @@ $lang['i_superuser'] = 'משתמש־על'; $lang['i_problems'] = '×ª×›× ×™×ª ×”×”×ª×§× ×” זיהתה מספר בעיות המפורטות להלן. ×ין ב×פשרותך להמשיך ×œ×¤× ×™ ×ª×™×§×•× ×Ÿ.'; $lang['i_modified'] = 'משיקולי ×בטחה סקריפט ×–×” יעבוד ×ך ורק ×¢× ×”×ª×§× ×ª DokuWiki חדשה ×©×œ× ×¢×‘×¨×” כל ×©×™× ×•×™. עליך לחלץ ×©× ×™×ª ×ת ×”×§×‘×¦×™× ×ž×”×—×‘×™×œ×” שהורדה ×ו להיעזר בדף - <a href="http://dokuwiki.org/install">Dokuwiki installation instructions</a>'; + <a href="https://www.dokuwiki.org/install">Dokuwiki installation instructions</a>'; $lang['i_funcna'] = '×¤×•× ×§×¦×™×™×ª ×”-PHP‏ <code>%s</code> ××™× ×” ×–×ž×™× ×”. יתכן ×›×™ מ×רח ×”×תר ×—×¡× ×ותה מסיבה כלשהי?'; $lang['i_phpver'] = 'גרסת PHP שלך <code>%s</code> × ×ž×•×›×” מ <code>%s</code> הצורך. ×תה צריך לשדרג PHP שלך להתקין.'; $lang['i_mbfuncoverload'] = 'יש לבטל ×ת mbstring.func_overload בphp.ini בכדי להריץ ×ת DokuWiki'; diff --git a/inc/lang/hr/lang.php b/inc/lang/hr/lang.php index 4fdc14782..7ea944cce 100644 --- a/inc/lang/hr/lang.php +++ b/inc/lang/hr/lang.php @@ -214,7 +214,7 @@ $lang['created'] = 'stvoreno'; $lang['restored'] = 'vraćeno na prijaÅ¡nju izmjenu (%s)'; $lang['external_edit'] = 'vanjsko ureÄ‘ivanje'; $lang['summary'] = 'Sažetak izmjena'; -$lang['noflash'] = 'Za prikazivanje ovog sadržaja potreban je <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>'; +$lang['noflash'] = 'Za prikazivanje ovog sadržaja potreban je <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>'; $lang['download'] = 'Preuzmi isjeÄak'; $lang['tools'] = 'Alati'; $lang['user_tools'] = 'KorisniÄki alati'; @@ -295,7 +295,7 @@ $lang['i_enableacl'] = 'Omogući ACL (preporuÄeno)'; $lang['i_superuser'] = 'Superkorisnik'; $lang['i_problems'] = 'Instalacija je pronaÅ¡la probleme koji su naznaÄeni ispod. Nije moguće nastaviti dok se ti problemi ne rijeÅ¡e.'; $lang['i_modified'] = 'Zbog sigurnosnih razlog, ova skripta raditi će samo sa novim i neizmijenjenim DokuWiki instalacijama. - Molimo ponovno prekopirajte datoteke iz preuzetoga paketa ili pogledajte detaljno <a href="http://dokuwiki.org/install">Uputstvo za postavljanje DokuWiki-a</a>'; + Molimo ponovno prekopirajte datoteke iz preuzetoga paketa ili pogledajte detaljno <a href="https://www.dokuwiki.org/install">Uputstvo za postavljanje DokuWiki-a</a>'; $lang['i_funcna'] = 'PHP funkcija <code>%s</code> nije dostupna. Možda ju je vaÅ¡ pružatelj hostinga onemogućio iz nekog razloga?'; $lang['i_phpver'] = 'VaÅ¡a PHP inaÄica <code>%s</code> je niža od potrebne <code>%s</code>. Trebate nadograditi vaÅ¡u PHP instalaciju.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload mora biti onemogućena u php.ini da bi ste pokrenuli DokuWiki.'; diff --git a/inc/lang/hu/lang.php b/inc/lang/hu/lang.php index e13c1ecd1..e3079e037 100644 --- a/inc/lang/hu/lang.php +++ b/inc/lang/hu/lang.php @@ -3,13 +3,13 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Hamp Gábor <gabor.hamp@gmail.com> + * @author Viktor Horváth <horvath.viktor@forrastrend.hu> * @author Ziegler Gábor <gziegler@freemail.hu> * @author Sandor TIHANYI <stihanyi+dw@gmail.com> * @author Siaynoq Mage <siaynoqmage@gmail.com> - * @author schilling.janos@gmail.com + * @author schilling.janos <schilling.janos@gmail.com> * @author Szabó Dávid <szabo.david@gyumolcstarhely.hu> - * @author Sándor TIHANYI <stihanyi+dw@gmail.com> - * @author David Szabo <szabo.david@gyumolcstarhely.hu> * @author Marton Sebok <sebokmarton@gmail.com> * @author Serenity87HUN <anikototh87@gmail.com> * @author Marina Vladi <deldadam@gmail.com> @@ -74,44 +74,7 @@ $lang['badpassconfirm'] = 'Hibás jelszó'; $lang['minoredit'] = 'Apróbb változások'; $lang['draftdate'] = 'Piszkozat elmentve:'; $lang['nosecedit'] = 'IdÅ‘közben megváltozott az oldal, emiatt a szakasz nem friss. Töltsd újra az egész oldalt!'; -$lang['regmissing'] = 'Sajnáljuk, az összes mezÅ‘t ki kell töltened.'; -$lang['reguexists'] = 'Sajnáljuk, ilyen azonosÃtójú felhasználónk már van.'; -$lang['regsuccess'] = 'A felhasználói azonosÃtót létrehoztuk. A jelszót postáztuk.'; -$lang['regsuccess2'] = 'A felhasználói azonosÃtót létrehoztuk.'; -$lang['regfail'] = 'A felhasználó létrehozása sikertelen.'; -$lang['regmailfail'] = 'Úgy tűnik hiba történt a jelszó postázása során. Kérjük lépj kapcsolatba az Adminisztrátorokkal!'; -$lang['regbadmail'] = 'A megadott e-mail cÃm érvénytelennek tűnik. Ha úgy gondolod ez hiba, lépj kapcsolatba az Adminisztrátorokkal!'; -$lang['regbadpass'] = 'A két megadott jelszó nem egyezik, próbáld újra!'; -$lang['regpwmail'] = 'A DokuWiki jelszavad'; -$lang['reghere'] = 'Még nincs azonosÃtód? Itt kérhetsz'; -$lang['profna'] = 'Ez a wiki nem támogatja a személyes beállÃtások módosÃtását.'; -$lang['profnochange'] = 'Nem történt változás.'; -$lang['profnoempty'] = 'A név és e-mail mezÅ‘ nem maradhat üresen!'; -$lang['profchanged'] = 'A személyes beállÃtások változtatása megtörtént.'; -$lang['profnodelete'] = 'Ez a wiki nem támogatja a felhasználói fiókok törlését'; -$lang['profdeleteuser'] = 'Felhasználói fiók törlése'; -$lang['profdeleted'] = 'Felhasználói fiókodat eltávolÃtottuk errÅ‘l a wiki-rÅ‘l.'; -$lang['profconfdelete'] = 'Szeretném eltávolÃtani a felhasználói fiókomat errÅ‘l a wikirÅ‘l. <br/> Ez a cselekvés nem visszavonható.'; -$lang['profconfdeletemissing'] = 'A megerÅ‘sÃtÅ‘ négyzet nincs bepipálva'; -$lang['proffail'] = 'A profil frissÃtése sikertelen.'; -$lang['pwdforget'] = 'Elfelejtetted a jelszavad? Itt kérhetsz újat'; -$lang['resendna'] = 'Ez a wiki nem támogatja a jelszó újraküldést.'; -$lang['resendpwd'] = 'Új jelszó beállÃtása a következÅ‘höz:'; -$lang['resendpwdmissing'] = 'Sajnáljuk, az összes mezÅ‘t ki kell töltened.'; -$lang['resendpwdnouser'] = 'Sajnáljuk, ilyen azonosÃtójú felhasználónk nem létezik.'; -$lang['resendpwdbadauth'] = 'Sajnáljuk, ez a megerÅ‘sÃtÅ‘ kód nem helyes. Biztos, hogy a teljes megerÅ‘sÃtÅ‘ linket pontosan beÃrtad?'; -$lang['resendpwdconfirm'] = 'A megerÅ‘sÃtÅ‘ linket e-mailben elküldtük.'; -$lang['resendpwdsuccess'] = 'Az új jelszavadat elküldtük e-mailben.'; -$lang['license'] = 'Hacsak máshol nincs egyéb rendelkezés, ezen wiki tartalma a következÅ‘ licenc alatt érhetÅ‘ el:'; -$lang['licenseok'] = 'Megjegyzés: az oldal szerkesztésével elfogadja, hogy a tartalom a következÅ‘ licenc alatt lesz elérhetÅ‘:'; -$lang['searchmedia'] = 'Keresett fájl neve:'; -$lang['searchmedia_in'] = 'Keresés a következÅ‘ben: %s'; -$lang['txt_upload'] = 'Válaszd ki a feltöltendÅ‘ fájlt:'; -$lang['txt_filename'] = 'Feltöltési név (elhagyható):'; -$lang['txt_overwrt'] = 'LétezÅ‘ fájl felülÃrása'; -$lang['maxuploadsize'] = 'Maximum %s méretű fájlokat tölthetsz fel.'; -$lang['lockedby'] = 'Jelenleg zárolta:'; -$lang['lockexpire'] = 'A zárolás lejár:'; +$lang['search_fullresults'] = 'Teljes szöveg'; $lang['js']['willexpire'] = 'Az oldalszerkesztési zárolásod körülbelül egy percen belül lejár.\nAz ütközések elkerülése végett használd az elÅ‘nézet gombot a zárolásod frissÃtéséhez.'; $lang['js']['notsavedyet'] = 'Elmentetlen változások vannak, amelyek el fognak veszni. Tényleg ezt akarod?'; @@ -154,6 +117,53 @@ $lang['js']['media_done_btn'] = 'Kész'; $lang['js']['media_drop'] = 'Húzd ide a fájlokat a feltöltéshez'; $lang['js']['media_cancel'] = 'eltávolÃtás'; $lang['js']['media_overwrt'] = 'MeglévÅ‘ fájlok felülÃrása'; +$lang['search_any_time'] = 'Bármikor'; +$lang['search_past_7_days'] = 'Elmúlt héten'; +$lang['search_past_month'] = 'Elmúlt hónapban'; +$lang['search_past_year'] = 'Az elmúlt évben'; +$lang['search_sort_by_mtime'] = 'Utolsó módosÃtás idÅ‘pontja szerint rendezve'; +$lang['search_exact_match'] = 'pontos egyezés'; +$lang['search_custom_match'] = 'egyéni'; +$lang['search_sort_by_hits'] = 'találatok szerinti rendezés'; +$lang['regmissing'] = 'Sajnáljuk, az összes mezÅ‘t ki kell töltened.'; +$lang['reguexists'] = 'Sajnáljuk, ilyen azonosÃtójú felhasználónk már van.'; +$lang['regsuccess'] = 'A felhasználói azonosÃtót létrehoztuk. A jelszót postáztuk.'; +$lang['regsuccess2'] = 'A felhasználói azonosÃtót létrehoztuk.'; +$lang['regfail'] = 'A felhasználó létrehozása sikertelen.'; +$lang['regmailfail'] = 'Úgy tűnik hiba történt a jelszó postázása során. Kérjük lépj kapcsolatba az Adminisztrátorokkal!'; +$lang['regbadmail'] = 'A megadott e-mail cÃm érvénytelennek tűnik. Ha úgy gondolod ez hiba, lépj kapcsolatba az Adminisztrátorokkal!'; +$lang['regbadpass'] = 'A két megadott jelszó nem egyezik, próbáld újra!'; +$lang['regpwmail'] = 'A DokuWiki jelszavad'; +$lang['reghere'] = 'Még nincs azonosÃtód? Itt kérhetsz'; +$lang['profna'] = 'Ez a wiki nem támogatja a személyes beállÃtások módosÃtását.'; +$lang['profnochange'] = 'Nem történt változás.'; +$lang['profnoempty'] = 'A név és e-mail mezÅ‘ nem maradhat üresen!'; +$lang['profchanged'] = 'A személyes beállÃtások változtatása megtörtént.'; +$lang['profnodelete'] = 'Ez a wiki nem támogatja a felhasználói fiókok törlését'; +$lang['profdeleteuser'] = 'Felhasználói fiók törlése'; +$lang['profdeleted'] = 'Felhasználói fiókodat eltávolÃtottuk errÅ‘l a wiki-rÅ‘l.'; +$lang['profconfdelete'] = 'Szeretném eltávolÃtani a felhasználói fiókomat errÅ‘l a wikirÅ‘l. <br/> Ez a cselekvés nem visszavonható.'; +$lang['profconfdeletemissing'] = 'A megerÅ‘sÃtÅ‘ négyzet nincs bepipálva'; +$lang['proffail'] = 'A profil frissÃtése sikertelen.'; +$lang['pwdforget'] = 'Elfelejtetted a jelszavad? Itt kérhetsz újat'; +$lang['resendna'] = 'Ez a wiki nem támogatja a jelszó újraküldést.'; +$lang['resendpwd'] = 'Új jelszó beállÃtása a következÅ‘höz:'; +$lang['resendpwdmissing'] = 'Sajnáljuk, az összes mezÅ‘t ki kell töltened.'; +$lang['resendpwdnouser'] = 'Sajnáljuk, ilyen azonosÃtójú felhasználónk nem létezik.'; +$lang['resendpwdbadauth'] = 'Sajnáljuk, ez a megerÅ‘sÃtÅ‘ kód nem helyes. Biztos, hogy a teljes megerÅ‘sÃtÅ‘ linket pontosan beÃrtad?'; +$lang['resendpwdconfirm'] = 'A megerÅ‘sÃtÅ‘ linket e-mailben elküldtük.'; +$lang['resendpwdsuccess'] = 'Az új jelszavadat elküldtük e-mailben.'; +$lang['license'] = 'Hacsak máshol nincs egyéb rendelkezés, ezen wiki tartalma a következÅ‘ licenc alatt érhetÅ‘ el:'; +$lang['licenseok'] = 'Megjegyzés: az oldal szerkesztésével elfogadja, hogy a tartalom a következÅ‘ licenc alatt lesz elérhetÅ‘:'; +$lang['searchmedia'] = 'Keresett fájl neve:'; +$lang['searchmedia_in'] = 'Keresés a következÅ‘ben: %s'; +$lang['txt_upload'] = 'Válaszd ki a feltöltendÅ‘ fájlt:'; +$lang['txt_filename'] = 'Feltöltési név (elhagyható):'; +$lang['txt_overwrt'] = 'LétezÅ‘ fájl felülÃrása'; +$lang['maxuploadsize'] = 'Maximum %s méretű fájlokat tölthetsz fel.'; +$lang['allowedmime'] = 'A megengedett fájlkiterjesztések listája'; +$lang['lockedby'] = 'Jelenleg zárolta:'; +$lang['lockexpire'] = 'A zárolás lejár:'; $lang['rssfailed'] = 'Hiba történt a hÃrfolyam betöltésekor: '; $lang['nothingfound'] = 'Üres mappa.'; $lang['mediaselect'] = 'Médiafájl kiválasztása'; @@ -205,7 +215,7 @@ $lang['created'] = 'létrehozva'; $lang['restored'] = 'régebbi változat helyreállÃtva (%s)'; $lang['external_edit'] = 'külsÅ‘ szerkesztés'; $lang['summary'] = 'A változások összefoglalása'; -$lang['noflash'] = 'Ennek a tartalomnak a megtekintéséhez <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> szükséges.'; +$lang['noflash'] = 'Ennek a tartalomnak a megtekintéséhez <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> szükséges.'; $lang['download'] = 'Kódrészlet letöltése'; $lang['tools'] = 'Eszközök'; $lang['user_tools'] = 'Felhasználói eszközök'; @@ -286,7 +296,7 @@ $lang['i_enableacl'] = 'Hozzáférési listák engedélyezése (ajánl $lang['i_superuser'] = 'Adminisztrátor'; $lang['i_problems'] = 'A BeállÃtó Varázsló a következÅ‘ problémák miatt megakadt. Nem tudjuk folytatni, amÃg ezek nincsenek elhárÃtva!'; $lang['i_modified'] = 'Biztonsági okokból ez a Varázsló csak új és módosÃtatlan DokuWiki változaton működik. -Csomagold ki újra a fájlokat a letöltött csomagból, vagy nézd meg a teljes <a href="http://dokuwiki.org/install">Dokuwiki telepÃtési útmutatót</a>.'; +Csomagold ki újra a fájlokat a letöltött csomagból, vagy nézd meg a teljes <a href="https://www.dokuwiki.org/install">Dokuwiki telepÃtési útmutatót</a>.'; $lang['i_funcna'] = 'A <code>%s</code> PHP funkció nem elérhetÅ‘. Esetleg a tárhelyszolgáltató letiltotta biztonsági okok miatt?'; $lang['i_phpver'] = 'A PHP <code>%s</code> verziója alacsonyabb, mint ami szükséges lenne: <code>%s</code>. FrissÃtsd a PHP-det újabb verzióra!'; $lang['i_mbfuncoverload'] = 'A DokuWiki futtatásához az mbstring.func_overload opciót ki kell kapcsolni a php.ini-ben.'; @@ -344,7 +354,7 @@ $lang['currentns'] = 'Aktuális névtér'; $lang['searchresult'] = 'Keresés eredménye'; $lang['plainhtml'] = 'Sima HTML'; $lang['wikimarkup'] = 'Wiki-jelölÅ‘nyelv'; -$lang['email_signature_text'] = 'Ezt a levelet a DokuWiki generálta -@DOKUWIKIURL@'; $lang['page_nonexist_rev'] = 'A(z) %s oldal nem létezik. KésÅ‘bb lett létrehozva a(z) <a href="%s">%s</a> helyen.'; $lang['unable_to_parse_date'] = 'A "%s" paraméter feldolgozása sikertelen.'; +$lang['email_signature_text'] = 'Ezt a levelet a DokuWiki generálta +@DOKUWIKIURL@'; diff --git a/inc/lang/hu/onceexisted.txt b/inc/lang/hu/onceexisted.txt new file mode 100644 index 000000000..243ec9218 --- /dev/null +++ b/inc/lang/hu/onceexisted.txt @@ -0,0 +1,3 @@ +======A keresett oldal már nem létezik====== + +Egy már nem létezÅ‘ oldal linkjére kattintottál. A [[?do=revisions|old revisions]]ben visszakeresheted, hogy mikor és miért szűnt meg az oldal, megnézheted vagy vissza is állÃthatsz verzióelÅ‘zményeket.
\ No newline at end of file diff --git a/inc/lang/ia/lang.php b/inc/lang/ia/lang.php index a00f8bfac..38b7a792c 100644 --- a/inc/lang/ia/lang.php +++ b/inc/lang/ia/lang.php @@ -164,7 +164,7 @@ $lang['created'] = 'create'; $lang['restored'] = 'ancian version restaurate (%s)'; $lang['external_edit'] = 'modification externe'; $lang['summary'] = 'Modificar summario'; -$lang['noflash'] = 'Le <a href="http://www.adobe.com/products/flashplayer/">plug-in Flash de Adobe</a> es necessari pro monstrar iste contento.'; +$lang['noflash'] = 'Le <a href="http://get.adobe.com/flashplayer">plug-in Flash de Adobe</a> es necessari pro monstrar iste contento.'; $lang['download'] = 'Discargar fragmento'; $lang['mail_newpage'] = 'pagina addite:'; $lang['mail_changed'] = 'pagina modificate:'; @@ -232,7 +232,7 @@ $lang['i_enableacl'] = 'Activar ACL (recommendate)'; $lang['i_superuser'] = 'Superusator'; $lang['i_problems'] = 'Le installator ha trovate alcun problemas, indicate hic infra. Tu debe resolver iste problemas pro poter continuar.'; $lang['i_modified'] = 'Pro motivos de securitate, iste script functiona solmente con un installation de DokuWiki nove e non modificate. -Tu debe re-extraher le files del pacchetto discargate, o consultar le <a href="http://dokuwiki.org/install">instructiones de installation</a> complete pro altere optiones.'; +Tu debe re-extraher le files del pacchetto discargate, o consultar le <a href="https://www.dokuwiki.org/install">instructiones de installation</a> complete pro altere optiones.'; $lang['i_funcna'] = 'Le function PHP <code>%s</code> non es disponibile. Pote esser que tu albergo web lo ha disactivate pro un ration o altere.'; $lang['i_phpver'] = 'Le version de PHP <code>%s</code> es plus ancian que le version requisite <code>%s</code>. Es necessari actualisar le installation de PHP.'; $lang['i_permfail'] = '<code>%s</code> non permitte le accesso de scriptura a DokuWiki. Tu debe reparar le permissiones de iste directorio!'; diff --git a/inc/lang/id/lang.php b/inc/lang/id/lang.php index 61f279839..f12960e73 100644 --- a/inc/lang/id/lang.php +++ b/inc/lang/id/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author NawanP <saya@nawan.my.id> * @author rusly-id <rusly-id@users.noreply.github.com> * @author mubaidillah <mubaidillah@gmail.com> * @author Irwan Butar Butar <irwansah.putra@gmail.com> @@ -24,6 +25,7 @@ $lang['btn_show'] = 'Tampilkan halaman'; $lang['btn_create'] = 'Buat halaman baru'; $lang['btn_search'] = 'Cari'; $lang['btn_save'] = 'Simpan'; +$lang['btn_preview'] = 'Pratayang'; $lang['btn_top'] = 'kembali ke atas'; $lang['btn_newer'] = '<< lebih lanjut'; $lang['btn_older'] = 'sebelumnya >>'; @@ -32,6 +34,7 @@ $lang['btn_recent'] = 'Perubahan terbaru'; $lang['btn_upload'] = 'Upload'; $lang['btn_cancel'] = 'Batal'; $lang['btn_index'] = 'Indeks'; +$lang['btn_secedit'] = 'Sunting'; $lang['btn_login'] = 'Login'; $lang['btn_logout'] = 'Keluar'; $lang['btn_admin'] = 'Admin'; @@ -41,7 +44,9 @@ $lang['btn_back'] = 'Kembali'; $lang['btn_backlink'] = 'Backlinks'; $lang['btn_subscribe'] = 'Ikuti Perubahan'; $lang['btn_profile'] = 'Ubah Profil'; +$lang['btn_reset'] = 'Atur ulang'; $lang['btn_resendpwd'] = 'Atur password baru'; +$lang['btn_draft'] = 'Sunting draf'; $lang['btn_recover'] = 'Cadangkan draf'; $lang['btn_draftdel'] = 'Hapus draft'; $lang['btn_revert'] = 'Kembalikan'; @@ -190,7 +195,7 @@ $lang['deleted'] = 'terhapus'; $lang['created'] = 'dibuat'; $lang['restored'] = 'revisi lama ditampilkan kembali (%s)'; $lang['external_edit'] = 'Perubahan eksternal'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> diperlukan untuk menampilkan konten ini.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> diperlukan untuk menampilkan konten ini.'; $lang['download'] = 'Unduh Cuplikan'; $lang['tools'] = 'Alat'; $lang['user_tools'] = 'Alat Pengguna'; @@ -257,7 +262,7 @@ $lang['i_installer'] = 'Instalasi DokuWiki'; $lang['i_wikiname'] = 'Nama Wiki'; $lang['i_enableacl'] = 'Aktifkan ACL (disarankan)'; $lang['i_problems'] = 'Terdapat beberapa kesalahan seperti berikut. Anda tidak dapat melanjutkan sampai kesalahan tersebut diperbaiki.'; -$lang['i_modified'] = 'Untuk alasan keamanan, skrip ini hanya dapat dijalankan pada instalasi DikuWiki baru dan belum di modifikasi. Silahkan meng-ekstrak kembali berkasi dari halaman dowload, atau lihat <a href="http://dokuwiki.org/install">Dokuwiki installation instructions</a> '; +$lang['i_modified'] = 'Untuk alasan keamanan, skrip ini hanya dapat dijalankan pada instalasi DikuWiki baru dan belum di modifikasi. Silahkan meng-ekstrak kembali berkasi dari halaman dowload, atau lihat <a href="https://www.dokuwiki.org/install">Dokuwiki installation instructions</a> '; $lang['i_funcna'] = 'Fungsi PHP <code>%s</code> tidak tersedia. Mungkin dinonaktifkan oleh layanan hosting Anda?'; $lang['i_phpver'] = 'Versi PHP Anda <code>%s</code> lebih rendah dari yang dibutuhkan <code>%s</code>. Mohon melakukan upgrade.'; $lang['i_permfail'] = '<code>%s</code> tidak dapat ditulis oleh DokuWiki. Anda harus memperbaiki konfigurasi hak akses untuk direktori tersebut.'; diff --git a/inc/lang/is/lang.php b/inc/lang/is/lang.php index de74c8c09..8837f03dd 100644 --- a/inc/lang/is/lang.php +++ b/inc/lang/is/lang.php @@ -139,7 +139,7 @@ $lang['created'] = 'myndað'; $lang['restored'] = 'Breytt aftur til fyrri útgáfu (%s)'; $lang['external_edit'] = 'utanaðkomandi breyta'; $lang['summary'] = 'Forskoða'; -$lang['noflash'] = 'Það þarf <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash viðbót</a> til að sýna sumt efnið á þessari sÃðu'; +$lang['noflash'] = 'Það þarf <a href="http://get.adobe.com/flashplayer">Adobe Flash viðbót</a> til að sýna sumt efnið á þessari sÃðu'; $lang['download'] = 'Hlaða niður til kóðabút'; $lang['mail_newpage'] = 'sÃðu bætt við:'; $lang['mail_changed'] = 'sÃðu breytt:'; diff --git a/inc/lang/it/lang.php b/inc/lang/it/lang.php index 7be236da4..e4bfe604d 100644 --- a/inc/lang/it/lang.php +++ b/inc/lang/it/lang.php @@ -235,7 +235,7 @@ $lang['created'] = 'creata'; $lang['restored'] = 'versione precedente ripristinata (%s)'; $lang['external_edit'] = 'modifica esterna'; $lang['summary'] = 'Oggetto della modifica'; -$lang['noflash'] = 'E\' necessario <a href="http://www.adobe.com/products/flashplayer/">il plugin Adobe Flash</a> per visualizzare questo contenuto.'; +$lang['noflash'] = 'E\' necessario <a href="http://get.adobe.com/flashplayer">il plugin Adobe Flash</a> per visualizzare questo contenuto.'; $lang['download'] = 'Scarica lo "snippet"'; $lang['tools'] = 'Strumenti'; $lang['user_tools'] = 'Strumenti Utente'; @@ -317,10 +317,10 @@ $lang['i_superuser'] = 'Amministratore'; $lang['i_problems'] = 'Si sono verificati problemi durante l\'installazione, indicati di seguito. Non è possibile continuare finché non saranno risolti.'; $lang['i_modified'] = 'Per motivi di sicurezza questa procedura funziona solamente con un\'installazione Dokuwiki nuova e non modificata. Prova a estrarre di nuovo i file dal pacchetto scaricato oppure consulta le -<a href="http://dokuwiki.org/install">istruzioni per l\'installazione di Dokuwiki</a>'; +<a href="https://www.dokuwiki.org/install">istruzioni per l\'installazione di Dokuwiki</a>'; $lang['i_funcna'] = 'La funzione PHP <code>%s</code> non è disponibile. Forse è stata disabilitata dal tuo provider per qualche motivo?'; $lang['i_disabled'] = 'E\' stato disabilitato dal tuo provider di servizi.'; -$lang['i_funcnmail'] = '<b>Nota:</b> La funzione mail PHP non è disponibile. %s Se rimane non disponibile, puoi provare ad installare <a href="http://dokuwiki.org/plugins/smtp">smtp plugin</a>.'; +$lang['i_funcnmail'] = '<b>Nota:</b> La funzione mail PHP non è disponibile. %s Se rimane non disponibile, puoi provare ad installare <a href="https://www.dokuwiki.org/plugin:smtp">smtp plugin</a>.'; $lang['i_phpver'] = 'La versione di PHP <code>%s</code> è inferiore a quella richiesta <code>%s</code>. Devi aggiornare l\'installazione di PHP.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload deve essere disabilitato in php.ini per eseguire DokuWiki.'; $lang['i_urandom'] = 'DokuWiki non può creare un numero crittograficamente sicuro di cookies. Puoi provare a controllare sulle impostazioni open_basedir su php.ini per un corretto <code>/dev/urandom</code> accesso.'; diff --git a/inc/lang/ja/lang.php b/inc/lang/ja/lang.php index 7882a8967..cd52029b7 100644 --- a/inc/lang/ja/lang.php +++ b/inc/lang/ja/lang.php @@ -199,7 +199,7 @@ $lang['current'] = 'ç¾åœ¨'; $lang['yours'] = 'ã‚ãªãŸã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³'; $lang['diff'] = 'ç¾åœ¨ã®ãƒªãƒ“ジョンã¨ã®å·®åˆ†ã‚’表示'; $lang['diff2'] = 'é¸æŠžã—ãŸãƒªãƒ“ジョン間ã®å·®åˆ†ã‚’表示'; -$lang['difflink'] = 'ã“ã®æ¯”較画é¢ã«ãƒªãƒ³ã‚¯ã™ã‚‹'; +$lang['difflink'] = 'ã“ã®æ¯”較画é¢ã¸ã®ãƒªãƒ³ã‚¯'; $lang['diff_type'] = '差分ã®è¡¨ç¤ºæ–¹æ³•:'; $lang['diff_inline'] = 'インライン'; $lang['diff_side'] = '横ã«ä¸¦ã¹ã‚‹'; @@ -218,7 +218,7 @@ $lang['created'] = '作æˆ'; $lang['restored'] = '以å‰ã®ãƒªãƒ“ジョンを復元 (%s)'; $lang['external_edit'] = '外部編集'; $lang['summary'] = 'ç·¨é›†ã®æ¦‚è¦'; -$lang['noflash'] = 'ã“ã®å†…容を表示ã™ã‚‹ã«ã¯ <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> ãŒå¿…è¦ã§ã™ã€‚'; +$lang['noflash'] = 'ã“ã®å†…容を表示ã™ã‚‹ã«ã¯ <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> ãŒå¿…è¦ã§ã™ã€‚'; $lang['download'] = 'ã“ã®éƒ¨åˆ†ã‚’ダウンãƒãƒ¼ãƒ‰'; $lang['tools'] = 'ツール'; $lang['user_tools'] = 'ユーザ用ツール'; @@ -300,10 +300,10 @@ $lang['i_superuser'] = 'スーパーユーザー'; $lang['i_problems'] = 'å•題ãŒç™ºè¦‹ã•れã¾ã—ãŸã€‚以下ã«ç¤ºã™å•題を解決ã™ã‚‹ã¾ã§ã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’続行ã§ãã¾ã›ã‚“。'; $lang['i_modified'] = 'ã‚»ã‚ュリティã®ç†ç”±ã‹ã‚‰ã€æ–°è¦ã‚‚ã—ãã¯ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºã—ã¦ã„ãªã„ DokuWiki ã«å¯¾ã—ã¦ã®ã¿ã€ã“ã®ã‚¹ã‚¯ãƒªãƒ—ãƒˆã¯æœ‰åйã§ã™ã€‚ ダウンãƒãƒ¼ãƒ‰ã—ãŸãƒ‘ッケージをå†è§£å‡ã—ã¦ä½¿ç”¨ã™ã‚‹ã‹ã€ - <a href="http://dokuwiki.org/install">Dokuwiki インストールガイド</a>ã‚’å‚考ã«ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。'; + <a href="https://www.dokuwiki.org/install">Dokuwiki インストールガイド</a>ã‚’å‚考ã«ã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ãã ã•ã„。'; $lang['i_funcna'] = 'PHPã®é–¢æ•° <code>%s</code> ãŒä½¿ç”¨ã§ãã¾ã›ã‚“。ホスティング会社ãŒä½•らã‹ã®ç†ç”±ã§ç„¡åйã«ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚'; $lang['i_disabled'] = 'ã”利用ã®ãƒ—ãƒãƒã‚¤ãƒ€ã«ã‚ˆã‚Šåˆ¶é™ã•れã¦ã„ã¾ã™ã€‚'; -$lang['i_funcnmail'] = '<b>注:</b>PHPã® mail 関数ãŒåˆ©ç”¨ä¸èƒ½ã«ãªã£ã¦ã„ã¾ã™ã€‚ %s ã“ã®çжæ³ãŒç¶šãå ´åˆã¯ã€<a href="http://dokuwiki.org/plugins/smtp">smtpプラグイン</a>をインストールã—ã¦è§£æ±ºã™ã‚‹äº‹ã‚‚出æ¥ã¾ã™ã€‚'; +$lang['i_funcnmail'] = '<b>注:</b>PHPã® mail 関数ãŒåˆ©ç”¨ä¸èƒ½ã«ãªã£ã¦ã„ã¾ã™ã€‚ %s ã“ã®çжæ³ãŒç¶šãå ´åˆã¯ã€<a href="https://www.dokuwiki.org/plugin:smtp">smtpプラグイン</a>をインストールã—ã¦è§£æ±ºã™ã‚‹äº‹ã‚‚出æ¥ã¾ã™ã€‚'; $lang['i_phpver'] = 'PHPã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ <code>%s</code> ãŒå¿…è¦ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ <code>%s</code> より以å‰ã®ã‚‚ã®ã§ã™ã€‚PHPã®ã‚¢ãƒƒãƒ—グレードãŒå¿…è¦ã§ã™ã€‚'; $lang['i_mbfuncoverload'] = 'DokuWiki を実行ã™ã‚‹ php.ini ファイル㮠mbstring.func_overload ã¯ç„¡åйã«ã—ã¦ä¸‹ã•ã„。'; $lang['i_urandom'] = 'DokuWikiã¯ã€Cookieã«å¯¾ã—ã¦æš—å·çš„ã«å®‰å…¨ãªç•ªå·ã‚’作æˆã§ãã¾ã›ã‚“。<code>/dev/urandom</code>ã«å¯¾ã™ã‚‹é©åˆ‡ãªã‚¢ã‚¯ã‚»ã‚¹ã«ã¤ã„ã¦ã€php.iniã®è¨å®š open_basedir を確èªã™ã‚‹äº‹ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚'; diff --git a/inc/lang/ka/lang.php b/inc/lang/ka/lang.php index e8e99c572..046a8a704 100644 --- a/inc/lang/ka/lang.php +++ b/inc/lang/ka/lang.php @@ -199,7 +199,7 @@ $lang['deleted'] = 'წáƒáƒ¨áƒšáƒ˜áƒšáƒ˜áƒ'; $lang['created'] = 'შექმნილიáƒ'; $lang['restored'] = 'ძველი ვერსირáƒáƒ¦áƒ“გენილირ(%s)'; $lang['external_edit'] = 'რედáƒáƒ¥áƒ¢áƒ˜áƒ ებáƒ'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">სáƒáƒáƒ˜áƒ áƒáƒ Adobe Flash Plugin</a>'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">სáƒáƒáƒ˜áƒ áƒáƒ Adobe Flash Plugin</a>'; $lang['download'] = 'Snippet-ის გáƒáƒ“მáƒáƒ¬áƒ”რáƒ'; $lang['tools'] = 'ინსტრუმენტები'; $lang['user_tools'] = 'მáƒáƒ›áƒ®áƒ›áƒáƒ ებლის ინსტრუმენტები'; diff --git a/inc/lang/ko/lang.php b/inc/lang/ko/lang.php index 50ad63444..0e43b8f35 100644 --- a/inc/lang/ko/lang.php +++ b/inc/lang/ko/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author merefox <admin@homerecz.com> * @author pavement <pavement@rael.cc> * @author Traend <Traend@ruu.kr> * @author Seungheon Song <esketch@gmail.com> @@ -51,7 +52,7 @@ $lang['btn_back'] = '뒤로'; $lang['btn_backlink'] = 'ì—ë§í¬'; $lang['btn_subscribe'] = 'êµ¬ë… ê´€ë¦¬'; $lang['btn_profile'] = '프로필 ì—…ë°ì´íЏ'; -$lang['btn_reset'] = '재'; +$lang['btn_reset'] = 'ìž¬ì„¤ì •'; $lang['btn_resendpwd'] = '새 비밀번호 ì„¤ì •'; $lang['btn_draft'] = '초안 편집'; $lang['btn_recover'] = '초안 복구'; @@ -127,6 +128,10 @@ $lang['search_exact_match'] = 'ì •í™•ížˆ ì¼ì¹˜'; $lang['search_starts_with'] = '시작'; $lang['search_ends_with'] = 'ë'; $lang['search_any_ns'] = 'ëª¨ë“ ë„¤ìž„ìŠ¤íŽ˜ì´ìФ'; +$lang['search_past_7_days'] = 'ì €ë²ˆ 주'; +$lang['search_past_month'] = 'ì €ë²ˆ 달'; +$lang['search_past_year'] = 'ì €ë²ˆ ë…„ë„'; +$lang['search_sort_by_hits'] = '조회수로 ì •ë ¬'; $lang['regmissing'] = '죄송하지만 ëª¨ë“ í•„ë“œë¥¼ 채워야 합니다.'; $lang['reguexists'] = '죄송하지만 ê°™ì€ ì´ë¦„ì„ ì‚¬ìš©í•˜ëŠ” 사용ìžê°€ 있습니다.'; $lang['regsuccess'] = 'ì‚¬ìš©ìž ê³„ì •ì„ ë§Œë“¤ì—ˆìœ¼ë©° 비밀번호는 ì´ë©”ì¼ë¡œ 보냈습니다.'; @@ -163,6 +168,7 @@ $lang['txt_upload'] = '올릴 íŒŒì¼ ì„ íƒ:'; $lang['txt_filename'] = '올릴 íŒŒì¼ ì´ë¦„ (ì„ íƒ ì‚¬í•):'; $lang['txt_overwrt'] = '기존 파ì¼ì— ë®ì–´ì“°ê¸°'; $lang['maxuploadsize'] = '최대 올리기 용량. 파ì¼ë‹¹ %s.'; +$lang['allowedmime'] = 'í—ˆìš©ëœ íŒŒì¼ í™•ìž¥ìž ë¦¬ìŠ¤íŠ¸'; $lang['lockedby'] = '현재 ìž ê·¼ 사용ìž:'; $lang['lockexpire'] = 'ìž ê¸ˆ í•´ì œ 시간:'; $lang['rssfailed'] = 'ì´ í”¼ë“œë¥¼ ê°€ì ¸ì˜¤ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤:'; @@ -216,7 +222,7 @@ $lang['created'] = '만듦'; $lang['restored'] = 'ì´ì „ íŒìœ¼ë¡œ ë˜ëŒë¦¼ (%s)'; $lang['external_edit'] = '바깥 편집'; $lang['summary'] = '편집 요약'; -$lang['noflash'] = 'ì´ ë‚´ìš©ì„ í‘œì‹œí•˜ê¸° 위해서 <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash 플러그ì¸</a>ì´ í•„ìš”í•©ë‹ˆë‹¤.'; +$lang['noflash'] = 'ì´ ë‚´ìš©ì„ í‘œì‹œí•˜ê¸° 위해서 <a href="http://get.adobe.com/flashplayer">Adobe Flash 플러그ì¸</a>ì´ í•„ìš”í•©ë‹ˆë‹¤.'; $lang['download'] = 'ì¡°ê° ë‹¤ìš´ë¡œë“œ'; $lang['tools'] = 'ë„구'; $lang['user_tools'] = 'ì‚¬ìš©ìž ë„구'; diff --git a/inc/lang/la/lang.php b/inc/lang/la/lang.php index 5f5f59e12..1968d512b 100644 --- a/inc/lang/la/lang.php +++ b/inc/lang/la/lang.php @@ -164,7 +164,7 @@ $lang['created'] = 'creatur'; $lang['restored'] = 'Recensio uetus restituta (%s)'; $lang['external_edit'] = 'Externe recensere'; $lang['summary'] = 'Indicem recensere'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> necessarium est.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> necessarium est.'; $lang['download'] = 'Snippet capere'; $lang['mail_newpage'] = 'Pagina addita:'; $lang['mail_changed'] = 'Pagina mutata:'; @@ -233,7 +233,7 @@ $lang['i_wikiname'] = 'Nomen Vicis'; $lang['i_enableacl'] = 'ICA aptum facias (consulatum est)'; $lang['i_superuser'] = 'Magister\stra'; $lang['i_problems'] = 'Creator hos errores habes. Continuare potes postquam omnia soluentur.'; -$lang['i_modified'] = 'Hoc scriptum solum cum noua forma Dokuuicis est. Hoc rursum capere in pagina, in qua haec machina capta est, potes aut i ad <a href="http://dokuwiki.org/install">Dokuuicis installation instructions</a>'; +$lang['i_modified'] = 'Hoc scriptum solum cum noua forma Dokuuicis est. Hoc rursum capere in pagina, in qua haec machina capta est, potes aut i ad <a href="https://www.dokuwiki.org/install">Dokuuicis installation instructions</a>'; $lang['i_funcna'] = 'PHP functio <code>%s</code> inepta est.'; $lang['i_phpver'] = 'Forma tua PHP <code>%s</code> minor quam illa necessaria <code>%s</code>.'; $lang['i_permfail'] = '<code>%s</code> non a uice scribitur. Facultates inspicere.'; diff --git a/inc/lang/lb/lang.php b/inc/lang/lb/lang.php index d4d0fb47f..7464275f5 100644 --- a/inc/lang/lb/lang.php +++ b/inc/lang/lb/lang.php @@ -125,7 +125,7 @@ $lang['created'] = 'erstallt'; $lang['restored'] = 'al Versioun zeréckgeholl (%s)'; $lang['external_edit'] = 'extern Ännerung'; $lang['summary'] = 'Resumé vun den Ännerungen'; -$lang['noflash'] = 'Den <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> get gebraucht fir dësen Inhalt unzeweisen.'; +$lang['noflash'] = 'Den <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> get gebraucht fir dësen Inhalt unzeweisen.'; $lang['mail_newpage'] = 'Säit bäigesat:'; $lang['mail_changed'] = 'Säit geännert:'; $lang['mail_subscribe_list'] = 'g\'ännert Säiten am Namespace:'; @@ -176,7 +176,7 @@ $lang['i_installer'] = 'DokuWiki Installer'; $lang['i_wikiname'] = 'Numm vum Wiki'; $lang['i_enableacl'] = 'ACL uschalten (rekommandéiert)'; $lang['i_problems'] = 'Den Installer huet Problemer fond. Se stinn hei ënnendrënner. Du kanns net weiderfueren bis de se behuewen hues.'; -$lang['i_modified'] = 'Aus Sécherheetsgrënn funktionnéiert dëse Script nëmme mat enger neier an onverännerter Dokuwiki Installatioun. Entweder muss de d\'Dateie frësch extrahéieren oder kuck d\'komplett <a href="http://dokuwiki.org/install">Dokuwiki Installatiounsinstruktiounen</a>'; +$lang['i_modified'] = 'Aus Sécherheetsgrënn funktionnéiert dëse Script nëmme mat enger neier an onverännerter Dokuwiki Installatioun. Entweder muss de d\'Dateie frësch extrahéieren oder kuck d\'komplett <a href="https://www.dokuwiki.org/install">Dokuwiki Installatiounsinstruktiounen</a>'; $lang['i_funcna'] = 'PHP-Funktioun <code>%s</code> ass net verfügbar. Vläicht huet däi Provider se aus iergend engem Grond ausgeschalt.'; $lang['i_phpver'] = 'Deng PHP-Versioun <code>%s</code> ass méi kleng wéi déi gebrauchte Versioun <code>%s</code>. Du muss deng PHP-Installatioun aktualiséieren. '; $lang['i_pol0'] = 'Oppene Wiki (liese, schreiwen an eroplueden fir jidfereen)'; diff --git a/inc/lang/lt/lang.php b/inc/lang/lt/lang.php index 004bb850f..788807429 100644 --- a/inc/lang/lt/lang.php +++ b/inc/lang/lt/lang.php @@ -141,7 +141,7 @@ $lang['created'] = 'sukurtas'; $lang['restored'] = 'atstatyta sena versija (%s)'; $lang['external_edit'] = 'redaguoti papildomomis priemonÄ—mis'; $lang['summary'] = 'Redaguoti santraukÄ…'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> reikalingas Å¡ios medžiagos peržiÅ«rai.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> reikalingas Å¡ios medžiagos peržiÅ«rai.'; $lang['mail_newpage'] = '[DokuWiki] puslapis pridÄ—tas:'; $lang['mail_changed'] = '[DokuWiki] puslapis pakeistas:'; $lang['mail_new_user'] = 'naujas vartotojas:'; diff --git a/inc/lang/lv/lang.php b/inc/lang/lv/lang.php index 1a101ad8b..c91e2b4f7 100644 --- a/inc/lang/lv/lang.php +++ b/inc/lang/lv/lang.php @@ -197,7 +197,7 @@ $lang['created'] = 'izveidots'; $lang['restored'] = 'vecÄ versija atjaunota (%s)'; $lang['external_edit'] = 'ÄrpussistÄ“mas labojums'; $lang['summary'] = 'AnotÄcija'; -$lang['noflash'] = 'Lai attÄ“lotu lapas saturu, vajag <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'Lai attÄ“lotu lapas saturu, vajag <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'LejuplÄdÄ“t «kodiņu»((snippet))'; $lang['tools'] = 'RÄ«ki'; $lang['user_tools'] = 'LietotÄja rÄ«ki'; @@ -278,7 +278,7 @@ $lang['i_enableacl'] = 'Lietot ACL (ieteikts)'; $lang['i_superuser'] = 'Superuser'; $lang['i_problems'] = 'InstalÄ“tÄjs atrada zemÄk minÄ“tÄs problÄ“mas. KamÄ“r tÄs nenovÄ“rÅ¡, nav iespÄ“jam turpinÄt.'; $lang['i_modified'] = 'Drošības nolÅ«kos Å¡is skripts darbosies tika ar jaunu nemodificÄ“tu Dokuwiki instalÄciju. -Vai nu no jauna jÄatarhivÄ“ faili no lejupielÄdÄ“tÄs pakas vai jÄraugÄs pÄ“c padoma pilnÄ Dokuwiki instalÄcijas instrukcijÄ <a href="http://dokuwiki.org/install"></a>'; +Vai nu no jauna jÄatarhivÄ“ faili no lejupielÄdÄ“tÄs pakas vai jÄraugÄs pÄ“c padoma pilnÄ Dokuwiki instalÄcijas instrukcijÄ <a href="https://www.dokuwiki.org/install"></a>'; $lang['i_funcna'] = 'PHP funkcija <code>%s</code> nav pieejama. VarbÅ«t jÅ«su servera Ä«paÅ¡nieks to kÄda iemesla dēļ atslÄ“dzis?'; $lang['i_phpver'] = 'JÅ«su PHP versija <code>%s</code> ir par vecu. Vajag versiju <code>%s</code>. Atjaunojiet savu PHP instalÄciju.'; $lang['i_mbfuncoverload'] = 'Lai darbinÄtu DokuWiki, php.ini failÄ ir jÄatspÄ“jo mbstring.func_overload.'; diff --git a/inc/lang/mk/lang.php b/inc/lang/mk/lang.php index 034d98b38..af7dc4768 100644 --- a/inc/lang/mk/lang.php +++ b/inc/lang/mk/lang.php @@ -139,7 +139,7 @@ $lang['created'] = 'креирана'; $lang['restored'] = 'обновена е Ñтара ревизија (%s)'; $lang['external_edit'] = 'надворешно уредување'; $lang['summary'] = 'Уреди го изводот'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash приклучокот</a> е потребен за да Ñе прикаже оваа Ñодржина.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">Adobe Flash приклучокот</a> е потребен за да Ñе прикаже оваа Ñодржина.'; $lang['download'] = 'Симни Snippe'; $lang['mail_newpage'] = 'додадена е Ñтраницата:'; $lang['mail_changed'] = 'променета е Ñтраницата:'; @@ -202,7 +202,7 @@ $lang['i_wikiname'] = 'вики име'; $lang['i_enableacl'] = 'Овозможи ACL (препорачано)'; $lang['i_superuser'] = 'Супер кориÑник'; $lang['i_problems'] = 'ИнÑталерот пронајде неколку проблеми кои Ñе прикажани подолу. Ðе можете да продолжите понатаму Ñе додека не ги поправите.'; -$lang['i_modified'] = 'За безбедноÑни причини оваа Ñкрипта ќе работи Ñамо Ñо нова и неизменета инÑталација од DokuWiki. Или извадете ги повторно датотеките од Ñимнатиот пакет или конÑултирајте Ñе Ñо комплетните <a href="http://dokuwiki.org/install">Dokuwiki инÑтрукции за инÑталација</a>'; +$lang['i_modified'] = 'За безбедноÑни причини оваа Ñкрипта ќе работи Ñамо Ñо нова и неизменета инÑталација од DokuWiki. Или извадете ги повторно датотеките од Ñимнатиот пакет или конÑултирајте Ñе Ñо комплетните <a href="https://www.dokuwiki.org/install">Dokuwiki инÑтрукции за инÑталација</a>'; $lang['i_funcna'] = 'PHP функцијата <code>%s</code> не е доÑтапна. Можеби вашиот хоÑтинг провајдер ја оневозможил Ñо причина?'; $lang['i_phpver'] = 'Вашата верзија на PHP <code>%s</code> е пониÑка од потребната <code>%s</code>. Треба да ја надградите вашата PHP инÑталација.'; $lang['i_permfail'] = '<code>%s</code> не е запишлива од DokuWiki. Треба да ги поправите подеÑувањата за пермиÑии на овој директориум!'; diff --git a/inc/lang/mr/lang.php b/inc/lang/mr/lang.php index 5aa22f30f..567a91dad 100644 --- a/inc/lang/mr/lang.php +++ b/inc/lang/mr/lang.php @@ -180,7 +180,7 @@ $lang['deleted'] = 'काढून टाकले'; $lang['created'] = 'निरà¥à¤®à¤¾à¤£ केले'; $lang['external_edit'] = 'बाहेरून संपादित'; $lang['summary'] = 'सारांश बदला'; -$lang['noflash'] = 'ही माहिती दाखवणà¥à¤¯à¤¾à¤¸à¤¾à¤ ी <a href="http://www.adobe.com/products/flashplayer/">अडोब फà¥à¤²à¥…श पà¥à¤²à¥‡à¤…र</a> ची गरज आहे.'; +$lang['noflash'] = 'ही माहिती दाखवणà¥à¤¯à¤¾à¤¸à¤¾à¤ ी <a href="http://get.adobe.com/flashplayer">अडोब फà¥à¤²à¥…श पà¥à¤²à¥‡à¤…र</a> ची गरज आहे.'; $lang['download'] = 'तà¥à¤•डा डाउनलोड करा'; $lang['tools'] = 'साधने'; $lang['user_tools'] = 'यà¥à¤œà¤°à¤šà¥€ साधने'; @@ -245,7 +245,7 @@ $lang['i_wikiname'] = 'विकी नाम'; $lang['i_enableacl'] = 'ACL चालू करा ( अधिक चांगले )'; $lang['i_superuser'] = 'सà¥à¤ªà¤°-सदसà¥à¤¯'; $lang['i_problems'] = 'इनसà¥à¤Ÿà¥‰à¤²à¤°à¤²à¤¾ काही अडचणि आलà¥à¤¯à¤¾ आहेत. तà¥à¤¯à¤¾ ठीक केलà¥à¤¯à¤¾à¤¶à¤¿à¤µà¤¾à¤¯ तà¥à¤®à¥à¤¹à¥€ पà¥à¤¢à¥‡ जाऊ शकत नाही.'; -$lang['i_modified'] = 'सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¥‡à¤šà¥à¤¯à¤¾ कारणासठि ही सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ फ़कà¥à¤¤ नवीन आणि बदललेलà¥à¤¯à¤¾ डॉकà¥à¤¯à¥à¤µà¤¿à¤•ि इनà¥à¤¸à¥à¤Ÿà¥‰à¤²à¥‡à¤¶à¤¨ मधेच चालेल. तà¥à¤®à¥à¤¹à¥€ à¤à¤•तर डाउनलोड केलेले पॅकेज मधील फाइल परत पà¥à¤°à¤¸à¤¾à¤°à¤¿à¤¤ करा किंवा <a href="http://dokuwiki.org/install">डॉकà¥à¤¯à¥à¤µà¤¿à¤•ि इनà¥à¤¸à¥à¤Ÿà¥‰à¤²à¥‡à¤¶à¤¨ विषयी सूचना</a> वाचा.'; +$lang['i_modified'] = 'सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¥‡à¤šà¥à¤¯à¤¾ कारणासठि ही सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ फ़कà¥à¤¤ नवीन आणि बदललेलà¥à¤¯à¤¾ डॉकà¥à¤¯à¥à¤µà¤¿à¤•ि इनà¥à¤¸à¥à¤Ÿà¥‰à¤²à¥‡à¤¶à¤¨ मधेच चालेल. तà¥à¤®à¥à¤¹à¥€ à¤à¤•तर डाउनलोड केलेले पॅकेज मधील फाइल परत पà¥à¤°à¤¸à¤¾à¤°à¤¿à¤¤ करा किंवा <a href="https://www.dokuwiki.org/install">डॉकà¥à¤¯à¥à¤µà¤¿à¤•ि इनà¥à¤¸à¥à¤Ÿà¥‰à¤²à¥‡à¤¶à¤¨ विषयी सूचना</a> वाचा.'; $lang['i_funcna'] = 'PHP मधलं <code>%s</code> हे फंकà¥à¤¶à¤¨ उपलबà¥à¤§ नाही. बहà¥à¤§à¤¾ तà¥à¤®à¤šà¥à¤¯à¤¾ होसà¥à¤Ÿà¤¿à¤‚ग पà¥à¤°à¤µà¤£à¤¾à¤°à¤¾à¤¨à¥‡ ते काही कारणाने अनà¥à¤ªà¤²à¤¬à¥à¤§ केलं असावं.'; $lang['i_phpver'] = 'तà¥à¤®à¤šà¥€ PHP आवृतà¥à¤¤à¤¿ <code>%s</code> ही आवशà¥à¤¯à¤• असलेलà¥à¤¯à¤¾ <code>%s</code> हà¥à¤¯à¤¾ आवृतà¥à¤¤à¤¿à¤ªà¥‡à¤•à¥à¤·à¤¾ कमी आहे. कृपया तà¥à¤®à¤šà¥‡ PHP इनà¥à¤¸à¥à¤Ÿà¥‰à¤²à¥‡à¤¶à¤¨ अदà¥à¤¯à¤¯à¤¾à¤µà¤¤ करा.'; $lang['i_permfail'] = '<code>%s</code> या डिरेकà¥à¤Ÿà¤°à¥€ मधà¥à¤¯à¥‡ डॉकà¥à¤¯à¥à¤µà¤¿à¤•ि बदल करू शकत नाही. कृपया या डिरेकà¥à¤Ÿà¤°à¥€à¤šà¥à¤¯à¤¾ परवानगà¥à¤¯à¤¾ ठीक करा.'; diff --git a/inc/lang/ne/lang.php b/inc/lang/ne/lang.php index c0daf29b5..903a3eeca 100644 --- a/inc/lang/ne/lang.php +++ b/inc/lang/ne/lang.php @@ -184,7 +184,7 @@ $lang['i_wikiname'] = 'विकी नाम'; $lang['i_enableacl'] = 'ACL लागॠगरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥( सिफारिस गरिà¤à¤•ो)'; $lang['i_superuser'] = 'मूखà¥à¤¯ पà¥à¤°à¤¯à¥‹à¤—करà¥à¤¤à¤¾'; $lang['i_problems'] = 'सà¥à¤¥à¤¾à¤ªà¤•ले तल देखाइà¤à¤•ो तà¥à¤°à¥à¤Ÿà¤¿ फेला पारà¥â€Œà¤¯à¥‹ ।तपाईले यो तà¥à¤°à¥à¤Ÿà¤¿ नसचà¥à¤¯à¤¾à¤ समà¥à¤® अगि बढà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥‡ छैन।'; -$lang['i_modified'] = 'सà¥à¤°à¤•à¥à¤·à¤¾à¤•ो कारणले यो सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ नया तथा नसचà¥à¤¯à¤¾à¤‡à¤à¤•ो Dokuwiki सà¥à¤¥à¤¾à¤ªà¤¨à¤¾à¤®à¤¾ मातà¥à¤° काम गरà¥à¤›à¥¤ तपाईले कि डाउनलोड गरà¥à¤¨à¥à¤à¤à¤•ो पà¥à¤¯à¤¾à¤•ेज पà¥à¤¨: खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ कि <a href="http://dokuwiki.org/install">Dokuwiki सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ विधि</a>'; +$lang['i_modified'] = 'सà¥à¤°à¤•à¥à¤·à¤¾à¤•ो कारणले यो सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ नया तथा नसचà¥à¤¯à¤¾à¤‡à¤à¤•ो Dokuwiki सà¥à¤¥à¤¾à¤ªà¤¨à¤¾à¤®à¤¾ मातà¥à¤° काम गरà¥à¤›à¥¤ तपाईले कि डाउनलोड गरà¥à¤¨à¥à¤à¤à¤•ो पà¥à¤¯à¤¾à¤•ेज पà¥à¤¨: खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ कि <a href="https://www.dokuwiki.org/install">Dokuwiki सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ विधि</a>'; $lang['i_funcna'] = 'PHP function <code>%s</code> उपलवà¥à¤§ छैन । हà¥à¤¨à¤¸à¤•à¥à¤› तपाईको होसà¥à¤Ÿà¤¿à¤™à¥à¤— पà¥à¤°à¤¦à¤¾à¤¯à¤•ले कà¥à¤¨à¥ˆ कारण वश यसलाई वनà¥à¤¦ गरिदिà¤à¤•ा हà¥à¤¨à¤¸à¤•à¥à¤›à¤¨à¥ । '; $lang['i_phpver'] = 'तपाईको PHP संसà¥à¤•रण <code>%s</code> चाहिà¤à¤•ो <code>%s</code> à¤à¤¨à¥à¤¦à¤¾ कम छ। तपाईले आफà¥à¤¨à¥‹ PHP सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ अधà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¨à¥à¤ªà¤°à¥à¤› ।'; $lang['i_permfail'] = '<code>%s</code> DokuWiki दà¥à¤µà¤¾à¤°à¤¾ लेखà¥à¤¯ छैन । तपाईले डाइरेकà¥à¤Ÿà¤°à¥€à¤•ो अनà¥à¤®à¤¤à¤¿ परिवरà¥à¤¤à¤¨ गरà¥à¤¨à¥à¤ªà¤°à¥à¤› !'; diff --git a/inc/lang/nl/lang.php b/inc/lang/nl/lang.php index f799318c3..58cd7096c 100644 --- a/inc/lang/nl/lang.php +++ b/inc/lang/nl/lang.php @@ -3,11 +3,11 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Mark Prins <mprins@users.sf.net> * @author PBU <pbu@xs4all.nl> * @author Gerrit Uitslag <klapinklapin@gmail.com> * @author Andy <astolker@icloud.com> * @author Harriet Neitz <harrietneitz@gmail.com> - * @author mark prins <mprins@users.sf.net> * @author François Kooman <fkooman.tuxed.net> * @author Jack van Klaren <dokuwiki@afentoe.xs4all.nl> * @author Riny Heijdendael <riny@heijdendael.nl> @@ -239,7 +239,7 @@ $lang['created'] = 'aangemaakt'; $lang['restored'] = 'oude revisie hersteld (%s)'; $lang['external_edit'] = 'Externe bewerking'; $lang['summary'] = 'Samenvatting wijziging'; -$lang['noflash'] = 'De <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> is vereist om de pagina te kunnen weergeven.'; +$lang['noflash'] = 'De <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> is vereist om de pagina te kunnen weergeven.'; $lang['download'] = 'Download fragment'; $lang['tools'] = 'Hulpmiddelen'; $lang['user_tools'] = 'Gebruikershulpmiddelen'; @@ -319,7 +319,7 @@ $lang['i_wikiname'] = 'Wikinaam'; $lang['i_enableacl'] = 'ACLs inschakelen (aanbevolen)'; $lang['i_superuser'] = 'Superuser'; $lang['i_problems'] = 'De installer vond problemen, hieronder aangegeven. Verhelp deze voor je doorgaat.'; -$lang['i_modified'] = 'Uit veiligheidsoverwegingen werkt dit script alleen met nieuwe en onveranderde DokuWiki-installaties. Pak de bestanden opnieuw uit of raadpleeg de <a href="http://dokuwiki.org/install">Dokuwiki installatie-instructies</a>'; +$lang['i_modified'] = 'Uit veiligheidsoverwegingen werkt dit script alleen met nieuwe en onveranderde DokuWiki-installaties. Pak de bestanden opnieuw uit of raadpleeg de <a href="https://www.dokuwiki.org/install">Dokuwiki installatie-instructies</a>'; $lang['i_funcna'] = 'PHP functie <code>%s</code> is niet beschikbaar. Wellicht heeft je hosting provider deze uitgeschakeld?'; $lang['i_phpver'] = 'PHP-versie <code>%s</code> is lager dan de vereiste <code>%s</code>. Upgrade PHP.'; $lang['i_mbfuncoverload'] = 'Om DokuWiki te draaien moet mbstring.func_overload uitgeschakeld zijn in php.ini.'; @@ -373,6 +373,7 @@ $lang['media_perm_upload'] = 'Sorry, u heeft niet voldoende rechten om besta $lang['media_update'] = 'Upload nieuwe versie'; $lang['media_restore'] = 'Deze versie terugzetten'; $lang['media_acl_warning'] = 'De lijst is mogelijk niet compleet door ACL beperkingen en verborgen pagina\'s.'; +$lang['email_fail'] = 'PHP mail() ontbreekt of is uitgeschakeld. De volgende e-mail is niet verzonden:'; $lang['currentns'] = 'Huidige namespace'; $lang['searchresult'] = 'Zoekresultaat'; $lang['plainhtml'] = 'Alleen HTML'; diff --git a/inc/lang/no/lang.php b/inc/lang/no/lang.php index 0b4cd8629..ccdb10d66 100644 --- a/inc/lang/no/lang.php +++ b/inc/lang/no/lang.php @@ -228,7 +228,7 @@ $lang['created'] = 'opprettet'; $lang['restored'] = 'gjenopprettet til en tidligere versjon (%s)'; $lang['external_edit'] = 'ekstern redigering'; $lang['summary'] = 'Redigeringskommentar'; -$lang['noflash'] = 'For at dette innholdet skal vises mÃ¥ du ha <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'For at dette innholdet skal vises mÃ¥ du ha <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'Last ned utdraget'; $lang['tools'] = 'Verktøy'; $lang['user_tools'] = 'Brukerverktøy'; @@ -310,7 +310,7 @@ $lang['i_superuser'] = 'Superbruker'; $lang['i_problems'] = 'Installasjonen oppdaget noen problemer, disse listes nedenfor. Du kan ikke fortsett før du har løst disse.'; $lang['i_modified'] = 'For sikkerhets skyld vil dette skriptet bare virke med en ny og uendret Dokuwiki-installsjon. Du bør enten pakke ut filene pÃ¥ nytt fra den nedlastede pakken, eller konsultere den komplette - <a href="http://dokuwiki.org/install">Dokuwiki-installasjonsinstruksen</a>'; + <a href="https://www.dokuwiki.org/install">Dokuwiki-installasjonsinstruksen</a>'; $lang['i_funcna'] = 'PHP-funksjonen <code>%s</code> er ikke tilgjengelig. Kanskje din nettleverandør har deaktivert denne?'; $lang['i_phpver'] = 'Din PHP versjon <code>%s</code> er lavere enn kravet <code>%s</code>. Du mÃ¥ oppgradere PHP installasjonen. '; $lang['i_mbfuncoverload'] = 'mbstring.func_overload mÃ¥ deaktiveres i php.ini for Ã¥ kjøre DokuWiki.'; diff --git a/inc/lang/pl/lang.php b/inc/lang/pl/lang.php index 40f0641b4..1148bed59 100644 --- a/inc/lang/pl/lang.php +++ b/inc/lang/pl/lang.php @@ -233,7 +233,7 @@ $lang['created'] = 'utworzono'; $lang['restored'] = 'przywrócono poprzedniÄ… wersjÄ™ (%s)'; $lang['external_edit'] = 'edycja zewnÄ™trzna'; $lang['summary'] = 'Opis zmian'; -$lang['noflash'] = 'Plugin <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> jest niezbÄ™dny do obejrzenia tej zawartoÅ›ci.'; +$lang['noflash'] = 'Plugin <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> jest niezbÄ™dny do obejrzenia tej zawartoÅ›ci.'; $lang['download'] = 'Pobierz zrzut'; $lang['tools'] = 'NarzÄ™dzia'; $lang['user_tools'] = 'NarzÄ™dzia użytkownika'; @@ -314,7 +314,7 @@ $lang['i_enableacl'] = 'Włącz mechanizm uprawnieÅ„ ACL (zalecane)'; $lang['i_superuser'] = 'Administrator'; $lang['i_problems'] = 'Instalator napotkaÅ‚ poniższe problemy. Nie można kontynuować póki nie zostanÄ… usuniÄ™te.'; $lang['i_modified'] = 'Ze wzglÄ™dów bezpieczeÅ„stwa, ten skrypt dziaÅ‚a tylko z nowÄ… i niezmodyfikowanÄ… instalacjÄ… DokuWiki. -Aby uruchomić instalator ponownie, rozpakuj archiwum DokuWiki lub zapoznaj siÄ™ z <a href="http://dokuwiki.org/install">instrukcjÄ… instalacji Dokuwiki</a>'; +Aby uruchomić instalator ponownie, rozpakuj archiwum DokuWiki lub zapoznaj siÄ™ z <a href="https://www.dokuwiki.org/install">instrukcjÄ… instalacji Dokuwiki</a>'; $lang['i_funcna'] = 'Funkcja PHP <code>%s</code> jest niedostÄ™pna.'; $lang['i_disabled'] = 'To zostaÅ‚o wyłączone przez twojego dostawcÄ™.'; $lang['i_phpver'] = 'Wersja PHP <code>%s</code> jest niższa od wymaganej <code>%s</code>. Zaktualizuj instalacjÄ™ PHP.'; diff --git a/inc/lang/pt-br/lang.php b/inc/lang/pt-br/lang.php index 620941b8f..ae5c75f60 100644 --- a/inc/lang/pt-br/lang.php +++ b/inc/lang/pt-br/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Eduardo Mozart de Oliveira <eduardomozart182@gmail.com> * @author ANDRE BASSANI DE FREITAS <dedebf@gmail.com> * @author Aleksandr Selivanov <alexgearbox@yandex.ru> * @author Davi Jorge <davimoises2015@hotmail.com> @@ -135,6 +136,7 @@ $lang['js']['media_done_btn'] = 'ConcluÃdo'; $lang['js']['media_drop'] = 'Arraste os arquivos até aqui para enviar'; $lang['js']['media_cancel'] = 'remover'; $lang['js']['media_overwrt'] = 'Sobrescrever arquivos existentes'; +$lang['js']['data_insecure'] = 'AVISO: Parece que seu diretório data não está corretamente seguro. Por favor, leia sobre <a href="https://www.dokuwiki.org/security#web_access_security">Web Access Security in DokuWiki</a>.'; $lang['search_exact_match'] = 'Correspondência exata'; $lang['search_starts_with'] = 'Começa com'; $lang['search_ends_with'] = 'Termina com'; @@ -237,7 +239,7 @@ $lang['created'] = 'criada'; $lang['restored'] = 'a revisão anterior foi restaurada (%s)'; $lang['external_edit'] = 'edição externa'; $lang['summary'] = 'Resumo da edição'; -$lang['noflash'] = 'O <a href="http://www.adobe.com/products/flashplayer/">plug-in Adobe Flash</a> é necessário para exibir este conteúdo.'; +$lang['noflash'] = 'O <a href="http://get.adobe.com/flashplayer">plug-in Adobe Flash</a> é necessário para exibir este conteúdo.'; $lang['download'] = 'Baixar o snippet'; $lang['tools'] = 'Ferramentas'; $lang['user_tools'] = 'Ferramentas do usuário'; @@ -318,7 +320,7 @@ $lang['i_enableacl'] = 'Habilitar Lista de Controle de Acessos (recome $lang['i_superuser'] = 'Superusuário'; $lang['i_problems'] = 'O instalador encontrou alguns problemas, indicados abaixo. Você não pode continuar até corrigi-los.'; $lang['i_modified'] = 'Por questões de segurança, esse script funcionará apenas em uma instalação nova e não modificada do DokuWiki. -Você pode extrair novamente os arquivos do pacote original ou consultar as <a href="http://dokuwiki.org/install">instruções de instalação do DokuWiki</a>.'; +Você pode extrair novamente os arquivos do pacote original ou consultar as <a href="https://www.dokuwiki.org/install">instruções de instalação do DokuWiki</a>.'; $lang['i_funcna'] = 'A função PHP <code>%s</code> não está disponÃvel. O seu host a mantém desabilitada por algum motivo?'; $lang['i_disabled'] = 'Foi desativado pelo seu provedor.'; $lang['i_funcnmail'] = '<b>Nota:</b> A função de correio PHP não está disponÃvel. %s Se permanecer indisponÃvel, você pode instalar o <a href="https://www.dokuwiki.org/plugin:smtp">plugin SMTP</a>.'; diff --git a/inc/lang/pt/lang.php b/inc/lang/pt/lang.php index f66cd23be..51a539e8d 100644 --- a/inc/lang/pt/lang.php +++ b/inc/lang/pt/lang.php @@ -228,7 +228,7 @@ $lang['created'] = 'criado'; $lang['restored'] = 'versão anterior restaurada (%s)'; $lang['external_edit'] = 'edição externa'; $lang['summary'] = 'Sumário da edição'; -$lang['noflash'] = 'O <a href="http://www.adobe.com/products/flashplayer/">Plugin Adobe Flash</a> é necessário para exibir este conteúdo.'; +$lang['noflash'] = 'O <a href="http://get.adobe.com/flashplayer">Plugin Adobe Flash</a> é necessário para exibir este conteúdo.'; $lang['download'] = 'Baixar Snippet'; $lang['tools'] = 'Ferramentas'; $lang['user_tools'] = 'Ferramentas de Usuário'; @@ -308,10 +308,10 @@ $lang['i_wikiname'] = 'Nome Wiki'; $lang['i_enableacl'] = 'Ativar ACL (recomendado)'; $lang['i_superuser'] = 'Superusuário'; $lang['i_problems'] = 'O instalador encontrou alguns problemas, indicados abaixo. Não pode continuar até que sejam corrigidos.'; -$lang['i_modified'] = 'Por razões de segurança, este script só funciona em novas e não-modificadas instalações do Dokuwiki. Você deve re-extrair os arquivos do pacote que baixou ou então consultar as <a href="http://dokuwiki.org/install">instruções de instalação do Dokuwiki</a>'; +$lang['i_modified'] = 'Por razões de segurança, este script só funciona em novas e não-modificadas instalações do Dokuwiki. Você deve re-extrair os arquivos do pacote que baixou ou então consultar as <a href="https://www.dokuwiki.org/install">instruções de instalação do Dokuwiki</a>'; $lang['i_funcna'] = 'A função PHP <code>%s</code> não está disponÃvel. Talvez o host a tenha desativado-a por alguma razão?'; $lang['i_disabled'] = 'Isso foi desativado pelo seu provedor.'; -$lang['i_funcnmail'] = '<b>Nota:</b> A função mail do PHP não está disponÃvel. %s Se ela permanecer indisponÃvel, instale o <a href="http://dokuwiki.org/plugins/smtp">plugin smtp</a>.'; +$lang['i_funcnmail'] = '<b>Nota:</b> A função mail do PHP não está disponÃvel. %s Se ela permanecer indisponÃvel, instale o <a href="https://www.dokuwiki.org/plugin:smtp">plugin smtp</a>.'; $lang['i_phpver'] = 'A versão de PHP actual <code>%s</code> é inferior à versão mÃnima <code>%s</code>. É preciso atualizar a instalação PHP.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload deve ser desativada no php.ini para executar o DokuWiki.'; $lang['i_urandom'] = 'DokuWiki não pode criar números criptograficamente seguros para cookies. Verifique a configuração open_basedir no php.ini para um acesso <code>/dev/urandom</code> adequado.'; diff --git a/inc/lang/ro/lang.php b/inc/lang/ro/lang.php index 756eb3cd7..4048f13ea 100644 --- a/inc/lang/ro/lang.php +++ b/inc/lang/ro/lang.php @@ -220,7 +220,7 @@ $lang['created'] = 'creat'; $lang['restored'] = 'versiune veche restaurată (%s)'; $lang['external_edit'] = 'editare externă'; $lang['summary'] = 'Editează sumarul'; -$lang['noflash'] = 'Plugin-ul <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> este necesar pentru afiÈ™area corectă a conÈ›inutului.'; +$lang['noflash'] = 'Plugin-ul <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> este necesar pentru afiÈ™area corectă a conÈ›inutului.'; $lang['download'] = 'Bloc descărcări'; $lang['tools'] = 'Unelte'; $lang['user_tools'] = 'Unelte utilizator'; @@ -301,7 +301,7 @@ $lang['i_enableacl'] = 'Activează ACL (liste de control a accesului) $lang['i_superuser'] = 'Utilizator privilegiat'; $lang['i_problems'] = 'Programul de instalare a găsit câteva probleme, indicate mai jos. Nu poÈ›i continua până nu le rezolvi.'; $lang['i_modified'] = 'Din motive de securitate, acest script va funcÈ›iona doar cu o instalare nouă È™i nemodificată a DokuWiki. -PoÈ›i fie să extragi din nou fiÈ™ierele din arhiva descărcată fie să consulÈ›i instrucÈ›iunile de instalare DokuWiki la <a href="http://dokuwiki.org/install">'; +PoÈ›i fie să extragi din nou fiÈ™ierele din arhiva descărcată fie să consulÈ›i instrucÈ›iunile de instalare DokuWiki la <a href="https://www.dokuwiki.org/install">'; $lang['i_funcna'] = 'FuncÈ›ia PHP <code>%s</code> nu este disponibilă. Probabil provider-ul tău a dezactivat-o pentru un motiv anume.'; $lang['i_disabled'] = 'a fost dezactivat de furnizorul tău'; $lang['i_funcnmail'] = '<b>Notă:</b> FuncÈ›ia PHP de email nu este disponibilă %s Daca tot rămâne nedisponibilă, trebuie sa instalezi <a href="https://www.dokuwiki.org/plugin:smtp">modulul stmp</a>. '; diff --git a/inc/lang/ru/lang.php b/inc/lang/ru/lang.php index ca41a04ee..2540a3315 100644 --- a/inc/lang/ru/lang.php +++ b/inc/lang/ru/lang.php @@ -248,7 +248,7 @@ $lang['created'] = 'Ñоздано'; $lang['restored'] = 'ÑÑ‚Ð°Ñ€Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ð²Ð¾ÑÑтановлена (%s)'; $lang['external_edit'] = 'внешнее изменение'; $lang['summary'] = 'Сводка изменений'; -$lang['noflash'] = 'Ð”Ð»Ñ Ð¿Ñ€Ð¾Ñмотра Ñтого Ñодержимого требуетÑÑ <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'Ð”Ð»Ñ Ð¿Ñ€Ð¾Ñмотра Ñтого Ñодержимого требуетÑÑ <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'Скачать фрагмент кода'; $lang['tools'] = 'ИнÑтрументы'; $lang['user_tools'] = 'ИнÑтрументы пользователÑ'; diff --git a/inc/lang/sk/lang.php b/inc/lang/sk/lang.php index 863fd6450..39af572ee 100644 --- a/inc/lang/sk/lang.php +++ b/inc/lang/sk/lang.php @@ -221,7 +221,7 @@ $lang['created'] = 'vytvorené'; $lang['restored'] = 'stará verzia bola obnovená (%s)'; $lang['external_edit'] = 'externá úprava'; $lang['summary'] = 'Komentár k úpravám'; -$lang['noflash'] = 'Pre zobrazenie tohto obsahu potrebujete <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'Pre zobrazenie tohto obsahu potrebujete <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'StiahnuÅ¥'; $lang['tools'] = 'Nástroje'; $lang['user_tools'] = 'Nástroje použÃvateľa'; @@ -301,7 +301,7 @@ $lang['i_wikiname'] = 'Názov Wiki'; $lang['i_enableacl'] = 'AktivovaÅ¥ ACL (doporuÄené)'; $lang['i_superuser'] = 'Správca'; $lang['i_problems'] = 'InÅ¡talátor narazil na nižšie uvedené problémy. Nemôžete pokraÄovaÅ¥, pokiaľ ich neodstránite.'; -$lang['i_modified'] = 'Z bezpeÄnostných dôvodov bude tento skript fungovaÅ¥ iba s novou, neupravenou inÅ¡taláciou Dokuwiki. Môžete buÄ znovu rozbaliÅ¥ stiahnutý inÅ¡talaÄný balÃk alebo preÅ¡tudovaÅ¥ <a href="http://dokuwiki.org/install"> inÅ¡talaÄné inÅ¡trukcie Dokuwiki</a>'; +$lang['i_modified'] = 'Z bezpeÄnostných dôvodov bude tento skript fungovaÅ¥ iba s novou, neupravenou inÅ¡taláciou Dokuwiki. Môžete buÄ znovu rozbaliÅ¥ stiahnutý inÅ¡talaÄný balÃk alebo preÅ¡tudovaÅ¥ <a href="https://www.dokuwiki.org/install"> inÅ¡talaÄné inÅ¡trukcie Dokuwiki</a>'; $lang['i_funcna'] = 'PHP funkcia <code>%s</code> nie je dostupná. Je možné, že ju z urÄitých dôvodov zablokoval váš poskytovateľ webhostingu?'; $lang['i_funcnmail'] = '<b>Note:</b> PHP mail funkcia nie je dostupná. %s Ak zostáva stále nedostupná, možno by ste mohli nainÅ¡talovaÅ¥ <a href="https://www.dokuwiki.org/plugin:smtp">smtp plugin</a>.'; $lang['i_phpver'] = 'VaÅ¡a verzia PHP <code>%s</code> je nižšia ako požadovaná <code>%s</code>. Potrebujete aktualizovaÅ¥ VaÅ¡u inÅ¡taláciu PHP.'; diff --git a/inc/lang/sl/lang.php b/inc/lang/sl/lang.php index 913fb5e97..87b372423 100644 --- a/inc/lang/sl/lang.php +++ b/inc/lang/sl/lang.php @@ -196,7 +196,7 @@ $lang['created'] = 'ustvarjena'; $lang['restored'] = 'povrnjena stara razliÄica (%s)'; $lang['external_edit'] = 'urejanje v zunanjem urejevalniku'; $lang['summary'] = 'Povzetek urejanja'; -$lang['noflash'] = 'Za prikaz vsebine je treba namestiti <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>'; +$lang['noflash'] = 'Za prikaz vsebine je treba namestiti <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>'; $lang['download'] = 'Naloži izrezek'; $lang['tools'] = 'Orodja'; $lang['user_tools'] = 'UporabniÅ¡ka orodja'; @@ -276,7 +276,7 @@ $lang['i_wikiname'] = 'Ime Wiki spletiÅ¡Äa'; $lang['i_enableacl'] = 'OmogoÄi ACL (priporoÄeno)'; $lang['i_superuser'] = 'Skrbnik'; $lang['i_problems'] = 'Namestilnik je naletel na težave, ki so izpisane spodaj. Namestitve ni mogoÄe nadaljevati, dokler težave ne bodo odpravljene.'; -$lang['i_modified'] = 'Iz varnostnih razlogov skript deluje le v novi in neprilagojeni namestitvi sistema DokuWiki. Postopek namestitve je treba zaÄeti znova ali pa sistem namestiti roÄno s pomoÄjo <a href="http://dokuwiki.org/install">navodil nameÅ¡Äanja Dokuwiki</a>.'; +$lang['i_modified'] = 'Iz varnostnih razlogov skript deluje le v novi in neprilagojeni namestitvi sistema DokuWiki. Postopek namestitve je treba zaÄeti znova ali pa sistem namestiti roÄno s pomoÄjo <a href="https://www.dokuwiki.org/install">navodil nameÅ¡Äanja Dokuwiki</a>.'; $lang['i_funcna'] = 'Funkcija PHP <code>%s</code> ni na voljo. Morda je možnost na strežniku zaradi varnostnih razlogov onemogoÄena.'; $lang['i_phpver'] = 'RazliÄica PHP <code>%s</code> je nižja od zahtevane razliÄice <code>%s</code>. Pred nadaljevanjem je treba posodobiti namestitev PHP.'; $lang['i_permfail'] = 'Predmet <code>%s</code> ni zapisljiv. Zahtevana je sprememba dovoljenj za to mapo.'; diff --git a/inc/lang/sq/lang.php b/inc/lang/sq/lang.php index f82c2ad8e..0343fde18 100644 --- a/inc/lang/sq/lang.php +++ b/inc/lang/sq/lang.php @@ -159,7 +159,7 @@ $lang['created'] = 'u krijua'; $lang['restored'] = 'Kthehu tek një version i vjetër (%s)'; $lang['external_edit'] = 'redaktim i jashtëm'; $lang['summary'] = 'Përmbledhja redaktimit'; -$lang['noflash'] = 'Nevojitet <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> për të paraqitur këtë përmbajtje.'; +$lang['noflash'] = 'Nevojitet <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> për të paraqitur këtë përmbajtje.'; $lang['download'] = 'Shkarko Copën'; $lang['mail_newpage'] = 'faqje u shtua:'; $lang['mail_changed'] = 'faqja u ndryshua:'; @@ -226,7 +226,7 @@ $lang['i_enableacl'] = 'Aktivizo ACL (rekomanduar)'; $lang['i_superuser'] = 'Superpërdorues'; $lang['i_problems'] = 'Installer-i gjeti disa probleme, të shfaqura më poshtë. Nuk mund të vazhdoni derisa t\'i keni rregulluar.'; $lang['i_modified'] = 'Për arsye sigurie ky skript do të punojë vetëm me një instalim të ri dhe të pamodifikuar DokuWiki. -Ose duhet të ekstraktoni skedarët nga e para nga pakoja e shkarkimit ose konsultohuni me <a href="http://dokuwiki.org/install">Dokuwiki installation instructions</a>'; +Ose duhet të ekstraktoni skedarët nga e para nga pakoja e shkarkimit ose konsultohuni me <a href="https://www.dokuwiki.org/install">Dokuwiki installation instructions</a>'; $lang['i_funcna'] = 'Funksioni PHP <code>%s</code> nuk është i disponueshëm. Mbase siguruesi juaj i host-it e ka çaktivizuar për ndonjë arsye?'; $lang['i_phpver'] = 'Versioni juaj i PHP <code>%s</code> është më i vogël se ai i duhuri <code>%s</code>. Duhet të përditësoni instalimin tuaj të PHP-së.'; $lang['i_permfail'] = '<code>%s</code> nuk është e shkruajtshme nga DokuWiki. Duhet të rregulloni lejet e përdorimit për këtë direktori.'; diff --git a/inc/lang/sr/lang.php b/inc/lang/sr/lang.php index 522002386..c34e42457 100644 --- a/inc/lang/sr/lang.php +++ b/inc/lang/sr/lang.php @@ -216,7 +216,7 @@ $lang['created'] = 'направљено'; $lang['restored'] = 'Ñтара верзија повраћена (%s)'; $lang['external_edit'] = 'Ñпољна измена'; $lang['summary'] = 'Сажетак измене'; -$lang['noflash'] = 'За приказивање ове врÑте материјала потребан вам је <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'За приказивање ове врÑте материјала потребан вам је <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'Преузми Ñнипет'; $lang['tools'] = 'Ðлатке'; $lang['user_tools'] = 'КориÑничке алатке'; @@ -296,7 +296,7 @@ $lang['i_wikiname'] = 'Ðазив викија'; $lang['i_enableacl'] = 'Укључи '; $lang['i_superuser'] = 'СуперкориÑник'; $lang['i_problems'] = 'ИнÑталација је наишла на проблеме који Ñу навадени у текÑту иÑпод. Ðе можете наÑтавити даље док их не иÑправите.'; -$lang['i_modified'] = 'Из ÑигурноÑних разлога ова Ñкрипта ради Ñамо Ñа новом Dokuwiki инÑталацијом. Требало би или да опет раÑпакујете архиву преузету Ñа Ñајта или да погледате <a href="http://dokuwiki.org/install">Dokuwiki инÑтрукције за инÑталацију</a>'; +$lang['i_modified'] = 'Из ÑигурноÑних разлога ова Ñкрипта ради Ñамо Ñа новом Dokuwiki инÑталацијом. Требало би или да опет раÑпакујете архиву преузету Ñа Ñајта или да погледате <a href="https://www.dokuwiki.org/install">Dokuwiki инÑтрукције за инÑталацију</a>'; $lang['i_funcna'] = 'ПХП функција <code>%s</code> није доÑтупна. Можда је Ваш хоÑтинг провајдер забранио из неког разлога?'; $lang['i_phpver'] = '<code>%s</code> Верзија Вашег ПХПа је нижа од неопходне <code>%s</code>. Требало би да надоградите ПХП инÑталацију.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload мора бити иÑкључен у датотеци php.ini да биÑте кориÑтили Докувики.'; diff --git a/inc/lang/sv/lang.php b/inc/lang/sv/lang.php index f26071c5d..8b91424ba 100644 --- a/inc/lang/sv/lang.php +++ b/inc/lang/sv/lang.php @@ -227,7 +227,7 @@ $lang['created'] = 'skapad'; $lang['restored'] = 'tidigare version Ã¥terställd (%s)'; $lang['external_edit'] = 'extern redigering'; $lang['summary'] = 'Redigeringskommentar'; -$lang['noflash'] = '<a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> behövs för att visa detta innehÃ¥ll.'; +$lang['noflash'] = '<a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> behövs för att visa detta innehÃ¥ll.'; $lang['download'] = 'Ladda ner kodfragmentet'; $lang['tools'] = 'Verktyg'; $lang['user_tools'] = 'Användarverktyg'; @@ -309,7 +309,7 @@ $lang['i_superuser'] = 'Användarnamn för administratören'; $lang['i_problems'] = 'Installationsprogrammet hittade nÃ¥gra problem som visas nedan. Du kan inte fortsätta innan du har fixat dem.'; $lang['i_modified'] = 'Av säkerhetsskäl fungerar det här skriptet bara med en ny och omodifierad installation av Dokuwiki. Du fÃ¥r antingen packa upp det nedladdade paketet pÃ¥ nytt, eller konsultera de kompletta - <a href="http://dokuwiki.org/install">instruktionerna för installation av Dokuwiki</a>'; + <a href="https://www.dokuwiki.org/install">instruktionerna för installation av Dokuwiki</a>'; $lang['i_funcna'] = 'PHP-funktionen <code>%s</code> är inte tillgänglig. Kanske ditt webbhotell har avaktiverat den av nÃ¥gon anledning?'; $lang['i_disabled'] = 'Det är avstängt av din leverantör.'; $lang['i_funcnmail'] = '<b>Note:</b> PHP mail funktionen är inte tillgänglig. %s Om det är fortsatt otillgängligt kan du installera <a href="https://www.dokuwiki.org/plugin:smtp">smtp pluginet</a>'; diff --git a/inc/lang/th/lang.php b/inc/lang/th/lang.php index aa87977a1..62ee10603 100644 --- a/inc/lang/th/lang.php +++ b/inc/lang/th/lang.php @@ -215,7 +215,7 @@ $lang['created'] = 'ถูà¸à¸ªà¸£à¹‰à¸²à¸‡'; $lang['restored'] = 'ย้à¸à¸™à¹„ปรุ่นà¸à¹ˆà¸à¸™à¸«à¸™à¹‰à¸² (%s)'; $lang['external_edit'] = 'à¹à¸à¹‰à¹„ขภายนà¸à¸'; $lang['summary'] = 'สรุป(หมายเหตุ)à¸à¸²à¸£à¹à¸à¹‰à¹„ขนี้'; -$lang['noflash'] = 'ต้à¸à¸‡à¸à¸²à¸£à¸•ัวเล่นà¹à¸Ÿà¸¥à¸Š <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> เพื่à¸à¹à¸ªà¸”งผลเนื้à¸à¸«à¸²à¸™à¸µà¹‰'; +$lang['noflash'] = 'ต้à¸à¸‡à¸à¸²à¸£à¸•ัวเล่นà¹à¸Ÿà¸¥à¸Š <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> เพื่à¸à¹à¸ªà¸”งผลเนื้à¸à¸«à¸²à¸™à¸µà¹‰'; $lang['download'] = 'ดาวน์โหลดสนิปเป็ด(Snippet)'; $lang['tools'] = 'เครื่à¸à¸‡à¸¡à¸·à¸'; $lang['user_tools'] = 'เครื่à¸à¸‡à¸¡à¸·à¸à¸ªà¸³à¸«à¸£à¸±à¸šà¸œà¸¹à¹‰à¹ƒà¸Šà¹‰'; @@ -284,7 +284,7 @@ $lang['i_superuser'] = 'ซุปเปà¸à¸£à¹Œà¸¢à¸¹à¸ªà¹€à¸‹à¸à¸£à $lang['i_problems'] = 'ตัวติดตั้งพบปัà¸à¸«à¸²à¸šà¸²à¸‡à¸›à¸£à¸°à¸à¸²à¸£ ตามที่ระบุด้านล่าง คุณไม่สามารถทำต่à¸à¹„ด้จนà¸à¸§à¹ˆà¸²à¸ˆà¸°à¹„ด้à¹à¸à¹‰à¹„ขสิ่งเหล่านั้น'; $lang['i_modified'] = 'ด้วยเหตุผลด้านความปลà¸à¸”ภัย สคริปต์นี้จะทำงานà¸à¸±à¸šà¹€à¸‰à¸žà¸²à¸°à¹‚ดà¸à¸¸à¸§à¸´à¸à¸´à¸—ี่ติดตั้งใหม่หรืà¸à¸¢à¸±à¸‡à¹„ม่ได้ดัดà¹à¸›à¸¥à¸‡à¹à¸à¹‰à¹„ข คุณควรเลืà¸à¸à¸£à¸°à¸«à¸§à¹ˆà¸²à¸‡à¸„ลี่ไฟล์จาà¸à¹à¸žà¸„เà¸à¸ˆà¸—ี่ได้ดาวน์โหลดมาà¸à¸µà¸à¸„รั้ง หรืà¸à¸¨à¸¶à¸à¸©à¸²à¸ˆà¸²à¸à¸„ู่มืภ-<a href="http://dokuwiki.org/install">Dokuwiki installation instructions</a>'; +<a href="https://www.dokuwiki.org/install">Dokuwiki installation instructions</a>'; $lang['i_funcna'] = 'PHP function <code>%s</code> ไม่สามารถใช้งานได้ à¸à¸²à¸ˆà¹€à¸›à¹‡à¸™à¹€à¸žà¸£à¸²à¸°à¸œà¸¹à¹‰à¹ƒà¸«à¹‰à¸šà¸£à¸´à¸à¸²à¸£à¹‚ฮสไม่เปิดให้ใช้งาน'; $lang['i_phpver'] = 'PHP รุ่นที่คุณà¸à¸³à¸¥à¸±à¸‡à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸à¸¢à¸¹à¹ˆà¸„ืภ<code>%s</code> คุณจำเป็นต้à¸à¸‡à¸à¸±à¸žà¹€à¸à¸£à¸” PHP ให้เป็นรุ่น <code>%s</code> หรืà¸à¸ªà¸¹à¸‡à¸à¸§à¹ˆà¸²'; $lang['i_permfail'] = '<code>%s</code> DokuWiki ไม่สามารถเขียนข้à¸à¸¡à¸¹à¸¥à¹„ด้ ต้à¸à¸‡à¸•ั้งค่าสิทธิ์à¸à¸²à¸£à¸à¸™à¸¸à¸à¸²à¸•ขà¸à¸‡à¹„ดเรคทà¸à¸£à¸µà¸™à¸µà¹‰à¹€à¸ªà¸µà¸¢à¸à¹ˆà¸à¸™!'; diff --git a/inc/lang/tr/lang.php b/inc/lang/tr/lang.php index e93af031f..5521e4245 100644 --- a/inc/lang/tr/lang.php +++ b/inc/lang/tr/lang.php @@ -222,7 +222,7 @@ $lang['created'] = 'oluÅŸturuldu'; $lang['restored'] = 'eski sürüme dönüldü (%s)'; $lang['external_edit'] = 'Dışarıdan düzenle'; $lang['summary'] = 'Özeti düzenle'; -$lang['noflash'] = 'Bu içeriÄŸi göstermek için <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Eklentisi</a> gerekmektedir.'; +$lang['noflash'] = 'Bu içeriÄŸi göstermek için <a href="http://get.adobe.com/flashplayer">Adobe Flash Eklentisi</a> gerekmektedir.'; $lang['download'] = 'Parçacığı indir'; $lang['tools'] = 'Alet'; $lang['user_tools'] = 'Kullanıcı Aletleri'; @@ -302,7 +302,7 @@ $lang['i_wikiname'] = 'Wiki Adı'; $lang['i_enableacl'] = 'ACL\'yi etkinleÅŸtir (tavsiye edilir)'; $lang['i_superuser'] = 'Ana Kullanıcı'; $lang['i_problems'] = 'Kurulum sihirbazı aÅŸağıda gösterilen sorunları buldu. Bunları düzeltmeden devam etmeniz mümkün deÄŸil.'; -$lang['i_modified'] = 'Güzenlik sebebiyle bu script sadece yeni ve deÄŸiÅŸtirilmemiÅŸ bir Dokuwiki kurulumunda çalışır. Ya indirdiÄŸiniz paketi yeniden açmalı ya da <a href="http://dokuwiki.org/install"> adresindeki Dokuwiki kurulum kılavuzu</a>na bakmalısınız.'; +$lang['i_modified'] = 'Güzenlik sebebiyle bu script sadece yeni ve deÄŸiÅŸtirilmemiÅŸ bir Dokuwiki kurulumunda çalışır. Ya indirdiÄŸiniz paketi yeniden açmalı ya da <a href="https://www.dokuwiki.org/install"> adresindeki Dokuwiki kurulum kılavuzu</a>na bakmalısınız.'; $lang['i_funcna'] = '<code>%s</code> PHP fonksiyonu bulunmamaktadır. Barındırma(Hosting) hizmetinde bu özellik kapatılmış olabilir.'; $lang['i_disabled'] = 'SaÄŸlayıcınız tarafından devre dışı bırakılmış.'; $lang['i_phpver'] = '<code>%s</code> PHP sürümü, gereken <code>%s</code> sürümünden daha düşük. PHP kurulumunu yükseltmeniz gerekmektedir.'; diff --git a/inc/lang/uk/lang.php b/inc/lang/uk/lang.php index 2b7784409..3ebdb3f4e 100644 --- a/inc/lang/uk/lang.php +++ b/inc/lang/uk/lang.php @@ -224,7 +224,7 @@ $lang['created'] = 'Ñтворено'; $lang['restored'] = 'відновлено Ñтару ревізію (%s)'; $lang['external_edit'] = 'зовнішнє редагуваннÑ'; $lang['summary'] = 'ПідÑумок змін'; -$lang['noflash'] = 'Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цієї Ñторінки необхідно вÑтановити <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a>.'; +$lang['noflash'] = 'Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду цієї Ñторінки необхідно вÑтановити <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a>.'; $lang['download'] = 'Завантажити фрагмент'; $lang['tools'] = 'ÐалаштуваннÑ'; $lang['user_tools'] = 'КориÑтувальницькькі налаштуваннÑ'; @@ -305,7 +305,7 @@ $lang['i_enableacl'] = 'Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ AC $lang['i_superuser'] = 'СуперкориÑтувач'; $lang['i_problems'] = 'Програма уÑтановки знайшла декілька проблем, що вказані нижче. Ви не можете продовжити, поки не виправите Ñ—Ñ…'; $lang['i_modified'] = 'З причин безпеки цей Ñкрипт буде працювати тільки з новою та немодифікованою уÑтановкою ДокуВікі. -Вам Ñлід або ще раз розпакувати файли із завантаженого пакету, або звернутиÑÑ Ð´Ð¾ повної <a href="http://dokuwiki.org/install">інÑтрукції з уÑтановки ДокуВікі</a>'; +Вам Ñлід або ще раз розпакувати файли із завантаженого пакету, або звернутиÑÑ Ð´Ð¾ повної <a href="https://www.dokuwiki.org/install">інÑтрукції з уÑтановки ДокуВікі</a>'; $lang['i_funcna'] = 'Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ PHP <code>%s</code> не доÑтупна. Можливо, хоÑтинг-провайдер відключив Ñ—Ñ— з ÑкихоÑÑŒ причин?'; $lang['i_phpver'] = 'ВерÑÑ–Ñ PHP <code>%s</code> менша, ніж необхідно - <code>%s</code>. Ðеобхідно оновити PHP.'; $lang['i_mbfuncoverload'] = 'mbstring.func_overload має бути вимкнена у php.ini щоб запуÑтити DokuWiki.'; diff --git a/inc/lang/vi/lang.php b/inc/lang/vi/lang.php index 455bd5639..2e17570c4 100644 --- a/inc/lang/vi/lang.php +++ b/inc/lang/vi/lang.php @@ -212,7 +212,7 @@ $lang['created'] = 'đã tạo'; $lang['restored'] = 'đã khôi phục phiên bản cÅ© (%s)'; $lang['external_edit'] = 'sá»a đổi bên ngoà i'; $lang['summary'] = 'Tóm lược sá»a đổi'; -$lang['noflash'] = 'Cần có <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash Plugin</a> má»›i có thể xem được ná»™i dung nà y.'; +$lang['noflash'] = 'Cần có <a href="http://get.adobe.com/flashplayer">Adobe Flash Plugin</a> má»›i có thể xem được ná»™i dung nà y.'; $lang['download'] = 'Tải xuống Ä‘oạn trÃch'; $lang['tools'] = 'Công cụ'; $lang['user_tools'] = 'Công cụ thà nh viên'; @@ -294,10 +294,10 @@ $lang['i_superuser'] = 'Siêu thà nh viên'; $lang['i_problems'] = 'Trình cà i đặt tìm thấy má»™t số vấn Ä‘á», được chỉ ra bên dưới. Bạn không thể tiếp tục cho đến khi bạn đã sá»a chúng.'; $lang['i_modified'] = 'Vì lý do bảo máºt, táºp lệnh nà y sẽ chỉ hoạt động vá»›i bản cà i đặt Dokuwiki má»›i và chưa được sá»a đổi. Bạn nên trÃch xuất lại các táºp tin từ gói đã tải xuống hoặc tham khảo - <a href="http://dokuwiki.org/install">Hướng dẫn cà i đặt Dokuwiki</a> đầy đủ'; + <a href="https://www.dokuwiki.org/install">Hướng dẫn cà i đặt Dokuwiki</a> đầy đủ'; $lang['i_funcna'] = 'Hà m PHP <code>%s</code> không có sẵn. Có lẽ nhà cung cấp dịch vụ lưu trữ cá»§a bạn đã vô hiệu hóa nó vì má»™t số lý do?'; $lang['i_disabled'] = 'Nó đã bị vô hiệu hóa bởi nhà cung cấp cá»§a bạn.'; -$lang['i_funcnmail'] = '<b>Lưu ý:</b> Không có sẵn hà m PHP mail. %s Nếu nó vẫn không có sẵn, bạn có thể cà i đặt <a href="http://dokuwiki.org/plugins/smtp">smtp plugin</a>.'; +$lang['i_funcnmail'] = '<b>Lưu ý:</b> Không có sẵn hà m PHP mail. %s Nếu nó vẫn không có sẵn, bạn có thể cà i đặt <a href="https://www.dokuwiki.org/plugin:smtp">smtp plugin</a>.'; $lang['i_phpver'] = 'Phiên bản PHP <code>%s</code> hiện taị thấp hÆ¡n mức <code>%s</code> cần thiết. Bạn cần nâng cấp cà i đặt PHP cá»§a bạn.'; $lang['i_mbfuncoverload'] = 'mbopes.func_overload phải bị vô hiệu trong php.ini để chạy DokuWiki.'; $lang['i_urandom'] = 'DokuWiki không thể tạo số máºt mã an toà n cho cookie. Bạn có thể muốn kiểm tra cà i đặt open_basingir trong php.ini để truy cáºp <code>/dev/urandom</code> thÃch hợp.'; diff --git a/inc/lang/zh-tw/lang.php b/inc/lang/zh-tw/lang.php index d90004dd0..9f4a128f0 100644 --- a/inc/lang/zh-tw/lang.php +++ b/inc/lang/zh-tw/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Chun-Chung Chen <cjj@u.washington.edu> * @author GHSRobert Ciang <robertus0617@gmail.com> * @author chinsan <chinsan@mail2000.com.tw> * @author Li-Jiun Huang <ljhuang.tw@gmail.com> @@ -76,6 +77,9 @@ $lang['badpassconfirm'] = '抱æ‰ï¼Œé€™å¯†ç¢¼æ˜¯éŒ¯çš„'; $lang['minoredit'] = 'å°ä¿®æ”¹'; $lang['draftdate'] = 'è‰ç¨¿å·²è‡ªå‹•å˜æª”æ–¼'; $lang['nosecedit'] = 'åœ¨æ‚¨ç·¨è¼¯æœŸé–“ï¼Œå…¶ä»–ä½¿ç”¨è€…ä¿®æ”¹éŽæœ¬é é¢ã€‚倿®µè³‡æ–™å·²é€¾æ™‚ï¼Œå› æ¤ç³»çµ±è¼‰å…¥äº†å…¨é ,以å–代之。'; +$lang['searchcreatepage'] = 'å¦‚æžœä½ æ²’æ‰¾åˆ°ä½ æ‰€å°‹æ‰¾çš„ï¼Œä½ å¯ä»¥ä»¥ä½ 的查詢為å,建立或編輯%sé é¢ã€‚'; +$lang['search_fullresults'] = 'å…¨æ–‡çµæžœ'; +$lang['js']['search_toggle_tools'] = 'åˆ‡æ›æœå°‹å·¥å…·'; $lang['js']['willexpire'] = '本é 的編輯鎖定將在一分é˜å…§åˆ°æœŸã€‚è¦é¿å…發生è¡çªï¼Œè«‹æŒ‰ã€Œé 覽ã€éµé‡è¨éŽ–å®šè¨ˆæ™‚ã€‚'; $lang['js']['notsavedyet'] = '未儲å˜çš„變更將會éºå¤±ï¼Œç¹¼çºŒå—Žï¼Ÿ'; $lang['js']['searchmedia'] = 'æœå°‹æª”案'; @@ -118,15 +122,24 @@ $lang['js']['media_done_btn'] = '完æˆ'; $lang['js']['media_drop'] = '拖拉檔案到æ¤ä¸Šå‚³'; $lang['js']['media_cancel'] = '刪除'; $lang['js']['media_overwrt'] = '覆蓋已å˜åœ¨çš„æª”案'; +$lang['js']['data_insecure'] = 'è¦å‘Šï¼šä¼¼ä¹Žä½ 的資料目錄沒有é©ç•¶çš„防è·ã€‚請閲讀關於<a href="https://www.dokuwiki.org/security#web_access_security">DokuWikiä¸çš„ç¶²é å˜å–安全性</a>。'; +$lang['search_exact_match'] = '精準的比å°'; +$lang['search_starts_with'] = 'èµ·å§‹æ–¼'; +$lang['search_ends_with'] = 'çµå°¾æ–¼'; +$lang['search_contains'] = '包å«'; +$lang['search_custom_match'] = '自定'; $lang['search_any_ns'] = '任何å稱空間'; $lang['search_any_time'] = '任何時間'; $lang['search_past_7_days'] = 'éŽå޻䏀週'; $lang['search_past_month'] = 'éŽåŽ»ä¸€å€‹æœˆ'; $lang['search_past_year'] = 'éŽå޻䏀年'; +$lang['search_sort_by_hits'] = '按點擊排åº'; +$lang['search_sort_by_mtime'] = '按最後修改排åº'; $lang['regmissing'] = '很抱æ‰ï¼Œæ‰€æœ‰æ¬„ä½éƒ½è¦å¡«å¯«ã€‚'; $lang['reguexists'] = '很抱æ‰ï¼Œæœ‰äººå·²ä½¿ç”¨äº†é€™å€‹å¸³è™Ÿã€‚'; $lang['regsuccess'] = '使用者帳號已建立,密碼已寄發至該電郵。'; $lang['regsuccess2'] = '使用者帳號已建立。'; +$lang['regfail'] = '無法建立使用者。'; $lang['regmailfail'] = '寄出密碼信似乎有å•題,請跟管ç†å“¡è¯çµ¡ï¼'; $lang['regbadmail'] = '您輸入的電郵地å€ä¼¼ä¹Žä¸æ£ç¢ºã€‚若您覺得是æ£ç¢ºçš„,請與管ç†å“¡è¯çµ¡ã€‚'; $lang['regbadpass'] = '兩次輸入的密碼ä¸ä¸€è‡´ï¼Œè«‹å†è©¦ä¸€æ¬¡ã€‚'; @@ -141,6 +154,7 @@ $lang['profdeleteuser'] = '刪除帳號'; $lang['profdeleted'] = '您的使用者帳號已從本 wiki 刪除'; $lang['profconfdelete'] = '我想把帳號從本 wiki 刪除(ä¸èƒ½å¾©åŽŸï¼‰'; $lang['profconfdeletemissing'] = '未勾é¸ç¢ºèªæ–¹å¡Š'; +$lang['proffail'] = '個人資料未更新。'; $lang['pwdforget'] = 'å¿˜è¨˜å¯†ç¢¼äº†ï¼Ÿç´¢å–æ–°å¯†ç¢¼ï¼'; $lang['resendna'] = '本 wiki 䏿”¯æ´é‡å¯„密碼。'; $lang['resendpwd'] = 'è¨å®šæ–°å¯†ç¢¼ä¾›'; @@ -157,6 +171,7 @@ $lang['txt_upload'] = 'è«‹é¸æ“‡è¦ä¸Šå‚³çš„æª”案:'; $lang['txt_filename'] = '請輸入è¦ä¸Šå‚³è‡³æœ¬ wiki 的檔案å稱 (éžå¿…è¦):'; $lang['txt_overwrt'] = '是å¦è¦è¦†è“‹åŽŸæœ‰æª”æ¡ˆ'; $lang['maxuploadsize'] = 'æ¯å€‹ä¸Šå‚³æª”案ä¸å¯å¤§æ–¼ %s 。'; +$lang['allowedmime'] = 'å…許的副檔å列表'; $lang['lockedby'] = 'ç›®å‰å·²è¢«ä¸‹åˆ—人員鎖定:'; $lang['lockexpire'] = 'é 計解除鎖定於:'; $lang['rssfailed'] = 'æ“·å– RSS 饋逿ª”時發生錯誤:'; @@ -200,6 +215,8 @@ $lang['diffprevrev'] = '剿¬¡ä¿®æ”¹ $lang['diffnextrev'] = '下次修改'; $lang['difflastrev'] = '最後一次修改 '; +$lang['diffbothprevrev'] = 'å…©é‚Šçš„å‰æ¬¡ä¿®è¨‚版'; +$lang['diffbothnextrev'] = '兩邊的下次修訂版'; $lang['line'] = '行'; $lang['breadcrumb'] = '足跡:'; $lang['youarehere'] = '您在這è£:'; @@ -210,7 +227,7 @@ $lang['created'] = '建立'; $lang['restored'] = '還原æˆèˆŠç‰ˆ (%s)'; $lang['external_edit'] = '外部編輯'; $lang['summary'] = '編輯摘è¦'; -$lang['noflash'] = '顯示æ¤å…§å®¹éœ€è¦ <a href="http://www.adobe.com/products/flashplayer/">Adobe Flash é™„åŠ å…ƒä»¶</a>。'; +$lang['noflash'] = '顯示æ¤å…§å®¹éœ€è¦ <a href="http://get.adobe.com/flashplayer">Adobe Flash é™„åŠ å…ƒä»¶</a>。'; $lang['download'] = '下載程å¼ç¢¼ç‰‡æ®µ'; $lang['tools'] = '工具'; $lang['user_tools'] = '使用者工具'; @@ -291,7 +308,7 @@ $lang['i_enableacl'] = '啟用 ACL (建è°)'; $lang['i_superuser'] = '超級使用者'; $lang['i_problems'] = '安è£ç¨‹å¼ç™¼ç¾å¦‚下的å•é¡Œã€‚æ‚¨å¿…é ˆä¿®æ£å®ƒå€‘æ‰èƒ½ç¹¼çºŒã€‚'; $lang['i_modified'] = '出於安全考é‡ï¼Œæœ¬è…³æœ¬åªèƒ½ç”¨æ–¼å®‰è£å…¨æ–°ä¸”未修改的 Dokuwiki。 -您å¯ä»¥é‡æ–°è§£å£“下載的å°åŒ…或查閱完整的<a href=\"http://dokuwiki.org/install\">Dokuwiki å®‰è£æŒ‡å—</a>'; +您å¯ä»¥é‡æ–°è§£å£“下載的å°åŒ…或查閱完整的<a href=\"https://www.dokuwiki.org/install\">Dokuwiki å®‰è£æŒ‡å—</a>'; $lang['i_funcna'] = 'PHP 函數 <code>%s</code> 無法使用。也許您的主機供應者基於æŸäº›ç†ç”±åœç”¨äº†å®ƒï¼Ÿ'; $lang['i_phpver'] = '您的 PHP 版本 <code>%s</code> 比需è¦çš„版本 <code>%s</code> é‚„ä½Žã€‚æ‚¨å¿…é ˆæ›´æ–°æ‚¨çš„PHP。'; $lang['i_permfail'] = '<code>%s</code> 無法經由 DokuWiki å¯«å…¥ã€‚æ‚¨å¿…é ˆä¿®æ£è©²ç›®éŒ„的權é™ï¼'; diff --git a/inc/load.php b/inc/load.php index 791f743d7..022ac014f 100644 --- a/inc/load.php +++ b/inc/load.php @@ -65,10 +65,6 @@ function load_autoload($name){ 'JpegMeta' => DOKU_INC.'inc/JpegMeta.php', 'SimplePie' => DOKU_INC.'inc/SimplePie.php', 'FeedParser' => DOKU_INC.'inc/FeedParser.php', - 'IXR_Server' => DOKU_INC.'inc/IXR_Library.php', - 'IXR_Client' => DOKU_INC.'inc/IXR_Library.php', - 'IXR_Error' => DOKU_INC.'inc/IXR_Library.php', - 'IXR_IntrospectionServer' => DOKU_INC.'inc/IXR_Library.php', 'SafeFN' => DOKU_INC.'inc/SafeFN.class.php', 'Sitemapper' => DOKU_INC.'inc/Sitemapper.php', 'Mailer' => DOKU_INC.'inc/Mailer.class.php', diff --git a/inc/media.php b/inc/media.php index 92e685b99..45824d556 100644 --- a/inc/media.php +++ b/inc/media.php @@ -7,11 +7,17 @@ */ use dokuwiki\ChangeLog\MediaChangeLog; -use dokuwiki\HTTP\DokuHTTPClient; -use dokuwiki\Subscriptions\MediaSubscriptionSender; use dokuwiki\Extension\Event; use dokuwiki\Form\Form; +use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Logger; +use dokuwiki\Subscriptions\MediaSubscriptionSender; +use dokuwiki\Ui\Media\DisplayRow; +use dokuwiki\Ui\Media\DisplayTile; +use dokuwiki\Ui\MediaDiff; +use dokuwiki\Utf8\PhpString; use dokuwiki\Utf8\Sort; +use splitbrain\slika\Slika; /** * Lists pages which currently use a media file selected for deletion @@ -181,7 +187,7 @@ function media_metaform($id, $auth) { if ($field[2] == 'text') { $form->addTextInput( $p['name'], - ($lang[$field[1]] ? $lang[$field[1]] : $field[1] . ':') + ($lang[$field[1]] ?: $field[1] . ':') )->id($p['id'])->addClass($p['class'])->val($value); } else { $form->addTextarea($p['name'], $lang[$field[1]])->id($p['id']) @@ -250,7 +256,7 @@ function media_delete($id,$auth){ // trigger an event - MEDIA_DELETE_FILE $data = array(); $data['id'] = $id; - $data['name'] = \dokuwiki\Utf8\PhpString::basename($file); + $data['name'] = PhpString::basename($file); $data['path'] = $file; $data['size'] = (file_exists($file)) ? filesize($file) : 0; @@ -312,7 +318,7 @@ function media_upload_xhr($ns,$auth){ 'mime' => $mime, 'ext' => $ext), $ns.':'.$id, - (($INPUT->get->str('ow') == 'true') ? true : false), + ($INPUT->get->str('ow') == 'true'), $auth, 'copy' ); @@ -567,11 +573,11 @@ function media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'mov * @param string $id * @return int - revision date */ -function media_saveOldRevision($id){ +function media_saveOldRevision($id) { global $conf, $lang; $oldf = mediaFN($id); - if(!file_exists($oldf)) return ''; + if (!file_exists($oldf)) return ''; $date = filemtime($oldf); if (!$conf['mediarevisions']) return $date; @@ -592,9 +598,9 @@ function media_saveOldRevision($id){ } } - $newf = mediaFN($id,$date); + $newf = mediaFN($id, $date); io_makeFileDir($newf); - if(copy($oldf, $newf)) { + if (copy($oldf, $newf)) { // Set the correct permission here. // Always chmod media because they may be saved with different permissions than expected from the php umask. // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) @@ -659,14 +665,13 @@ function media_contentcheck($file,$mime){ * @param string $file path to file * @param string $mime mime type * @param bool|int $old_rev revision timestamp or false - * @return bool */ function media_notify($id,$file,$mime,$old_rev=false,$current_rev=false){ global $conf; - if(empty($conf['notify'])) return false; //notify enabled? + if(empty($conf['notify'])) return; //notify enabled? $subscription = new MediaSubscriptionSender(); - return $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev); + $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev); } /** @@ -711,13 +716,13 @@ function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false,$sort=fals foreach($data as $item){ if (!$fullscreenview) { //FIXME old call: media_printfile($item,$auth,$jump); - $display = new \dokuwiki\Ui\Media\DisplayRow($item); + $display = new DisplayRow($item); $display->scrollIntoView($jump == $item->getID()); $display->show(); } else { //FIXME old call: media_printfile_thumbs($item,$auth,$jump); echo '<li>'; - $display = new \dokuwiki\Ui\Media\DisplayTile($item); + $display = new DisplayTile($item); $display->scrollIntoView($jump == $item->getID()); $display->show(); echo '</li>'; @@ -997,10 +1002,10 @@ function media_tab_history($image, $ns, $auth=null) { if ($auth >= AUTH_READ && $image) { if ($do == 'diff'){ - media_diff($image, $ns, $auth); + (new dokuwiki\Ui\MediaDiff($image))->show(); //media_diff($image, $ns, $auth); } else { $first = $INPUT->int('first'); - html_revisions($first, $image); + (new dokuwiki\Ui\MediaRevisions($image))->show($first); } } else { echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; @@ -1017,7 +1022,7 @@ function media_tab_history($image, $ns, $auth=null) { * * @author Kate Arzamastseva <pshns@ukr.net> */ -function media_preview($image, $auth, $rev='', $meta=false) { +function media_preview($image, $auth, $rev = '', $meta = false) { $size = media_image_preview_size($image, $rev, $meta); @@ -1041,7 +1046,7 @@ function media_preview($image, $auth, $rev='', $meta=false) { echo '<img src="'.$src.'" alt="" style="max-width: '.$size[0].'px;" />'; echo '</a>'; - echo '</div>'.NL; + echo '</div>'; } } @@ -1052,12 +1057,12 @@ function media_preview($image, $auth, $rev='', $meta=false) { * * @param string $image media id * @param int $auth permission level - * @param string|int $rev revision timestamp, or empty string + * @param int|string $rev revision timestamp, or empty string */ function media_preview_buttons($image, $auth, $rev = '') { global $lang, $conf; - echo '<ul class="actions">'.DOKU_LF; + echo '<ul class="actions">'; if ($auth >= AUTH_DELETE && !$rev && file_exists(mediaFN($image))) { @@ -1071,7 +1076,7 @@ function media_preview_buttons($image, $auth, $rev = '') { $form->addTagClose('div'); echo '<li>'; echo $form->toHTML(); - echo '</li>'.DOKU_LF; + echo '</li>'; } $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); @@ -1087,7 +1092,7 @@ function media_preview_buttons($image, $auth, $rev = '') { $form->addTagClose('div'); echo '<li>'; echo $form->toHTML(); - echo '</li>'.DOKU_LF; + echo '</li>'; } if ($auth >= AUTH_UPLOAD && $rev && $conf['mediarevisions'] && file_exists(mediaFN($image, $rev))) { @@ -1104,10 +1109,10 @@ function media_preview_buttons($image, $auth, $rev = '') { $form->addTagClose('div'); echo '<li>'; echo $form->toHTML(); - echo '</li>'.DOKU_LF; + echo '</li>'; } - echo '</ul>'.DOKU_LF; + echo '</ul>'; } /** @@ -1118,16 +1123,18 @@ function media_preview_buttons($image, $auth, $rev = '') { * @param int|string $rev * @param JpegMeta|bool $meta * @param int $size - * @return array|false + * @return array */ -function media_image_preview_size($image, $rev, $meta, $size = 500) { - if (!preg_match("/\.(jpe?g|gif|png)$/", $image) || !file_exists(mediaFN($image, $rev))) return false; +function media_image_preview_size($image, $rev, $meta = false, $size = 500) { + if (!preg_match("/\.(jpe?g|gif|png)$/", $image) + || !file_exists($filename = mediaFN($image, $rev)) + ) return array(); - $info = getimagesize(mediaFN($image, $rev)); + $info = getimagesize($filename); $w = (int) $info[0]; $h = (int) $info[1]; - if($meta && ($w > $size || $h > $size)){ + if ($meta && ($w > $size || $h > $size)) { $ratio = $meta->getResizeRatio($size, $size); $w = floor($w * $ratio); $h = floor($h * $ratio); @@ -1145,10 +1152,10 @@ function media_image_preview_size($image, $rev, $meta, $size = 500) { * @param string $alt alternative value * @return string */ -function media_getTag($tags,$meta,$alt=''){ - if($meta === false) return $alt; +function media_getTag($tags, $meta = false, $alt = '') { + if (!$meta) return $alt; $info = $meta->getField($tags); - if($info == false) return $alt; + if (!$info) return $alt; return $info; } @@ -1163,19 +1170,19 @@ function media_getTag($tags,$meta,$alt=''){ function media_file_tags($meta) { // load the field descriptions static $fields = null; - if(is_null($fields)){ + if (is_null($fields)) { $config_files = getConfigFiles('mediameta'); foreach ($config_files as $config_file) { - if(file_exists($config_file)) include($config_file); + if (file_exists($config_file)) include($config_file); } } $tags = array(); - foreach($fields as $key => $tag){ + foreach ($fields as $key => $tag) { $t = array(); if (!empty($tag[0])) $t = array($tag[0]); - if(isset($tag[3]) && is_array($tag[3])) $t = array_merge($t,$tag[3]); + if (isset($tag[3]) && is_array($tag[3])) $t = array_merge($t,$tag[3]); $value = media_getTag($t, $meta); $tags[] = array('tag' => $tag, 'value' => $value); } @@ -1233,80 +1240,22 @@ function media_details($image, $auth, $rev='', $meta=false) { * @param string $ns * @param int $auth permission level * @param bool $fromajax - * @return false|null|string + * + * @deprecated 2020-12-31 */ function media_diff($image, $ns, $auth, $fromajax = false) { - global $conf; - global $INPUT; - - if ($auth < AUTH_READ || !$image || !$conf['mediarevisions']) return ''; - - $rev1 = $INPUT->int('rev'); - - $rev2 = $INPUT->ref('rev2'); - if(is_array($rev2)){ - $rev1 = (int) $rev2[0]; - $rev2 = (int) $rev2[1]; - - if(!$rev1){ - $rev1 = $rev2; - unset($rev2); - } - }else{ - $rev2 = $INPUT->int('rev2'); - } - - if ($rev1 && !file_exists(mediaFN($image, $rev1))) $rev1 = false; - if ($rev2 && !file_exists(mediaFN($image, $rev2))) $rev2 = false; - - if($rev1 && $rev2){ // two specific revisions wanted - // make sure order is correct (older on the left) - if($rev1 < $rev2){ - $l_rev = $rev1; - $r_rev = $rev2; - }else{ - $l_rev = $rev2; - $r_rev = $rev1; - } - }elseif($rev1){ // single revision given, compare to current - $r_rev = ''; - $l_rev = $rev1; - }else{ // no revision was given, compare previous to current - $r_rev = ''; - $medialog = new MediaChangeLog($image); - $revs = $medialog->getRevisions(0, 1); - if (file_exists(mediaFN($image, $revs[0]))) { - $l_rev = $revs[0]; - } else { - $l_rev = ''; - } - } - - // prepare event data - $data = array(); - $data[0] = $image; - $data[1] = $l_rev; - $data[2] = $r_rev; - $data[3] = $ns; - $data[4] = $auth; - $data[5] = $fromajax; - - // trigger event - return Event::createAndTrigger('MEDIA_DIFF', $data, '_media_file_diff', true); + dbg_deprecated('see '. MediaDiff::class .'::show()'); } /** * Callback for media file diff * * @param array $data event data - * @return false|null + * + * @deprecated 2020-12-31 */ function _media_file_diff($data) { - if(is_array($data) && count($data)===6) { - media_file_diff($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); - } else { - return false; - } + dbg_deprecated('see '. MediaDiff::class .'::show()'); } /** @@ -1320,120 +1269,10 @@ function _media_file_diff($data) { * @param string $ns * @param int $auth permission level * @param bool $fromajax + * @deprecated 2020-12-31 */ function media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax) { - global $lang; - global $INPUT; - - $l_meta = new JpegMeta(mediaFN($image, $l_rev)); - $r_meta = new JpegMeta(mediaFN($image, $r_rev)); - - $is_img = preg_match('/\.(jpe?g|gif|png)$/', $image); - if ($is_img) { - $l_size = media_image_preview_size($image, $l_rev, $l_meta); - $r_size = media_image_preview_size($image, $r_rev, $r_meta); - $is_img = ($l_size && $r_size && ($l_size[0] >= 30 || $r_size[0] >= 30)); - - $difftype = $INPUT->str('difftype'); - - if (!$fromajax) { - $form = new Form([ - 'id' => 'mediamanager__form_diffview', - 'action' => media_managerURL([], '&'), - 'method' => 'get', - 'class' => 'diffView', - ]); - $form->addTagOpen('div')->addClass('no'); - $form->setHiddenField('sectok', null); - $form->setHiddenField('mediado', 'diff'); - $form->setHiddenField('rev2[0]', $l_rev); - $form->setHiddenField('rev2[1]', $r_rev); - echo $form->toHTML(); - - echo NL.'<div id="mediamanager__diff" >'.NL; - } - - if ($difftype == 'opacity' || $difftype == 'portions') { - media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $difftype); - if (!$fromajax) echo '</div>'; - return; - } - } - - list($l_head, $r_head) = (new dokuwiki\Ui\Diff)->diffHead($l_rev, $r_rev, $image, true); - - ?> - <div class="table"> - <table> - <tr> - <th><?php echo $l_head; ?></th> - <th><?php echo $r_head; ?></th> - </tr> - <?php - - echo '<tr class="image">'; - echo '<td>'; - media_preview($image, $auth, $l_rev, $l_meta); - echo '</td>'; - - echo '<td>'; - media_preview($image, $auth, $r_rev, $r_meta); - echo '</td>'; - echo '</tr>'.NL; - - echo '<tr class="actions">'; - echo '<td>'; - media_preview_buttons($image, $auth, $l_rev); - echo '</td>'; - - echo '<td>'; - media_preview_buttons($image, $auth, $r_rev); - echo '</td>'; - echo '</tr>'.NL; - - $l_tags = media_file_tags($l_meta); - $r_tags = media_file_tags($r_meta); - // FIXME r_tags-only stuff - foreach ($l_tags as $key => $l_tag) { - if ($l_tag['value'] != $r_tags[$key]['value']) { - $r_tags[$key]['highlighted'] = true; - $l_tags[$key]['highlighted'] = true; - } else if (!$l_tag['value'] || !$r_tags[$key]['value']) { - unset($r_tags[$key]); - unset($l_tags[$key]); - } - } - - echo '<tr>'; - foreach(array($l_tags,$r_tags) as $tags){ - echo '<td>'.NL; - - echo '<dl class="img_tags">'; - foreach($tags as $tag){ - $value = cleanText($tag['value']); - if (!$value) $value = '-'; - echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; - echo '<dd>'; - if ($tag['highlighted']) { - echo '<strong>'; - } - if ($tag['tag'][2] == 'date') echo dformat($value); - else echo hsc($value); - if ($tag['highlighted']) { - echo '</strong>'; - } - echo '</dd>'; - } - echo '</dl>'.NL; - - echo '</td>'; - } - echo '</tr>'.NL; - - echo '</table>'.NL; - echo '</div>'.NL; - - if ($is_img && !$fromajax) echo '</div>'; + dbg_deprecated('see '. MediaDiff::class .'::showFileDiff()'); } /** @@ -1448,32 +1287,10 @@ function media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax) { * @param array $l_size array with width and height * @param array $r_size array with width and height * @param string $type + * @deprecated 2020-12-31 */ function media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type) { - if ($l_size != $r_size) { - if ($r_size[0] > $l_size[0]) { - $l_size = $r_size; - } - } - - $l_more = array('rev' => $l_rev, 'h' => $l_size[1], 'w' => $l_size[0]); - $r_more = array('rev' => $r_rev, 'h' => $l_size[1], 'w' => $l_size[0]); - - $l_src = ml($image, $l_more); - $r_src = ml($image, $r_more); - - // slider - echo '<div class="slider" style="max-width: '.($l_size[0]-20).'px;" ></div>'.NL; - - // two images in divs - echo '<div class="imageDiff ' . $type . '">'.NL; - echo '<div class="image1" style="max-width: '.$l_size[0].'px;">'; - echo '<img src="'.$l_src.'" alt="" />'; - echo '</div>'.NL; - echo '<div class="image2" style="max-width: '.$l_size[0].'px;">'; - echo '<img src="'.$r_src.'" alt="" />'; - echo '</div>'.NL; - echo '</div>'.NL; + dbg_deprecated('see '. MediaDiff::class .'::showImageDiff()'); } /** @@ -1568,12 +1385,12 @@ function media_searchlist($query,$ns,$auth=null,$fullscreen=false,$sort='natural foreach($evdata['data'] as $item){ if (!$fullscreen) { // FIXME old call: media_printfile($item,$item['perm'],'',true); - $display = new \dokuwiki\Ui\Media\DisplayRow($item); + $display = new DisplayRow($item); $display->relativeDisplay($ns); $display->show(); } else { // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); - $display = new \dokuwiki\Ui\Media\DisplayTile($item); + $display = new DisplayTile($item); $display->relativeDisplay($ns); echo '<li>'; $display->show(); @@ -1873,7 +1690,7 @@ function media_nstree_li($item){ } /** - * Resizes the given image to the given size + * Resizes or crop the given image to the given size * * @author Andreas Gohr <andi@splitbrain.org> * @@ -1881,41 +1698,42 @@ function media_nstree_li($item){ * @param string $ext extension * @param int $w desired width * @param int $h desired height + * @param bool $crop should a center crop be used? * @return string path to resized or original size if failed */ -function media_resize_image($file, $ext, $w, $h=0){ +function media_mod_image($file, $ext, $w, $h=0, $crop=false) +{ global $conf; if(!$h) $h = $w; // we wont scale up to infinity if($w > 2000 || $h > 2000) return $file; - //cache - $local = getCacheName($file,'.media.'.$w.'x'.$h.'.'.$ext); - $mtime = (int) @filemtime($local); // 0 if not exists + $operation = $crop ? 'crop' : 'resize'; $options = [ 'quality' => $conf['jpg_quality'], 'imconvert' => $conf['im_convert'], ]; - if( $mtime <= (int) @filemtime($file) ) { + $cache = new \dokuwiki\Cache\CacheImageMod($file, $w, $h, $ext, $crop); + if(!$cache->useCache()) { try { - \splitbrain\slika\Slika::run($file, $options) - ->autorotate() - ->resize($w, $h) - ->save($local, $ext); - if($conf['fperm']) @chmod($local, $conf['fperm']); + Slika::run($file, $options) + ->autorotate() + ->$operation($w, $h) + ->save($cache->cache, $ext); + if($conf['fperm']) @chmod($cache->cache, $conf['fperm']); } catch (\splitbrain\slika\Exception $e) { - dbglog($e->getMessage()); + Logger::debug($e->getMessage()); return $file; } } - return $local; + return $cache->cache; } /** - * Center crops the given image to the wanted size + * Resizes the given image to the given size * * @author Andreas Gohr <andi@splitbrain.org> * @@ -1925,35 +1743,25 @@ function media_resize_image($file, $ext, $w, $h=0){ * @param int $h desired height * @return string path to resized or original size if failed */ -function media_crop_image($file, $ext, $w, $h=0){ - global $conf; - if(!$h) $h = $w; - // we wont scale up to infinity - if($w > 2000 || $h > 2000) return $file; - - //cache - $local = getCacheName($file,'.media.'.$w.'x'.$h.'.crop.'.$ext); - $mtime = (int) @filemtime($local); // 0 if not exists - - $options = [ - 'quality' => $conf['jpg_quality'], - 'imconvert' => $conf['im_convert'], - ]; - - if( $mtime <= (int) @filemtime($file) ) { - try { - \splitbrain\slika\Slika::run($file, $options) - ->autorotate() - ->crop($w, $h) - ->save($local, $ext); - if($conf['fperm']) @chmod($local, $conf['fperm']); - } catch (\splitbrain\slika\Exception $e) { - dbglog($e->getMessage()); - return $file; - } - } +function media_resize_image($file, $ext, $w, $h = 0) +{ + return media_mod_image($file, $ext, $w, $h, false); +} - return $local; +/** + * Center crops the given image to the wanted size + * + * @author Andreas Gohr <andi@splitbrain.org> + * + * @param string $file filename, path to file + * @param string $ext extension + * @param int $w desired width + * @param int $h desired height + * @return string path to resized or original size if failed + */ +function media_crop_image($file, $ext, $w, $h = 0) +{ + return media_mod_image($file, $ext, $w, $h, true); } /** @@ -2246,9 +2054,9 @@ function media_resize_imageGD($ext,$from,$from_w,$from_h,$to,$to_w,$to_h,$ofs_x= } } - // destroy GD image ressources - if($image) imagedestroy($image); - if($newimg) imagedestroy($newimg); + // destroy GD image resources + imagedestroy($image); + imagedestroy($newimg); return $okay; } diff --git a/inc/pageutils.php b/inc/pageutils.php index c281ffc5b..6af58ed82 100644 --- a/inc/pageutils.php +++ b/inc/pageutils.php @@ -1,4 +1,5 @@ <?php + /** * Utilities for handling pagenames * @@ -9,6 +10,8 @@ use dokuwiki\ChangeLog\MediaChangeLog; use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\File\MediaResolver; +use dokuwiki\File\PageResolver; /** * Fetch the an ID from request @@ -25,7 +28,8 @@ use dokuwiki\ChangeLog\PageChangeLog; * @param bool $clean if true, ID is cleaned * @return string */ -function getID($param='id',$clean=true){ +function getID($param = 'id', $clean = true) +{ /** @var Input $INPUT */ global $INPUT; global $conf; @@ -34,56 +38,58 @@ function getID($param='id',$clean=true){ $id = $INPUT->str($param); //construct page id from request URI - if(empty($id) && $conf['userewrite'] == 2){ + if (empty($id) && $conf['userewrite'] == 2) { $request = $INPUT->server->str('REQUEST_URI'); $script = ''; //get the script URL - if($conf['basedir']){ + if ($conf['basedir']) { $relpath = ''; - if($param != 'id') { + if ($param != 'id') { $relpath = 'lib/exe/'; } $script = $conf['basedir'] . $relpath . \dokuwiki\Utf8\PhpString::basename($INPUT->server->str('SCRIPT_FILENAME')); - - }elseif($INPUT->server->str('PATH_INFO')){ + } elseif ($INPUT->server->str('PATH_INFO')) { $request = $INPUT->server->str('PATH_INFO'); - }elseif($INPUT->server->str('SCRIPT_NAME')){ + } elseif ($INPUT->server->str('SCRIPT_NAME')) { $script = $INPUT->server->str('SCRIPT_NAME'); - }elseif($INPUT->server->str('DOCUMENT_ROOT') && $INPUT->server->str('SCRIPT_FILENAME')){ - $script = preg_replace ('/^'.preg_quote($INPUT->server->str('DOCUMENT_ROOT'),'/').'/','', - $INPUT->server->str('SCRIPT_FILENAME')); - $script = '/'.$script; + } elseif ($INPUT->server->str('DOCUMENT_ROOT') && $INPUT->server->str('SCRIPT_FILENAME')) { + $script = preg_replace( + '/^' . preg_quote($INPUT->server->str('DOCUMENT_ROOT'), '/') . '/', + '', + $INPUT->server->str('SCRIPT_FILENAME') + ); + $script = '/' . $script; } //clean script and request (fixes a windows problem) - $script = preg_replace('/\/\/+/','/',$script); - $request = preg_replace('/\/\/+/','/',$request); + $script = preg_replace('/\/\/+/', '/', $script); + $request = preg_replace('/\/\/+/', '/', $request); //remove script URL and Querystring to gain the id - if(preg_match('/^'.preg_quote($script,'/').'(.*)/',$request, $match)){ - $id = preg_replace ('/\?.*/','',$match[1]); + if (preg_match('/^' . preg_quote($script, '/') . '(.*)/', $request, $match)) { + $id = preg_replace('/\?.*/', '', $match[1]); } $id = urldecode($id); //strip leading slashes - $id = preg_replace('!^/+!','',$id); + $id = preg_replace('!^/+!', '', $id); } // Namespace autolinking from URL - if(substr($id,-1) == ':' || ($conf['useslash'] && substr($id,-1) == '/')){ - if(page_exists($id.$conf['start'])){ + if (substr($id, -1) == ':' || ($conf['useslash'] && substr($id, -1) == '/')) { + if (page_exists($id . $conf['start'])) { // start page inside namespace - $id = $id.$conf['start']; - }elseif(page_exists($id.noNS(cleanID($id)))){ + $id = $id . $conf['start']; + } elseif (page_exists($id . noNS(cleanID($id)))) { // page named like the NS inside the NS - $id = $id.noNS(cleanID($id)); - }elseif(page_exists($id)){ + $id = $id . noNS(cleanID($id)); + } elseif (page_exists($id)) { // page like namespace exists - $id = substr($id,0,-1); - }else{ + $id = substr($id, 0, -1); + } else { // fall back to default - $id = $id.$conf['start']; + $id = $id . $conf['start']; } if (isset($ACT) && $ACT === 'show') { $urlParameters = $_GET; @@ -93,8 +99,8 @@ function getID($param='id',$clean=true){ send_redirect(wl($id, $urlParameters, true, '&')); } } - if($clean) $id = cleanID($id); - if($id === '' && $param=='id') $id = $conf['start']; + if ($clean) $id = cleanID($id); + if ($id === '' && $param == 'id') $id = $conf['start']; return $id; } @@ -111,7 +117,8 @@ function getID($param='id',$clean=true){ * @param boolean $ascii Force ASCII * @return string cleaned id */ -function cleanID($raw_id,$ascii=false){ +function cleanID($raw_id, $ascii = false) +{ global $conf; static $sepcharpat = null; @@ -124,33 +131,33 @@ function cleanID($raw_id,$ascii=false){ } $sepchar = $conf['sepchar']; - if($sepcharpat == null) // build string only once to save clock cycles - $sepcharpat = '#\\'.$sepchar.'+#'; + if ($sepcharpat == null) // build string only once to save clock cycles + $sepcharpat = '#\\' . $sepchar . '+#'; $id = trim((string)$raw_id); $id = \dokuwiki\Utf8\PhpString::strtolower($id); //alternative namespace seperator - if($conf['useslash']){ - $id = strtr($id,';/','::'); - }else{ - $id = strtr($id,';/',':'.$sepchar); + if ($conf['useslash']) { + $id = strtr($id, ';/', '::'); + } else { + $id = strtr($id, ';/', ':' . $sepchar); } - if($conf['deaccent'] == 2 || $ascii) $id = \dokuwiki\Utf8\Clean::romanize($id); - if($conf['deaccent'] || $ascii) $id = \dokuwiki\Utf8\Clean::deaccent($id,-1); + if ($conf['deaccent'] == 2 || $ascii) $id = \dokuwiki\Utf8\Clean::romanize($id); + if ($conf['deaccent'] || $ascii) $id = \dokuwiki\Utf8\Clean::deaccent($id, -1); //remove specials - $id = \dokuwiki\Utf8\Clean::stripspecials($id,$sepchar,'\*'); + $id = \dokuwiki\Utf8\Clean::stripspecials($id, $sepchar, '\*'); - if($ascii) $id = \dokuwiki\Utf8\Clean::strip($id); + if ($ascii) $id = \dokuwiki\Utf8\Clean::strip($id); //clean up - $id = preg_replace($sepcharpat,$sepchar,$id); - $id = preg_replace('#:+#',':',$id); - $id = trim($id,':._-'); - $id = preg_replace('#:[:\._\-]+#',':',$id); - $id = preg_replace('#[:\._\-]+:#',':',$id); + $id = preg_replace($sepcharpat, $sepchar, $id); + $id = preg_replace('#:+#', ':', $id); + $id = trim($id, ':._-'); + $id = preg_replace('#:[:\._\-]+#', ':', $id); + $id = preg_replace('#[:\._\-]+:#', ':', $id); if (!$ascii) $cache[(string)$raw_id] = $id; return($id); @@ -164,10 +171,11 @@ function cleanID($raw_id,$ascii=false){ * @param string $id * @return string|false the namespace part or false if the given ID has no namespace (root) */ -function getNS($id){ - $pos = strrpos((string)$id,':'); - if($pos!==false){ - return substr((string)$id,0,$pos); +function getNS($id) +{ + $pos = strrpos((string)$id, ':'); + if ($pos !== false) { + return substr((string)$id, 0, $pos); } return false; } @@ -180,10 +188,11 @@ function getNS($id){ * @param string $id * @return string */ -function noNS($id) { +function noNS($id) +{ $pos = strrpos($id, ':'); - if ($pos!==false) { - return substr($id, $pos+1); + if ($pos !== false) { + return substr($id, $pos + 1); } else { return $id; } @@ -197,7 +206,8 @@ function noNS($id) { * @param string $id * @return string */ -function curNS($id) { +function curNS($id) +{ return noNS(getNS($id)); } @@ -209,7 +219,8 @@ function curNS($id) { * @param string $id * @return string */ -function noNSorNS($id) { +function noNSorNS($id) +{ global $conf; $p = noNS($id); @@ -231,25 +242,26 @@ function noNSorNS($id) { * * @author Andreas Gohr <andi@splitbrain.org> */ -function sectionID($title,&$check) { - $title = str_replace(array(':','.'),'',cleanID($title)); - $new = ltrim($title,'0123456789_-'); - if(empty($new)){ - $title = 'section'.preg_replace('/[^0-9]+/','',$title); //keep numbers from headline - }else{ +function sectionID($title, &$check) +{ + $title = str_replace(array(':','.'), '', cleanID($title)); + $new = ltrim($title, '0123456789_-'); + if (empty($new)) { + $title = 'section' . preg_replace('/[^0-9]+/', '', $title); //keep numbers from headline + } else { $title = $new; } - if(is_array($check)){ - $suffix=0; + if (is_array($check)) { + $suffix = 0; $candidateTitle = $title; - while(in_array($candidateTitle, $check)){ - $candidateTitle = $title . ++$suffix; + while (in_array($candidateTitle, $check)) { + $candidateTitle = $title . ++$suffix; } - $check []= $candidateTitle; + $check [] = $candidateTitle; return $candidateTitle; } else { - return $title; + return $title; } } @@ -266,14 +278,38 @@ function sectionID($title,&$check) { * @param bool $date_at * @return bool exists? */ -function page_exists($id,$rev='',$clean=true, $date_at=false) { - if($rev !== '' && $date_at) { +function page_exists($id, $rev = '', $clean = true, $date_at = false) +{ + $id = (explode('#', $id, 2))[0]; // #3608 + + if ($rev !== '' && $date_at) { $pagelog = new PageChangeLog($id); $pagelog_rev = $pagelog->getLastRevisionAt($rev); - if($pagelog_rev !== false) + if ($pagelog_rev !== false) $rev = $pagelog_rev; } - return file_exists(wikiFN($id,$rev,$clean)); + return file_exists(wikiFN($id, $rev, $clean)); +} + +/** + * Media existence check + * + * @param string $id page id + * @param string|int $rev empty or revision timestamp + * @param bool $clean flag indicating that $id should be cleaned (see mediaFN as well) + * @param bool $date_at + * @return bool exists? + */ +function media_exists($id, $rev = '', $clean = true, $date_at = false) +{ + if ($rev !== '' && $date_at) { + $changeLog = new MediaChangeLog($id); + $changelog_rev = $changeLog->getLastRevisionAt($rev); + if ($changelog_rev !== false) { + $rev = $changelog_rev; + } + } + return file_exists(mediaFN($id, $rev, $clean)); } /** @@ -289,7 +325,8 @@ function page_exists($id,$rev='',$clean=true, $date_at=false) { * * @author Andreas Gohr <andi@splitbrain.org> */ -function wikiFN($raw_id,$rev='',$clean=true){ +function wikiFN($raw_id, $rev = '', $clean = true) +{ global $conf; global $cache_wikifn; @@ -298,30 +335,32 @@ function wikiFN($raw_id,$rev='',$clean=true){ $id = $raw_id; if ($clean) $id = cleanID($id); - $id = str_replace(':','/',$id); + $id = str_replace(':', '/', $id); if (isset($cache[$id]) && isset($cache[$id][$rev])) { return $cache[$id][$rev]; } - if(empty($rev)){ - $fn = $conf['datadir'].'/'.utf8_encodeFN($id).'.txt'; - }else{ - $fn = $conf['olddir'].'/'.utf8_encodeFN($id).'.'.$rev.'.txt'; - if($conf['compression']){ + if (empty($rev)) { + $fn = $conf['datadir'] . '/' . utf8_encodeFN($id) . '.txt'; + } else { + $fn = $conf['olddir'] . '/' . utf8_encodeFN($id) . '.' . $rev . '.txt'; + if ($conf['compression']) { //test for extensions here, we want to read both compressions - if (file_exists($fn . '.gz')){ + if (file_exists($fn . '.gz')) { $fn .= '.gz'; - }else if(file_exists($fn . '.bz2')){ + } elseif (file_exists($fn . '.bz2')) { $fn .= '.bz2'; - }else{ + } else { //file doesnt exist yet, so we take the configured extension $fn .= '.' . $conf['compression']; } } } - if (!isset($cache[$id])) { $cache[$id] = array(); } + if (!isset($cache[$id])) { + $cache[$id] = array(); + } $cache[$id][$rev] = $fn; return $fn; } @@ -334,9 +373,10 @@ function wikiFN($raw_id,$rev='',$clean=true){ * @param string $id page id * @return string full path */ -function wikiLockFN($id) { +function wikiLockFN($id) +{ global $conf; - return $conf['lockdir'].'/'.md5(cleanID($id)).'.lock'; + return $conf['lockdir'] . '/' . md5(cleanID($id)) . '.lock'; } @@ -349,11 +389,12 @@ function wikiLockFN($id) { * @param string $ext file extension * @return string full path */ -function metaFN($id,$ext){ +function metaFN($id, $ext) +{ global $conf; $id = cleanID($id); - $id = str_replace(':','/',$id); - $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext; + $id = str_replace(':', '/', $id); + $fn = $conf['metadir'] . '/' . utf8_encodeFN($id) . $ext; return $fn; } @@ -366,11 +407,12 @@ function metaFN($id,$ext){ * @param string $ext extension of media * @return string */ -function mediaMetaFN($id,$ext){ +function mediaMetaFN($id, $ext) +{ global $conf; $id = cleanID($id); - $id = str_replace(':','/',$id); - $fn = $conf['mediametadir'].'/'.utf8_encodeFN($id).$ext; + $id = str_replace(':', '/', $id); + $fn = $conf['mediametadir'] . '/' . utf8_encodeFN($id) . $ext; return $fn; } @@ -383,11 +425,12 @@ function mediaMetaFN($id,$ext){ * @param string $id page id * @return array */ -function metaFiles($id){ +function metaFiles($id) +{ $basename = metaFN($id, ''); - $files = glob($basename.'.*', GLOB_MARK); + $files = glob($basename . '.*', GLOB_MARK); // filter files like foo.bar.meta when $id == 'foo' - return $files ? preg_grep('/^'.preg_quote($basename, '/').'\.[^.\/]*$/u', $files) : array(); + return $files ? preg_grep('/^' . preg_quote($basename, '/') . '\.[^.\/]*$/u', $files) : array(); } /** @@ -404,16 +447,17 @@ function metaFiles($id){ * * @return string full path */ -function mediaFN($id, $rev='', $clean=true){ +function mediaFN($id, $rev = '', $clean = true) +{ global $conf; if ($clean) $id = cleanID($id); - $id = str_replace(':','/',$id); - if(empty($rev)){ - $fn = $conf['mediadir'].'/'.utf8_encodeFN($id); - }else{ + $id = str_replace(':', '/', $id); + if (empty($rev)) { + $fn = $conf['mediadir'] . '/' . utf8_encodeFN($id); + } else { $ext = mimetype($id); - $name = substr($id,0, -1*strlen($ext[0])-1); - $fn = $conf['mediaolddir'].'/'.utf8_encodeFN($name .'.'.( (int) $rev ).'.'.$ext[0]); + $name = substr($id, 0, -1 * strlen($ext[0]) - 1); + $fn = $conf['mediaolddir'] . '/' . utf8_encodeFN($name . '.' . ( (int) $rev ) . '.' . $ext[0]); } return $fn; } @@ -428,14 +472,15 @@ function mediaFN($id, $rev='', $clean=true){ * * @author Andreas Gohr <andi@splitbrain.org> */ -function localeFN($id,$ext='txt'){ +function localeFN($id, $ext = 'txt') +{ global $conf; - $file = DOKU_CONF.'lang/'.$conf['lang'].'/'.$id.'.'.$ext; - if(!file_exists($file)){ - $file = DOKU_INC.'inc/lang/'.$conf['lang'].'/'.$id.'.'.$ext; - if(!file_exists($file)){ + $file = DOKU_CONF . 'lang/' . $conf['lang'] . '/' . $id . '.' . $ext; + if (!file_exists($file)) { + $file = DOKU_INC . 'inc/lang/' . $conf['lang'] . '/' . $id . '.' . $ext; + if (!file_exists($file)) { //fall back to english - $file = DOKU_INC.'inc/lang/en/'.$id.'.'.$ext; + $file = DOKU_INC . 'inc/lang/en/' . $id . '.' . $ext; } } return $file; @@ -450,32 +495,33 @@ function localeFN($id,$ext='txt'){ * Partyly based on a cleanPath function found at * http://php.net/manual/en/function.realpath.php#57016 * - * @author <bart at mediawave dot nl> - * + * @deprecated 2020-09-30 * @param string $ns namespace which is context of id * @param string $id relative id * @param bool $clean flag indicating that id should be cleaned * @return string */ -function resolve_id($ns,$id,$clean=true){ +function resolve_id($ns, $id, $clean = true) +{ global $conf; + dbg_deprecated(\dokuwiki\File\Resolver::class . ' and its children'); // some pre cleaning for useslash: - if($conf['useslash']) $id = str_replace('/',':',$id); + if ($conf['useslash']) $id = str_replace('/', ':', $id); // if the id starts with a dot we need to handle the // relative stuff - if($id && $id[0] == '.'){ + if ($id && $id[0] == '.') { // normalize initial dots without a colon - $id = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/','\1\3:',$id); + $id = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/', '\1\3:', $id); // prepend the current namespace - $id = $ns.':'.$id; + $id = $ns . ':' . $id; // cleanup relatives $result = array(); $pathA = explode(':', $id); if (!$pathA[0]) $result[] = ''; - foreach ($pathA AS $key => $dir) { + foreach ($pathA as $key => $dir) { if ($dir == '..') { if (end($result) == '..') { $result[] = '..'; @@ -488,122 +534,57 @@ function resolve_id($ns,$id,$clean=true){ } if (!end($pathA)) $result[] = ''; $id = implode(':', $result); - }elseif($ns !== false && strpos($id,':') === false){ + } elseif ($ns !== false && strpos($id, ':') === false) { //if link contains no namespace. add current namespace (if any) - $id = $ns.':'.$id; + $id = $ns . ':' . $id; } - if($clean) $id = cleanID($id); + if ($clean) $id = cleanID($id); return $id; } /** * Returns a full media id * - * @author Andreas Gohr <andi@splitbrain.org> - * * @param string $ns namespace which is context of id - * @param string &$page (reference) relative media id, updated to resolved id + * @param string &$media (reference) relative media id, updated to resolved id * @param bool &$exists (reference) updated with existance of media * @param int|string $rev * @param bool $date_at + * @deprecated 2020-09-30 */ -function resolve_mediaid($ns,&$page,&$exists,$rev='',$date_at=false){ - $page = resolve_id($ns,$page); - if($rev !== '' && $date_at){ - $medialog = new MediaChangeLog($page); - $medialog_rev = $medialog->getLastRevisionAt($rev); - if($medialog_rev !== false) { - $rev = $medialog_rev; - } - } - - $file = mediaFN($page,$rev); - $exists = file_exists($file); +function resolve_mediaid($ns, &$media, &$exists, $rev = '', $date_at = false) +{ + dbg_deprecated(MediaResolver::class); + $resolver = new MediaResolver("$ns:deprecated"); + $media = $resolver->resolveId($media, $rev, $date_at); + $exists = media_exists($media, $rev, false, $date_at); } /** * Returns a full page id * - * @author Andreas Gohr <andi@splitbrain.org> - * + * @deprecated 2020-09-30 * @param string $ns namespace which is context of id * @param string &$page (reference) relative page id, updated to resolved id * @param bool &$exists (reference) updated with existance of media * @param string $rev * @param bool $date_at */ -function resolve_pageid($ns,&$page,&$exists,$rev='',$date_at=false ){ - global $conf; - global $ID; - $exists = false; +function resolve_pageid($ns, &$page, &$exists, $rev = '', $date_at = false) +{ + dbg_deprecated(PageResolver::class); - //empty address should point to current page - if ($page === "") { - $page = $ID; - } - - //keep hashlink if exists then clean both parts - if (strpos($page,'#')) { - list($page,$hash) = explode('#',$page,2); + global $ID; + if (getNS($ID) == $ns) { + $context = $ID; // this is usually the case } else { - $hash = ''; - } - $hash = cleanID($hash); - $page = resolve_id($ns,$page,false); // resolve but don't clean, yet - - // get filename (calls clean itself) - if($rev !== '' && $date_at) { - $pagelog = new PageChangeLog($page); - $pagelog_rev = $pagelog->getLastRevisionAt($rev); - if($pagelog_rev !== false)//something found - $rev = $pagelog_rev; + $context = "$ns:deprecated"; // only used when a different context namespace was given } - $file = wikiFN($page,$rev); - - // if ends with colon or slash we have a namespace link - if(in_array(substr($page,-1), array(':', ';')) || - ($conf['useslash'] && substr($page,-1) == '/')){ - if(page_exists($page.$conf['start'],$rev,true,$date_at)){ - // start page inside namespace - $page = $page.$conf['start']; - $exists = true; - }elseif(page_exists($page.noNS(cleanID($page)),$rev,true,$date_at)){ - // page named like the NS inside the NS - $page = $page.noNS(cleanID($page)); - $exists = true; - }elseif(page_exists($page,$rev,true,$date_at)){ - // page like namespace exists - $page = $page; - $exists = true; - }else{ - // fall back to default - $page = $page.$conf['start']; - } - }else{ - //check alternative plural/nonplural form - if(!file_exists($file)){ - if( $conf['autoplural'] ){ - if(substr($page,-1) == 's'){ - $try = substr($page,0,-1); - }else{ - $try = $page.'s'; - } - if(page_exists($try,$rev,true,$date_at)){ - $page = $try; - $exists = true; - } - } - }else{ - $exists = true; - } - } - - // now make sure we have a clean page - $page = cleanID($page); - //add hash if any - if(!empty($hash)) $page .= '#'.$hash; + $resolver = new PageResolver($context); + $page = $resolver->resolveId($page, $rev, $date_at); + $exists = page_exists($page, $rev, false, $date_at); } /** @@ -617,10 +598,11 @@ function resolve_pageid($ns,&$page,&$exists,$rev='',$date_at=false ){ * @param string $ext This is appended to the filename if given * @return string The filename of the cachefile */ -function getCacheName($data,$ext=''){ +function getCacheName($data, $ext = '') +{ global $conf; $md5 = md5($data); - $file = $conf['cachedir'].'/'.$md5[0].'/'.$md5.$ext; + $file = $conf['cachedir'] . '/' . $md5[0] . '/' . $md5 . $ext; io_makeFileDir($file); return $file; } @@ -633,7 +615,8 @@ function getCacheName($data,$ext=''){ * @param string $id page id * @return bool */ -function isHiddenPage($id){ +function isHiddenPage($id) +{ $data = array( 'id' => $id, 'hidden' => false @@ -647,15 +630,16 @@ function isHiddenPage($id){ * * @param array $data event data - see isHiddenPage() */ -function _isHiddenPage(&$data) { +function _isHiddenPage(&$data) +{ global $conf; global $ACT; if ($data['hidden']) return; - if(empty($conf['hidepages'])) return; - if($ACT == 'admin') return; + if (empty($conf['hidepages'])) return; + if ($ACT == 'admin') return; - if(preg_match('/'.$conf['hidepages'].'/ui',':'.$data['id'])){ + if (preg_match('/' . $conf['hidepages'] . '/ui', ':' . $data['id'])) { $data['hidden'] = true; } } @@ -668,7 +652,8 @@ function _isHiddenPage(&$data) { * @param string $id page id * @return bool */ -function isVisiblePage($id){ +function isVisiblePage($id) +{ return !isHiddenPage($id); } @@ -683,7 +668,8 @@ function isVisiblePage($id){ * @param string $id page id * @return string */ -function prettyprint_id($id) { +function prettyprint_id($id) +{ if (!$id || $id === ':') { return '*'; } @@ -710,20 +696,21 @@ function prettyprint_id($id) { * @param bool $safe if true, only encoded when non ASCII characters detected * @return string */ -function utf8_encodeFN($file,$safe=true){ +function utf8_encodeFN($file, $safe = true) +{ global $conf; - if($conf['fnencode'] == 'utf-8') return $file; + if ($conf['fnencode'] == 'utf-8') return $file; - if($safe && preg_match('#^[a-zA-Z0-9/_\-\.%]+$#',$file)){ + if ($safe && preg_match('#^[a-zA-Z0-9/_\-\.%]+$#', $file)) { return $file; } - if($conf['fnencode'] == 'safe'){ + if ($conf['fnencode'] == 'safe') { return SafeFN::encode($file); } $file = urlencode($file); - $file = str_replace('%2F','/',$file); + $file = str_replace('%2F', '/', $file); return $file; } @@ -738,11 +725,12 @@ function utf8_encodeFN($file,$safe=true){ * @param string $file file name * @return string */ -function utf8_decodeFN($file){ +function utf8_decodeFN($file) +{ global $conf; - if($conf['fnencode'] == 'utf-8') return $file; + if ($conf['fnencode'] == 'utf-8') return $file; - if($conf['fnencode'] == 'safe'){ + if ($conf['fnencode'] == 'safe') { return SafeFN::decode($file); } @@ -762,7 +750,8 @@ function utf8_decodeFN($file){ * @param bool $useacl only return pages readable by the current user, false to ignore ACLs * @return false|string the full page id of the found page, false if any */ -function page_findnearest($page, $useacl = true){ +function page_findnearest($page, $useacl = true) +{ if ((string) $page === '') return false; global $ID; @@ -770,10 +759,10 @@ function page_findnearest($page, $useacl = true){ do { $ns = getNS($ns); $pageid = cleanID("$ns:$page"); - if(page_exists($pageid) && (!$useacl || auth_quickaclcheck($pageid) >= AUTH_READ)){ + if (page_exists($pageid) && (!$useacl || auth_quickaclcheck($pageid) >= AUTH_READ)) { return $pageid; } - } while($ns !== false); + } while ($ns !== false); return false; } diff --git a/inc/parser/metadata.php b/inc/parser/metadata.php index 849fffe8d..3a0ad4f5f 100644 --- a/inc/parser/metadata.php +++ b/inc/parser/metadata.php @@ -477,11 +477,12 @@ class Doku_Renderer_metadata extends Doku_Renderer $default = $this->_simpleTitle($id); // first resolve and clean up the $id - resolve_pageid(getNS($ID), $id, $exists); + $resolver = new \dokuwiki\File\PageResolver($ID); + $id = $resolver->resolveId($id); @list($page) = explode('#', $id, 2); // set metadata - $this->meta['relation']['references'][$page] = $exists; + $this->meta['relation']['references'][$page] = page_exists($page); // $data = array('relation' => array('isreferencedby' => array($ID => true))); // p_set_metadata($id, $data); @@ -721,7 +722,7 @@ class Doku_Renderer_metadata extends Doku_Renderer list($src) = explode('#', $src, 2); if (!media_isexternal($src)) { - resolve_mediaid(getNS($ID), $src, $exists); + $src = (new \dokuwiki\File\MediaResolver($ID))->resolveId($src); } if (preg_match('/.(jpe?g|gif|png)$/i', $src)) { $this->firstimage = $src; @@ -741,8 +742,9 @@ class Doku_Renderer_metadata extends Doku_Renderer if (media_isexternal($src)) { return; } - resolve_mediaid(getNS($ID), $src, $exists); - $this->meta['relation']['media'][$src] = $exists; + $src = (new \dokuwiki\File\MediaResolver($ID))->resolveId($src); + $file = mediaFN($src); + $this->meta['relation']['media'][$src] = file_exists($file); } #endregion diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 417b143c6..5899320cf 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -1,6 +1,8 @@ <?php use dokuwiki\ChangeLog\MediaChangeLog; +use dokuwiki\File\MediaResolver; +use dokuwiki\File\PageResolver; /** * Renderer for XHTML output @@ -202,11 +204,13 @@ class Doku_Renderer_xhtml extends Doku_Renderer { /** * Render a heading * - * @param string $text the text to display - * @param int $level header level - * @param int $pos byte position in the original source + * @param string $text the text to display + * @param int $level header level + * @param int $pos byte position in the original source + * @param bool $returnonly whether to return html or write to doc attribute + * @return void|string writes to doc attribute or returns html depends on $returnonly */ - public function header($text, $level, $pos) { + public function header($text, $level, $pos, $returnonly = false) { global $conf; if(blank($text)) return; //skip empty headlines @@ -232,19 +236,25 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->finishSectionEdit($pos - 1); } - // write the header - $this->doc .= DOKU_LF.'<h'.$level; + // build the header + $header = DOKU_LF.'<h'.$level; if($level <= $conf['maxseclevel']) { $data = array(); $data['target'] = 'section'; $data['name'] = $text; $data['hid'] = $hid; $data['codeblockOffset'] = $this->_codeblock; - $this->doc .= ' class="'.$this->startSectionEdit($pos, $data).'"'; + $header .= ' class="'.$this->startSectionEdit($pos, $data).'"'; + } + $header .= ' id="'.$hid.'">'; + $header .= $this->_xmlEntities($text); + $header .= "</h$level>".DOKU_LF; + + if ($returnonly) { + return $header; + } else { + $this->doc .= $header; } - $this->doc .= ' id="'.$hid.'">'; - $this->doc .= $this->_xmlEntities($text); - $this->doc .= "</h$level>".DOKU_LF; } /** @@ -657,7 +667,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { global $lang; global $INPUT; - $language = preg_replace(PREG_PATTERN_VALID_LANGUAGE, '', $language); + $language = preg_replace(PREG_PATTERN_VALID_LANGUAGE, '', $language ?? ''); if($filename) { // add icon @@ -891,7 +901,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $default = $this->_simpleTitle($id); // now first resolve and clean up the $id - resolve_pageid(getNS($ID), $id, $exists, $this->date_at, true); + $id = (new PageResolver($ID))->resolveId($id, $this->date_at, true); + $exists = page_exists($id, $this->date_at, false, true); $link = array(); $name = $this->_getLinkTitle($name, $default, $isImage, $id, $linktype); @@ -1054,7 +1065,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { if($conf['target']['interwiki']) $link['rel'] .= ' noopener'; $link['url'] = $url; - $link['title'] = htmlspecialchars($link['url']); + $link['title'] = $this->_xmlEntities($link['url']); // output formatted if($returnonly) { @@ -1172,7 +1183,8 @@ class Doku_Renderer_xhtml extends Doku_Renderer { if (strpos($src, '#') !== false) { list($src, $hash) = explode('#', $src, 2); } - resolve_mediaid(getNS($ID), $src, $exists, $this->date_at, true); + $src = (new MediaResolver($ID))->resolveId($src,$this->date_at,true); + $exists = media_exists($src); $noLink = false; $render = ($linking == 'linkonly') ? false : true; @@ -1739,7 +1751,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * @return string */ public function _xmlEntities($string) { - return htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); + return hsc($string); } @@ -1787,7 +1799,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer { // see internalmedia() and externalmedia() list($img['src']) = explode('#', $img['src'], 2); if($img['type'] == 'internalmedia') { - resolve_mediaid(getNS($ID), $img['src'], $exists ,$this->date_at, true); + $img['src'] = (new MediaResolver($ID))->resolveId($img['src'], $this->date_at, true); } return $this->_media( @@ -1988,10 +2000,10 @@ class Doku_Renderer_xhtml extends Doku_Renderer { * @access protected * @return string revision ('' for current) */ - protected function _getLastMediaRevisionAt($media_id){ - if(!$this->date_at || media_isexternal($media_id)) return ''; - $pagelog = new MediaChangeLog($media_id); - return $pagelog->getLastRevisionAt($this->date_at); + protected function _getLastMediaRevisionAt($media_id) { + if (!$this->date_at || media_isexternal($media_id)) return ''; + $changelog = new MediaChangeLog($media_id); + return $changelog->getLastRevisionAt($this->date_at); } #endregion diff --git a/inc/parserutils.php b/inc/parserutils.php index c9aacd91d..edcce9a08 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -114,8 +114,15 @@ function p_wiki_xhtml($id, $rev='', $excuse=true,$date_at=''){ */ function p_locale_xhtml($id){ //fetch parsed locale - $html = p_cached_output(localeFN($id)); - return $html; + $data = ['id' => $id, 'html' => '']; + + $event = new Event('PARSER_LOCALE_XHTML', $data); + if ($event->advise_before()) { + $data['html'] = p_cached_output(localeFN($data['id'])); + } + $event->advise_after(); + + return $data['html']; } /** diff --git a/inc/template.php b/inc/template.php index 9b7dfa5ab..c70d9f9fb 100644 --- a/inc/template.php +++ b/inc/template.php @@ -8,6 +8,7 @@ use dokuwiki\Extension\AdminPlugin; use dokuwiki\Extension\Event; +use dokuwiki\File\PageResolver; /** * Access a template file @@ -457,12 +458,14 @@ function tpl_pagelink($id, $name = null, $return = false) { * @return false|string */ function tpl_getparent($id) { + $resolver = new PageResolver('root'); + $parent = getNS($id).':'; - resolve_pageid('', $parent, $exists); + $parent = $resolver->resolveId($parent); if($parent == $id) { $pos = strrpos(getNS($id), ':'); $parent = substr($parent, 0, $pos).':'; - resolve_pageid('', $parent, $exists); + $parent = $resolver->resolveId($parent); if($parent == $id) return false; } return $parent; @@ -800,11 +803,13 @@ function tpl_youarehere($sep = null, $return = false) { } // print current page, skipping start page, skipping for namespace index - resolve_pageid('', $page, $exists); - if (isset($page) && $page == $part.$parts[$i]) { - if($return) return $out; - print $out; - return true; + if (isset($page)) { + $page = (new PageResolver('root'))->resolveId($page); + if ($page == $part . $parts[$i]) { + if ($return) return $out; + print $out; + return true; + } } $page = $part.$parts[$i]; if($page == $conf['start']) { diff --git a/install.php b/install.php index f37a15435..362bb0b4f 100644 --- a/install.php +++ b/install.php @@ -1,4 +1,5 @@ <?php + /*><div style="width:60%; margin: auto; background-color: #fcc; border: 1px solid #faa; padding: 0.5em 1em;"> <h1 style="font-size: 120%">No PHP Support</h1> @@ -14,25 +15,29 @@ * @author Chris Smith <chris@jalakai.co.uk> */ -if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/'); -if(!defined('DOKU_CONF')) define('DOKU_CONF',DOKU_INC.'conf/'); -if(!defined('DOKU_LOCAL')) define('DOKU_LOCAL',DOKU_INC.'conf/'); +if (!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__) . '/'); +if (!defined('DOKU_CONF')) define('DOKU_CONF', DOKU_INC . 'conf/'); +if (!defined('DOKU_LOCAL')) define('DOKU_LOCAL', DOKU_INC . 'conf/'); // load and initialize the core system -require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC . 'inc/init.php'); +require_once(DOKU_INC . 'inc/pageutils.php'); // check for error reporting override or set error reporting to sane values -if (!defined('DOKU_E_LEVEL')) { error_reporting(E_ALL ^ E_NOTICE); } -else { error_reporting(DOKU_E_LEVEL); } +if (!defined('DOKU_E_LEVEL')) { + error_reporting(E_ALL ^ E_NOTICE); +} else { + error_reporting(DOKU_E_LEVEL); +} // language strings -require_once(DOKU_INC.'inc/lang/en/lang.php'); -if(isset($_REQUEST['l']) && !is_array($_REQUEST['l'])) { - $LC = preg_replace('/[^a-z\-]+/','',$_REQUEST['l']); +require_once(DOKU_INC . 'inc/lang/en/lang.php'); +if (isset($_REQUEST['l']) && !is_array($_REQUEST['l'])) { + $LC = preg_replace('/[^a-z\-]+/', '', $_REQUEST['l']); } -if(empty($LC)) $LC = 'en'; -if($LC && $LC != 'en' ) { - require_once(DOKU_INC.'inc/lang/'.$LC.'/lang.php'); +if (empty($LC)) $LC = 'en'; +if ($LC && $LC != 'en') { + require_once(DOKU_INC . 'inc/lang/' . $LC . '/lang.php'); } // initialise variables ... @@ -87,13 +92,13 @@ header('Content-Type: text/html; charset=utf-8'); <div style="float: right; width: 34%;"> <?php - if(file_exists(DOKU_INC.'inc/lang/'.$LC.'/install.html')){ - include(DOKU_INC.'inc/lang/'.$LC.'/install.html'); - }else{ - print "<div lang=\"en\" dir=\"ltr\">\n"; - include(DOKU_INC.'inc/lang/en/install.html'); - print "</div>\n"; - } + if (file_exists(DOKU_INC . 'inc/lang/' . $LC . '/install.html')) { + include(DOKU_INC . 'inc/lang/' . $LC . '/install.html'); + } else { + print "<div lang=\"en\" dir=\"ltr\">\n"; + include(DOKU_INC . 'inc/lang/en/install.html'); + print "</div>\n"; + } ?> <a style=" background: transparent @@ -106,29 +111,29 @@ header('Content-Type: text/html; charset=utf-8'); <div style="float: left; width: 58%;"> <?php - try { - if(! (check_functions() && check_permissions()) ){ - echo '<p>'.$lang['i_problems'].'</p>'; - print_errors(); - print_retry(); - }elseif(!check_configs()){ - echo '<p>'.$lang['i_modified'].'</p>'; + try { + if (! (check_functions() && check_permissions())) { + echo '<p>' . $lang['i_problems'] . '</p>'; + print_errors(); + print_retry(); + } elseif (!check_configs()) { + echo '<p>' . $lang['i_modified'] . '</p>'; + print_errors(); + } elseif (check_data($_REQUEST['d'])) { + // check_data has sanitized all input parameters + if (!store_data($_REQUEST['d'])) { + echo '<p>' . $lang['i_failure'] . '</p>'; print_errors(); - }elseif(check_data($_REQUEST['d'])){ - // check_data has sanitized all input parameters - if(!store_data($_REQUEST['d'])){ - echo '<p>'.$lang['i_failure'].'</p>'; - print_errors(); - }else{ - echo '<p>'.$lang['i_success'].'</p>'; - } - }else{ - print_errors(); - print_form($_REQUEST['d']); + } else { + echo '<p>' . $lang['i_success'] . '</p>'; } - } catch (Exception $e) { - echo 'Caught exception: ', $e->getMessage(), "\n"; + } else { + print_errors(); + print_form($_REQUEST['d']); } + } catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + } ?> </div> @@ -146,17 +151,18 @@ header('Content-Type: text/html; charset=utf-8'); * * @param array $d submitted entry 'd' of request data */ -function print_form($d){ +function print_form($d) +{ global $lang; global $LC; - include(DOKU_CONF.'license.php'); + include(DOKU_CONF . 'license.php'); - if(!is_array($d)) $d = array(); - $d = array_map('hsc',$d); + if (!is_array($d)) $d = array(); + $d = array_map('hsc', $d); - if(!isset($d['acl'])) $d['acl']=1; - if(!isset($d['pop'])) $d['pop']=1; + if (!isset($d['acl'])) $d['acl'] = 1; + if (!isset($d['pop'])) $d['pop'] = 1; ?> <form action="" method="post"> @@ -191,11 +197,11 @@ function print_form($d){ <label for="policy"><?php echo $lang['i_policy']?></label> <select class="text" name="d[policy]" id="policy"> - <option value="0" <?php echo ($d['policy'] == 0)?'selected="selected"':'' ?>><?php + <option value="0" <?php echo ($d['policy'] == 0) ? 'selected="selected"' : '' ?>><?php echo $lang['i_pol0']?></option> - <option value="1" <?php echo ($d['policy'] == 1)?'selected="selected"':'' ?>><?php + <option value="1" <?php echo ($d['policy'] == 1) ? 'selected="selected"' : '' ?>><?php echo $lang['i_pol1']?></option> - <option value="2" <?php echo ($d['policy'] == 2)?'selected="selected"':'' ?>><?php + <option value="2" <?php echo ($d['policy'] == 2) ? 'selected="selected"' : '' ?>><?php echo $lang['i_pol2']?></option> </select> @@ -210,14 +216,14 @@ function print_form($d){ <fieldset> <p><?php echo $lang['i_license']?></p> <?php - array_push($license,array('name' => $lang['i_license_none'], 'url'=>'')); - if(empty($d['license'])) $d['license'] = 'cc-by-sa'; - foreach($license as $key => $lic){ - echo '<label for="lic_'.$key.'">'; - echo '<input type="radio" name="d[license]" value="'.hsc($key).'" id="lic_'.$key.'"'. - (($d['license'] === $key)?' checked="checked"':'').'>'; + array_push($license, array('name' => $lang['i_license_none'], 'url' => '')); + if (empty($d['license'])) $d['license'] = 'cc-by-sa'; + foreach ($license as $key => $lic) { + echo '<label for="lic_' . $key . '">'; + echo '<input type="radio" name="d[license]" value="' . hsc($key) . '" id="lic_' . $key . '"' . + (($d['license'] === $key) ? ' checked="checked"' : '') . '>'; echo hsc($lic['name']); - if($lic['url']) echo ' <a href="'.$lic['url'].'" target="_blank"><sup>[?]</sup></a>'; + if ($lic['url']) echo ' <a href="' . $lic['url'] . '" target="_blank"><sup>[?]</sup></a>'; echo '</label>'; } ?> @@ -241,7 +247,8 @@ function print_form($d){ <?php } -function print_retry() { +function print_retry() +{ global $lang; global $LC; ?> @@ -262,7 +269,8 @@ function print_retry() { * @param array $d * @return bool ok? */ -function check_data(&$d){ +function check_data(&$d) +{ static $form_default = array( 'title' => '', 'acl' => '1', @@ -278,12 +286,11 @@ function check_data(&$d){ global $lang; global $error; - if(!is_array($d)) $d = array(); - foreach($d as $k => $v) { - if(is_array($v)) + if (!is_array($d)) $d = array(); + foreach ($d as $k => $v) { + if (is_array($v)) unset($d[$k]); - else - $d[$k] = (string)$v; + else $d[$k] = (string)$v; } //autolowercase the username @@ -291,36 +298,35 @@ function check_data(&$d){ $ok = false; - if(isset($_REQUEST['submit'])) { + if (isset($_REQUEST['submit'])) { $ok = true; // check input - if(empty($d['title'])){ - $error[] = sprintf($lang['i_badval'],$lang['i_wikiname']); + if (empty($d['title'])) { + $error[] = sprintf($lang['i_badval'], $lang['i_wikiname']); $ok = false; } - if(isset($d['acl'])){ - if(!preg_match('/^[a-z0-9_]+$/',$d['superuser'])){ - $error[] = sprintf($lang['i_badval'],$lang['i_superuser']); + if (isset($d['acl'])) { + if (empty($d['superuser']) || ($d['superuser'] !== cleanID($d['superuser']))) { + $error[] = sprintf($lang['i_badval'], $lang['i_superuser']); $ok = false; } - if(empty($d['password'])){ - $error[] = sprintf($lang['i_badval'],$lang['pass']); + if (empty($d['password'])) { + $error[] = sprintf($lang['i_badval'], $lang['pass']); $ok = false; - } - elseif(!isset($d['confirm']) || $d['confirm'] != $d['password']){ - $error[] = sprintf($lang['i_badval'],$lang['passchk']); + } elseif (!isset($d['confirm']) || $d['confirm'] != $d['password']) { + $error[] = sprintf($lang['i_badval'], $lang['passchk']); $ok = false; } - if(empty($d['fullname']) || strstr($d['fullname'],':')){ - $error[] = sprintf($lang['i_badval'],$lang['fullname']); + if (empty($d['fullname']) || strstr($d['fullname'], ':')) { + $error[] = sprintf($lang['i_badval'], $lang['fullname']); $ok = false; } - if(empty($d['email']) || strstr($d['email'],':') || !strstr($d['email'],'@')){ - $error[] = sprintf($lang['i_badval'],$lang['email']); + if (empty($d['email']) || strstr($d['email'], ':') || !strstr($d['email'], '@')) { + $error[] = sprintf($lang['i_badval'], $lang['email']); $ok = false; } - }else{ + } else { // Since default = 1, browser won't send acl=0 when user untick acl $d['acl'] = '0'; } @@ -337,7 +343,8 @@ function check_data(&$d){ * @param array $d * @return bool */ -function store_data($d){ +function store_data($d) +{ global $LC; $ok = true; $d['policy'] = (int) $d['policy']; @@ -354,8 +361,8 @@ function store_data($d){ EOT; // add any config options set by a previous installer - $preset = __DIR__.'/install.conf'; - if(file_exists($preset)){ + $preset = __DIR__ . '/install.conf'; + if (file_exists($preset)) { $output .= "# preset config options\n"; $output .= file_get_contents($preset); $output .= "\n\n"; @@ -363,17 +370,17 @@ EOT; @unlink($preset); } - $output .= '$conf[\'title\'] = \''.addslashes($d['title'])."';\n"; - $output .= '$conf[\'lang\'] = \''.addslashes($LC)."';\n"; - $output .= '$conf[\'license\'] = \''.addslashes($d['license'])."';\n"; - if($d['acl']){ - $output .= '$conf[\'useacl\'] = 1'.";\n"; + $output .= '$conf[\'title\'] = \'' . addslashes($d['title']) . "';\n"; + $output .= '$conf[\'lang\'] = \'' . addslashes($LC) . "';\n"; + $output .= '$conf[\'license\'] = \'' . addslashes($d['license']) . "';\n"; + if ($d['acl']) { + $output .= '$conf[\'useacl\'] = 1' . ";\n"; $output .= "\$conf['superuser'] = '@admin';\n"; } - if(!$d['allowreg']){ - $output .= '$conf[\'disableactions\'] = \'register\''.";\n"; + if (!$d['allowreg']) { + $output .= '$conf[\'disableactions\'] = \'register\'' . ";\n"; } - $ok = $ok && fileWrite(DOKU_LOCAL.'local.php',$output); + $ok = $ok && fileWrite(DOKU_LOCAL . 'local.php', $output); if ($d['acl']) { // hash the password @@ -396,8 +403,8 @@ EOT; EOT; // --- user:bcryptpasswordhash:Real Name:email:groups,comma,seperated - $output = $output."\n".join(":",array($d['superuser'], $pass, $d['fullname'], $d['email'], 'admin,user'))."\n"; - $ok = $ok && fileWrite(DOKU_LOCAL.'users.auth.php', $output); + $output = $output . "\n" . join(":", array($d['superuser'], $pass, $d['fullname'], $d['email'], 'admin,user')) . "\n"; + $ok = $ok && fileWrite(DOKU_LOCAL . 'users.auth.php', $output); // create acl.auth.php $output = <<<EOT @@ -411,21 +418,21 @@ EOT; # Date: $now EOT; - if($d['policy'] == 2){ + if ($d['policy'] == 2) { $output .= "* @ALL 0\n"; $output .= "* @user 8\n"; - }elseif($d['policy'] == 1){ + } elseif ($d['policy'] == 1) { $output .= "* @ALL 1\n"; $output .= "* @user 8\n"; - }else{ + } else { $output .= "* @ALL 8\n"; } - $ok = $ok && fileWrite(DOKU_LOCAL.'acl.auth.php', $output); + $ok = $ok && fileWrite(DOKU_LOCAL . 'acl.auth.php', $output); } // enable popularity submission - if(isset($d['pop']) && $d['pop']){ - @touch(DOKU_INC.'data/cache/autosubmit.txt'); + if (isset($d['pop']) && $d['pop']) { + @touch(DOKU_INC . 'data/cache/autosubmit.txt'); } // disable auth plugins til needed @@ -444,7 +451,7 @@ EOT; \$plugins['authpgsql'] = 0; EOT; - $ok = $ok && fileWrite(DOKU_LOCAL.'plugins.local.php', $output); + $ok = $ok && fileWrite(DOKU_LOCAL . 'plugins.local.php', $output); return $ok; } @@ -458,17 +465,20 @@ EOT; * @param string $data * @return bool */ -function fileWrite($filename, $data) { +function fileWrite($filename, $data) +{ global $error; global $lang; if (($fp = @fopen($filename, 'wb')) === false) { - $filename = str_replace($_SERVER['DOCUMENT_ROOT'],'{DOCUMENT_ROOT}/', $filename); - $error[] = sprintf($lang['i_writeerr'],$filename); + $filename = str_replace($_SERVER['DOCUMENT_ROOT'], '{DOCUMENT_ROOT}/', $filename); + $error[] = sprintf($lang['i_writeerr'], $filename); return false; } - if (!empty($data)) { fwrite($fp, $data); } + if (!empty($data)) { + fwrite($fp, $data); + } fclose($fp); return true; } @@ -482,23 +492,24 @@ function fileWrite($filename, $data) { * * @return bool */ -function check_configs(){ +function check_configs() +{ global $error; global $lang; $ok = true; $config_files = array( - 'local' => DOKU_LOCAL.'local.php', - 'users' => DOKU_LOCAL.'users.auth.php', - 'auth' => DOKU_LOCAL.'acl.auth.php' + 'local' => DOKU_LOCAL . 'local.php', + 'users' => DOKU_LOCAL . 'users.auth.php', + 'auth' => DOKU_LOCAL . 'acl.auth.php' ); // configs shouldn't exist foreach ($config_files as $file) { if (file_exists($file) && filesize($file)) { - $file = str_replace($_SERVER['DOCUMENT_ROOT'],'{DOCUMENT_ROOT}/', $file); - $error[] = sprintf($lang['i_confexists'],$file); + $file = str_replace($_SERVER['DOCUMENT_ROOT'], '{DOCUMENT_ROOT}/', $file); + $error[] = sprintf($lang['i_confexists'], $file); $ok = false; } } @@ -513,30 +524,31 @@ function check_configs(){ * * @return bool */ -function check_permissions(){ +function check_permissions() +{ global $error; global $lang; $dirs = array( 'conf' => DOKU_LOCAL, - 'data' => DOKU_INC.'data', - 'pages' => DOKU_INC.'data/pages', - 'attic' => DOKU_INC.'data/attic', - 'media' => DOKU_INC.'data/media', - 'media_attic' => DOKU_INC.'data/media_attic', - 'media_meta' => DOKU_INC.'data/media_meta', - 'meta' => DOKU_INC.'data/meta', - 'cache' => DOKU_INC.'data/cache', - 'locks' => DOKU_INC.'data/locks', - 'index' => DOKU_INC.'data/index', - 'tmp' => DOKU_INC.'data/tmp' + 'data' => DOKU_INC . 'data', + 'pages' => DOKU_INC . 'data/pages', + 'attic' => DOKU_INC . 'data/attic', + 'media' => DOKU_INC . 'data/media', + 'media_attic' => DOKU_INC . 'data/media_attic', + 'media_meta' => DOKU_INC . 'data/media_meta', + 'meta' => DOKU_INC . 'data/meta', + 'cache' => DOKU_INC . 'data/cache', + 'locks' => DOKU_INC . 'data/locks', + 'index' => DOKU_INC . 'data/index', + 'tmp' => DOKU_INC . 'data/tmp' ); $ok = true; - foreach($dirs as $dir){ - if(!file_exists("$dir/.") || !is_writable($dir)){ - $dir = str_replace($_SERVER['DOCUMENT_ROOT'],'{DOCUMENT_ROOT}', $dir); - $error[] = sprintf($lang['i_permfail'],$dir); + foreach ($dirs as $dir) { + if (!file_exists("$dir/.") || !is_writable($dir)) { + $dir = str_replace($_SERVER['DOCUMENT_ROOT'], '{DOCUMENT_ROOT}', $dir); + $error[] = sprintf($lang['i_permfail'], $dir); $ok = false; } } @@ -550,17 +562,18 @@ function check_permissions(){ * * @return bool */ -function check_functions(){ +function check_functions() +{ global $error; global $lang; $ok = true; - if(version_compare(phpversion(),'5.6.0','<')){ - $error[] = sprintf($lang['i_phpver'],phpversion(),'5.6.0'); + if (version_compare(phpversion(), '5.6.0', '<')) { + $error[] = sprintf($lang['i_phpver'], phpversion(), '5.6.0'); $ok = false; } - if(ini_get('mbstring.func_overload') != 0){ + if (ini_get('mbstring.func_overload') != 0) { $error[] = $lang['i_mbfuncoverload']; $ok = false; } @@ -573,17 +586,17 @@ function check_functions(){ $ok = false; } - if(ini_get('mbstring.func_overload') != 0){ + if (ini_get('mbstring.func_overload') != 0) { $error[] = $lang['i_mbfuncoverload']; $ok = false; } - $funcs = explode(' ','addslashes call_user_func chmod copy fgets '. - 'file file_exists fseek flush filesize ftell fopen '. - 'glob header ignore_user_abort ini_get mkdir '. - 'ob_start opendir parse_ini_file readfile realpath '. - 'rename rmdir serialize session_start unlink usleep '. - 'preg_replace file_get_contents htmlspecialchars_decode '. + $funcs = explode(' ', 'addslashes call_user_func chmod copy fgets ' . + 'file file_exists fseek flush filesize ftell fopen ' . + 'glob header ignore_user_abort ini_get mkdir ' . + 'ob_start opendir parse_ini_file readfile realpath ' . + 'rename rmdir serialize session_start unlink usleep ' . + 'preg_replace file_get_contents htmlspecialchars_decode ' . 'spl_autoload_register stream_select fsockopen pack xml_parser_create'); if (!function_exists('mb_substr')) { @@ -591,19 +604,18 @@ function check_functions(){ $funcs[] = 'utf8_decode'; } - if(!function_exists('mail')){ - if(strpos(ini_get('disable_functions'),'mail') !== false) { + if (!function_exists('mail')) { + if (strpos(ini_get('disable_functions'), 'mail') !== false) { $disabled = $lang['i_disabled']; - } - else { + } else { $disabled = ""; } - $error[] = sprintf($lang['i_funcnmail'],$disabled); + $error[] = sprintf($lang['i_funcnmail'], $disabled); } - foreach($funcs as $func){ - if(!function_exists($func)){ - $error[] = sprintf($lang['i_funcna'],$func); + foreach ($funcs as $func) { + if (!function_exists($func)) { + $error[] = sprintf($lang['i_funcna'], $func); $ok = false; } } @@ -615,18 +627,19 @@ function check_functions(){ * * @author Andreas Gohr <andi@splitbrain.org> */ -function langsel(){ +function langsel() +{ global $lang; global $LC; - $dir = DOKU_INC.'inc/lang'; + $dir = DOKU_INC . 'inc/lang'; $dh = opendir($dir); - if(!$dh) return; + if (!$dh) return; $langs = array(); while (($file = readdir($dh)) !== false) { - if(preg_match('/^[\._]/',$file)) continue; - if(is_dir($dir.'/'.$file) && file_exists($dir.'/'.$file.'/lang.php')){ + if (preg_match('/^[\._]/', $file)) continue; + if (is_dir($dir . '/' . $file) && file_exists($dir . '/' . $file . '/lang.php')) { $langs[] = $file; } } @@ -636,12 +649,12 @@ function langsel(){ echo '<form action="">'; echo $lang['i_chooselang']; echo ': <select name="l" onchange="submit()">'; - foreach($langs as $l){ + foreach ($langs as $l) { $sel = ($l == $LC) ? 'selected="selected"' : ''; - echo '<option value="'.$l.'" '.$sel.'>'.$l.'</option>'; + echo '<option value="' . $l . '" ' . $sel . '>' . $l . '</option>'; } echo '</select> '; - echo '<button type="submit">'.$lang['btn_update'].'</button>'; + echo '<button type="submit">' . $lang['btn_update'] . '</button>'; echo '</form>'; } @@ -650,11 +663,12 @@ function langsel(){ * * @author Andreas Gohr <andi@splitbrain.org> */ -function print_errors(){ +function print_errors() +{ global $error; - if(!empty($error)) { + if (!empty($error)) { echo '<ul>'; - foreach ($error as $err){ + foreach ($error as $err) { echo "<li>$err</li>"; } echo '</ul>'; diff --git a/lib/exe/css.php b/lib/exe/css.php index 76821baf3..05e55bb56 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -328,7 +328,7 @@ function css_interwiki(){ // default style echo 'a.interwiki {'; - echo ' background: transparent url('.DOKU_BASE.'lib/images/interwiki.png) 0 0 no-repeat;'; + echo ' background: transparent url('.DOKU_BASE.'lib/images/interwiki.svg) 0 0 no-repeat;'; echo ' background-size: 1.2em;'; echo ' padding: 0 0 0 1.4em;'; echo '}'; diff --git a/lib/exe/xmlrpc.php b/lib/exe/xmlrpc.php index dc0438ee1..e90fb9eba 100644 --- a/lib/exe/xmlrpc.php +++ b/lib/exe/xmlrpc.php @@ -5,11 +5,14 @@ use dokuwiki\Remote\XmlRpcServer; -if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/../../'); +if (!defined('DOKU_INC')) define('DOKU_INC', __DIR__ . '/../../'); -require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC . 'inc/init.php'); session_write_close(); //close session -if(!$conf['remote']) die((new IXR_Error(-32605, "XML-RPC server not enabled."))->getXml()); - -$server = new XmlRpcServer(); +$server = new XmlRpcServer(true); +try { + $server->serve(); +} catch (\Exception $e) { + $server->error($e->getCode(), $e->getMessage()); +} diff --git a/lib/images/smileys/deleteme.svg b/lib/images/smileys/deleteme.svg index 40ec14f30..c4d218a99 100644 --- a/lib/images/smileys/deleteme.svg +++ b/lib/images/smileys/deleteme.svg @@ -1 +1,6 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 215 36"><path d="M17.91 0C8.004.05 0 8.094 0 18c0 9.941 8.059 18 18 18l181.352-.092c9.192-.93 16.187-8.669 16.187-17.908 0-9.941-8.059-18-18-18H17.91z" fill="#ffcc4d"/><path d="M184.636 28.598q-.624 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.425-.425 1.05-.425h12.814q.652 0 1.05.397.396.369.396.992 0 .596-.397.964-.397.369-1.049.369h-11.34v6.89h8.137q.623 0 1.02.396.425.369.425.964 0 .596-.425.993-.397.368-1.02.368h-8.138v7.088h11.341q.652 0 1.05.369.396.368.396.964 0 .623-.397 1.02-.397.369-1.049.369zm-8.619-22.143q.624 0 1.05.425.425.426.425 1.05v19.194q0 .623-.454 1.049-.425.425-1.02.425-.625 0-1.05-.425-.425-.426-.425-1.05v-14.09l-6.861 13.977q-.482.737-1.276.737-.936 0-1.361-.878l-6.776-13.581v13.836q0 .623-.425 1.049-.426.425-1.05.425-.623 0-1.048-.425-.426-.426-.426-1.05V7.93q0-.623.426-1.049.425-.425 1.049-.425.85 0 1.304.794l8.42 16.87 8.194-16.87q.454-.794 1.304-.794zm-39.069 22.143q-.624 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.425-.425 1.05-.425h12.814q.652 0 1.05.397.396.369.396.992 0 .596-.397.964-.397.369-1.049.369h-11.34v6.89h8.137q.623 0 1.02.396.425.369.425.964 0 .596-.425.993-.397.368-1.02.368h-8.137v7.088h11.34q.652 0 1.05.369.396.368.396.964 0 .623-.397 1.02-.397.369-1.049.369zm-6.095-22.143q.595 0 .963.397.397.369.397.964t-.397.992q-.368.369-.963.369h-6.096v17.947q0 .623-.425 1.049-.426.425-1.05.425-.623 0-1.048-.425-.426-.426-.426-1.05V9.178h-6.124q-.595 0-.992-.369-.369-.397-.369-.992t.369-.964q.397-.397.992-.397zM98.36 28.598q-.624 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.425-.425 1.05-.425h12.814q.652 0 1.05.397.396.369.396.992 0 .596-.397.964-.397.369-1.049.369h-11.34v6.89h8.136q.624 0 1.021.396.425.369.425.964 0 .596-.425.993-.397.368-1.02.368h-8.138v7.088h11.341q.652 0 1.05.369.396.368.396.964 0 .623-.397 1.02-.397.369-1.049.369zm-18.23 0q-.624 0-1.05-.425-.396-.426-.396-1.05V7.93q0-.623.425-1.049.425-.425 1.02-.425.625 0 1.05.425.425.426.425 1.05v17.72H91.87q.623 0 1.049.425.425.425.425 1.049 0 .623-.425 1.049-.426.425-1.05.425zm-19.818 0q-.624 0-1.05-.425-.424-.426-.424-1.05V7.93q0-.652.425-1.049.425-.425 1.049-.425h12.815q.652 0 1.049.397.397.369.397.992 0 .596-.397.964-.397.369-1.049.369h-11.34v6.89h8.136q.624 0 1.02.396.426.369.426.964 0 .596-.425.993-.397.368-1.02.368h-8.138v7.088h11.341q.652 0 1.049.369.397.368.397.964 0 .623-.397 1.02-.397.369-1.049.369zm-22.2 0q-.623 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.426-.425 1.05-.425h5.131q3.204 0 5.699 1.418 2.495 1.417 3.884 3.94 1.39 2.496 1.39 5.7 0 3.203-1.39 5.726-1.39 2.524-3.884 3.941-2.495 1.418-5.699 1.418zm5.132-2.608q2.353 0 4.196-1.078 1.871-1.077 2.892-3.005 1.049-1.956 1.049-4.395 0-2.438-1.049-4.366-1.02-1.928-2.892-3.005-1.843-1.078-4.196-1.078h-3.657V25.99z" fill="#1a1a1a"/><path fill="#9aaab4" d="M27.025 8.543l-1.241 3.16-1.242-3.16h-2.886l-1.34 3.412-1.341-3.412h-2.689l-1.34 3.412-1.341-3.412h-2.887l-1.242 3.16-1.241-3.16H6.587l2.6 19.496h16.886l2.6-19.496zM23.1 9.71l1.711 4.471L23 18.79l-1.71-4.352zm-5.469.258l1.71 4.468-1.71 4.352-1.71-4.352zm-5.469-.258l1.809 4.727-1.71 4.352-1.81-4.608zM9.25 17.32l.227-.594 1.774 4.635-1.095 2.787zm1.469 10.71L12.26 24l1.542 4.03zm2.553-6.67l1.675-4.375 1.674 4.376-1.674 4.263zm2.817 6.67L17.63 24l1.542 4.03zm2.552-6.67l1.674-4.375 1.675 4.376-1.675 4.263zm2.818 6.67L23 24l1.542 4.03zm3.752-3.614l-1.2-3.055 1.774-4.634.286.747z"/><path fill="#67757f" d="M27.373 29.422c0-.769-.623-1.392-1.392-1.392H9.28a1.392 1.392 0 0 0 0 2.783H25.98c.769 0 1.392-.623 1.392-1.391zM30.157 7.15c0-.77-.623-1.392-1.392-1.392H6.495a1.392 1.392 0 0 0 0 2.784h22.27c.769 0 1.392-.623 1.392-1.392z"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 148 36"> + <path fill="#ffcc4d" d="M147.999 32.001A4 4 0 0 1 144 36H3.999A3.999 3.999 0 0 1 0 32.001V4a4 4 0 0 1 3.999-4H144a4 4 0 0 1 3.999 3.999z"/> + <path fill="#664500" d="M138.61 22.995q0 1.742-1.821 1.742-1.841 0-1.841-1.739V9.128q0-1.724 1.84-1.724 1.822 0 1.822 1.724zm-1.821 7.668q-.98 0-1.595-.604-.62-.616-.62-1.561 0-.96.605-1.58.616-.616 1.61-.616.96 0 1.576.635.62.635.62 1.56 0 .912-.62 1.55-.616.616-1.576.616zm-16.781-7.423q.325 2.053 1.398 3.077 1.092 1.024 2.93 1.024 1.125 0 1.806-.227.684-.245 1.742-.91.586-.36 1.058-.36.605 0 1.093.552.502.54.502 1.108 0 1.171-1.954 2.165-1.935.994-4.308.994-3.73 0-5.878-2.343-2.15-2.362-2.15-6.35 0-4.081 2.082-6.527 2.087-2.441 5.715-2.441 3.254 0 5.223 2.131 1.97 2.136 1.97 5.601 0 1.32-.522 1.92-.518.586-1.61.586zm7.536-3.205q-.132-1.678-1.092-2.683-.945-1.013-2.408-1.013-1.565 0-2.62.975-1.057.979-1.352 2.721zm-18.1-3.598v8.935q0 .88.378 1.383.37.492 1.088.492.473 0 .99-.197.817-.31 1.172-.31.556 0 .96.567.408.556.408 1.225 0 .748-.635 1.186-.616.424-1.53.68-.892.265-1.871.265-2.344 0-3.481-1.27-1.142-1.285-1.142-3.957v-8.999h-1.171q-.877 0-1.236-.276-.36-.295-.36-1.285 0-.964.341-1.24.34-.29 1.255-.29h1.171V9.88q0-.847.409-1.19.404-.36 1.383-.36 1.058 0 1.463.36.408.34.408 1.19v3.466h3.061q.847 0 1.153.325.31.31.31 1.205 0 .862-.325 1.221-.325.34-1.138.34zm-19.11 6.803q.33 2.053 1.399 3.077 1.096 1.024 2.933 1.024 1.122 0 1.806-.227.68-.245 1.739-.91.59-.36 1.058-.36.605 0 1.096.552.503.54.503 1.108 0 1.171-1.954 2.165-1.939.994-4.312.994-3.73 0-5.878-2.343-2.146-2.362-2.146-6.35 0-4.081 2.078-6.527 2.087-2.441 5.715-2.441 3.258 0 5.227 2.131 1.965 2.136 1.965 5.601 0 1.32-.517 1.92-.522.586-1.61.586zm7.537-3.205q-.129-1.678-1.089-2.683-.945-1.013-2.411-1.013-1.56 0-2.62.975-1.057.979-1.348 2.721zm-14.857 9.033q0 1.527-1.875 1.527-1.807 0-1.807-1.527V6.803q0-.782.424-1.126.423-.34 1.417-.34.975 0 1.398.359.443.34.443 1.107zM64.766 23.24q.325 2.053 1.398 3.077 1.093 1.024 2.933 1.024 1.123 0 1.807-.227.68-.245 1.739-.91.585-.36 1.058-.36.605 0 1.092.552.503.54.503 1.108 0 1.171-1.95 2.165-1.94.994-4.317.994-3.726 0-5.873-2.343-2.15-2.362-2.15-6.35 0-4.081 2.086-6.527 2.078-2.441 5.71-2.441 3.255 0 5.224 2.131 1.969 2.136 1.969 5.601 0 1.32-.518 1.92-.521.586-1.614.586zm7.536-3.205q-.132-1.678-1.092-2.683-.945-1.013-2.407-1.013-1.561 0-2.62.975-1.058.979-1.353 2.721zM42.973 30.338q-1.417 0-2.196-.733-.767-.733-.767-2.067V10.772q0-1.546.782-2.325.794-.782 2.378-.782h4.505q4.902 0 7.748 3.008 2.85 2.998 2.85 7.96 0 5.356-2.835 8.53-2.812 3.175-7.763 3.175zm.764-4.006q0 .537.472.537h3.273q3.368 0 5.208-2.132 1.852-2.147 1.852-5.972 0-3.583-1.852-5.6-1.855-2.034-5.208-2.034h-3.175q-.245 0-.408.177-.162.182-.162.458z"/> + <path fill="#9aaab4" d="M28.006 7.71L26.7 11.048 25.387 7.71h-3.05l-1.414 3.606-1.417-3.606h-2.838l-1.414 3.606-1.417-3.606h-3.05l-1.312 3.338L8.168 7.71H6.425L9.17 28.297h17.828L29.745 7.71zM23.86 8.946l1.81 4.72-1.912 4.865-1.807-4.596zm-5.771.272l1.803 4.717-1.803 4.596-1.807-4.596zm-5.775-.272l1.908 4.99-1.806 4.595-1.913-4.864zm-3.077 8.032l.238-.624 1.875 4.895-1.157 2.94zm1.55 11.312l1.629-4.256 1.629 4.256zm2.698-7.041l1.77-4.623 1.764 4.623-1.765 4.497zm2.975 7.04l1.625-4.255 1.629 4.256zm2.695-7.04l1.765-4.623 1.769 4.623-1.77 4.497zm2.974 7.04l1.625-4.255 1.633 4.256zm3.961-3.817l-1.266-3.223 1.875-4.895.302.79z"/> + <path fill="#67757f" d="M28.377 29.76a1.47 1.47 0 0 0-1.474-1.474H9.27a1.47 1.47 0 0 0 0 2.94h17.64a1.47 1.47 0 0 0 1.47-1.466zm2.94-23.52a1.47 1.47 0 0 0-1.474-1.466H6.331a1.47 1.47 0 0 0 0 2.936h23.52a1.47 1.47 0 0 0 1.47-1.47z"/> +</svg> diff --git a/lib/images/smileys/exclaim.svg b/lib/images/smileys/exclaim.svg index e730a0839..fe00254bb 100644 --- a/lib/images/smileys/exclaim.svg +++ b/lib/images/smileys/exclaim.svg @@ -1 +1,4 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#BE1931" cx="18" cy="32" r="3"/><path fill="#BE1931" d="M21 24c0 1.657-1.344 3-3 3-1.657 0-3-1.343-3-3V5c0-1.657 1.343-3 3-3 1.656 0 3 1.343 3 3v19z"/></svg>
\ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"> + <circle cx="18.001" cy="18.001" r="18" fill="#ffcc4d"/> + <path fill="#664500" d="M15.578 26.993a2.423 2.423 0 1 1 4.846.004 2.423 2.423 0 0 1-4.846-.007zm.19-18.294c0-1.304.96-2.11 2.23-2.11 1.243 0 2.233.836 2.233 2.106v11.94c0 1.27-.99 2.11-2.23 2.11-1.274 0-2.234-.81-2.234-2.11z"/> +</svg> diff --git a/lib/images/smileys/fixme.svg b/lib/images/smileys/fixme.svg index d67aaa1ee..3d2165dc3 100644 --- a/lib/images/smileys/fixme.svg +++ b/lib/images/smileys/fixme.svg @@ -1 +1,5 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 139.53906 36.000092" width="139.539" height="36"><path d="M17.91 0C8.004.05 0 8.094 0 18c0 9.941 8.059 18 18 18l105.352-.092c9.192-.93 16.187-8.669 16.187-17.908 0-9.941-8.059-18-18-18H17.91z" fill="#ffcc4d"/><circle fill="#be1931" cx="18" cy="32" r="3"/><path fill="#be1931" d="M21 24a3 3 0 0 1-6 0V5a3 3 0 1 1 6 0z"/><path d="M108.615 28.598q-.624 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.425-.425 1.049-.425h12.815q.652 0 1.05.397.396.369.396.992 0 .596-.397.964-.397.369-1.049.369h-11.34v6.89h8.136q.624 0 1.021.396.425.369.425.964 0 .596-.425.993-.397.368-1.02.368h-8.138v7.088h11.341q.652 0 1.05.369.396.368.396.964 0 .623-.397 1.02-.397.369-1.049.369zM99.996 6.455q.624 0 1.05.425.424.426.424 1.05v19.194q0 .623-.453 1.049-.426.425-1.021.425-.624 0-1.049-.425-.425-.426-.425-1.05v-14.09L91.66 27.01q-.482.737-1.276.737-.936 0-1.361-.878l-6.776-13.581v13.836q0 .623-.426 1.049-.425.425-1.049.425-.623 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.623.425-1.049.426-.425 1.05-.425.85 0 1.304.794l8.42 16.87 8.194-16.87q.453-.794 1.304-.794zM74.791 26.216q.312.454.312.964 0 .567-.369.993-.368.425-.992.425-.709 0-1.134-.539l-6.152-8.534-6.521 8.648q-.426.425-1.021.425-.624 0-.992-.397-.34-.397-.34-.964t.34-1.02l6.606-8.79L58.29 8.78q-.283-.369-.283-.879 0-.595.368-1.02.369-.426.993-.426.737 0 1.049.425l6.095 8.45 6.351-8.45q.397-.425 1.05-.425.595 0 .935.397.368.397.368.964 0 .482-.311.964l-6.465 8.619zm-22.937 2.382q-.623 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.426-.425 1.05-.425.651 0 1.048.425.426.397.426 1.05v19.194q0 .623-.426 1.049-.397.425-1.049.425zm-19.506 0q-.623 0-1.049-.425-.425-.426-.425-1.05V7.93q0-.652.425-1.049.426-.425 1.05-.425h12.814q.652 0 1.05.397.396.369.396.992 0 .596-.397.964-.397.369-1.049.369h-11.34v6.89h8.137q.623 0 1.02.396.426.369.426.964 0 .596-.426.993-.397.368-1.02.368h-8.137v8.336q0 .623-.426 1.049-.425.425-1.049.425z" fill="#1a1a1a"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 36"> + <path fill="#ffcc4d" d="M149.998 32.001A3.998 3.998 0 0 1 146 36H4.003A3.999 3.999 0 0 1 0 32.001V4.003A4.001 4.001 0 0 1 3.999 0h142a3.999 3.999 0 0 1 4 4.003z"/> + <path fill="#664500" d="M136.619 22.503q0 1.739-1.822 1.739-1.84 0-1.84-1.739V8.633q0-1.724 1.84-1.724 1.822 0 1.822 1.727zm-1.822 7.665q-.979 0-1.595-.605-.62-.616-.62-1.56 0-.96.605-1.58.616-.616 1.61-.616.96 0 1.576.635.62.635.62 1.56 0 .911-.62 1.55-.616.616-1.576.616zm-16.781-7.423q.325 2.052 1.398 3.077 1.092 1.024 2.93 1.024 1.122 0 1.806-.227.684-.245 1.742-.91.586-.36 1.059-.36.604 0 1.088.556.507.537.507 1.104 0 1.171-1.955 2.165-1.935.994-4.312.994-3.727 0-5.877-2.343-2.147-2.362-2.147-6.35 0-4.082 2.083-6.527 2.082-2.442 5.714-2.442 3.254 0 5.224 2.136 1.969 2.132 1.969 5.597 0 1.32-.522 1.92-.518.586-1.61.586zm7.536-3.205q-.132-1.678-1.092-2.683-.945-1.013-2.408-1.013-1.564 0-2.623.979-1.058.975-1.349 2.717zm-15.27 8.969q0 .831-.388 1.22-.378.375-1.448.375-.979 0-1.338-.36-.355-.377-.355-1.235V13.274l-4.8 8.526q-.492.866-.98 1.093-.472.211-1.091.211-.632 0-1.123-.227-.488-.245-.945-1.043l-4.766-8.428v15.103q0 .847-.359 1.22-.359.375-1.368.375-1.058 0-1.433-.378-.374-.39-.374-1.217V9.173q0-2.264 2.166-2.264.797 0 1.255.295.472.29.907 1.073l6.04 10.84 6.172-11.086q.325-.551.778-.831.454-.291 1.323-.291 1.054 0 1.591.537.537.521.537 1.727zm-36.279-7.295q2.18 1.905 3.273 3.712 1.108 1.791 1.108 3.485 0 1.693-1.871 1.693-.847 0-1.255-.325-.39-.34-.552-1.172-.28-1.5-1.141-2.82-.847-1.315-2.264-2.471-1.625 1.27-2.57 2.589-.926 1.315-1.157 2.698-.162.896-.586 1.21-.404.29-1.319.29-1.757 0-1.757-1.757 0-1.613 1.171-3.42 1.172-1.807 3.534-3.79-1.855-1.758-2.929-3.565-1.073-1.807-1.073-3.322 0-1.675 1.822-1.675.895 0 1.3.356.423.34.604 1.24.227 1.171.847 2.279.635 1.088 2.196 2.619 1.693-1.55 2.426-2.669.73-1.122.926-2.23.178-.895.586-1.24.424-.355 1.32-.355 1.84 0 1.84 1.709 0 1.481-1.126 3.224-1.123 1.723-3.353 3.707zM59.176 5.832q.847 0 1.448.62.62.604.62 1.451 0 .847-.62 1.448-.601.585-1.448.585t-1.447-.585q-.586-.605-.586-1.448 0-.847.604-1.451.601-.616 1.43-.616zm1.84 22.741q0 1.53-1.87 1.53-1.807 0-1.807-1.53V14.037q0-.763.405-1.107.423-.356 1.436-.356.99 0 1.413.356.424.359.424 1.107zm-16.213-.098q0 .847-.454 1.236-.438.393-1.432.393-1.01 0-1.433-.378-.404-.39-.404-1.247V10.277q0-3.111 3.156-3.111h8.137q1.058 0 1.497.34.442.34.442 1.368 0 .994-.473 1.384-.472.378-1.466.378h-7q-.242 0-.404.177-.163.178-.163.454v5.37h6.134q1.093 0 1.531.378.439.356.439 1.316 0 .979-.473 1.383-.468.393-1.497.393h-6.134z"/> + <path fill="#8899a6" d="M26.494 19.453c-.453 0-.899.057-1.326.159l-7.623-7.623a5.889 5.889 0 0 0-5.734-7.22c-.661 0-1.542.677-.809 1.41l2.204 2.204s.733 1.466-.734 2.937c-1.47 1.466-2.936.733-2.936.733L7.332 9.849c-.733-.733-1.406.144-1.406.813a5.889 5.889 0 0 0 7.215 5.73l7.62 7.623a5.862 5.862 0 0 0 5.733 7.215c.662 0 1.543-.673.81-1.41l-2.204-2.2s-.733-1.47.737-2.936c1.466-1.466 2.933-.733 2.933-.733l2.203 2.2c.737.737 1.41-.144 1.41-.81a5.89 5.89 0 0 0-5.889-5.888z"/> +</svg> diff --git a/lib/images/smileys/question.svg b/lib/images/smileys/question.svg index d76931bc4..657616f8e 100644 --- a/lib/images/smileys/question.svg +++ b/lib/images/smileys/question.svg @@ -1 +1,4 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#BE1931" d="M17 27c-1.657 0-3-1.343-3-3v-4c0-1.657 1.343-3 3-3 .603-.006 6-1 6-5 0-2-2-4-5-4-2.441 0-4 2-4 3 0 1.657-1.343 3-3 3s-3-1.343-3-3c0-4.878 4.58-9 10-9 8 0 11 5.982 11 11 0 4.145-2.277 7.313-6.413 8.92-.9.351-1.79.587-2.587.747V24c0 1.657-1.343 3-3 3z"/><circle fill="#BE1931" cx="17" cy="32" r="3"/></svg>
\ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"> + <circle cx="18" cy="18" r="18" fill="#ffcc4d"/> + <path fill="#664500" d="M15.579 26.981a2.421 2.421 0 1 1 4.842.008 2.42 2.42 0 0 1-4.838-.008zm2.333-4.158c-1.07 0-2.03-.79-2.03-1.87v-2.609a1.95 1.95 0 0 1 1.94-1.958c.389-.004 3.878-.654 3.878-3.262 0-1.304-1.293-2.608-3.232-2.608-1.576 0-2.585 1.304-2.585 1.954a1.95 1.95 0 0 1-1.94 1.958 1.947 1.947 0 0 1-1.935-1.958c0-3.183 2.96-5.87 6.464-5.87 5.167 0 7.106 3.9 7.106 7.174 0 2.706-1.474 4.774-4.146 5.821-.583.227-.813.303-1.331.405v.869c0 1.081-1.119 1.958-2.189 1.958z"/> +</svg> diff --git a/lib/plugins/acl/lang/hu/lang.php b/lib/plugins/acl/lang/hu/lang.php index cc35243e1..867638333 100644 --- a/lib/plugins/acl/lang/hu/lang.php +++ b/lib/plugins/acl/lang/hu/lang.php @@ -2,13 +2,11 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Sandor TIHANYI <stihanyi+dw@gmail.com> * @author Siaynoq Mage <siaynoqmage@gmail.com> - * @author schilling.janos@gmail.com + * @author schilling.janos <schilling.janos@gmail.com> * @author Szabó Dávid <szabo.david@gyumolcstarhely.hu> - * @author Sándor TIHANYI <stihanyi+dw@gmail.com> - * @author David Szabo <szabo.david@gyumolcstarhely.hu> * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['admin_acl'] = 'Hozzáférési lista (ACL) kezelÅ‘'; diff --git a/lib/plugins/acl/lang/pt-br/lang.php b/lib/plugins/acl/lang/pt-br/lang.php index 466a2d23a..962d91b1d 100644 --- a/lib/plugins/acl/lang/pt-br/lang.php +++ b/lib/plugins/acl/lang/pt-br/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Eduardo Mozart de Oliveira <eduardomozart182@gmail.com> * @author Luis Fernando Enciso <lfenciso@certto.com.br> * @author Alauton/Loug * @author Frederico Gonçalves Guimarães <frederico@teia.bio.br> @@ -28,7 +29,7 @@ $lang['btn_select'] = 'Selecionar'; $lang['p_user_id'] = 'O usuário <b class="acluser">%s</b> possui as seguintes permissões na página <b class="aclpage">%s</b>: <i>%s</i>.'; $lang['p_user_ns'] = 'O usuário <b class="acluser">%s</b> possui as seguintes permissões no espaço de nomes <b class="aclns">%s</b>: <i>%s</i>.'; $lang['p_group_id'] = 'Os membros do grupo <b class="aclgroup">%s</b> possuem as seguintes permissões na página <b class="aclpage">%s</b>: <i>%s</i>.'; -$lang['p_group_ns'] = 'Os membros do grupo <b class="aclgroup">%s</b> possuem as seguintes permissões no espaço de nomes <b class="aclpage">%s</b>: <i>%s</i>.'; +$lang['p_group_ns'] = 'Os membros do grupo <b class="aclgroup">%s</b> possuem as seguintes permissões no espaço de nomes <b class="aclns">%s</b>: <i>%s</i>.'; $lang['p_choose_id'] = 'Por favor <b>digite um usuário ou grupo</b> no formulário acima para ver ou editar as permissões para a página <b class="aclpage">%s</b>.'; $lang['p_choose_ns'] = 'Por favor <b>digite um usuário ou grupo</b> no formulário acima para ver ou editar as permissões para o espaço de nomes <b class="aclpage">%s</b>.'; $lang['p_inherited'] = 'Nota: Essas permissões não foram definidas explicitamente, mas sim herdadas de outros grupos ou espaço de nomes superiores.'; diff --git a/lib/plugins/authad/lang/bg/settings.php b/lib/plugins/authad/lang/bg/settings.php index bcd2968dc..f77fc899d 100644 --- a/lib/plugins/authad/lang/bg/settings.php +++ b/lib/plugins/authad/lang/bg/settings.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Alinur <alinur@danwin1210.de> * @author Kiril <neohidra@gmail.com> */ $lang['account_suffix'] = 'ÐаÑтавка на акаунта Ви. Ðапример <code>@нÑкакъв.домейн.org</code>'; @@ -17,3 +18,4 @@ $lang['use_tls'] = 'Ползване на TLS ÑвързаноÑÑ‚ $lang['debug'] = 'Показване на допълнителна debug Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ грешка?'; $lang['expirywarn'] = 'Предупреждаване на потребителите Ð¥ дни преди изтичане валидноÑтта на паролата им. Въведете 0 за изключване.'; $lang['additional'] = 'СпиÑък Ñ Ð´Ð¾Ð¿ÑŠÐ»Ð½Ð¸Ñ‚ÐµÐ»Ð½Ð¸ AD атрибути за извличане от потребителÑките данни (разделÑйте ги ÑÑŠÑ Ð·Ð°Ð¿ÐµÑ‚Ð°Ñ). Ползва Ñе от нÑколко приÑтавки.'; +$lang['update_mail'] = 'Позволи на потребители да Ñи ÑменÑÑ‚ имейл адреÑите?'; diff --git a/lib/plugins/authad/lang/fr/settings.php b/lib/plugins/authad/lang/fr/settings.php index 0503c7ed0..3bb107ba8 100644 --- a/lib/plugins/authad/lang/fr/settings.php +++ b/lib/plugins/authad/lang/fr/settings.php @@ -13,7 +13,7 @@ $lang['domain_controllers'] = 'Une liste de contrôleurs de domaine séparés $lang['admin_username'] = 'Un utilisateur Active Directory avec accès aux données de tous les autres utilisateurs. Facultatif, mais nécessaire pour certaines actions telles que l\'envoi de courriels d\'abonnement.'; $lang['admin_password'] = 'Le mot de passe de l\'utilisateur ci-dessus.'; $lang['sso'] = 'Est-ce que l\'authentification unique (Single-Sign-On) par Kerberos ou NTLM doit être utilisée?'; -$lang['sso_charset'] = 'Le jeu de caractères de votre serveur web va passer le nom d\'utilisateur Kerberos ou NTLM. Vide pour UTF-8 ou latin-1. Nécessite l\'extension iconv.'; +$lang['sso_charset'] = 'Le jeu de caractères que votre serveur web utilisera pour transmettre le nom d\'utilisateur Kerberos ou NTLM. Vide pour UTF-8 ou latin-1. Nécessite l\'extension iconv.'; $lang['real_primarygroup'] = 'Est-ce que le véritable groupe principal doit être résolu au lieu de présumer "Domain Users" (plus lent)?'; $lang['use_ssl'] = 'Utiliser une connexion SSL? Si utilisée, n\'activez pas TLS ci-dessous.'; $lang['use_tls'] = 'Utiliser une connexion TLS? Si utilisée, n\'activez pas SSL ci-dessus.'; diff --git a/lib/plugins/authad/lang/hu/lang.php b/lib/plugins/authad/lang/hu/lang.php index 023e6b956..21f7fbb2c 100644 --- a/lib/plugins/authad/lang/hu/lang.php +++ b/lib/plugins/authad/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['domain'] = 'Bejelentkezési tartomány'; diff --git a/lib/plugins/authad/lang/hu/settings.php b/lib/plugins/authad/lang/hu/settings.php index be0592d68..20dc0a690 100644 --- a/lib/plugins/authad/lang/hu/settings.php +++ b/lib/plugins/authad/lang/hu/settings.php @@ -2,7 +2,8 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * + * @author Hamp Gábor <gabor.hamp@gmail.com> * @author Marton Sebok <sebokmarton@gmail.com> * @author Marina Vladi <deldadam@gmail.com> */ @@ -19,3 +20,4 @@ $lang['use_tls'] = 'TLS használata? Ha használjuk, tiltsuk le az $lang['debug'] = 'További hibakeresési üzenetek megjelenÃtése hiba esetén'; $lang['expirywarn'] = 'Felhasználók értesÃtése ennyi nappal a jelszavuk lejárata elÅ‘tt. 0 a funkció kikapcsolásához.'; $lang['additional'] = 'VesszÅ‘vel elválasztott lista a további AD attribútumok lekéréséhez. Néhány bÅ‘vÃtmény használhatja.'; +$lang['update_mail'] = 'A felhasználók frissÃthetik (megváltozatathatják) az emailcÃmüket?'; diff --git a/lib/plugins/authldap/lang/fa/settings.php b/lib/plugins/authldap/lang/fa/settings.php index 658cdf8ba..f41cf1893 100644 --- a/lib/plugins/authldap/lang/fa/settings.php +++ b/lib/plugins/authldap/lang/fa/settings.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Faramarz Karamizadeh <f.karamizadeh@yahoo.com> * @author علیرضا ایوز <info@alirezaivaz.ir> * @author Masoud Sadrnezhaad <masoud@sadrnezhaad.ir> * @author Mohammad Sadegh <msdn2013@gmail.com> diff --git a/lib/plugins/authldap/lang/hu/lang.php b/lib/plugins/authldap/lang/hu/lang.php index 07c16f3f0..0736dc4d4 100644 --- a/lib/plugins/authldap/lang/hu/lang.php +++ b/lib/plugins/authldap/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['connectfail'] = 'Az LDAP nem tudott csatlakozni: %s'; diff --git a/lib/plugins/authldap/lang/hu/settings.php b/lib/plugins/authldap/lang/hu/settings.php index 364a1e987..754012587 100644 --- a/lib/plugins/authldap/lang/hu/settings.php +++ b/lib/plugins/authldap/lang/hu/settings.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> * @author Marina Vladi <deldadam@gmail.com> */ diff --git a/lib/plugins/authpdo/_test/sqlite.test.php b/lib/plugins/authpdo/_test/sqlite.test.php index 58fcadcb8..4816f8e33 100644 --- a/lib/plugins/authpdo/_test/sqlite.test.php +++ b/lib/plugins/authpdo/_test/sqlite.test.php @@ -106,7 +106,7 @@ class sqlite_plugin_authpdo_test extends DokuWikiTest { $this->assertTrue($ok); $groups = $auth->selectGroups(); $this->assertArrayHasKey('test', $groups); - $this->assertEquals(3, $groups['test']['gid']); + $this->assertEquals(4, $groups['test']['gid']); } /** @@ -131,12 +131,12 @@ class sqlite_plugin_authpdo_test extends DokuWikiTest { $this->assertEquals('admin', $info['user']); $this->assertEquals('The Admin', $info['name']); $this->assertEquals('admin@example.com', $info['mail']); - $this->assertEquals(array('admin', 'user'), $info['grps']); + $this->assertEquals(array('additional', 'admin', 'user'), $info['grps']); // group retrieval - $this->assertEquals(array('admin', 'user'), $auth->retrieveGroups()); - $this->assertEquals(array('user'), $auth->retrieveGroups(1)); - $this->assertEquals(array('admin'), $auth->retrieveGroups(0, 1)); + $this->assertEquals(array('additional', 'admin', 'user'), $auth->retrieveGroups()); + $this->assertEquals(array('admin', 'user'), $auth->retrieveGroups(1)); + $this->assertEquals(array('additional'), $auth->retrieveGroups(0, 1)); // user creation $auth->createUser('test', 'password', 'A Test user', 'test@example.com', array('newgroup')); @@ -145,7 +145,7 @@ class sqlite_plugin_authpdo_test extends DokuWikiTest { $this->assertEquals('A Test user', $info['name']); $this->assertEquals('test@example.com', $info['mail']); $this->assertEquals(array('newgroup', 'user'), $info['grps']); - $this->assertEquals(array('admin', 'newgroup', 'user'), $auth->retrieveGroups()); + $this->assertEquals(array('additional', 'admin', 'newgroup', 'user'), $auth->retrieveGroups()); // user modification $auth->modifyUser('test', array('user' => 'tester', 'name' => 'The Test User', 'pass' => 'secret')); @@ -166,7 +166,7 @@ class sqlite_plugin_authpdo_test extends DokuWikiTest { 'name' => 'The Admin', 'mail' => 'admin@example.com', 'uid' => '1', - 'grps' => array('admin', 'user') + 'grps' => array('additional', 'admin', 'user') ), 'user' => array( 'user' => 'user', diff --git a/lib/plugins/authpdo/_test/test.sqlite3 b/lib/plugins/authpdo/_test/test.sqlite3 Binary files differindex 8d3a9ba61..9cf5e1475 100644 --- a/lib/plugins/authpdo/_test/test.sqlite3 +++ b/lib/plugins/authpdo/_test/test.sqlite3 diff --git a/lib/plugins/authpdo/lang/hu/lang.php b/lib/plugins/authpdo/lang/hu/lang.php index 1a2098eac..2dd525556 100644 --- a/lib/plugins/authpdo/lang/hu/lang.php +++ b/lib/plugins/authpdo/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['connectfail'] = 'Az adatbázishoz való csatlakozás sikertelen.'; diff --git a/lib/plugins/authpdo/lang/ko/settings.php b/lib/plugins/authpdo/lang/ko/settings.php index e2361d581..da9beb1c6 100644 --- a/lib/plugins/authpdo/lang/ko/settings.php +++ b/lib/plugins/authpdo/lang/ko/settings.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author merefox <admin@homerecz.com> * @author pavement <pavement@rael.cc> * @author Traend <Traend@ruu.kr> */ diff --git a/lib/plugins/authplain/_test/escaping.test.php b/lib/plugins/authplain/_test/escaping.test.php index 58f1025d7..7790d9308 100644 --- a/lib/plugins/authplain/_test/escaping.test.php +++ b/lib/plugins/authplain/_test/escaping.test.php @@ -103,6 +103,31 @@ class helper_plugin_authplain_escaping_test extends DokuWikiTest { $this->assertEquals($escaped, $result[2]); } } + + /** + * @see testCleaning + */ + public function provideCleaning() + { + return [ + ['user', 'user'], + ['USER', 'user'], + [' USER ', 'user'], + [' US ER ', 'us_er'], + ['http://foo;bar', 'http_foo_bar'], + ]; + } + + /** + * @param string $input + * @param string $expected + * @dataProvider provideCleaning + */ + public function testCleaning($input, $expected) + { + $this->assertEquals($expected, $this->auth->cleanUser($input)); + $this->assertEquals($expected, $this->auth->cleanGroup($input)); + } } /** diff --git a/lib/plugins/authplain/auth.php b/lib/plugins/authplain/auth.php index a92fb3b2c..f2dd4f9c8 100644 --- a/lib/plugins/authplain/auth.php +++ b/lib/plugins/authplain/auth.php @@ -354,7 +354,8 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin public function cleanUser($user) { global $conf; - return cleanID(str_replace(':', $conf['sepchar'], $user)); + + return cleanID(str_replace([':', '/', ';'], $conf['sepchar'], $user)); } /** @@ -366,7 +367,8 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin public function cleanGroup($group) { global $conf; - return cleanID(str_replace(':', $conf['sepchar'], $group)); + + return cleanID(str_replace([':', '/', ';'], $conf['sepchar'], $group)); } /** diff --git a/lib/plugins/authplain/lang/hu/lang.php b/lib/plugins/authplain/lang/hu/lang.php index 5f684d722..84cfbbeb6 100644 --- a/lib/plugins/authplain/lang/hu/lang.php +++ b/lib/plugins/authplain/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['userexists'] = 'Sajnáljuk, ilyen azonosÃtójú felhasználónk már van.'; diff --git a/lib/plugins/config/lang/bg/lang.php b/lib/plugins/config/lang/bg/lang.php index 04aa5b0a3..515905840 100644 --- a/lib/plugins/config/lang/bg/lang.php +++ b/lib/plugins/config/lang/bg/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Alinur <alinur@danwin1210.de> * @author Salif Mehmed <salif13mehmed@gmail.com> * @author Nikolay Vladimirov <nikolay@vladimiroff.com> * @author Viktor Usunov <usun0v@mail.bg> diff --git a/lib/plugins/config/lang/fa/lang.php b/lib/plugins/config/lang/fa/lang.php index e9c4e3cd6..e65ffbf02 100644 --- a/lib/plugins/config/lang/fa/lang.php +++ b/lib/plugins/config/lang/fa/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Faramarz Karamizadeh <f.karamizadeh@yahoo.com> * @author علیرضا ایوز <info@alirezaivaz.ir> * @author Masoud Sadrnezhaad <masoud@sadrnezhaad.ir> * @author behrad eslamifar <behrad_es@yahoo.com) diff --git a/lib/plugins/config/lang/fi/lang.php b/lib/plugins/config/lang/fi/lang.php index e8d7c8f4c..471e2fc13 100644 --- a/lib/plugins/config/lang/fi/lang.php +++ b/lib/plugins/config/lang/fi/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Pasi <zazuu@zazuu.net> * @author Tuomo Hartikainen <tuomo.hartikainen@heksia.fi> * @author otto <otto@valjakko.net> * @author Teemu Mattila <ghcsystems@gmail.com> diff --git a/lib/plugins/config/lang/hu/lang.php b/lib/plugins/config/lang/hu/lang.php index 71782632a..fbe53a28f 100644 --- a/lib/plugins/config/lang/hu/lang.php +++ b/lib/plugins/config/lang/hu/lang.php @@ -3,12 +3,12 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Hamp Gábor <gabor.hamp@gmail.com> + * @author Viktor Horváth <horvath.viktor@forrastrend.hu> * @author Sandor TIHANYI <stihanyi+dw@gmail.com> * @author Siaynoq Mage <siaynoqmage@gmail.com> - * @author schilling.janos@gmail.com + * @author schilling.janos <schilling.janos@gmail.com> * @author Szabó Dávid <szabo.david@gyumolcstarhely.hu> - * @author Sándor TIHANYI <stihanyi+dw@gmail.com> - * @author David Szabo <szabo.david@gyumolcstarhely.hu> * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['menu'] = 'BeállÃtóközpont'; @@ -127,6 +127,8 @@ $lang['rss_content'] = 'Mit mutassunk az XML hÃrfolyam elemekben?'; $lang['rss_update'] = 'Hány másodpercenként frissÃtsük az XML hÃrfolyamot?'; $lang['rss_show_summary'] = 'A hÃrfolyam cÃmébe összefoglaló helyezése'; $lang['rss_media'] = 'Milyen változások legyenek felsorolva az XML hÃrfolyamban?'; +$lang['rss_media_o_both'] = 'mindkettÅ‘'; +$lang['rss_media_o_pages'] = 'oldalak'; $lang['updatecheck'] = 'FrissÃtések és biztonsági figyelmeztetések figyelése. Ehhez a DokuWikinek kapcsolatba kell lépnie a update.dokuwiki.org-gal.'; $lang['userewrite'] = 'Szép URL-ek használata'; $lang['useslash'] = 'Per-jel használata névtér-elválasztóként az URL-ekben'; @@ -144,6 +146,8 @@ $lang['xsendfile'] = 'Használjuk az X-Sendfile fejlécet, hogy a we $lang['renderer_xhtml'] = 'Az elsÅ‘dleges (xhtml) wiki kimenet generálója'; $lang['renderer__core'] = '%s (dokuwiki mag)'; $lang['renderer__plugin'] = '%s (bÅ‘vÃtmény)'; +$lang['search_fragment_o_exact'] = 'pontosan'; +$lang['search_fragment_o_contains'] = 'tartalmaz'; $lang['dnslookups'] = 'A DokuWiki megpróbál hosztneveket keresni a távoli IP-cÃmekhez. Amennyiben lassú, vagy nem működÅ‘ DNS-szervered van vagy csak nem szeretnéd ezt a funkciót, tiltsd le ezt az opciót!'; $lang['proxy____host'] = 'Proxy-szerver neve'; $lang['proxy____port'] = 'Proxy port'; diff --git a/lib/plugins/config/lang/ko/lang.php b/lib/plugins/config/lang/ko/lang.php index 2d2582a09..de1d73006 100644 --- a/lib/plugins/config/lang/ko/lang.php +++ b/lib/plugins/config/lang/ko/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author merefox <admin@homerecz.com> * @author pavement <pavement@rael.cc> * @author Traend <Traend@ruu.kr> * @author Seungheon Song <esketch@gmail.com> @@ -152,6 +153,7 @@ $lang['renderer_xhtml'] = '주요 (xhtml) 위키 ì¶œë ¥ì— ì‚¬ìš©í• ë Œë $lang['renderer__core'] = '%s (ë„ì¿ ìœ„í‚¤ 코어)'; $lang['renderer__plugin'] = '%s (플러그ì¸)'; $lang['search_nslimit'] = 'ê²€ìƒ‰ì„ í˜„ìž¬ X 네임스페ì´ìŠ¤ë¡œ ì œí•œí•˜ì‹ì‹œì˜¤. ë” ê¹Šì€ ë„¤ìž„ìŠ¤íŽ˜ì´ìФ ë‚´ì˜ íŽ˜ì´ì§€ì—서 ê²€ìƒ‰ì„ ì‹¤í–‰í•˜ë©´ 첫 번째 X 네임스페ì´ìŠ¤ê°€ 필터로 추가ë©ë‹ˆë‹¤.'; +$lang['search_fragment_o_exact'] = 'ì •í™•í•œ'; $lang['dnslookups'] = 'ë„ì¿ ìœ„í‚¤ê°€ 문서를 편집하는 사용ìžì˜ ì›ê²© IP ì£¼ì†Œì— ëŒ€í•œ 호스트 ì´ë¦„ì„ ì¡°íšŒí•©ë‹ˆë‹¤. 서버가 ëŠë¦¬ê±°ë‚˜ DNS 서버를 ìž‘ë™í•˜ì§€ 않거나 ì´ ê¸°ëŠ¥ì„ ì›í•˜ì§€ 않으면, ì´ ì˜µì…˜ì„ ë¹„í™œì„±í™”í•˜ì„¸ìš”'; $lang['jquerycdn'] = 'ì œì´ì¿¼ë¦¬(jQuery)와 ì œì´ì¿¼ë¦¬UI 스í¬ë¦½íЏ 파ì¼ì„ 컨í…ì¸ ì „ì†¡ë„¤íŠ¸ì›Œí¬(CDN)ì—서 불러와야만 합니까? ì´ê²ƒì€ 추가ì ì¸ HTTPìš”ì²ì„ 합니다. 하지만 파ì¼ì´ 빨리 ë¶ˆëŸ¬ì§€ê³ ìºì‰¬ì— ì €ìž¥ë˜ê²Œ í• ìˆ˜ 있습니다.'; $lang['jquerycdn_o_0'] = '컨í…ì¸ ì „ì†¡ë„¤íŠ¸ì›Œí¬(CDN) 사용 안 함. 로컬 ì „ì†¡ë§Œ 함'; diff --git a/lib/plugins/config/lang/nl/lang.php b/lib/plugins/config/lang/nl/lang.php index 6346143b6..89ec542bd 100644 --- a/lib/plugins/config/lang/nl/lang.php +++ b/lib/plugins/config/lang/nl/lang.php @@ -3,10 +3,10 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Mark Prins <mprins@users.sf.net> * @author PBU <pbu@xs4all.nl> * @author Gerrit Uitslag <klapinklapin@gmail.com> * @author Harriet Neitz <harrietneitz@gmail.com> - * @author mark prins <mprins@users.sf.net> * @author Pieter van der Meulen <pieter@vdmeulen.net> * @author Wouter Schoot <wouter@schoot.org> * @author John de Graaff <john@de-graaff.net> @@ -127,12 +127,14 @@ $lang['mailfrom'] = 'E-mailadres van afzender voor automatische e-m $lang['mailreturnpath'] = 'Email adres voor de ontvanger van meldingen van niet-afleverbare berichten'; $lang['mailprefix'] = 'Te gebruiken voorvoegsel voor onderwerp automatische email. Leeglaten gebruik de wikititel.'; $lang['htmlmail'] = 'Zend multipart HTML e-mail. Dit ziet er beter uit, maar is groter. Uitschakelen betekent e-mail in platte tekst.'; +$lang['dontlog'] = 'Schakel logging uit voor de volgende opties.'; $lang['sitemap'] = 'Genereer Google sitemap (dagen). 0 betekent uitschakelen.'; $lang['rss_type'] = 'XML feed type'; $lang['rss_linkto'] = 'XML feed linkt naar'; $lang['rss_content'] = 'Wat moet er in de XML feed items weergegeven worden?'; $lang['rss_update'] = 'XML feed verversingsinterval (sec)'; $lang['rss_show_summary'] = 'XML feed samenvatting in titel weergeven'; +$lang['rss_show_deleted'] = 'XML-feed Toon verwijderde feeds'; $lang['rss_media'] = 'Welk type verandering moet in de XML feed worden weergegeven?'; $lang['rss_media_o_both'] = 'beide'; $lang['rss_media_o_pages'] = 'pagina\'s'; @@ -161,6 +163,8 @@ $lang['search_fragment_o_starts_with'] = 'begint met'; $lang['search_fragment_o_ends_with'] = 'eindigt op'; $lang['search_fragment_o_contains'] = 'bevat'; $lang['trustedproxy'] = 'Vertrouw op doorstuurproxy\'s die overeenkomen met deze reguliere expressie over het echte client-IP dat ze rapporteren. De standaard komt overeen met lokale netwerken. Laat leeg om geen proxy te vertrouwen.'; +$lang['_feature_flags'] = 'Functievlaggen'; +$lang['defer_js'] = 'Stel uitvoeren van javascript uit todat de HTML van de pagina is geparsed. Verbetert de waargenomen paginasnelheid, maar kan bij een klein aantal plug-ins voor problemen zorgen.'; $lang['dnslookups'] = 'DokuWiki zoekt de hostnamen van IP-adressen van gebruikers die pagina wijzigen op. Schakel deze optie uit als je geen of een langzame DNS server hebt.'; $lang['jquerycdn'] = 'Moet er een CDN gebruikt worden om de jQuery en jQuery UI bestanden te laden. Dit zorgt voor extra HTTP verzoeken, maar bestanden laden mogelijk sneller en zitten misschien al in de cache van de gebruiker.'; $lang['jquerycdn_o_0'] = 'Geen CDN gebruiken'; diff --git a/lib/plugins/config/lang/pt-br/lang.php b/lib/plugins/config/lang/pt-br/lang.php index 78a20574e..75412d903 100644 --- a/lib/plugins/config/lang/pt-br/lang.php +++ b/lib/plugins/config/lang/pt-br/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Eduardo Mozart de Oliveira <eduardomozart182@gmail.com> * @author ANDRE BASSANI DE FREITAS <dedebf@gmail.com> * @author Aleksandr Selivanov <alexgearbox@yandex.ru> * @author Davi Jorge <davimoises2015@hotmail.com> @@ -134,6 +135,7 @@ $lang['mailfrom'] = 'Endereço de e-mail a ser utilizado para mensa $lang['mailreturnpath'] = 'Endereço de e-mail do destinatário para notificações de falha de entrega'; $lang['mailprefix'] = 'Prefixo do assunto dos e-mails de envio automático'; $lang['htmlmail'] = 'Enviar e-mail HTML multipartes, que têm uma aparência melhor, mas um tamanho maior. Desabilite para enviar e-mails em texto puro.'; +$lang['dontlog'] = 'Desabilita o registro de log para os seguintes tipos de logs.'; $lang['sitemap'] = 'Gerar Google Sitemap (dias)'; $lang['rss_type'] = 'Tipo de fonte XML'; $lang['rss_linkto'] = 'Os links da fonte XML apontam para'; diff --git a/lib/plugins/config/lang/zh-tw/lang.php b/lib/plugins/config/lang/zh-tw/lang.php index e2c9fb099..b99a8df36 100644 --- a/lib/plugins/config/lang/zh-tw/lang.php +++ b/lib/plugins/config/lang/zh-tw/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Chun-Chung Chen <cjj@u.washington.edu> * @author GHSRobert Ciang <robertus0617@gmail.com> * @author Li-Jiun Huang <ljhuang.tw@gmail.com> * @author http://www.chinese-tools.com/tools/converter-simptrad.html diff --git a/lib/plugins/extension/action.php b/lib/plugins/extension/action.php index 3bb044825..b57fe558e 100644 --- a/lib/plugins/extension/action.php +++ b/lib/plugins/extension/action.php @@ -57,8 +57,13 @@ class action_plugin_extension extends DokuWiki_Action_Plugin switch ($act) { case 'enable': case 'disable': - $extension->$act(); //enables/disables + if(getSecurityToken() != $INPUT->str('sectok')) { + http_status(403); + echo 'Security Token did not match. Possible CSRF attack.'; + return; + } + $extension->$act(); //enables/disables $reverse = ($act == 'disable') ? 'enable' : 'disable'; $return = array( diff --git a/lib/plugins/extension/lang/el/intro_install.txt b/lib/plugins/extension/lang/el/intro_install.txt index bdb342d8b..f2177e176 100644 --- a/lib/plugins/extension/lang/el/intro_install.txt +++ b/lib/plugins/extension/lang/el/intro_install.txt @@ -1 +1 @@ -Εδώ μποÏείτε να φοÏτώσετε επιπÏόσθετα με το χÎÏι και Ï€Ïότυπα είτε με αποστολή από τον υπολογιστή ή με την παÏοχή ενός URLμε άμεσο κατÎβασμα από τον υπολογιστή.
\ No newline at end of file +Εδώ μποÏείτε να εγκαταστήσετε Ï€Ïόσθετα και Ï€Ïότυπα είτε ανεβάζοντάς τα είτε μÎσω URL. diff --git a/lib/plugins/extension/lang/el/intro_plugins.txt b/lib/plugins/extension/lang/el/intro_plugins.txt index 189a27c4e..2377d295a 100644 --- a/lib/plugins/extension/lang/el/intro_plugins.txt +++ b/lib/plugins/extension/lang/el/intro_plugins.txt @@ -1 +1 @@ -Αυτά είναι το επιπÏόσθετα που εισήχθηκαν τώÏα στο DokuWiki. ΜποÏείτε να ενεÏγοποιήσετε ή απενεÏγοποιήσετε ή να ακυÏώσετε την εγκατάσταση εδώ. Οι ενημεÏώσεις των επιπÏόσθετων Ï€Ïοβάλλονται εδώ επίσης, βεβαιωθείτε πως διαβάσατε τα σχετικά ÎγγÏαφα Ï€Ïιν την ενημÎÏωση.
\ No newline at end of file +Αυτά είναι το εγκατεστημÎνα Ï€Ïόσθετα στο DokuWiki σας. Εδώ μποÏείτε να τα ενεÏγοποιήσετε, απενεÏγοποιήσετε ή να απεγκαταστήσετε. Εδώ εμφανίζονται και ενημεÏώσεις των Ï€Ïόσθετων, διαβάστε την τεκμηÏίωση του κάθε Ï€Ïόσθετου Ï€Ïιν την ενημÎÏωση. diff --git a/lib/plugins/extension/lang/el/intro_search.txt b/lib/plugins/extension/lang/el/intro_search.txt index 1fdbfe10e..7e9528174 100644 --- a/lib/plugins/extension/lang/el/intro_search.txt +++ b/lib/plugins/extension/lang/el/intro_search.txt @@ -1 +1 @@ -Πατώντας στο τόξο Îχετε Ï€Ïόσβαση σε στοιχεία Ï„Ïίτων του [[doku>plugins|plugins]] and [[doku>template|templates]] DokuWiki. ΠαÏακαλώ να γνωÏίζετε ότι η εγκατάσταση ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï„Ïίτου μποÏεί να θÎσει θÎμα **Ïίσκου ασφάλειας**, για την οποία μποÏεί να θÎλετε να διαβάζετε Ï€Ïώτα.you[[doku>security#plugin_security|plugin security]] +Σε αυτή την καÏÏ„Îλα Îχετε Ï€Ïόσβαση σε [[doku>plugins|plugins]] and [[doku>template|templates]] DokuWiki. Η εγκατάσταση Î»Î¿Î³Î¹ÏƒÎ¼Î¹ÎºÎ¿Ï Ï„Ïίτων δημιουÏγών αποτελεί **Ïίσκο ασφάλειας**, για το οποίο μποÏείτε να διαβάσετε το [[doku>security#plugin_security|plugin security]] diff --git a/lib/plugins/extension/lang/el/lang.php b/lib/plugins/extension/lang/el/lang.php index cfbea5d0d..599b1b685 100644 --- a/lib/plugins/extension/lang/el/lang.php +++ b/lib/plugins/extension/lang/el/lang.php @@ -3,87 +3,103 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * - * @author Katerina Katapodi <extragold1234@hotmail.com> */ -$lang['menu'] = 'ΚÏÏια ΠαÏάταση'; -$lang['tab_plugins'] = 'ΕγκαταστημÎνα ΕπιπÏόσθετα'; -$lang['tab_templates'] = 'ΕγκατεστημÎνα μοντÎλα'; +$lang['menu'] = 'ΔιαχείÏιση Ï€Ïόσθετων'; +$lang['tab_plugins'] = 'ΕγκαταστημÎνα Ï€Ïόσθετα'; +$lang['tab_templates'] = 'ΕγκατεστημÎνα Ï€Ïότυπα'; $lang['tab_search'] = 'Αναζήτηση και Εγκατάσταση'; -$lang['tab_install'] = 'Εγκατάσταση ΧειÏοκίνητα'; -$lang['notimplemented'] = 'Αυτό το χαÏακτηÏιστικό δεν Îχει καθιεÏωθεί ακόμα'; -$lang['notinstalled'] = 'Αυτή η Ï€ÏοÎκταση δεν Îχει εγκαταταθεί'; -$lang['alreadyenabled'] = 'Αυτή το επιπÏόσθετο Îχει ήδη ενεÏγοποιηθεί.'; -$lang['alreadydisabled'] = 'Το επιπÏόσθετο Îχει ήδη απενεÏγοποιηθεί.'; -$lang['pluginlistsaveerror'] = 'ΥπήÏξε σφάλμα κατά την αποθήκευση της λίστας επιπÏόσθετων.'; +$lang['tab_install'] = 'ΧειÏοκίνητη Εγκατάσταση'; +$lang['notimplemented'] = 'Αυτή η λειτουÏγικότητα δεν Îχει υλοποιηθεί ακόμα'; +$lang['notinstalled'] = 'Αυτό το Ï€Ïόσθετο δεν Îχει εγκαταταθεί'; +$lang['alreadyenabled'] = 'Αυτή το Ï€Ïόσθετο Îχει ήδη ενεÏγοποιηθεί.'; +$lang['alreadydisabled'] = 'Η επÎκταση Îχει ήδη απενεÏγοποιηθεί.'; +$lang['pluginlistsaveerror'] = 'ΥπήÏξε σφάλμα κατά την αποθήκευση της λίστας Ï€Ïόσθετων.'; $lang['unknownauthor'] = 'Άγνωστος συγγÏαφÎας '; -$lang['unknownversion'] = 'Άγνωστη εκδοχή '; -$lang['btn_info'] = 'Î Ïοβάλλετε πεÏισσότεÏες πληÏοφοÏίες'; +$lang['unknownversion'] = 'Άγνωστη Îκδοση '; +$lang['btn_info'] = 'Î Ïοβολή πεÏισσότεÏων πληÏοφοÏιών'; $lang['btn_update'] = 'ΕνημÎÏωση'; -$lang['btn_uninstall'] = 'ΑκÏÏωση εγκατάστασης'; +$lang['btn_uninstall'] = 'Απεγκατάσταση'; $lang['btn_enable'] = 'ΕνεÏγοποίηση'; $lang['btn_disable'] = 'ΑπενεÏγοποίηση'; -$lang['btn_install'] = 'ΡÏθμιση, εγκατάσταση'; -$lang['btn_reinstall'] = 'Εγκαταστήστε ξανά'; -$lang['js']['reallydel'] = 'ΘÎλετε οπωσδήποτε να ακυÏώσετε αυτήν την Ï€ÏοÎκταση?'; +$lang['btn_install'] = 'Εγκατάσταση'; +$lang['btn_reinstall'] = 'Επανεγκατάσταση'; +$lang['js']['reallydel'] = 'ΘÎλετε να απεγκαταστήσετε αυτήν την επÎκταση?'; $lang['js']['display_viewoptions'] = 'ΕπιλογÎÏ‚:'; $lang['js']['display_enabled'] = 'ενεÏγοποίηση'; $lang['js']['display_disabled'] = 'απενεÏγοποίηση'; $lang['js']['display_updatable'] = 'Ï€ÏÎπει να ενημεÏωθεί'; -$lang['search_for'] = 'Î ÏοÎκταση Αναζήτησης'; +$lang['search_for'] = 'Αναζήτησης επÎκτασης'; $lang['search'] = 'Αναζήτηση'; $lang['extensionby'] = '<strong>%s</strong> από %s '; -$lang['screenshot'] = 'Εικονίδιο %s '; -$lang['popularity'] = 'Φήμη: %s%%'; +$lang['screenshot'] = 'Στιγμιότυπο %s '; +$lang['popularity'] = 'Δημοτικότητα: %s%%'; $lang['homepage_link'] = 'ΈγγÏαφα '; -$lang['bugs_features'] = 'Λάθη'; -$lang['tags'] = 'Tags '; -$lang['author_hint'] = 'Αναζητήστε πεÏαιτÎÏω από αυτόν τον συγγÏαφÎα'; -$lang['installed'] = 'Εγκατάσταση:'; -$lang['downloadurl'] = 'Κατεβάστε URL:'; -$lang['repository'] = 'ΧώÏος αÏχείων'; +$lang['bugs_features'] = 'Σφάλματα'; +$lang['tags'] = 'ΕτικÎτες '; +$lang['author_hint'] = 'Αναζητήστε Ï€Ïόσθετα από αυτόν τον δημιουÏγό'; +$lang['installed'] = 'ΕγκατεστημÎνα:'; +$lang['downloadurl'] = 'ΚατÎβασμα από URL:'; +$lang['repository'] = 'ΑÏχειοθήκη'; $lang['unknown'] = '<em>άγνωστο</em> '; -$lang['installed_version'] = 'ΜοÏφή εγκατάστασης:'; -$lang['install_date'] = 'Η τελευταία σας ενημÎÏωση:'; -$lang['available_version'] = 'ΔιαθÎσιμη μοÏφή;'; +$lang['installed_version'] = 'ΕγκατεστημÎνη Îκδοση:'; +$lang['install_date'] = 'Τελευταία ενημÎÏωση:'; +$lang['available_version'] = 'ΔιαθÎσιμη Îκδοση:'; $lang['compatible'] = 'Συμβατό με:'; $lang['depends'] = 'ΕξαÏτάται από:'; -$lang['similar'] = 'Όμοιο με : '; -$lang['conflicts'] = 'Αντιτίθεται στο:'; -$lang['donate'] = 'Έτσι? '; -$lang['donate_action'] = 'ΑγόÏασε στον συγγÏαφÎα Îναν καφÎ'; +$lang['similar'] = 'ΠαÏόμοιο με : '; +$lang['conflicts'] = 'ΣυγκÏοÏεται με:'; +$lang['donate'] = 'ΔωÏεά '; +$lang['donate_action'] = 'ΑγόÏασε στον δημιουÏγό Îναν καφÎ!'; $lang['repo_retry'] = 'Î Ïοσπαθήστε πάλι'; $lang['provides'] = 'ΠαÏÎχει; '; -$lang['status'] = 'Στάτους;'; +$lang['status'] = 'Κατάσταση:'; $lang['status_installed'] = 'εγκαταστημÎνο'; $lang['status_not_installed'] = 'μη εγκαταστημÎνο'; $lang['status_protected'] = 'Ï€ÏοστατευμÎνο'; $lang['status_enabled'] = 'ενεÏγοποιημÎνο'; $lang['status_disabled'] = 'απενεÏγοποιημÎνο'; -$lang['status_unmodifiable'] = 'δεν μποÏεί να Ï„Ïοποποιηθεί'; -$lang['status_plugin'] = 'επιπÏόσθετο'; -$lang['status_template'] = 'μοντÎλο'; -$lang['status_bundled'] = 'δεμÎνο'; -$lang['msg_enabled'] = 'Το επιπÏόσθετο %s ενεÏγοποιήθηκε'; -$lang['msg_disabled'] = 'Το επιπÏόσθετο %s απενεÏγοποιήθηκε'; -$lang['msg_delete_success'] = 'Η Ï€ÏοÎκταση %s δεν εγκαταστάθηκε '; -$lang['msg_delete_failed'] = 'Η ακÏÏωση εγκατάστασης Î ÏοÎκτασης %s απÎτυχε'; -$lang['msg_template_install_success'] = 'Το μοντÎλο %s εγκαταστάθηκε με επιτυχία '; -$lang['msg_template_update_success'] = 'Το μοντÎλο %s ενημεÏώθηκε με επιτυχία '; -$lang['msg_plugin_install_success'] = 'Το επιπÏόσθετο %s εγκαταστάθηκε με επιτυχία '; -$lang['msg_plugin_update_success'] = 'Το επιπÏόσθετο %s ενημεÏώθηκε με επιτυχία '; -$lang['msg_upload_failed'] = 'Το ανÎβασμα του φακÎλλου απÎτυχε'; -$lang['missing_dependency'] = '<strong>Ιδιότητα που λείπει ή απενεÏγοποιήθηκε:</strong> %s '; -$lang['security_issue'] = '<strong>Δεν είναι ασφαλÎÏ‚:</strong> %s '; +$lang['status_unmodifiable'] = 'μη Ï„Ïοποποιήσιμο'; +$lang['status_plugin'] = 'Ï€Ïόσθετο'; +$lang['status_template'] = 'Ï€Ïότυπο'; +$lang['status_bundled'] = 'σε ομάδα'; + +$lang['msg_enabled'] = 'Το Ï€Ïόσθετο %s ενεÏγοποιήθηκε'; +$lang['msg_disabled'] = 'Το Ï€Ïόσθετο %s απενεÏγοποιήθηκε'; +$lang['msg_delete_success'] = 'Η επÎκταση %s δεν εγκαταστάθηκε '; +$lang['msg_delete_failed'] = 'Η ακÏÏωση εγκατάστασης %s απÎτυχε'; +$lang['msg_template_install_success'] = 'Το Ï€Ïότυπο %s εγκαταστάθηκε με επιτυχία '; +$lang['msg_template_update_success'] = 'Το Ï€Ïότυπο %s ενημεÏώθηκε με επιτυχία '; +$lang['msg_plugin_install_success'] = 'Το Ï€Ïόσθετο %s εγκαταστάθηκε με επιτυχία '; +$lang['msg_plugin_update_success'] = 'Το Ï€Ïόσθετο %s ενημεÏώθηκε με επιτυχία '; +$lang['msg_upload_failed'] = 'Το ανÎβασμα του αÏχείου απÎτυχε'; + +$lang['missing_dependency'] = '<strong>ΕξάÏτηση που λείπει ή απενεÏγοποιήθηκε:</strong> %s'; +$lang['security_issue'] = '<strong>ΘÎμα ασφάλειας:</strong> %s '; $lang['security_warning'] = '<strong>Î Ïοειδοποίηση Ασφάλειας:</strong> %s '; -$lang['update_available'] = '<strong>ΕνημÎÏωση:</strong> Η νÎα εκδοχή %s είναι διαθÎσιμη. '; -$lang['wrong_folder'] = '<strong>Λάθος εγκατάσταση του επιπÏόσθετου:</strong> Δώστε όνομα ξανά στην λίστα διευθÏνσεων του επιπÏόσθετου "%s" στο "%s". '; -$lang['url_change'] = '<strong>URL άλλαξε:</strong> Ο Ï„Ïόπος κατεβάσματος του URL Îχει ανοίξει μια φοÏά από το Ï€Ïώτο κατÎβασμα. ΕλÎγξετε αν το νÎο URL ισχÏει Ï€Ïιν την ενημÎÏωση της επÎκτασης. (επιπÏόσθετου).<br />ΚαινοÏÏγιο: %s<br />Παλιό: %s '; -$lang['error_badurl'] = 'Τα URLs Ï€ÏÎπει να αÏχίζουν με http ή https '; -$lang['error_dircreate'] = 'Δεν μπόÏεσε να δημιουÏγήσει Ï€ÏοσωÏινό φάκελλο για να κατεβάσει αÏχεία'; -$lang['error_download'] = 'Δεν μπόÏεσε να κατεβάσει τον φάκελλο : %s'; -$lang['error_findfolder'] = 'Δεν μπόÏεσε να εντοπίσει την λίστα διευθÏνσεως επÎκτασης, Ï€ÏÎπει να κατεβάσετε και εγκαταστήσετε χειÏοκίνητα'; -$lang['git'] = 'Αυτή η πεÏαιτÎÏω ÏÏθμιση εγκαταστάθηκε μÎσω git, μποÏεί να μην θÎλετε να την ανανεώσετε εδώ.'; -$lang['auth'] = 'Αυτό το αυθεντικό plugin(επιπÏόσθετο) δεν Îχει ενεÏγοποιηθεί κατά την διαμόÏφωση, Ï€Ïοσπαθήστε να το απενεÏγοποιήσετε. '; -$lang['install_url'] = 'Εγκαταστήσετε από το URL:'; -$lang['install_upload'] = 'Ανεβάστε στον υπολογιστή την Î ÏοÎκταση:'; -$lang['repo_error'] = 'Δεν μπόÏεσε να υπάÏξει Ï€Ïόσβαση στον χώÏο αποθήκευσης επιπÏόσθετων. Βεβαιωθείτε πως ο διακομιστής σας μποÏεί να επικοινωνήσει με το www.dokuwiki.org για να ελÎγξετε τις σχετικÎÏ‚ Ïυθμίσεις.'; +$lang['update_available'] = '<strong>ΕνημÎÏωση:</strong> Η νÎα Îκδοση %s είναι διαθÎσιμη.'; +$lang['wrong_folder'] = '<strong>ΛανθασμÎνη εγκατάσταση του Ï€Ïόσθετου:</strong> Μετονομάστε το φάκελο "%s" σε "%s".'; +$lang['url_change'] = '<strong>To URL άλλαξε:</strong> Το URL άλλαξε από το Ï€ÏοηγοÏμενο κατÎβασμα. ΕλÎγξετε την οÏθότητα του νÎου URL Ï€Ïιν την ενημÎÏωση του Ï€Ïόσθετου.<br />ΚαινοÏÏγιο: %s<br />Παλιό: %s'; + +$lang['error_badurl'] = 'Τα URLs Ï€ÏÎπει να αÏχίζουν με http ή https'; +$lang['error_dircreate'] = 'Σφάλμα κατά τη δημιουÏγία Ï€ÏοσωÏÎ¹Î½Î¿Ï Ï†Î±ÎºÎλου για το κατÎβασμα του αÏχείου'; +$lang['error_download'] = 'Σφάλμα κατά τη λήψη του αÏχείου : %s'; +$lang['error_findfolder'] = 'ΑδÏνατος ο Ï€ÏοσδιοÏισμός του φακÎλου του Ï€Ïόσθετου. Î ÏÎπει να το κατεβάσετε και εγκαταστήσετε χειÏοκίνητα'; +$lang['error_copy'] = 'Σφάλμα κατά την αντιγÏαφή του αÏχείου στην Ï€Ïοσπάθεια εγκατάστασης αÏχείων στο φάκελο <em>%s</em>: ο δίσκος είναι πιθανόν γεμάτος, ή δεν υπάÏχουν δικαιώματα Ï€Ïόσβασης στον φάκελο. Πιθανή μεÏική εγκατάσταση του Ï€Ïόσθετου με αποτÎλεσμα την ασταθή λειτουÏγία του wiki.'; + +$lang['noperms'] = 'Δεν υπάÏχουν δικαιώματα εγγÏαφής στο φάκελο των Ï€Ïόσσθετων'; +$lang['notplperms'] = 'Δεν υπάÏχουν δικαιώματα εγγÏαφής στο φάκελο των Ï€ÏοτÏπων'; +$lang['nopluginperms'] = 'Δεν υπάÏχουν δικαιώματα εγγÏαφής στο φάκελο των Ï€Ïόσσθετων'; +$lang['git'] = 'Αυτό το Ï€Ïόσθετο εγκαταστάθηκε μÎσω git, μποÏεί να μην θÎλετε να το ανανεώσετε εδώ.'; +$lang['auth'] = 'Αυτό το Ï€Ïόσθετο ταυτοποίησης δεν Îχει ενεÏγοποιηθεί κατά στις Ïυθμίσεις, εξετάστε μήπως θÎλετε να το απενεÏγοποιήσετε.'; + +$lang['install_url'] = 'Εγκατάσταση από το URL:'; +$lang['install_upload'] = 'Ανεβάστε το Ï€Ïόσθετο:'; + +$lang['repo_error'] = 'Σφάλμα επικοινωνίας με την αÏχειοθήκη Ï€Ïόσθετων. Βεβαιωθείτε ότι είναι Ï€Ïοσβάσιμο το www.dokuwiki.org και ελÎγξετε τις σχετικÎÏ‚ Ïυθμίσεις proxy.'; +$lang['nossl'] = 'Your PHP seems to miss SSL support. Downloading will not work for many DokuWiki extensions.'; + +$lang['js']['display_viewoptions'] = 'ΕπιλογÎÏ‚ εμφάνισης:'; +$lang['js']['display_enabled'] = 'ενεÏγοποιημÎνο'; +$lang['js']['display_disabled'] = 'απενεÏγοποιημÎνο'; +$lang['js']['display_updatable'] = 'ανανεώσιμο'; + diff --git a/lib/plugins/extension/lang/fr/lang.php b/lib/plugins/extension/lang/fr/lang.php index 65d93d012..deea45e48 100644 --- a/lib/plugins/extension/lang/fr/lang.php +++ b/lib/plugins/extension/lang/fr/lang.php @@ -3,8 +3,8 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Schplurtz le Déboulonné <schplurtz@laposte.net> * @author Pierre Henriot <pierre.henriot@gmail.com> - * @author Schplurtz le Déboulonné <Schplurtz@laposte.net> * @author Damien Regad <dregad@mantisbt.org> * @author Yves Grandvalet <Yves.Grandvalet@laposte.net> * @author Carbain Frédéric <fcarbain@yahoo.fr> @@ -48,7 +48,7 @@ $lang['downloadurl'] = 'Téléchargement :'; $lang['repository'] = 'Dépôt : '; $lang['unknown'] = '<em>inconnu</em>'; $lang['installed_version'] = 'Version installée :'; -$lang['install_date'] = 'Dernière mise à jour :'; +$lang['install_date'] = 'Dernière mise à jour :'; $lang['available_version'] = 'Version disponible :'; $lang['compatible'] = 'Compatible avec :'; $lang['depends'] = 'Dépend de :'; diff --git a/lib/plugins/extension/lang/hu/lang.php b/lib/plugins/extension/lang/hu/lang.php index 7d531e15b..0e1174007 100644 --- a/lib/plugins/extension/lang/hu/lang.php +++ b/lib/plugins/extension/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['menu'] = 'BÅ‘vÃtménykezelÅ‘'; diff --git a/lib/plugins/extension/lang/nl/lang.php b/lib/plugins/extension/lang/nl/lang.php index 4fe8359d8..67fe36b8b 100644 --- a/lib/plugins/extension/lang/nl/lang.php +++ b/lib/plugins/extension/lang/nl/lang.php @@ -3,12 +3,12 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Mark Prins <mprins@users.sf.net> * @author Rene <wllywlnt@yahoo.com> * @author Gerrit Uitslag <klapinklapin@gmail.com> * @author Johan Vervloet <johan.vervloet@gmail.com> * @author Mijndert <mijndert@mijndertstuij.nl> * @author Johan Wijnker <johan@wijnker.eu> - * @author Mark C. Prins <mprins@users.sf.net> * @author hugo smet <hugo.smet@scarlet.be> */ $lang['menu'] = 'Uitbreidingen'; @@ -78,6 +78,7 @@ $lang['msg_template_update_success'] = 'Template %s werd succesvol geüpdatet'; $lang['msg_plugin_install_success'] = 'Plugin %s werd succesvol geïnstalleerd'; $lang['msg_plugin_update_success'] = 'Plugin %s werd succesvol geüpdatet'; $lang['msg_upload_failed'] = 'Uploaden van het bestand is mislukt'; +$lang['msg_nooverwrite'] = 'Uitbreiding %s bestaat al en wordt niet overschreven; vink de optie Bestaande bestanden overschrijven aan om te overschrijven'; $lang['missing_dependency'] = '<strong>niet aanwezige of uitgeschakelde afhankelijkheid</strong> %s'; $lang['security_issue'] = '<strong>Veiligheids kwestie:</strong> %s'; $lang['security_warning'] = '<strong>Veiligheids Waarschuwing</strong> %s'; diff --git a/lib/plugins/extension/lang/zh-tw/lang.php b/lib/plugins/extension/lang/zh-tw/lang.php index 102e074c2..c8249c3a3 100644 --- a/lib/plugins/extension/lang/zh-tw/lang.php +++ b/lib/plugins/extension/lang/zh-tw/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author Chun-Chung Chen <cjj@u.washington.edu> * @author GHSRobert Ciang <robertus0617@gmail.com> * @author Stan <talktostan@gmail.com> * @author June-Hao Hou <junehao@gmail.com> diff --git a/lib/plugins/extension/script.js b/lib/plugins/extension/script.js index 7c915808e..7742b1583 100644 --- a/lib/plugins/extension/script.js +++ b/lib/plugins/extension/script.js @@ -64,8 +64,9 @@ jQuery(function(){ DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_extension', - ext: extension, - act: act + ext: extension, + act: act, + sectok: $btn.parents('form').find('input[name=sectok]').val() }, function (data) { $btn.css('cursor', '') @@ -74,12 +75,15 @@ jQuery(function(){ .removeClass('enable') .text(data.label) .addClass(data.reverse) - .parents('li') + .parents('li') .removeClass('disabled') .removeClass('enabled') .addClass(data.state); } - ); + ).fail(function() { + $btn.css('cursor', '') + .removeAttr('disabled'); + }); }); /** diff --git a/lib/plugins/logviewer/admin.php b/lib/plugins/logviewer/admin.php index 3eb0a920a..e2a6fc6d2 100644 --- a/lib/plugins/logviewer/admin.php +++ b/lib/plugins/logviewer/admin.php @@ -103,10 +103,10 @@ class admin_plugin_logviewer extends DokuWiki_Admin_Plugin echo '<dd>'; while ($line[0] === ' ' && $line[1] === ' ') { echo hsc(substr($line, 2)) . '<br />'; - $line = $lines[$i++]; + $line = $lines[++$i]; } echo '</dd>'; - $i -= 2; // rewind the counter + $i -= 1; // rewind the counter } else { // other lines are actual log lines in three parts list($dt, $file, $msg) = explode("\t", $line, 3); diff --git a/lib/plugins/popularity/lang/hu/lang.php b/lib/plugins/popularity/lang/hu/lang.php index 213d22655..5f4450fd4 100644 --- a/lib/plugins/popularity/lang/hu/lang.php +++ b/lib/plugins/popularity/lang/hu/lang.php @@ -2,13 +2,11 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Sandor TIHANYI <stihanyi+dw@gmail.com> * @author Siaynoq Mage <siaynoqmage@gmail.com> - * @author schilling.janos@gmail.com + * @author schilling.janos <schilling.janos@gmail.com> * @author Szabó Dávid <szabo.david@gyumolcstarhely.hu> - * @author Sándor TIHANYI <stihanyi+dw@gmail.com> - * @author David Szabo <szabo.david@gyumolcstarhely.hu> * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['name'] = 'Visszajelzés a DokuWiki használatáról (sok idÅ‘t vehet igénybe a betöltése)'; diff --git a/lib/plugins/revert/lang/hu/lang.php b/lib/plugins/revert/lang/hu/lang.php index 278af1864..6d152cfcc 100644 --- a/lib/plugins/revert/lang/hu/lang.php +++ b/lib/plugins/revert/lang/hu/lang.php @@ -2,13 +2,11 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Sandor TIHANYI <stihanyi+dw@gmail.com> * @author Siaynoq Mage <siaynoqmage@gmail.com> - * @author schilling.janos@gmail.com + * @author schilling.janos <schilling.janos@gmail.com> * @author Szabó Dávid <szabo.david@gyumolcstarhely.hu> - * @author Sándor TIHANYI <stihanyi+dw@gmail.com> - * @author David Szabo <szabo.david@gyumolcstarhely.hu> * @author Marton Sebok <sebokmarton@gmail.com> * @author Marina Vladi <deldadam@gmail.com> */ diff --git a/lib/plugins/revert/lang/ko/lang.php b/lib/plugins/revert/lang/ko/lang.php index a71dc067a..2d2ab7d90 100644 --- a/lib/plugins/revert/lang/ko/lang.php +++ b/lib/plugins/revert/lang/ko/lang.php @@ -3,6 +3,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * + * @author merefox <admin@homerecz.com> * @author pavement <pavement@rael.cc> * @author Traend <Traend@ruu.kr> * @author Seungheon Song <esketch@gmail.com> diff --git a/lib/plugins/styling/admin.php b/lib/plugins/styling/admin.php index 9720e16d5..08c9afdc2 100644 --- a/lib/plugins/styling/admin.php +++ b/lib/plugins/styling/admin.php @@ -34,6 +34,7 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin global $INPUT; $run = $INPUT->extract('run')->str('run'); if (!$run) return; + if(!checkSecurityToken()) return; $run = 'run'.ucfirst($run); $this->$run(); } @@ -76,6 +77,7 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin echo $this->locale_xhtml('intro'); echo '<form class="styling" method="post" action="'.$target.'">'; + formSecurityToken(); echo '<table><tbody>'; foreach ($replacements as $key => $value) { diff --git a/lib/plugins/styling/lang/el/lang.php b/lib/plugins/styling/lang/el/lang.php index 9f6b15012..c66be1318 100644 --- a/lib/plugins/styling/lang/el/lang.php +++ b/lib/plugins/styling/lang/el/lang.php @@ -3,19 +3,28 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * - * @author Katerina Katapodi <extragold1234@hotmail.com> */ -$lang['menu'] = 'Ρυθμίσεις ΤÏπου ΜοντÎλου'; -$lang['error'] = 'Συγγνώμη, αυτό το Ï€Ïότυπο δεν υποστηÏίζει αυτήν την λειτουÏγία.'; -$lang['btn_preview'] = 'Έλεγχος αλλαγών '; -$lang['btn_save'] = 'ΑποθηκεÏσετε τις αλλαγÎÏ‚'; -$lang['btn_reset'] = 'Ρυθμίστε ξανά τις Ï„ÏÎχουσες αλλαγÎÏ‚'; -$lang['btn_revert'] = 'Τα Ï€Ïότυπα επαναφοÏάς πίσω στο επιλεγμÎνο Ï€Ïότυπο'; -$lang['__text__'] = 'ΚÏÏιο χÏώμα κειμÎνου'; -$lang['__background__'] = 'ΚÏÏιο χÏώμα φόντου'; -$lang['__text_alt__'] = 'Εναλλακτικό χÏώμα κειμÎνου'; -$lang['__background_alt__'] = 'Εναλλακτικό χÏώμα φόντου'; -$lang['__text_neu__'] = 'ΟυδÎτεÏο χÏώμα κειμÎνου'; -$lang['__background_neu__'] = 'ΟυδÎτεÏο (λευκό?) χÏώμα βάσης'; -$lang['__border__'] = 'ΧÏώμα πλαισίων'; -$lang['__highlight__'] = 'ΧÏώμα Ï†Ï‰Ï„Î¹ÏƒÎ¼Î¿Ï (κυÏίως για αναζήτηση αποτελεσμάτων)'; +$lang['menu'] = 'Εμφάνιση styles Ï€ÏοτÏπων (templates)'; +$lang['js']['loader'] = 'Η Ï€Ïοεπισκόπιση φοÏτώνει ...<br />Εάν αυτό το μήνυμα δεν φÏγει οι Ïυθμίσεις σας μποÏεί να είναι εφαλμÎνες'; +$lang['js']['popup'] = 'Άνοιγμα σε popup'; + +// custom language strings for the plugin +$lang['error'] = 'Μη υποστηÏιζόμενη λειτουÏγικότητα από το Ï€Ïότυπο.'; + +$lang['btn_preview'] = 'Î Ïοεπισκόπιση αλλαγών'; +$lang['btn_save'] = 'Αποθήκευση αλλαγών'; +$lang['btn_reset'] = 'ΑκÏÏωση τελευταίων αλλαγών'; +$lang['btn_revert'] = 'ΕπαναφοÏά των styles στις Ï€ÏοκαθοÏισμÎνες τιμÎÏ‚'; + +// default guaranteed placeholders +$lang['__text__'] = 'ΧÏώμα κυÏίως κειμÎνου'; +$lang['__background__'] = 'ΧÏώμα κυÏίως φόντου'; +$lang['__text_alt__'] = 'ΧÏώμα ÎµÎ½Î±Î»Î»Î±ÎºÏ„Î¹ÎºÎ¿Ï ÎºÎµÎ¹Î¼Îνου'; +$lang['__background_alt__'] = 'ΧÏώμα ÎµÎ½Î±Î»Î»Î±ÎºÏ„Î¹ÎºÎ¿Ï Ï†ÏŒÎ½Ï„Î¿Ï…'; +$lang['__text_neu__'] = 'ΧÏώμα ουδÎτεÏου κειμÎνου'; +$lang['__background_neu__'] = 'ΧÏώμα ουδÎτεÏου φόντου'; +$lang['__border__'] = 'ΧÏώμα πεÏιγÏάμματος'; +$lang['__highlight__'] = 'ΧÏώμα επισήμανσης (κυÏίως για αποτελÎσματα αναζήτησης)'; + + + diff --git a/lib/plugins/styling/lang/hu/lang.php b/lib/plugins/styling/lang/hu/lang.php index c6ef5de93..4717d9b5b 100644 --- a/lib/plugins/styling/lang/hu/lang.php +++ b/lib/plugins/styling/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['menu'] = 'Sablon kinézetének beállÃtásai'; diff --git a/lib/plugins/usermanager/lang/hu/lang.php b/lib/plugins/usermanager/lang/hu/lang.php index 963fcd1fc..f76e21f57 100644 --- a/lib/plugins/usermanager/lang/hu/lang.php +++ b/lib/plugins/usermanager/lang/hu/lang.php @@ -2,13 +2,12 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * + * @author Hamp Gábor <gabor.hamp@gmail.com> * @author Sandor TIHANYI <stihanyi+dw@gmail.com> * @author Siaynoq Mage <siaynoqmage@gmail.com> - * @author schilling.janos@gmail.com + * @author schilling.janos <schilling.janos@gmail.com> * @author Szabó Dávid <szabo.david@gyumolcstarhely.hu> - * @author Sándor TIHANYI <stihanyi+dw@gmail.com> - * @author David Szabo <szabo.david@gyumolcstarhely.hu> * @author Marton Sebok <sebokmarton@gmail.com> * @author Serenity87HUN <anikototh87@gmail.com> * @author Marina Vladi <deldadam@gmail.com> @@ -72,3 +71,5 @@ $lang['import_error_readfail'] = 'Sikertelen importálás. A feltöltött fájl $lang['import_error_create'] = 'Ez a felhasználó nem hozható létre'; $lang['import_notify_fail'] = 'Az értesÃtÅ‘ e-mail nem küldhetÅ‘ el az alábbi importált felhasználónak: %s e-mailcÃme: %s.'; $lang['import_downloadfailures'] = 'Töltsd le a hibákat tartalmazó fájlt CSV formátumban, hogy ki tudd javÃtani a hibákat'; +$lang['addUser_error_pass_not_identical'] = 'A begépelt jelszavak különböznek.'; +$lang['addUser_error_modPass_disabled'] = 'A jelszó megváltoztatása jelenleg nem lehetséges.'; diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js index 02c1ddfce..2253d05cf 100644 --- a/lib/scripts/edit.js +++ b/lib/scripts/edit.js @@ -210,7 +210,8 @@ function deleteDraft() { jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', { call: 'draftdel', - id: $dwform.find('input[name=id]').val() + id: $dwform.find('input[name=id]').val(), + sectok: $dwform.find('input[name=sectok]').val() } ); } diff --git a/lib/styles/all.css b/lib/styles/all.css index 01efce6d1..5a30dc5e4 100644 --- a/lib/styles/all.css +++ b/lib/styles/all.css @@ -70,3 +70,8 @@ em em.u { img.icon.smiley { height: 1.2em; } + +svg { + width: auto; + height: 1.2em; +} diff --git a/lib/tpl/dokuwiki/detail.php b/lib/tpl/dokuwiki/detail.php index ec6eabb60..b5f0a6361 100644 --- a/lib/tpl/dokuwiki/detail.php +++ b/lib/tpl/dokuwiki/detail.php @@ -9,7 +9,6 @@ // must be run from within DokuWiki if (!defined('DOKU_INC')) die(); -header('X-UA-Compatible: IE=edge,chrome=1'); ?><!DOCTYPE html> <html lang="<?php echo $conf['lang']?>" dir="<?php echo $lang['direction'] ?>" class="no-js"> diff --git a/lib/tpl/dokuwiki/lang/hu/lang.php b/lib/tpl/dokuwiki/lang/hu/lang.php index 083736623..eb9a5a11a 100644 --- a/lib/tpl/dokuwiki/lang/hu/lang.php +++ b/lib/tpl/dokuwiki/lang/hu/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Marton Sebok <sebokmarton@gmail.com> */ $lang['__background_site__'] = 'Lap szÃne (a tartalom mögött)'; diff --git a/lib/tpl/dokuwiki/mediamanager.php b/lib/tpl/dokuwiki/mediamanager.php index c39b81f37..c859ab627 100644 --- a/lib/tpl/dokuwiki/mediamanager.php +++ b/lib/tpl/dokuwiki/mediamanager.php @@ -7,7 +7,6 @@ */ // must be run from within DokuWiki if (!defined('DOKU_INC')) die(); -header('X-UA-Compatible: IE=edge,chrome=1'); ?><!DOCTYPE html> <html lang="<?php echo $conf['lang']?>" dir="<?php echo $lang['direction'] ?>" class="popup no-js"> diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php index 4910e1b21..17d41420e 100644 --- a/vendor/composer/InstalledVersions.php +++ b/vendor/composer/InstalledVersions.php @@ -30,7 +30,7 @@ private static $installed = array ( 'aliases' => array ( ), - 'reference' => '4ee6ddae660f9ec72c1f6e2ddb72d6b29d6d8900', + 'reference' => 'a30be5ec00ba89ade3ec8ffa407fa7e18824943c', 'name' => 'splitbrain/dokuwiki', ), 'versions' => @@ -55,6 +55,15 @@ private static $installed = array ( ), 'reference' => '3c12a7931d509c5e3557c5ed44c9a32e9c917c7d', ), + 'kissifrot/php-ixr' => + array ( + 'pretty_version' => '1.8.3', + 'version' => '1.8.3.0', + 'aliases' => + array ( + ), + 'reference' => '4477cd1a67416ce5b6a2080f9a79d9eb50a965c1', + ), 'marcusschwarz/lesserphp' => array ( 'pretty_version' => 'v0.5.5', @@ -98,7 +107,7 @@ private static $installed = array ( 'aliases' => array ( ), - 'reference' => '4ee6ddae660f9ec72c1f6e2ddb72d6b29d6d8900', + 'reference' => 'a30be5ec00ba89ade3ec8ffa407fa7e18824943c', ), 'splitbrain/php-archive' => array ( @@ -120,12 +129,12 @@ private static $installed = array ( ), 'splitbrain/slika' => array ( - 'pretty_version' => '1.0.4', - 'version' => '1.0.4.0', + 'pretty_version' => '1.0.5', + 'version' => '1.0.5.0', 'aliases' => array ( ), - 'reference' => 'fda87e816eb150f3608282da962788b4ad509c11', + 'reference' => 'be0785cb6b7def847df5d92e0e5fde57def7220f', ), ), ); diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 855f95f23..a8c2bcb90 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -11,4 +11,5 @@ return array( 'splitbrain\\phpcli\\' => array($vendorDir . '/splitbrain/php-cli/src'), 'splitbrain\\PHPArchive\\' => array($vendorDir . '/splitbrain/php-archive/src'), 'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'), + 'IXR\\' => array($vendorDir . '/kissifrot/php-ixr/src'), ); diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 4618df6b3..80a0ea3c7 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -23,6 +23,10 @@ class ComposerStaticInita19a915ee98347a0c787119619d2ff9b array ( 'phpseclib\\' => 10, ), + 'I' => + array ( + 'IXR\\' => 4, + ), ); public static $prefixDirsPsr4 = array ( @@ -46,6 +50,10 @@ class ComposerStaticInita19a915ee98347a0c787119619d2ff9b array ( 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib', ), + 'IXR\\' => + array ( + 0 => __DIR__ . '/..' . '/kissifrot/php-ixr/src', + ), ); public static $prefixesPsr0 = array ( diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 86a2915cd..7aa179a7b 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -88,6 +88,56 @@ "install-path": "../geshi/geshi" }, { + "name": "kissifrot/php-ixr", + "version": "1.8.3", + "version_normalized": "1.8.3.0", + "source": { + "type": "git", + "url": "https://github.com/kissifrot/php-ixr.git", + "reference": "4477cd1a67416ce5b6a2080f9a79d9eb50a965c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kissifrot/php-ixr/zipball/4477cd1a67416ce5b6a2080f9a79d9eb50a965c1", + "reference": "4477cd1a67416ce5b6a2080f9a79d9eb50a965c1", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "time": "2016-11-17T12:00:18+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "IXR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Incutio Ltd 2010 - Simon Willison", + "homepage": "http://scripts.incutio.com/xmlrpc/" + } + ], + "description": "Incutio XML-RPC library (IXR)", + "homepage": "http://scripts.incutio.com/xmlrpc/", + "keywords": [ + "remote procedure call", + "rpc", + "xlm-rpc", + "xmlrpc" + ], + "support": { + "issues": "https://github.com/kissifrot/php-ixr/issues", + "source": "https://github.com/kissifrot/php-ixr/tree/master" + }, + "install-path": "../kissifrot/php-ixr" + }, + { "name": "marcusschwarz/lesserphp", "version": "v0.5.5", "version_normalized": "0.5.5.0", @@ -487,32 +537,32 @@ }, { "name": "splitbrain/slika", - "version": "1.0.4", - "version_normalized": "1.0.4.0", + "version": "1.0.5", + "version_normalized": "1.0.5.0", "source": { "type": "git", "url": "https://github.com/splitbrain/slika.git", - "reference": "fda87e816eb150f3608282da962788b4ad509c11" + "reference": "be0785cb6b7def847df5d92e0e5fde57def7220f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/splitbrain/slika/zipball/fda87e816eb150f3608282da962788b4ad509c11", - "reference": "fda87e816eb150f3608282da962788b4ad509c11", + "url": "https://api.github.com/repos/splitbrain/slika/zipball/be0785cb6b7def847df5d92e0e5fde57def7220f", + "reference": "be0785cb6b7def847df5d92e0e5fde57def7220f", "shasum": "" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-gd": "PHP's builtin image manipulation library. Alternatively use an installation of ImageMagick" }, - "time": "2020-09-07T18:35:00+00:00", + "time": "2022-02-04T22:41:26+00:00", "type": "library", "installation-source": "dist", "autoload": { "psr-4": { - "splitbrain\\slika\\tests\\": "tests", - "splitbrain\\slika\\": "src" + "splitbrain\\slika\\": "src", + "splitbrain\\slika\\tests\\": "tests" } }, "notification-url": "https://packagist.org/downloads/", @@ -526,6 +576,10 @@ } ], "description": "Simple image resizing", + "support": { + "issues": "https://github.com/splitbrain/slika/issues", + "source": "https://github.com/splitbrain/slika/tree/1.0.5" + }, "install-path": "../splitbrain/slika" } ], diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 57d493fd1..1013664e8 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -6,7 +6,7 @@ 'aliases' => array ( ), - 'reference' => '4ee6ddae660f9ec72c1f6e2ddb72d6b29d6d8900', + 'reference' => 'a30be5ec00ba89ade3ec8ffa407fa7e18824943c', 'name' => 'splitbrain/dokuwiki', ), 'versions' => @@ -31,6 +31,15 @@ ), 'reference' => '3c12a7931d509c5e3557c5ed44c9a32e9c917c7d', ), + 'kissifrot/php-ixr' => + array ( + 'pretty_version' => '1.8.3', + 'version' => '1.8.3.0', + 'aliases' => + array ( + ), + 'reference' => '4477cd1a67416ce5b6a2080f9a79d9eb50a965c1', + ), 'marcusschwarz/lesserphp' => array ( 'pretty_version' => 'v0.5.5', @@ -74,7 +83,7 @@ 'aliases' => array ( ), - 'reference' => '4ee6ddae660f9ec72c1f6e2ddb72d6b29d6d8900', + 'reference' => 'a30be5ec00ba89ade3ec8ffa407fa7e18824943c', ), 'splitbrain/php-archive' => array ( @@ -96,12 +105,12 @@ ), 'splitbrain/slika' => array ( - 'pretty_version' => '1.0.4', - 'version' => '1.0.4.0', + 'pretty_version' => '1.0.5', + 'version' => '1.0.5.0', 'aliases' => array ( ), - 'reference' => 'fda87e816eb150f3608282da962788b4ad509c11', + 'reference' => 'be0785cb6b7def847df5d92e0e5fde57def7220f', ), ), ); diff --git a/vendor/kissifrot/php-ixr/.editorconfig b/vendor/kissifrot/php-ixr/.editorconfig new file mode 100644 index 000000000..427884b20 --- /dev/null +++ b/vendor/kissifrot/php-ixr/.editorconfig @@ -0,0 +1,8 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true diff --git a/vendor/kissifrot/php-ixr/.gitignore b/vendor/kissifrot/php-ixr/.gitignore new file mode 100644 index 000000000..af08cb0d2 --- /dev/null +++ b/vendor/kissifrot/php-ixr/.gitignore @@ -0,0 +1,6 @@ +.project +.idea +.vscode +.phpunit.result.cache +composer.lock +vendor diff --git a/vendor/kissifrot/php-ixr/LICENSE.txt b/vendor/kissifrot/php-ixr/LICENSE.txt new file mode 100644 index 000000000..066028156 --- /dev/null +++ b/vendor/kissifrot/php-ixr/LICENSE.txt @@ -0,0 +1,28 @@ +IXR - The Incutio XML-RPC Library + +Copyright (c) 2010, Incutio Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of Incutio Ltd. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/kissifrot/php-ixr/README.md b/vendor/kissifrot/php-ixr/README.md new file mode 100644 index 000000000..55165d601 --- /dev/null +++ b/vendor/kissifrot/php-ixr/README.md @@ -0,0 +1,37 @@ +#Incutio XML-RPC library (IXR) + +**Note**: _This is a fork of the original Incutio XML-RPC library (IXR) SVN repo hosted on <https://code.google.com/p/php-ixr/>_ + +All credits go to Incutio. + +**Docs and Homepage:** <http://scripts.incutio.com/xmlrpc/> + +#Introduction + +The Incutio XML-RPC library (IXR) is designed primarily for ease of use. It incorporates both client and server classes, and is designed to hide as much of the workings of XML-RPC from the user as possible. A key feature of the library is automatic type conversion from PHP types to XML-RPC types and vice versa. This should enable developers to write web services with very little knowledge of the underlying XML-RPC standard. + +Don't however be fooled by it's simple surface. The library includes a wide variety of additional XML-RPC specifications and has all of the features required for serious web service implementations. + +#Background / History + +The original XML-RPC library was developed back in 2002 and updated through 2010 by Incutio for a number of projects the company was working on at the time. It has become fairly dated but is still used extensively by a wide range of commercial and open-source projects. +This fork makes it usable on more recent systems (PHP 5.4+ ones) + +#Composer + +A [Composer](http://getcomposer.org/) file has been added to this repository. + +This package is published to [Packagist](https://packagist.org/), but if you don't want to use it simply add + + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/kissifrot/php-ixr" + } + ], + + "require": { + "kissifrot/php-ixr": "1.8.*" + } + +To your composer.json file diff --git a/vendor/kissifrot/php-ixr/composer.json b/vendor/kissifrot/php-ixr/composer.json new file mode 100644 index 000000000..9e8985d09 --- /dev/null +++ b/vendor/kissifrot/php-ixr/composer.json @@ -0,0 +1,27 @@ +{ + "name": "kissifrot/php-ixr", + "type": "library", + "description": "Incutio XML-RPC library (IXR)", + "keywords": ["xmlrpc","xlm-rpc", "remote procedure call", "rpc"], + "homepage": "http://scripts.incutio.com/xmlrpc/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Incutio Ltd 2010 - Simon Willison", + "homepage": "http://scripts.incutio.com/xmlrpc/" + } + ], + "require": { + "php": ">=5.4.0", + "ext-xml": "*" + }, + "require-dev": { + "phpunit/phpunit": "^8.0" + }, + "autoload": { + "psr-4": { + "IXR\\tests\\": "tests/", + "IXR\\": "src/" + } + } +} diff --git a/vendor/kissifrot/php-ixr/src/Client/Client.php b/vendor/kissifrot/php-ixr/src/Client/Client.php new file mode 100644 index 000000000..9d13fbe9e --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Client/Client.php @@ -0,0 +1,209 @@ +<?php +namespace IXR\Client; + +use IXR\Message\Error; +use IXR\Message\Message; +use IXR\Request\Request; + +/** + * IXR_Client + * + * @package IXR + * @since 1.5.0 + * + */ +class Client +{ + protected $server; + protected $port; + protected $path; + protected $useragent; + protected $response; + /** @var bool|Message */ + protected $message = false; + protected $debug = false; + /** @var int Connection timeout in seconds */ + protected $timeout; + /** @var null|int Timeout for actual data transfer; in seconds */ + protected $timeout_io = null; + protected $headers = []; + + /** + * @var null|Error + * + * Storage place for an error message + */ + private $error = null; + + public function __construct($server, $path = false, $port = 80, $timeout = 15, $timeout_io = null) + { + if (!$path) { + // Assume we have been given a URL instead + $bits = parse_url($server); + $this->server = $bits['host']; + $this->port = isset($bits['port']) ? $bits['port'] : 80; + $this->path = isset($bits['path']) ? $bits['path'] : '/'; + + // Make absolutely sure we have a path + if (!$this->path) { + $this->path = '/'; + } + + if (!empty($bits['query'])) { + $this->path .= '?' . $bits['query']; + } + } else { + $this->server = $server; + $this->path = $path; + $this->port = $port; + } + $this->useragent = 'The Incutio XML-RPC PHP Library'; + $this->timeout = $timeout; + $this->timeout_io = $timeout_io; + } + + public function query() + { + $args = func_get_args(); + $method = array_shift($args); + $request = new Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + $r = "\r\n"; + $request = "POST {$this->path} HTTP/1.0$r"; + + // Merged from WP #8145 - allow custom headers + $this->headers['Host'] = $this->server; + $this->headers['Content-Type'] = 'text/xml'; + $this->headers['User-Agent'] = $this->useragent; + $this->headers['Content-Length'] = $length; + + foreach ($this->headers as $header => $value) { + $request .= "{$header}: {$value}{$r}"; + } + $request .= $r; + + $request .= $xml; + + // Now send the request + if ($this->debug) { + echo '<pre class="ixr_request">' . htmlspecialchars($request) . "\n</pre>\n\n"; + } + + if ($this->timeout) { + try { + $fp = fsockopen($this->server, $this->port, $errno, $errstr, $this->timeout); + } catch (\Exception $e) { + $fp = false; + } + } else { + try { + $fp = fsockopen($this->server, $this->port, $errno, $errstr); + } catch (\Exception $e) { + $fp = false; + } + } + if (!$fp) { + return $this->handleError(-32300, 'transport error - could not open socket'); + } + if (null !== $this->timeout_io) { + stream_set_timeout($fp, $this->timeout_io); + } + fputs($fp, $request); + $contents = ''; + $debugContents = ''; + $gotFirstLine = false; + $gettingHeaders = true; + while (!feof($fp)) { + $line = fgets($fp, 4096); + if (!$gotFirstLine) { + // Check line for '200' + if (strstr($line, '200') === false) { + return $this->handleError(-32300, 'transport error - HTTP status code was not 200'); + } + $gotFirstLine = true; + } + if (trim($line) == '') { + $gettingHeaders = false; + } + if (!$gettingHeaders) { + // merged from WP #12559 - remove trim + $contents .= $line; + } + if ($this->debug) { + $debugContents .= $line; + } + } + if ($this->debug) { + echo '<pre class="ixr_response">' . htmlspecialchars($debugContents) . "\n</pre>\n\n"; + } + + // Now parse what we've got back + $this->message = new Message($contents); + if (!$this->message->parse()) { + // XML error + return $this->handleError(-32700, 'Parse error. Message not well formed'); + } + + // Is the message a fault? + if ($this->message->messageType == 'fault') { + return $this->handleError($this->message->faultCode, $this->message->faultString); + } + + // Message must be OK + return true; + } + + public function getResponse() + { + // methodResponses can only have one param - return that + return $this->message->params[0]; + } + + public function isError() + { + return (is_object($this->error)); + } + + protected function handleError($errorCode, $errorMessage) + { + $this->error = new Error($errorCode, $errorMessage); + + return false; + } + + public function getError() + { + return $this->error; + } + + public function getErrorCode() + { + return $this->error->code; + } + + public function getErrorMessage() + { + return $this->error->message; + } + + + /** + * Gets the current timeout set for data transfer + * @return int|null + */ + public function getTimeoutIo() + { + return $this->timeout_io; + } + + /** + * Sets the timeout for data transfer + * @param int $timeout_io + * @return $this + */ + public function setTimeoutIo($timeout_io) + { + $this->timeout_io = $timeout_io; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Client/ClientMulticall.php b/vendor/kissifrot/php-ixr/src/Client/ClientMulticall.php new file mode 100644 index 000000000..b54a179bb --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Client/ClientMulticall.php @@ -0,0 +1,36 @@ +<?php +namespace IXR\Client; + +/** + * IXR_ClientMulticall + * + * @package IXR + * @since 1.5.0 + */ +class ClientMulticall extends Client +{ + private $calls = []; + + public function __construct($server, $path = false, $port = 80) + { + parent::__construct($server, $path, $port); + $this->useragent = 'The Incutio XML-RPC PHP Library (multicall client)'; + } + + public function addCall() + { + $args = func_get_args(); + $methodName = array_shift($args); + $struct = [ + 'methodName' => $methodName, + 'params' => $args + ]; + $this->calls[] = $struct; + } + + public function query() + { + // Prepare multicall, then call the parent::query() method + return parent::query('system.multicall', $this->calls); + } +} diff --git a/vendor/kissifrot/php-ixr/src/Client/ClientSSL.php b/vendor/kissifrot/php-ixr/src/Client/ClientSSL.php new file mode 100644 index 000000000..7bbd5a551 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Client/ClientSSL.php @@ -0,0 +1,235 @@ +<?php +namespace IXR\Client; + +use IXR\Exception\ClientException; +use IXR\Message\Message; +use IXR\Request\Request; + +/** + * Client for communicating with a XML-RPC Server over HTTPS. + * + * @author Jason Stirk <jstirk@gmm.com.au> (@link http://blog.griffin.homelinux.org/projects/xmlrpc/) + * @version 0.2.0 26May2005 08:34 +0800 + * @copyright (c) 2004-2005 Jason Stirk + * @package IXR + */ +class ClientSSL extends Client +{ + /** + * Filename of the SSL Client Certificate + * @access private + * @since 0.1.0 + * @var string + */ + private $_certFile; + + /** + * Filename of the SSL CA Certificate + * @access private + * @since 0.1.0 + * @var string + */ + private $_caFile; + + /** + * Filename of the SSL Client Private Key + * @access private + * @since 0.1.0 + * @var string + */ + private $_keyFile; + + /** + * Passphrase to unlock the private key + * @access private + * @since 0.1.0 + * @var string + */ + private $_passphrase; + + /** + * Constructor + * @param string $server URL of the Server to connect to + * @since 0.1.0 + */ + public function __construct($server, $path = false, $port = 443, $timeout = false, $timeout_io = null) + { + parent::__construct($server, $path, $port, $timeout, $timeout_io); + $this->useragent = 'The Incutio XML-RPC PHP Library for SSL'; + + // Set class fields + $this->_certFile = false; + $this->_caFile = false; + $this->_keyFile = false; + $this->_passphrase = ''; + } + + /** + * Set the client side certificates to communicate with the server. + * + * @since 0.1.0 + * @param string $certificateFile Filename of the client side certificate to use + * @param string $keyFile Filename of the client side certificate's private key + * @param string $keyPhrase Passphrase to unlock the private key + * @throws ClientException + */ + public function setCertificate($certificateFile, $keyFile, $keyPhrase = '') + { + // Check the files all exist + if (is_file($certificateFile)) { + $this->_certFile = $certificateFile; + } else { + throw new ClientException('Could not open certificate: ' . $certificateFile); + } + + if (is_file($keyFile)) { + $this->_keyFile = $keyFile; + } else { + throw new ClientException('Could not open private key: ' . $keyFile); + } + + $this->_passphrase = (string)$keyPhrase; + } + + public function setCACertificate($caFile) + { + if (is_file($caFile)) { + $this->_caFile = $caFile; + } else { + throw new ClientException('Could not open CA certificate: ' . $caFile); + } + } + + /** + * Sets the connection timeout (in seconds) + * @param int $newTimeOut Timeout in seconds + * @returns void + * @since 0.1.2 + */ + public function setTimeOut($newTimeOut) + { + $this->timeout = (int)$newTimeOut; + } + + /** + * Returns the connection timeout (in seconds) + * @returns int + * @since 0.1.2 + */ + public function getTimeOut() + { + return $this->timeout; + } + + /** + * Set the query to send to the XML-RPC Server + * @since 0.1.0 + */ + public function query() + { + $args = func_get_args(); + $method = array_shift($args); + $request = new Request($method, $args); + $length = $request->getLength(); + $xml = $request->getXml(); + + $this->debugOutput('<pre>' . htmlspecialchars($xml) . PHP_EOL . '</pre>'); + + //This is where we deviate from the normal query() + //Rather than open a normal sock, we will actually use the cURL + //extensions to make the calls, and handle the SSL stuff. + + $curl = curl_init('https://' . $this->server . $this->path); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + + //Since 23Jun2004 (0.1.2) - Made timeout a class field + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->timeout); + if (null !== $this->timeout_io) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout_io); + } + + if ($this->debug) { + curl_setopt($curl, CURLOPT_VERBOSE, 1); + } + + curl_setopt($curl, CURLOPT_HEADER, 1); + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); + if($this->port !== 443) { + curl_setopt($curl, CURLOPT_PORT, $this->port); + } + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + "Content-Type: text/xml", + "Content-length: {$length}" + ]); + + // Process the SSL certificates, etc. to use + if (!($this->_certFile === false)) { + // We have a certificate file set, so add these to the cURL handler + curl_setopt($curl, CURLOPT_SSLCERT, $this->_certFile); + curl_setopt($curl, CURLOPT_SSLKEY, $this->_keyFile); + + if ($this->debug) { + $this->debugOutput('SSL Cert at : ' . $this->_certFile); + $this->debugOutput('SSL Key at : ' . $this->_keyFile); + } + + // See if we need to give a passphrase + if (!($this->_passphrase === '')) { + curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $this->_passphrase); + } + + if ($this->_caFile === false) { + // Don't verify their certificate, as we don't have a CA to verify against + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); + } else { + // Verify against a CA + curl_setopt($curl, CURLOPT_CAINFO, $this->_caFile); + } + } + + // Call cURL to do it's stuff and return us the content + $contents = curl_exec($curl); + curl_close($curl); + + // Check for 200 Code in $contents + if (!strstr($contents, '200 OK')) { + //There was no "200 OK" returned - we failed + return $this->handleError(-32300, 'transport error - HTTP status code was not 200'); + } + + if ($this->debug) { + $this->debugOutput('<pre>' . htmlspecialchars($contents) . PHP_EOL . '</pre>'); + } + // Now parse what we've got back + // Since 20Jun2004 (0.1.1) - We need to remove the headers first + // Why I have only just found this, I will never know... + // So, remove everything before the first < + $contents = substr($contents, strpos($contents, '<')); + + $this->message = new Message($contents); + if (!$this->message->parse()) { + // XML error + return $this->handleError(-32700, 'parse error. not well formed'); + } + // Is the message a fault? + if ($this->message->messageType == 'fault') { + return $this->handleError($this->message->faultCode, $this->message->faultString); + } + + // Message must be OK + return true; + } + + /** + * Debug output, if debug is enabled + * @param $message + */ + private function debugOutput($message) + { + if ($this->debug) { + echo $message . PHP_EOL; + } + } +} diff --git a/vendor/kissifrot/php-ixr/src/DataType/Base64.php b/vendor/kissifrot/php-ixr/src/DataType/Base64.php new file mode 100644 index 000000000..647a8193e --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/DataType/Base64.php @@ -0,0 +1,23 @@ +<?php +namespace IXR\DataType; + +/** + * IXR_Base64 + * + * @package IXR + * @since 1.5.0 + */ +class Base64 +{ + private $data; + + public function __construct($data) + { + $this->data = $data; + } + + public function getXml() + { + return '<base64>' . base64_encode($this->data) . '</base64>'; + } +} diff --git a/vendor/kissifrot/php-ixr/src/DataType/Date.php b/vendor/kissifrot/php-ixr/src/DataType/Date.php new file mode 100644 index 000000000..f448b4a48 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/DataType/Date.php @@ -0,0 +1,56 @@ +<?php + +namespace IXR\DataType; + +/** + * IXR_Date + * + * @package IXR + * @since 1.5.0 + */ +class Date +{ + /** @var \DateTime */ + private $dateTime; + + public function __construct($time) + { + // $time can be a PHP timestamp or an ISO one + if (is_numeric($time)) { + $this->parseTimestamp($time); + } else { + $this->parseIso($time); + } + } + + private function parseTimestamp($timestamp) + { + $date = new \DateTime(); + $this->dateTime = $date->setTimestamp($timestamp); + } + + /** + * Parses more or less complete iso dates and much more, if no timezone given assumes UTC + * + * @param string $iso + * @throws \Exception when no valid date is given + */ + protected function parseIso($iso) { + $this->dateTime = new \DateTime($iso, new \DateTimeZone('UTC')); + } + + public function getIso() + { + return $this->dateTime->format(\DateTime::ATOM); + } + + public function getXml() + { + return '<dateTime.iso8601>' . $this->getIso() . '</dateTime.iso8601>'; + } + + public function getTimestamp() + { + return (int)$this->dateTime->format('U'); + } +} diff --git a/vendor/kissifrot/php-ixr/src/DataType/Value.php b/vendor/kissifrot/php-ixr/src/DataType/Value.php new file mode 100644 index 000000000..f8cbef6b0 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/DataType/Value.php @@ -0,0 +1,121 @@ +<?php +namespace IXR\DataType; + + +class Value +{ + private $data; + private $type; + + public function __construct($data, $type = null) + { + $this->data = $data; + if (!$type) { + $type = $this->calculateType(); + } + $this->type = $type; + if ($type === 'struct') { + // Turn all the values in the array in to new IXR_Value objects + foreach ($this->data as $key => $value) { + $this->data[$key] = new Value($value); + } + } + if ($type === 'array') { + for ($i = 0, $j = count($this->data); $i < $j; $i++) { + $this->data[$i] = new Value($this->data[$i]); + } + } + } + + public function calculateType() + { + if ($this->data === true || $this->data === false) { + return 'boolean'; + } + if (is_integer($this->data)) { + return 'int'; + } + if (is_double($this->data)) { + return 'double'; + } + + // Deal with IXR object types base64 and date + if (is_object($this->data) && $this->data instanceof Date) { + return 'date'; + } + if (is_object($this->data) && $this->data instanceof Base64) { + return 'base64'; + } + + // If it is a normal PHP object convert it in to a struct + if (is_object($this->data)) { + $this->data = get_object_vars($this->data); + return 'struct'; + } + if (!is_array($this->data)) { + return 'string'; + } + + // We have an array - is it an array or a struct? + if ($this->isStruct($this->data)) { + return 'struct'; + } else { + return 'array'; + } + } + + public function getXml() + { + // Return XML for this value + switch ($this->type) { + case 'boolean': + return '<boolean>' . (((bool)$this->data) ? '1' : '0') . '</boolean>'; + case 'int': + return '<int>' . $this->data . '</int>'; + case 'double': + return '<double>' . $this->data . '</double>'; + case 'string': + return '<string>' . htmlspecialchars($this->data) . '</string>'; + case 'array': + $return = '<array><data>' . "\n"; + foreach ($this->data as $item) { + $return .= ' <value>' . $item->getXml() . "</value>\n"; + } + $return .= '</data></array>'; + return $return; + break; + case 'struct': + $return = '<struct>' . "\n"; + foreach ($this->data as $name => $value) { + $name = htmlspecialchars($name); + $return .= " <member><name>$name</name><value>"; + $return .= $value->getXml() . "</value></member>\n"; + } + $return .= '</struct>'; + return $return; + case 'date': + case 'base64': + return $this->data->getXml(); + default: + return false; + } + } + + /** + * Checks whether or not the supplied array is a struct or not + * + * @param array $array + * @return boolean + */ + public function isStruct($array) + { + $expected = 0; + foreach ($array as $key => $value) { + if ((string)$key != (string)$expected) { + return true; + } + $expected++; + } + return false; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Exception/ClientException.php b/vendor/kissifrot/php-ixr/src/Exception/ClientException.php new file mode 100644 index 000000000..5fa91a9ae --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Exception/ClientException.php @@ -0,0 +1,9 @@ +<?php + +namespace IXR\Exception; + + +class ClientException extends \Exception +{ + +} diff --git a/vendor/kissifrot/php-ixr/src/Exception/ServerException.php b/vendor/kissifrot/php-ixr/src/Exception/ServerException.php new file mode 100644 index 000000000..a6b69538e --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Exception/ServerException.php @@ -0,0 +1,9 @@ +<?php + +namespace IXR\Exception; + + +class ServerException extends \Exception +{ + +} diff --git a/vendor/kissifrot/php-ixr/src/Message/Error.php b/vendor/kissifrot/php-ixr/src/Message/Error.php new file mode 100644 index 000000000..6dbb46c5c --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Message/Error.php @@ -0,0 +1,43 @@ +<?php +namespace IXR\Message; + +/** + * IXR_Error + * + * @package IXR + * @since 1.5.0 + */ +class Error +{ + public $code; + public $message; + + public function __construct($code, $message) + { + $this->code = $code; + $this->message = htmlspecialchars($message); + } + + public function getXml() + { + $xml = <<<EOD +<methodResponse> + <fault> + <value> + <struct> + <member> + <name>faultCode</name> + <value><int>{$this->code}</int></value> + </member> + <member> + <name>faultString</name> + <value><string>{$this->message}</string></value> + </member> + </struct> + </value> + </fault> +</methodResponse> +EOD; + return $xml; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Message/Message.php b/vendor/kissifrot/php-ixr/src/Message/Message.php new file mode 100644 index 000000000..e8a1d922a --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Message/Message.php @@ -0,0 +1,210 @@ +<?php +namespace IXR\Message; + + +use IXR\DataType\Date; + +class Message +{ + public $message; + public $messageType; // methodCall / methodResponse / fault + public $faultCode; + public $faultString; + public $methodName; + public $params; + + // Current variable stacks + private $_arraystructs = []; // The stack used to keep track of the current array/struct + private $_arraystructstypes = []; // Stack keeping track of if things are structs or array + private $_currentStructName = []; // A stack as well + private $_param; + private $_value; + private $_currentTag; + private $_currentTagContents; + // The XML parser + private $_parser; + + public function __construct($message) + { + $this->message =& $message; + } + + public function parse() + { + // first remove the XML declaration + // merged from WP #10698 - this method avoids the RAM usage of preg_replace on very large messages + $header = preg_replace('/<\?xml.*?\?' . '>/s', '', substr($this->message, 0, 100), 1); + $this->message = trim(substr_replace($this->message, $header, 0, 100)); + if ('' == $this->message) { + return false; + } + + // Then remove the DOCTYPE + $header = preg_replace('/^<!DOCTYPE[^>]*+>/i', '', substr($this->message, 0, 200), 1); + $this->message = trim(substr_replace($this->message, $header, 0, 200)); + if ('' == $this->message) { + return false; + } + + // Check that the root tag is valid + $root_tag = substr($this->message, 0, strcspn(substr($this->message, 0, 20), "> \t\r\n")); + if ('<!DOCTYPE' === strtoupper($root_tag)) { + return false; + } + if (!in_array($root_tag, ['<methodCall', '<methodResponse', '<fault'])) { + return false; + } + + // Bail if there are too many elements to parse + $element_limit = 30000; + if ($element_limit && 2 * $element_limit < substr_count($this->message, '<')) { + return false; + } + + $this->_parser = xml_parser_create(); + // Set XML parser to take the case of tags in to account + xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false); + // Set XML parser callback functions + xml_set_object($this->_parser, $this); + xml_set_element_handler($this->_parser, 'tagOpen', 'tagClose'); + xml_set_character_data_handler($this->_parser, 'cdata'); + $chunk_size = 262144; // 256Kb, parse in chunks to avoid the RAM usage on very large messages + $final = false; + do { + if (strlen($this->message) <= $chunk_size) { + $final = true; + } + $part = substr($this->message, 0, $chunk_size); + $this->message = substr($this->message, $chunk_size); + if (!xml_parse($this->_parser, $part, $final)) { + return false; + } + if ($final) { + break; + } + } while (true); + xml_parser_free($this->_parser); + + // Grab the error messages, if any + if ($this->messageType === 'fault') { + $this->faultCode = $this->params[0]['faultCode']; + $this->faultString = $this->params[0]['faultString']; + } + return true; + } + + /** + * Opening tag handler + * @param $parser + * @param $tag + * @param $attr + */ + public function tagOpen($parser, $tag, $attr) + { + $this->_currentTagContents = ''; + $this->currentTag = $tag; + switch ($tag) { + case 'methodCall': + case 'methodResponse': + case 'fault': + $this->messageType = $tag; + break; + /* Deal with stacks of arrays and structs */ + case 'data': // data is to all intents and puposes more interesting than array + $this->_arraystructstypes[] = 'array'; + $this->_arraystructs[] = []; + break; + case 'struct': + $this->_arraystructstypes[] = 'struct'; + $this->_arraystructs[] = []; + break; + } + } + + /** + * Character Data handler + * @param $parser + * @param $cdata + */ + public function cdata($parser, $cdata) + { + $this->_currentTagContents .= $cdata; + } + + /** + * Closing tag handler + * @param $parser + * @param $tag + */ + public function tagClose($parser, $tag) + { + $valueFlag = false; + switch ($tag) { + case 'int': + case 'i4': + $value = (int)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'double': + $value = (double)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'string': + $value = (string)($this->_currentTagContents); + $valueFlag = true; + break; + case 'dateTime.iso8601': + $value = new Date(trim($this->_currentTagContents)); + $valueFlag = true; + break; + case 'value': + // "If no type is indicated, the type is string." + if (trim($this->_currentTagContents) != '') { + $value = (string)$this->_currentTagContents; + $valueFlag = true; + } + break; + case 'boolean': + $value = (boolean)trim($this->_currentTagContents); + $valueFlag = true; + break; + case 'base64': + $value = base64_decode($this->_currentTagContents); + $valueFlag = true; + break; + /* Deal with stacks of arrays and structs */ + case 'data': + case 'struct': + $value = array_pop($this->_arraystructs); + array_pop($this->_arraystructstypes); + $valueFlag = true; + break; + case 'member': + array_pop($this->_currentStructName); + break; + case 'name': + $this->_currentStructName[] = trim($this->_currentTagContents); + break; + case 'methodName': + $this->methodName = trim($this->_currentTagContents); + break; + } + + if ($valueFlag) { + if (count($this->_arraystructs) > 0) { + // Add value to struct or array + if ($this->_arraystructstypes[count($this->_arraystructstypes) - 1] === 'struct') { + // Add to struct + $this->_arraystructs[count($this->_arraystructs) - 1][$this->_currentStructName[count($this->_currentStructName) - 1]] = $value; + } else { + // Add to array + $this->_arraystructs[count($this->_arraystructs) - 1][] = $value; + } + } else { + // Just add as a paramater + $this->params[] = $value; + } + } + $this->_currentTagContents = ''; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Request/Request.php b/vendor/kissifrot/php-ixr/src/Request/Request.php new file mode 100644 index 000000000..2664fb7a8 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Request/Request.php @@ -0,0 +1,48 @@ +<?php + +namespace IXR\Request; + +use IXR\DataType\Value; + +/** + * IXR_Request + * + * @package IXR + * @since 1.5.0 + */ +class Request +{ + private $method; + private $args; + private $xml; + + public function __construct($method, $args) + { + $this->method = $method; + $this->args = $args; + $this->xml = <<<EOD +<?xml version="1.0"?> +<methodCall> +<methodName>{$this->method}</methodName> +<params> + +EOD; + foreach ($this->args as $arg) { + $this->xml .= '<param><value>'; + $v = new Value($arg); + $this->xml .= $v->getXml(); + $this->xml .= "</value></param>\n"; + } + $this->xml .= '</params></methodCall>'; + } + + public function getLength() + { + return strlen($this->xml); + } + + public function getXml() + { + return $this->xml; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Server/ClassServer.php b/vendor/kissifrot/php-ixr/src/Server/ClassServer.php new file mode 100644 index 000000000..1b0816429 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Server/ClassServer.php @@ -0,0 +1,98 @@ +<?php +namespace IXR\Server; + +use IXR\Message\Error; + +/** + * Extension of the {@link Server} class to easily wrap objects. + * + * Class is designed to extend the existing XML-RPC server to allow the + * presentation of methods from a variety of different objects via an + * XML-RPC server. + * It is intended to assist in organization of your XML-RPC methods by allowing + * you to "write once" in your existing model classes and present them. + * + * @author Jason Stirk <jstirk@gmm.com.au> + * @version 1.0.1 19Apr2005 17:40 +0800 + * @copyright Copyright (c) 2005 Jason Stirk + * @package IXR + */ +class ClassServer extends Server +{ + + private $_objects; + private $_delim; + + public function __construct($delim = '.', $wait = false) + { + parent::__construct([], false, $wait); + $this->_delim = $delim; + $this->_objects = []; + } + + public function addMethod($rpcName, $functionName) + { + $this->callbacks[$rpcName] = $functionName; + } + + public function registerObject($object, $methods, $prefix = null) + { + if (is_null($prefix)) { + $prefix = get_class($object); + } + $this->_objects[$prefix] = $object; + + // Add to our callbacks array + foreach ($methods as $method) { + if (is_array($method)) { + $targetMethod = $method[0]; + $method = $method[1]; + } else { + $targetMethod = $method; + } + $this->callbacks[$prefix . $this->_delim . $method] = [$prefix, $targetMethod]; + } + } + + public function call($methodname, $args) + { + if (!$this->hasMethod($methodname)) { + return new Error(-32601, 'server error. requested method ' . $methodname . ' does not exist.'); + } + $method = $this->callbacks[$methodname]; + + // Perform the callback and send the response + if (count($args) == 1) { + // If only one paramater just send that instead of the whole array + $args = $args[0]; + } + + // See if this method comes from one of our objects or maybe self + if (is_array($method) || (substr($method, 0, 5) == 'this:')) { + if (is_array($method)) { + $object = $this->_objects[$method[0]]; + $method = $method[1]; + } else { + $object = $this; + $method = substr($method, 5); + } + + // It's a class method - check it exists + if (!method_exists($object, $method)) { + return new Error(-32601, 'server error. requested class method "' . $method . '" does not exist.'); + } + + // Call the method + $result = $object->$method($args); + } else { + // It's a function - does it exist? + if (!function_exists($method)) { + return new Error(-32601, 'server error. requested function "' . $method . '" does not exist.'); + } + + // Call the function + $result = $method($args); + } + return $result; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Server/IntrospectionServer.php b/vendor/kissifrot/php-ixr/src/Server/IntrospectionServer.php new file mode 100644 index 000000000..8557e1fe1 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Server/IntrospectionServer.php @@ -0,0 +1,171 @@ +<?php +namespace IXR\Server; + +use IXR\DataType\Base64; +use IXR\DataType\Date; +use IXR\Message\Error; + +/** + * IXR_IntrospectionServer + * + * @package IXR + * @since 1.5.0 + */ +class IntrospectionServer extends Server +{ + + private $signatures; + private $help; + + public function __construct() + { + $this->setCallbacks(); + $this->setCapabilities(); + $this->capabilities['introspection'] = [ + 'specUrl' => 'http://xmlrpc.usefulinc.com/doc/reserved.html', + 'specVersion' => 1 + ]; + $this->addCallback( + 'system.methodSignature', + 'this:methodSignature', + ['array', 'string'], + 'Returns an array describing the return type and required parameters of a method' + ); + $this->addCallback( + 'system.getCapabilities', + 'this:getCapabilities', + ['struct'], + 'Returns a struct describing the XML-RPC specifications supported by this server' + ); + $this->addCallback( + 'system.listMethods', + 'this:listMethods', + ['array'], + 'Returns an array of available methods on this server' + ); + $this->addCallback( + 'system.methodHelp', + 'this:methodHelp', + ['string', 'string'], + 'Returns a documentation string for the specified method' + ); + } + + public function addCallback($method, $callback, $args, $help) + { + $this->callbacks[$method] = $callback; + $this->signatures[$method] = $args; + $this->help[$method] = $help; + } + + public function call($methodname, $args) + { + // Make sure it's in an array + if ($args && !is_array($args)) { + $args = [$args]; + } + + // Over-rides default call method, adds signature check + if (!$this->hasMethod($methodname)) { + return new Error(-32601, + 'server error. requested method "' . $this->message->methodName . '" not specified.'); + } + $method = $this->callbacks[$methodname]; + $signature = $this->signatures[$methodname]; + array_shift($signature); + + // Check the number of arguments + if (count($args) != count($signature)) { + return new Error(-32602, 'server error. wrong number of method parameters'); + } + + // Check the argument types + $ok = true; + $argsbackup = $args; + for ($i = 0, $j = count($args); $i < $j; $i++) { + $arg = array_shift($args); + $type = array_shift($signature); + switch ($type) { + case 'int': + case 'i4': + if (is_array($arg) || !is_int($arg)) { + $ok = false; + } + break; + case 'base64': + case 'string': + if (!is_string($arg)) { + $ok = false; + } + break; + case 'boolean': + if ($arg !== false && $arg !== true) { + $ok = false; + } + break; + case 'float': + case 'double': + if (!is_float($arg)) { + $ok = false; + } + break; + case 'date': + case 'dateTime.iso8601': + if (!($arg instanceof Date)) { + $ok = false; + } + break; + } + if (!$ok) { + return new Error(-32602, 'server error. invalid method parameters'); + } + } + // It passed the test - run the "real" method call + return parent::call($methodname, $argsbackup); + } + + public function methodSignature($method) + { + if (!$this->hasMethod($method)) { + return new Error(-32601, 'server error. requested method "' . $method . '" not specified.'); + } + // We should be returning an array of types + $types = $this->signatures[$method]; + $return = []; + foreach ($types as $type) { + switch ($type) { + case 'string': + $return[] = 'string'; + break; + case 'int': + case 'i4': + $return[] = 42; + break; + case 'double': + $return[] = 3.1415; + break; + case 'dateTime.iso8601': + $return[] = new Date(time()); + break; + case 'boolean': + $return[] = true; + break; + case 'base64': + $return[] = new Base64('base64'); + break; + case 'array': + $return[] = ['array']; + break; + case 'struct': + $return[] = ['struct' => 'struct']; + break; + } + } + return $return; + } + + public function methodHelp($method) + { + return $this->help[$method]; + } +} diff --git a/vendor/kissifrot/php-ixr/src/Server/Server.php b/vendor/kissifrot/php-ixr/src/Server/Server.php new file mode 100644 index 000000000..694c48a39 --- /dev/null +++ b/vendor/kissifrot/php-ixr/src/Server/Server.php @@ -0,0 +1,190 @@ +<?php + +namespace IXR\Server; + + +use IXR\DataType\Value; +use IXR\Exception\ServerException; +use IXR\Message\Error; +use IXR\Message\Message; + +class Server +{ + protected $callbacks = []; + protected $message; + protected $capabilities; + + public function __construct($callbacks = false, $data = false, $wait = false) + { + $this->setCapabilities(); + if ($callbacks) { + $this->callbacks = $callbacks; + } + $this->setCallbacks(); + if (!$wait) { + $this->serve($data); + } + } + + public function serve($data = false) + { + if (!$data) { + if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'POST') { + header('Content-Type: text/plain'); // merged from WP #9093 + throw new ServerException('XML-RPC server accepts POST requests only.'); + } + + $data = file_get_contents('php://input'); + } + $this->message = new Message($data); + if (!$this->message->parse()) { + $this->error(-32700, 'parse error. not well formed'); + } + if ($this->message->messageType != 'methodCall') { + $this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall'); + } + $result = $this->call($this->message->methodName, $this->message->params); + + // Is the result an error? + if ($result instanceof Error) { + $this->error($result); + } + + // Encode the result + $r = new Value($result); + $resultxml = $r->getXml(); + + // Create the XML + $xml = <<<EOD +<methodResponse> + <params> + <param> + <value> + $resultxml + </value> + </param> + </params> +</methodResponse> + +EOD; + // Send it + $this->output($xml); + } + + protected function call($methodname, $args) + { + if (!$this->hasMethod($methodname)) { + return new Error(-32601, 'server error. requested method ' . $methodname . ' does not exist.'); + } + $method = $this->callbacks[$methodname]; + // Perform the callback and send the response + + if (is_array($args) && count($args) == 1) { + // If only one parameter just send that instead of the whole array + $args = $args[0]; + } + + try { + // Are we dealing with a function or a method? + if (is_string($method) && substr($method, 0, 5) === 'this:') { + // It's a class method - check it exists + $method = substr($method, 5); + + return $this->$method($args); + } + + return call_user_func($method, $args); + } catch (\BadFunctionCallException $exception) { + return new Error(-32601, "server error. requested callable '{$method}' does not exist."); + } + + } + + public function error($error, $message = false) + { + // Accepts either an error object or an error code and message + if ($message && !is_object($error)) { + $error = new Error($error, $message); + } + $this->output($error->getXml()); + } + + public function output($xml) + { + $xml = '<?xml version="1.0"?>' . "\n" . $xml; + $length = strlen($xml); + header('Connection: close'); + header('Content-Length: ' . $length); + header('Content-Type: text/xml'); + header('Date: ' . date('r')); + echo $xml; + exit; + } + + protected function hasMethod($method) + { + return in_array($method, array_keys($this->callbacks)); + } + + protected function setCapabilities() + { + // Initialises capabilities array + $this->capabilities = [ + 'xmlrpc' => [ + 'specUrl' => 'http://www.xmlrpc.com/spec', + 'specVersion' => 1 + ], + 'faults_interop' => [ + 'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php', + 'specVersion' => 20010516 + ], + 'system.multicall' => [ + 'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208', + 'specVersion' => 1 + ], + ]; + } + + public function getCapabilities($args) + { + return $this->capabilities; + } + + public function setCallbacks() + { + $this->callbacks['system.getCapabilities'] = 'this:getCapabilities'; + $this->callbacks['system.listMethods'] = 'this:listMethods'; + $this->callbacks['system.multicall'] = 'this:multiCall'; + } + + public function listMethods($args) + { + // Returns a list of methods - uses array_reverse to ensure user defined + // methods are listed before server defined methods + return array_reverse(array_keys($this->callbacks)); + } + + public function multiCall($methodcalls) + { + // See http://www.xmlrpc.com/discuss/msgReader$1208 + $return = []; + foreach ($methodcalls as $call) { + $method = $call['methodName']; + $params = $call['params']; + if ($method == 'system.multicall') { + $result = new Error(-32600, 'Recursive calls to system.multicall are forbidden'); + } else { + $result = $this->call($method, $params); + } + if ($result instanceof Error) { + $return[] = [ + 'faultCode' => $result->code, + 'faultString' => $result->message + ]; + } else { + $return[] = [$result]; + } + } + return $return; + } +} diff --git a/vendor/splitbrain/slika/.gitignore b/vendor/splitbrain/slika/.gitignore index e176a6519..10d9f3788 100644 --- a/vendor/splitbrain/slika/.gitignore +++ b/vendor/splitbrain/slika/.gitignore @@ -1,2 +1,3 @@ vendor/ artefacts/ +.phpunit.result.cache diff --git a/vendor/splitbrain/slika/README.md b/vendor/splitbrain/slika/README.md index 0b987d442..e0955f615 100644 --- a/vendor/splitbrain/slika/README.md +++ b/vendor/splitbrain/slika/README.md @@ -40,6 +40,8 @@ try { } ``` +Please also check the [API Docs](https://splitbrain.github.io/slika/) for details. + ## Operations ### resize diff --git a/vendor/splitbrain/slika/composer.json b/vendor/splitbrain/slika/composer.json index 8acd290a0..febc83381 100644 --- a/vendor/splitbrain/slika/composer.json +++ b/vendor/splitbrain/slika/composer.json @@ -19,6 +19,6 @@ } }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.0" } } diff --git a/vendor/splitbrain/slika/composer.lock b/vendor/splitbrain/slika/composer.lock index 6957699fc..ad327ce6a 100644 --- a/vendor/splitbrain/slika/composer.lock +++ b/vendor/splitbrain/slika/composer.lock @@ -4,41 +4,36 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e6d04a08a3bf009f10b144e21fe4eb68", + "content-hash": "417266ec475af898d03447406f47a5d9", "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", + "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^6.0", + "doctrine/coding-standard": "^8.0", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" + "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" @@ -52,7 +47,7 @@ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "homepage": "https://ocramius.github.io/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", @@ -61,24 +56,42 @@ "constructor", "instantiate" ], - "time": "2019-10-21T16:45:58+00:00" + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-11-10T18:47:58+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.5", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", - "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", + "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "replace": { "myclabs/deep-copy": "self.version" @@ -109,32 +122,43 @@ "object", "object graph" ], - "time": "2020-01-17T21:11:47+00:00" + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2020-11-13T09:40:50+00:00" }, { "name": "phar-io/manifest", - "version": "1.0.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -164,24 +188,28 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/master" + }, + "time": "2020-06-27T14:33:11+00:00" }, { "name": "phar-io/version", - "version": "2.0.1", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + "reference": "e4782611070e50613683d2b9a57730e9a3ba5451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "url": "https://api.github.com/repos/phar-io/version/zipball/e4782611070e50613683d2b9a57730e9a3ba5451", + "reference": "e4782611070e50613683d2b9a57730e9a3ba5451", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -211,29 +239,33 @@ } ], "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.0.4" + }, + "time": "2020-12-13T23:18:30+00:00" }, { "name": "phpdocumentor/reflection-common", - "version": "2.1.0", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", - "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", "shasum": "" }, "require": { - "php": ">=7.1" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -260,32 +292,35 @@ "reflection", "static analysis" ], - "time": "2020-04-27T09:25:28+00:00" + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.1.0", + "version": "5.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", - "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", + "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", "shasum": "" }, "require": { - "ext-filter": "^7.1", - "php": "^7.2", - "phpdocumentor/reflection-common": "^2.0", - "phpdocumentor/type-resolver": "^1.0", - "webmozart/assert": "^1" + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" }, "require-dev": { - "doctrine/instantiator": "^1", - "mockery/mockery": "^1" + "mockery/mockery": "~1.3.2" }, "type": "library", "extra": { @@ -313,34 +348,37 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2020-02-22T12:28:44+00:00" + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + }, + "time": "2020-09-03T19:13:55+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.1.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", - "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", + "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", "shasum": "" }, "require": { - "php": "^7.2", + "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.2", - "mockery/mockery": "~1" + "ext-tokenizer": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-1.x": "1.x-dev" } }, "autoload": { @@ -359,37 +397,41 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2020-02-18T18:59:58+00:00" + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0" + }, + "time": "2020-09-17T18:55:26+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.10.3", + "version": "1.12.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "451c3cd1418cf640de218914901e51b064abb093" + "reference": "245710e971a030f42e08f4912863805570f23d39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", - "reference": "451c3cd1418cf640de218914901e51b064abb093", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/245710e971a030f42e08f4912863805570f23d39", + "reference": "245710e971a030f42e08f4912863805570f23d39", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" + "doctrine/instantiator": "^1.2", + "php": "^7.2 || ~8.0, <8.1", + "phpdocumentor/reflection-docblock": "^5.2", + "sebastian/comparator": "^3.0 || ^4.0", + "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5 || ^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpspec/phpspec": "^6.0", + "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10.x-dev" + "dev-master": "1.11.x-dev" } }, "autoload": { @@ -422,44 +464,48 @@ "spy", "stub" ], - "time": "2020-03-05T15:02:03+00:00" + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/1.12.2" + }, + "time": "2020-12-19T10:15:11+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "6.1.4", + "version": "7.0.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + "reference": "bb7c9a210c72e4709cdde67f8b7362f672f2225c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bb7c9a210c72e4709cdde67f8b7362f672f2225c", + "reference": "bb7c9a210c72e4709cdde67f8b7362f672f2225c", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", + "php": ">=7.2", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", + "phpunit/php-token-stream": "^3.1.1 || ^4.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", + "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.2.2" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-xdebug": "^2.7.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -485,27 +531,37 @@ "testing", "xunit" ], - "time": "2018-10-31T16:06:48+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.14" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-12-02T13:39:03+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "050bedf145a257b1ff02746c31894800e5122946" + "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", - "reference": "050bedf145a257b1ff02746c31894800e5122946", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4b49fb70f067272b659ef0174ff9ca40fdaa6357", + "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -535,7 +591,17 @@ "filesystem", "iterator" ], - "time": "2018-09-13T20:33:42+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:25:21+00:00" }, { "name": "phpunit/php-text-template", @@ -576,27 +642,31 @@ "keywords": [ "template" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" + }, "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "2.1.2", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", + "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -625,33 +695,43 @@ "keywords": [ "timer" ], - "time": "2019-06-07T04:22:29+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:20:02+00:00" }, { "name": "phpunit/php-token-stream", - "version": "3.1.1", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/a853a0e183b9db7eed023d7933a858fa1c8d25a3", + "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.1" + "php": "^7.3 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -674,57 +754,67 @@ "keywords": [ "tokenizer" ], - "time": "2019-09-17T06:23:10+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "abandoned": true, + "time": "2020-08-04T08:28:15+00:00" }, { "name": "phpunit/phpunit", - "version": "7.5.20", + "version": "8.5.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9467db479d1b0487c99733bb1e7944d32deded2c" + "reference": "c25f79895d27b6ecd5abfa63de1606b786a461a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c", - "reference": "9467db479d1b0487c99733bb1e7944d32deded2c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c25f79895d27b6ecd5abfa63de1606b786a461a3", + "reference": "c25f79895d27b6ecd5abfa63de1606b786a461a3", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.1", + "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.0", + "phar-io/manifest": "^2.0.1", + "phar-io/version": "^3.0.2", + "php": ">=7.2", + "phpspec/prophecy": "^1.10.3", + "phpunit/php-code-coverage": "^7.0.12", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", + "phpunit/php-timer": "^2.1.2", + "sebastian/comparator": "^3.0.2", + "sebastian/diff": "^3.0.2", + "sebastian/environment": "^4.2.3", + "sebastian/exporter": "^3.1.2", + "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0", + "sebastian/resource-operations": "^2.0.1", + "sebastian/type": "^1.1.3", "sebastian/version": "^2.0.1" }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" - }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-soap": "*", "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" + "phpunit/php-invoker": "^2.0.0" }, "bin": [ "phpunit" @@ -732,7 +822,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.5-dev" + "dev-master": "8.5-dev" } }, "autoload": { @@ -758,27 +848,41 @@ "testing", "xunit" ], - "time": "2020-01-08T08:45:45+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.14" + }, + "funding": [ + { + "url": "https://phpunit.de/donate.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-01-17T07:37:30+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", + "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -803,29 +907,39 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:15:22+00:00" }, { "name": "sebastian/comparator", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + "reference": "1071dfcef776a57013124ff35e1fc41ccd294758" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1071dfcef776a57013124ff35e1fc41ccd294758", + "reference": "1071dfcef776a57013124ff35e1fc41ccd294758", "shasum": "" }, "require": { - "php": "^7.1", + "php": ">=7.1", "sebastian/diff": "^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "^7.1" + "phpunit/phpunit": "^8.5" }, "type": "library", "extra": { @@ -844,6 +958,10 @@ ], "authors": [ { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, @@ -854,10 +972,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -867,24 +981,34 @@ "compare", "equality" ], - "time": "2018-07-12T15:12:46+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T08:04:30+00:00" }, { "name": "sebastian/diff", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/14f72dd46eaf2f2293cbe79c93cc0bc43161a211", + "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "^7.5 || ^8.0", @@ -907,12 +1031,12 @@ ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", @@ -923,24 +1047,34 @@ "unidiff", "unified diff" ], - "time": "2019-02-04T06:01:07+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:59:04+00:00" }, { "name": "sebastian/environment", - "version": "4.2.3", + "version": "4.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", - "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", + "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -976,24 +1110,34 @@ "environment", "hhvm" ], - "time": "2019-11-20T08:46:58+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:53:42+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.2", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e", + "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e", "shasum": "" }, "require": { - "php": "^7.0", + "php": ">=7.0", "sebastian/recursion-context": "^3.0" }, "require-dev": { @@ -1043,27 +1187,40 @@ "export", "exporter" ], - "time": "2019-09-14T09:02:43+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:47:53+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/474fb9edb7ab891665d3bfc6317f42a0a150454b", + "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-uopz": "*" @@ -1071,7 +1228,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1094,24 +1251,34 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:43:24+00:00" }, { "name": "sebastian/object-enumerator", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", + "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", "shasum": "" }, "require": { - "php": "^7.0", + "php": ">=7.0", "sebastian/object-reflector": "^1.1.1", "sebastian/recursion-context": "^3.0" }, @@ -1141,24 +1308,34 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:40:27+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.1", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", + "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" @@ -1186,24 +1363,34 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:37:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", + "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.0" }, "require-dev": { "phpunit/phpunit": "^6.0" @@ -1225,38 +1412,48 @@ ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:34:24+00:00" }, { "name": "sebastian/resource-operations", - "version": "2.0.1", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", + "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=7.1" }, "type": "library", "extra": { @@ -1281,7 +1478,73 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2018-10-04T04:07:39+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:30:19+00:00" + }, + { + "name": "sebastian/type", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-30T07:25:11+00:00" }, { "name": "sebastian/version", @@ -1324,24 +1587,28 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/master" + }, "time": "2016-10-03T07:35:21+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.15.0", + "version": "v1.22.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "suggest": { "ext-ctype": "For best performance" @@ -1349,7 +1616,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { @@ -1382,6 +1653,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -1396,27 +1670,27 @@ "type": "tidelift" } ], - "time": "2020-02-27T09:26:54+00:00" + "time": "2021-01-07T16:49:33+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.3", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + "reference": "75a63c33a8577608444246075ea0af0d052e452a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", + "reference": "75a63c33a8577608444246075ea0af0d052e452a", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -1436,27 +1710,38 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2019-06-13T22:48:21+00:00" + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/master" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2020-07-12T23:59:07+00:00" }, { "name": "webmozart/assert", - "version": "1.8.0", + "version": "1.9.1", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" + "url": "https://github.com/webmozarts/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", - "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0", + "php": "^5.3.3 || ^7.0 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { + "phpstan/phpstan": "<0.12.20", "vimeo/psalm": "<3.9.1" }, "require-dev": { @@ -1484,7 +1769,11 @@ "check", "validate" ], - "time": "2020-04-18T12:12:48+00:00" + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.9.1" + }, + "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], @@ -1494,5 +1783,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } diff --git a/vendor/splitbrain/slika/src/Adapter.php b/vendor/splitbrain/slika/src/Adapter.php index 99d1de1d3..66d774858 100644 --- a/vendor/splitbrain/slika/src/Adapter.php +++ b/vendor/splitbrain/slika/src/Adapter.php @@ -3,7 +3,9 @@ namespace splitbrain\slika; - +/** + * Base class for image adapters. Defines what image processing adapters need to provide + */ abstract class Adapter { /** @var string path tot he image */ diff --git a/vendor/splitbrain/slika/src/Exception.php b/vendor/splitbrain/slika/src/Exception.php index 8db7f0686..98b59c404 100644 --- a/vendor/splitbrain/slika/src/Exception.php +++ b/vendor/splitbrain/slika/src/Exception.php @@ -3,7 +3,9 @@ namespace splitbrain\slika; - +/** + * Exception thrown on all errors during image processing + */ class Exception extends \Exception { diff --git a/vendor/splitbrain/slika/src/GdAdapter.php b/vendor/splitbrain/slika/src/GdAdapter.php index c55859955..3f05b06b9 100644 --- a/vendor/splitbrain/slika/src/GdAdapter.php +++ b/vendor/splitbrain/slika/src/GdAdapter.php @@ -3,7 +3,9 @@ namespace splitbrain\slika; - +/** + * Image processing adapter for PHP's libGD + */ class GdAdapter extends Adapter { /** @var resource libGD image */ diff --git a/vendor/splitbrain/slika/src/ImageMagickAdapter.php b/vendor/splitbrain/slika/src/ImageMagickAdapter.php index 50527a894..b0499bfe8 100644 --- a/vendor/splitbrain/slika/src/ImageMagickAdapter.php +++ b/vendor/splitbrain/slika/src/ImageMagickAdapter.php @@ -3,7 +3,9 @@ namespace splitbrain\slika; - +/** + * Image Processing Adapter for ImageMagick's command line utility `convert` + */ class ImageMagickAdapter extends Adapter { /** @var array the CLI arguments to run imagemagick */ @@ -86,10 +88,14 @@ class ImageMagickAdapter extends Adapter if ($width == 0) $width = $height; if ($height == 0) $height = $width; + $size = $width . 'x' . $height; + + $this->args[] = '-resize'; + $this->args[] = "$size^"; $this->args[] = '-gravity'; $this->args[] = 'center'; $this->args[] = '-crop'; - $this->args[] = $width . 'x' . $height . '+0+0'; + $this->args[] = "$size+0+0"; $this->args[] = '+repage'; return $this; } diff --git a/vendor/splitbrain/slika/src/Slika.php b/vendor/splitbrain/slika/src/Slika.php index 122bfaa7f..9782c1ed0 100644 --- a/vendor/splitbrain/slika/src/Slika.php +++ b/vendor/splitbrain/slika/src/Slika.php @@ -3,17 +3,19 @@ namespace splitbrain\slika; - +/** + * Factory to process an image using an available Adapter + */ class Slika { - /** @var int rotate an image counter clock wise */ + /** rotate an image counter clock wise */ const ROTATE_CCW = 8; - /** @var int rotate an image clock wise */ + /** rotate an image clock wise */ const ROTATE_CW = 6; - /** @var int rotate on it's head */ + /** rotate on it's head */ const ROTATE_TOPDOWN = 3; - + /** these can be overwritten using the options array in run() */ const DEFAULT_OPTIONS = [ 'quality' => 92, 'imconvert' => '/usr/bin/convert', |