Merge remote-tracking branch 'splitbrain/master'

This commit is contained in:
Gerry Weißbach 2014-07-16 08:02:34 +02:00
commit 0bd5b90b4c
712 changed files with 24045 additions and 15098 deletions

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
; http://editorconfig.org/
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[inc/{geshi,phpseclib}/**]
; Use editor default (possible autodetection).
indent_style =
indent_size =
trim_trailing_whitespace = false
insert_final_newline = false

8
.gitattributes vendored
View File

@ -4,3 +4,11 @@
*.gif binary
*.ico binary
*.xcf binary
.gitattributes export-ignore
.gitignore export-ignore
.editorconfig export-ignore
.travis.yml export-ignore
_test export-ignore
_cs export-ignore
lib/plugins/testing export-ignore

10
.gitignore vendored
View File

@ -9,6 +9,7 @@
/conf/lang/*
/conf/plugin_lang/*
/conf/plugins.local.*
/conf/tpl/*
.htaccess
*.swp
*.bak
@ -26,25 +27,23 @@
/data/media_attic/*
/data/meta/*
/data/pages/*
/data/tmp/*
!/data/pages/wiki/dokuwiki.txt
!/data/pages/wiki/syntax.txt
!/data/pages/wiki/welcome.txt
/data/tmp/*
/lib/tpl/*
!/lib/tpl/default
!/lib/tpl/dokuwiki
!/lib/tpl/index.php
/lib/plugins/*
!/lib/plugins/acl
!/lib/plugins/authad
!/lib/plugins/authldap
!/lib/plugins/authmysql
!/lib/plugins/authpgsql
!/lib/plugins/authplain
!/lib/plugins/acl
!/lib/plugins/config
!/lib/plugins/extension
!/lib/plugins/info
!/lib/plugins/plugin
!/lib/plugins/popularity
!/lib/plugins/revert
!/lib/plugins/safefnrecode
@ -52,5 +51,8 @@
!/lib/plugins/usermanager
!/lib/plugins/action.php
!/lib/plugins/admin.php
!/lib/plugins/auth.php
!/lib/plugins/index.html
!/lib/plugins/remote.php
!/lib/plugins/syntax.php
lib/images/*/local/*

View File

@ -9,4 +9,4 @@ notifications:
- "chat.freenode.net#dokuwiki"
on_success: change
on_failure: change
script: cd _test && phpunit --stderr
script: cd _test && phpunit --verbose --stderr

View File

@ -9,35 +9,28 @@ This is the test suite to automatically test various parts of DokuWiki.
===== PHPUnit Installation ======
==== via PEAR installer ====
You can install phpunit through your distribution's package manager or simply
download the newest phar file into the _test directory:
pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit
==== via Composer ====
Include a composer.json file in your project, which can be as minimal as:
<code>
{
"require-dev": {
"phpunit/phpunit": "3.7.*"
}
}
</code>
==== via PHP archive (PHAR) ====
Download http://pear.phpunit.de/get/phpunit.phar and make it executable on your system.
cd _test/
wget https://phar.phpunit.de/phpunit.phar
===== Running all tests =====
Just change to the ''_test'' directory and run phpunit:
Just change to the ''_test'' directory and run phpunit (depending on your install
method):
cd _test/
phpunit
or
cd _test/
php phpunit.phar
===== Troubleshooting =====
PHPUnit will fail on some systems with a //headers already sent// error.
This is a known problem with PHPUnit, the error can be avoided by passing the
'--stderr' flag to phpunit:
@ -46,8 +39,10 @@ This is a known problem with PHPUnit, the error can be avoided by passing the
On windows you may have to enable OpenSSL support for https tests.
Some of them point to httpclient_http.tests.php on the failure.
To enable HTTPS support copy the ''libeay32.dll'' and ''ssleay32.dll'' to your ''windows\system32'' folder
and add the following line to your php.ini in the extension section:
To enable HTTPS support copy the ''libeay32.dll'' and ''ssleay32.dll''
to your ''windows\system32'' folder and add the following line to your php.ini
in the extension section:
<code ini>
extension=php_openssl.dll
</code>
@ -56,13 +51,13 @@ extension=php_openssl.dll
You can run a single test file by providing it as an argument to phpunit:
phpunit --stderr tests/inc/common_cleanText.test.php
phpunit tests/inc/common_cleanText.test.php
You can also use groups to exclude certain test from running. For example use
the following command to avoid long running test or tests accessing the
Internet.
phpunit --stderr --exclude-group slow,internet
phpunit --exclude-group slow,internet
===== Create new Tests =====
@ -71,23 +66,10 @@ folder. Please respect the folder structure and naming convention. Inside the
file, implement a class, extending 'DokuWikiTest'. Every method, starting
with 'test' will be called as a test (e.g. 'testIfThisIsValid');
===== TODO for the test framework =====
* test cross platform compatibility: especially test windows
* update http://www.dokuwiki.org/devel:unittesting
* optional: add helper methods to TestRequest for easy form submission
* createForm(), ...
* check PHP Unit test_helpers https://github.com/sebastianbergmann/php-test-helpers
===== Migration Protocol =====
The following tests were not migrated:
* inc/indexer_idx_indexlengths (fs dependencies)
* inc/mail_send (integration test)
* inc/parser/parser_formatting
* inc/parser/xhtml_htmlphp (runkit)
* inc/parser/xhtml_links

View File

@ -115,5 +115,8 @@ abstract class DokuWikiTest extends PHPUnit_Framework_TestCase {
// reload language
$local = $conf['lang'];
trigger_event('INIT_LANG_LOAD', $local, 'init_lang', true);
global $INPUT;
$INPUT = new Input();
}
}

View File

@ -44,13 +44,18 @@ class TestRequest {
* @return TestResponse the resulting output of the request
*/
public function execute($uri='/doku.php') {
global $INPUT;
global $ID;
global $INFO;
// save old environment
$server = $_SERVER;
$session = $_SESSION;
$get = $_GET;
$post = $_POST;
$request = $_REQUEST;
$input = $INPUT;
// prepare the right URI
$this->setUri($uri);
@ -74,6 +79,7 @@ class TestRequest {
// now execute dokuwiki and grep the output
header_remove();
ob_start('ob_start_callback');
$INPUT = new Input();
include(DOKU_INC.$this->script);
ob_end_flush();
@ -89,6 +95,7 @@ class TestRequest {
$_GET = $get;
$_POST = $post;
$_REQUEST = $request;
$INPUT = $input;
return $response;
}

View File

@ -1,7 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="bootstrap.php"
convertNoticesToExceptions="false">
convertNoticesToExceptions="false"
colors="true"
stderr="true"
>
<testsuites>
<testsuite name="DokuWiki Tests">

View File

@ -5,7 +5,7 @@
*
* most tests are in auth_password.test.php
*/
class PassHash_test extends PHPUnit_Framework_TestCase {
class PassHash_test extends DokuWikiTest {
function test_hmac(){
// known hashes taken from https://code.google.com/p/yii/issues/detail?id=1942

View File

@ -1,6 +1,6 @@
<?php
class auth_password_test extends PHPUnit_Framework_TestCase {
class auth_password_test extends DokuWikiTest {
// hashes for the password foo$method, using abcdefgh as salt
var $passes = array(

View File

@ -0,0 +1,83 @@
<?php
/**
* Class cache_use_test
*
* Tests if caching can actually be used
*/
class cache_use_test extends DokuWikiTest {
/** @var cache_renderer $cache */
private $cache;
function setUp() {
global $ID, $conf;
parent::setUp();
$ID = 'cached';
$file = wikiFN($ID);
$conf['cachetime'] = 0; // ensure the value is not -1, which disables caching
saveWikiText($ID, 'Content', 'Created');
$this->cache = new cache_renderer($ID, $file, 'xhtml');
$this->cache->storeCache('Test');
// set the modification times explicitly (overcome Issue #694)
$time = time();
touch($file, $time-1);
touch($this->cache->cache, $time);
}
function test_use() {
$this->assertTrue($this->cache->useCache());
}
/**
* In all the following tests the cache should not be usable
* as such, they are meaningless if test_use didn't pass.
*
* @depends test_use
*/
function test_purge() {
/* @var Input $INPUT */
global $INPUT;
$INPUT->set('purge',1);
$this->assertFalse($this->cache->useCache());
$this->assertNotEmpty($this->cache->depends['purge']);
}
/**
* @depends test_use
*/
function test_filedependency() {
// give the dependent src file the same mtime as the cache
touch($this->cache->file, filemtime($this->cache->cache));
$this->assertFalse($this->cache->useCache());
}
/**
* @depends test_use
*/
function test_age() {
// need to age both our source file & the cache
$age = 10;
$time = time() - $age - 1; // older than age
touch($this->cache->file, $time - 1);
touch($this->cache->cache, $time);
$this->assertFalse($this->cache->useCache(array('age' => $age)));
}
/**
* @depends test_use
*/
function test_confnocaching() {
global $conf;
$conf['cachetime'] = -1; // disables renderer caching
$this->assertFalse($this->cache->useCache());
$this->assertNotEmpty($this->cache->_nocache);
}
}

View File

@ -0,0 +1,188 @@
<?php
/**
* Tests for requesting revisions of a page with getRevisions()
*
* This class uses the files:
* - data/pages/mailinglist.txt
* - data/meta/mailinglist.changes
*/
class changelog_getrevisionsaround_test extends DokuWikiTest {
/**
* list of revisions in mailinglist.changes
*/
private $revsexpected = array(
1374261194, //current page
1371579614, 1368622240,
1368622195, 1368622152,
1368612599, 1368612506,
1368609772, 1368575634,
1363436892, 1362527164,
1362527046, 1362526861,
1362526767, 1362526167,
1362526119, 1362526039,
1362525926, 1362525899,
1362525359, 1362525145,
1362524799, 1361901536,
1360110636
);
private $pageid = 'mailinglist';
function setup() {
parent::setup();
global $cache_revinfo;
$cache =& $cache_revinfo;
if(isset($cache['nonexist'])) {
unset($cache['nonexist']);
}
if(isset($cache['mailinglist'])) {
unset($cache['mailinglist']);
}
}
/**
* no nonexist.changes meta file available
*/
function test_changemetadatanotexists() {
$rev1 = 1362526767;
$rev2 = 1362527164;
$max = 50;
$id = 'nonexist';
$revsexpected = array(array(), array());
$pagelog = new PageChangeLog($id, $chunk_size = 8192);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
}
/**
* Surrounding revisions of rev1 and rev2 overlaps
*/
function test_request_overlapping() {
$rev1 = 1362526767;
$rev2 = 1362527164;
$max = 10;
$revsexpected = array(
array_slice($this->revsexpected, 8, 11),
array_slice($this->revsexpected, 5, 11)
);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
}
/**
* Surrounding revisions of rev1 and rev2 don't overlap.
*/
function test_request_non_overlapping() {
$rev1 = 1362525899;
$rev2 = 1368612599;
$max = 10;
$revsexpected = array(
array_slice($this->revsexpected, 13, 11),
array_slice($this->revsexpected, 0, 11)
);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
}
/**
* rev1 and rev2 are at start and end of the changelog.
* Should return still a number of revisions equal to max
*/
function test_request_first_last() {
$rev1 = 1360110636;
$rev2 = 1374261194;
$max = 10;
$revsexpected = array(
array_slice($this->revsexpected, 13, 11),
array_slice($this->revsexpected, 0, 11)
);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
//todo: number of revisions on the left side is not (yet) completed until max number
$revsexpected = array(
array_slice($this->revsexpected, 18, 6),
array_slice($this->revsexpected, 0, 11)
);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
}
/**
* Number of requested revisions is larger than available revisions,
* so returns whole log
*/
function test_request_wholelog() {
$rev1 = 1362525899;
$rev2 = 1368612599;
$max = 50;
$revsexpected = array($this->revsexpected, $this->revsexpected);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
}
/**
* When rev1 > rev2, their order is changed
*/
function test_request_wrong_order_revs() {
$rev1 = 1362527164;
$rev2 = 1362526767;
$max = 10;
$revsexpected = array(
array_slice($this->revsexpected, 8, 11),
array_slice($this->revsexpected, 5, 11)
);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisionsAround($rev1, $rev2, $max);
$this->assertEquals($revsexpected, $revs);
}
}

View File

@ -0,0 +1,418 @@
<?php
/**
* Tests for requesting revisioninfo of a revision of a page with getRevisionInfo()
*
* This class uses the files:
* - data/pages/mailinglist.txt
* - data/meta/mailinglist.changes
*/
class changelog_getrelativerevision_test extends DokuWikiTest {
private $logline = "1362525899 127.0.0.1 E mailinglist pubcie [Data entry] \n";
private $pageid = 'mailinglist';
function setup() {
parent::setup();
global $cache_revinfo;
$cache =& $cache_revinfo;
if(isset($cache['nonexist'])) {
unset($cache['nonexist']);
}
if(isset($cache['mailinglist'])) {
unset($cache['mailinglist']);
}
}
/**
* no nonexist.changes meta file available
*/
function test_changemetadatanotexists() {
$rev = 1362525899;
$dir = 1;
$id = 'nonexist';
$revsexpected = false;
$pagelog = new PageChangeLog($id, $chunk_size = 8192);
$revs = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revsexpected, $revs);
}
/**
* no nonexist.changes meta file available
*/
function test_nodirection() {
$rev = 1362525899;
$dir = 0;
$revsexpected = false;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revsexpected, $revs);
}
/**
* start at exact current revision of mailinglist page
*
*/
function test_startatexactcurrentrev() {
$rev = 1385051947;
$dir = 1;
$revsexpectedpos = false;
$revsexpectedneg = 1374261194;
//set a known timestamp
touch(wikiFN($this->pageid), $rev);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revsexpectedpos, $revs);
$revs = $pagelog->getRelativeRevision($rev, -$dir);
$this->assertEquals($revsexpectedneg, $revs);
}
/**
* start at exact last revision of mailinglist page
*
*/
function test_startatexactlastrev() {
$rev = 1360110636;
$dir = 1;
$revsexpectedpos = 1361901536;
$revsexpectedneg = false;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revsexpectedpos, $revs);
$revs = $pagelog->getRelativeRevision($rev, -$dir);
$this->assertEquals($revsexpectedneg, $revs);
}
/**
* start at exact one before last revision of mailinglist page
*
*/
function test_requestlastrevisions() {
$rev = 1361901536;
$dir = -1;
$revsexpectedlast = 1360110636;
$revsexpectedbeforelast = false;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revsexpectedlast, $revs);
$revs = $pagelog->getRelativeRevision($rev, 2 * $dir);
$this->assertEquals($revsexpectedbeforelast, $revs);
}
/**
* request existing rev and check cache
*/
function test_requestrev_checkcache() {
$rev = 1362525359;
$dir = 1;
$revexpected = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
//checked info returned from cache
$info = $pagelog->getRevisionInfo($revfound);
$this->assertEquals($infoexpected, $info);
}
/**
* request existing rev
*/
function test_requestnextrev() {
$rev = 1362525899;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$dir = 1;
$revexpected = 1362525926;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = 2;
$revexpected = 1362526039;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = -1;
$revexpected = 1362525359;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = -2;
$revexpected = 1362525145;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request existing rev with chucked reading
*/
function test_requestnextrev_chuncked() {
$rev = 1362525899;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$dir = 1;
$revexpected = 1362525926;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = 2;
$revexpected = 1362526039;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = -1;
$revexpected = 1362525359;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = -2;
$revexpected = 1362525145;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request existing rev with chucked reading, chunk size smaller than line length
*/
function test_requestnextrev_chunkshorterthanlines() {
$rev = 1362525899;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$dir = 1;
$revexpected = 1362525926;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = 2;
$revexpected = 1362526039;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = -1;
$revexpected = 1362525359;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
$dir = -2;
$revexpected = 1362525145;
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request existing rev
*/
function test_requestnextfifthrev() {
$rev = 1362525899;
$dir = 5;
$revexpected = 1362526767;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request existing rev with chucked reading
*/
function test_requestnextfifthrev_chuncked() {
$rev = 1362525899;
$dir = 5;
$revexpected = 1362526767;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request existing rev
*/
function test_requestprevrev() {
$rev = 1362525899;
$dir1 = -1;
$dir5 = -5;
$revexpected1 = 1362525359;
$revexpected5 = 1360110636;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound1 = $pagelog->getRelativeRevision($rev, $dir1);
$this->assertEquals($revexpected1, $revfound1);
$revfound5 = $pagelog->getRelativeRevision($rev, $dir5);
$this->assertEquals($revexpected5, $revfound5);
}
/**
* request existing rev with chucked reading
*/
function test_requestprevrev_chuncked() {
$rev = 1362525899;
$dir1 = -1;
$dir5 = -5;
$revexpected1 = 1362525359;
$revexpected5 = 1360110636;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revfound1 = $pagelog->getRelativeRevision($rev, $dir1);
$this->assertEquals($revexpected1, $revfound1);
$revfound5 = $pagelog->getRelativeRevision($rev, $dir5);
$this->assertEquals($revexpected5, $revfound5);
}
/**
* request after recentest version in changelog
*/
function test_requestrecentestlogline_next() {
$rev = 1374261194;
$dir = 1;
$revexpected = false;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request after recentest version in changelog, with chuncked reading
*/
function test_requestrecentestlogline_next_chuncked() {
$rev = 1374261194;
$dir = 1;
$revexpected = false;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request before current version
*/
function test_requestrecentestlogline_prev() {
$rev = 1374261194;
$dir = -1;
$revexpected = 1371579614;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* request before current version, with chuncked reading
*/
function test_requestrecentestlogline_prev_chuncked() {
$rev = 1374261194;
$dir = -1;
$revexpected = 1371579614;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* Request negative revision
* looks in positive direction, so it catches the oldest revision
*/
function test_negativerev_posdir() {
$rev = -10;
$dir = 1;
$revexpected = 1360110636;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* Request negative revision
* looks in negative direction, but there is nothing
*/
function test_negativerev_negdir() {
$rev = -10;
$dir = -1;
$revexpected = false;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* Start at non existing revision somewhere between existing revisions
*/
function test_startatnotexistingrev_next() {
$rev = 1362525890;
$dir = 1;
$revexpected = 1362525899;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
/**
* Start at non existing revision somewhere between existing revisions
*/
function test_startatnotexistingrev_prev() {
$rev = 1362525890;
$dir = -1;
$revexpected = 1362525359;
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revfound = $pagelog->getRelativeRevision($rev, $dir);
$this->assertEquals($revexpected, $revfound);
}
function test_iscurrentpagerevision() {
$rev = 1385051947;
$currentexpected = true;
//set a known timestamp
touch(wikiFN($this->pageid), $rev);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$current = $pagelog->isCurrentRevision($rev);
$this->assertEquals($currentexpected, $current);
}
function test_isnotcurrentpagerevision() {
$rev = 1385051947;
$not_current_rev = $rev - 1;
$currentexpected = false;
//set a known timestamp
touch(wikiFN($this->pageid), $rev);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$current = $pagelog->isCurrentRevision($not_current_rev);
$this->assertEquals($currentexpected, $current);
}
function test_notexistingcurrentpage() {
$rev = 1385051947;
$currentexpected = false;
$pagelog = new PageChangeLog('nonexistingpage', $chunk_size = 8192);
$current = $pagelog->isCurrentRevision($rev);
$this->assertEquals($currentexpected, $current);
}
}

View File

@ -21,7 +21,7 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
unset($cache['nonexist']);
}
if(isset($cache['mailinglist'])) {
unset($cache['nonexist']);
unset($cache['mailinglist']);
}
}
@ -29,11 +29,12 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* no nonexist.changes meta file available
*/
function test_changemetadatanotexists() {
$rev = 1362525899;
$id = 'nonexist';
$rev = 1362525899;
$id = 'nonexist';
$revsexpected = false;
$revs = getRevisionInfo($id, $rev, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($id, $chunk_size = 8192);
$revs = $pagelog->getRevisionInfo($rev);
$this->assertEquals($revsexpected, $revs);
}
@ -41,13 +42,14 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request existing rev
*/
function test_requestrev() {
$rev = 1362525899;
$rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
//returns cached value
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@ -55,10 +57,23 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request existing rev with chucked reading
*/
function test_requestrev_chuncked() {
$rev = 1362525899;
$rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
/**
* request existing rev with chucked reading
*/
function test_requestrev_chunckedsmallerthanlinelength() {
$rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@ -66,13 +81,14 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request current version
*/
function test_requestrecentestlogline() {
$rev = 1374261194;
$rev = 1374261194;
$infoexpected = parseChangelogLine($this->firstlogline);
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
//returns cached value
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@ -80,10 +96,11 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* request current version, with chuncked reading
*/
function test_requestrecentestlogline_chuncked() {
$rev = 1374261194;
$rev = 1374261194;
$infoexpected = parseChangelogLine($this->firstlogline);
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
@ -93,7 +110,8 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
function test_negativerev() {
$rev = -10;
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals(false, $info);
}
@ -103,7 +121,8 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
function test_notexistingrev() {
$rev = 1362525890;
$info = getRevisionInfo($this->pageid, $rev, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals(false, $info);
}
@ -111,10 +130,11 @@ class changelog_getrevisionsinfo_test extends DokuWikiTest {
* sometimes chuncksize is set to true
*/
function test_chuncksizetrue() {
$rev = 1362525899;
$rev = 1362525899;
$infoexpected = parseChangelogLine($this->logline);
$info = getRevisionInfo($this->pageid, $rev, true);
$pagelog = new PageChangeLog($this->pageid, true);
$info = $pagelog->getRevisionInfo($rev);
$this->assertEquals($infoexpected, $info);
}
}

View File

@ -36,7 +36,7 @@ class changelog_getrevisions_test extends DokuWikiTest {
unset($cache['nonexist']);
}
if(isset($cache['mailinglist'])) {
unset($cache['nonexist']);
unset($cache['mailinglist']);
}
}
@ -45,11 +45,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
*/
function test_changemetadatanotexists() {
$first = 0;
$num = 1;
$id = 'nonexist';
$revs = getRevisions($id, $first, $num, $chunk_size = 8192, $media = false);
$num = 1;
$id = 'nonexist';
$revsexpected = array();
$pagelog = new PageChangeLog($id, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -58,14 +59,20 @@ class changelog_getrevisions_test extends DokuWikiTest {
* (so skips first line which belongs to the current existing page)
*/
function test_requestlastrev() {
$first = 0;
$num = 1;
$first = 0;
$num = 1;
$revsexpected = array($this->revsexpected[1]);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -74,14 +81,20 @@ class changelog_getrevisions_test extends DokuWikiTest {
* (so skips first line which belongs to the current existing page)
*/
function test_requestonebutlastrev() {
$first = 1;
$num = 1;
$first = 1;
$num = 1;
$revsexpected = array($this->revsexpected[2]);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -90,14 +103,20 @@ class changelog_getrevisions_test extends DokuWikiTest {
* (so skips first line of current existing page)
*/
function test_requestrevswithoffset() {
$first = 10;
$num = 5;
$first = 10;
$num = 5;
$revsexpected = array_slice($this->revsexpected, $first + 1, $num);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 20);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -105,14 +124,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* first = -1 requests recentest logline, without skipping
*/
function test_requestrecentestlogline() {
$first = -1;
$num = 1;
$first = -1;
$num = 1;
$revsexpected = array($this->revsexpected[0]);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -120,11 +141,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
* chunck size = 0 skips chuncked loading
*/
function test_wholefile() {
$first = 0;
$num = 1000;
$first = 0;
$num = 1000;
$revsexpected = array_slice($this->revsexpected, 1);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 0, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 0);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -132,14 +154,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* Negative range returns no result
*/
function test_negativenum() {
$first = 0;
$num = -10;
$first = 0;
$num = -10;
$revsexpected = array();
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -147,14 +171,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* Negative range returns no result
*/
function test_negativennumoffset() {
$first = 2;
$num = -10;
$first = 2;
$num = -10;
$revsexpected = array();
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -162,14 +188,16 @@ class changelog_getrevisions_test extends DokuWikiTest {
* zero range returns no result
*/
function test_zeronum() {
$first = 5;
$num = 0;
$first = 5;
$num = 0;
$revsexpected = array();
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 512, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 512);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -177,11 +205,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
* get oldest revisions
*/
function test_requestlargeoffset() {
$first = 22;
$num = 50;
$first = 22;
$num = 50;
$revsexpected = array_slice($this->revsexpected, $first + 1);
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}
@ -189,11 +218,12 @@ class changelog_getrevisions_test extends DokuWikiTest {
* request with too large offset and range
*/
function test_requesttoolargenumberrevs() {
$first = 50;
$num = 50;
$first = 50;
$num = 50;
$revsexpected = array();
$revs = getRevisions($this->pageid, $first, $num, $chunk_size = 8192, $media = false);
$pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
$revs = $pagelog->getRevisions($first, $num);
$this->assertEquals($revsexpected, $revs);
}

View File

@ -0,0 +1,56 @@
<?php
class cli_options extends DokuWikiTest {
function test_simpleshort() {
$options = new DokuCLI_Options();
$options->registerOption('exclude', 'exclude files', 'x', 'file');
$options->args = array('-x', 'foo', 'bang');
$options->parseOptions();
$this->assertEquals('foo', $options->getOpt('exclude'));
$this->assertEquals(array('bang'), $options->args);
$this->assertFalse($options->getOpt('nothing'));
}
function test_simplelong1() {
$options = new DokuCLI_Options();
$options->registerOption('exclude', 'exclude files', 'x', 'file');
$options->args = array('--exclude', 'foo', 'bang');
$options->parseOptions();
$this->assertEquals('foo', $options->getOpt('exclude'));
$this->assertEquals(array('bang'), $options->args);
$this->assertFalse($options->getOpt('nothing'));
}
function test_simplelong2() {
$options = new DokuCLI_Options();
$options->registerOption('exclude', 'exclude files', 'x', 'file');
$options->args = array('--exclude=foo', 'bang');
$options->parseOptions();
$this->assertEquals('foo', $options->getOpt('exclude'));
$this->assertEquals(array('bang'), $options->args);
$this->assertFalse($options->getOpt('nothing'));
}
function test_complex() {
$options = new DokuCLI_Options();
$options->registerOption('plugins', 'run on plugins only', 'p');
$options->registerCommand('status', 'display status info');
$options->registerOption('long', 'display long lines', 'l', false, 'status');
$options->args = array('-p', 'status', '--long', 'foo');
$options->parseOptions();
$this->assertEquals('status', $options->getCmd());
$this->assertTrue($options->getOpt('plugins'));
$this->assertTrue($options->getOpt('long'));
$this->assertEquals(array('foo'), $options->args);
}
}

View File

@ -38,6 +38,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['writable'] = true;
$info['editable'] = true;
$info['lastmod'] = false;
$info['currentrev'] = false;
$info['meta'] = array();
$info['ip'] = null;
$info['user'] = null;
@ -77,6 +78,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['filepath'] = $filename;
$info['exists'] = true;
$info['lastmod'] = $rev;
$info['currentrev'] = $rev;
$info['meta'] = p_get_metadata($ID);
$this->assertEquals($info, pageinfo());
@ -101,6 +103,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['filepath'] = $filename;
$info['exists'] = true;
$info['lastmod'] = $rev;
$info['currentrev'] = $rev;
$info['meta'] = p_get_metadata($ID);
$info['rev'] = '';
@ -131,6 +134,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['namespace'] = 'wiki';
$info['meta'] = p_get_metadata($ID);
$info['rev'] = $REV;
$info['currentrev'] = $rev;
$info['filepath'] = str_replace('pages','attic',substr($filename,0,-3).$REV.'.txt.gz');
$this->assertEquals($info, pageinfo());
@ -153,6 +157,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['namespace'] = 'wiki';
$info['exists'] = true;
$info['lastmod'] = $rev;
$info['currentrev'] = $rev;
$info['meta'] = p_get_metadata($ID);
$info['filepath'] = $filename;
@ -197,6 +202,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['filepath'] = $filename;
$info['exists'] = true;
$info['lastmod'] = $rev;
$info['currentrev'] = $rev;
$info['meta'] = p_get_metadata($ID); // need $INFO set correctly for addLogEntry()
global $INFO;
@ -226,6 +232,7 @@ class common_pageinfo_test extends DokuWikiTest {
touch($filename,$now);
$info['lastmod'] = $now;
$info['currentrev'] = $now;
$info['meta']['last_change'] = false;
$info['ip'] = null;
$info['user'] = null;
@ -251,6 +258,7 @@ class common_pageinfo_test extends DokuWikiTest {
$info['filepath'] = $filename;
$info['exists'] = true;
$info['lastmod'] = $rev;
$info['currentrev'] = $rev;
$info['meta'] = p_get_metadata($ID);
// setup a draft, make it more recent than the current page

View File

@ -0,0 +1,29 @@
<?php
class common_stripsourcemaps_test extends DokuWikiTest {
function test_all() {
$text = <<<EOL
//@ sourceMappingURL=/foo/bar/xxx.map
//# sourceMappingURL=/foo/bar/xxx.map
/*@ sourceMappingURL=/foo/bar/xxx.map */
/*# sourceMappingURL=/foo/bar/xxx.map */
bang
EOL;
$expect = <<<EOL
//
//
/**/
/**/
bang
EOL;
stripsourcemaps($text);
$this->assertEquals($expect, $text);
}
}

View File

@ -1,15 +1,22 @@
<?php
require_once (__DIR__ . '/httpclient_mock.php');
class httpclient_http_test extends DokuWikiTest {
protected $server = 'http://httpbin.org';
/**
* @group internet
*/
function test_simpleget(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/get?foo=bar');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('args',$resp);
@ -20,9 +27,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_dget(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->dget($this->server.'/get',array('foo'=>'bar'));
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('args',$resp);
@ -33,9 +44,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_gzip(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/gzip');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('gzipped',$resp);
@ -46,9 +61,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_simplepost(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->post($this->server.'/post',array('foo'=>'bar'));
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('form',$resp);
@ -59,9 +78,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_redirect(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/redirect/3');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('url',$resp);
@ -72,9 +95,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_relredirect(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/relative-redirect/3');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('url',$resp);
@ -85,9 +112,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_redirectfail(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/redirect/5');
$this->assertTrue($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertEquals('Maximum number of redirects exceeded',$http->error);
}
@ -95,11 +126,19 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_cookies(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$http->get($this->server.'/cookies/set/foo/bar');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertEquals(array('foo' => 'bar'), $http->cookies);
$data = $http->get($this->server.'/cookies');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('cookies',$resp);
@ -110,9 +149,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_teapot(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/status/418');
$this->assertTrue($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertEquals(418,$http->status);
}
@ -120,18 +163,26 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_maxbody(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$http->max_bodysize = 250;
// this should abort completely
$data = $http->get($this->server.'/stream/30');
$this->assertTrue($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
// this should read just the needed bytes
$http->max_bodysize_abort = false;
$http->keep_alive = false;
$data = $http->get($this->server.'/stream/30');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
/* should read no more than max_bodysize+1 */
$this->assertLessThanOrEqual(251,strlen($data));
}
@ -140,24 +191,36 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_maxbodyok(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$http->max_bodysize = 500*1024;
$data = $http->get($this->server.'/stream/5');
$this->assertTrue($data !== false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data !== false, 'HTTP response '.$http->error);
$http->max_bodysize_abort = false;
$data = $http->get($this->server.'/stream/5');
$this->assertTrue($data !== false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data !== false, 'HTTP response '.$http->error);
}
/**
* @group internet
*/
function test_basicauth(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$http->user = 'user';
$http->pass = 'pass';
$data = $http->get($this->server.'/basic-auth/user/pass');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertEquals(array('authenticated'=>true,'user'=>'user'), $resp);
@ -167,11 +230,15 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_basicauthfail(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$http->user = 'user';
$http->pass = 'invalid';
$data = $http->get($this->server.'/basic-auth/user/pass');
$this->assertTrue($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertEquals(401,$http->status);
}
@ -179,10 +246,10 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_timeout(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$http->timeout = 5;
$data = $http->get($this->server.'/delay/10');
$this->assertTrue($data === false, 'HTTP response');
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertEquals(-100,$http->status);
}
@ -190,9 +257,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_headers(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get($this->server.'/response-headers?baz=&foo=bar');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('baz',$http->resp_headers);
@ -204,9 +275,13 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_chunked(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get('http://whoopdedo.org/cgi-bin/chunked/2550');
$this->assertFalse($data === false, 'HTTP response');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertEquals(2550,strlen($data));
}
@ -216,13 +291,17 @@ class httpclient_http_test extends DokuWikiTest {
* @group internet
*/
function test_wikimatrix(){
$http = new HTTPClient();
$http = new HTTPMockClient();
$data = $http->get('http://www.wikimatrix.org/cfeed/dokuwiki/-/-');
$this->assertTrue($data !== false, $http->error);
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data !== false, 'HTTP response '.$http->error);
}
function test_postencode(){
$http = new HTTPClient();
$http = new HTTPMockClient();
// check simple data

View File

@ -1,5 +1,7 @@
<?php
require_once (__DIR__ . '/httpclient_mock.php');
class httpclient_http_proxy_test extends DokuWikiTest {
protected $url = 'http://test.dokuwiki.org/README';
@ -7,7 +9,7 @@ class httpclient_http_proxy_test extends DokuWikiTest {
* @group internet
*/
function test_simpleget(){
$http = new HTTPClient();
$http = new HTTPMockClient();
// proxy provided by Andrwe Lord Weber <dokuwiki@andrwe.org>
$http->proxy_host = 'proxy.andrwe.org';
$http->proxy_port = 8080;
@ -16,5 +18,4 @@ class httpclient_http_proxy_test extends DokuWikiTest {
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertTrue(strpos($data,'DokuWiki') !== false, 'response content');
}
}

View File

@ -12,4 +12,19 @@ class httpclient_https_proxy_test extends httpclient_http_proxy_test {
}
parent::setUp();
}
/**
* @group internet
*/
function test_connectfail(){
$http = new HTTPMockClient();
// proxy provided by Andrwe Lord Weber <dokuwiki@andrwe.org>
$http->proxy_host = 'proxy.andrwe.org';
$http->proxy_port = 8080;
// the proxy accepts connections to dokuwiki.org only - the connect call should fail
$data = $http->get('https://www.google.com');
$this->assertFalse($data);
$this->assertEquals(-150, $http->status);
}
}

View File

@ -0,0 +1,46 @@
<?php
/**
* Class HTTPMockClient
*
* Does not really mock the client, it still does real connections but will retry failed connections
* to work around shaky connectivity.
*/
class HTTPMockClient extends HTTPClient {
protected $tries;
/**
* Sets shorter timeout
*/
function __construct() {
parent::__construct();
$this->timeout = 8; // slightly faster timeouts
}
/**
* Returns true if the connection timed out
*
* @return bool
*/
function noconnection() {
return ($this->tries === 0);
}
/**
* Retries sending the request multiple times
*
* @param string $url
* @param string $data
* @param string $method
* @return bool
*/
function sendRequest($url, $data = '', $method = 'GET') {
$this->tries = 2; // configures the number of retries
$return = false;
while($this->tries) {
$return = parent::sendRequest($url, $data, $method);
if($this->status != -100) break;
$this->tries--;
}
return $return;
}
}

View File

@ -214,6 +214,25 @@ class input_test extends DokuWikiTest {
$this->assertEquals('bla',$test);
}
public function test_valid(){
$_REQUEST = $this->data;
$_POST = $this->data;
$_GET = $this->data;
$INPUT = new Input();
$valids = array(17, 'foo');
$this->assertSame(null, $INPUT->valid('nope', $valids));
$this->assertSame('bang', $INPUT->valid('nope', $valids, 'bang'));
$this->assertSame(17, $INPUT->valid('int', $valids));
$this->assertSame('foo', $INPUT->valid('string', $valids));
$this->assertSame(null, $INPUT->valid('array', $valids));
$valids = array(true);
$this->assertSame(true, $INPUT->valid('string', $valids));
$this->assertSame(true, $INPUT->valid('one', $valids));
$this->assertSame(null, $INPUT->valid('zero', $valids));
}
public function test_extract(){
$_REQUEST = $this->data;
$_POST = $this->data;

View File

@ -4,7 +4,7 @@ class io_rmdir_test extends DokuWikiTest {
function test_nopes(){
// set up test dir
$dir = io_mktmpdir();
$dir = realpath(io_mktmpdir());
$top = dirname($dir);
$this->assertTrue($dir !== false);
$this->assertTrue(is_dir($dir));

View File

@ -191,7 +191,10 @@ class mailer_test extends DokuWikiTest {
// ask message lint if it is okay
$html = new HTTPClient();
$results = $html->post('http://tools.ietf.org/tools/msglint/msglint', array('msg'=>$msg));
$this->assertTrue($results !== false);
if($results === false) {
$this->markTestSkipped('no response from validator');
return;
}
// parse the result lines
$lines = explode("\n", $results);

View File

@ -3,7 +3,7 @@
require_once DOKU_INC . 'inc/parser/parser.php';
require_once DOKU_INC . 'inc/parser/handler.php';
abstract class TestOfDoku_Parser extends PHPUnit_Framework_TestCase {
abstract class TestOfDoku_Parser extends DokuWikiTest {
var $P;
var $H;

View File

@ -10,8 +10,9 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
}
function testSingleQuoteOpening() {
$raw = "Foo 'hello Bar";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("Foo 'hello Bar");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -23,12 +24,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testSingleQuoteOpeningSpecial() {
$raw = "Foo said:'hello Bar";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("Foo said:'hello Bar");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -40,12 +42,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testSingleQuoteClosing() {
$raw = "Foo hello' Bar";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("Foo hello' Bar");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -57,12 +60,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testSingleQuoteClosingSpecial() {
$raw = "Foo hello') Bar";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("Foo hello') Bar");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -74,12 +78,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testSingleQuotes() {
$raw = "Foo 'hello' Bar";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("Foo 'hello' Bar");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -93,12 +98,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testApostrophe() {
$raw = "hey it's fine weather today";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("hey it's fine weather today");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -110,13 +116,14 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testSingleQuotesSpecial() {
$raw = "Foo ('hello') Bar";
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse("Foo ('hello') Bar");
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -130,12 +137,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuoteOpening() {
$raw = 'Foo "hello Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('Foo "hello Bar');
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -147,12 +155,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuoteOpeningSpecial() {
$raw = 'Foo said:"hello Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('Foo said:"hello Bar');
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -164,12 +173,14 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuoteClosing() {
$raw = 'Foo hello" Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('Foo hello" Bar');
$this->H->status['doublequote'] = 1;
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -181,12 +192,14 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuoteClosingSpecial() {
$raw = 'Foo hello") Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('Foo hello") Bar');
$this->H->status['doublequote'] = 1;
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -198,12 +211,31 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuoteClosingSpecial2() {
$raw = 'Foo hello") Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->H->status['doublequote'] = 0;
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo hello')),
array('doublequoteopening',array()),
array('cdata',array(') Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuotes() {
$raw = 'Foo "hello" Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('Foo "hello" Bar');
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -217,12 +249,13 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testDoubleQuotesSpecial() {
$raw = 'Foo ("hello") Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('Foo ("hello") Bar');
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -236,12 +269,54 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls, 'wikitext => '.$raw);
}
function testAllQuotes() {
function testDoubleQuotesEnclosingBrackets() {
$raw = 'Foo "{hello}" Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse('There was written "He thought \'It\'s a man\'s world\'".');
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('doublequoteopening',array()),
array('cdata',array('{hello}')),
array('doublequoteclosing',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls,'wikitext - '.$raw);
}
function testDoubleQuotesEnclosingLink() {
$raw = 'Foo "[[www.domain.com]]" Bar';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('doublequoteopening',array()),
array('cdata',array('[[www.domain.com]]')),
array('doublequoteclosing',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls,'wikitext => '.$raw);
}
function testAllQuotes() {
$raw = 'There was written "He thought \'It\'s a man\'s world\'".';
$this->P->addMode('quotes',new Doku_Parser_Mode_Quotes());
$this->P->parse($raw);
$calls = array (
array('document_start',array()),
@ -262,7 +337,7 @@ class TestOfDoku_Parser_Quotes extends TestOfDoku_Parser {
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls,'wikitext => '.$raw);
}
}

View File

@ -44,7 +44,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTableWinEOL() {
@ -84,7 +84,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testEmptyTable() {
@ -109,7 +109,7 @@ def');
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTableHeaders() {
@ -143,7 +143,152 @@ def');
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTableHead() {
$this->P->addMode('table',new Doku_Parser_Mode_Table());
$this->P->parse('
abc
^ X ^ Y ^ Z ^
| x | y | z |
def');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n\nabc")),
array('p_close',array()),
array('table_open',array(3, 2, 6)),
array('tablethead_open',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Y ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablethead_close',array()),
array('tablerow_open',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' x ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' y ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' z ')),
array('tablecell_close',array()),
array('tablerow_close',array()),
array('table_close',array(33)),
array('p_open',array()),
array('cdata',array('def')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTableHeadOneRowTable() {
$this->P->addMode('table',new Doku_Parser_Mode_Table());
$this->P->parse('
abc
^ X ^ Y ^ Z ^
def');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n\nabc")),
array('p_close',array()),
array('table_open',array(3, 1, 6)),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Y ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('table_close',array(19)),
array('p_open',array()),
array('cdata',array('def')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTableHeadMultiline() {
$this->P->addMode('table',new Doku_Parser_Mode_Table());
$this->P->parse('
abc
^ X1 ^ Y1 ^ Z1 ^
^ X2 ^ Y2 ^ Z2 ^
| A | B | C |
def');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n\nabc")),
array('p_close',array()),
array('table_open',array(3, 3, 6)),
array('tablethead_open',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X1 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Y1 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z1 ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X2 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Y2 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z2 ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablethead_close',array()),
array('tablerow_open',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' A ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' B ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' C ')),
array('tablecell_close',array()),
array('tablerow_close',array()),
array('table_close',array(53)),
array('p_open',array()),
array('cdata',array('def')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
@ -178,7 +323,7 @@ def');
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testCellSpan() {
@ -220,7 +365,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testCellRowSpan() {
@ -268,7 +413,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testCellRowSpanFirstRow() {
@ -326,9 +471,134 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testRowSpanTableHead() {
$this->P->addMode('table',new Doku_Parser_Mode_Table());
$this->P->parse('
abc
^ X1 ^ Y1 ^ Z1 ^
^ X2 ^ ::: ^ Z2 ^
| A3 | B3 | C3 |
def');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n\nabc")),
array('p_close',array()),
array('table_open',array(3, 3, 6)),
array('tablethead_open',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X1 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,2)),
array('cdata',array(' Y1 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z1 ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X2 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z2 ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablethead_close',array()),
array('tablerow_open',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' A3 ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' B3 ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' C3 ')),
array('tablecell_close',array()),
array('tablerow_close',array()),
array('table_close',array(57)),
array('p_open',array()),
array('cdata',array('def')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testRowSpanAcrossTableHeadBoundary() {
$this->P->addMode('table',new Doku_Parser_Mode_Table());
$this->P->parse('
abc
^ X1 ^ Y1 ^ Z1 ^
^ X2 ^ ::: ^ Z2 ^
| A3 | ::: | C3 |
| A4 | ::: | C4 |
def');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n\nabc")),
array('p_close',array()),
array('table_open',array(3, 4, 6)),
array('tablethead_open',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X1 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,2)),
array('cdata',array(' Y1 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z1 ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablerow_open',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' X2 ')),
array('tableheader_close',array()),
array('tableheader_open',array(1,NULL,1)),
array('cdata',array(' Z2 ')),
array('tableheader_close',array()),
array('tablerow_close',array()),
array('tablethead_close',array()),
array('tablerow_open',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' A3 ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,2)),
array('cdata',array('')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' C3 ')),
array('tablecell_close',array()),
array('tablerow_close',array()),
array('tablerow_open',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' A4 ')),
array('tablecell_close',array()),
array('tablecell_open',array(1,NULL,1)),
array('cdata',array(' C4 ')),
array('tablecell_close',array()),
array('tablerow_close',array()),
array('table_close',array(76)),
array('p_open',array()),
array('cdata',array('def')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testCellAlignmentFormatting() {
$this->P->addMode('table',new Doku_Parser_Mode_Table());
$this->P->addMode('strong',new Doku_Parser_Mode_Formatting('strong'));
@ -365,7 +635,7 @@ def');
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
@ -411,7 +681,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
// This is really a failing test - formatting able to spread across cols
@ -466,7 +736,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
// This is really a failing test - unformatted able to spread across cols
@ -517,7 +787,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTableLinebreak() {
@ -565,7 +835,7 @@ def');
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
// This is really a failing test - footnote able to spread across cols
@ -624,7 +894,7 @@ def');
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
$this->assertEquals($calls,array_map('stripbyteindex',$this->H->calls));
}
function testTable_FS1833() {
@ -646,4 +916,3 @@ def');
}
}

View File

@ -0,0 +1,53 @@
<?php
require_once DOKU_INC . 'inc/parser/renderer.php';
/**
* Tests for Doku_Renderer::_resolveInterWiki()
*/
class Test_resolveInterwiki extends DokuWikiTest {
function testDefaults() {
$Renderer = new Doku_Renderer();
$Renderer->interwiki = getInterwiki();
$Renderer->interwiki['scheme'] = '{SCHEME}://example.com';
$Renderer->interwiki['withslash'] = '/test';
$Renderer->interwiki['onlytext'] = ':onlytext{NAME}'; //with {URL} double urlencoded
$Renderer->interwiki['withquery'] = ':anyns:{NAME}?do=edit';
$tests = array(
// shortcut, reference and expected
array('wp', 'foo @+%/#txt', 'http://en.wikipedia.org/wiki/foo @+%/#txt'),
array('amazon', 'foo @+%/#txt', 'http://www.amazon.com/exec/obidos/ASIN/foo%20%40%2B%25%2F/splitbrain-20/#txt'),
array('doku', 'foo @+%/#txt', 'http://www.dokuwiki.org/foo%20%40%2B%25%2F#txt'),
array('coral', 'http://example.com:83/path/naar/?query=foo%20%40%2B%25%2F', 'http://example.com.83.nyud.net:8090/path/naar/?query=foo%20%40%2B%25%2F'),
array('scheme', 'ftp://foo @+%/#txt', 'ftp://example.com#txt'),
//relative url
array('withslash', 'foo @+%/#txt', '/testfoo%20%40%2B%25%2F#txt'),
array('skype', 'foo @+%/#txt', 'skype:foo @+%/#txt'),
//dokuwiki id's
array('onlytext', 'foo @+%#txt', DOKU_BASE.'doku.php?id=onlytextfoo#txt'),
array('user', 'foo @+%#txt', DOKU_BASE.'doku.php?id=user:foo#txt'),
array('withquery', 'foo @+%#txt', DOKU_BASE.'doku.php?id=anyns:foo&amp;do=edit#txt')
);
foreach($tests as $test) {
$url = $Renderer->_resolveInterWiki($test[0], $test[1]);
$this->assertEquals($test[2], $url);
}
}
function testNonexisting() {
$Renderer = new Doku_Renderer();
$Renderer->interwiki = getInterwiki();
$shortcut = 'nonexisting';
$reference = 'foo @+%/';
$url = $Renderer->_resolveInterWiki($shortcut, $reference);
$expected = 'http://www.google.com/search?q=foo%20%40%2B%25%2F&amp;btnI=lucky';
$this->assertEquals($expected, $url);
}
}

View File

@ -0,0 +1,79 @@
<?php
class parserutils_get_renderer_test extends DokuWikiTest {
private $plugin_controller;
// test default behaviour / usual settings
function test_p_get_renderer_normal() {
global $conf;
$old_conf = $conf;
$conf['renderer_xhtml'] = 'xhtml';
$this->assertInstanceOf('Doku_Renderer_xhtml', p_get_renderer('xhtml'));
$conf = $old_conf;
}
// test get a renderer plugin
function test_p_get_renderer_plugin() {
global $conf;
global $plugin_controller;
$old_conf = $conf;
$conf['renderer_xhtml'] = 'get_renderer_test';
$this->plugin_controller = $plugin_controller;
$plugin_controller = $this;
$this->assertInstanceOf('renderer_plugin_test', p_get_renderer('xhtml'));
$conf = $old_conf;
$plugin_controller = $this->plugin_controller;
}
// test fallback succeeds
function test_p_get_renderer_fallback() {
global $conf;
$old_conf = $conf;
$conf['renderer_xhtml'] = 'badvalue';
$this->assertInstanceOf('Doku_Renderer_xhtml', p_get_renderer('xhtml'));
$conf = $old_conf;
}
// test fallback fails
function test_p_get_renderer_fallback_fail() {
global $conf;
$old_conf = $conf;
$conf['renderer_junk'] = 'badvalue';
$this->assertNull(p_get_renderer('junk'));
$conf = $old_conf;
}
// wrapper function for the fake plugin controller, return $this for the fake syntax of this test
function load($type,$name,$new=false,$disabled=false){
if ($name == 'get_renderer_test') {
return new renderer_plugin_test();
} else {
return $this->plugin_controller->load($type, $name, $new, $disabled);
}
}
}
require_once DOKU_INC . 'inc/parser/xhtml.php';
class renderer_plugin_test extends Doku_Renderer_xhtml {
function canRender($format) {
return ($format=='xhtml');
}
}
// vim:ts=4:sw=4:et:

View File

@ -1,6 +1,38 @@
<?php
class Tar_TestCase extends DokuWikiTest {
/**
* file extensions that several tests use
*/
protected $extensions = array('tar');
public function setUp() {
parent::setUp();
if (extension_loaded('zlib')) {
$this->extensions[] = 'tgz';
}
if (extension_loaded('bz2')) {
$this->extensions[] = 'tbz';
}
}
/*
* dependency for tests needing zlib extension to pass
*/
public function test_ext_zlib() {
if (!extension_loaded('zlib')) {
$this->markTestSkipped('skipping all zlib tests. Need zlib extension');
}
}
/*
* dependency for tests needing zlib extension to pass
*/
public function test_ext_bz2() {
if (!extension_loaded('bz2')) {
$this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension');
}
}
/**
* simple test that checks that the given filenames and contents can be grepped from
@ -58,8 +90,6 @@ class Tar_TestCase extends DokuWikiTest {
$tar->addData('another/testdata3.txt', 'testcontent3');
$tar->close();
copy ($tmp, '/tmp/test.tar');
$this->assertTrue(filesize($tmp) > 30); //arbitrary non-zero number
$data = file_get_contents($tmp);
@ -89,7 +119,7 @@ copy ($tmp, '/tmp/test.tar');
public function test_tarcontent() {
$dir = dirname(__FILE__).'/tar';
foreach(array('tar', 'tgz', 'tbz') as $ext) {
foreach($this->extensions as $ext) {
$tar = new Tar();
$file = "$dir/test.$ext";
@ -112,7 +142,7 @@ copy ($tmp, '/tmp/test.tar');
$dir = dirname(__FILE__).'/tar';
$out = sys_get_temp_dir().'/dwtartest'.md5(time());
foreach(array('tar', 'tgz', 'tbz') as $ext) {
foreach($this->extensions as $ext) {
$tar = new Tar();
$file = "$dir/test.$ext";
@ -138,7 +168,7 @@ copy ($tmp, '/tmp/test.tar');
$dir = dirname(__FILE__).'/tar';
$out = sys_get_temp_dir().'/dwtartest'.md5(time());
foreach(array('tar', 'tgz', 'tbz') as $ext) {
foreach($this->extensions as $ext) {
$tar = new Tar();
$file = "$dir/test.$ext";
@ -164,7 +194,7 @@ copy ($tmp, '/tmp/test.tar');
$dir = dirname(__FILE__).'/tar';
$out = sys_get_temp_dir().'/dwtartest'.md5(time());
foreach(array('tar', 'tgz', 'tbz') as $ext) {
foreach($this->extensions as $ext) {
$tar = new Tar();
$file = "$dir/test.$ext";
@ -190,7 +220,7 @@ copy ($tmp, '/tmp/test.tar');
$dir = dirname(__FILE__).'/tar';
$out = sys_get_temp_dir().'/dwtartest'.md5(time());
foreach(array('tar', 'tgz', 'tbz') as $ext) {
foreach($this->extensions as $ext) {
$tar = new Tar();
$file = "$dir/test.$ext";
@ -215,7 +245,7 @@ copy ($tmp, '/tmp/test.tar');
$dir = dirname(__FILE__).'/tar';
$out = sys_get_temp_dir().'/dwtartest'.md5(time());
foreach(array('tar', 'tgz', 'tbz') as $ext) {
foreach($this->extensions as $ext) {
$tar = new Tar();
$file = "$dir/test.$ext";
@ -249,6 +279,9 @@ copy ($tmp, '/tmp/test.tar');
$this->assertEquals(Tar::COMPRESS_BZIP, $tar->filetype('foo.tar.bz2'));
}
/**
* @depends test_ext_zlib
*/
public function test_longpathextract() {
$dir = dirname(__FILE__).'/tar';
$out = sys_get_temp_dir().'/dwtartest'.md5(time());
@ -338,6 +371,7 @@ copy ($tmp, '/tmp/test.tar');
/**
* Extract a tarbomomb
* @depends test_ext_zlib
*/
public function test_tarbomb() {
$dir = dirname(__FILE__).'/tar';

View File

@ -5,7 +5,7 @@ if(!defined('UTF8_NOMBSTRING')) define('UTF8_NOMBSTRING',1);
/**
* @group slow
*/
class utf8_romanize_test extends PHPUnit_Framework_TestCase {
class utf8_romanize_test extends DokuWikiTest {
/**
* Check Japanese romanization

View File

@ -0,0 +1,23 @@
<?php
// use no mbstring help here
if(!defined('UTF8_NOMBSTRING')) define('UTF8_NOMBSTRING',1);
class utf8_strtolower_test extends DokuWikiTest {
function test_givens(){
$data = array(
'Αρχιτεκτονική Μελέτη' => 'αρχιτεκτονική μελέτη', // FS#2173
);
foreach($data as $input => $expected) {
$this->assertEquals($expected, utf8_strtolower($input));
}
// just make sure our data was correct
if(function_exists('mb_strtolower')) {
foreach($data as $input => $expected) {
$this->assertEquals($expected, mb_strtolower($input, 'utf-8'));
}
}
}
}

View File

@ -10,41 +10,70 @@ class css_css_compress_test extends DokuWikiTest {
* line *test*
* check
*/';
$this->assertEquals(css_compress($text), '');
$this->assertEquals('', css_compress($text));
}
function test_mlcom2(){
$text = '#comment/* */ {
color: lime;
}';
$this->assertEquals(css_compress($text), '#comment/* */{color:lime;}');
$this->assertEquals('#comment/* */{color:lime;}', css_compress($text));
}
function test_slcom1(){
$text = '// this is a comment';
$this->assertEquals(css_compress($text), '');
$this->assertEquals('', css_compress($text));
}
function test_slcom2(){
$text = '#foo {
color: lime; // another comment
}';
$this->assertEquals(css_compress($text), '#foo{color:lime;}');
$this->assertEquals('#foo{color:lime;}', css_compress($text));
}
function test_slcom3(){
$text = '#foo {
background-image: url(http://foo.bar/baz.jpg);
background-image: url(http://foo.bar/baz.jpg); // this is a comment
}';
$this->assertEquals(css_compress($text), '#foo{background-image:url(http://foo.bar/baz.jpg);}');
$this->assertEquals('#foo{background-image:url(http://foo.bar/baz.jpg);}', css_compress($text));
}
function test_slcom4(){
$text = '#foo {
background-image: url(http://foo.bar/baz.jpg); background-image: url(http://foo.bar/baz.jpg); // this is a comment
}';
$this->assertEquals('#foo{background-image:url(http://foo.bar/baz.jpg);background-image:url(http://foo.bar/baz.jpg);}', css_compress($text));
}
function test_slcom5(){
$text = '#foo {
background-image: url(http://foo.bar/baz.jpg); // background-image: url(http://foo.bar/baz.jpg); this is all commented
}';
$this->assertEquals('#foo{background-image:url(http://foo.bar/baz.jpg);}', css_compress($text));
}
function test_slcom6(){
$text = '#foo {
background-image: url(//foo.bar/baz.jpg); // background-image: url(http://foo.bar/baz.jpg); this is all commented
}';
$this->assertEquals('#foo{background-image:url(//foo.bar/baz.jpg);}', css_compress($text));
}
function test_slcom7(){
$text = '#foo a[href ^="https://"], #foo a[href ^=\'https://\'] {
background-image: url(//foo.bar/baz.jpg); // background-image: url(http://foo.bar/baz.jpg); this is \'all\' "commented"
}';
$this->assertEquals('#foo a[href ^="https://"],#foo a[href ^=\'https://\']{background-image:url(//foo.bar/baz.jpg);}', css_compress($text));
}
function test_hack(){
$text = '/* Mac IE will not see this and continue with inline-block */
/* \\*/
display: inline;
/* */';
$this->assertEquals(css_compress($text), '/* \\*/display:inline;/* */');
$this->assertEquals('/* \\*/display:inline;/* */', css_compress($text));
}
function test_hack2(){
@ -54,12 +83,12 @@ class css_css_compress_test extends DokuWikiTest {
height: 450px;
}
/**/';
$this->assertEquals(css_compress($text), '/*\\*/* html .page{height:450px;}/**/');
$this->assertEquals('/*\\*/* html .page{height:450px;}/**/', css_compress($text));
}
function test_nl1(){
$text = "a{left:20px;\ntop:20px}";
$this->assertEquals(css_compress($text), 'a{left:20px;top:20px}');
$this->assertEquals('a{left:20px;top:20px}', css_compress($text));
}
function test_shortening() {
@ -102,6 +131,13 @@ class css_css_compress_test extends DokuWikiTest {
$this->assertEquals($expected, $input);
}
function test_data() {
$input = 'list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);';
$expect = 'list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);';
$this->assertEquals($expect, css_compress($input));
}
}
//Setup VIM: ex: et ts=4 :

View File

@ -33,7 +33,7 @@ class InttestsBasicTest extends DokuWikiTest {
$response = $request->execute();
$this->assertTrue(
strpos($response->getContent(), 'DokuWiki') >= 0,
strpos($response->getContent(), 'DokuWiki') !== false,
'DokuWiki was not a word in the output'
);
}
@ -60,7 +60,7 @@ class InttestsBasicTest extends DokuWikiTest {
$this->assertEquals('wiki:dokuwiki', $request->getPost('id'));
// output check
$this->assertTrue(strpos($response->getContent(), 'Andreas Gohr') >= 0);
$this->assertTrue(strpos($response->getContent(), 'Andreas Gohr') !== false);
}
function testPostGet() {
@ -84,7 +84,7 @@ class InttestsBasicTest extends DokuWikiTest {
$this->assertEquals('wiki:dokuwiki', $request->getGet('id'));
// output check
$this->assertTrue(strpos($response->getContent(), 'Andreas Gohr') >= 0);
$this->assertTrue(strpos($response->getContent(), 'Andreas Gohr') !== false);
}
function testGet() {
@ -116,7 +116,7 @@ class InttestsBasicTest extends DokuWikiTest {
$this->assertEquals('bar', $request->getGet('test'));
// output check
$this->assertTrue(strpos($response->getContent(), 'Andreas Gohr') >= 0);
$this->assertTrue(strpos($response->getContent(), 'Andreas Gohr') !== false);
}
function testScripts() {
@ -168,5 +168,13 @@ class InttestsBasicTest extends DokuWikiTest {
$response = new TestResponse('',array_slice($this->some_headers,0,-2)); // slice off the last two headers to leave no status header
$this->assertNull($response->getStatusCode());
}
function testINPUT() {
$request = new TestRequest();
$response = $request->get(array('id' => 'mailinglist'), '/doku.php');
// output check
$this->assertTrue(strpos($response->getContent(), 'Netiquette') !== false);
}
}

View File

@ -1,378 +1,317 @@
#!/usr/bin/php
<?php
#------------------------------------------------------------------------------
if ('cli' != php_sapi_name()) die();
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once DOKU_INC.'inc/init.php';
require_once DOKU_INC.'inc/common.php';
require_once DOKU_INC.'inc/cliopts.php';
/**
* Checkout and commit pages from the command line while maintaining the history
*/
class PageCLI extends DokuCLI {
#------------------------------------------------------------------------------
function usage($action) {
switch ( $action ) {
case 'checkout':
print "Usage: dwpage.php [opts] checkout <wiki:page> [working_file]
protected $force = false;
protected $username = '';
Checks out a file from the repository, using the wiki id and obtaining
a lock for the page.
If a working_file is specified, this is where the page is copied to.
Otherwise defaults to the same as the wiki page in the current
working directory.
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
/* global */
$options->registerOption(
'force',
'force obtaining a lock for the page (generally bad idea)',
'f'
);
$options->registerOption(
'user',
'work as this user. defaults to current CLI user',
'u'
);
$options->setHelp(
'Utility to help command line Dokuwiki page editing, allow '.
'pages to be checked out for editing then committed after changes'
);
EXAMPLE
$ ./dwpage.php checkout wiki:syntax ./new_syntax.txt
/* checkout command */
$options->registerCommand(
'checkout',
'Checks out a file from the repository, using the wiki id and obtaining '.
'a lock for the page. '."\n".
'If a working_file is specified, this is where the page is copied to. '.
'Otherwise defaults to the same as the wiki page in the current '.
'working directory.'
);
$options->registerArgument(
'wikipage',
'The wiki page to checkout',
true,
'checkout'
);
$options->registerArgument(
'workingfile',
'How to name the local checkout',
false,
'checkout'
);
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
";
break;
case 'commit':
print "Usage: dwpage.php [opts] -m \"Msg\" commit <working_file> <wiki:page>
/* commit command */
$options->registerCommand(
'commit',
'Checks in the working_file into the repository using the specified '.
'wiki id, archiving the previous version.'
);
$options->registerArgument(
'workingfile',
'The local file to commit',
true,
'commit'
);
$options->registerArgument(
'wikipage',
'The wiki page to create or update',
true,
'commit'
);
$options->registerOption(
'message',
'Summary describing the change (required)',
'm',
'summary',
'commit'
);
$options->registerOption(
'trivial',
'minor change',
't',
false,
'commit'
);
Checks in the working_file into the repository using the specified
wiki id, archiving the previous version.
/* lock command */
$options->registerCommand(
'lock',
'Obtains or updates a lock for a wiki page'
);
$options->registerArgument(
'wikipage',
'The wiki page to lock',
true,
'lock'
);
EXAMPLE
$ ./dwpage.php -m \"Some message\" commit ./new_syntax.txt wiki:syntax
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
-t, trivial: minor change
-m (required): Summary message describing the change
";
break;
case 'lock':
print "Usage: dwpage.php [opts] lock <wiki:page>
Obtains or updates a lock for a wiki page
EXAMPLE
$ ./dwpage.php lock wiki:syntax
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
";
break;
case 'unlock':
print "Usage: dwpage.php [opts] unlock <wiki:page>
Removes a lock for a wiki page.
EXAMPLE
$ ./dwpage.php unlock wiki:syntax
OPTIONS
-h, --help=<action>: get help
-f: force obtaining a lock for the page (generally bad idea)
";
break;
default:
print "Usage: dwpage.php [opts] <action>
Utility to help command line Dokuwiki page editing, allow
pages to be checked out for editing then committed after changes
Normal operation would be;
ACTIONS
checkout: see $ dwpage.php --help=checkout
commit: see $ dwpage.php --help=commit
lock: see $ dwpage.php --help=lock
OPTIONS
-h, --help=<action>: get help
e.g. $ ./dwpage.php -hcommit
e.g. $ ./dwpage.php --help=commit
";
break;
/* unlock command */
$options->registerCommand(
'unlock',
'Removes a lock for a wiki page.'
);
$options->registerArgument(
'wikipage',
'The wiki page to unlock',
true,
'unlock'
);
}
}
#------------------------------------------------------------------------------
function getUser() {
$user = getenv('USER');
if (empty ($user)) {
$user = getenv('USERNAME');
} else {
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
$this->force = $options->getOpt('force', false);
$this->username = $options->getOpt('user', $this->getUser());
$command = $options->getCmd();
switch($command) {
case 'checkout':
$wiki_id = array_shift($options->args);
$localfile = array_shift($options->args);
$this->commandCheckout($wiki_id, $localfile);
break;
case 'commit':
$localfile = array_shift($options->args);
$wiki_id = array_shift($options->args);
$this->commandCommit(
$localfile,
$wiki_id,
$options->getOpt('message', ''),
$options->getOpt('trivial', false)
);
break;
case 'lock':
$wiki_id = array_shift($options->args);
$this->obtainLock($wiki_id);
$this->success("$wiki_id locked");
break;
case 'unlock':
$wiki_id = array_shift($options->args);
$this->clearLock($wiki_id);
$this->success("$wiki_id unlocked");
break;
default:
echo $options->help();
}
}
/**
* Check out a file
*
* @param string $wiki_id
* @param string $localfile
*/
protected function commandCheckout($wiki_id, $localfile) {
global $conf;
$wiki_id = cleanID($wiki_id);
$wiki_fn = wikiFN($wiki_id);
if(!file_exists($wiki_fn)) {
$this->fatal("$wiki_id does not yet exist");
}
if(empty($localfile)) {
$localfile = getcwd().'/'.utf8_basename($wiki_fn);
}
if(!file_exists(dirname($localfile))) {
$this->fatal("Directory ".dirname($localfile)." does not exist");
}
if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) {
$this->fatal("Attempt to check out file into data directory - not allowed");
}
$this->obtainLock($wiki_id);
if(!copy($wiki_fn, $localfile)) {
$this->clearLock($wiki_id);
$this->fatal("Unable to copy $wiki_fn to $localfile");
}
$this->success("$wiki_id > $localfile");
}
/**
* Save a file as a new page revision
*
* @param string $localfile
* @param string $wiki_id
* @param string $message
* @param bool $minor
*/
protected function commandCommit($localfile, $wiki_id, $message, $minor) {
$wiki_id = cleanID($wiki_id);
$message = trim($message);
if(!file_exists($localfile)) {
$this->fatal("$localfile does not exist");
}
if(!is_readable($localfile)) {
$this->fatal("Cannot read from $localfile");
}
if(!$message) {
$this->fatal("Summary message required");
}
$this->obtainLock($wiki_id);
saveWikiText($wiki_id, file_get_contents($localfile), $message, $minor);
$this->clearLock($wiki_id);
$this->success("$localfile > $wiki_id");
}
/**
* Lock the given page or exit
*
* @param string $wiki_id
*/
protected function obtainLock($wiki_id) {
if($this->force) $this->deleteLock($wiki_id);
$_SERVER['REMOTE_USER'] = $this->username;
if(checklock($wiki_id)) {
$this->error("Page $wiki_id is already locked by another user");
exit(1);
}
lock($wiki_id);
$_SERVER['REMOTE_USER'] = '_'.$this->username.'_';
if(checklock($wiki_id) != $this->username) {
$this->error("Unable to obtain lock for $wiki_id ");
var_dump(checklock($wiki_id));
exit(1);
}
}
/**
* Clear the lock on the given page
*
* @param string $wiki_id
*/
protected function clearLock($wiki_id) {
if($this->force) $this->deleteLock($wiki_id);
$_SERVER['REMOTE_USER'] = $this->username;
if(checklock($wiki_id)) {
$this->error("Page $wiki_id is locked by another user");
exit(1);
}
unlock($wiki_id);
if(file_exists(wikiLockFN($wiki_id))) {
$this->error("Unable to clear lock for $wiki_id");
exit(1);
}
}
/**
* Forcefully remove a lock on the page given
*
* @param string $wiki_id
*/
protected function deleteLock($wiki_id) {
$wikiLockFN = wikiLockFN($wiki_id);
if(file_exists($wikiLockFN)) {
if(!unlink($wikiLockFN)) {
$this->error("Unable to delete $wikiLockFN");
exit(1);
}
}
}
/**
* Get the current user's username from the environment
*
* @return string
*/
protected function getUser() {
$user = getenv('USER');
if(empty ($user)) {
$user = getenv('USERNAME');
} else {
return $user;
}
if(empty ($user)) {
$user = 'admin';
}
return $user;
}
if (empty ($user)) {
$user = 'admin';
}
return $user;
}
#------------------------------------------------------------------------------
function getSuppliedArgument($OPTS, $short, $long) {
$arg = $OPTS->get($short);
if ( is_null($arg) ) {
$arg = $OPTS->get($long);
}
return $arg;
}
#------------------------------------------------------------------------------
function obtainLock($WIKI_ID) {
global $USERNAME;
if ( !file_exists(wikiFN($WIKI_ID)) ) {
fwrite( STDERR, "$WIKI_ID does not yet exist\n");
}
$_SERVER['REMOTE_USER'] = $USERNAME;
if ( checklock($WIKI_ID) ) {
fwrite( STDERR, "Page $WIKI_ID is already locked by another user\n");
exit(1);
}
lock($WIKI_ID);
$_SERVER['REMOTE_USER'] = '_'.$USERNAME.'_';
if ( checklock($WIKI_ID) != $USERNAME ) {
fwrite( STDERR, "Unable to obtain lock for $WIKI_ID\n" );
exit(1);
}
}
#------------------------------------------------------------------------------
function clearLock($WIKI_ID) {
global $USERNAME ;
if ( !file_exists(wikiFN($WIKI_ID)) ) {
fwrite( STDERR, "$WIKI_ID does not yet exist\n");
}
$_SERVER['REMOTE_USER'] = $USERNAME;
if ( checklock($WIKI_ID) ) {
fwrite( STDERR, "Page $WIKI_ID is locked by another user\n");
exit(1);
}
unlock($WIKI_ID);
if ( file_exists(wikiLockFN($WIKI_ID)) ) {
fwrite( STDERR, "Unable to clear lock for $WIKI_ID\n" );
exit(1);
}
}
#------------------------------------------------------------------------------
function deleteLock($WIKI_ID) {
$wikiLockFN = wikiLockFN($WIKI_ID);
if ( file_exists($wikiLockFN) ) {
if ( !unlink($wikiLockFN) ) {
fwrite( STDERR, "Unable to delete $wikiLockFN\n" );
exit(1);
}
}
}
#------------------------------------------------------------------------------
$USERNAME = getUser();
$CWD = getcwd();
$SYSTEM_ID = '127.0.0.1';
#------------------------------------------------------------------------------
$OPTS = Doku_Cli_Opts::getOptions(
__FILE__,
'h::fm:u:s:t',
array(
'help==',
'user=',
'system=',
'trivial',
)
);
if ( $OPTS->isError() ) {
print $OPTS->getMessage()."\n";
exit(1);
}
if ( $OPTS->has('h') or $OPTS->has('help') or !$OPTS->hasArgs() ) {
usage(getSuppliedArgument($OPTS,'h','help'));
exit(0);
}
if ( $OPTS->has('u') or $OPTS->has('user') ) {
$USERNAME = getSuppliedArgument($OPTS,'u','user');
}
if ( $OPTS->has('s') or $OPTS->has('system') ) {
$SYSTEM_ID = getSuppliedArgument($OPTS,'s','system');
}
#------------------------------------------------------------------------------
switch ( $OPTS->arg(0) ) {
#----------------------------------------------------------------------
case 'checkout':
$WIKI_ID = $OPTS->arg(1);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
$WIKI_FN = wikiFN($WIKI_ID);
if ( !file_exists($WIKI_FN) ) {
fwrite( STDERR, "$WIKI_ID does not yet exist\n");
exit(1);
}
$TARGET_FN = $OPTS->arg(2);
if ( empty($TARGET_FN) ) {
$TARGET_FN = getcwd().'/'.utf8_basename($WIKI_FN);
}
if ( !file_exists(dirname($TARGET_FN)) ) {
fwrite( STDERR, "Directory ".dirname($TARGET_FN)." does not exist\n");
exit(1);
}
if ( stristr( realpath(dirname($TARGET_FN)), realpath($conf['datadir']) ) !== false ) {
fwrite( STDERR, "Attempt to check out file into data directory - not allowed\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
}
obtainLock($WIKI_ID);
# Need to lock the file first?
if ( !copy($WIKI_FN, $TARGET_FN) ) {
fwrite( STDERR, "Unable to copy $WIKI_FN to $TARGET_FN\n");
clearLock($WIKI_ID);
exit(1);
}
print "$WIKI_ID > $TARGET_FN\n";
exit(0);
break;
#----------------------------------------------------------------------
case 'commit':
$TARGET_FN = $OPTS->arg(1);
if ( !$TARGET_FN ) {
fwrite( STDERR, "Target filename required\n");
exit(1);
}
if ( !file_exists($TARGET_FN) ) {
fwrite( STDERR, "$TARGET_FN does not exist\n");
exit(1);
}
if ( !is_readable($TARGET_FN) ) {
fwrite( STDERR, "Cannot read from $TARGET_FN\n");
exit(1);
}
$WIKI_ID = $OPTS->arg(2);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
if ( !$OPTS->has('m') ) {
fwrite( STDERR, "Summary message required\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
}
$_SERVER['REMOTE_USER'] = $USERNAME;
if ( checklock($WIKI_ID) ) {
fwrite( STDERR, "$WIKI_ID is locked by another user\n");
exit(1);
}
obtainLock($WIKI_ID);
saveWikiText($WIKI_ID, file_get_contents($TARGET_FN), $OPTS->get('m'), $OPTS->has('t'));
clearLock($WIKI_ID);
exit(0);
break;
#----------------------------------------------------------------------
case 'lock':
$WIKI_ID = $OPTS->arg(1);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
}
obtainLock($WIKI_ID);
print "Locked : $WIKI_ID\n";
exit(0);
break;
#----------------------------------------------------------------------
case 'unlock':
$WIKI_ID = $OPTS->arg(1);
if ( !$WIKI_ID ) {
fwrite( STDERR, "Wiki page ID required\n");
exit(1);
}
if ( $OPTS->has('f') ) {
deleteLock($WIKI_ID);
} else {
clearLock($WIKI_ID);
}
print "Unlocked : $WIKI_ID\n";
exit(0);
break;
#----------------------------------------------------------------------
default:
fwrite( STDERR, "Invalid action ".$OPTS->arg(0)."\n" );
exit(1);
break;
}
// Main
$cli = new PageCLI();
$cli->run();

334
bin/gittool.php Executable file
View File

@ -0,0 +1,334 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
/**
* Easily manage DokuWiki git repositories
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class GitToolCLI extends DokuCLI {
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
$options->setHelp(
"Manage git repositories for DokuWiki and its plugins and templates.\n\n".
"$> ./bin/gittool.php clone gallery template:ach\n".
"$> ./bin/gittool.php repos\n".
"$> ./bin/gittool.php origin -v"
);
$options->registerArgument(
'command',
'Command to execute. See below',
true
);
$options->registerCommand(
'clone',
'Tries to install a known plugin or template (prefix with template:) via git. Uses the DokuWiki.org '.
'plugin repository to find the proper git repository. Multiple extensions can be given as parameters'
);
$options->registerArgument(
'extension',
'name of the extension to install, prefix with \'template:\' for templates',
true,
'clone'
);
$options->registerCommand(
'install',
'The same as clone, but when no git source repository can be found, the extension is installed via '.
'download'
);
$options->registerArgument(
'extension',
'name of the extension to install, prefix with \'template:\' for templates',
true,
'install'
);
$options->registerCommand(
'repos',
'Lists all git repositories found in this DokuWiki installation'
);
$options->registerCommand(
'*',
'Any unknown commands are assumed to be arguments to git and will be executed in all repositories '.
'found within this DokuWiki installation'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
$command = $options->getCmd();
if(!$command) $command = array_shift($options->args);
switch($command) {
case '':
echo $options->help();
break;
case 'clone':
$this->cmd_clone($options->args);
break;
case 'install':
$this->cmd_install($options->args);
break;
case 'repo':
case 'repos':
$this->cmd_repos();
break;
default:
$this->cmd_git($command, $options->args);
}
}
/**
* Tries to install the given extensions using git clone
*
* @param $extensions
*/
public function cmd_clone($extensions) {
$errors = array();
$succeeded = array();
foreach($extensions as $ext) {
$repo = $this->getSourceRepo($ext);
if(!$repo) {
$this->error("could not find a repository for $ext");
$errors[] = $ext;
} else {
if($this->cloneExtension($ext, $repo)) {
$succeeded[] = $ext;
} else {
$errors[] = $ext;
}
}
}
echo "\n";
if($succeeded) $this->success('successfully cloned the following extensions: '.join(', ', $succeeded));
if($errors) $this->error('failed to clone the following extensions: '.join(', ', $errors));
}
/**
* Tries to install the given extensions using git clone with fallback to install
*
* @param $extensions
*/
public function cmd_install($extensions) {
$errors = array();
$succeeded = array();
foreach($extensions as $ext) {
$repo = $this->getSourceRepo($ext);
if(!$repo) {
$this->info("could not find a repository for $ext");
if($this->downloadExtension($ext)) {
$succeeded[] = $ext;
} else {
$errors[] = $ext;
}
} else {
if($this->cloneExtension($ext, $repo)) {
$succeeded[] = $ext;
} else {
$errors[] = $ext;
}
}
}
echo "\n";
if($succeeded) $this->success('successfully installed the following extensions: '.join(', ', $succeeded));
if($errors) $this->error('failed to install the following extensions: '.join(', ', $errors));
}
/**
* Executes the given git command in every repository
*
* @param $cmd
* @param $arg
*/
public function cmd_git($cmd, $arg) {
$repos = $this->findRepos();
$shell = array_merge(array('git', $cmd), $arg);
$shell = array_map('escapeshellarg', $shell);
$shell = join(' ', $shell);
foreach($repos as $repo) {
if(!@chdir($repo)) {
$this->error("Could not change into $repo");
continue;
}
echo "\n";
$this->info("executing $shell in $repo");
$ret = 0;
system($shell, $ret);
if($ret == 0) {
$this->success("git succeeded in $repo");
} else {
$this->error("git failed in $repo");
}
}
}
/**
* Simply lists the repositories
*/
public function cmd_repos() {
$repos = $this->findRepos();
foreach($repos as $repo) {
echo "$repo\n";
}
}
/**
* Install extension from the given download URL
*
* @param string $ext
* @return bool
*/
private function downloadExtension($ext) {
/** @var helper_plugin_extension_extension $plugin */
$plugin = plugin_load('helper', 'extension_extension');
if(!$ext) die("extension plugin not available, can't continue");
$plugin->setExtension($ext);
$url = $plugin->getDownloadURL();
if(!$url) {
$this->error("no download URL for $ext");
return false;
}
$ok = false;
try {
$this->info("installing $ext via download from $url");
$ok = $plugin->installFromURL($url);
} catch(Exception $e) {
$this->error($e->getMessage());
}
if($ok) {
$this->success("installed $ext via download");
return true;
} else {
$this->success("failed to install $ext via download");
return false;
}
}
/**
* Clones the extension from the given repository
*
* @param string $ext
* @param string $repo
* @return bool
*/
private function cloneExtension($ext, $repo) {
if(substr($ext, 0, 9) == 'template:') {
$target = fullpath(tpl_incdir().'../'.substr($ext, 9));
} else {
$target = DOKU_PLUGIN.$ext;
}
$this->info("cloning $ext from $repo to $target");
$ret = 0;
system("git clone $repo $target", $ret);
if($ret === 0) {
$this->success("cloning of $ext succeeded");
return true;
} else {
$this->error("cloning of $ext failed");
return false;
}
}
/**
* Returns all git repositories in this DokuWiki install
*
* Looks in root, template and plugin directories only.
*
* @return array
*/
private function findRepos() {
$this->info('Looking for .git directories');
$data = array_merge(
glob(DOKU_INC.'.git', GLOB_ONLYDIR),
glob(DOKU_PLUGIN.'*/.git', GLOB_ONLYDIR),
glob(fullpath(tpl_incdir().'../').'/*/.git', GLOB_ONLYDIR)
);
if(!$data) {
$this->error('Found no .git directories');
} else {
$this->success('Found '.count($data).' .git directories');
}
$data = array_map('fullpath', array_map('dirname', $data));
return $data;
}
/**
* Returns the repository for the given extension
*
* @param $extension
* @return bool|string
*/
private function getSourceRepo($extension) {
/** @var helper_plugin_extension_extension $ext */
$ext = plugin_load('helper', 'extension_extension');
if(!$ext) die("extension plugin not available, can't continue");
$ext->setExtension($extension);
$repourl = $ext->getSourcerepoURL();
if(!$repourl) return false;
// match github repos
if(preg_match('/github\.com\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
return 'https://github.com/'.$user.'/'.$repo.'.git';
}
// match gitorious repos
if(preg_match('/gitorious.org\/([^\/]+)\/([^\/]+)?/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
if(!$repo) $repo = $user;
return 'https://git.gitorious.org/'.$user.'/'.$repo.'.git';
}
// match bitbucket repos - most people seem to use mercurial there though
if(preg_match('/bitbucket\.org\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
return 'https://bitbucket.org/'.$user.'/'.$repo.'.git';
}
return false;
}
}
// Main
$cli = new GitToolCLI();
$cli->run();

View File

@ -1,98 +1,103 @@
#!/usr/bin/php
<?php
if ('cli' != php_sapi_name()) die();
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/cliopts.php');
session_write_close();
// handle options
$short_opts = 'hcuq';
$long_opts = array('help', 'clear', 'update', 'quiet');
$OPTS = Doku_Cli_Opts::getOptions(__FILE__,$short_opts,$long_opts);
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
_usage();
exit(1);
}
$CLEAR = false;
$QUIET = false;
$INDEXER = null;
foreach ($OPTS->options as $key => $val) {
switch ($key) {
case 'h':
case 'help':
_usage();
exit;
case 'c':
case 'clear':
$CLEAR = true;
break;
case 'q':
case 'quiet':
$QUIET = true;
break;
}
}
#------------------------------------------------------------------------------
# Action
if($CLEAR) _clearindex();
_update();
#------------------------------------------------------------------------------
function _usage() {
print "Usage: indexer.php <options>
Updates the searchindex by indexing all new or changed pages
when the -c option is given the index is cleared first.
OPTIONS
-h, --help show this help and exit
-c, --clear clear the index before updating
-q, --quiet don't produce any output
";
}
function _update(){
global $conf;
$data = array();
_quietecho("Searching pages... ");
search($data,$conf['datadir'],'search_allpages',array('skipacl' => true));
_quietecho(count($data)." pages found.\n");
foreach($data as $val){
_index($val['id']);
}
}
function _index($id){
global $CLEAR;
global $QUIET;
_quietecho("$id... ");
idx_addPage($id, !$QUIET, $CLEAR);
_quietecho("done.\n");
}
/**
* Clear all index files
* Update the Search Index from command line
*/
function _clearindex(){
_quietecho("Clearing index... ");
idx_get_indexer()->clear();
_quietecho("done.\n");
class IndexerCLI extends DokuCLI {
private $quiet = false;
private $clear = false;
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
$options->setHelp(
'Updates the searchindex by indexing all new or changed pages. When the -c option is '.
'given the index is cleared first.'
);
$options->registerOption(
'clear',
'clear the index before updating',
'c'
);
$options->registerOption(
'quiet',
'don\'t produce any output',
'q'
);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
$this->clear = $options->getOpt('clear');
$this->quiet = $options->getOpt('quiet');
if($this->clear) $this->clearindex();
$this->update();
}
/**
* Update the index
*/
function update() {
global $conf;
$data = array();
$this->quietecho("Searching pages... ");
search($data, $conf['datadir'], 'search_allpages', array('skipacl' => true));
$this->quietecho(count($data)." pages found.\n");
foreach($data as $val) {
$this->index($val['id']);
}
}
/**
* Index the given page
*
* @param string $id
*/
function index($id) {
$this->quietecho("$id... ");
idx_addPage($id, !$this->quiet, $this->clear);
$this->quietecho("done.\n");
}
/**
* Clear all index files
*/
function clearindex() {
$this->quietecho("Clearing index... ");
idx_get_indexer()->clear();
$this->quietecho("done.\n");
}
/**
* Print message if not supressed
*
* @param string $msg
*/
function quietecho($msg) {
if(!$this->quiet) echo $msg;
}
}
function _quietecho($msg) {
global $QUIET;
if(!$QUIET) echo $msg;
}
//Setup VIM: ex: et ts=2 :
// Main
$cli = new IndexerCLI();
$cli->run();

View File

@ -1,5 +1,10 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
/**
* A simple commandline tool to render some DokuWiki syntax with a given
* renderer.
@ -9,59 +14,48 @@
* DokuWiki markup
*
* @license GPL2
* @author Andreas Gohr <andi@splitbrain.org>
* @author Andreas Gohr <andi@splitbrain.org>
*/
if ('cli' != php_sapi_name()) die();
class RenderCLI extends DokuCLI {
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION',1);
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/common.php');
require_once(DOKU_INC.'inc/parserutils.php');
require_once(DOKU_INC.'inc/cliopts.php');
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
$options->setHelp(
'A simple commandline tool to render some DokuWiki syntax with a given renderer.'.
"\n\n".
'This may not work for plugins that expect a certain environment to be '.
'set up before rendering, but should work for most or even all standard '.
'DokuWiki markup'
);
$options->registerOption('renderer', 'The renderer mode to use. Defaults to xhtml', 'r', 'mode');
}
// handle options
$short_opts = 'hr:';
$long_opts = array('help','renderer:');
$OPTS = Doku_Cli_Opts::getOptions(__FILE__,$short_opts,$long_opts);
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
_usage();
exit(1);
}
$RENDERER = 'xhtml';
foreach ($OPTS->options as $key => $val) {
switch ($key) {
case 'h':
case 'help':
_usage();
exit;
case 'r':
case 'renderer':
$RENDERER = $val;
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @throws DokuCLI_Exception
* @return void
*/
protected function main(DokuCLI_Options $options) {
$renderer = $options->getOpt('renderer', 'xhtml');
// do the action
$source = stream_get_contents(STDIN);
$info = array();
$result = p_render($renderer, p_get_instructions($source), $info);
if(is_null($result)) throw new DokuCLI_Exception("No such renderer $renderer");
echo $result;
}
}
// do the action
$source = stream_get_contents(STDIN);
$info = array();
$result = p_render($RENDERER,p_get_instructions($source),$info);
if(is_null($result)) die("No such renderer $RENDERER\n");
echo $result;
/**
* Print usage info
*/
function _usage(){
print "Usage: render.php <options>
Reads DokuWiki syntax from STDIN and renders it with the given renderer
to STDOUT
OPTIONS
-h, --help show this help and exit
-r, --renderer <renderer> the render mode (default: xhtml)
";
}
// Main
$cli = new RenderCLI();
$cli->run();

View File

@ -1,148 +1,110 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
/**
* Strip unwanted languages from the DokuWiki install
*
* @author Martin 'E.T.' Misuth <et.github@ethome.sk>
* Remove unwanted languages from a DokuWiki install
*/
if ('cli' != php_sapi_name()) die();
class StripLangsCLI extends DokuCLI {
#------------------------------------------------------------------------------
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once DOKU_INC.'inc/cliopts.php';
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
#------------------------------------------------------------------------------
function usage($show_examples = false) {
print "Usage: striplangs.php [-h [-x]] [-e] [-k lang1[,lang2]..[,langN]]
$options->setHelp(
'Remove all languages from the installation, besides the ones specified. English language '.
'is never removed!'
);
Removes all languages from the installation, besides the ones
after the -k option. English language is never removed!
OPTIONS
-h, --help get this help
-x, --examples get also usage examples
-k, --keep comma separated list of languages, -e is always implied
-e, --english keeps english, dummy to use without -k\n";
if ( $show_examples ) {
print "\n
EXAMPLES
Strips all languages, but keeps 'en' and 'de':
striplangs -k de
Strips all but 'en','ca-valencia','cs','de','is','sk':
striplangs --keep ca-valencia,cs,de,is,sk
Strips all but 'en':
striplangs -e
No option specified, prints usage and throws error:
striplangs\n";
$options->registerOption(
'keep',
'Comma separated list of languages to keep in addition to English.',
'k'
);
$options->registerOption(
'english-only',
'Remove all languages except English',
'e'
);
}
}
function getSuppliedArgument($OPTS, $short, $long) {
$arg = $OPTS->get($short);
if ( is_null($arg) ) {
$arg = $OPTS->get($long);
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
if($options->getOpt('keep')) {
$keep = explode(',', $options->getOpt('keep'));
if(!in_array('en', $keep)) $keep[] = 'en';
} elseif($options->getOpt('english-only')) {
$keep = array('en');
} else {
echo $options->help();
exit(0);
}
// Kill all language directories in /inc/lang and /lib/plugins besides those in $langs array
$this->stripDirLangs(realpath(dirname(__FILE__).'/../inc/lang'), $keep);
$this->processExtensions(realpath(dirname(__FILE__).'/../lib/plugins'), $keep);
$this->processExtensions(realpath(dirname(__FILE__).'/../lib/tpl'), $keep);
}
return $arg;
}
function processPlugins($path, $keep_langs) {
if (is_dir($path)) {
$entries = scandir($path);
/**
* Strip languages from extensions
*
* @param string $path path to plugin or template dir
* @param array $keep_langs languages to keep
*/
protected function processExtensions($path, $keep_langs) {
if(is_dir($path)) {
$entries = scandir($path);
foreach ($entries as $entry) {
if ($entry != "." && $entry != "..") {
if ( is_dir($path.'/'.$entry) ) {
foreach($entries as $entry) {
if($entry != "." && $entry != "..") {
if(is_dir($path.'/'.$entry)) {
$plugin_langs = $path.'/'.$entry.'/lang';
$plugin_langs = $path.'/'.$entry.'/lang';
if ( is_dir( $plugin_langs ) ) {
stripDirLangs($plugin_langs, $keep_langs);
if(is_dir($plugin_langs)) {
$this->stripDirLangs($plugin_langs, $keep_langs);
}
}
}
}
}
}
}
function stripDirLangs($path, $keep_langs) {
$dir = dir($path);
/**
* Strip languages from path
*
* @param string $path path to lang dir
* @param array $keep_langs languages to keep
*/
protected function stripDirLangs($path, $keep_langs) {
$dir = dir($path);
while(($cur_dir = $dir->read()) !== false) {
if( $cur_dir != '.' and $cur_dir != '..' and is_dir($path.'/'.$cur_dir)) {
while(($cur_dir = $dir->read()) !== false) {
if($cur_dir != '.' and $cur_dir != '..' and is_dir($path.'/'.$cur_dir)) {
if ( !in_array($cur_dir, $keep_langs, true ) ) {
killDir($path.'/'.$cur_dir);
}
}
}
$dir->close();
}
function killDir($dir) {
if (is_dir($dir)) {
$entries = scandir($dir);
foreach ($entries as $entry) {
if ($entry != "." && $entry != "..") {
if ( is_dir($dir.'/'.$entry) ) {
killDir($dir.'/'.$entry);
} else {
unlink($dir.'/'.$entry);
if(!in_array($cur_dir, $keep_langs, true)) {
io_rmdir($path.'/'.$cur_dir, true);
}
}
}
reset($entries);
rmdir($dir);
$dir->close();
}
}
#------------------------------------------------------------------------------
// handle options
$short_opts = 'hxk:e';
$long_opts = array('help', 'examples', 'keep=','english');
$OPTS = Doku_Cli_Opts::getOptions(__FILE__, $short_opts, $long_opts);
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
exit(1);
}
// handle '--examples' option
$show_examples = ( $OPTS->has('x') or $OPTS->has('examples') ) ? true : false;
// handle '--help' option
if ( $OPTS->has('h') or $OPTS->has('help') ) {
usage($show_examples);
exit(0);
}
// handle both '--keep' and '--english' options
if ( $OPTS->has('k') or $OPTS->has('keep') ) {
$preserved_langs = getSuppliedArgument($OPTS,'k','keep');
$langs = explode(',', $preserved_langs);
// ! always enforce 'en' lang when using '--keep' (DW relies on it)
if ( !isset($langs['en']) ) {
$langs[]='en';
}
} elseif ( $OPTS->has('e') or $OPTS->has('english') ) {
// '--english' was specified strip everything besides 'en'
$langs = array ('en');
} else {
// no option was specified, print usage but don't do anything as
// this run might not be intented
usage();
print "\n
ERROR
No option specified, use either -h -x to get more info,
or -e to strip every language besides english.\n";
exit(1);
}
// Kill all language directories in /inc/lang and /lib/plugins besides those in $langs array
stripDirLangs(realpath(dirname(__FILE__).'/../inc/lang'), $langs);
processPlugins(realpath(dirname(__FILE__).'/../lib/plugins'), $langs);
$cli = new StripLangsCLI();
$cli->run();

View File

@ -1,134 +1,133 @@
#!/usr/bin/php
<?php
if ('cli' != php_sapi_name()) die();
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
#------------------------------------------------------------------------------
ini_set('memory_limit','128M');
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once DOKU_INC.'inc/init.php';
require_once DOKU_INC.'inc/common.php';
require_once DOKU_INC.'inc/search.php';
require_once DOKU_INC.'inc/cliopts.php';
/**
* Find wanted pages
*/
class WantedPagesCLI extends DokuCLI {
#------------------------------------------------------------------------------
function usage() {
print "Usage: wantedpages.php [wiki:namespace]
const DIR_CONTINUE = 1;
const DIR_NS = 2;
const DIR_PAGE = 3;
Outputs a list of wanted pages (pages which have
internal links but do not yet exist).
If the optional [wiki:namespace] is not provided,
defaults to the root wiki namespace
OPTIONS
-h, --help get help
";
}
#------------------------------------------------------------------------------
define ('DW_DIR_CONTINUE',1);
define ('DW_DIR_NS',2);
define ('DW_DIR_PAGE',3);
#------------------------------------------------------------------------------
function dw_dir_filter($entry, $basepath) {
if ($entry == '.' || $entry == '..' ) {
return DW_DIR_CONTINUE;
}
if ( is_dir($basepath . '/' . $entry) ) {
if ( strpos($entry, '_') === 0 ) {
return DW_DIR_CONTINUE;
}
return DW_DIR_NS;
}
if ( preg_match('/\.txt$/',$entry) ) {
return DW_DIR_PAGE;
}
return DW_DIR_CONTINUE;
}
#------------------------------------------------------------------------------
function dw_get_pages($dir) {
static $trunclen = null;
if ( !$trunclen ) {
global $conf;
$trunclen = strlen($conf['datadir'].':');
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
$options->setHelp(
'Outputs a list of wanted pages (pages which have internal links but do not yet exist).'
);
$options->registerArgument(
'namespace',
'The namespace to lookup. Defaults to root namespace',
false
);
}
if ( !is_dir($dir) ) {
fwrite( STDERR, "Unable to read directory $dir\n");
exit(1);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
$pages = array();
$dh = opendir($dir);
while ( false !== ( $entry = readdir($dh) ) ) {
$status = dw_dir_filter($entry, $dir);
if ( $status == DW_DIR_CONTINUE ) {
continue;
} else if ( $status == DW_DIR_NS ) {
$pages = array_merge($pages, dw_get_pages($dir . '/' . $entry));
if($options->args) {
$startdir = dirname(wikiFN($options->args[0].':xxx'));
} else {
$page = array(
'id' => pathID(substr($dir.'/'.$entry,$trunclen)),
'file'=> $dir.'/'.$entry,
);
$pages[] = $page;
$startdir = dirname(wikiFN('xxx'));
}
$this->info("searching $startdir");
$wanted_pages = array();
foreach($this->get_pages($startdir) as $page) {
$wanted_pages = array_merge($wanted_pages, $this->internal_links($page));
}
$wanted_pages = array_unique($wanted_pages);
sort($wanted_pages);
foreach($wanted_pages as $page) {
print $page."\n";
}
}
closedir($dh);
return $pages;
}
#------------------------------------------------------------------------------
function dw_internal_links($page) {
global $conf;
$instructions = p_get_instructions(file_get_contents($page['file']));
$links = array();
$cns = getNS($page['id']);
$exists = false;
foreach($instructions as $ins){
if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink') ){
$mid = $ins[1][0];
resolve_pageid($cns,$mid,$exists);
if ( !$exists ) {
list($mid) = explode('#',$mid); //record pages without hashs
$links[] = $mid;
protected function dir_filter($entry, $basepath) {
if($entry == '.' || $entry == '..') {
return WantedPagesCLI::DIR_CONTINUE;
}
if(is_dir($basepath.'/'.$entry)) {
if(strpos($entry, '_') === 0) {
return WantedPagesCLI::DIR_CONTINUE;
}
return WantedPagesCLI::DIR_NS;
}
if(preg_match('/\.txt$/', $entry)) {
return WantedPagesCLI::DIR_PAGE;
}
return WantedPagesCLI::DIR_CONTINUE;
}
protected function get_pages($dir) {
static $trunclen = null;
if(!$trunclen) {
global $conf;
$trunclen = strlen($conf['datadir'].':');
}
if(!is_dir($dir)) {
throw new DokuCLI_Exception("Unable to read directory $dir");
}
$pages = array();
$dh = opendir($dir);
while(false !== ($entry = readdir($dh))) {
$status = $this->dir_filter($entry, $dir);
if($status == WantedPagesCLI::DIR_CONTINUE) {
continue;
} else if($status == WantedPagesCLI::DIR_NS) {
$pages = array_merge($pages, $this->get_pages($dir.'/'.$entry));
} else {
$page = array(
'id' => pathID(substr($dir.'/'.$entry, $trunclen)),
'file' => $dir.'/'.$entry,
);
$pages[] = $page;
}
}
closedir($dh);
return $pages;
}
function internal_links($page) {
global $conf;
$instructions = p_get_instructions(file_get_contents($page['file']));
$links = array();
$cns = getNS($page['id']);
$exists = false;
foreach($instructions as $ins) {
if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink')) {
$mid = $ins[1][0];
resolve_pageid($cns, $mid, $exists);
if(!$exists) {
list($mid) = explode('#', $mid); //record pages without hashs
$links[] = $mid;
}
}
}
return $links;
}
return $links;
}
#------------------------------------------------------------------------------
$OPTS = Doku_Cli_Opts::getOptions(__FILE__,'h',array('help'));
if ( $OPTS->isError() ) {
fwrite( STDERR, $OPTS->getMessage() . "\n");
exit(1);
}
if ( $OPTS->has('h') or $OPTS->has('help') ) {
usage();
exit(0);
}
$START_DIR = $conf['datadir'];
if ( $OPTS->numArgs() == 1 ) {
$START_DIR .= '/' . $OPTS->arg(0);
}
#------------------------------------------------------------------------------
$WANTED_PAGES = array();
foreach ( dw_get_pages($START_DIR) as $WIKI_PAGE ) {
$WANTED_PAGES = array_merge($WANTED_PAGES,dw_internal_links($WIKI_PAGE));
}
$WANTED_PAGES = array_unique($WANTED_PAGES);
sort($WANTED_PAGES);
foreach ( $WANTED_PAGES as $WANTED_PAGE ) {
print $WANTED_PAGE."\n";
}
exit(0);
// Main
$cli = new WantedPagesCLI();
$cli->run();

View File

@ -24,12 +24,13 @@ amazon.de http://www.amazon.de/exec/obidos/ASIN/{URL}/splitbrain-21/
amazon.uk http://www.amazon.co.uk/exec/obidos/ASIN/
paypal https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=
phpfn http://www.php.net/{NAME}
coral http://{HOST}.{PORT}.nyud.net:8090/{PATH}?{QUERY}
coral http://{HOST}.{PORT}.nyud.net:8090{PATH}?{QUERY}
freecache http://freecache.org/{NAME}
sb http://www.splitbrain.org/go/
skype skype:{NAME}
google.de http://www.google.de/search?q=
go http://www.google.com/search?q={URL}&amp;btnI=lucky
user :user:{NAME}
# To support VoIP/SIP links
callto callto://{NAME}

View File

@ -5,7 +5,7 @@
* following contents:
* fieldname - Where data will be saved (EXIF or IPTC field)
* label - key to lookup in the $lang var, if not found printed as is
* htmltype - 'text' or 'textarea'
* htmltype - 'text', 'textarea' or 'date'
* lookups - array additional fields to lookup the data (EXIF or IPTC fields)
*
* The fields are not ordered continously to make inserting additional items

View File

@ -2,6 +2,164 @@
# but were removed later. An up to date DokuWiki should not have any of
# the files installed
# removed in 2014-05-05
lib/images/fileicons/audio.png
lib/plugins/acl/lang/hi/lang.php
lib/plugins/acl/lang/id-ni/lang.php
lib/plugins/acl/lang/lb/lang.php
lib/plugins/acl/lang/ms/lang.php
lib/plugins/authad/lang/lv/settings.php
lib/plugins/authldap/lang/lv/settings.php
lib/plugins/authmysql/lang/fi/settings.php
lib/plugins/authmysql/lang/lv/settings.php
lib/plugins/authpgsql/lang/fi/settings.php
lib/plugins/authpgsql/lang/it/settings.php
lib/plugins/authpgsql/lang/lv/settings.php
lib/plugins/authpgsql/lang/pl/settings.php
lib/plugins/config/lang/hr/lang.php
lib/plugins/config/lang/id/lang.php
lib/plugins/config/lang/kk/lang.php
lib/plugins/config/lang/lb/lang.php
lib/plugins/config/lang/mk/lang.php
lib/plugins/config/lang/ms/lang.php
lib/plugins/config/lang/vi/lang.php
lib/plugins/plugin/admin.php
lib/plugins/plugin/classes/ap_delete.class.php
lib/plugins/plugin/classes/ap_download.class.php
lib/plugins/plugin/classes/ap_enable.class.php
lib/plugins/plugin/classes/ap_info.class.php
lib/plugins/plugin/classes/ap_manage.class.php
lib/plugins/plugin/classes/ap_update.class.php
lib/plugins/plugin/lang/af/lang.php
lib/plugins/plugin/lang/ar/admin_plugin.txt
lib/plugins/plugin/lang/ar/lang.php
lib/plugins/plugin/lang/bg/admin_plugin.txt
lib/plugins/plugin/lang/bg/lang.php
lib/plugins/plugin/lang/ca-valencia/admin_plugin.txt
lib/plugins/plugin/lang/ca-valencia/lang.php
lib/plugins/plugin/lang/ca/admin_plugin.txt
lib/plugins/plugin/lang/ca/lang.php
lib/plugins/plugin/lang/cs/admin_plugin.txt
lib/plugins/plugin/lang/cs/lang.php
lib/plugins/plugin/lang/da/admin_plugin.txt
lib/plugins/plugin/lang/da/lang.php
lib/plugins/plugin/lang/de-informal/admin_plugin.txt
lib/plugins/plugin/lang/de-informal/lang.php
lib/plugins/plugin/lang/de/admin_plugin.txt
lib/plugins/plugin/lang/de/lang.php
lib/plugins/plugin/lang/el/admin_plugin.txt
lib/plugins/plugin/lang/el/lang.php
lib/plugins/plugin/lang/en/admin_plugin.txt
lib/plugins/plugin/lang/en/lang.php
lib/plugins/plugin/lang/eo/admin_plugin.txt
lib/plugins/plugin/lang/eo/lang.php
lib/plugins/plugin/lang/es/admin_plugin.txt
lib/plugins/plugin/lang/es/lang.php
lib/plugins/plugin/lang/et/lang.php
lib/plugins/plugin/lang/eu/admin_plugin.txt
lib/plugins/plugin/lang/eu/lang.php
lib/plugins/plugin/lang/fa/admin_plugin.txt
lib/plugins/plugin/lang/fa/lang.php
lib/plugins/plugin/lang/fi/admin_plugin.txt
lib/plugins/plugin/lang/fi/lang.php
lib/plugins/plugin/lang/fr/admin_plugin.txt
lib/plugins/plugin/lang/fr/lang.php
lib/plugins/plugin/lang/gl/admin_plugin.txt
lib/plugins/plugin/lang/gl/lang.php
lib/plugins/plugin/lang/he/admin_plugin.txt
lib/plugins/plugin/lang/he/lang.php
lib/plugins/plugin/lang/hi/lang.php
lib/plugins/plugin/lang/hr/lang.php
lib/plugins/plugin/lang/hu/admin_plugin.txt
lib/plugins/plugin/lang/hu/lang.php
lib/plugins/plugin/lang/ia/admin_plugin.txt
lib/plugins/plugin/lang/ia/lang.php
lib/plugins/plugin/lang/id-ni/lang.php
lib/plugins/plugin/lang/id/lang.php
lib/plugins/plugin/lang/is/lang.php
lib/plugins/plugin/lang/it/admin_plugin.txt
lib/plugins/plugin/lang/it/lang.php
lib/plugins/plugin/lang/ja/admin_plugin.txt
lib/plugins/plugin/lang/ja/lang.php
lib/plugins/plugin/lang/kk/lang.php
lib/plugins/plugin/lang/ko/admin_plugin.txt
lib/plugins/plugin/lang/ko/lang.php
lib/plugins/plugin/lang/la/admin_plugin.txt
lib/plugins/plugin/lang/la/lang.php
lib/plugins/plugin/lang/lb/admin_plugin.txt
lib/plugins/plugin/lang/lb/lang.php
lib/plugins/plugin/lang/lt/admin_plugin.txt
lib/plugins/plugin/lang/lt/lang.php
lib/plugins/plugin/lang/lv/admin_plugin.txt
lib/plugins/plugin/lang/lv/lang.php
lib/plugins/plugin/lang/mk/lang.php
lib/plugins/plugin/lang/mr/admin_plugin.txt
lib/plugins/plugin/lang/mr/lang.php
lib/plugins/plugin/lang/ms/lang.php
lib/plugins/plugin/lang/ne/lang.php
lib/plugins/plugin/lang/nl/admin_plugin.txt
lib/plugins/plugin/lang/nl/lang.php
lib/plugins/plugin/lang/no/admin_plugin.txt
lib/plugins/plugin/lang/no/lang.php
lib/plugins/plugin/lang/pl/admin_plugin.txt
lib/plugins/plugin/lang/pl/lang.php
lib/plugins/plugin/lang/pt-br/admin_plugin.txt
lib/plugins/plugin/lang/pt-br/lang.php
lib/plugins/plugin/lang/pt/admin_plugin.txt
lib/plugins/plugin/lang/pt/lang.php
lib/plugins/plugin/lang/ro/admin_plugin.txt
lib/plugins/plugin/lang/ro/lang.php
lib/plugins/plugin/lang/ru/admin_plugin.txt
lib/plugins/plugin/lang/ru/lang.php
lib/plugins/plugin/lang/sk/admin_plugin.txt
lib/plugins/plugin/lang/sk/lang.php
lib/plugins/plugin/lang/sl/admin_plugin.txt
lib/plugins/plugin/lang/sl/lang.php
lib/plugins/plugin/lang/sq/admin_plugin.txt
lib/plugins/plugin/lang/sq/lang.php
lib/plugins/plugin/lang/sr/admin_plugin.txt
lib/plugins/plugin/lang/sr/lang.php
lib/plugins/plugin/lang/sv/admin_plugin.txt
lib/plugins/plugin/lang/sv/lang.php
lib/plugins/plugin/lang/th/admin_plugin.txt
lib/plugins/plugin/lang/th/lang.php
lib/plugins/plugin/lang/tr/admin_plugin.txt
lib/plugins/plugin/lang/tr/lang.php
lib/plugins/plugin/lang/uk/admin_plugin.txt
lib/plugins/plugin/lang/uk/lang.php
lib/plugins/plugin/lang/vi/lang.php
lib/plugins/plugin/lang/zh-tw/admin_plugin.txt
lib/plugins/plugin/lang/zh-tw/lang.php
lib/plugins/plugin/lang/zh/admin_plugin.txt
lib/plugins/plugin/lang/zh/lang.php
lib/plugins/plugin/plugin.info.txt
lib/plugins/plugin/style.css
lib/plugins/popularity/lang/et/lang.php
lib/plugins/popularity/lang/hr/lang.php
lib/plugins/popularity/lang/id/lang.php
lib/plugins/popularity/lang/kk/lang.php
lib/plugins/popularity/lang/lb/lang.php
lib/plugins/popularity/lang/mk/lang.php
lib/plugins/popularity/lang/ms/lang.php
lib/plugins/popularity/lang/vi/lang.php
lib/plugins/revert/lang/af/lang.php
lib/plugins/revert/lang/hi/lang.php
lib/plugins/revert/lang/hr/lang.php
lib/plugins/revert/lang/id-ni/lang.php
lib/plugins/revert/lang/id/lang.php
lib/plugins/revert/lang/kk/lang.php
lib/plugins/revert/lang/lb/lang.php
lib/plugins/revert/lang/lt/lang.php
lib/plugins/revert/lang/mk/lang.php
lib/plugins/revert/lang/ms/lang.php
lib/plugins/revert/lang/vi/lang.php
lib/plugins/usermanager/lang/hi/lang.php
lib/plugins/usermanager/lang/hr/lang.php
lib/plugins/usermanager/lang/id-ni/lang.php
lib/plugins/usermanager/lang/lb/lang.php
lib/plugins/usermanager/lang/ms/lang.php
lib/plugins/usermanager/lang/vi/lang.php
# removed in 2013-11-18
lib/images/arrow_down.gif
lib/images/arrow_up.gif

View File

@ -6,7 +6,7 @@ Read the [[doku>manual|DokuWiki Manual]] to unleash the full power of DokuWiki.
===== Download =====
DokuWiki is available at http://www.splitbrain.org/go/dokuwiki
DokuWiki is available at http://download.dokuwiki.org/
===== Read More =====
@ -24,7 +24,7 @@ All documentation and additional information besides the [[syntax|syntax descrip
**Installing DokuWiki**
* [[doku>requirements|System Requirements]]
* [[http://www.splitbrain.org/go/dokuwiki|Download DokuWiki]] :!:
* [[http://download.dokuwiki.org/|Download DokuWiki]] :!:
* [[doku>changes|Change Log]]
* [[doku>Install|How to install or upgrade]] :!:
* [[doku>config|Configuration]]
@ -50,7 +50,7 @@ All documentation and additional information besides the [[syntax|syntax descrip
* [[doku>mailinglist|Join the mailing list]]
* [[http://forum.dokuwiki.org|Check out the user forum]]
* [[doku>irc|Talk to other users in the IRC channel]]
* [[http://bugs.splitbrain.org/index.php?project=1|Submit bugs and feature wishes]]
* [[https://github.com/splitbrain/dokuwiki/issues|Submit bugs and feature wishes]]
* [[http://www.wikimatrix.org/forum/viewforum.php?id=10|Share your experiences in the WikiMatrix forum]]
* [[doku>thanks|Some humble thanks]]

View File

@ -121,9 +121,9 @@ By using four or more dashes, you can make a horizontal line:
----
===== Images and Other Files =====
===== Media Files =====
You can include external and internal [[doku>images]] with curly brackets. Optionally you can specify the size of them.
You can include external and internal [[doku>images|images, videos and audio files]] with curly brackets. Optionally you can specify the size of them.
Real size: {{wiki:dokuwiki-128.png}}
@ -157,10 +157,31 @@ Of course, you can add a title (displayed as a tooltip by most browsers), too.
{{ wiki:dokuwiki-128.png |This is the caption}}
If you specify a filename (external or internal) that is not an image (''gif, jpeg, png''), then it will be displayed as a link instead.
For linking an image to another page see [[#Image Links]] above.
==== Supported Media Formats ====
DokuWiki can embed the following media formats directly.
| Image | ''gif'', ''jpg'', ''png'' |
| Video | ''webm'', ''ogv'', ''mp4'' |
| Audio | ''ogg'', ''mp3'', ''wav'' |
| Flash | ''swf'' |
If you specify a filename that is not a supported media format, then it will be displayed as a link instead.
==== Fallback Formats ====
Unfortunately not all browsers understand all video and audio formats. To mitigate the problem, you can upload your file in different formats for maximum browser compatibility.
For example consider this embedded mp4 video:
{{video.mp4|A funny video}}
When you upload a ''video.webm'' and ''video.ogv'' next to the referenced ''video.mp4'', DokuWiki will automatically add them as alternatives so that one of the three files is understood by your browser.
Additionally DokuWiki supports a "poster" image which will be shown before the video has started. That image needs to have the same filename as the video and be either a jpg or png file. In the example above a ''video.jpg'' file would work.
===== Lists =====
Dokuwiki supports ordered and unordered lists. To create a list item, indent your text by two spaces and use a ''*'' for unordered lists or a ''-'' for ordered ones.

View File

@ -9,7 +9,7 @@
*/
// update message version
$updateVersion = 43;
$updateVersion = 45;
// xdebug_start_profiling();

View File

@ -15,13 +15,19 @@ require_once(DOKU_INC.'inc/init.php');
//close session
session_write_close();
//feed disabled?
if(!actionOK('rss')) {
http_status(404);
echo '<error>RSS feed is disabled.</error>';
exit;
}
// get params
$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)
$cache = getCacheName(join('', array_values($opt)).$_SERVER['REMOTE_USER'], '.feed');
$key = join('', array_values($opt)).$_SERVER['REMOTE_USER'];
$key = join('', array_values($opt)).'$'.$_SERVER['REMOTE_USER'].'$'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'];
$cache = new cache($key, '.feed');
// prepare cache depends
@ -121,6 +127,8 @@ function rss_parseOptions() {
'items' => array('int', 'num', $conf['recent']),
// Boolean, only used in rc mode
'show_minor' => array('bool', 'minor', 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
@ -132,15 +140,14 @@ function rss_parseOptions() {
$opt['items'] = max(0, (int) $opt['items']);
$opt['show_minor'] = (bool) $opt['show_minor'];
$opt['sort'] = valid_input_set('sort', array('default' => 'natural', 'date'), $opt);
$opt['guardmail'] = ($conf['mailguard'] != '' && $conf['mailguard'] != 'none');
$type = valid_input_set(
'type', array(
'rss', 'rss2', 'atom', 'atom1', 'rss1',
'default' => $conf['rss_type']
),
$_REQUEST
$type = $INPUT->valid(
'type',
array( 'rss', 'rss2', 'atom', 'atom1', 'rss1'),
$conf['rss_type']
);
switch($type) {
case 'rss':
@ -182,7 +189,7 @@ function rss_parseOptions() {
function rss_buildItems(&$rss, &$data, $opt) {
global $conf;
global $lang;
/* @var auth_basic $auth */
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
$eventData = array(
@ -293,18 +300,19 @@ function rss_buildItems(&$rss, &$data, $opt) {
case 'diff':
case 'htmldiff':
if($ditem['media']) {
$revs = getRevisions($id, 0, 1, 8192, true);
$medialog = new MediaChangeLog($id);
$revs = $medialog->getRevisions(0, 1);
$rev = $revs[0];
$src_r = '';
$src_l = '';
if($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)), 300)) {
$more = 'w='.$size[0].'&h='.$size[1].'t='.@filemtime(mediaFN($id));
$src_r = ml($id, $more);
$more = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id));
$src_r = ml($id, $more, true, '&amp;', 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];
$src_l = ml($id, $more);
$src_l = ml($id, $more, true, '&amp;', true);
}
$content = '';
if($src_r) {
@ -318,7 +326,8 @@ function rss_buildItems(&$rss, &$data, $opt) {
} else {
require_once(DOKU_INC.'inc/DifferenceEngine.php');
$revs = getRevisions($id, 0, 1);
$pagelog = new PageChangeLog($id);
$revs = $pagelog->getRevisions(0, 1);
$rev = $revs[0];
if($rev) {
@ -347,8 +356,8 @@ function rss_buildItems(&$rss, &$data, $opt) {
case 'html':
if($ditem['media']) {
if($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)))) {
$more = 'w='.$size[0].'&h='.$size[1].'t='.@filemtime(mediaFN($id));
$src = ml($id, $more);
$more = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id));
$src = ml($id, $more, true, '&amp;', true);
$content = '<img src="'.$src.'" alt="'.$id.'" />';
} else {
$content = '';
@ -378,8 +387,8 @@ function rss_buildItems(&$rss, &$data, $opt) {
default:
if($ditem['media']) {
if($size = media_image_preview_size($id, false, new JpegMeta(mediaFN($id)))) {
$more = 'w='.$size[0].'&h='.$size[1].'t='.@filemtime(mediaFN($id));
$src = ml($id, $more);
$more = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id));
$src = ml($id, $more, true, '&amp;', true);
$content = '<img src="'.$src.'" alt="'.$id.'" />';
} else {
$content = '';
@ -399,6 +408,7 @@ function rss_buildItems(&$rss, &$data, $opt) {
if($userInfo) {
switch($conf['showuseras']) {
case 'username':
case 'username_link':
$item->author = $userInfo['name'];
break;
default:
@ -473,7 +483,7 @@ function rssListNamespace($opt) {
global $conf;
$ns = ':'.cleanID($opt['namespace']);
$ns = str_replace(':', '/', $ns);
$ns = utf8_encodeFN(str_replace(':', '/', $ns));
$data = array();
$search_opts = array(
@ -481,7 +491,7 @@ function rssListNamespace($opt) {
'pagesonly' => true,
'listfiles' => true
);
search($data, $conf['datadir'], 'search_universal', $search_opts, $ns);
search($data, $conf['datadir'], 'search_universal', $search_opts, $ns, $lvl = 1, $opt['sort']);
return $data;
}

View File

@ -15,8 +15,8 @@ class EmailAddressValidator {
/**
* Check email address validity
* @param strEmailAddress Email address to be checked
* @return True if email is valid, false if not
* @param string $strEmailAddress Email address to be checked
* @return bool True if email is valid, false if not
*/
public function check_email_address($strEmailAddress) {
@ -82,8 +82,8 @@ class EmailAddressValidator {
/**
* Checks email section before "@" symbol for validity
* @param strLocalPortion Text to be checked
* @return True if local portion is valid, false if not
* @param string $strLocalPortion Text to be checked
* @return bool True if local portion is valid, false if not
*/
protected function check_local_portion($strLocalPortion) {
// Local portion can only be from 1 to 64 characters, inclusive.
@ -113,8 +113,8 @@ class EmailAddressValidator {
/**
* Checks email section after "@" symbol for validity
* @param strDomainPortion Text to be checked
* @return True if domain portion is valid, false if not
* @param string $strDomainPortion Text to be checked
* @return bool True if domain portion is valid, false if not
*/
protected function check_domain_portion($strDomainPortion) {
// Total domain can only be from 1 to 255 characters, inclusive
@ -172,10 +172,10 @@ class EmailAddressValidator {
/**
* Check given text length is between defined bounds
* @param strText Text to be checked
* @param intMinimum Minimum acceptable length
* @param intMaximum Maximum acceptable length
* @return True if string is within bounds (inclusive), false if not
* @param string $strText Text to be checked
* @param int $intMinimum Minimum acceptable length
* @param int $intMaximum Maximum acceptable length
* @return bool True if string is within bounds (inclusive), false if not
*/
protected function check_text_length($strText, $intMinimum, $intMaximum) {
// Minimum and maximum are both inclusive

View File

@ -35,6 +35,19 @@ class DokuHTTPClient extends HTTPClient {
$this->proxy_pass = conf_decodeString($conf['proxy']['pass']);
$this->proxy_ssl = $conf['proxy']['ssl'];
$this->proxy_except = $conf['proxy']['except'];
// allow enabling debugging via URL parameter (if debugging allowed)
if($conf['allowdebug']) {
if(
isset($_REQUEST['httpdebug']) ||
(
isset($_SERVER['HTTP_REFERER']) &&
strpos($_SERVER['HTTP_REFERER'], 'httpdebug') !== false
)
) {
$this->debug = true;
}
}
}
@ -61,6 +74,9 @@ class DokuHTTPClient extends HTTPClient {
}
/**
* Class HTTPClientException
*/
class HTTPClientException extends Exception { }
/**
@ -249,12 +265,17 @@ class HTTPClient {
if (empty($port)) $port = 8080;
}else{
$request_url = $path;
$server = $server;
if (!isset($port)) $port = ($uri['scheme'] == 'https') ? 443 : 80;
}
// add SSL stream prefix if needed - needs SSL support in PHP
if($port == 443 || $this->proxy_ssl) $server = 'ssl://'.$server;
if($port == 443 || $this->proxy_ssl) {
if(!in_array('ssl', stream_get_transports())) {
$this->status = -200;
$this->error = 'This PHP version does not support SSL - cannot connect to server';
}
$server = 'ssl://'.$server;
}
// prepare headers
$headers = $this->headers;
@ -274,7 +295,6 @@ class HTTPClient {
}
}
$headers['Content-Length'] = strlen($data);
$rmethod = 'POST';
}elseif($method == 'GET'){
$data = ''; //no data allowed on GET requests
}
@ -304,11 +324,18 @@ class HTTPClient {
}
// try establish a CONNECT tunnel for SSL
if($this->_ssltunnel($socket, $request_url)){
// no keep alive for tunnels
$this->keep_alive = false;
// tunnel is authed already
if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']);
try {
if($this->_ssltunnel($socket, $request_url)){
// no keep alive for tunnels
$this->keep_alive = false;
// tunnel is authed already
if(isset($headers['Proxy-Authentication'])) unset($headers['Proxy-Authentication']);
}
} catch (HTTPClientException $e) {
$this->status = $e->getCode();
$this->error = $e->getMessage();
fclose($socket);
return false;
}
// keep alive?
@ -330,7 +357,7 @@ class HTTPClient {
try {
//set non-blocking
stream_set_blocking($socket, false);
stream_set_blocking($socket, 0);
// build request
$request = "$method $request_url HTTP/".$this->http.HTTP_NL;
@ -363,7 +390,7 @@ class HTTPClient {
// get Status
if (!preg_match('/^HTTP\/(\d\.\d)\s*(\d+).*?\n/', $r_headers, $m))
throw new HTTPClientException('Server returned bad answer');
throw new HTTPClientException('Server returned bad answer '.$r_headers);
$this->status = $m[2];
@ -445,7 +472,7 @@ class HTTPClient {
if ($chunk_size > 0) {
$r_body .= $this->_readData($socket, $chunk_size, 'chunk');
$byte = $this->_readData($socket, 2, 'chunk'); // read trailing \r\n
$this->_readData($socket, 2, 'chunk'); // read trailing \r\n
}
} while ($chunk_size && !$abort);
}elseif(isset($this->resp_headers['content-length']) && !isset($this->resp_headers['transfer-encoding'])){
@ -467,7 +494,6 @@ class HTTPClient {
$r_body = $this->_readData($socket, $this->max_bodysize, 'response (content-length limited)', true);
}else{
// read entire socket
$r_size = 0;
while (!feof($socket)) {
$r_body .= $this->_readData($socket, 4096, 'response (unlimited)', true);
}
@ -496,7 +522,6 @@ class HTTPClient {
if (!$this->keep_alive ||
(isset($this->resp_headers['connection']) && $this->resp_headers['connection'] == 'Close')) {
// close socket
$status = socket_get_status($socket);
fclose($socket);
unset(self::$connections[$connectionId]);
}
@ -526,6 +551,7 @@ class HTTPClient {
*
* @param resource &$socket
* @param string &$requesturl
* @throws HTTPClientException when a tunnel is needed but could not be established
* @return bool true if a tunnel was established
*/
function _ssltunnel(&$socket, &$requesturl){
@ -538,7 +564,7 @@ class HTTPClient {
$request = "CONNECT {$requestinfo['host']}:{$requestinfo['port']} HTTP/1.0".HTTP_NL;
$request .= "Host: {$requestinfo['host']}".HTTP_NL;
if($this->proxy_user) {
'Proxy-Authorization Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL;
$request .= 'Proxy-Authorization: Basic '.base64_encode($this->proxy_user.':'.$this->proxy_pass).HTTP_NL;
}
$request .= HTTP_NL;
@ -559,7 +585,8 @@ class HTTPClient {
return true;
}
}
return false;
throw new HTTPClientException('Failed to establish secure proxy connection', -150);
}
/**

View File

@ -15,6 +15,8 @@ class Input {
public $post;
/** @var GetInput Access $_GET parameters */
public $get;
/** @var ServerInput Access $_SERVER parameters */
public $server;
protected $access;
@ -25,6 +27,7 @@ class Input {
$this->access = &$_REQUEST;
$this->post = new PostInput();
$this->get = new GetInput();
$this->server = new ServerInput();
}
/**
@ -140,6 +143,26 @@ class Input {
return (string) $this->access[$name];
}
/**
* Access a request parameter and make sure it is has a valid value
*
* Please note that comparisons to the valid values are not done typesafe (request vars
* are always strings) however the function will return the correct type from the $valids
* array when an match was found.
*
* @param string $name Parameter name
* @param array $valids Array of valid values
* @param mixed $default Default to return if parameter isn't set or not valid
* @return null|mixed
*/
public function valid($name, $valids, $default = null) {
if(!isset($this->access[$name])) return $default;
if(is_array($this->access[$name])) return $default; // we don't allow arrays
$found = array_search($this->access[$name], $valids);
if($found !== false) return $valids[$found]; // return the valid value for type safety
return $default;
}
/**
* Access a request parameter as bool
*
@ -260,3 +283,18 @@ class GetInput extends Input {
$_REQUEST[$name] = $value;
}
}
/**
* Internal class used for $_SERVER access in Input class
*/
class ServerInput extends Input {
protected $access;
/**
* Initialize the $access array, remove subclass members
*/
function __construct() {
$this->access = &$_SERVER;
}
}

View File

@ -2929,7 +2929,8 @@ class JpegMeta {
$length = strlen($data) - $pos;
}
return substr($data, $pos, $length);
$rv = substr($data, $pos, $length);
return $rv;
}
/*************************************************************/

View File

@ -39,6 +39,8 @@ class Mailer {
*/
public function __construct() {
global $conf;
/* @var Input $INPUT */
global $INPUT;
$server = parse_url(DOKU_URL, PHP_URL_HOST);
if(strpos($server,'.') === false) $server = $server.'.localhost';
@ -53,7 +55,7 @@ class Mailer {
// add some default headers for mailfiltering FS#2247
$this->setHeader('X-Mailer', 'DokuWiki');
$this->setHeader('X-DokuWiki-User', $_SERVER['REMOTE_USER']);
$this->setHeader('X-DokuWiki-User', $INPUT->server->str('REMOTE_USER'));
$this->setHeader('X-DokuWiki-Title', $conf['title']);
$this->setHeader('X-DokuWiki-Server', $server);
$this->setHeader('X-Auto-Response-Suppress', 'OOF');
@ -181,6 +183,9 @@ class Mailer {
public function setBody($text, $textrep = null, $htmlrep = null, $html = null, $wrap = true) {
global $INFO;
global $conf;
/* @var Input $INPUT */
global $INPUT;
$htmlrep = (array)$htmlrep;
$textrep = (array)$textrep;
@ -218,24 +223,24 @@ class Mailer {
$cip = gethostsbyaddrs($ip);
$trep = array(
'DATE' => dformat(),
'BROWSER' => $_SERVER['HTTP_USER_AGENT'],
'BROWSER' => $INPUT->server->str('HTTP_USER_AGENT'),
'IPADDRESS' => $ip,
'HOSTNAME' => $cip,
'TITLE' => $conf['title'],
'DOKUWIKIURL' => DOKU_URL,
'USER' => $_SERVER['REMOTE_USER'],
'USER' => $INPUT->server->str('REMOTE_USER'),
'NAME' => $INFO['userinfo']['name'],
'MAIL' => $INFO['userinfo']['mail'],
);
$trep = array_merge($trep, (array)$textrep);
$hrep = array(
'DATE' => '<i>'.hsc(dformat()).'</i>',
'BROWSER' => hsc($_SERVER['HTTP_USER_AGENT']),
'BROWSER' => hsc($INPUT->server->str('HTTP_USER_AGENT')),
'IPADDRESS' => '<code>'.hsc($ip).'</code>',
'HOSTNAME' => '<code>'.hsc($cip).'</code>',
'TITLE' => hsc($conf['title']),
'DOKUWIKIURL' => '<a href="'.DOKU_URL.'">'.DOKU_URL.'</a>',
'USER' => hsc($_SERVER['REMOTE_USER']),
'USER' => hsc($INPUT->server->str('REMOTE_USER')),
'NAME' => hsc($INFO['userinfo']['name']),
'MAIL' => '<a href="mailto:"'.hsc($INFO['userinfo']['mail']).'">'.
hsc($INFO['userinfo']['mail']).'</a>',
@ -277,7 +282,7 @@ class Mailer {
/**
* Add the To: recipients
*
* @see setAddress
* @see cleanAddress
* @param string|array $address Multiple adresses separated by commas or as array
*/
public function to($address) {
@ -287,7 +292,7 @@ class Mailer {
/**
* Add the Cc: recipients
*
* @see setAddress
* @see cleanAddress
* @param string|array $address Multiple adresses separated by commas or as array
*/
public function cc($address) {
@ -297,7 +302,7 @@ class Mailer {
/**
* Add the Bcc: recipients
*
* @see setAddress
* @see cleanAddress
* @param string|array $address Multiple adresses separated by commas or as array
*/
public function bcc($address) {
@ -310,7 +315,7 @@ class Mailer {
* This is set to $conf['mailfrom'] when not specified so you shouldn't need
* to call this function
*
* @see setAddress
* @see cleanAddress
* @param string $address from address
*/
public function from($address) {
@ -333,9 +338,9 @@ class Mailer {
* for headers. Addresses may not contain Non-ASCII data!
*
* Example:
* setAddress("föö <foo@bar.com>, me@somewhere.com","TBcc");
* cc("föö <foo@bar.com>, me@somewhere.com","TBcc");
*
* @param string|array $address Multiple adresses separated by commas or as array
* @param string|array $addresses Multiple adresses separated by commas or as array
* @return bool|string the prepared header (can contain multiple lines)
*/
public function cleanAddress($addresses) {
@ -522,7 +527,7 @@ class Mailer {
// clean up addresses
if(empty($this->headers['From'])) $this->from($conf['mailfrom']);
$addrs = array('To', 'From', 'Cc', 'Bcc');
$addrs = array('To', 'From', 'Cc', 'Bcc', 'Reply-To', 'Sender');
foreach($addrs as $addr) {
if(isset($this->headers[$addr])) {
$this->headers[$addr] = $this->cleanAddress($this->headers[$addr]);

View File

@ -378,7 +378,8 @@ class RemoteAPICore {
throw new RemoteException('The requested page does not exist', 121);
}
$info = getRevisionInfo($id, $time, 1024);
$pagelog = new PageChangeLog($id, 1024);
$info = $pagelog->getRevisionInfo($time);
$data = array(
'name' => $id,
@ -650,11 +651,12 @@ class RemoteAPICore {
throw new RemoteException('Empty page ID', 131);
}
$revisions = getRevisions($id, $first, $conf['recent']+1);
$pagelog = new PageChangeLog($id);
$revisions = $pagelog->getRevisions($first, $conf['recent']+1);
if(count($revisions)==0 && $first!=0) {
$first=0;
$revisions = getRevisions($id, $first, $conf['recent']+1);
$revisions = $pagelog->getRevisions($first, $conf['recent']+1);
}
if(count($revisions)>0 && $first==0) {
@ -676,7 +678,8 @@ class RemoteAPICore {
// case this can lead to less pages being returned than
// specified via $conf['recent']
if($time){
$info = getRevisionInfo($id, $time, 1024);
$pagelog->setChunkSize(1024);
$info = $pagelog->getRevisionInfo($time);
if(!empty($info)) {
$data['user'] = $info['user'];
$data['ip'] = $info['ip'];

View File

@ -131,9 +131,9 @@ class Sitemapper {
$encoded_sitemap_url = urlencode(wl('', array('do' => 'sitemap'), true, '&'));
$ping_urls = array(
'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap='.$encoded_sitemap_url,
'yahoo' => 'http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=dokuwiki&url='.$encoded_sitemap_url,
'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap='.$encoded_sitemap_url,
'microsoft' => 'http://www.bing.com/webmaster/ping.aspx?siteMap='.$encoded_sitemap_url,
'yandex' => 'http://blogs.yandex.ru/pings/?status=success&url='.$encoded_sitemap_url
);
$data = array('ping_urls' => $ping_urls,

View File

@ -26,6 +26,8 @@ class TarLib {
public $_result = true;
function __construct($file, $comptype = TarLib::COMPRESS_AUTO, $complevel = 9) {
dbg_deprecated('class Tar');
if(!$file) $this->error('__construct', '$file');
$this->file = $file;

View File

@ -20,6 +20,7 @@ function act_dispatch(){
global $ID;
global $INFO;
global $QUERY;
/* @var Input $INPUT */
global $INPUT;
global $lang;
global $conf;
@ -94,7 +95,7 @@ function act_dispatch(){
// user profile changes
if (in_array($ACT, array('profile','profile_delete'))) {
if(!$_SERVER['REMOTE_USER']) {
if(!$INPUT->server->str('REMOTE_USER')) {
$ACT = 'login';
} else {
switch ($ACT) {
@ -190,7 +191,7 @@ function act_dispatch(){
unset($evt);
// when action 'show', the intial not 'show' and POST, do a redirect
if($ACT == 'show' && $preact != 'show' && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){
if($ACT == 'show' && $preact != 'show' && strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post'){
act_redirect($ID,$preact);
}
@ -414,6 +415,8 @@ function act_revert($act){
global $ID;
global $REV;
global $lang;
/* @var Input $INPUT */
global $INPUT;
// FIXME $INFO['writable'] currently refers to the attic version
// global $INFO;
// if (!$INFO['writable']) {
@ -445,7 +448,7 @@ function act_revert($act){
session_write_close();
// when done, show current page
$_SERVER['REQUEST_METHOD'] = 'post'; //should force a redirect
$INPUT->server->set('REQUEST_METHOD','post'); //should force a redirect
$REV = '';
return 'show';
}
@ -493,17 +496,20 @@ function act_redirect_execute($opts){
function act_auth($act){
global $ID;
global $INFO;
/* @var Input $INPUT */
global $INPUT;
//already logged in?
if(isset($_SERVER['REMOTE_USER']) && $act=='login'){
if($INPUT->server->has('REMOTE_USER') && $act=='login'){
return 'show';
}
//handle logout
if($act=='logout'){
$lockedby = checklock($ID); //page still locked?
if($lockedby == $_SERVER['REMOTE_USER'])
if($lockedby == $INPUT->server->str('REMOTE_USER')){
unlock($ID); //try to unlock
}
// do the logout stuff
auth_logoff();
@ -697,7 +703,7 @@ function act_sitemap($act) {
// Send file
//use x-sendfile header to pass the delivery to compatible webservers
if (http_sendfile($sitemap)) exit;
http_sendfile($sitemap);
readfile($sitemap);
exit;
@ -719,10 +725,11 @@ function act_subscription($act){
global $lang;
global $INFO;
global $ID;
/* @var Input $INPUT */
global $INPUT;
// subcriptions work for logged in users only
if(!$_SERVER['REMOTE_USER']) return 'show';
if(!$INPUT->server->str('REMOTE_USER')) return 'show';
// get and preprocess data.
$params = array();
@ -733,7 +740,7 @@ function act_subscription($act){
}
// any action given? if not just return and show the subscription page
if(!$params['action'] || !checkSecurityToken()) return $act;
if(empty($params['action']) || !checkSecurityToken()) return $act;
// Handle POST data, may throw exception.
trigger_event('ACTION_HANDLE_SUBSCRIBE', $params, 'subscription_handle_post');
@ -745,9 +752,9 @@ function act_subscription($act){
// Perform action.
$sub = new Subscription();
if($action == 'unsubscribe'){
$ok = $sub->remove($target, $_SERVER['REMOTE_USER'], $style);
$ok = $sub->remove($target, $INPUT->server->str('REMOTE_USER'), $style);
}else{
$ok = $sub->add($target, $_SERVER['REMOTE_USER'], $style);
$ok = $sub->add($target, $INPUT->server->str('REMOTE_USER'), $style);
}
if($ok) {
@ -776,6 +783,8 @@ function act_subscription($act){
function subscription_handle_post(&$params) {
global $INFO;
global $lang;
/* @var Input $INPUT */
global $INPUT;
// Get and validate parameters.
if (!isset($params['target'])) {
@ -806,7 +815,7 @@ function subscription_handle_post(&$params) {
}
if ($is === false) {
throw new Exception(sprintf($lang['subscr_not_subscribed'],
$_SERVER['REMOTE_USER'],
$INPUT->server->str('REMOTE_USER'),
prettyprint_id($target)));
}
// subscription_set deletes a subscription if style = null.

View File

@ -131,6 +131,8 @@ function auth_setup() {
function auth_loadACL() {
global $config_cascade;
global $USERINFO;
/* @var Input $INPUT */
global $INPUT;
if(!is_readable($config_cascade['acl']['default'])) return array();
@ -145,10 +147,10 @@ function auth_loadACL() {
// substitute user wildcard first (its 1:1)
if(strstr($line, '%USER%')){
// if user is not logged in, this ACL line is meaningless - skip it
if (!isset($_SERVER['REMOTE_USER'])) continue;
if (!$INPUT->server->has('REMOTE_USER')) continue;
$id = str_replace('%USER%',cleanID($_SERVER['REMOTE_USER']),$id);
$rest = str_replace('%USER%',auth_nameencode($_SERVER['REMOTE_USER']),$rest);
$id = str_replace('%USER%',cleanID($INPUT->server->str('REMOTE_USER')),$id);
$rest = str_replace('%USER%',auth_nameencode($INPUT->server->str('REMOTE_USER')),$rest);
}
// substitute group wildcard (its 1:m)
@ -217,6 +219,8 @@ function auth_login($user, $pass, $sticky = false, $silent = false) {
global $lang;
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
/* @var Input $INPUT */
global $INPUT;
$sticky ? $sticky = true : $sticky = false; //sanity check
@ -226,7 +230,7 @@ function auth_login($user, $pass, $sticky = false, $silent = false) {
//usual login
if($auth->checkPass($user, $pass)) {
// make logininfo globally available
$_SERVER['REMOTE_USER'] = $user;
$INPUT->server->set('REMOTE_USER', $user);
$secret = auth_cookiesalt(!$sticky, true); //bind non-sticky to session
auth_setCookie($user, auth_encrypt($pass, $secret), $sticky);
return true;
@ -253,7 +257,7 @@ function auth_login($user, $pass, $sticky = false, $silent = false) {
) {
// he has session, cookie and browser right - let him in
$_SERVER['REMOTE_USER'] = $user;
$INPUT->server->set('REMOTE_USER', $user);
$USERINFO = $session['info']; //FIXME move all references to session
return true;
}
@ -288,7 +292,10 @@ function auth_validateToken($token) {
}
// still here? trust the session data
global $USERINFO;
$_SERVER['REMOTE_USER'] = $_SESSION[DOKU_COOKIE]['auth']['user'];
/* @var Input $INPUT */
global $INPUT;
$INPUT->server->set('REMOTE_USER',$_SESSION[DOKU_COOKIE]['auth']['user']);
$USERINFO = $_SESSION[DOKU_COOKIE]['auth']['info'];
return true;
}
@ -321,11 +328,14 @@ function auth_createToken() {
* @return string a MD5 sum of various browser headers
*/
function auth_browseruid() {
/* @var Input $INPUT */
global $INPUT;
$ip = clientIP(true);
$uid = '';
$uid .= $_SERVER['HTTP_USER_AGENT'];
$uid .= $_SERVER['HTTP_ACCEPT_ENCODING'];
$uid .= $_SERVER['HTTP_ACCEPT_CHARSET'];
$uid .= $INPUT->server->str('HTTP_USER_AGENT');
$uid .= $INPUT->server->str('HTTP_ACCEPT_ENCODING');
$uid .= $INPUT->server->str('HTTP_ACCEPT_CHARSET');
$uid .= substr($ip, 0, strpos($ip, '.'));
$uid = strtolower($uid);
return md5($uid);
@ -511,6 +521,8 @@ function auth_logoff($keepbc = false) {
global $USERINFO;
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
/* @var Input $INPUT */
global $INPUT;
// make sure the session is writable (it usually is)
@session_start();
@ -523,16 +535,11 @@ function auth_logoff($keepbc = false) {
unset($_SESSION[DOKU_COOKIE]['auth']['info']);
if(!$keepbc && isset($_SESSION[DOKU_COOKIE]['bc']))
unset($_SESSION[DOKU_COOKIE]['bc']);
if(isset($_SERVER['REMOTE_USER']))
unset($_SERVER['REMOTE_USER']);
$INPUT->server->remove('REMOTE_USER');
$USERINFO = null; //FIXME
$cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
if(version_compare(PHP_VERSION, '5.2.0', '>')) {
setcookie(DOKU_COOKIE, '', time() - 600000, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true);
} else {
setcookie(DOKU_COOKIE, '', time() - 600000, $cookieDir, '', ($conf['securecookie'] && is_ssl()));
}
setcookie(DOKU_COOKIE, '', time() - 600000, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true);
if($auth) $auth->logOff();
}
@ -557,13 +564,16 @@ function auth_ismanager($user = null, $groups = null, $adminonly = false) {
global $USERINFO;
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
/* @var Input $INPUT */
global $INPUT;
if(!$auth) return false;
if(is_null($user)) {
if(!isset($_SERVER['REMOTE_USER'])) {
if(!$INPUT->server->has('REMOTE_USER')) {
return false;
} else {
$user = $_SERVER['REMOTE_USER'];
$user = $INPUT->server->str('REMOTE_USER');
}
}
if(is_null($groups)) {
@ -655,9 +665,11 @@ function auth_isMember($memberlist, $user, array $groups) {
function auth_quickaclcheck($id) {
global $conf;
global $USERINFO;
/* @var Input $INPUT */
global $INPUT;
# if no ACL is used always return upload rights
if(!$conf['useacl']) return AUTH_UPLOAD;
return auth_aclcheck($id, $_SERVER['REMOTE_USER'], $USERINFO['grps']);
return auth_aclcheck($id, $INPUT->server->str('REMOTE_USER'), $USERINFO['grps']);
}
/**
@ -845,6 +857,12 @@ function auth_nameencode($name, $skip_group = false) {
return $cache[$name][$skip_group];
}
/**
* callback encodes the matches
*
* @param array $matches first complete match, next matching subpatterms
* @return string
*/
function auth_nameencode_callback($matches) {
return '%'.dechex(ord(substr($matches[1],-1)));
}
@ -1056,18 +1074,18 @@ function updateprofile() {
}
if($conf['profileconfirm']) {
if(!$auth->checkPass($_SERVER['REMOTE_USER'], $INPUT->post->str('oldpass'))) {
if(!$auth->checkPass($INPUT->server->str('REMOTE_USER'), $INPUT->post->str('oldpass'))) {
msg($lang['badpassconfirm'], -1);
return false;
}
}
if($result = $auth->triggerUserMod('modify', array($_SERVER['REMOTE_USER'], $changes))) {
if($result = $auth->triggerUserMod('modify', array($INPUT->server->str('REMOTE_USER'), $changes))) {
// update cookie and session with the changed data
if($changes['pass']) {
list( /*user*/, $sticky, /*pass*/) = auth_getCookie();
$pass = auth_encrypt($changes['pass'], auth_cookiesalt(!$sticky, true));
auth_setCookie($_SERVER['REMOTE_USER'], $pass, (bool) $sticky);
auth_setCookie($INPUT->server->str('REMOTE_USER'), $pass, (bool) $sticky);
}
return true;
}
@ -1075,6 +1093,11 @@ function updateprofile() {
return false;
}
/**
* Delete the current logged-in user
*
* @return bool true on success, false on any error
*/
function auth_deleteprofile(){
global $conf;
global $lang;
@ -1098,13 +1121,13 @@ function auth_deleteprofile(){
}
if($conf['profileconfirm']) {
if(!$auth->checkPass($_SERVER['REMOTE_USER'], $INPUT->post->str('oldpass'))) {
if(!$auth->checkPass($INPUT->server->str('REMOTE_USER'), $INPUT->post->str('oldpass'))) {
msg($lang['badpassconfirm'], -1);
return false;
}
}
$deleted[] = $_SERVER['REMOTE_USER'];
$deleted[] = $INPUT->server->str('REMOTE_USER');
if($auth->triggerUserMod('delete', array($deleted))) {
// force and immediate logout including removing the sticky cookie
auth_logoff();
@ -1308,11 +1331,8 @@ function auth_setCookie($user, $pass, $sticky) {
$cookie = base64_encode($user).'|'.((int) $sticky).'|'.base64_encode($pass);
$cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
$time = $sticky ? (time() + 60 * 60 * 24 * 365) : 0; //one year
if(version_compare(PHP_VERSION, '5.2.0', '>')) {
setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true);
} else {
setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()));
}
setcookie(DOKU_COOKIE, $cookie, $time, $cookieDir, '', ($conf['securecookie'] && is_ssl()), true);
// set session
$_SESSION[DOKU_COOKIE]['auth']['user'] = $user;
$_SESSION[DOKU_COOKIE]['auth']['pass'] = sha1($pass);

View File

@ -8,16 +8,25 @@
if(!defined('DOKU_INC')) die('meh.');
/**
* Generic handling of caching
*/
class cache {
var $key = ''; // primary identifier for this item
var $ext = ''; // file ext for cache data, secondary identifier for this item
var $cache = ''; // cache file name
var $depends = array(); // array containing cache dependency information,
// used by _useCache to determine cache validity
public $key = ''; // primary identifier for this item
public $ext = ''; // file ext for cache data, secondary identifier for this item
public $cache = ''; // cache file name
public $depends = array(); // array containing cache dependency information,
// used by _useCache to determine cache validity
var $_event = ''; // event to be triggered during useCache
var $_time;
var $_nocache = false; // if set to true, cache will not be used or stored
function cache($key,$ext) {
/**
* @param string $key primary identifier
* @param string $ext file extension
*/
public function cache($key,$ext) {
$this->key = $key;
$this->ext = $ext;
$this->cache = getCacheName($key,$ext);
@ -26,7 +35,7 @@ class cache {
/**
* public method to determine whether the cache can be used
*
* to assist in cetralisation of event triggering and calculation of cache statistics,
* to assist in centralisation of event triggering and calculation of cache statistics,
* don't override this function override _useCache()
*
* @param array $depends array of cache dependencies, support dependecies:
@ -36,7 +45,7 @@ class cache {
*
* @return bool true if cache can be used, false otherwise
*/
function useCache($depends=array()) {
public function useCache($depends=array()) {
$this->depends = $depends;
$this->_addDependencies();
@ -55,12 +64,15 @@ class cache {
* age - expire cache if older than age (seconds)
* files - expire cache if any file in this array was updated more recently than the cache
*
* Note that this function needs to be public as it is used as callback for the event handler
*
* can be overridden
*
* @return bool see useCache()
*/
function _useCache() {
public function _useCache() {
if ($this->_nocache) return false; // caching turned off
if (!empty($this->depends['purge'])) return false; // purge requested?
if (!($this->_time = @filemtime($this->cache))) return false; // cache exists?
@ -83,7 +95,7 @@ class cache {
* it should not remove any existing dependencies and
* it should only overwrite a dependency when the new value is more stringent than the old
*/
function _addDependencies() {
protected function _addDependencies() {
global $INPUT;
if ($INPUT->has('purge')) $this->depends['purge'] = true; // purge requested
}
@ -94,7 +106,7 @@ class cache {
* @param bool $clean true to clean line endings, false to leave line endings alone
* @return string cache contents
*/
function retrieveCache($clean=true) {
public function retrieveCache($clean=true) {
return io_readFile($this->cache, $clean);
}
@ -104,14 +116,16 @@ class cache {
* @param string $data the data to be cached
* @return bool true on success, false otherwise
*/
function storeCache($data) {
public function storeCache($data) {
if ($this->_nocache) return false;
return io_savefile($this->cache, $data);
}
/**
* remove any cached data associated with this cache instance
*/
function removeCache() {
public function removeCache() {
@unlink($this->cache);
}
@ -122,7 +136,7 @@ class cache {
* @param bool $success result of this cache use attempt
* @return bool pass-thru $success value
*/
function _stats($success) {
protected function _stats($success) {
global $conf;
static $stats = null;
static $file;
@ -157,14 +171,24 @@ class cache {
}
}
/**
* Parser caching
*/
class cache_parser extends cache {
var $file = ''; // source file for cache
var $mode = ''; // input mode (represents the processing the input file will undergo)
public $file = ''; // source file for cache
public $mode = ''; // input mode (represents the processing the input file will undergo)
public $page = '';
var $_event = 'PARSER_CACHE_USE';
function cache_parser($id, $file, $mode) {
/**
*
* @param string $id page id
* @param string $file source file for cache
* @param string $mode input mode
*/
public function cache_parser($id, $file, $mode) {
if ($id) $this->page = $id;
$this->file = $file;
$this->mode = $mode;
@ -172,24 +196,25 @@ class cache_parser extends cache {
parent::cache($file.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.'.$mode);
}
function _useCache() {
/**
* method contains cache use decision logic
*
* @return bool see useCache()
*/
public function _useCache() {
if (!@file_exists($this->file)) return false; // source exists?
return parent::_useCache();
}
function _addDependencies() {
global $conf, $config_cascade;
$this->depends['age'] = isset($this->depends['age']) ?
min($this->depends['age'],$conf['cachetime']) : $conf['cachetime'];
protected function _addDependencies() {
// parser cache file dependencies ...
$files = array($this->file, // ... source
$files = array($this->file, // ... source
DOKU_INC.'inc/parser/parser.php', // ... parser
DOKU_INC.'inc/parser/handler.php', // ... handler
);
$files = array_merge($files, getConfigFiles('main')); // ... wiki settings
$files = array_merge($files, getConfigFiles('main')); // ... wiki settings
$this->depends['files'] = !empty($this->depends['files']) ? array_merge($files, $this->depends['files']) : $files;
parent::_addDependencies();
@ -197,8 +222,17 @@ class cache_parser extends cache {
}
/**
* Caching of data of renderer
*/
class cache_renderer extends cache_parser {
function _useCache() {
/**
* method contains cache use decision logic
*
* @return bool see useCache()
*/
public function _useCache() {
global $conf;
if (!parent::_useCache()) return false;
@ -231,7 +265,19 @@ class cache_renderer extends cache_parser {
return true;
}
function _addDependencies() {
protected function _addDependencies() {
global $conf;
// default renderer cache file 'age' is dependent on 'cachetime' setting, two special values:
// -1 : do not cache (should not be overridden)
// 0 : cache never expires (can be overridden) - no need to set depends['age']
if ($conf['cachetime'] == -1) {
$this->_nocache = true;
return;
} elseif ($conf['cachetime'] > 0) {
$this->depends['age'] = isset($this->depends['age']) ?
min($this->depends['age'],$conf['cachetime']) : $conf['cachetime'];
}
// renderer cache file dependencies ...
$files = array(
@ -253,18 +299,39 @@ class cache_renderer extends cache_parser {
}
}
/**
* Caching of parser instructions
*/
class cache_instructions extends cache_parser {
function cache_instructions($id, $file) {
/**
* @param string $id page id
* @param string $file source file for cache
*/
public function cache_instructions($id, $file) {
parent::cache_parser($id, $file, 'i');
}
function retrieveCache($clean=true) {
/**
* retrieve the cached data
*
* @param bool $clean true to clean line endings, false to leave line endings alone
* @return string cache contents
*/
public function retrieveCache($clean=true) {
$contents = io_readFile($this->cache, false);
return !empty($contents) ? unserialize($contents) : array();
}
function storeCache($instructions) {
/**
* cache $instructions
*
* @param string $instructions the instruction to be cached
* @return bool true on success, false otherwise
*/
public function storeCache($instructions) {
if ($this->_nocache) return false;
return io_savefile($this->cache,serialize($instructions));
}
}

View File

@ -18,6 +18,9 @@ define('DOKU_CHANGE_TYPE_REVERT', 'R');
* 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
*/
function parseChangelogLine($line) {
$tmp = explode("\t", $line);
@ -43,7 +46,7 @@ function parseChangelogLine($line) {
* @param String $summary Summary of the change
* @param mixed $extra In case of a revert the revision (timestmp) of the reverted page
* @param array $flags Additional flags in a key value array.
* Availible flags:
* Available flags:
* - ExternalEdit - mark as an external edit.
*
* @author Andreas Gohr <andi@splitbrain.org>
@ -52,6 +55,8 @@ function parseChangelogLine($line) {
*/
function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null){
global $conf, $INFO;
/** @var Input $INPUT */
global $INPUT;
// check for special flags as keys
if (!is_array($flags)) { $flags = array(); }
@ -65,7 +70,7 @@ function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extr
if(!$date) $date = time(); //use current time if none supplied
$remote = (!$flagExternalEdit)?clientIP(true):'127.0.0.1';
$user = (!$flagExternalEdit)?$_SERVER['REMOTE_USER']:'';
$user = (!$flagExternalEdit)?$INPUT->server->str('REMOTE_USER'):'';
$strip = array("\t", "\n");
$logline = array(
@ -114,15 +119,26 @@ function addLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extr
* @author Andreas Gohr <andi@splitbrain.org>
* @author Esther Brunner <wikidesign@gmail.com>
* @author Ben Coburn <btcoburn@silicodon.net>
*
* @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_*
* @param String $summary Summary of the change
* @param mixed $extra In case of a revert the revision (timestmp) of the reverted page
* @param array $flags Additional flags in a key value array.
* Available flags:
* - (none, so far)
*/
function addMediaLogEntry($date, $id, $type=DOKU_CHANGE_TYPE_EDIT, $summary='', $extra='', $flags=null){
global $conf;
/** @var Input $INPUT */
global $INPUT;
$id = cleanid($id);
if(!$date) $date = time(); //use current time if none supplied
$remote = clientIP(true);
$user = $_SERVER['REMOTE_USER'];
$user = $INPUT->server->str('REMOTE_USER');
$strip = array("\t", "\n");
$logline = array(
@ -290,6 +306,12 @@ function getRecentsSince($from,$to=null,$ns='',$flags=0){
* @see getRecents()
* @author Andreas Gohr <andi@splitbrain.org>
* @author Ben Coburn <btcoburn@silicodon.net>
*
* @param string $line changelog line
* @param string $ns restrict to given namespace
* @param int $flags flags to control which changes are included
* @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
@ -333,6 +355,665 @@ function _handleRecent($line,$ns,$flags,&$seen){
return $recent;
}
/**
* Class ChangeLog
* methods for handling of changelog of pages or media files
*/
abstract class ChangeLog {
/** @var string */
protected $id;
/** @var int */
protected $chunk_size;
/** @var array */
protected $cache;
/**
* Constructor
*
* @param string $id page id
* @param int $chunk_size maximum block size read from file
*/
public function __construct($id, $chunk_size = 8192) {
global $cache_revinfo;
$this->cache =& $cache_revinfo;
if(!isset($this->cache[$id])) {
$this->cache[$id] = array();
}
$this->id = $id;
$this->setChunkSize($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 path to changelog
*
* @return string path to file
*/
abstract protected function getChangelogFilename();
/**
* Returns path to current page/media
*
* @return string path to file
*/
abstract protected function getFilename();
/**
* Get the changelog information for a specific page id and 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
* @return bool|array false or array with entries:
* - date: unix timestamp
* - ip: IPv4 address (127.0.0.1)
* - type: log line type
* - id: page id
* - user: user name
* - sum: edit summary (or action reason)
* - extra: extra data (varies by line type)
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
public function getRevisionInfo($rev) {
$rev = max($rev, 0);
// check if it's already in the memory cache
if(isset($this->cache[$this->id]) && isset($this->cache[$this->id][$rev])) {
return $this->cache[$this->id][$rev];
}
//read lines from changelog
list($fp, $lines) = $this->readloglines($rev);
if($fp) {
fclose($fp);
}
if(empty($lines)) return false;
// parse and cache changelog lines
foreach($lines as $value) {
$tmp = parseChangelogLine($value);
if($tmp !== false) {
$this->cache[$this->id][$tmp['date']] = $tmp;
}
}
if(!isset($this->cache[$this->id][$rev])) {
return false;
}
return $this->cache[$this->id][$rev];
}
/**
* Return a list of page revisions numbers
*
* Does not guarantee that the revision exists in the attic,
* only that a line with the date exists in the changelog.
* By default the current revision is skipped.
*
* The current revision is automatically skipped when the page exists.
* See $INFO['meta']['last_change'] for the current revision.
* A negative $first let read the current revision too.
*
* For efficiency, the log lines are parsed and cached for later
* calls to getRevisionInfo. Large changelog files are read
* backwards in chunks until the requested number of changelog
* lines are recieved.
*
* @param int $first skip the first n changelog lines
* @param int $num number of revisions to return
* @return array with the revision timestamps
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
public function getRevisions($first, $num) {
$revs = array();
$lines = array();
$count = 0;
$num = max($num, 0);
if($num == 0) {
return $revs;
}
if($first < 0) {
$first = 0;
} else if(@file_exists($this->getFilename())) {
// skip current 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) {
// read whole file
$lines = file($file);
if($lines === false) {
return $revs;
}
} else {
// read chunks backwards
$fp = fopen($file, 'rb'); // "file pointer"
if($fp === false) {
return $revs;
}
fseek($fp, 0, SEEK_END);
$tail = ftell($fp);
// chunk backwards
$finger = max($tail - $this->chunk_size, 0);
while($count < $num + $first) {
$nl = $this->getNewlinepointer($fp, $finger);
// was the chunk big enough? if not, take another bite
if($nl > 0 && $tail <= $nl) {
$finger = max($finger - $this->chunk_size, 0);
continue;
} else {
$finger = $nl;
}
// read chunk
$chunk = '';
$read_size = max($tail - $finger, 0); // found chunk size
$got = 0;
while($got < $read_size && !feof($fp)) {
$tmp = @fread($fp, max(min($this->chunk_size, $read_size - $got), 0));
if($tmp === false) {
break;
} //error state
$got += strlen($tmp);
$chunk .= $tmp;
}
$tmp = explode("\n", $chunk);
array_pop($tmp); // remove trailing newline
// combine with previous chunk
$count += count($tmp);
$lines = array_merge($tmp, $lines);
// next chunk
if($finger == 0) {
break;
} // already read all the lines
else {
$tail = $finger;
$finger = max($tail - $this->chunk_size, 0);
}
}
fclose($fp);
}
// skip parsing extra lines
$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)); }
else if($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'];
}
}
return $revs;
}
/**
* Get the nth revision left or right handside for a specific page id and revision (timestamp)
*
* For large changelog files, only the chunk containing the
* reference revision $rev is read and sometimes a next chunck.
*
* 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
* @return bool|int
* timestamp of the requested revision
* otherwise false
*/
public function getRelativeRevision($rev, $direction) {
$rev = max($rev, 0);
$direction = (int) $direction;
//no direction given or last rev, so no follow-up
if(!$direction || ($direction > 0 && $this->isCurrentRevision($rev))) {
return false;
}
//get lines from 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
// also parse and cache changelog lines for getRevisionInfo().
$revcounter = 0;
$relativerev = false;
$checkotherchunck = true; //always runs once
while(!$relativerev && $checkotherchunck) {
$tmp = array();
//parse in normal or reverse order
$count = count($lines);
if($direction > 0) {
$start = 0;
$step = 1;
} else {
$start = $count - 1;
$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;
//look for revs older/earlier then reference $rev and select $direction-th one
if(($direction > 0 && $tmp['date'] > $rev) || ($direction < 0 && $tmp['date'] < $rev)) {
$revcounter++;
if($revcounter == abs($direction)) {
$relativerev = $tmp['date'];
}
}
}
}
//true when $rev is found, but not the wanted follow-up.
$checkotherchunck = $fp
&& ($tmp['date'] == $rev || ($revcounter > 0 && !$relativerev))
&& !(($tail == $eof && $direction > 0) || ($head == 0 && $direction < 0));
if($checkotherchunck) {
list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, $direction);
if(empty($lines)) break;
}
}
if($fp) {
fclose($fp);
}
return $relativerev;
}
/**
* Returns revisions around rev1 and rev2
* When available it returns $max entries for each revision
*
* @param int $rev1 oldest revision timestamp
* @param int $rev2 newest revision timestamp (0 looks up last revision)
* @param int $max maximum number of revisions returned
* @return array with two arrays with revisions surrounding rev1 respectively rev2
*/
public function getRevisionsAround($rev1, $rev2, $max = 50) {
$max = floor(abs($max) / 2)*2 + 1;
$rev1 = max($rev1, 0);
$rev2 = max($rev2, 0);
if($rev2) {
if($rev2 < $rev1) {
$rev = $rev2;
$rev2 = $rev1;
$rev1 = $rev;
}
} else {
//empty right side means a removed page. Look up last revision.
$revs = $this->getRevisions(-1, 1);
$rev2 = $revs[0];
}
//collect revisions around rev2
list($revs2, $allrevs, $fp, $lines, $head, $tail) = $this->retrieveRevisionsAround($rev2, $max);
if(empty($revs2)) return array(array(), array());
//collect revisions around rev1
$index = array_search($rev1, $allrevs);
if($index === false) {
//no overlapping revisions
list($revs1,,,,,) = $this->retrieveRevisionsAround($rev1, $max);
if(empty($revs1)) $revs1 = array();
} else {
//revisions overlaps, reuse revisions around rev2
$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'];
$index++;
if($index > floor($max / 2)) break 2;
}
}
list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1);
}
sort($revs1);
//return wanted selection
$revs1 = array_slice($revs1, max($index - floor($max/2), 0), $max);
}
return array(array_reverse($revs1), array_reverse($revs2));
}
/**
* Returns lines from changelog.
* If file larger than $chuncksize, only chunck is read that could contain $rev.
*
* @param int $rev revision timestamp
* @return array(fp, array(changeloglines), $head, $tail, $eof)|bool
* returns false when not succeed. fp only defined for chuck reading, needs closing.
*/
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());
}
/**
* 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
*
* @param int $rev revision timestamp
* @param int $max maximum number of revisions to be returned
* @return bool|array
* return array with entries:
* - $requestedrevs: array of with $max revision timestamps
* - $revs: all parsed revision timestamps
* - $fp: filepointer only defined for chuck reading, needs closing.
* - $lines: non-parsed changelog lines before the parsed revisions
* - $head: position of first readed changelogline
* - $lasttail: position of end of last readed changelogline
* otherwise false
*/
protected function retrieveRevisionsAround($rev, $max) {
//get lines from changelog
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
$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) {
//count revs after reference $rev
$aftercount++;
if($aftercount == 1) $beforecount = count($revs);
}
//enough revs after reference $rev?
if($aftercount > floor($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
$lines = array();
$i = 0;
if($aftercount > 0) {
$head = $starthead;
$tail = $starttail;
while($head > 0) {
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'];
$beforecount++;
//enough revs before reference $rev?
if($beforecount > max(floor($max / 2), $max - $aftercount)) break 2;
}
}
}
}
sort($revs);
//keep only non-parsed lines
$lines = array_slice($lines, 0, $i);
//trunk desired selection
$requestedrevs = array_slice($revs, -$max, $max);
return array($requestedrevs, $revs, $fp, $lines, $head, $lasttail);
}
}
/**
* Class PageChangelog handles changelog of a wiki page
*/
class PageChangelog extends ChangeLog {
/**
* Returns path to changelog
*
* @return string path to file
*/
protected function getChangelogFilename() {
return metaFN($this->id, '.changes');
}
/**
* Returns path to current page/media
*
* @return string path to file
*/
protected function getFilename() {
return wikiFN($this->id);
}
}
/**
* Class MediaChangelog handles changelog of a media file
*/
class MediaChangelog extends ChangeLog {
/**
* Returns path to changelog
*
* @return string path to file
*/
protected function getChangelogFilename() {
return mediaMetaFN($this->id, '.changes');
}
/**
* Returns path to current page/media
*
* @return string path to file
*/
protected function getFilename() {
return mediaFN($this->id);
}
}
/**
* Get the changelog information for a specific page id
* and revision (timestamp). Adjacent changelog lines
@ -341,88 +1022,19 @@ function _handleRecent($line,$ns,$flags,&$seen){
* changelog files, only the chunk containing the
* requested changelog line is read.
*
* @deprecated 2013-11-20
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*/
function getRevisionInfo($id, $rev, $chunk_size=8192, $media=false) {
global $cache_revinfo;
$cache =& $cache_revinfo;
if (!isset($cache[$id])) { $cache[$id] = array(); }
$rev = max($rev, 0);
// check if it's already in the memory cache
if (isset($cache[$id]) && isset($cache[$id][$rev])) {
return $cache[$id][$rev];
}
if ($media) {
$file = mediaMetaFN($id, '.changes');
function getRevisionInfo($id, $rev, $chunk_size = 8192, $media = false) {
dbg_deprecated('class PageChangeLog or class MediaChangelog');
if($media) {
$changelog = new MediaChangeLog($id, $chunk_size);
} else {
$file = metaFN($id, '.changes');
$changelog = new PageChangeLog($id, $chunk_size);
}
if (!@file_exists($file)) { return false; }
if (filesize($file)<$chunk_size || $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);
$tail = ftell($fp);
$finger = 0;
$finger_rev = 0;
// find chunk
while ($tail-$head>$chunk_size) {
$finger = $head+floor(($tail-$head)/2.0);
fseek($fp, $finger);
fgets($fp); // slip the finger forward to a new line
$finger = ftell($fp);
$tmp = fgets($fp); // then read at that location
$tmp = parseChangelogLine($tmp);
$finger_rev = $tmp['date'];
if ($finger==$head || $finger==$tail) { break; }
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;
}
// read chunk
$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($chunk_size-$got, 0));
if ($tmp===false) { break; } //error state
$got += strlen($tmp);
$chunk .= $tmp;
}
$lines = explode("\n", $chunk);
array_pop($lines); // remove trailing newline
fclose($fp);
}
// parse and cache changelog lines
foreach ($lines as $value) {
$tmp = parseChangelogLine($value);
if ($tmp!==false) {
$cache[$id][$tmp['date']] = $tmp;
}
}
if (!isset($cache[$id][$rev])) { return false; }
return $cache[$id][$rev];
return $changelog->getRevisionInfo($rev);
}
/**
@ -431,10 +1043,6 @@ function getRevisionInfo($id, $rev, $chunk_size=8192, $media=false) {
* only that a line with the date exists in the changelog.
* By default the current revision is skipped.
*
* id: the page of interest
* first: skip the first n changelog lines
* num: number of revisions to return
*
* The current revision is automatically skipped when the page exists.
* See $INFO['meta']['last_change'] for the current revision.
*
@ -443,106 +1051,24 @@ function getRevisionInfo($id, $rev, $chunk_size=8192, $media=false) {
* backwards in chunks until the requested number of changelog
* lines are recieved.
*
* @deprecated 2013-11-20
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @author Kate Arzamastseva <pshns@ukr.net>
*
* @param string $id the page of interest
* @param int $first skip the first n changelog lines
* @param int $num number of revisions to return
* @param int $chunk_size
* @param bool $media
* @return array
*/
function getRevisions($id, $first, $num, $chunk_size=8192, $media=false) {
global $cache_revinfo;
$cache =& $cache_revinfo;
if (!isset($cache[$id])) { $cache[$id] = array(); }
$revs = array();
$lines = array();
$count = 0;
if ($media) {
$file = mediaMetaFN($id, '.changes');
function getRevisions($id, $first, $num, $chunk_size = 8192, $media = false) {
dbg_deprecated('class PageChangeLog or class MediaChangelog');
if($media) {
$changelog = new MediaChangeLog($id, $chunk_size);
} else {
$file = metaFN($id, '.changes');
$changelog = new PageChangeLog($id, $chunk_size);
}
$num = max($num, 0);
if ($num == 0) { return $revs; }
$chunk_size = max($chunk_size, 0);
if ($first<0) {
$first = 0;
} else if (!$media && @file_exists(wikiFN($id)) || $media && @file_exists(mediaFN($id))) {
// skip current revision if the page exists
$first = max($first+1, 0);
}
if (!@file_exists($file)) { return $revs; }
if (filesize($file)<$chunk_size || $chunk_size==0) {
// read whole file
$lines = file($file);
if ($lines===false) { return $revs; }
} else {
// read chunks backwards
$fp = fopen($file, 'rb'); // "file pointer"
if ($fp===false) { return $revs; }
fseek($fp, 0, SEEK_END);
$tail = ftell($fp);
// chunk backwards
$finger = max($tail-$chunk_size, 0);
while ($count<$num+$first) {
fseek($fp, $finger);
$nl = $finger;
if ($finger>0) {
fgets($fp); // slip the finger forward to a new line
$nl = ftell($fp);
}
// was the chunk big enough? if not, take another bite
if($nl > 0 && $tail <= $nl){
$finger = max($finger-$chunk_size, 0);
continue;
}else{
$finger = $nl;
}
// read chunk
$chunk = '';
$read_size = max($tail-$finger, 0); // found chunk size
$got = 0;
while ($got<$read_size && !feof($fp)) {
$tmp = @fread($fp, max($read_size-$got, 0));
if ($tmp===false) { break; } //error state
$got += strlen($tmp);
$chunk .= $tmp;
}
$tmp = explode("\n", $chunk);
array_pop($tmp); // remove trailing newline
// combine with previous chunk
$count += count($tmp);
$lines = array_merge($tmp, $lines);
// next chunk
if ($finger==0) { break; } // already read all the lines
else {
$tail = $finger;
$finger = max($tail-$chunk_size, 0);
}
}
fclose($fp);
}
// skip parsing extra lines
$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)); }
else if ($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) {
$cache[$id][$tmp['date']] = $tmp;
$revs[] = $tmp['date'];
}
}
return $revs;
return $changelog->getRevisions($first, $num);
}

647
inc/cli.php Normal file
View File

@ -0,0 +1,647 @@
<?php
/**
* Class DokuCLI
*
* All DokuWiki commandline scripts should inherit from this class and implement the abstract methods.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
abstract class DokuCLI {
/** @var string the executed script itself */
protected $bin;
/** @var DokuCLI_Options the option parser */
protected $options;
/** @var DokuCLI_Colors */
public $colors;
/**
* constructor
*
* Initialize the arguments, set up helper classes and set up the CLI environment
*/
public function __construct() {
set_exception_handler(array($this, 'fatal'));
$this->options = new DokuCLI_Options();
$this->colors = new DokuCLI_Colors();
}
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @return void
*/
abstract protected function setup(DokuCLI_Options $options);
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @return void
*/
abstract protected function main(DokuCLI_Options $options);
/**
* Execute the CLI program
*
* Executes the setup() routine, adds default options, initiate the options parsing and argument checking
* and finally executes main()
*/
public function run() {
if('cli' != php_sapi_name()) throw new DokuCLI_Exception('This has to be run from the command line');
// setup
$this->setup($this->options);
$this->options->registerOption(
'no-colors',
'Do not use any colors in output. Useful when piping output to other tools or files.'
);
$this->options->registerOption(
'help',
'Display this help screen and exit immeadiately.',
'h'
);
// parse
$this->options->parseOptions();
// handle defaults
if($this->options->getOpt('no-colors')) {
$this->colors->disable();
}
if($this->options->getOpt('help')) {
echo $this->options->help();
exit(0);
}
// check arguments
$this->options->checkArguments();
// execute
$this->main($this->options);
exit(0);
}
/**
* Exits the program on a fatal error
*
* @param Exception|string $error either an exception or an error message
*/
public function fatal($error) {
$code = 0;
if(is_object($error) && is_a($error, 'Exception')) {
/** @var Exception $error */
$code = $error->getCode();
$error = $error->getMessage();
}
if(!$code) $code = DokuCLI_Exception::E_ANY;
$this->error($error);
exit($code);
}
/**
* Print an error message
*
* @param $string
*/
public function error($string) {
$this->colors->ptln("E: $string", 'red', STDERR);
}
/**
* Print a success message
*
* @param $string
*/
public function success($string) {
$this->colors->ptln("S: $string", 'green', STDERR);
}
/**
* Print an info message
*
* @param $string
*/
public function info($string) {
$this->colors->ptln("I: $string", 'cyan', STDERR);
}
}
/**
* Class DokuCLI_Colors
*
* Handles color output on (Linux) terminals
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class DokuCLI_Colors {
/** @var array known color names */
protected $colors = array(
'reset' => "\33[0m",
'black' => "\33[0;30m",
'darkgray' => "\33[1;30m",
'blue' => "\33[0;34m",
'lightblue' => "\33[1;34m",
'green' => "\33[0;32m",
'lightgreen' => "\33[1;32m",
'cyan' => "\33[0;36m",
'lightcyan' => "\33[1;36m",
'red' => "\33[0;31m",
'lightred' => "\33[1;31m",
'purple' => "\33[0;35m",
'lightpurple' => "\33[1;35m",
'brown' => "\33[0;33m",
'yellow' => "\33[1;33m",
'lightgray' => "\33[0;37m",
'white' => "\33[1;37m",
);
/** @var bool should colors be used? */
protected $enabled = true;
/**
* Constructor
*
* Tries to disable colors for non-terminals
*/
public function __construct() {
if(function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
$this->enabled = false;
return;
}
if(!getenv('TERM')) {
$this->enabled = false;
return;
}
}
/**
* enable color output
*/
public function enable() {
$this->enabled = true;
}
/**
* disable color output
*/
public function disable() {
$this->enabled = false;
}
/**
* Convenience function to print a line in a given color
*
* @param $line
* @param $color
* @param resource $channel
*/
public function ptln($line, $color, $channel = STDOUT) {
$this->set($color);
fwrite($channel, rtrim($line)."\n");
$this->reset();
}
/**
* Set the given color for consecutive output
*
* @param string $color one of the supported color names
* @throws DokuCLI_Exception
*/
public function set($color) {
if(!$this->enabled) return;
if(!isset($this->colors[$color])) throw new DokuCLI_Exception("No such color $color");
echo $this->colors[$color];
}
/**
* reset the terminal color
*/
public function reset() {
$this->set('reset');
}
}
/**
* Class DokuCLI_Options
*
* Parses command line options passed to the CLI script. Allows CLI scripts to easily register all accepted options and
* commands and even generates a help text from this setup.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class DokuCLI_Options {
/** @var array keeps the list of options to parse */
protected $setup;
/** @var array store parsed options */
protected $options = array();
/** @var string current parsed command if any */
protected $command = '';
/** @var array passed non-option arguments */
public $args = array();
/** @var string the executed script */
protected $bin;
/**
* Constructor
*/
public function __construct() {
$this->setup = array(
'' => array(
'opts' => array(),
'args' => array(),
'help' => ''
)
); // default command
$this->args = $this->readPHPArgv();
$this->bin = basename(array_shift($this->args));
$this->options = array();
}
/**
* Sets the help text for the tool itself
*
* @param string $help
*/
public function setHelp($help) {
$this->setup['']['help'] = $help;
}
/**
* Register the names of arguments for help generation and number checking
*
* This has to be called in the order arguments are expected
*
* @param string $arg argument name (just for help)
* @param string $help help text
* @param bool $required is this a required argument
* @param string $command if theses apply to a sub command only
* @throws DokuCLI_Exception
*/
public function registerArgument($arg, $help, $required = true, $command = '') {
if(!isset($this->setup[$command])) throw new DokuCLI_Exception("Command $command not registered");
$this->setup[$command]['args'][] = array(
'name' => $arg,
'help' => $help,
'required' => $required
);
}
/**
* This registers a sub command
*
* Sub commands have their own options and use their own function (not main()).
*
* @param string $command
* @param string $help
* @throws DokuCLI_Exception
*/
public function registerCommand($command, $help) {
if(isset($this->setup[$command])) throw new DokuCLI_Exception("Command $command already registered");
$this->setup[$command] = array(
'opts' => array(),
'args' => array(),
'help' => $help
);
}
/**
* Register an option for option parsing and help generation
*
* @param string $long multi character option (specified with --)
* @param string $help help text for this option
* @param string|null $short one character option (specified with -)
* @param bool|string $needsarg does this option require an argument? give it a name here
* @param string $command what command does this option apply to
* @throws DokuCLI_Exception
*/
public function registerOption($long, $help, $short = null, $needsarg = false, $command = '') {
if(!isset($this->setup[$command])) throw new DokuCLI_Exception("Command $command not registered");
$this->setup[$command]['opts'][$long] = array(
'needsarg' => $needsarg,
'help' => $help,
'short' => $short
);
if($short) {
if(strlen($short) > 1) throw new DokuCLI_Exception("Short options should be exactly one ASCII character");
$this->setup[$command]['short'][$short] = $long;
}
}
/**
* Checks the actual number of arguments against the required number
*
* Throws an exception if arguments are missing. Called from parseOptions()
*
* @throws DokuCLI_Exception
*/
public function checkArguments() {
$argc = count($this->args);
$req = 0;
foreach($this->setup[$this->command]['args'] as $arg) {
if(!$arg['required']) break; // last required arguments seen
$req++;
}
if($req > $argc) throw new DokuCLI_Exception("Not enough arguments", DokuCLI_Exception::E_OPT_ARG_REQUIRED);
}
/**
* Parses the given arguments for known options and command
*
* The given $args array should NOT contain the executed file as first item anymore! The $args
* array is stripped from any options and possible command. All found otions can be accessed via the
* getOpt() function
*
* Note that command options will overwrite any global options with the same name
*
* @throws DokuCLI_Exception
*/
public function parseOptions() {
$non_opts = array();
$argc = count($this->args);
for($i = 0; $i < $argc; $i++) {
$arg = $this->args[$i];
// The special element '--' means explicit end of options. Treat the rest of the arguments as non-options
// and end the loop.
if($arg == '--') {
$non_opts = array_merge($non_opts, array_slice($this->args, $i + 1));
break;
}
// '-' is stdin - a normal argument
if($arg == '-') {
$non_opts = array_merge($non_opts, array_slice($this->args, $i));
break;
}
// first non-option
if($arg{0} != '-') {
$non_opts = array_merge($non_opts, array_slice($this->args, $i));
break;
}
// long option
if(strlen($arg) > 1 && $arg{1} == '-') {
list($opt, $val) = explode('=', substr($arg, 2), 2);
if(!isset($this->setup[$this->command]['opts'][$opt])) {
throw new DokuCLI_Exception("No such option $arg", DokuCLI_Exception::E_UNKNOWN_OPT);
}
// argument required?
if($this->setup[$this->command]['opts'][$opt]['needsarg']) {
if(is_null($val) && $i + 1 < $argc && !preg_match('/^--?[\w]/', $this->args[$i + 1])) {
$val = $this->args[++$i];
}
if(is_null($val)) {
throw new DokuCLI_Exception("Option $arg requires an argument", DokuCLI_Exception::E_OPT_ARG_REQUIRED);
}
$this->options[$opt] = $val;
} else {
$this->options[$opt] = true;
}
continue;
}
// short option
$opt = substr($arg, 1);
if(!isset($this->setup[$this->command]['short'][$opt])) {
throw new DokuCLI_Exception("No such option $arg", DokuCLI_Exception::E_UNKNOWN_OPT);
} else {
$opt = $this->setup[$this->command]['short'][$opt]; // store it under long name
}
// argument required?
if($this->setup[$this->command]['opts'][$opt]['needsarg']) {
$val = null;
if($i + 1 < $argc && !preg_match('/^--?[\w]/', $this->args[$i + 1])) {
$val = $this->args[++$i];
}
if(is_null($val)) {
throw new DokuCLI_Exception("Option $arg requires an argument", DokuCLI_Exception::E_OPT_ARG_REQUIRED);
}
$this->options[$opt] = $val;
} else {
$this->options[$opt] = true;
}
}
// parsing is now done, update args array
$this->args = $non_opts;
// if not done yet, check if first argument is a command and reexecute argument parsing if it is
if(!$this->command && $this->args && isset($this->setup[$this->args[0]])) {
// it is a command!
$this->command = array_shift($this->args);
$this->parseOptions(); // second pass
}
}
/**
* Get the value of the given option
*
* Please note that all options are accessed by their long option names regardless of how they were
* specified on commandline.
*
* Can only be used after parseOptions() has been run
*
* @param string $option
* @param mixed $default what to return if the option was not set
* @return mixed
*/
public function getOpt($option, $default = false) {
if(isset($this->options[$option])) return $this->options[$option];
return $default;
}
/**
* Return the found command if any
*
* @return string
*/
public function getCmd() {
return $this->command;
}
/**
* Builds a help screen from the available options. You may want to call it from -h or on error
*
* @return string
*/
public function help() {
$text = '';
$hascommands = (count($this->setup) > 1);
foreach($this->setup as $command => $config) {
$hasopts = (bool) $this->setup[$command]['opts'];
$hasargs = (bool) $this->setup[$command]['args'];
if(!$command) {
$text .= 'USAGE: '.$this->bin;
} else {
$text .= "\n$command";
}
if($hasopts) $text .= ' <OPTIONS>';
foreach($this->setup[$command]['args'] as $arg) {
if($arg['required']) {
$text .= ' <'.$arg['name'].'>';
} else {
$text .= ' [<'.$arg['name'].'>]';
}
}
$text .= "\n";
if($this->setup[$command]['help']) {
$text .= "\n";
$text .= $this->tableFormat(
array(2, 72),
array('', $this->setup[$command]['help']."\n")
);
}
if($hasopts) {
$text .= "\n OPTIONS\n\n";
foreach($this->setup[$command]['opts'] as $long => $opt) {
$name = '';
if($opt['short']) {
$name .= '-'.$opt['short'];
if($opt['needsarg']) $name .= ' <'.$opt['needsarg'].'>';
$name .= ', ';
}
$name .= "--$long";
if($opt['needsarg']) $name .= ' <'.$opt['needsarg'].'>';
$text .= $this->tableFormat(
array(2, 20, 52),
array('', $name, $opt['help'])
);
$text .= "\n";
}
}
if($hasargs) {
$text .= "\n";
foreach($this->setup[$command]['args'] as $arg) {
$name = '<'.$arg['name'].'>';
$text .= $this->tableFormat(
array(2, 20, 52),
array('', $name, $arg['help'])
);
}
}
if($command == '' && $hascommands) {
$text .= "\nThis tool accepts a command as first parameter as outlined below:\n";
}
}
return $text;
}
/**
* Safely read the $argv PHP array across different PHP configurations.
* Will take care on register_globals and register_argc_argv ini directives
*
* @throws DokuCLI_Exception
* @return array the $argv PHP array or PEAR error if not registered
*/
private function readPHPArgv() {
global $argv;
if(!is_array($argv)) {
if(!@is_array($_SERVER['argv'])) {
if(!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
throw new DokuCLI_Exception(
"Could not read cmd args (register_argc_argv=Off?)",
DOKU_CLI_OPTS_ARG_READ
);
}
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
}
return $_SERVER['argv'];
}
return $argv;
}
/**
* Displays text in multiple word wrapped columns
*
* @param array $widths list of column widths (in characters)
* @param array $texts list of texts for each column
* @return string
*/
private function tableFormat($widths, $texts) {
$wrapped = array();
$maxlen = 0;
foreach($widths as $col => $width) {
$wrapped[$col] = explode("\n", wordwrap($texts[$col], $width - 1, "\n", true)); // -1 char border
$len = count($wrapped[$col]);
if($len > $maxlen) $maxlen = $len;
}
$out = '';
for($i = 0; $i < $maxlen; $i++) {
foreach($widths as $col => $width) {
if(isset($wrapped[$col][$i])) {
$val = $wrapped[$col][$i];
} else {
$val = '';
}
$out .= sprintf('%-'.$width.'s', $val);
}
$out .= "\n";
}
return $out;
}
}
/**
* Class DokuCLI_Exception
*
* The code is used as exit code for the CLI tool. This should probably be extended. Many cases just fall back to the
* E_ANY code.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class DokuCLI_Exception extends Exception {
const E_ANY = -1; // no error code specified
const E_UNKNOWN_OPT = 1; //Unrecognized option
const E_OPT_ARG_REQUIRED = 2; //Option requires argument
const E_OPT_ARG_DENIED = 3; //Option not allowed argument
const E_OPT_ABIGUOUS = 4; //Option abiguous
const E_ARG_READ = 5; //Could not read argv
public function __construct($message = "", $code = 0, Exception $previous = null) {
if(!$code) $code = DokuCLI_Exception::E_ANY;
parent::__construct($message, $code, $previous);
}
}

View File

@ -68,15 +68,16 @@ define('DOKU_CLI_OPTS_ARG_READ',5);//Could not read argv
*
* @author Andrei Zmievski <andrei@php.net>
*
* @deprecated 2014-05-16
*/
class Doku_Cli_Opts {
/**
* <?php ?>
* @see http://www.sitepoint.com/article/php-command-line-1/3
* @param string executing file name - this MUST be passed the __FILE__ constant
* @param string short options
* @param array (optional) long options
* @param string $bin_file executing file name - this MUST be passed the __FILE__ constant
* @param string $short_options short options
* @param array $long_options (optional) long options
* @return Doku_Cli_Opts_Container or Doku_Cli_Opts_Error
*/
function & getOptions($bin_file, $short_options, $long_options = null) {
@ -233,12 +234,12 @@ class Doku_Cli_Opts {
* Parse short option
*
* @param string $arg Argument
* @param string[] $short_options Available short options
* @param string $short_options Available short options
* @param string[][] &$opts
* @param string[] &$args
*
* @access private
* @return void
* @return void|Doku_Cli_Opts_Error
*/
function _parseShortOption($arg, $short_options, &$opts, &$args) {
$len = strlen($arg);
@ -324,7 +325,7 @@ class Doku_Cli_Opts {
* @param string[] &$args
*
* @access private
* @return void|PEAR_Error
* @return void|Doku_Cli_Opts_Error
*/
function _parseLongOption($arg, $long_options, &$opts, &$args) {
@list($opt, $opt_arg) = explode('=', $arg, 2);
@ -402,7 +403,7 @@ class Doku_Cli_Opts {
* Will take care on register_globals and register_argc_argv ini directives
*
* @access public
* @return mixed the $argv PHP array or PEAR error if not registered
* @return array|Doku_Cli_Opts_Error the $argv PHP array or PEAR error if not registered
*/
function readPHPArgv() {
global $argv;
@ -421,10 +422,19 @@ class Doku_Cli_Opts {
return $argv;
}
/**
* @param $code
* @param $msg
* @return Doku_Cli_Opts_Error
*/
function raiseError($code, $msg) {
return new Doku_Cli_Opts_Error($code, $msg);
}
/**
* @param $obj
* @return bool
*/
function isError($obj) {
return is_a($obj, 'Doku_Cli_Opts_Error');
}

View File

@ -22,6 +22,9 @@ define('RECENTS_MEDIA_PAGES_MIXED', 32);
*
* @author Andreas Gohr <andi@splitbrain.org>
* @see htmlspecialchars()
*
* @param string $string the string being converted
* @return string converted string
*/
function hsc($string) {
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
@ -33,6 +36,9 @@ function hsc($string) {
* You can give an indention as optional parameter
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $string line of text
* @param int $indent number of spaces indention
*/
function ptln($string, $indent = 0) {
echo str_repeat(' ', $indent)."$string\n";
@ -42,6 +48,9 @@ function ptln($string, $indent = 0) {
* strips control characters (<32) from the given string
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param $string string being stripped
* @return string
*/
function stripctl($string) {
return preg_replace('/[\x00-\x1F]+/s', '', $string);
@ -56,15 +65,21 @@ function stripctl($string) {
* @return string
*/
function getSecurityToken() {
return PassHash::hmac('md5', session_id().$_SERVER['REMOTE_USER'], auth_cookiesalt());
/** @var Input $INPUT */
global $INPUT;
return PassHash::hmac('md5', session_id().$INPUT->server->str('REMOTE_USER'), auth_cookiesalt());
}
/**
* Check the secret CSRF token
*
* @param null|string $token security token or null to read it from request variable
* @return bool success if the token matched
*/
function checkSecurityToken($token = null) {
/** @var Input $INPUT */
global $INPUT;
if(empty($_SERVER['REMOTE_USER'])) return true; // no logged in user, no need for a check
if(!$INPUT->server->str('REMOTE_USER')) return true; // no logged in user, no need for a check
if(is_null($token)) $token = $INPUT->str('sectok');
if(getSecurityToken() != $token) {
@ -78,6 +93,9 @@ function checkSecurityToken($token = null) {
* Print a hidden form field with a secret CSRF token
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param bool $print if true print the field, otherwise html of the field is returned
* @return void|string html of hidden form field
*/
function formSecurityToken($print = true) {
$ret = '<div class="no"><input type="hidden" name="sectok" value="'.getSecurityToken().'" /></div>'."\n";
@ -90,17 +108,24 @@ function formSecurityToken($print = true) {
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Chris Smith <chris@jalakai.co.uk>
*
* @param string $id pageid
* @param bool $htmlClient add info about whether is mobile browser
* @return array with info for a request of $id
*
*/
function basicinfo($id, $htmlClient=true){
global $USERINFO;
/* @var Input $INPUT */
global $INPUT;
// set info about manager/admin status.
$info['isadmin'] = false;
$info['ismanager'] = false;
if(isset($_SERVER['REMOTE_USER'])) {
if($INPUT->server->has('REMOTE_USER')) {
$info['userinfo'] = $USERINFO;
$info['perm'] = auth_quickaclcheck($id);
$info['client'] = $_SERVER['REMOTE_USER'];
$info['client'] = $INPUT->server->str('REMOTE_USER');
if($info['perm'] == AUTH_ADMIN) {
$info['isadmin'] = true;
@ -111,7 +136,7 @@ function basicinfo($id, $htmlClient=true){
// if some outside auth were used only REMOTE_USER is set
if(!$info['userinfo']['name']) {
$info['userinfo']['name'] = $_SERVER['REMOTE_USER'];
$info['userinfo']['name'] = $INPUT->server->str('REMOTE_USER');
}
} else {
@ -134,12 +159,16 @@ function basicinfo($id, $htmlClient=true){
* array.
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @return array with info about current document
*/
function pageinfo() {
global $ID;
global $REV;
global $RANGE;
global $lang;
/* @var Input $INPUT */
global $INPUT;
$info = basicinfo($ID);
@ -148,19 +177,20 @@ function pageinfo() {
$info['id'] = $ID;
$info['rev'] = $REV;
if(isset($_SERVER['REMOTE_USER'])) {
if($INPUT->server->has('REMOTE_USER')) {
$sub = new Subscription();
$info['subscribed'] = $sub->user_subscription();
} else {
$info['subscribed'] = false;
}
$info['locked'] = checklock($ID);
$info['filepath'] = fullpath(wikiFN($ID));
$info['exists'] = @file_exists($info['filepath']);
$info['locked'] = checklock($ID);
$info['filepath'] = fullpath(wikiFN($ID));
$info['exists'] = @file_exists($info['filepath']);
$info['currentrev'] = @filemtime($info['filepath']);
if($REV) {
//check if current revision was meant
if($info['exists'] && (@filemtime($info['filepath']) == $REV)) {
if($info['exists'] && ($info['currentrev'] == $REV)) {
$REV = '';
} elseif($RANGE) {
//section editing does not work with old revisions!
@ -187,13 +217,14 @@ function pageinfo() {
$info['meta'] = p_get_metadata($ID);
//who's the editor
$pagelog = new PageChangeLog($ID, 1024);
if($REV) {
$revinfo = getRevisionInfo($ID, $REV, 1024);
$revinfo = $pagelog->getRevisionInfo($REV);
} else {
if(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 = getRevisionInfo($ID, $info['lastmod'], 1024);
$revinfo = $pagelog->getRevisionInfo($info['lastmod']);
// cache most recent changelog line in metadata if missing and still valid
if($revinfo !== false) {
$info['meta']['last_change'] = $revinfo;
@ -237,6 +268,8 @@ function pageinfo() {
/**
* Return information about the current media item as an associative array.
*
* @return array with info about current media item
*/
function mediainfo(){
global $NS;
@ -252,6 +285,10 @@ function mediainfo(){
* Build an string of URL parameters
*
* @author Andreas Gohr
*
* @param array $params array with key-value pairs
* @param string $sep series of pairs are separated by this character
* @return string query string
*/
function buildURLparams($params, $sep = '&amp;') {
$url = '';
@ -272,6 +309,10 @@ function buildURLparams($params, $sep = '&amp;') {
* Skips keys starting with '_', values get HTML encoded
*
* @author Andreas Gohr
*
* @param array $params array with (attribute name-attribute value) pairs
* @param bool $skipempty skip empty string values?
* @return string
*/
function buildAttributes($params, $skipempty = false) {
$url = '';
@ -293,6 +334,8 @@ function buildAttributes($params, $skipempty = false) {
* This builds the breadcrumb trail and returns it as array
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @return array(pageid=>name, ... )
*/
function breadcrumbs() {
// we prepare the breadcrumbs early for quick session closing
@ -352,14 +395,21 @@ function breadcrumbs() {
* Urlencoding is ommitted when the second parameter is false
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id pageid being filtered
* @param bool $ue apply urlencoding?
* @return string
*/
function idfilter($id, $ue = true) {
global $conf;
/* @var Input $INPUT */
global $INPUT;
if($conf['useslash'] && $conf['userewrite']) {
$id = strtr($id, ':', '/');
} elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' &&
$conf['userewrite'] &&
strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') === false
strpos($INPUT->server->str('SERVER_SOFTWARE'), 'Microsoft-IIS') === false
) {
$id = strtr($id, ':', ';');
}
@ -374,10 +424,15 @@ function idfilter($id, $ue = true) {
/**
* This builds a link to a wikipage
*
* It handles URL rewriting and adds additional parameter if
* given in $more
* It handles URL rewriting and adds additional parameters
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id, defaults to start page
* @param string|array $urlParameters URL parameters, associative array recommended
* @param bool $absolute request an absolute URL instead of relative
* @param string $separator parameter separator
* @return string
*/
function wl($id = '', $urlParameters = '', $absolute = false, $separator = '&amp;') {
global $conf;
@ -419,13 +474,19 @@ function wl($id = '', $urlParameters = '', $absolute = false, $separator = '&amp
* Handles URL rewriting if enabled. Follows the style of wl().
*
* @author Ben Coburn <btcoburn@silicodon.net>
* @param string $id page id, defaults to start page
* @param string $format the export renderer to use
* @param string|array $urlParameters URL parameters, associative array recommended
* @param bool $abs request an absolute URL instead of relative
* @param string $sep parameter separator
* @return string
*/
function exportlink($id = '', $format = 'raw', $more = '', $abs = false, $sep = '&amp;') {
function exportlink($id = '', $format = 'raw', $urlParameters = '', $abs = false, $sep = '&amp;') {
global $conf;
if(is_array($more)) {
$more = buildURLparams($more, $sep);
if(is_array($urlParameters)) {
$urlParameters = buildURLparams($urlParameters, $sep);
} else {
$more = str_replace(',', $sep, $more);
$urlParameters = str_replace(',', $sep, $urlParameters);
}
$format = rawurlencode($format);
@ -438,13 +499,13 @@ function exportlink($id = '', $format = 'raw', $more = '', $abs = false, $sep =
if($conf['userewrite'] == 2) {
$xlink .= DOKU_SCRIPT.'/'.$id.'?do=export_'.$format;
if($more) $xlink .= $sep.$more;
if($urlParameters) $xlink .= $sep.$urlParameters;
} elseif($conf['userewrite'] == 1) {
$xlink .= '_export/'.$format.'/'.$id;
if($more) $xlink .= '?'.$more;
if($urlParameters) $xlink .= '?'.$urlParameters;
} else {
$xlink .= DOKU_SCRIPT.'?do=export_'.$format.$sep.'id='.$id;
if($more) $xlink .= $sep.$more;
if($urlParameters) $xlink .= $sep.$urlParameters;
}
return $xlink;
@ -551,6 +612,8 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
* Consider using wl() instead, unless you absoutely need the doku.php endpoint
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @return string
*/
function script() {
return DOKU_BASE.DOKU_SCRIPT;
@ -577,6 +640,7 @@ function script() {
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michael Klier <chi@chimeric.de>
*
* @param string $text - optional text to check, if not given the globals are used
* @return bool - true if a spam word was found
*/
@ -587,6 +651,8 @@ function checkwordblock($text = '') {
global $SUM;
global $conf;
global $INFO;
/* @var Input $INPUT */
global $INPUT;
if(!$conf['usewordblock']) return false;
@ -619,9 +685,9 @@ function checkwordblock($text = '') {
if(count($re) && preg_match('#('.join('|', $re).')#si', $text, $matches)) {
// prepare event data
$data['matches'] = $matches;
$data['userinfo']['ip'] = $_SERVER['REMOTE_ADDR'];
if($_SERVER['REMOTE_USER']) {
$data['userinfo']['user'] = $_SERVER['REMOTE_USER'];
$data['userinfo']['ip'] = $INPUT->server->str('REMOTE_ADDR');
if($INPUT->server->str('REMOTE_USER')) {
$data['userinfo']['user'] = $INPUT->server->str('REMOTE_USER');
$data['userinfo']['name'] = $INFO['userinfo']['name'];
$data['userinfo']['mail'] = $INFO['userinfo']['mail'];
}
@ -643,16 +709,22 @@ function checkwordblock($text = '') {
* headers
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param boolean $single If set only a single IP is returned
* @return string
*/
function clientIP($single = false) {
/* @var Input $INPUT */
global $INPUT;
$ip = array();
$ip[] = $_SERVER['REMOTE_ADDR'];
if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
$ip = array_merge($ip, explode(',', str_replace(' ', '', $_SERVER['HTTP_X_FORWARDED_FOR'])));
if(!empty($_SERVER['HTTP_X_REAL_IP']))
$ip = array_merge($ip, explode(',', str_replace(' ', '', $_SERVER['HTTP_X_REAL_IP'])));
$ip[] = $INPUT->server->str('REMOTE_ADDR');
if($INPUT->server->str('HTTP_X_FORWARDED_FOR')) {
$ip = array_merge($ip, explode(',', str_replace(' ', '', $INPUT->server->str('HTTP_X_FORWARDED_FOR'))));
}
if($INPUT->server->str('HTTP_X_REAL_IP')) {
$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
@ -709,18 +781,22 @@ function clientIP($single = false) {
* Adapted from the example code at url below
*
* @link http://www.brainhandles.com/2007/10/15/detecting-mobile-browsers/#code
*
* @return bool if true, client is mobile browser; otherwise false
*/
function clientismobile() {
/* @var Input $INPUT */
global $INPUT;
if(isset($_SERVER['HTTP_X_WAP_PROFILE'])) return true;
if($INPUT->server->has('HTTP_X_WAP_PROFILE')) return true;
if(preg_match('/wap\.|\.wap/i', $_SERVER['HTTP_ACCEPT'])) return true;
if(preg_match('/wap\.|\.wap/i', $INPUT->server->str('HTTP_ACCEPT'))) return true;
if(!isset($_SERVER['HTTP_USER_AGENT'])) return false;
if(!$INPUT->server->has('HTTP_USER_AGENT')) return false;
$uamatches = 'midp|j2me|avantg|docomo|novarra|palmos|palmsource|240x320|opwv|chtml|pda|windows ce|mmp\/|blackberry|mib\/|symbian|wireless|nokia|hand|mobi|phone|cdm|up\.b|audio|SIE\-|SEC\-|samsung|HTC|mot\-|mitsu|sagem|sony|alcatel|lg|erics|vx|NEC|philips|mmm|xx|panasonic|sharp|wap|sch|rover|pocket|benq|java|pt|pg|vox|amoi|bird|compal|kg|voda|sany|kdd|dbt|sendo|sgh|gradi|jb|\d\d\di|moto';
if(preg_match("/$uamatches/i", $_SERVER['HTTP_USER_AGENT'])) return true;
if(preg_match("/$uamatches/i", $INPUT->server->str('HTTP_USER_AGENT'))) return true;
return false;
}
@ -731,6 +807,7 @@ function clientismobile() {
* If $conf['dnslookups'] is disabled it simply returns the input string
*
* @author Glen Harris <astfgl@iamnota.org>
*
* @param string $ips comma separated list of IP addresses
* @return string a comma separated list of hostnames
*/
@ -757,9 +834,15 @@ function gethostsbyaddrs($ips) {
* removes stale lockfiles
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id
* @return bool page is locked?
*/
function checklock($id) {
global $conf;
/* @var Input $INPUT */
global $INPUT;
$lock = wikiLockFN($id);
//no lockfile
@ -772,8 +855,8 @@ function checklock($id) {
}
//my own lock
list($ip, $session) = explode("\n", io_readFile($lock));
if($ip == $_SERVER['REMOTE_USER'] || $ip == clientIP() || $session == session_id()) {
@list($ip, $session) = explode("\n", io_readFile($lock));
if($ip == $INPUT->server->str('REMOTE_USER') || $ip == clientIP() || (session_id() && $session == session_id())) {
return false;
}
@ -784,17 +867,21 @@ function checklock($id) {
* Lock a page for editing
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id to lock
*/
function lock($id) {
global $conf;
/* @var Input $INPUT */
global $INPUT;
if($conf['locktime'] == 0) {
return;
}
$lock = wikiLockFN($id);
if($_SERVER['REMOTE_USER']) {
io_saveFile($lock, $_SERVER['REMOTE_USER']);
if($INPUT->server->str('REMOTE_USER')) {
io_saveFile($lock, $INPUT->server->str('REMOTE_USER'));
} else {
io_saveFile($lock, clientIP()."\n".session_id());
}
@ -804,14 +891,18 @@ function lock($id) {
* Unlock a page if it was locked by the user
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id to unlock
* @return bool true if a lock was removed
*/
function unlock($id) {
/* @var Input $INPUT */
global $INPUT;
$lock = wikiLockFN($id);
if(@file_exists($lock)) {
list($ip, $session) = explode("\n", io_readFile($lock));
if($ip == $_SERVER['REMOTE_USER'] || $ip == clientIP() || $session == session_id()) {
@list($ip, $session) = explode("\n", io_readFile($lock));
if($ip == $INPUT->server->str('REMOTE_USER') || $ip == clientIP() || $session == session_id()) {
@unlink($lock);
return true;
}
@ -826,6 +917,9 @@ function unlock($id) {
*
* @see formText() for 2crlf conversion
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $text
* @return string
*/
function cleanText($text) {
$text = preg_replace("/(\015\012)|(\015)/", "\012", $text);
@ -845,6 +939,9 @@ function cleanText($text) {
*
* @see cleanText() for 2unix conversion
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $text
* @return string
*/
function formText($text) {
$text = str_replace("\012", "\015\012", $text);
@ -855,6 +952,10 @@ function formText($text) {
* Returns the specified local text in raw format
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id
* @param string $ext extension of file being read, default 'txt'
* @return string
*/
function rawLocale($id, $ext = 'txt') {
return io_readFile(localeFN($id, $ext));
@ -864,6 +965,10 @@ function rawLocale($id, $ext = 'txt') {
* Returns the raw WikiText
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id
* @param string $rev timestamp when a revision of wikitext is desired
* @return string
*/
function rawWiki($id, $rev = '') {
return io_readWikiPage(wikiFN($id, $rev), $id, $rev);
@ -874,6 +979,9 @@ function rawWiki($id, $rev = '') {
*
* @triggers COMMON_PAGETPL_LOAD
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id the id of the page to be created
* @return string parsed pagetemplate content
*/
function pageTemplate($id) {
global $conf;
@ -925,6 +1033,9 @@ function pageTemplate($id) {
* This works on data from COMMON_PAGETPL_LOAD
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param array $data array with event data
* @return string
*/
function parsePageTemplate(&$data) {
/**
@ -937,6 +1048,8 @@ function parsePageTemplate(&$data) {
global $USERINFO;
global $conf;
/* @var Input $INPUT */
global $INPUT;
// replace placeholders
$file = noNS($id);
@ -968,7 +1081,7 @@ function parsePageTemplate(&$data) {
utf8_ucfirst($page),
utf8_ucwords($page),
utf8_strtoupper($page),
$_SERVER['REMOTE_USER'],
$INPUT->server->str('REMOTE_USER'),
$USERINFO['name'],
$USERINFO['mail'],
$conf['dformat'],
@ -990,6 +1103,11 @@ function parsePageTemplate(&$data) {
* The returned order is prefix, section and suffix.
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $range in form "from-to"
* @param string $id page id
* @param string $rev optional, the revision timestamp
* @return array with three slices
*/
function rawWikiSlices($range, $id, $rev = '') {
$text = io_readWikiPage(wikiFN($id, $rev), $id, $rev);
@ -1014,6 +1132,12 @@ function rawWikiSlices($range, $id, $rev = '') {
* lines between sections if needed (used on saving).
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $pre prefix
* @param string $text text in the middle
* @param string $suf suffix
* @param bool $pretty add additional empty lines between sections
* @return string
*/
function con($pre, $text, $suf, $pretty = false) {
if($pretty) {
@ -1038,6 +1162,11 @@ function con($pre, $text, $suf, $pretty = false) {
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Ben Coburn <btcoburn@silicodon.net>
*
* @param string $id page id
* @param string $text wikitext being saved
* @param string $summary summary of text update
* @param bool $minor mark this saved version as minor update
*/
function saveWikiText($id, $text, $summary, $minor = false) {
/* Note to developers:
@ -1049,6 +1178,9 @@ function saveWikiText($id, $text, $summary, $minor = false) {
global $conf;
global $lang;
global $REV;
/* @var Input $INPUT */
global $INPUT;
// ignore if no changes were made
if($text == rawWiki($id, '')) {
return;
@ -1059,8 +1191,9 @@ function saveWikiText($id, $text, $summary, $minor = false) {
$wasRemoved = (trim($text) == ''); // check for empty or whitespace only
$wasCreated = !@file_exists($file);
$wasReverted = ($REV == true);
$pagelog = new PageChangeLog($id, 1024);
$newRev = false;
$oldRev = getRevisions($id, -1, 1, 1024); // from changelog
$oldRev = $pagelog->getRevisions(-1, 1); // from changelog
$oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]);
if(!@file_exists(wikiFN($id, $old)) && @file_exists($file) && $old >= $oldRev) {
// add old revision to the attic if missing
@ -1111,7 +1244,7 @@ function saveWikiText($id, $text, $summary, $minor = false) {
$type = DOKU_CHANGE_TYPE_CREATE;
} else if($wasRemoved) {
$type = DOKU_CHANGE_TYPE_DELETE;
} else if($minor && $conf['useacl'] && $_SERVER['REMOTE_USER']) {
} else if($minor && $conf['useacl'] && $INPUT->server->str('REMOTE_USER')) {
$type = DOKU_CHANGE_TYPE_MINOR_EDIT;
} //minor edits only for logged in users
@ -1138,9 +1271,11 @@ function saveWikiText($id, $text, $summary, $minor = false) {
* revision date
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $id page id
* @return int|string revision timestamp
*/
function saveOldRevision($id) {
global $conf;
$oldf = wikiFN($id);
if(!@file_exists($oldf)) return '';
$date = filemtime($oldf);
@ -1158,12 +1293,14 @@ function saveOldRevision($id) {
* @param string $summary What changed
* @param boolean $minor Is this a minor edit?
* @param array $replace Additional string substitutions, @KEY@ to be replaced by value
*
* @return bool
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace = array()) {
global $conf;
/* @var Input $INPUT */
global $INPUT;
// decide if there is something to do, eg. whom to mail
if($who == 'admin') {
@ -1172,8 +1309,8 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace =
$to = $conf['notify'];
} elseif($who == 'subscribers') {
if(!actionOK('subscribe')) return false; //subscribers enabled?
if($conf['useacl'] && $_SERVER['REMOTE_USER'] && $minor) return false; //skip minors
$data = array('id' => $id, 'addresslist' => '', 'self' => false);
if($conf['useacl'] && $INPUT->server->str('REMOTE_USER') && $minor) return false; //skip minors
$data = array('id' => $id, 'addresslist' => '', 'self' => false, 'replacements' => $replace);
trigger_event(
'COMMON_NOTIFY_ADDRESSLIST', $data,
array(new Subscription(), 'notifyaddresses')
@ -1195,12 +1332,17 @@ function notify($id, $who, $rev = '', $summary = '', $minor = false, $replace =
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Todd Augsburger <todd@rollerorgans.com>
*
* @return array|string
*/
function getGoogleQuery() {
if(!isset($_SERVER['HTTP_REFERER'])) {
/* @var Input $INPUT */
global $INPUT;
if(!$INPUT->server->has('HTTP_REFERER')) {
return '';
}
$url = parse_url($_SERVER['HTTP_REFERER']);
$url = parse_url($INPUT->server->str('HTTP_REFERER'));
// only handle common SEs
if(!preg_match('/(google|bing|yahoo|ask|duckduckgo|babylon|aol|yandex)/',$url['host'])) return '';
@ -1230,8 +1372,10 @@ function getGoogleQuery() {
/**
* Return the human readable size of a file
*
* @param int $size A file size
* @param int $dec A number of decimal places
* @param int $size A file size
* @param int $dec A number of decimal places
* @return string human readable size
*
* @author Martin Benjamin <b.martin@cybernet.ch>
* @author Aidan Lister <aidan@php.net>
* @version 1.0.0
@ -1253,6 +1397,9 @@ function filesize_h($size, $dec = 1) {
* Return the given timestamp as human readable, fuzzy age
*
* @author Andreas Gohr <gohr@cosmocode.de>
*
* @param int $dt timestamp
* @return string
*/
function datetime_h($dt) {
global $lang;
@ -1287,6 +1434,10 @@ function datetime_h($dt) {
*
* @see datetime_h
* @author Andreas Gohr <gohr@cosmocode.de>
*
* @param int|null $dt timestamp when given, null will take current timestamp
* @param string $format empty default to $conf['dformat'], or provide format as recognized by strftime()
* @return string
*/
function dformat($dt = null, $format = '') {
global $conf;
@ -1304,6 +1455,7 @@ function dformat($dt = null, $format = '') {
*
* @author <ungu at terong dot com>
* @link http://www.php.net/manual/en/function.date.php#54072
*
* @param int $int_date: current date in UNIX timestamp
* @return string
*/
@ -1320,6 +1472,9 @@ function date_iso8601($int_date) {
*
* @author Harry Fuecks <hfuecks@gmail.com>
* @author Christopher Smith <chris@jalakai.co.uk>
*
* @param string $email email address
* @return string
*/
function obfuscate($email) {
global $conf;
@ -1347,6 +1502,10 @@ function obfuscate($email) {
* Removes quoting backslashes
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $string
* @param string $char backslashed character
* @return string
*/
function unslash($string, $char = "'") {
return str_replace('\\'.$char, $char, $string);
@ -1357,19 +1516,27 @@ function unslash($string, $char = "'") {
*
* @author <gilthans dot NO dot SPAM at gmail dot com>
* @link http://de3.php.net/manual/en/ini.core.php#79564
*
* @param string $v shorthands
* @return int|string
*/
function php_to_byte($v) {
$l = substr($v, -1);
$ret = substr($v, 0, -1);
switch(strtoupper($l)) {
/** @noinspection PhpMissingBreakStatementInspection */
case 'P':
$ret *= 1024;
/** @noinspection PhpMissingBreakStatementInspection */
case 'T':
$ret *= 1024;
/** @noinspection PhpMissingBreakStatementInspection */
case 'G':
$ret *= 1024;
/** @noinspection PhpMissingBreakStatementInspection */
case 'M':
$ret *= 1024;
/** @noinspection PhpMissingBreakStatementInspection */
case 'K':
$ret *= 1024;
break;
@ -1382,6 +1549,9 @@ function php_to_byte($v) {
/**
* Wrapper around preg_quote adding the default delimiter
*
* @param string $string
* @return string
*/
function preg_quote_cb($string) {
return preg_quote($string, '/');
@ -1415,37 +1585,135 @@ function shorten($keep, $short, $max, $min = 9, $char = '…') {
* Return the users realname or e-mail address for use
* in page footer and recent changes pages
*
* @param string|null $username or null when currently logged-in user should be used
* @param bool $textonly true returns only plain text, true allows returning html
* @return string html or plain text(not escaped) of formatted user name
*
* @author Andy Webber <dokuwiki AT andywebber DOT com>
*/
function editorinfo($username) {
global $conf;
function editorinfo($username, $textonly = false) {
return userlink($username, $textonly);
}
/**
* Returns users realname w/o link
*
* @param string|null $username or null when currently logged-in user should be used
* @param bool $textonly true returns only plain text, true allows returning html
* @return string html or plain text(not escaped) of formatted user name
*
* @triggers COMMON_USER_LINK
*/
function userlink($username = null, $textonly = false) {
global $conf, $INFO;
/** @var DokuWiki_Auth_Plugin $auth */
global $auth;
/** @var Input $INPUT */
global $INPUT;
switch($conf['showuseras']) {
case 'username':
case 'email':
case 'email_link':
if($auth) $info = $auth->getUserData($username);
break;
default:
return hsc($username);
}
if(isset($info) && $info) {
switch($conf['showuseras']) {
case 'username':
return hsc($info['name']);
case 'email':
return obfuscate($info['mail']);
case 'email_link':
$mail = obfuscate($info['mail']);
return '<a href="mailto:'.$mail.'">'.$mail.'</a>';
default:
return hsc($username);
// prepare initial event data
$data = array(
'username' => $username, // the unique user name
'name' => '',
'link' => array( //setting 'link' to false disables linking
'target' => '',
'pre' => '',
'suf' => '',
'style' => '',
'more' => '',
'url' => '',
'title' => '',
'class' => ''
),
'userlink' => '', // formatted user name as will be returned
'textonly' => $textonly
);
if($username === null) {
$data['username'] = $username = $INPUT->server->str('REMOTE_USER');
if($textonly){
$data['name'] = $INFO['userinfo']['name']. ' (' . $INPUT->server->str('REMOTE_USER') . ')';
}else {
$data['name'] = '<bdi>' . hsc($INFO['userinfo']['name']) . '</bdi> (<bdi>' . hsc($INPUT->server->str('REMOTE_USER')) . '</bdi>)';
}
} else {
return hsc($username);
}
$evt = new Doku_Event('COMMON_USER_LINK', $data);
if($evt->advise_before(true)) {
if(empty($data['name'])) {
if($conf['showuseras'] == 'loginname') {
$data['name'] = $textonly ? $data['username'] : hsc($data['username']);
} else {
if($auth) $info = $auth->getUserData($username);
if(isset($info) && $info) {
switch($conf['showuseras']) {
case 'username':
case 'username_link':
$data['name'] = $textonly ? $info['name'] : hsc($info['name']);
break;
case 'email':
case 'email_link':
$data['name'] = obfuscate($info['mail']);
break;
}
}
}
}
/** @var Doku_Renderer_xhtml $xhtml_renderer */
static $xhtml_renderer = null;
if(!$data['textonly'] && empty($data['link']['url'])) {
if(in_array($conf['showuseras'], array('email_link', 'username_link'))) {
if(!isset($info)) {
if($auth) $info = $auth->getUserData($username);
}
if(isset($info) && $info) {
if($conf['showuseras'] == 'email_link') {
$data['link']['url'] = 'mailto:' . obfuscate($info['mail']);
} else {
if(is_null($xhtml_renderer)) {
$xhtml_renderer = p_get_renderer('xhtml');
}
if(empty($xhtml_renderer->interwiki)) {
$xhtml_renderer->interwiki = getInterwiki();
}
$shortcut = 'user';
$exists = null;
$data['link']['url'] = $xhtml_renderer->_resolveInterWiki($shortcut, $username, $exists);
$data['link']['class'] .= ' interwiki iw_user';
if($exists !== null) {
if($exists) {
$data['link']['class'] .= ' wikilink1';
} else {
$data['link']['class'] .= ' wikilink2';
$data['link']['rel'] = 'nofollow';
}
}
}
} else {
$data['textonly'] = true;
}
} else {
$data['textonly'] = true;
}
}
if($data['textonly']) {
$data['userlink'] = $data['name'];
} else {
$data['link']['name'] = $data['name'];
if(is_null($xhtml_renderer)) {
$xhtml_renderer = p_get_renderer('xhtml');
}
$data['userlink'] = $xhtml_renderer->_formatLink($data['link']);
}
}
$evt->advise_after();
unset($evt);
return $data['userlink'];
}
/**
@ -1453,6 +1721,7 @@ function editorinfo($username) {
* When no image exists, returns an empty string
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $type - type of image 'badge' or 'button'
* @return string
*/
@ -1461,7 +1730,6 @@ function license_img($type) {
global $conf;
if(!$conf['license']) return '';
if(!is_array($license[$conf['license']])) return '';
$lic = $license[$conf['license']];
$try = array();
$try[] = 'lib/images/license/'.$type.'/'.$conf['license'].'.png';
$try[] = 'lib/images/license/'.$type.'/'.$conf['license'].'.gif';
@ -1483,9 +1751,8 @@ function license_img($type) {
* @author Filip Oscadal <webmaster@illusionsoftworks.cz>
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param int $mem Size of memory you want to allocate in bytes
* @param int $bytes
* @internal param int $used already allocated memory (see above)
* @param int $mem Size of memory you want to allocate in bytes
* @param int $bytes already allocated memory (see above)
* @return bool
*/
function is_mem_available($mem, $bytes = 1048576) {
@ -1516,8 +1783,13 @@ function is_mem_available($mem, $bytes = 1048576) {
*
* @link http://support.microsoft.com/kb/q176113/
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $url url being directed to
*/
function send_redirect($url) {
/* @var Input $INPUT */
global $INPUT;
//are there any undisplayed messages? keep them in session for display
global $MSG;
if(isset($MSG) && count($MSG) && !defined('NOSESSION')) {
@ -1531,7 +1803,7 @@ function send_redirect($url) {
// work around IE bug
// http://www.ianhoar.com/2008/11/16/internet-explorer-6-and-redirected-anchor-links/
list($url, $hash) = explode('#', $url);
@list($url, $hash) = explode('#', $url);
if($hash) {
if(strpos($url, '?')) {
$url = $url.'&#'.$hash;
@ -1541,9 +1813,9 @@ function send_redirect($url) {
}
// check if running on IIS < 6 with CGI-PHP
if(isset($_SERVER['SERVER_SOFTWARE']) && isset($_SERVER['GATEWAY_INTERFACE']) &&
(strpos($_SERVER['GATEWAY_INTERFACE'], 'CGI') !== false) &&
(preg_match('|^Microsoft-IIS/(\d)\.\d$|', trim($_SERVER['SERVER_SOFTWARE']), $matches)) &&
if($INPUT->server->has('SERVER_SOFTWARE') && $INPUT->server->has('GATEWAY_INTERFACE') &&
(strpos($INPUT->server->str('GATEWAY_INTERFACE'), 'CGI') !== false) &&
(preg_match('|^Microsoft-IIS/(\d)\.\d$|', trim($INPUT->server->str('SERVER_SOFTWARE')), $matches)) &&
$matches[1] < 6
) {
header('Refresh: 0;url='.$url);
@ -1584,6 +1856,10 @@ function valid_input_set($param, $valid_values, $array, $exc = '') {
/**
* Read a preference from the DokuWiki cookie
* (remembering both keys & values are urlencoded)
*
* @param string $pref preference key
* @param mixed $default value returned when preference not found
* @return string preference value
*/
function get_doku_pref($pref, $default) {
$enc_pref = urlencode($pref);
@ -1602,6 +1878,9 @@ function get_doku_pref($pref, $default) {
/**
* Add a preference to the DokuWiki cookie
* (remembering $_COOKIE['DOKU_PREFS'] is urlencoded)
*
* @param string $pref preference key
* @param string $val preference value
*/
function set_doku_pref($pref, $val) {
global $conf;
@ -1630,4 +1909,13 @@ function set_doku_pref($pref, $val) {
}
}
/**
* Strips source mapping declarations from given text #601
*
* @param &string $text reference to the CSS or JavaScript code to clean
*/
function stripsourcemaps(&$text){
$text = preg_replace('/^(\/\/|\/\*)[@#]\s+sourceMappingURL=.*?(\*\/)?$/im', '\\1\\2', $text);
}
//Setup VIM: ex: et ts=2 :

View File

@ -237,13 +237,14 @@ function getConfigFiles($type) {
* check if the given action was disabled in config
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param string $action
* @returns boolean true if enabled, false if disabled
*/
function actionOK($action){
static $disabled = null;
if(is_null($disabled) || defined('SIMPLE_TEST')){
global $conf;
/** @var auth_basic $auth */
/** @var DokuWiki_Auth_Plugin $auth */
global $auth;
// prepare disabled actions array and handle legacy options

View File

@ -8,15 +8,18 @@
if(!defined('DOKU_INC')) die('meh.');
/**
* The event
*/
class Doku_Event {
// public properties
var $name = ''; // READONLY event name, objects must register against this name to see the event
var $data = null; // READWRITE data relevant to the event, no standardised format (YET!)
var $result = null; // READWRITE the results of the event action, only relevant in "_AFTER" advise
public $name = ''; // READONLY event name, objects must register against this name to see the event
public $data = null; // READWRITE data relevant to the event, no standardised format (YET!)
public $result = null; // READWRITE the results of the event action, only relevant in "_AFTER" advise
// event handlers may modify this if they are preventing the default action
// to provide the after event handlers with event results
var $canPreventDefault = true; // READONLY if true, event handlers can prevent the events default action
public $canPreventDefault = true; // READONLY if true, event handlers can prevent the events default action
// private properties, event handlers can effect these through the provided methods
var $_default = true; // whether or not to carry out the default action associated with the event
@ -32,6 +35,13 @@ class Doku_Event {
}
/**
* @return string
*/
function __toString() {
return $this->name;
}
/**
* advise functions
*
@ -47,7 +57,8 @@ class Doku_Event {
* $evt->advise_after();
* unset($evt);
*
* @return results of processing the event, usually $this->_default
* @param bool $enablePreventDefault
* @return bool results of processing the event, usually $this->_default
*/
function advise_before($enablePreventDefault=true) {
global $EVENT_HANDLER;
@ -73,14 +84,21 @@ class Doku_Event {
* $this->_default, all of which may have been modified by the event handlers.
* - advise all registered (<event>_AFTER) handlers that the event has taken place
*
* @return $event->results
* @param null|callable $action
* @param bool $enablePrevent
* @return mixed $event->results
* the value set by any <event>_before or <event> handlers if the default action is prevented
* or the results of the default action (as modified by <event>_after handlers)
* or NULL no action took place and no handler modified the value
*/
function trigger($action=null, $enablePrevent=true) {
if (!is_callable($action)) $enablePrevent = false;
if (!is_callable($action)) {
$enablePrevent = false;
if (!is_null($action)) {
trigger_error('The default action of '.$this.' is not null but also not callable. Maybe the method is not public?', E_USER_WARNING);
}
}
if ($this->advise_before($enablePrevent) && is_callable($action)) {
if (is_array($action)) {
@ -112,12 +130,15 @@ class Doku_Event {
function preventDefault() { $this->_default = false; }
}
/**
* Controls the registration and execution of all events,
*/
class Doku_Event_Handler {
// public properties: none
// private properties
var $_hooks = array(); // array of events and their registered handlers
protected $_hooks = array(); // array of events and their registered handlers
/**
* event_handler
@ -128,6 +149,7 @@ class Doku_Event_Handler {
function Doku_Event_Handler() {
// load action plugins
/** @var DokuWiki_Action_Plugin $plugin */
$plugin = null;
$pluginlist = plugin_list('action');
@ -143,34 +165,47 @@ class Doku_Event_Handler {
*
* register a hook for an event
*
* @param $event (string) name used by the event, (incl '_before' or '_after' for triggers)
* @param $obj (obj) object in whose scope method is to be executed,
* @param $event string name used by the event, (incl '_before' or '_after' for triggers)
* @param $advise string
* @param $obj object object in whose scope method is to be executed,
* if NULL, method is assumed to be a globally available function
* @param $method (function) event handler function
* @param $param (mixed) data passed to the event handler
* @param $method string event handler function
* @param $param mixed data passed to the event handler
* @param $seq int sequence number for ordering hook execution (ascending)
*/
function register_hook($event, $advise, $obj, $method, $param=null) {
$this->_hooks[$event.'_'.$advise][] = array($obj, $method, $param);
function register_hook($event, $advise, $obj, $method, $param=null, $seq=0) {
$seq = (int)$seq;
$doSort = !isset($this->_hooks[$event.'_'.$advise][$seq]);
$this->_hooks[$event.'_'.$advise][$seq][] = array($obj, $method, $param);
if ($doSort) {
ksort($this->_hooks[$event.'_'.$advise]);
}
}
function process_event(&$event,$advise='') {
/**
* process the before/after event
*
* @param Doku_Event $event
* @param string $advise BEFORE or AFTER
*/
function process_event($event,$advise='') {
$evt_name = $event->name . ($advise ? '_'.$advise : '_BEFORE');
if (!empty($this->_hooks[$evt_name])) {
foreach ($this->_hooks[$evt_name] as $hook) {
// list($obj, $method, $param) = $hook;
$obj =& $hook[0];
$method = $hook[1];
$param = $hook[2];
foreach ($this->_hooks[$evt_name] as $sequenced_hooks) {
foreach ($sequenced_hooks as $hook) {
list($obj, $method, $param) = $hook;
if (is_null($obj)) {
$method($event, $param);
} else {
$obj->$method($event, $param);
if (is_null($obj)) {
$method($event, $param);
} else {
$obj->$method($event, $param);
}
if (!$event->_continue) return;
}
if (!$event->_continue) break;
}
}
}
@ -181,12 +216,12 @@ class Doku_Event_Handler {
*
* function wrapper to process (create, trigger and destroy) an event
*
* @param $name (string) name for the event
* @param $data (mixed) event data
* @param $action (callback) (optional, default=NULL) default action, a php callback function
* @param $canPreventDefault (bool) (optional, default=true) can hooks prevent the default action
* @param $name string name for the event
* @param $data mixed event data
* @param $action callback (optional, default=NULL) default action, a php callback function
* @param $canPreventDefault bool (optional, default=true) can hooks prevent the default action
*
* @return (mixed) the event results value after all event processing is complete
* @return mixed the event results value after all event processing is complete
* by default this is the return value of the default action however
* it can be set or modified by event handler hooks
*/

View File

@ -185,6 +185,8 @@ class HtmlDescribable {
*/
var $descriptionTruncSize;
var $description;
/**
* Returns a formatted description field, depending on descriptionHtmlSyndicated and
* $descriptionTruncSize properties
@ -222,7 +224,7 @@ class FeedHtmlField {
/**
* Creates a new instance of FeedHtmlField.
* @param $string: if given, sets the rawFieldContent property
* @param string $parFieldContent: if given, sets the rawFieldContent property
*/
function FeedHtmlField($parFieldContent) {
if ($parFieldContent) {
@ -267,8 +269,14 @@ class FeedHtmlField {
* @author Kai Blankenhorn <kaib@bitfolge.de>
*/
class UniversalFeedCreator extends FeedCreator {
/** @var FeedCreator */
var $_feed;
/**
* Sets format
*
* @param string $format
*/
function _setFormat($format) {
switch (strtoupper($format)) {
@ -344,7 +352,7 @@ class UniversalFeedCreator extends FeedCreator {
* Creates a syndication feed based on the items previously added.
*
* @see FeedCreator::addItem()
* @param string format format the feed should comply to. Valid values are:
* @param string $format format the feed should comply to. Valid values are:
* "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS"
* @return string the contents of the feed.
*/
@ -358,10 +366,10 @@ class UniversalFeedCreator extends FeedCreator {
* header may be sent to redirect the use to the newly created file.
* @since 1.4
*
* @param string format format the feed should comply to. Valid values are:
* @param string $format format the feed should comply to. Valid values are:
* "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS"
* @param string filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param boolean displayContents optional send the content of the file or not. If true, the file will be sent in the body of the response.
* @param string $filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param boolean $displayContents optional send the content of the file or not. If true, the file will be sent in the body of the response.
*/
function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {
$this->_setFormat($format);
@ -376,10 +384,10 @@ class UniversalFeedCreator extends FeedCreator {
* before anything else, especially before you do the time consuming task to build the feed
* (web fetching, for example).
*
* @param string format format the feed should comply to. Valid values are:
* @param string $format format the feed should comply to. Valid values are:
* "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".
* @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
* @param string $filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param int $timeout optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
*/
function useCached($format="RSS0.91", $filename="", $timeout=3600) {
$this->_setFormat($format);
@ -390,7 +398,7 @@ class UniversalFeedCreator extends FeedCreator {
/**
* Outputs feed to the browser - needed for on-the-fly feed generation (like it is done in WordPress, etc.)
*
* @param format string format the feed should comply to. Valid values are:
* @param $format string format the feed should comply to. Valid values are:
* "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".
*/
function outputFeed($format='RSS0.91') {
@ -422,7 +430,13 @@ class FeedCreator extends HtmlDescribable {
/**
* Optional attributes of a feed.
*/
var $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
var $syndicationURL, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
/**
* Optional attribute of a feed
*
* @var FeedImage
*/
var $image = null;
/**
* The url of the external xsl stylesheet used to format the naked rss feed.
@ -430,13 +444,18 @@ class FeedCreator extends HtmlDescribable {
*/
var $xslStyleSheet = "";
/**
* Style sheet for rss feed
*/
var $cssStyleSheet = "";
/**
* @access private
* @var FeedItem[]
*/
var $items = Array();
/**
* This feed's MIME content type.
* @since 1.4
@ -466,7 +485,7 @@ class FeedCreator extends HtmlDescribable {
/**
* Adds an FeedItem to the feed.
*
* @param object FeedItem $item The FeedItem to add to the feed.
* @param FeedItem $item The FeedItem to add to the feed.
* @access public
*/
function addItem($item) {
@ -482,8 +501,8 @@ class FeedCreator extends HtmlDescribable {
* If the string is already shorter than $length, it is returned unchanged.
*
* @static
* @param string string A string to be truncated.
* @param int length the maximum length the string should be truncated to
* @param string $string A string to be truncated.
* @param int $length the maximum length the string should be truncated to
* @return string the truncated string
*/
function iTrunc($string, $length) {
@ -527,8 +546,8 @@ class FeedCreator extends HtmlDescribable {
/**
* Creates a string containing all additional elements specified in
* $additionalElements.
* @param elements array an associative array containing key => value pairs
* @param indentString string a string that will be inserted before every generated line
* @param $elements array an associative array containing key => value pairs
* @param $indentString string a string that will be inserted before every generated line
* @return string the XML tags corresponding to $additionalElements
*/
function _createAdditionalElements($elements, $indentString="") {
@ -541,6 +560,9 @@ class FeedCreator extends HtmlDescribable {
return $ae;
}
/**
* Create elements for stylesheets
*/
function _createStylesheetReferences() {
$xml = "";
if ($this->cssStyleSheet) $xml .= "<?xml-stylesheet href=\"".$this->cssStyleSheet."\" type=\"text/css\"?>\n";
@ -610,8 +632,8 @@ class FeedCreator extends HtmlDescribable {
* before anything else, especially before you do the time consuming task to build the feed
* (web fetching, for example).
* @since 1.4
* @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
* @param $filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param $timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
*/
function useCached($filename="", $timeout=3600) {
$this->_timeout = $timeout;
@ -629,8 +651,8 @@ class FeedCreator extends HtmlDescribable {
* header may be sent to redirect the user to the newly created file.
* @since 1.4
*
* @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param redirect boolean optional send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.
* @param $filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
* @param $displayContents boolean optional send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.
*/
function saveFeed($filename="", $displayContents=true) {
if ($filename=="") {
@ -667,6 +689,7 @@ class FeedCreator extends HtmlDescribable {
* Usually, you won't need to use this.
*/
class FeedDate {
/** @var int */
var $unix;
/**
@ -726,7 +749,7 @@ class FeedDate {
/**
* Gets the date stored in this FeedDate as an RFC 822 date.
*
* @return a date in RFC 822 format
* @return string a date in RFC 822 format
*/
function rfc822() {
//return gmdate("r",$this->unix);
@ -738,7 +761,7 @@ class FeedDate {
/**
* Gets the date stored in this FeedDate as an ISO 8601 date.
*
* @return a date in ISO 8601 (RFC 3339) format
* @return string a date in ISO 8601 (RFC 3339) format
*/
function iso8601() {
$date = gmdate("Y-m-d\TH:i:sO",$this->unix);
@ -751,7 +774,7 @@ class FeedDate {
/**
* Gets the date stored in this FeedDate as unix time stamp.
*
* @return a date as a unix time stamp
* @return int a date as a unix time stamp
*/
function unix() {
return $this->unix;
@ -777,7 +800,7 @@ class RSSCreator10 extends FeedCreator {
$feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
$feed.= $this->_createGeneratorComment();
if ($this->cssStyleSheet=="") {
$cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
$this->cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
}
$feed.= $this->_createStylesheetReferences();
$feed.= "<rdf:RDF\n";
@ -1032,12 +1055,16 @@ class PIECreator01 extends FeedCreator {
$this->encoding = "utf-8";
}
/**
* Build content
* @return string
*/
function createFeed() {
$feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
$feed.= $this->_createStylesheetReferences();
$feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n";
$feed.= " <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
$this->truncSize = 500;
$this->descriptionTruncSize = 500;
$feed.= " <subtitle>".$this->getDescription()."</subtitle>\n";
$feed.= " <link>".$this->link."</link>\n";
$icnt = count($this->items);
@ -1091,6 +1118,10 @@ class AtomCreator10 extends FeedCreator {
$this->encoding = "utf-8";
}
/**
* Build content
* @return string
*/
function createFeed() {
$feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
$feed.= $this->_createGeneratorComment();
@ -1174,6 +1205,10 @@ class AtomCreator03 extends FeedCreator {
$this->encoding = "utf-8";
}
/**
* Build content
* @return string
*/
function createFeed() {
$feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
$feed.= $this->_createGeneratorComment();
@ -1281,6 +1316,7 @@ class MBOXCreator extends FeedCreator {
*/
function createFeed() {
$icnt = count($this->items);
$feed = "";
for ($i=0; $i<$icnt; $i++) {
if ($this->items[$i]->author!="") {
$from = $this->items[$i]->author;
@ -1331,6 +1367,10 @@ class OPMLCreator extends FeedCreator {
$this->encoding = "utf-8";
}
/**
* Build content
* @return string
*/
function createFeed() {
$feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
$feed.= $this->_createGeneratorComment();
@ -1441,6 +1481,7 @@ class HTMLCreator extends FeedCreator {
}
//set an openInNewWindow_token_to be inserted or not
$targetInsert = "";
if ($this->openInNewWindow) {
$targetInsert = " target='_blank'";
}
@ -1568,6 +1609,14 @@ class JSCreator extends HTMLCreator {
* @author Andreas Gohr <andi@splitbrain.org>
*/
class DokuWikiFeedCreator extends UniversalFeedCreator{
/**
* Build content
*
* @param string $format
* @param string $encoding
* @return string
*/
function createFeed($format = "RSS0.91",$encoding='iso-8859-15') {
$this->_setFormat($format);
$this->_feed->encoding = $encoding;

View File

@ -77,7 +77,7 @@ function sendFile($file, $mime, $dl, $cache, $public = false, $orig = null) {
}
//use x-sendfile header to pass the delivery to compatible webservers
if(http_sendfile($file)) exit;
http_sendfile($file);
// send file contents
$fp = @fopen($file, "rb");

View File

@ -47,15 +47,11 @@ class Doku_Form {
* with up to four parameters is deprecated, instead the first parameter
* should be an array with parameters.
*
* @param mixed $params Parameters for the HTML form element; Using the
* deprecated calling convention this is the ID
* attribute of the form
* @param string $action (optional, deprecated) submit URL, defaults to
* current page
* @param string $method (optional, deprecated) 'POST' or 'GET', default
* is POST
* @param string $enctype (optional, deprecated) Encoding type of the
* data
* @param mixed $params Parameters for the HTML form element; Using the deprecated
* calling convention this is the ID attribute of the form
* @param bool|string $action (optional, deprecated) submit URL, defaults to current page
* @param bool|string $method (optional, deprecated) 'POST' or 'GET', default is POST
* @param bool|string $enctype (optional, deprecated) Encoding type of the data
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function Doku_Form($params, $action=false, $method=false, $enctype=false) {
@ -135,7 +131,7 @@ class Doku_Form {
* The element can be either a pseudo-tag or string.
* If string, it is printed without escaping special chars. *
*
* @param string $elem Pseudo-tag or string to add to the form.
* @param string|array $elem Pseudo-tag or string to add to the form.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function addElement($elem) {
@ -147,8 +143,8 @@ class Doku_Form {
*
* Inserts a content element at a position.
*
* @param string $pos 0-based index where the element will be inserted.
* @param string $elem Pseudo-tag or string to add to the form.
* @param string $pos 0-based index where the element will be inserted.
* @param string|array $elem Pseudo-tag or string to add to the form.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function insertElement($pos, $elem) {
@ -160,8 +156,8 @@ class Doku_Form {
*
* Replace with NULL to remove an element.
*
* @param int $pos 0-based index the element will be placed at.
* @param string $elem Pseudo-tag or string to add to the form.
* @param int $pos 0-based index the element will be placed at.
* @param string|array $elem Pseudo-tag or string to add to the form.
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function replaceElement($pos, $elem) {
@ -176,7 +172,7 @@ class Doku_Form {
* Gets the position of the first of a type of element.
*
* @param string $type Element type to look for.
* @return array pseudo-element if found, false otherwise
* @return int position of element if found, otherwise false
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function findElementByType($type) {
@ -193,7 +189,7 @@ class Doku_Form {
* Gets the position of the element with an ID attribute.
*
* @param string $id ID of the element to find.
* @return array pseudo-element if found, false otherwise
* @return int position of element if found, otherwise false
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function findElementById($id) {
@ -211,7 +207,7 @@ class Doku_Form {
*
* @param string $name Attribute name.
* @param string $value Attribute value.
* @return array pseudo-element if found, false otherwise
* @return int position of element if found, otherwise false
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function findElementByAttribute($name, $value) {
@ -230,7 +226,7 @@ class Doku_Form {
* first (underflow) or last (overflow) element.
*
* @param int $pos 0-based index
* @return arrayreference pseudo-element
* @return array reference pseudo-element
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
function &getElementAt($pos) {
@ -565,10 +561,11 @@ function form_makeListboxField($name, $values, $selected='', $label=null, $id=''
if (is_null($label)) $label = $name;
$options = array();
reset($values);
if (is_null($selected) || $selected == '')
if (is_null($selected) || $selected == '') {
$selected = array();
elseif (!is_array($selected))
} elseif (!is_array($selected)) {
$selected = array($selected);
}
// FIXME: php doesn't know the difference between a string and an integer
if (is_string(key($values))) {
foreach ($values as $val=>$text) {
@ -576,11 +573,13 @@ function form_makeListboxField($name, $values, $selected='', $label=null, $id=''
}
} else {
foreach ($values as $val) {
if (is_array($val))
@list($val,$text) = $val;
else
$disabled = false;
if (is_array($val)) {
@list($val,$text,$disabled) = $val;
} else {
$text = null;
$options[] = array($val,$text,in_array($val,$selected));
}
$options[] = array($val,$text,in_array($val,$selected),$disabled);
}
}
$elem = array('_elem'=>'listboxfield', '_options'=>$options, '_text'=>$label, '_class'=>$class,
@ -934,11 +933,12 @@ function form_listboxfield($attrs) {
$s .= '<select '.buildAttributes($attrs,true).'>'.DOKU_LF;
if (!empty($attrs['_options'])) {
foreach ($attrs['_options'] as $opt) {
@list($value,$text,$select) = $opt;
@list($value,$text,$select,$disabled) = $opt;
$p = '';
if(is_null($text)) $text = $value;
$p .= ' value="'.formText($value).'"';
if (!empty($select)) $p .= ' selected="selected"';
if ($disabled) $p .= ' disabled="disabled"';
$s .= '<option'.$p.'>'.formText($text).'</option>';
}
} else {

View File

@ -72,8 +72,20 @@ function _ft_pageSearch(&$data) {
$pages = end($stack);
$pages_matched = array();
foreach(array_keys($pages) as $id){
$text = utf8_strtolower(rawWiki($id));
if (strpos($text, $phrase) !== false) {
$evdata = array(
'id' => $id,
'phrase' => $phrase,
'text' => rawWiki($id)
);
$evt = new Doku_Event('FULLTEXT_PHRASE_MATCH',$evdata);
if ($evt->advise_before() && $evt->result !== true) {
$text = utf8_strtolower($evdata['text']);
if (strpos($text, $phrase) !== false) {
$evt->result = true;
}
}
$evt->advise_after();
if ($evt->result === true) {
$pages_matched[$id] = 0; // phrase: always 0 hit
}
}
@ -333,7 +345,7 @@ function ft_snippet($id,$highlight){
$pre = min($pre,100-$post);
} else if ($post>50) {
$post = min($post, 100-$pre);
} else {
} else if ($offset == 0) {
// both are less than 50, means the context is the whole string
// make it so and break out of this loop - there is no need for the
// complex snippet calculations
@ -354,12 +366,12 @@ function ft_snippet($id,$highlight){
}
// set $offset for next match attempt
// substract strlen to avoid splitting a potential search success,
// this is an approximation as the search pattern may match strings
// of varying length and it will fail if the context snippet
// boundary breaks a matching string longer than the current match
$utf8_offset = $utf8_idx + $post;
$offset = $idx + strlen(utf8_substr($text,$utf8_idx,$post));
// continue matching after the current match
// if the current match is not the longest possible match starting at the current offset
// this prevents further matching of this snippet but for possible matches of length
// smaller than match length + context (at least 50 characters) this match is part of the context
$utf8_offset = $utf8_idx + $utf8_len;
$offset = $idx + strlen(utf8_substr($text,$utf8_idx,$utf8_len));
$offset = utf8_correctIdx($text,$offset);
}

View File

@ -19,6 +19,7 @@ if(!defined('NL')) define('NL',"\n");
* @return string the HTML code of the link
*/
function html_wikilink($id,$name=null,$search=''){
/** @var Doku_Renderer_xhtml $xhtml_renderer */
static $xhtml_renderer = null;
if(is_null($xhtml_renderer)){
$xhtml_renderer = p_get_renderer('xhtml');
@ -64,6 +65,20 @@ function html_login(){
print '</div>'.NL;
}
/**
* Denied page content
*
* @return string html
*/
function html_denied() {
print p_locale_xhtml('denied');
if(!$_SERVER['REMOTE_USER']){
html_login();
}
}
/**
* inserts section edit buttons if wanted or removes the markers
*
@ -396,8 +411,8 @@ function html_locked(){
print p_locale_xhtml('locked');
print '<ul>';
print '<li><div class="li"><strong>'.$lang['lockedby'].':</strong> '.editorinfo($INFO['locked']).'</div></li>';
print '<li><div class="li"><strong>'.$lang['lockexpire'].':</strong> '.$expire.' ('.$min.' min)</div></li>';
print '<li><div class="li"><strong>'.$lang['lockedby'].'</strong> '.editorinfo($INFO['locked']).'</div></li>';
print '<li><div class="li"><strong>'.$lang['lockexpire'].'</strong> '.$expire.' ('.$min.' min)</div></li>';
print '</ul>';
}
@ -414,20 +429,23 @@ function html_revisions($first=0, $media_id = false){
global $conf;
global $lang;
$id = $ID;
if ($media_id) {
$id = $media_id;
$changelog = new MediaChangeLog($id);
} else {
$changelog = new PageChangeLog($id);
}
/* 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 html_recent()
*/
if (!$media_id) $revisions = getRevisions($ID, $first, $conf['recent']+1);
else {
$revisions = getRevisions($media_id, $first, $conf['recent']+1, 8192, true);
$id = $media_id;
}
$revisions = $changelog->getRevisions($first, $conf['recent']+1);
if(count($revisions)==0 && $first!=0){
$first=0;
if (!$media_id) $revisions = getRevisions($ID, $first, $conf['recent']+1);
else $revisions = getRevisions($media_id, $first, $conf['recent']+1, 8192, true);
$revisions = $changelog->getRevisions($first, $conf['recent']+1);
}
$hasNext = false;
if (count($revisions)>$conf['recent']) {
@ -486,15 +504,18 @@ function html_revisions($first=0, $media_id = false){
$form->addElement(form_makeCloseTag('span'));
}
$changelog->setChunkSize(1024);
$form->addElement(form_makeOpenTag('span', array('class' => 'user')));
if (!$media_id) $editor = $INFO['editor'];
else {
$revinfo = getRevisionInfo($id, @filemtime(fullpath(mediaFN($id))), 1024, true);
if($revinfo['user']){
if($media_id) {
$revinfo = $changelog->getRevisionInfo(@filemtime(fullpath(mediaFN($id))));
if($revinfo['user']) {
$editor = $revinfo['user'];
}else{
} else {
$editor = $revinfo['ip'];
}
} else {
$editor = $INFO['editor'];
}
$form->addElement((empty($editor))?('('.$lang['external_edit'].')'):editorinfo($editor));
$form->addElement(form_makeCloseTag('span'));
@ -509,12 +530,11 @@ function html_revisions($first=0, $media_id = false){
foreach($revisions as $rev){
$date = dformat($rev);
if (!$media_id) {
$info = getRevisionInfo($id,$rev,true);
$exists = page_exists($id,$rev);
} else {
$info = getRevisionInfo($id,$rev,true,true);
$exists = @file_exists(mediaFN($id,$rev));
$info = $changelog->getRevisionInfo($rev);
if($media_id) {
$exists = @file_exists(mediaFN($id, $rev));
} else {
$exists = page_exists($id, $rev);
}
if ($info['type']===DOKU_CHANGE_TYPE_MINOR_EDIT)
@ -691,7 +711,7 @@ function html_recent($first=0, $show_changes='both'){
$form->addElement(form_makeOpenTag('div', array('class' => 'li')));
if ($recent['media']) {
if (!empty($recent['media'])) {
$form->addElement(media_printicon($recent['id']));
} else {
$icon = DOKU_BASE.'lib/images/fileicons/file.png';
@ -705,7 +725,7 @@ function html_recent($first=0, $show_changes='both'){
$diff = false;
$href = '';
if ($recent['media']) {
if (!empty($recent['media'])) {
$diff = (count(getRevisions($recent['id'], 0, 1, 8192, true)) && @file_exists(mediaFN($recent['id'])));
if ($diff) {
$href = media_managerURL(array('tab_details' => 'history',
@ -715,7 +735,7 @@ function html_recent($first=0, $show_changes='both'){
$href = wl($recent['id'],"do=diff", false, '&');
}
if ($recent['media'] && !$diff) {
if (!empty($recent['media']) && !$diff) {
$form->addElement('<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />');
} else {
$form->addElement(form_makeOpenTag('a', array('class' => 'diff_link', 'href' => $href)));
@ -729,7 +749,7 @@ function html_recent($first=0, $show_changes='both'){
$form->addElement(form_makeCloseTag('a'));
}
if ($recent['media']) {
if (!empty($recent['media'])) {
$href = media_managerURL(array('tab_details' => 'history',
'image' => $recent['id'], 'ns' => getNS($recent['id'])), '&');
} else {
@ -745,7 +765,7 @@ function html_recent($first=0, $show_changes='both'){
)));
$form->addElement(form_makeCloseTag('a'));
if ($recent['media']) {
if (!empty($recent['media'])) {
$href = media_managerURL(array('tab_details' => 'view', 'image' => $recent['id'], 'ns' => getNS($recent['id'])), '&');
$class = (file_exists(mediaFN($recent['id']))) ? 'wikilink1' : $class = 'wikilink2';
$form->addElement(form_makeOpenTag('a', array('class' => $class, 'href' => $href)));
@ -902,6 +922,14 @@ function html_li_default($item){
* a member of an object.
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param array $data array with item arrays
* @param string $class class of ul wrapper
* @param callable $func callback to print an list item
* @param string $lifunc callback to the opening li tag
* @param bool $forcewrapper Trigger building a wrapper ul if the first level is
0 (we have a root object) or 1 (just the root content)
* @return string html of an unordered list
*/
function html_buildlist($data,$class,$func,$lifunc='html_li_default',$forcewrapper=false){
if (count($data) === 0) {
@ -1008,10 +1036,15 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
$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 = '&mdash;';
}else{
$l_info = getRevisionInfo($id,$l_rev,true, $media);
$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>';
@ -1029,7 +1062,7 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
}
if($r_rev){
$r_info = getRevisionInfo($id,$r_rev,true, $media);
$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>';
@ -1045,7 +1078,7 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
$r_head_title.'</a></bdi>'.
$head_separator.$r_user.' '.$r_sum;
}elseif($_rev = @filemtime($media_or_wikiFN($id))){
$_info = getRevisionInfo($id,$_rev,true, $media);
$_info = $changelog->getRevisionInfo($_rev);
if($_info['user']){
$_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
if(auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
@ -1069,162 +1102,386 @@ function html_diff_head($l_rev, $r_rev, $id = null, $media = false, $inline = fa
}
/**
* show diff
* Show diff
* between current page version and provided $text
* or between the revisions provided via GET or POST
*
* @author Andreas Gohr <andi@splitbrain.org>
* @param string $text - compare with this text with most current version
* @param bool $intro - display the intro text
* @param string $type type of the diff (inline or sidebyside)
* @param string $text when non-empty: compare with this text with most current version
* @param bool $intro display the intro text
* @param string $type type of the diff (inline or sidebyside)
*/
function html_diff($text='',$intro=true,$type=null){
function html_diff($text = '', $intro = true, $type = null) {
global $ID;
global $REV;
global $lang;
global $INPUT;
global $INFO;
$pagelog = new PageChangeLog($ID);
/*
* Determine diff type
*/
if(!$type) {
$type = $INPUT->str('difftype');
if (empty($type)) {
if(empty($type)) {
$type = get_doku_pref('difftype', $type);
if (empty($type) && $INFO['ismobile']) {
if(empty($type) && $INFO['ismobile']) {
$type = 'inline';
}
}
}
if($type != 'inline') $type = 'sidebyside';
/*
* 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;
$rev2 = $INPUT->ref('rev2');
if(is_array($rev2)){
if(is_array($rev2)) {
$rev1 = (int) $rev2[0];
$rev2 = (int) $rev2[1];
if(!$rev1){
if(!$rev1) {
$rev1 = $rev2;
unset($rev2);
}
}else{
} else {
$rev2 = $INPUT->int('rev2');
}
/*
* Determine left and right revision, its texts and the header
*/
$r_minor = '';
$l_minor = '';
if($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> '.
if($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($text);
$r_head = $lang['yours'];
}else{
if($rev1 && isset($rev2) && $rev2){ // two specific revisions wanted
$r_rev = '';
$r_text = cleanText($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){
if($rev1 < $rev2) {
$l_rev = $rev1;
$r_rev = $rev2;
}else{
} else {
$l_rev = $rev2;
$r_rev = $rev1;
}
}elseif($rev1){ // single revision given, compare to current
} elseif($rev1) { // single revision given, compare to current
$r_rev = '';
$l_rev = $rev1;
}else{ // no revision was given, compare previous to current
} else { // no revision was given, compare previous to current
$r_rev = '';
$revs = getRevisions($ID, 0, 1);
$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){
if(!$l_rev && !$r_rev) {
$l_text = '';
}else{
$l_text = rawWiki($ID,$l_rev);
} else {
$l_text = rawWiki($ID, $l_rev);
}
$r_text = rawWiki($ID,$r_rev);
$r_text = rawWiki($ID, $r_rev);
list($l_head, $r_head, $l_minor, $r_minor) = html_diff_head($l_rev, $r_rev, null, false, $type == 'inline');
}
$df = new Diff(explode("\n",$l_text),explode("\n",$r_text));
if($type == 'inline'){
$tdf = new InlineDiffFormatter();
} else {
$tdf = new TableDiffFormatter();
/*
* Build navigation
*/
$l_nav = '';
$r_nav = '';
if(!$text) {
list($l_nav, $r_nav) = html_diff_navigation($pagelog, $type, $l_rev, $r_rev);
}
/*
* Create diff object and the formatter
*/
$diff = new Diff(explode("\n", $l_text), explode("\n", $r_text));
if($type == 'inline') {
$diffformatter = new InlineDiffFormatter();
} else {
$diffformatter = new TableDiffFormatter();
}
/*
* Display intro
*/
if($intro) print p_locale_xhtml('diff');
if (!$text) {
ptln('<div class="diffoptions">');
/*
* Display type and exact reference
*/
if(!$text) {
ptln('<div class="diffoptions group">');
$form = new Doku_Form(array('action'=>wl()));
$form->addHidden('id',$ID);
$form->addHidden('rev2[0]',$l_rev);
$form->addHidden('rev2[1]',$r_rev);
$form->addHidden('do','diff');
$form->addElement(form_makeListboxField(
'difftype',
array(
'sidebyside' => $lang['diff_side'],
'inline' => $lang['diff_inline']),
$type,
$lang['diff_type'],
'','',
array('class'=>'quickselect')));
$form->addElement(form_makeButton('submit', 'diff','Go'));
$form = new Doku_Form(array('action' => wl()));
$form->addHidden('id', $ID);
$form->addHidden('rev2[0]', $l_rev);
$form->addHidden('rev2[1]', $r_rev);
$form->addHidden('do', 'diff');
$form->addElement(
form_makeListboxField(
'difftype',
array(
'sidebyside' => $lang['diff_side'],
'inline' => $lang['diff_inline']
),
$type,
$lang['diff_type'],
'', '',
array('class' => 'quickselect')
)
);
$form->addElement(form_makeButton('submit', 'diff', 'Go'));
$form->printForm();
$diffurl = wl($ID, array(
'do' => 'diff',
'rev2[0]' => $l_rev,
'rev2[1]' => $r_rev,
'difftype' => $type,
));
ptln('<p><a class="wikilink1" href="'.$diffurl.'">'.$lang['difflink'].'</a></p>');
ptln('</div>');
ptln('<p>');
// link to exactly this view FS#2835
echo html_diff_navigationlink($type, 'difflink', $l_rev, $r_rev ? $r_rev : $INFO['currentrev']);
ptln('</p>');
ptln('</div>'); // .diffoptions
}
/*
* Display diff view table
*/
?>
<div class="table">
<table class="diff diff_<?php echo $type?>">
<?php if ($type == 'inline') { ?>
<tr>
<th class="diff-lineheader">-</th><th <?php echo $l_minor?>>
<?php echo $l_head?>
</th>
</tr>
<tr>
<th class="diff-lineheader">+</th><th <?php echo $r_minor?>>
<?php echo $r_head?>
</th>
</tr>
<?php } else { ?>
<tr>
<th colspan="2" <?php echo $l_minor?>>
<?php echo $l_head?>
</th>
<th colspan="2" <?php echo $r_minor?>>
<?php echo $r_head?>
</th>
</tr>
<?php }
echo html_insert_softbreaks($tdf->format($df)); ?>
<table class="diff diff_<?php echo $type ?>">
<?php
//navigation and header
if($type == 'inline') {
if(!$text) { ?>
<tr>
<td class="diff-lineheader">-</td>
<td class="diffnav"><?php echo $l_nav ?></td>
</tr>
<tr>
<th class="diff-lineheader">-</th>
<th <?php echo $l_minor ?>>
<?php echo $l_head ?>
</th>
</tr>
<?php } ?>
<tr>
<td class="diff-lineheader">+</td>
<td class="diffnav"><?php echo $r_nav ?></td>
</tr>
<tr>
<th class="diff-lineheader">+</th>
<th <?php echo $r_minor ?>>
<?php echo $r_head ?>
</th>
</tr>
<?php } else {
if(!$text) { ?>
<tr>
<td colspan="2" class="diffnav"><?php echo $l_nav ?></td>
<td colspan="2" class="diffnav"><?php echo $r_nav ?></td>
</tr>
<?php } ?>
<tr>
<th colspan="2" <?php echo $l_minor ?>>
<?php echo $l_head ?>
</th>
<th colspan="2" <?php echo $r_minor ?>>
<?php echo $r_head ?>
</th>
</tr>
<?php }
//diff view
echo html_insert_softbreaks($diffformatter->format($diff)); ?>
</table>
</div>
<?php
<?php
}
/**
* Create html for revision navigation
*
* @param PageChangeLog $pagelog changelog object of current page
* @param string $type inline vs sidebyside
* @param int $l_rev left revision timestamp
* @param int $r_rev right revision timestamp
* @return string[] html of left and right navigation elements
*/
function html_diff_navigation($pagelog, $type, $l_rev, $r_rev) {
global $INFO, $ID;
// last timestamp is not in changelog, retrieve timestamp from metadata
// note: when page is removed, the metadata timestamp is zero
$r_rev = $r_rev ? $r_rev : $INFO['meta']['last_change']['date'];
//retrieve revisions with additional info
list($l_revs, $r_revs) = $pagelog->getRevisionsAround($l_rev, $r_rev);
$l_revisions = array();
if(!$l_rev) {
$l_revisions[0] = array(0, "", false); //no left revision given, add dummy
}
foreach($l_revs as $rev) {
$info = $pagelog->getRevisionInfo($rev);
$l_revisions[$rev] = array(
$rev,
dformat($info['date']) . ' ' . editorinfo($info['user'], true) . ' ' . $info['sum'],
$r_rev ? $rev >= $r_rev : false //disable?
);
}
$r_revisions = array();
if(!$r_rev) {
$r_revisions[0] = array(0, "", false); //no right revision given, add dummy
}
foreach($r_revs as $rev) {
$info = $pagelog->getRevisionInfo($rev);
$r_revisions[$rev] = array(
$rev,
dformat($info['date']) . ' ' . editorinfo($info['user'], true) . ' ' . $info['sum'],
$rev <= $l_rev //disable?
);
}
//determine previous/next revisions
$l_index = array_search($l_rev, $l_revs);
$l_prev = $l_revs[$l_index + 1];
$l_next = $l_revs[$l_index - 1];
if($r_rev) {
$r_index = array_search($r_rev, $r_revs);
$r_prev = $r_revs[$r_index + 1];
$r_next = $r_revs[$r_index - 1];
} else {
//removed page
if($l_next) {
$r_prev = $r_revs[0];
} else {
$r_prev = null;
}
$r_next = null;
}
/*
* Left side:
*/
$l_nav = '';
//move back
if($l_prev) {
$l_nav .= html_diff_navigationlink($type, 'diffbothprevrev', $l_prev, $r_prev);
$l_nav .= html_diff_navigationlink($type, 'diffprevrev', $l_prev, $r_rev);
}
//dropdown
$form = new Doku_Form(array('action' => wl()));
$form->addHidden('id', $ID);
$form->addHidden('difftype', $type);
$form->addHidden('rev2[1]', $r_rev);
$form->addHidden('do', 'diff');
$form->addElement(
form_makeListboxField(
'rev2[0]',
$l_revisions,
$l_rev,
'', '', '',
array('class' => 'quickselect')
)
);
$form->addElement(form_makeButton('submit', 'diff', 'Go'));
$l_nav .= $form->getForm();
//move forward
if($l_next && ($l_next < $r_rev || !$r_rev)) {
$l_nav .= html_diff_navigationlink($type, 'diffnextrev', $l_next, $r_rev);
}
/*
* Right side:
*/
$r_nav = '';
//move back
if($l_rev < $r_prev) {
$r_nav .= html_diff_navigationlink($type, 'diffprevrev', $l_rev, $r_prev);
}
//dropdown
$form = new Doku_Form(array('action' => wl()));
$form->addHidden('id', $ID);
$form->addHidden('rev2[0]', $l_rev);
$form->addHidden('difftype', $type);
$form->addHidden('do', 'diff');
$form->addElement(
form_makeListboxField(
'rev2[1]',
$r_revisions,
$r_rev,
'', '', '',
array('class' => 'quickselect')
)
);
$form->addElement(form_makeButton('submit', 'diff', 'Go'));
$r_nav .= $form->getForm();
//move forward
if($r_next) {
if($pagelog->isCurrentRevision($r_next)) {
$r_nav .= html_diff_navigationlink($type, 'difflastrev', $l_rev); //last revision is diff with current page
} else {
$r_nav .= html_diff_navigationlink($type, 'diffnextrev', $l_rev, $r_next);
}
$r_nav .= html_diff_navigationlink($type, 'diffbothnextrev', $l_next, $r_next);
}
return array($l_nav, $r_nav);
}
/**
* Create html link to a diff defined by two revisions
*
* @param string $difftype display type
* @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
*/
function html_diff_navigationlink($difftype, $linktype, $lrev, $rrev = null) {
global $ID, $lang;
if(!$rrev) {
$urlparam = array(
'do' => 'diff',
'rev' => $lrev,
'difftype' => $difftype,
);
} else {
$urlparam = array(
'do' => 'diff',
'rev2[0]' => $lrev,
'rev2[1]' => $rrev,
'difftype' => $difftype,
);
}
return '<a class="' . $linktype . '" href="' . wl($ID, $urlparam) . '" title="' . $lang[$linktype] . '">' .
'<span>' . $lang[$linktype] . '</span>' .
'</a>' . "\n";
}
/**
* Insert soft breaks in diff html
*
* @param $diffhtml
* @return string
*/
function html_insert_softbreaks($diffhtml) {
// search the diff html string for both:
// - html tags, so these can be ignored
@ -1232,6 +1489,12 @@ function html_insert_softbreaks($diffhtml) {
return preg_replace_callback('/<[^>]*>|[^<> ]{12,}/','html_softbreak_callback',$diffhtml);
}
/**
* callback which adds softbreaks
*
* @param array $match array with first the complete match
* @return string the replacement
*/
function html_softbreak_callback($match){
// if match is an html tag, return it intact
if ($match[0]{0} == '<') return $match[0];
@ -1343,7 +1606,7 @@ function html_updateprofile(){
global $conf;
global $INPUT;
global $INFO;
/** @var auth_basic $auth */
/** @var DokuWiki_Auth_Plugin $auth */
global $auth;
print p_locale_xhtml('updateprofile');
@ -1517,6 +1780,7 @@ function html_edit(){
* Display the default edit form
*
* Is the default action for HTML_EDIT_FORMSELECTION.
* @param mixed[] $param
*/
function html_edit_form($param) {
global $TEXT;
@ -1559,7 +1823,7 @@ function html_minoredit(){
function html_debug(){
global $conf;
global $lang;
/** @var auth_basic $auth */
/** @var DokuWiki_Auth_Plugin $auth */
global $auth;
global $INFO;
@ -1634,6 +1898,17 @@ function html_debug(){
print_r($inis);
print '</pre>';
if (function_exists('apache_get_version')) {
$apache['version'] = apache_get_version();
if (function_exists('apache_get_modules')) {
$apache['modules'] = apache_get_modules();
}
print '<b>Apache</b><pre>';
print_r($apache);
print '</pre>';
}
print '</body></html>';
}

View File

@ -64,12 +64,13 @@ function http_conditionalRequest($timestamp){
* Let the webserver send the given file via x-sendfile method
*
* @author Chris Smith <chris@jalakai.co.uk>
* @returns void or exits with previously header() commands executed
* @param string $file absolute path of file to send
* @returns void or exits with previous header() commands executed
*/
function http_sendfile($file) {
global $conf;
//use x-sendfile header to pass the delivery to compatible webservers
//use x-sendfile header to pass the delivery to compatible web servers
if($conf['xsendfile'] == 1){
header("X-LIGHTTPD-send-file: $file");
ob_end_clean();
@ -79,12 +80,12 @@ function http_sendfile($file) {
ob_end_clean();
exit;
}elseif($conf['xsendfile'] == 3){
// FS#2388 nginx just needs the relative path.
$file = DOKU_REL.substr($file, strlen(fullpath(DOKU_INC)) + 1);
header("X-Accel-Redirect: $file");
ob_end_clean();
exit;
}
return false;
}
/**
@ -92,7 +93,7 @@ function http_sendfile($file) {
*
* This function exits the running script
*
* @param ressource $fh - file handle for an already open file
* @param resource $fh - file handle for an already open file
* @param int $size - size of the whole file
* @param int $mime - MIME type of the file
*
@ -204,7 +205,7 @@ function http_gzip_valid($uncompressed_file) {
*
* This function handles output of cacheable resource files. It ses the needed
* HTTP headers. If a useable cache is present, it is passed to the web server
* and the scrpt is terminated.
* and the script is terminated.
*/
function http_cached($cache, $cache_ok) {
global $conf;
@ -223,7 +224,8 @@ function http_cached($cache, $cache_ok) {
header('Content-Encoding: gzip');
readfile($cache.".gz");
} else {
if (!http_sendfile($cache)) readfile($cache);
http_sendfile($cache);
readfile($cache);
}
exit;
}

View File

@ -270,8 +270,9 @@ class Doku_Indexer {
// Special handling for titles so the index file is simpler
if (array_key_exists('title', $key)) {
$value = $key['title'];
if (is_array($value))
if (is_array($value)) {
$value = $value[0];
}
$this->saveIndexKey('title', '', $pid, $value);
unset($key['title']);
}
@ -299,20 +300,24 @@ class Doku_Indexer {
if ($val !== "") {
$id = array_search($val, $metawords, true);
if ($id === false) {
// didn't find $val, so we'll add it to the end of metawords and create a placeholder in metaidx
$id = count($metawords);
$metawords[$id] = $val;
$metaidx[$id] = '';
$addwords = true;
}
// test if value is already in the index
if (isset($val_idx[$id]) && $val_idx[$id] <= 0)
if (isset($val_idx[$id]) && $val_idx[$id] <= 0){
$val_idx[$id] = 0;
else // else add it
} else { // else add it
$val_idx[$id] = 1;
}
}
}
if ($addwords)
if ($addwords) {
$this->saveIndex($metaname.'_w', '', $metawords);
}
$vals_changed = false;
foreach ($val_idx as $id => $action) {
if ($action == -1) {
@ -1213,17 +1218,18 @@ class Doku_Indexer {
* @author Tom N Harris <tnharris@whoopdedo.org>
*/
protected function updateTuple($line, $id, $count) {
$newLine = $line;
if ($newLine !== '')
$newLine = preg_replace('/(^|:)'.preg_quote($id,'/').'\*\d*/', '', $newLine);
$newLine = trim($newLine, ':');
if ($count) {
if (strlen($newLine) > 0)
return "$id*$count:".$newLine;
else
return "$id*$count".$newLine;
if ($line != ''){
$line = preg_replace('/(^|:)'.preg_quote($id,'/').'\*\d*/', '', $line);
}
return $newLine;
$line = trim($line, ':');
if ($count) {
if ($line) {
return "$id*$count:".$line;
} else {
return "$id*$count";
}
}
return $line;
}
/**

View File

@ -102,15 +102,21 @@ function getVersion(){
function check(){
global $conf;
global $INFO;
/* @var Input $INPUT */
global $INPUT;
if ($INFO['isadmin'] || $INFO['ismanager']){
msg('DokuWiki version: '.getVersion(),1);
}
if(version_compare(phpversion(),'5.2.0','<')){
msg('Your PHP version is too old ('.phpversion().' vs. 5.2.0+ needed)',-1);
}else{
msg('PHP version '.phpversion(),1);
if(version_compare(phpversion(),'5.2.0','<')){
msg('Your PHP version is too old ('.phpversion().' vs. 5.2.0+ needed)',-1);
}else{
msg('PHP version '.phpversion(),1);
}
} else {
if(version_compare(phpversion(),'5.2.0','<')){
msg('Your PHP version is too old',-1);
}
}
$mem = (int) php_to_byte(ini_get('memory_limit'));
@ -200,7 +206,7 @@ function check(){
}
if($INFO['userinfo']['name']){
msg('You are currently logged in as '.$_SERVER['REMOTE_USER'].' ('.$INFO['userinfo']['name'].')',0);
msg('You are currently logged in as '.$INPUT->server->str('REMOTE_USER').' ('.$INFO['userinfo']['name'].')',0);
msg('You are part of the groups '.join($INFO['userinfo']['grps'],', '),0);
}else{
msg('You are currently not logged in',0);
@ -274,6 +280,15 @@ define('MSG_USERS_ONLY', 1);
define('MSG_MANAGERS_ONLY',2);
define('MSG_ADMINS_ONLY',4);
/**
* Display a message to the user
*
* @param string $message
* @param int $lvl -1 = error, 0 = info, 1 = success, 2 = notify
* @param string $line line number
* @param string $file file number
* @param int $allow who's allowed to see the message, see MSG_* constants
*/
function msg($message,$lvl=0,$line='',$file='',$allow=MSG_PUBLIC){
global $MSG, $MSG_shown;
$errors[-1] = 'error';
@ -303,6 +318,7 @@ function msg($message,$lvl=0,$line='',$file='',$allow=MSG_PUBLIC){
* lvl => int, level of the message (see msg() function)
* allow => int, flag used to determine who is allowed to see the message
* see MSG_* constants
* @return bool
*/
function info_msg_allowed($msg){
global $INFO, $auth;
@ -357,6 +373,9 @@ function dbg($msg,$hidden=false){
*/
function dbglog($msg,$header=''){
global $conf;
/* @var Input $INPUT */
global $INPUT;
// The debug log isn't automatically cleaned thus only write it when
// debugging has been enabled by the user.
if($conf['allowdebug'] !== 1) return;
@ -369,11 +388,37 @@ function dbglog($msg,$header=''){
$file = $conf['cachedir'].'/debug.log';
$fh = fopen($file,'a');
if($fh){
fwrite($fh,date('H:i:s ').$_SERVER['REMOTE_ADDR'].': '.$msg."\n");
fwrite($fh,date('H:i:s ').$INPUT->server->str('REMOTE_ADDR').': '.$msg."\n");
fclose($fh);
}
}
/**
* Log accesses to deprecated fucntions to the debug log
*
* @param string $alternative The function or method that should be used instead
*/
function dbg_deprecated($alternative = '') {
global $conf;
if(!$conf['allowdebug']) return;
$backtrace = debug_backtrace();
array_shift($backtrace);
$self = array_shift($backtrace);
$call = array_shift($backtrace);
$called = trim($self['class'].'::'.$self['function'].'()', ':');
$caller = trim($call['class'].'::'.$call['function'].'()', ':');
$msg = $called.' is deprecated. It was called from ';
$msg .= $caller.' in '.$call['file'].':'.$call['line'];
if($alternative) {
$msg .= ' '.$alternative.' should be used instead!';
}
dbglog($msg);
}
/**
* Print a reversed, prettyprinted backtrace
*

View File

@ -140,18 +140,21 @@ if ($conf['gzip_output'] &&
}
// init session
if (!headers_sent() && !defined('NOSESSION')){
session_name("DokuWiki");
$cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
if (version_compare(PHP_VERSION, '5.2.0', '>')) {
session_set_cookie_params(0,$cookieDir,'',($conf['securecookie'] && is_ssl()),true);
}else{
session_set_cookie_params(0,$cookieDir,'',($conf['securecookie'] && is_ssl()));
if(!headers_sent() && !defined('NOSESSION')) {
if(!defined('DOKU_SESSION_NAME')) define ('DOKU_SESSION_NAME', "DokuWiki");
if(!defined('DOKU_SESSION_LIFETIME')) define ('DOKU_SESSION_LIFETIME', 0);
if(!defined('DOKU_SESSION_PATH')) {
$cookieDir = empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'];
define ('DOKU_SESSION_PATH', $cookieDir);
}
if(!defined('DOKU_SESSION_DOMAIN')) define ('DOKU_SESSION_DOMAIN', '');
session_name(DOKU_SESSION_NAME);
session_set_cookie_params(DOKU_SESSION_LIFETIME, DOKU_SESSION_PATH, DOKU_SESSION_DOMAIN, ($conf['securecookie'] && is_ssl()), true);
session_start();
// load left over messages
if(isset($_SESSION[DOKU_COOKIE]['msg'])){
if(isset($_SESSION[DOKU_COOKIE]['msg'])) {
$MSG = $_SESSION[DOKU_COOKIE]['msg'];
unset($_SESSION[DOKU_COOKIE]['msg']);
}
@ -173,7 +176,7 @@ if(function_exists('set_magic_quotes_runtime')) @set_magic_quotes_runtime(0);
$_REQUEST = array_merge($_GET,$_POST);
// we don't want a purge URL to be digged
if(isset($_REQUEST['purge']) && $_SERVER['HTTP_REFERER']) unset($_REQUEST['purge']);
if(isset($_REQUEST['purge']) && !empty($_SERVER['HTTP_REFERER'])) unset($_REQUEST['purge']);
// disable gzip if not available
if($conf['compression'] == 'bz2' && !function_exists('bzopen')){
@ -183,11 +186,6 @@ if($conf['compression'] == 'gz' && !function_exists('gzopen')){
$conf['compression'] = 0;
}
// fix dateformat for upgraders
if(strpos($conf['dformat'],'%') === false){
$conf['dformat'] = '%Y/%m/%d %H:%M';
}
// precalculate file creation modes
init_creationmodes();
@ -404,6 +402,10 @@ function remove_magic_quotes(&$array) {
* Returns the full absolute URL to the directory where
* DokuWiki is installed in (includes a trailing slash)
*
* !! Can not access $_SERVER values through $INPUT
* !! here as this function is called before $INPUT is
* !! initialized.
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function getBaseURL($abs=null){
@ -443,12 +445,12 @@ function getBaseURL($abs=null){
//split hostheader into host and port
if(isset($_SERVER['HTTP_HOST'])){
$parsed_host = parse_url('http://'.$_SERVER['HTTP_HOST']);
$host = $parsed_host['host'];
$port = $parsed_host['port'];
$host = isset($parsed_host['host']) ? $parsed_host['host'] : null;
$port = isset($parsed_host['port']) ? $parsed_host['port'] : null;
}elseif(isset($_SERVER['SERVER_NAME'])){
$parsed_host = parse_url('http://'.$_SERVER['SERVER_NAME']);
$host = $parsed_host['host'];
$port = $parsed_host['port'];
$host = isset($parsed_host['host']) ? $parsed_host['host'] : null;
$port = isset($parsed_host['port']) ? $parsed_host['port'] : null;
}else{
$host = php_uname('n');
$port = '';

View File

@ -367,8 +367,6 @@ function io_createNamespace($id, $ns_type='pages') {
* @author Andreas Gohr <andi@splitbrain.org>
*/
function io_makeFileDir($file){
global $conf;
$dir = dirname($file);
if(!@is_dir($dir)){
io_mkdir_p($dir) || msg("Creating directory $dir failed",-1);

View File

@ -25,7 +25,7 @@ $lang['btn_back'] = 'Terug';
$lang['btn_backlink'] = 'Wat skakel hierheen';
$lang['btn_subscribe'] = 'Hou bladsy dop';
$lang['btn_register'] = 'Skep gerus \'n rekening';
$lang['loggedinas'] = 'Ingeteken as';
$lang['loggedinas'] = 'Ingeteken as:';
$lang['user'] = 'Gebruikernaam';
$lang['pass'] = 'Wagwoord';
$lang['newpass'] = 'Nuive wagwoord';
@ -52,7 +52,7 @@ $lang['mediaroot'] = 'root';
$lang['toc'] = 'Inhoud';
$lang['current'] = 'huidige';
$lang['line'] = 'Streak';
$lang['youarehere'] = 'Jy is hier';
$lang['youarehere'] = 'Jy is hier:';
$lang['by'] = 'by';
$lang['restored'] = 'Het terug gegaan na vroeëre weergawe (%s)';
$lang['summary'] = 'Voorskou';
@ -63,8 +63,8 @@ $lang['qb_extlink'] = 'Eksterne skakel';
$lang['qb_hr'] = 'Horisontale streep';
$lang['qb_sig'] = 'Handtekening met datum';
$lang['admin_register'] = 'Skep gerus \'n rekening';
$lang['img_backto'] = 'Terug na';
$lang['img_date'] = 'Datem';
$lang['img_camera'] = 'Camera';
$lang['btn_img_backto'] = 'Terug na %s';
$lang['img_date'] = 'Datem:';
$lang['img_camera'] = 'Camera:';
$lang['i_wikiname'] = 'Wiki Naam';
$lang['i_funcna'] = 'PHP funksie <code>%s</code> is nie beskibaar nie. Miskien is dit af gehaal.';

View File

@ -1,3 +1,3 @@
====== لا صلاحيات ======
عذرا، ليس مصرح لك الاستمرار، لعلك نسيت تسجيل الدخول؟
عذرا، ليس مصرح لك الاستمرار

View File

@ -53,7 +53,7 @@ $lang['btn_register'] = 'سجّل';
$lang['btn_apply'] = 'طبق';
$lang['btn_media'] = 'مدير الوسائط';
$lang['btn_deleteuser'] = 'احذف حسابي الخاص';
$lang['loggedinas'] = 'داخل باسم';
$lang['loggedinas'] = 'داخل باسم:';
$lang['user'] = 'اسم المستخدم';
$lang['pass'] = 'كلمة السر';
$lang['newpass'] = 'كلمة سر جديدة';
@ -98,12 +98,12 @@ $lang['license'] = 'مالم يشر لخلاف ذلك، فإن ا
$lang['licenseok'] = 'لاحظ: بتحرير هذه الصفحة أنت توافق على ترخيص محتواها تحت الرخصة التالية:';
$lang['searchmedia'] = 'ابحث في أسماء الملفات:';
$lang['searchmedia_in'] = 'ابحث في %s';
$lang['txt_upload'] = 'اختر ملفاً للرفع';
$lang['txt_filename'] = 'رفع كـ (اختياري)';
$lang['txt_upload'] = 'اختر ملفاً للرفع:';
$lang['txt_filename'] = 'رفع كـ (اختياري):';
$lang['txt_overwrt'] = 'اكتب على ملف موجود';
$lang['maxuploadsize'] = 'الحجم الاقصى %s للملف';
$lang['lockedby'] = 'مقفلة حاليا لـ';
$lang['lockexpire'] = 'ينتهي القفل في';
$lang['lockedby'] = 'مقفلة حاليا لـ:';
$lang['lockexpire'] = 'ينتهي القفل في:';
$lang['js']['willexpire'] = 'سينتهي قفل تحرير هذه الصفحه خلال دقيقة.\nلتجنب التعارض استخدم زر المعاينة لتصفير مؤقت القفل.';
$lang['js']['notsavedyet'] = 'التعديلات غير المحفوظة ستفقد.';
$lang['js']['searchmedia'] = 'ابحث عن ملفات';
@ -184,9 +184,9 @@ $lang['diff_type'] = 'أظهر الفروق:';
$lang['diff_inline'] = 'ضمنا';
$lang['diff_side'] = 'جنبا إلى جنب';
$lang['line'] = 'سطر';
$lang['breadcrumb'] = 'أثر';
$lang['youarehere'] = 'أنت هنا';
$lang['lastmod'] = 'آخر تعديل';
$lang['breadcrumb'] = 'أثر:';
$lang['youarehere'] = 'أنت هنا:';
$lang['lastmod'] = 'آخر تعديل:';
$lang['by'] = 'بواسطة';
$lang['deleted'] = 'حذفت';
$lang['created'] = 'اُنشئت';
@ -239,20 +239,20 @@ $lang['admin_register'] = 'أضف مستخدما جديدا';
$lang['metaedit'] = 'تحرير البيانات الشمولية ';
$lang['metasaveerr'] = 'فشلت كتابة البيانات الشمولية';
$lang['metasaveok'] = 'حُفظت البيانات الشمولية';
$lang['img_backto'] = 'عودة إلى';
$lang['img_title'] = 'العنوان';
$lang['img_caption'] = 'وصف';
$lang['img_date'] = 'التاريخ';
$lang['img_fname'] = 'اسم الملف';
$lang['img_fsize'] = 'الحجم';
$lang['img_artist'] = 'المصور';
$lang['img_copyr'] = 'حقوق النسخ';
$lang['img_format'] = 'الهيئة';
$lang['img_camera'] = 'الكمرا';
$lang['img_keywords'] = 'كلمات مفتاحية';
$lang['img_width'] = 'العرض';
$lang['img_height'] = 'الإرتفاع';
$lang['img_manager'] = 'اعرض في مدير الوسائط';
$lang['btn_img_backto'] = 'عودة إلى %s';
$lang['img_title'] = 'العنوان:';
$lang['img_caption'] = 'وصف:';
$lang['img_date'] = 'التاريخ:';
$lang['img_fname'] = 'اسم الملف:';
$lang['img_fsize'] = 'الحجم:';
$lang['img_artist'] = 'المصور:';
$lang['img_copyr'] = 'حقوق النسخ:';
$lang['img_format'] = 'الهيئة:';
$lang['img_camera'] = 'الكمرا:';
$lang['img_keywords'] = 'كلمات مفتاحية:';
$lang['img_width'] = 'العرض:';
$lang['img_height'] = 'الإرتفاع:';
$lang['btn_mediaManager'] = 'اعرض في مدير الوسائط';
$lang['subscr_subscribe_success'] = 'اضيف %s لقائمة اشتراك %s';
$lang['subscr_subscribe_error'] = 'خطأ في إضافة %s لقائمة اشتراك %s';
$lang['subscr_subscribe_noaddress'] = 'ليس هناك عنوان مرتبط بولوجك، لا يمكن اضافتك لقائمة الاشتراك';

View File

@ -1,3 +1,3 @@
====== Müraciət qadağan edilmişdir ======
Sizin bu əməliyyat üçün kifayət qədər haqqınız yoxdur. Bəlkə, Siz sistemə oz istifadəçi adınız ilə girməyi unutmusunuz?
Sizin bu əməliyyat üçün kifayət qədər haqqınız yoxdur.

View File

@ -44,7 +44,7 @@ $lang['btn_recover'] = 'Qaralamanı qaytar';
$lang['btn_draftdel'] = 'Qaralamanı sil';
$lang['btn_revert'] = 'Qaytar';
$lang['btn_register'] = 'Qeydiyyatdan keç';
$lang['loggedinas'] = 'İstifadəcinin adı';
$lang['loggedinas'] = 'İstifadəcinin adı:';
$lang['user'] = 'istifadəci adı';
$lang['pass'] = 'Şifrə';
$lang['newpass'] = 'Yeni şifrə';
@ -82,10 +82,10 @@ $lang['license'] = 'Fərqli şey göstərilmiş hallardan başqa,
$lang['licenseok'] = 'Qeyd: bu səhifəni düzəliş edərək, Siz elədiyiniz düzəlişi aşağıda göstərilmiş lisenziyanın şərtlərinə uyğun istifadəsinə razılıq verirsiniz:';
$lang['searchmedia'] = 'Faylın adına görə axtarış:';
$lang['searchmedia_in'] = '%s-ın içində axtarış';
$lang['txt_upload'] = 'Serverə yükləmək üçün fayl seçin';
$lang['txt_filename'] = 'Faylın wiki-də olan adını daxil edin (mütləq deyil)';
$lang['txt_upload'] = 'Serverə yükləmək üçün fayl seçin:';
$lang['txt_filename'] = 'Faylın wiki-də olan adını daxil edin (mütləq deyil):';
$lang['txt_overwrt'] = 'Mövcud olan faylın üstündən yaz';
$lang['lockedby'] = 'В данный момент заблокирован Bu an blokdadır';
$lang['lockedby'] = 'В данный момент заблокирован Bu an blokdadır:';
$lang['lockexpire'] = 'Blok bitir:';
$lang['js']['willexpire'] = 'Sizin bu səhifədə dəyişik etmək üçün blokunuz bir dəqiqə ərzində bitəcək.\nMünaqişələrdən yayınmaq və blokun taymerini sıfırlamaq üçün, baxış düyməsini sıxın.';
$lang['rssfailed'] = 'Aşağıda göstərilmiş xəbər lentini əldə edən zaman xəta baş verdi: ';
@ -128,9 +128,9 @@ $lang['yours'] = 'Sizin versiyanız';
$lang['diff'] = 'hazırki versiyadan fərqləri göstər';
$lang['diff2'] = 'Versiyaların arasındaki fərqləri göstər ';
$lang['line'] = 'Sətr';
$lang['breadcrumb'] = 'Siz ziyarət etdiniz';
$lang['youarehere'] = 'Siz burdasınız';
$lang['lastmod'] = 'Son dəyişiklər';
$lang['breadcrumb'] = 'Siz ziyarət etdiniz:';
$lang['youarehere'] = 'Siz burdasınız:';
$lang['lastmod'] = 'Son dəyişiklər:';
$lang['by'] = ' Kimdən';
$lang['deleted'] = 'silinib';
$lang['created'] = 'yaranıb';
@ -172,17 +172,17 @@ $lang['admin_register'] = 'İstifadəçi əlavə et';
$lang['metaedit'] = 'Meta-məlumatlarda düzəliş et';
$lang['metasaveerr'] = 'Meta-məlumatları yazan zamanı xəta';
$lang['metasaveok'] = 'Meta-məlumatlar yadda saxlandı';
$lang['img_backto'] = 'Qayıd';
$lang['img_title'] = 'Başlıq';
$lang['img_caption'] = 'İmza';
$lang['img_date'] = 'Tarix';
$lang['img_fname'] = 'Faylın adı';
$lang['img_fsize'] = 'Boy';
$lang['img_artist'] = 'Şkilin müəllifi';
$lang['img_copyr'] = 'Müəllif hüquqları';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Model';
$lang['img_keywords'] = 'Açar sözlər';
$lang['btn_img_backto'] = 'Qayıd %s';
$lang['img_title'] = 'Başlıq:';
$lang['img_caption'] = 'İmza:';
$lang['img_date'] = 'Tarix:';
$lang['img_fname'] = 'Faylın adı:';
$lang['img_fsize'] = 'Boy:';
$lang['img_artist'] = 'Şkilin müəllifi:';
$lang['img_copyr'] = 'Müəllif hüquqları:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Model:';
$lang['img_keywords'] = 'Açar sözlər:';
$lang['authtempfail'] = 'İstifadəçilərin autentifikasiyası müvəqqəti dayandırılıb. Əgər bu problem uzun müddət davam edir sə, administrator ilə əlaqə saxlayın.';
$lang['i_chooselang'] = 'Dili seçin/Language';
$lang['i_installer'] = 'DokuWiki quraşdırılır';

View File

@ -1,4 +1,4 @@
====== Отказан достъп ======
Нямате достатъчно права, за да продължите. Може би сте забравили да се впишете?
Нямате достатъчно права, за да продължите.

View File

@ -50,8 +50,8 @@ $lang['btn_revert'] = 'Възстановяване';
$lang['btn_register'] = 'Регистриране';
$lang['btn_apply'] = 'Прилагане';
$lang['btn_media'] = 'Диспечер на файлове';
$lang['btn_deleteuser'] = 'Изтрий профила ми';
$lang['loggedinas'] = 'Вписани сте като';
$lang['btn_deleteuser'] = 'Изтриване на профила';
$lang['loggedinas'] = 'Вписани сте като:';
$lang['user'] = 'Потребител';
$lang['pass'] = 'Парола';
$lang['newpass'] = 'Нова парола';
@ -62,7 +62,7 @@ $lang['fullname'] = 'Истинско име';
$lang['email'] = 'Електронна поща';
$lang['profile'] = 'Потребителски профил';
$lang['badlogin'] = 'Грешно потребителско име или парола.';
$lang['badpassconfirm'] = 'Съжаляваме, паролата е грешна';
$lang['badpassconfirm'] = 'За съжаление паролата е грешна';
$lang['minoredit'] = 'Промените са незначителни';
$lang['draftdate'] = 'Черновата е автоматично записана на';
$lang['nosecedit'] = 'Страницата бе междувременно променена, презареждане на страницата поради неактуална информация.';
@ -77,13 +77,13 @@ $lang['regpwmail'] = 'Паролата ви за DokuWiki';
$lang['reghere'] = 'Все още нямате профил? Направете си';
$lang['profna'] = 'Wiki-то не поддържа промяна на профила';
$lang['profnochange'] = 'Няма промени.';
$lang['profnoempty'] = 'Въвеждането на име и ел. поща е задължително';
$lang['profnoempty'] = 'Въвеждането на име и имейл е задължително';
$lang['profchanged'] = 'Потребителският профил е обновен успешно.';
$lang['profnodelete'] = 'Не е възможно изтриване на потребители в това wiki ';
$lang['profdeleteuser'] = 'Изтрий профила ми';
$lang['profnodelete'] = 'Изтриването на потребители в това wiki не е възможно';
$lang['profdeleteuser'] = 'Изтриване на профила';
$lang['profdeleted'] = 'Вашият профил е премахнат от това wiki ';
$lang['profconfdelete'] = 'Искам да изтрия профила си от това wiki. <br/> Веднъж изтрит, профила не може да бъде възстановен!';
$lang['profconfdeletemissing'] = 'Не и маркирана опцията за потвърждение';
$lang['profconfdelete'] = 'Искам да изтрия профила си от това wiki. <br/> Веднъж изтрит, профилът не може да бъде възстановен!';
$lang['profconfdeletemissing'] = 'Не сте поставили отметка в кутията потвърждение';
$lang['pwdforget'] = 'Забравили сте паролата си? Получете нова';
$lang['resendna'] = 'Wiki-то не поддържа повторно пращане на паролата.';
$lang['resendpwd'] = 'Задаване на нова парола за';
@ -96,12 +96,12 @@ $lang['license'] = 'Ако не е посочено друго, с
$lang['licenseok'] = 'Бележка: Редактирайки страницата, Вие се съгласявате да лицензирате промените (които сте направили) под следния лиценз:';
$lang['searchmedia'] = 'Търсене на файл: ';
$lang['searchmedia_in'] = 'Търсене в %s';
$lang['txt_upload'] = 'Изберете файл за качване';
$lang['txt_filename'] = 'Качи като (незадължително)';
$lang['txt_upload'] = 'Изберете файл за качване:';
$lang['txt_filename'] = 'Качи като (незадължително):';
$lang['txt_overwrt'] = 'Презапиши съществуващите файлове';
$lang['maxuploadsize'] = 'Макс. размер за отделните файлове е %s.';
$lang['lockedby'] = 'В момента е заключена от';
$lang['lockexpire'] = 'Ще бъде отключена на';
$lang['lockedby'] = 'В момента е заключена от:';
$lang['lockexpire'] = 'Ще бъде отключена на:';
$lang['js']['willexpire'] = 'Страницата ще бъде отключена за редактиране след минута.\nЗа предотвратяване на конфликти, ползвайте бутона "Преглед", за рестартиране на брояча за заключване.';
$lang['js']['notsavedyet'] = 'Незаписаните промени ще бъдат загубени. Желаете ли да продължите?';
$lang['js']['searchmedia'] = 'Търсене на файлове';
@ -140,7 +140,7 @@ $lang['js']['media_diff_portions'] = 'По половинка';
$lang['js']['media_select'] = 'Изберете файлове...';
$lang['js']['media_upload_btn'] = 'Качване';
$lang['js']['media_done_btn'] = 'Готово';
$lang['js']['media_drop'] = 'Влачете и пуснете файливе тук, за да бъдат качени';
$lang['js']['media_drop'] = 'Влачете и пуснете файлове тук, за да бъдат качени';
$lang['js']['media_cancel'] = 'премахване';
$lang['js']['media_overwrt'] = 'Презапиши съществуващите файлове';
$lang['rssfailed'] = 'Възникна грешка при получаването на емисията: ';
@ -164,7 +164,7 @@ $lang['accessdenied'] = 'Нямате необходимите прав
$lang['mediausage'] = 'Ползвайте следния синтаксис, за да упоменете файла:';
$lang['mediaview'] = 'Преглед на оригиналния файл';
$lang['mediaroot'] = 'root';
$lang['mediaupload'] = 'Качете файл в текущото именно пространство. За създаване на подимено пространство, добавете име преди това на файла като ги разделите с двоеточие в полето "Качи като"';
$lang['mediaupload'] = 'Качете файл в текущото именно пространство. За създаване на подименно пространство, добавете име преди това на файла като ги разделите с двоеточие в полето "Качи като"';
$lang['mediaextchange'] = 'Разширението на файла е сменено от .%s на .%s!';
$lang['reference'] = 'Връзки за';
$lang['ref_inuse'] = 'Файлът не може да бъде изтрит, защото все още се ползва от следните страници:';
@ -181,9 +181,9 @@ $lang['diff_type'] = 'Преглед на разликите:';
$lang['diff_inline'] = 'Вграден';
$lang['diff_side'] = 'Един до друг';
$lang['line'] = 'Ред';
$lang['breadcrumb'] = 'Следа';
$lang['youarehere'] = 'Намирате се в';
$lang['lastmod'] = 'Последна промяна';
$lang['breadcrumb'] = 'Следа:';
$lang['youarehere'] = 'Намирате се в:';
$lang['lastmod'] = 'Последна промяна:';
$lang['by'] = 'от';
$lang['deleted'] = 'изтрита';
$lang['created'] = 'създадена';
@ -236,23 +236,23 @@ $lang['admin_register'] = 'Добавяне на нов потребит
$lang['metaedit'] = 'Редактиране на метаданни';
$lang['metasaveerr'] = 'Записването на метаданните се провали';
$lang['metasaveok'] = 'Метаданните са запазени успешно';
$lang['img_backto'] = 'Назад към';
$lang['img_title'] = 'Заглавие';
$lang['img_caption'] = 'Надпис';
$lang['img_date'] = 'Дата';
$lang['img_fname'] = 'Име на файла';
$lang['img_fsize'] = 'Размер';
$lang['img_artist'] = 'Фотограф';
$lang['img_copyr'] = 'Авторско право';
$lang['img_format'] = 'Формат';
$lang['img_camera'] = 'Фотоапарат';
$lang['img_keywords'] = 'Ключови думи';
$lang['img_width'] = 'Ширина';
$lang['img_height'] = 'Височина';
$lang['img_manager'] = 'Преглед в диспечера на файлове';
$lang['btn_img_backto'] = 'Назад към %s';
$lang['img_title'] = 'Заглавие:';
$lang['img_caption'] = 'Надпис:';
$lang['img_date'] = 'Дата:';
$lang['img_fname'] = 'Име на файла:';
$lang['img_fsize'] = 'Размер:';
$lang['img_artist'] = 'Фотограф:';
$lang['img_copyr'] = 'Авторско право:';
$lang['img_format'] = 'Формат:';
$lang['img_camera'] = 'Фотоапарат:';
$lang['img_keywords'] = 'Ключови думи:';
$lang['img_width'] = 'Ширина:';
$lang['img_height'] = 'Височина:';
$lang['btn_mediaManager'] = 'Преглед в диспечера на файлове';
$lang['subscr_subscribe_success'] = '%s е добавен към списъка с абониралите се за %s';
$lang['subscr_subscribe_error'] = 'Грешка при добавянето на %s към списъка с абониралите се за %s';
$lang['subscr_subscribe_noaddress'] = 'Добавянето ви към списъка с абонати не е възможно поради липсата на свързан адрес (на ел. поща) с профила ви.';
$lang['subscr_subscribe_noaddress'] = 'Добавянето ви към списъка с абонати не е възможно поради липсата на свързан адрес (имейл) с профила ви.';
$lang['subscr_unsubscribe_success'] = '%s е премахнат от списъка с абониралите се за %s';
$lang['subscr_unsubscribe_error'] = 'Грешка при премахването на %s от списъка с абониралите се за %s';
$lang['subscr_already_subscribed'] = '%s е вече абониран за %s';
@ -263,12 +263,12 @@ $lang['subscr_m_current_header'] = 'Текущи абонаменти';
$lang['subscr_m_unsubscribe'] = 'Прекратяване на абонамента';
$lang['subscr_m_subscribe'] = 'Абониране';
$lang['subscr_m_receive'] = 'Получаване';
$lang['subscr_style_every'] = 'на ел. писмо при всяка промяна';
$lang['subscr_style_digest'] = 'на ел. писмо с обобщение на промените във всяка страница (всеки %.2f дни)';
$lang['subscr_style_list'] = 'на списък с променените страници от последното ел. писмо (всеки %.2f дни)';
$lang['subscr_style_every'] = 'на имейл при всяка промяна';
$lang['subscr_style_digest'] = 'на имейл с обобщение на промените във всяка страница (всеки %.2f дни)';
$lang['subscr_style_list'] = 'на списък с променените страници от последния имейл (всеки %.2f дни)';
$lang['authtempfail'] = 'Удостоверяването на потребители не е възможно за момента. Ако продължи дълго, моля уведомете администратора на Wiki страницата.';
$lang['authpwdexpire'] = 'Срока на паролата ви ще изтече след %d дни. Препорачително е да я смените по-скоро.';
$lang['i_chooselang'] = 'Изберете вашия изик';
$lang['authpwdexpire'] = 'Срока на паролата ви ще изтече след %d дни. Препоръчително е да я смените по-скоро.';
$lang['i_chooselang'] = 'Изберете вашия език';
$lang['i_installer'] = 'Инсталатор на DokuWiki';
$lang['i_wikiname'] = 'Име на Wiki-то';
$lang['i_enableacl'] = 'Ползване на списък за достъп (ACL) [препоръчително]';

View File

@ -1,4 +1,4 @@
====== Регистриране като нов потребител ======
Моля, попълнете всичките полета отдолу, за да бъде създаден нов профил. Уверете се, че въведеният **адрес на ел. поща е правилен**. Ако няма поле за парола, ще ви бъде изпратена такава на въведения адрес. Потребителското име трябва да бъде валидно [[doku>pagename|име на страница]].
Моля, попълнете всичките полета отдолу, за да бъде създаден нов профил. Уверете се, че въведеният **имейл адрес е правилен**. Ако няма поле за парола, ще ви бъде изпратена такава на въведения адрес. Потребителското име трябва да бъде валидно [[doku>pagename|име на страница]].

View File

@ -1,3 +1,3 @@
====== Пращане на нова парола ======
Моля, въведете потребителското си име във формата по-долу, ако желаете да получите нова парола. По ел. поща ще получите линк, с който да потвърдите.
Моля, въведете потребителското си име във формата по-долу, ако желаете да получите нова парола. Чрез имейл ще получите линк, с който да потвърдите.

View File

@ -1,3 +1,3 @@
====== অনুমতি অস্বীকার =====
দুঃখিত, আপনি কি এগিয়ে যেতে যথেষ্ট অধিকার নেই. সম্ভবত আপনি লগইন ভুলে গেছেন?
দুঃখিত, আপনি কি এগিয়ে যেতে যথেষ্ট অধিকার নেই.

View File

@ -5,6 +5,7 @@
*
* @author Foysol <ragebot1125@gmail.com>
* @author ninetailz <ninetailz1125@gmail.com>
* @author Khan M. B. Asad <muhammad2017@gmail.com>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'itr';
@ -49,7 +50,7 @@ $lang['btn_register'] = 'খাতা';
$lang['btn_apply'] = 'প্রয়োগ করা';
$lang['btn_media'] = 'মিডিয়া ম্যানেজার';
$lang['btn_deleteuser'] = 'আমার অ্যাকাউন্ট অপসারণ করুন';
$lang['loggedinas'] = 'লগ ইন';
$lang['loggedinas'] = 'লগ ইন:';
$lang['user'] = 'ইউজারনেম';
$lang['pass'] = 'পাসওয়ার্ড';
$lang['newpass'] = 'নতুন পাসওয়ার্ড';
@ -95,12 +96,12 @@ $lang['license'] = 'অন্যথায় নোট যেখ
$lang['licenseok'] = 'দ্রষ্টব্য: আপনি নিম্নলিখিত লাইসেন্সের অধীনে আপনার বিষয়বস্তু লাইসেন্স সম্মত হন এই পৃষ্ঠার সম্পাদনার দ্বারা:';
$lang['searchmedia'] = 'অনুসন্ধান ফাইলের নাম:';
$lang['searchmedia_in'] = 'অনুসন্ধান %s -এ';
$lang['txt_upload'] = 'আপলোড করার জন্য নির্বাচন করুন ফাইল';
$lang['txt_filename'] = 'হিসাবে আপলোড করুন (ঐচ্ছিক)';
$lang['txt_upload'] = 'আপলোড করার জন্য নির্বাচন করুন ফাইল:';
$lang['txt_filename'] = 'হিসাবে আপলোড করুন (ঐচ্ছিক):';
$lang['txt_overwrt'] = 'বিদ্যমান ফাইল মুছে যাবে';
$lang['maxuploadsize'] = 'সর্বোচ্চ আপলোড করুন. %s-ফাইলের প্রতি.';
$lang['lockedby'] = 'বর্তমানে দ্বারা লক';
$lang['lockexpire'] = 'তালা এ মেয়াদ শেষ';
$lang['lockedby'] = 'বর্তমানে দ্বারা লক:';
$lang['lockexpire'] = 'তালা এ মেয়াদ শেষ:';
$lang['js']['willexpire'] = 'এই পৃষ্ঠার সম্পাদনার জন্য আপনার লক এক মিনিটের মধ্যে মেয়াদ শেষ সম্পর্কে. \ দ্বন্দ্ব লক টাইমার রিসেট প্রিভিউ বাটন ব্যবহার এড়াতে.';
$lang['js']['notsavedyet'] = 'অসংরক্ষিত পরিবর্তন হারিয়ে যাবে.';
$lang['js']['searchmedia'] = 'ফাইলের জন্য অনুসন্ধান';
@ -117,3 +118,43 @@ $lang['js']['mediadisplayimg'] = 'ছবিটি দেখান';
$lang['js']['mediadisplaylnk'] = 'শুধুমাত্র লিঙ্ক দেখান';
$lang['js']['mediasmall'] = 'ক্ষুদ্র সংস্করণ';
$lang['js']['mediamedium'] = 'মাধ্যম সংস্করণ';
$lang['js']['medialarge'] = 'বড় সংস্করণ';
$lang['js']['mediaoriginal'] = 'আসল সংস্করণ';
$lang['js']['medialnk'] = 'বিস্তারিত পৃষ্ঠায় লিংক';
$lang['js']['mediadirect'] = 'মূল সরাসরি লিঙ্ক';
$lang['js']['medianolnk'] = 'কোনো লিঙ্ক নাই';
$lang['js']['medianolink'] = 'ইমেজ লিঙ্ক কোরো না';
$lang['js']['medialeft'] = 'বাম দিকে ইমেজ সারিবদ্ধ কর';
$lang['js']['mediaright'] = 'ডান দিকে ইমেজ সারিবদ্ধ কর';
$lang['js']['mediacenter'] = 'মাঝখানে ইমেজ সারিবদ্ধ কর';
$lang['js']['medianoalign'] = 'কোনো সারিবদ্ধ করা প্রয়োজন নেই';
$lang['js']['nosmblinks'] = 'উইন্ডোস শেয়ার এর সাথে সংযোগ সাধন কেবল মাইক্রোসফ্ট ইন্টারনেট এক্সপ্লোরারেই সম্ভব।\nতবে আপনি লিংকটি কপি পেস্ট করতেই পারেন।';
$lang['js']['linkwiz'] = 'লিংক উইজার্ড';
$lang['js']['linkto'] = 'সংযোগের লক্ষ্য:';
$lang['js']['del_confirm'] = 'নির্বাচিত আইটেম(গুলো) আসলেই মুছে ফেলতে চান?';
$lang['js']['restore_confirm'] = 'এই সংস্করণ সত্যিই পূর্বাবস্থায় ফিরিয়ে আনতে চান?';
$lang['js']['media_diff'] = 'পার্থক্যগুলো দেখুন:';
$lang['js']['media_diff_both'] = 'পাশাপাশি';
$lang['js']['media_diff_opacity'] = 'শাইন-থ্রু';
$lang['js']['media_diff_portions'] = 'ঝেঁটিয়ে বিদায়';
$lang['js']['media_select'] = 'ফাইল নির্বাচন...';
$lang['js']['media_upload_btn'] = 'আপলোড';
$lang['js']['media_done_btn'] = 'সাধিত';
$lang['js']['media_drop'] = 'আপলোডের জন্য এখানে ফাইল ফেলুন';
$lang['js']['media_cancel'] = 'অপসারণ';
$lang['js']['media_overwrt'] = 'বর্তমান ফাইল ওভাররাইট করুন';
$lang['rssfailed'] = 'ফিডটি জোগাড় করতে গিয়ে একটি ত্রুটি ঘটেছে:';
$lang['nothingfound'] = 'কিছু পাওয়া যায়নি।';
$lang['mediaselect'] = 'মিডিয়া ফাইল';
$lang['fileupload'] = 'মিডিয়া ফাইল আপলোড';
$lang['uploadsucc'] = 'আপলোড সফল';
$lang['uploadfail'] = 'আপলোড ব্যর্থ। অনুমতি জনিত ত্রুটি কী?';
$lang['uploadwrong'] = 'আপলোড প্রত্যাখ্যাত। এই ফাইল এক্সটেনশন অননুমোদিত।';
$lang['uploadexist'] = 'ফাইল ইতিমধ্যেই বিরাজমান। কিছু করা হয়নি।';
$lang['uploadbadcontent'] = 'আপলোডকৃত সামগ্রী %s ফাইল এক্সটেনশন এর সাথে মিলেনি।';
$lang['uploadspam'] = 'স্প্যাম ব্ল্যাকলিস্ট আপলোড আটকে দিয়েছে।';
$lang['uploadxss'] = 'সামগ্রীটি ক্ষতিকর ভেবে আপলোড আটকে দেয়া হয়েছে।';
$lang['uploadsize'] = 'আপলোডকৃত ফাইলটি বেশি বড়ো। (সর্বোচ্চ %s)';
$lang['deletesucc'] = '"%s" ফাইলটি মুছে ফেলা হয়েছে।';
$lang['deletefail'] = '"%s" ডিলিট করা যায়নি - অনুমতি আছে কি না দেখুন।';
$lang['mediainuse'] = '"%s" ফাইলটি মোছা হয়নি - এটি এখনো ব্যবহৃত হচ্ছে।';

View File

@ -1,4 +1,4 @@
====== Permís denegat ======
Disculpe, pero no té permís per a continuar. ¿Haurà oblidat iniciar sessió?
Disculpe, pero no té permís per a continuar.

View File

@ -45,7 +45,7 @@ $lang['btn_recover'] = 'Recuperar borrador';
$lang['btn_draftdel'] = 'Borrar borrador';
$lang['btn_revert'] = 'Recuperar';
$lang['btn_register'] = 'Registrar-se';
$lang['loggedinas'] = 'Sessió de';
$lang['loggedinas'] = 'Sessió de:';
$lang['user'] = 'Nom d\'usuari';
$lang['pass'] = 'Contrasenya';
$lang['newpass'] = 'Contrasenya nova';
@ -83,11 +83,11 @@ $lang['license'] = 'Excepte quan s\'indique una atra cosa, el cont
$lang['licenseok'] = 'Nota: a l\'editar esta pàgina accepta llicenciar el seu contingut baix la següent llicència:';
$lang['searchmedia'] = 'Buscar nom d\'archiu:';
$lang['searchmedia_in'] = 'Buscar en %s';
$lang['txt_upload'] = 'Seleccione l\'archiu que vol pujar';
$lang['txt_filename'] = 'Enviar com (opcional)';
$lang['txt_upload'] = 'Seleccione l\'archiu que vol pujar:';
$lang['txt_filename'] = 'Enviar com (opcional):';
$lang['txt_overwrt'] = 'Sobreescriure archius existents';
$lang['lockedby'] = 'Actualment bloquejat per';
$lang['lockexpire'] = 'El bloqueig venç a les';
$lang['lockedby'] = 'Actualment bloquejat per:';
$lang['lockexpire'] = 'El bloqueig venç a les:';
$lang['js']['willexpire'] = 'El seu bloqueig per a editar esta pàgina vencerà en un minut.\nPer a evitar conflictes utilise el botó de vista prèvia i reiniciarà el contador.';
$lang['js']['notsavedyet'] = 'Els canvis no guardats es perdran.\n¿Segur que vol continuar?';
$lang['rssfailed'] = 'Ha ocorregut un erro al solicitar este canal: ';
@ -130,9 +130,9 @@ $lang['yours'] = 'La seua versió';
$lang['diff'] = 'Mostrar diferències en la versió actual';
$lang['diff2'] = 'Mostrar diferències entre versions';
$lang['line'] = 'Llínea';
$lang['breadcrumb'] = 'Traça';
$lang['youarehere'] = 'Vosté està ací';
$lang['lastmod'] = 'Última modificació el';
$lang['breadcrumb'] = 'Traça:';
$lang['youarehere'] = 'Vosté està ací:';
$lang['lastmod'] = 'Última modificació el:';
$lang['by'] = 'per';
$lang['deleted'] = 'borrat';
$lang['created'] = 'creat';
@ -174,17 +174,17 @@ $lang['admin_register'] = 'Afegir nou usuari';
$lang['metaedit'] = 'Editar meta-senyes';
$lang['metasaveerr'] = 'Erro escrivint meta-senyes';
$lang['metasaveok'] = 'Meta-senyes guardades';
$lang['img_backto'] = 'Tornar a';
$lang['img_title'] = 'Títul';
$lang['img_caption'] = 'Subtítul';
$lang['img_date'] = 'Data';
$lang['img_fname'] = 'Nom de l\'archiu';
$lang['img_fsize'] = 'Tamany';
$lang['img_artist'] = 'Fotógraf';
$lang['img_copyr'] = 'Copyright';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Càmara';
$lang['img_keywords'] = 'Paraules clau';
$lang['btn_img_backto'] = 'Tornar a %s';
$lang['img_title'] = 'Títul:';
$lang['img_caption'] = 'Subtítul:';
$lang['img_date'] = 'Data:';
$lang['img_fname'] = 'Nom de l\'archiu:';
$lang['img_fsize'] = 'Tamany:';
$lang['img_artist'] = 'Fotógraf:';
$lang['img_copyr'] = 'Copyright:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Càmara:';
$lang['img_keywords'] = 'Paraules clau:';
$lang['authtempfail'] = 'L\'autenticació d\'usuaris està desactivada temporalment. Si la situació persistix, per favor, informe a l\'administrador del Wiki.';
$lang['i_chooselang'] = 'Trie l\'idioma';
$lang['i_installer'] = 'Instalador de DokuWiki';

View File

@ -1,4 +1,4 @@
====== Permís denegat ======
No teniu prou drets per continuar. Potser us heu descuidat d'entrar?
No teniu prou drets per continuar.

View File

@ -48,7 +48,7 @@ $lang['btn_draftdel'] = 'Suprimeix esborrany';
$lang['btn_revert'] = 'Restaura';
$lang['btn_register'] = 'Registra\'m';
$lang['btn_apply'] = 'Aplica';
$lang['loggedinas'] = 'Heu entrat com';
$lang['loggedinas'] = 'Heu entrat com:';
$lang['user'] = 'Nom d\'usuari';
$lang['pass'] = 'Contrasenya';
$lang['newpass'] = 'Nova contrasenya';
@ -87,8 +87,8 @@ $lang['license'] = 'Excepte on es digui una altra cosa, el conting
$lang['licenseok'] = 'Nota. En editar aquesta pàgina esteu acceptant que el vostre contingut estigui subjecte a la llicència següent:';
$lang['searchmedia'] = 'Cerca pel nom de fitxer';
$lang['searchmedia_in'] = 'Cerca en: %s';
$lang['txt_upload'] = 'Trieu el fitxer que voleu penjar';
$lang['txt_filename'] = 'Introduïu el nom wiki (opcional)';
$lang['txt_upload'] = 'Trieu el fitxer que voleu penjar:';
$lang['txt_filename'] = 'Introduïu el nom wiki (opcional):';
$lang['txt_overwrt'] = 'Sobreescriu el fitxer actual';
$lang['maxuploadsize'] = 'Puja com a màxim %s per arxiu.';
$lang['lockedby'] = 'Actualment blocat per:';
@ -174,9 +174,9 @@ $lang['diff_type'] = 'Veieu les diferències:';
$lang['diff_inline'] = 'En línia';
$lang['diff_side'] = 'Un al costat de l\'altre';
$lang['line'] = 'Línia';
$lang['breadcrumb'] = 'Camí';
$lang['youarehere'] = 'Sou aquí';
$lang['lastmod'] = 'Darrera modificació';
$lang['breadcrumb'] = 'Camí:';
$lang['youarehere'] = 'Sou aquí:';
$lang['lastmod'] = 'Darrera modificació:';
$lang['by'] = 'per';
$lang['deleted'] = 'suprimit';
$lang['created'] = 'creat';
@ -228,19 +228,19 @@ $lang['admin_register'] = 'Afegeix nou usuari';
$lang['metaedit'] = 'Edita metadades';
$lang['metasaveerr'] = 'No s\'han pogut escriure les metadades';
$lang['metasaveok'] = 'S\'han desat les metadades';
$lang['img_backto'] = 'Torna a';
$lang['img_title'] = 'Títol';
$lang['img_caption'] = 'Peu d\'imatge';
$lang['img_date'] = 'Data';
$lang['img_fname'] = 'Nom de fitxer';
$lang['img_fsize'] = 'Mida';
$lang['img_artist'] = 'Fotògraf';
$lang['img_copyr'] = 'Copyright';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Càmera';
$lang['img_keywords'] = 'Paraules clau';
$lang['img_width'] = 'Ample';
$lang['img_height'] = 'Alçada';
$lang['btn_img_backto'] = 'Torna a %s';
$lang['img_title'] = 'Títol:';
$lang['img_caption'] = 'Peu d\'imatge:';
$lang['img_date'] = 'Data:';
$lang['img_fname'] = 'Nom de fitxer:';
$lang['img_fsize'] = 'Mida:';
$lang['img_artist'] = 'Fotògraf:';
$lang['img_copyr'] = 'Copyright:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Càmera:';
$lang['img_keywords'] = 'Paraules clau:';
$lang['img_width'] = 'Ample:';
$lang['img_height'] = 'Alçada:';
$lang['subscr_subscribe_success'] = 'S\'ha afegit %s a la llista de subscripcions per %s';
$lang['subscr_subscribe_error'] = 'Hi ha hagut un error a l\'afegir %s a la llista per %s';
$lang['subscr_subscribe_noaddress'] = 'No hi ha cap adreça associada pel vostre nom d\'usuari, no podeu ser afegit a la llista de subscripcions';

View File

@ -1,3 +1,3 @@
====== Nepovolená akce ======
Promiňte, ale nemáte dostatečná oprávnění k této činnosti. Možná jste se zapomněli přihlásit?
Promiňte, ale nemáte dostatečná oprávnění k této činnosti.

View File

@ -15,8 +15,8 @@
* @author Jakub A. Těšínský (j@kub.cz)
* @author mkucera66@seznam.cz
* @author Zbyněk Křivka <krivka@fit.vutbr.cz>
* @author Gerrit Uitslag <klapinklapin@gmail.com>
* @author Petr Klíma <qaxi@seznam.cz>
* @author Radovan Buroň <radovan@buron.cz>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@ -61,7 +61,9 @@ $lang['btn_register'] = 'Registrovat';
$lang['btn_apply'] = 'Použít';
$lang['btn_media'] = 'Správa médií';
$lang['btn_deleteuser'] = 'Odstranit můj účet';
$lang['loggedinas'] = 'Přihlášen(a) jako';
$lang['btn_img_backto'] = 'Zpět na %s';
$lang['btn_mediaManager'] = 'Zobrazit ve správě médií';
$lang['loggedinas'] = 'Přihlášen(a) jako:';
$lang['user'] = 'Uživatelské jméno';
$lang['pass'] = 'Heslo';
$lang['newpass'] = 'Nové heslo';
@ -106,8 +108,8 @@ $lang['license'] = 'Kromě míst, kde je explicitně uvedeno jinak
$lang['licenseok'] = 'Poznámka: Tím, že editujete tuto stránku, souhlasíte, aby váš obsah byl licencován pod následující licencí:';
$lang['searchmedia'] = 'Hledat jméno souboru:';
$lang['searchmedia_in'] = 'Hledat v %s';
$lang['txt_upload'] = 'Vyberte soubor jako přílohu';
$lang['txt_filename'] = 'Wiki jméno (volitelné)';
$lang['txt_upload'] = 'Vyberte soubor jako přílohu:';
$lang['txt_filename'] = 'Wiki jméno (volitelné):';
$lang['txt_overwrt'] = 'Přepsat existující soubor';
$lang['maxuploadsize'] = 'Max. velikost souboru %s';
$lang['lockedby'] = 'Právě zamknuto:';
@ -193,9 +195,9 @@ $lang['diff_type'] = 'Zobrazit rozdíly:';
$lang['diff_inline'] = 'Vložené';
$lang['diff_side'] = 'Přidané';
$lang['line'] = 'Řádek';
$lang['breadcrumb'] = 'Historie';
$lang['youarehere'] = 'Umístění';
$lang['lastmod'] = 'Poslední úprava';
$lang['breadcrumb'] = 'Historie:';
$lang['youarehere'] = 'Umístění:';
$lang['lastmod'] = 'Poslední úprava:';
$lang['by'] = 'autor:';
$lang['deleted'] = 'odstraněno';
$lang['created'] = 'vytvořeno';
@ -248,20 +250,18 @@ $lang['admin_register'] = 'Přidat nového uživatele';
$lang['metaedit'] = 'Upravit Metadata';
$lang['metasaveerr'] = 'Chyba při zápisu metadat';
$lang['metasaveok'] = 'Metadata uložena';
$lang['img_backto'] = 'Zpět na';
$lang['img_title'] = 'Titulek';
$lang['img_caption'] = 'Popis';
$lang['img_date'] = 'Datum';
$lang['img_fname'] = 'Jméno souboru';
$lang['img_fsize'] = 'Velikost';
$lang['img_artist'] = 'Autor fotografie';
$lang['img_copyr'] = 'Copyright';
$lang['img_format'] = 'Formát';
$lang['img_camera'] = 'Typ fotoaparátu';
$lang['img_keywords'] = 'Klíčová slova';
$lang['img_width'] = 'Šířka';
$lang['img_height'] = 'Výška';
$lang['img_manager'] = 'Zobrazit ve správě médií';
$lang['img_title'] = 'Titulek:';
$lang['img_caption'] = 'Popis:';
$lang['img_date'] = 'Datum:';
$lang['img_fname'] = 'Jméno souboru:';
$lang['img_fsize'] = 'Velikost:';
$lang['img_artist'] = 'Autor fotografie:';
$lang['img_copyr'] = 'Copyright:';
$lang['img_format'] = 'Formát:';
$lang['img_camera'] = 'Typ fotoaparátu:';
$lang['img_keywords'] = 'Klíčová slova:';
$lang['img_width'] = 'Šířka:';
$lang['img_height'] = 'Výška:';
$lang['subscr_subscribe_success'] = '%s byl přihlášen do seznamu odběratelů %s';
$lang['subscr_subscribe_error'] = 'Došlo k chybě při přihlašování %s do seznamu odběratelů %s';
$lang['subscr_subscribe_noaddress'] = 'K Vašemu loginu neexistuje žádná adresa, nemohl jste být přihlášen do seznamu odběratelů.';

View File

@ -1,3 +1,3 @@
====== Adgang nægtet! ======
Du har ikke rettigheder til at fortsætte. Måske er du ikke logget ind.
Du har ikke rettigheder til at fortsætte.

View File

@ -61,7 +61,7 @@ $lang['btn_register'] = 'Registrér';
$lang['btn_apply'] = 'Anvend';
$lang['btn_media'] = 'Media Manager';
$lang['btn_deleteuser'] = 'Fjern Min Konto';
$lang['loggedinas'] = 'Logget ind som';
$lang['loggedinas'] = 'Logget ind som:';
$lang['user'] = 'Brugernavn';
$lang['pass'] = 'Adgangskode';
$lang['newpass'] = 'Ny adgangskode';
@ -105,12 +105,12 @@ $lang['license'] = 'Med mindre andet angivet, vil indhold på denn
$lang['licenseok'] = 'Note: ved at ændre denne side, acceptere du at dit indhold bliver frigivet under følgende licens:';
$lang['searchmedia'] = 'Søg filnavn';
$lang['searchmedia_in'] = 'Søg i %s';
$lang['txt_upload'] = 'Vælg den fil der skal overføres';
$lang['txt_filename'] = 'Indtast wikinavn (valgfrit)';
$lang['txt_upload'] = 'Vælg den fil der skal overføres:';
$lang['txt_filename'] = 'Indtast wikinavn (valgfrit):';
$lang['txt_overwrt'] = 'Overskriv eksisterende fil';
$lang['maxuploadsize'] = 'Upload max. %s pr. fil.';
$lang['lockedby'] = 'Midlertidig låst af';
$lang['lockexpire'] = 'Lås udløber kl.';
$lang['lockedby'] = 'Midlertidig låst af:';
$lang['lockexpire'] = 'Lås udløber kl:.';
$lang['js']['willexpire'] = 'Din lås på dette dokument udløber om et minut.\nTryk på Forhåndsvisning-knappen for at undgå konflikter.';
$lang['js']['notsavedyet'] = 'Ugemte ændringer vil blive mistet
Fortsæt alligevel?';
@ -191,9 +191,9 @@ $lang['diff_type'] = 'Vis forskelle:';
$lang['diff_inline'] = 'Indeni';
$lang['diff_side'] = 'Side ved Side';
$lang['line'] = 'Linje';
$lang['breadcrumb'] = 'Sti';
$lang['youarehere'] = 'Du er her';
$lang['lastmod'] = 'Sidst ændret';
$lang['breadcrumb'] = 'Sti:';
$lang['youarehere'] = 'Du er her:';
$lang['lastmod'] = 'Sidst ændret:';
$lang['by'] = 'af';
$lang['deleted'] = 'slettet';
$lang['created'] = 'oprettet';
@ -246,20 +246,20 @@ $lang['admin_register'] = 'Tilføj ny bruger';
$lang['metaedit'] = 'Rediger metadata';
$lang['metasaveerr'] = 'Skrivning af metadata fejlede';
$lang['metasaveok'] = 'Metadata gemt';
$lang['img_backto'] = 'Tilbage til';
$lang['img_title'] = 'Titel';
$lang['img_caption'] = 'Billedtekst';
$lang['img_date'] = 'Dato';
$lang['img_fname'] = 'Filnavn';
$lang['img_fsize'] = 'Størrelse';
$lang['img_artist'] = 'Fotograf';
$lang['img_copyr'] = 'Ophavsret';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Kamera';
$lang['img_keywords'] = 'Emneord';
$lang['img_width'] = 'Bredde';
$lang['img_height'] = 'Højde';
$lang['img_manager'] = 'Vis i Media Manager';
$lang['btn_img_backto'] = 'Tilbage til %s';
$lang['img_title'] = 'Titel:';
$lang['img_caption'] = 'Billedtekst:';
$lang['img_date'] = 'Dato:';
$lang['img_fname'] = 'Filnavn:';
$lang['img_fsize'] = 'Størrelse:';
$lang['img_artist'] = 'Fotograf:';
$lang['img_copyr'] = 'Ophavsret:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Kamera:';
$lang['img_keywords'] = 'Emneord:';
$lang['img_width'] = 'Bredde:';
$lang['img_height'] = 'Højde:';
$lang['btn_mediaManager'] = 'Vis i Media Manager';
$lang['subscr_subscribe_success'] = 'Tilføjede %s til abonnement listen for %s';
$lang['subscr_subscribe_error'] = 'Fejl ved tilføjelse af %s til abonnement listen for %s';
$lang['subscr_subscribe_noaddress'] = 'Der er ikke nogen addresse forbundet til din bruger, så du kan ikke blive tilføjet til abonnement listen';

View File

@ -1,4 +1,4 @@
====== Zugang verweigert ======
Du hast nicht die erforderliche Berechtigung, um diese Aktion durchzuführen. Eventuell bist du nicht am Wiki angemeldet?
Du hast nicht die erforderliche Berechtigung, um diese Aktion durchzuführen.

View File

@ -66,7 +66,7 @@ $lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['loggedinas'] = 'Angemeldet als:';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
$lang['newpass'] = 'Neues Passwort';
@ -111,12 +111,12 @@ $lang['license'] = 'Falls nicht anders bezeichnet, ist der Inhalt
$lang['licenseok'] = 'Hinweis: Durch das Bearbeiten dieser Seite gibst du dein Einverständnis, dass dein Inhalt unter der folgenden Lizenz veröffentlicht wird:';
$lang['searchmedia'] = 'Suche nach Datei:';
$lang['searchmedia_in'] = 'Suche in %s';
$lang['txt_upload'] = 'Datei zum Hochladen auswählen';
$lang['txt_filename'] = 'Hochladen als (optional)';
$lang['txt_upload'] = 'Datei zum Hochladen auswählen:';
$lang['txt_filename'] = 'Hochladen als (optional):';
$lang['txt_overwrt'] = 'Bestehende Datei überschreiben';
$lang['maxuploadsize'] = 'Max. %s pro Datei-Upload.';
$lang['lockedby'] = 'Momentan gesperrt von';
$lang['lockexpire'] = 'Sperre läuft ab am';
$lang['lockedby'] = 'Momentan gesperrt von:';
$lang['lockexpire'] = 'Sperre läuft ab am:';
$lang['js']['willexpire'] = 'Die Sperre zur Bearbeitung dieser Seite läuft in einer Minute ab.\nUm Bearbeitungskonflikte zu vermeiden, solltest du sie durch einen Klick auf den Vorschau-Knopf verlängern.';
$lang['js']['notsavedyet'] = 'Nicht gespeicherte Änderungen gehen verloren!';
$lang['js']['searchmedia'] = 'Suche nach Dateien';
@ -196,9 +196,9 @@ $lang['diff_type'] = 'Unterschiede anzeigen:';
$lang['diff_inline'] = 'Inline';
$lang['diff_side'] = 'Side by Side';
$lang['line'] = 'Zeile';
$lang['breadcrumb'] = 'Zuletzt angesehen';
$lang['youarehere'] = 'Du befindest dich hier';
$lang['lastmod'] = 'Zuletzt geändert';
$lang['breadcrumb'] = 'Zuletzt angesehen:';
$lang['youarehere'] = 'Du befindest dich hier:';
$lang['lastmod'] = 'Zuletzt geändert:';
$lang['by'] = 'von';
$lang['deleted'] = 'gelöscht';
$lang['created'] = 'angelegt';
@ -251,20 +251,20 @@ $lang['admin_register'] = 'Neuen Benutzer anmelden';
$lang['metaedit'] = 'Metadaten bearbeiten';
$lang['metasaveerr'] = 'Die Metadaten konnten nicht gesichert werden';
$lang['metasaveok'] = 'Metadaten gesichert';
$lang['img_backto'] = 'Zurück zu';
$lang['img_title'] = 'Titel';
$lang['img_caption'] = 'Bildunterschrift';
$lang['img_date'] = 'Datum';
$lang['img_fname'] = 'Dateiname';
$lang['img_fsize'] = 'Größe';
$lang['img_artist'] = 'Fotograf';
$lang['img_copyr'] = 'Copyright';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Kamera';
$lang['img_keywords'] = 'Schlagwörter';
$lang['img_width'] = 'Breite';
$lang['img_height'] = 'Höhe';
$lang['img_manager'] = 'Im Medien-Manager anzeigen';
$lang['btn_img_backto'] = 'Zurück zu %s';
$lang['img_title'] = 'Titel:';
$lang['img_caption'] = 'Bildunterschrift:';
$lang['img_date'] = 'Datum:';
$lang['img_fname'] = 'Dateiname:';
$lang['img_fsize'] = 'Größe:';
$lang['img_artist'] = 'Fotograf:';
$lang['img_copyr'] = 'Copyright:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Kamera:';
$lang['img_keywords'] = 'Schlagwörter:';
$lang['img_width'] = 'Breite:';
$lang['img_height'] = 'Höhe:';
$lang['btn_mediaManager'] = 'Im Medien-Manager anzeigen';
$lang['subscr_subscribe_success'] = 'Die Seite %s wurde zur Abonnementliste von %s hinzugefügt';
$lang['subscr_subscribe_error'] = 'Fehler beim Hinzufügen von %s zur Abonnementliste von %s';
$lang['subscr_subscribe_noaddress'] = 'In deinem Account ist keine E-Mail-Adresse hinterlegt. Dadurch kann die Seite nicht abonniert werden';

View File

@ -1,4 +1,4 @@
====== Zugang verweigert ======
Sie haben nicht die erforderliche Berechtigung, um diese Aktion durchzuführen. Eventuell sind Sie nicht am Wiki angemeldet?
Sie haben nicht die erforderliche Berechtigung, um diese Aktion durchzuführen.

View File

@ -23,6 +23,9 @@
* @author Pierre Corell <info@joomla-praxis.de>
* @author Mateng Schimmerlos <mateng@firemail.de>
* @author Benedikt Fey <spam@lifeisgoooood.de>
* @author Joerg <scooter22@gmx.de>
* @author Simon <st103267@stud.uni-stuttgart.de>
* @author Hoisl <hoisl@gmx.at>
*/
$lang['encoding'] = 'utf-8';
$lang['direction'] = 'ltr';
@ -67,7 +70,9 @@ $lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['btn_img_backto'] = 'Zurück zu %s';
$lang['btn_mediaManager'] = 'Im Medien-Manager anzeigen';
$lang['loggedinas'] = 'Angemeldet als:';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
$lang['newpass'] = 'Neues Passwort';
@ -112,12 +117,12 @@ $lang['license'] = 'Falls nicht anders bezeichnet, ist der Inhalt
$lang['licenseok'] = 'Hinweis: Durch das Bearbeiten dieser Seite geben Sie Ihr Einverständnis, dass Ihr Inhalt unter der folgenden Lizenz veröffentlicht wird:';
$lang['searchmedia'] = 'Suche Dateinamen:';
$lang['searchmedia_in'] = 'Suche in %s';
$lang['txt_upload'] = 'Datei zum Hochladen auswählen';
$lang['txt_filename'] = 'Hochladen als (optional)';
$lang['txt_upload'] = 'Datei zum Hochladen auswählen:';
$lang['txt_filename'] = 'Hochladen als (optional):';
$lang['txt_overwrt'] = 'Bestehende Datei überschreiben';
$lang['maxuploadsize'] = 'Max. %s pro Datei-Upload.';
$lang['lockedby'] = 'Momentan gesperrt von';
$lang['lockexpire'] = 'Sperre läuft ab am';
$lang['lockedby'] = 'Momentan gesperrt von:';
$lang['lockexpire'] = 'Sperre läuft ab am:';
$lang['js']['willexpire'] = 'Die Sperre zur Bearbeitung dieser Seite läuft in einer Minute ab.\nUm Bearbeitungskonflikte zu vermeiden, sollten Sie sie durch einen Klick auf den Vorschau-Knopf verlängern.';
$lang['js']['notsavedyet'] = 'Nicht gespeicherte Änderungen gehen verloren!';
$lang['js']['searchmedia'] = 'Suche Dateien';
@ -196,10 +201,13 @@ $lang['difflink'] = 'Link zu dieser Vergleichsansicht';
$lang['diff_type'] = 'Unterschiede anzeigen:';
$lang['diff_inline'] = 'Inline';
$lang['diff_side'] = 'Side by Side';
$lang['diffprevrev'] = 'Vorhergehende Überarbeitung';
$lang['diffnextrev'] = 'Nächste Überarbeitung';
$lang['difflastrev'] = 'Letzte Überarbeitung';
$lang['line'] = 'Zeile';
$lang['breadcrumb'] = 'Zuletzt angesehen';
$lang['youarehere'] = 'Sie befinden sich hier';
$lang['lastmod'] = 'Zuletzt geändert';
$lang['breadcrumb'] = 'Zuletzt angesehen:';
$lang['youarehere'] = 'Sie befinden sich hier:';
$lang['lastmod'] = 'Zuletzt geändert:';
$lang['by'] = 'von';
$lang['deleted'] = 'gelöscht';
$lang['created'] = 'angelegt';
@ -252,20 +260,18 @@ $lang['admin_register'] = 'Neuen Benutzer anmelden';
$lang['metaedit'] = 'Metadaten bearbeiten';
$lang['metasaveerr'] = 'Die Metadaten konnten nicht gesichert werden';
$lang['metasaveok'] = 'Metadaten gesichert';
$lang['img_backto'] = 'Zurück zu';
$lang['img_title'] = 'Titel';
$lang['img_caption'] = 'Bildunterschrift';
$lang['img_date'] = 'Datum';
$lang['img_fname'] = 'Dateiname';
$lang['img_fsize'] = 'Größe';
$lang['img_artist'] = 'FotografIn';
$lang['img_copyr'] = 'Copyright';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Kamera';
$lang['img_keywords'] = 'Schlagwörter';
$lang['img_width'] = 'Breite';
$lang['img_height'] = 'Höhe';
$lang['img_manager'] = 'Im Medien-Manager anzeigen';
$lang['img_title'] = 'Titel:';
$lang['img_caption'] = 'Bildunterschrift:';
$lang['img_date'] = 'Datum:';
$lang['img_fname'] = 'Dateiname:';
$lang['img_fsize'] = 'Größe:';
$lang['img_artist'] = 'FotografIn:';
$lang['img_copyr'] = 'Copyright:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Kamera:';
$lang['img_keywords'] = 'Schlagwörter:';
$lang['img_width'] = 'Breite:';
$lang['img_height'] = 'Höhe:';
$lang['subscr_subscribe_success'] = '%s hat nun Änderungen der Seite %s abonniert';
$lang['subscr_subscribe_error'] = '%s kann die Änderungen der Seite %s nicht abonnieren';
$lang['subscr_subscribe_noaddress'] = 'Weil Ihre E-Mail-Adresse fehlt, können Sie das Thema nicht abonnieren';
@ -345,3 +351,4 @@ $lang['media_restore'] = 'Diese Version wiederherstellen';
$lang['currentns'] = 'Aktueller Namensraum';
$lang['searchresult'] = 'Suchergebnisse';
$lang['plainhtml'] = 'HTML Klartext';
$lang['wikimarkup'] = 'Wiki Markup';

View File

@ -2,4 +2,3 @@
Συγγνώμη, αλλά δεν έχετε επαρκή δικαιώματα για την συγκεκριμένη ενέργεια.
Μήπως παραλείψατε να συνδεθείτε;

View File

@ -56,7 +56,7 @@ $lang['btn_register'] = 'Εγγραφή';
$lang['btn_apply'] = 'Εφαρμογή';
$lang['btn_media'] = 'Διαχειριστής πολυμέσων';
$lang['btn_deleteuser'] = 'Αφαίρεσε τον λογαριασμό μου';
$lang['loggedinas'] = 'Συνδεδεμένος ως';
$lang['loggedinas'] = 'Συνδεδεμένος ως:';
$lang['user'] = 'Όνομα χρήστη';
$lang['pass'] = 'Κωδικός';
$lang['newpass'] = 'Νέος κωδικός';
@ -100,12 +100,12 @@ $lang['license'] = 'Εκτός εάν αναφέρεται δια
$lang['licenseok'] = 'Σημείωση: Τροποποιώντας αυτή την σελίδα αποδέχεστε την διάθεση του υλικού σας σύμφωνα με την ακόλουθη άδεια:';
$lang['searchmedia'] = 'Αναζήτηση αρχείου:';
$lang['searchmedia_in'] = 'Αναζήτηση σε %s';
$lang['txt_upload'] = 'Επιλέξτε αρχείο για φόρτωση';
$lang['txt_filename'] = 'Επιλέξτε νέο όνομα αρχείου (προαιρετικό)';
$lang['txt_upload'] = 'Επιλέξτε αρχείο για φόρτωση:';
$lang['txt_filename'] = 'Επιλέξτε νέο όνομα αρχείου (προαιρετικό):';
$lang['txt_overwrt'] = 'Αντικατάσταση υπάρχοντος αρχείου';
$lang['maxuploadsize'] = 'Μέγιστο μέγεθος αρχείου: %s.';
$lang['lockedby'] = 'Προσωρινά κλειδωμένο από';
$lang['lockexpire'] = 'Το κλείδωμα λήγει στις';
$lang['lockedby'] = 'Προσωρινά κλειδωμένο από:';
$lang['lockexpire'] = 'Το κλείδωμα λήγει στις:';
$lang['js']['willexpire'] = 'Το κλείδωμά σας για την επεξεργασία αυτής της σελίδας θα λήξει σε ένα λεπτό.\n Για να το ανανεώσετε χρησιμοποιήστε την Προεπισκόπηση.';
$lang['js']['notsavedyet'] = 'Οι μη αποθηκευμένες αλλαγές θα χαθούν.
Θέλετε να συνεχίσετε;';
@ -186,9 +186,9 @@ $lang['diff_type'] = 'Προβολή διαφορών:';
$lang['diff_inline'] = 'Σε σειρά';
$lang['diff_side'] = 'Δίπλα-δίπλα';
$lang['line'] = 'Γραμμή';
$lang['breadcrumb'] = 'Ιστορικό';
$lang['youarehere'] = 'Είστε εδώ';
$lang['lastmod'] = 'Τελευταία τροποποίηση';
$lang['breadcrumb'] = 'Ιστορικό:';
$lang['youarehere'] = 'Είστε εδώ:';
$lang['lastmod'] = 'Τελευταία τροποποίηση:';
$lang['by'] = 'από';
$lang['deleted'] = 'διαγράφηκε';
$lang['created'] = 'δημιουργήθηκε';
@ -241,20 +241,20 @@ $lang['admin_register'] = 'Προσθήκη νέου χρήστη';
$lang['metaedit'] = 'Τροποποίηση metadata';
$lang['metasaveerr'] = 'Η αποθήκευση των metadata απέτυχε';
$lang['metasaveok'] = 'Επιτυχής αποθήκευση metadata';
$lang['img_backto'] = 'Επιστροφή σε';
$lang['img_title'] = 'Τίτλος';
$lang['img_caption'] = 'Λεζάντα';
$lang['img_date'] = 'Ημερομηνία';
$lang['img_fname'] = 'Όνομα αρχείου';
$lang['img_fsize'] = 'Μέγεθος';
$lang['img_artist'] = 'Καλλιτέχνης';
$lang['img_copyr'] = 'Copyright';
$lang['img_format'] = 'Format';
$lang['img_camera'] = 'Camera';
$lang['img_keywords'] = 'Λέξεις-κλειδιά';
$lang['img_width'] = 'Πλάτος';
$lang['img_height'] = 'Ύψος';
$lang['img_manager'] = 'Εμφάνιση στον διαχειριστή πολυμέσων';
$lang['btn_img_backto'] = 'Επιστροφή σε %s';
$lang['img_title'] = 'Τίτλος:';
$lang['img_caption'] = 'Λεζάντα:';
$lang['img_date'] = 'Ημερομηνία:';
$lang['img_fname'] = 'Όνομα αρχείου:';
$lang['img_fsize'] = 'Μέγεθος:';
$lang['img_artist'] = 'Καλλιτέχνης:';
$lang['img_copyr'] = 'Copyright:';
$lang['img_format'] = 'Format:';
$lang['img_camera'] = 'Camera:';
$lang['img_keywords'] = 'Λέξεις-κλειδιά:';
$lang['img_width'] = 'Πλάτος:';
$lang['img_height'] = 'Ύψος:';
$lang['btn_mediaManager'] = 'Εμφάνιση στον διαχειριστή πολυμέσων';
$lang['subscr_subscribe_success'] = 'Ο/η %s προστέθηκε στην λίστα ειδοποιήσεων για το %s';
$lang['subscr_subscribe_error'] = 'Σφάλμα κατά την προσθήκη του/της %s στην λίστα ειδοποιήσεων για το %s';
$lang['subscr_subscribe_noaddress'] = 'Δεν υπάρχει διεύθυνση ταχυδρομείου συσχετισμένη με το όνομα χρήστη σας. Κατά συνέπεια δεν μπορείτε να προστεθείτε στην λίστα ειδοποιήσεων';

Some files were not shown because too many files have changed in this diff Show More