Merge branch 'master' into stable

This commit is contained in:
Guy Brand 2018-04-22 13:15:03 +02:00
commit a08ab6e8bb
1046 changed files with 42031 additions and 14388 deletions

1
.gitattributes vendored
View File

@ -9,6 +9,7 @@
.gitignore export-ignore
.editorconfig export-ignore
.travis.yml export-ignore
appveyor.yml export-ignore
composer.json export-ignore
composer.lock export-ignore
_test export-ignore

11
.gitignore vendored
View File

@ -67,7 +67,7 @@ lib/images/*/local/*
# composer default ignores
composer.phar
vendor/bin/*
vendor/*/*/phpunit.xml
vendor/*/*/phpunit.xml*
vendor/*/*/.travis.yml
vendor/*/*/bin/*
vendor/*/*/tests/*
@ -81,3 +81,12 @@ vendor/paragonie/random_compat/build-phar.sh
vendor/paragonie/random_compat/dist/*
vendor/paragonie/random_compat/other/*
vendor/simplepie/simplepie/db.sql
vendor/marcusschwarz/lesserphp/package.sh
vendor/marcusschwarz/lesserphp/lessify*
vendor/marcusschwarz/lesserphp/Makefile
vendor/marcusschwarz/lesserphp/plessc
vendor/splitbrain/php-cli/examples/*
vendor/splitbrain/php-cli/screenshot*
vendor/splitbrain/php-cli/generate-api.sh
vendor/splitbrain/php-cli/apigen.neon

View File

@ -1,5 +1,3 @@
## Enable this to restrict editing to logged in users only
## You should disable Indexes and MultiViews either here or in the
## global config. Symlinks maybe needed for URL rewriting.
#Options -Indexes -MultiViews +FollowSymLinks

View File

@ -1,13 +1,11 @@
language: php
sudo: false
php:
- "nightly"
- "7.2"
- "7.1"
- "7.0"
- "5.6"
- "5.5"
- "5.4"
- "5.3"
env:
- DISABLE_FUNCTIONS=
- DISABLE_FUNCTIONS="gzopen"
@ -30,6 +28,7 @@ matrix:
env: DISABLE_FUNCTIONS=
allow_failures:
- php: "hhvm"
- php: "nightly"
exclude:
- php: "hhvm"
env: DISABLE_FUNCTIONS="gzopen"
@ -40,7 +39,7 @@ notifications:
on_success: change
on_failure: change
install:
- wget -O ~/.phpenv/versions/hhvm/bin/phpunit https://phar.phpunit.de/phpunit.phar
- wget -O ~/.phpenv/versions/hhvm/bin/phpunit https://phar.phpunit.de/phpunit-5.7.phar
- chmod 755 ~/.phpenv/versions/hhvm/bin/phpunit
before_script:
# Disable the HHVM JIT for faster Unit Testing

2
README
View File

@ -4,7 +4,7 @@ at http://www.dokuwiki.org/
For Installation Instructions see
http://www.dokuwiki.org/install
DokuWiki - 2004-2016 (c) Andreas Gohr <andi@splitbrain.org>
DokuWiki - 2004-2018 (c) Andreas Gohr <andi@splitbrain.org>
and the DokuWiki Community
See COPYING and file headers for license info

View File

@ -1,6 +1,28 @@
<?php
if(!class_exists('PHPUnit_Framework_TestCase')) {
/**
* phpunit 5/6 compatibility
*/
class PHPUnit_Framework_TestCase extends PHPUnit\Framework\TestCase {
/**
* setExpectedException is deprecated in PHPUnit 6
*
* @param string $class
* @param null|string $message
*/
public function setExpectedException($class, $message=null) {
$this->expectException($class);
if(!is_null($message)) {
$this->expectExceptionMessage($message);
}
}
}
}
/**
* Helper class to provide basic functionality for tests
*
* @uses PHPUnit_Framework_TestCase and thus PHPUnit 5.7+ is required
*/
abstract class DokuWikiTest extends PHPUnit_Framework_TestCase {
@ -128,35 +150,6 @@ abstract class DokuWikiTest extends PHPUnit_Framework_TestCase {
$INPUT = new Input();
}
/**
* Compatibility for older PHPUnit versions
*
* @param string $originalClassName
* @return PHPUnit_Framework_MockObject_MockObject
*/
protected function createMock($originalClassName) {
if(is_callable(array('parent', 'createMock'))) {
return parent::createMock($originalClassName);
} else {
return $this->getMock($originalClassName);
}
}
/**
* Compatibility for older PHPUnit versions
*
* @param string $originalClassName
* @param array $methods
* @return PHPUnit_Framework_MockObject_MockObject
*/
protected function createPartialMock($originalClassName, array $methods) {
if(is_callable(array('parent', 'createPartialMock'))) {
return parent::createPartialMock($originalClassName, $methods);
} else {
return $this->getMock($originalClassName, $methods);
}
}
/**
* Waits until a new second has passed
*
@ -178,4 +171,24 @@ abstract class DokuWikiTest extends PHPUnit_Framework_TestCase {
$last = $now;
return $now;
}
/**
* Allow for testing inaccessible methods (private or protected)
*
* This makes it easier to test protected methods without needing to create intermediate
* classes inheriting and changing the access.
*
* @link https://stackoverflow.com/a/8702347/172068
* @param object $obj Object in which to call the method
* @param string $func The method to call
* @param array $args The arguments to call the method with
* @return mixed
* @throws ReflectionException when the given obj/func does not exist
*/
protected static function callInaccessibleMethod($obj, $func, array $args) {
$class = new \ReflectionClass($obj);
$method = $class->getMethod($func);
$method->setAccessible(true);
return $method->invokeArgs($obj, $args);
}
}

View File

@ -4,46 +4,122 @@
* runtime inspection.
*/
// output buffering
$output_buffer = '';
function ob_start_callback($buffer) {
global $output_buffer;
$output_buffer .= $buffer;
}
/**
* Helper class to execute a fake request
*/
class TestRequest {
private $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php');
private $script;
protected $valid_scripts = array('/doku.php', '/lib/exe/fetch.php', '/lib/exe/detail.php', '/lib/exe/ajax.php');
protected $script;
private $server = array();
private $session = array();
private $get = array();
private $post = array();
protected $server = array();
protected $session = array();
protected $get = array();
protected $post = array();
protected $data = array();
public function getServer($key) { return $this->server[$key]; }
public function getSession($key) { return $this->session[$key]; }
public function getGet($key) { return $this->get[$key]; }
public function getPost($key) { return $this->post[$key]; }
public function getScript() { return $this->script; }
/** @var string stores the output buffer, even when it's flushed */
protected $output_buffer = '';
public function setServer($key, $value) { $this->server[$key] = $value; }
public function setSession($key, $value) { $this->session[$key] = $value; }
public function setGet($key, $value) { $this->get[$key] = $value; }
public function setPost($key, $value) { $this->post[$key] = $value; }
/** @var null|TestRequest the currently running request */
static protected $running = null;
/**
* Get a $_SERVER var
*
* @param string $key
* @return mixed
*/
public function getServer($key) {
return $this->server[$key];
}
/**
* Get a $_SESSION var
*
* @param string $key
* @return mixed
*/
public function getSession($key) {
return $this->session[$key];
}
/**
* Get a $_GET var
*
* @param string $key
* @return mixed
*/
public function getGet($key) {
return $this->get[$key];
}
/**
* Get a $_POST var
*
* @param string $key
* @return mixed
*/
public function getPost($key) {
return $this->post[$key];
}
/**
* Get the script that will execute the request
*
* @return string
*/
public function getScript() {
return $this->script;
}
/**
* Set a $_SERVER var
*
* @param string $key
* @param mixed $value
*/
public function setServer($key, $value) {
$this->server[$key] = $value;
}
/**
* Set a $_SESSION var
*
* @param string $key
* @param mixed $value
*/
public function setSession($key, $value) {
$this->session[$key] = $value;
}
/**
* Set a $_GET var
*
* @param string $key
* @param mixed $value
*/
public function setGet($key, $value) {
$this->get[$key] = $value;
}
/**
* Set a $_POST var
*
* @param string $key
* @param mixed $value
*/
public function setPost($key, $value) {
$this->post[$key] = $value;
}
/**
* Executes the request
*
* @param string $url end URL to simulate, needs to start with /doku.php currently
* @param string $uri end URL to simulate, needs to be one of the testable scripts
* @return TestResponse the resulting output of the request
*/
public function execute($uri='/doku.php') {
public function execute($uri = '/doku.php') {
global $INPUT;
// save old environment
@ -53,12 +129,12 @@ class TestRequest {
$post = $_POST;
$request = $_REQUEST;
$input = $INPUT;
// prepare the right URI
$this->setUri($uri);
// import all defined globals into the function scope
foreach(array_keys($GLOBALS) as $glb){
foreach(array_keys($GLOBALS) as $glb) {
global $$glb;
}
@ -71,20 +147,23 @@ class TestRequest {
$_REQUEST = array_merge($_GET, $_POST);
// reset output buffer
global $output_buffer;
$output_buffer = '';
$this->output_buffer = '';
// now execute dokuwiki and grep the output
self::$running = $this;
header_remove();
ob_start('ob_start_callback');
ob_start(array($this, 'ob_start_callback'));
$INPUT = new Input();
include(DOKU_INC.$this->script);
include(DOKU_INC . $this->script);
ob_end_flush();
self::$running = null;
// create the response object
$response = new TestResponse(
$output_buffer,
(function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list()) // cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli
$this->output_buffer,
// cli sapi doesn't do headers, prefer xdebug_get_headers() which works under cli
(function_exists('xdebug_get_headers') ? xdebug_get_headers() : headers_list()),
$this->data
);
// reset environment
@ -107,28 +186,28 @@ class TestRequest {
* It initializes the $_SERVER['REQUEST_URI'] and $_SERVER['QUERY_STRING']
* with all set GET variables.
*
* @param string $url end URL to simulate, needs to start with /doku.php currently
* @todo make this work with other end points
* @param string $uri end URL to simulate
* @throws Exception when an invalid script is passed
*/
protected function setUri($uri){
if(!preg_match('#^('.join('|',$this->valid_scripts).')#',$uri)){
throw new Exception("$uri \n--- only ".join(', ',$this->valid_scripts)." are supported currently");
protected function setUri($uri) {
if(!preg_match('#^(' . join('|', $this->valid_scripts) . ')#', $uri)) {
throw new Exception("$uri \n--- only " . join(', ', $this->valid_scripts) . " are supported currently");
}
$params = array();
list($uri, $query) = explode('?',$uri,2);
list($uri, $query) = explode('?', $uri, 2);
if($query) parse_str($query, $params);
$this->script = substr($uri,1);
$this->get = array_merge($params, $this->get);
if(count($this->get)){
$query = '?'.http_build_query($this->get, '', '&');
$this->script = substr($uri, 1);
$this->get = array_merge($params, $this->get);
if(count($this->get)) {
$query = '?' . http_build_query($this->get, '', '&');
$query = str_replace(
array('%3A', '%5B', '%5D'),
array(':', '[', ']'),
$query
);
$uri = $uri.$query;
$uri = $uri . $query;
}
$this->setServer('QUERY_STRING', $query);
@ -138,11 +217,11 @@ class TestRequest {
/**
* Simulate a POST request with the given variables
*
* @param array $post all the POST parameters to use
* @param string $url end URL to simulate, needs to start with /doku.php, /lib/exe/fetch.php or /lib/exe/detail.php currently
* @param return TestResponse
* @param array $post all the POST parameters to use
* @param string $uri end URL to simulate
* @return TestResponse
*/
public function post($post=array(), $uri='/doku.php') {
public function post($post = array(), $uri = '/doku.php') {
$this->post = array_merge($this->post, $post);
$this->setServer('REQUEST_METHOD', 'POST');
return $this->execute($uri);
@ -151,15 +230,51 @@ class TestRequest {
/**
* Simulate a GET request with the given variables
*
* @param array $GET all the GET parameters to use
* @param string $url end URL to simulate, needs to start with /doku.php, /lib/exe/fetch.php or /lib/exe/detail.php currently
* @param return TestResponse
* @param array $get all the GET parameters to use
* @param string $uri end URL to simulate
* @return TestResponse
*/
public function get($get=array(), $uri='/doku.php') {
$this->get = array_merge($this->get, $get);
public function get($get = array(), $uri = '/doku.php') {
$this->get = array_merge($this->get, $get);
$this->setServer('REQUEST_METHOD', 'GET');
return $this->execute($uri);
}
/**
* Callback for ob_start
*
* This continues to fill our own buffer, even when some part
* of the code askes for flushing the buffers
*
* @param string $buffer
*/
public function ob_start_callback($buffer) {
$this->output_buffer .= $buffer;
}
/**
* Access the TestRequest from the executed code
*
* This allows certain functions to access the TestRequest that is accessing them
* to add additional info.
*
* @return null|TestRequest the currently executed request if any
*/
public static function getRunning() {
return self::$running;
}
/**
* Store data to be read in the response later
*
* When called multiple times with the same key, the data is appended to this
* key's array
*
* @param string $key the identifier for this information
* @param mixed $value arbitrary data to store
*/
public function addData($key, $value) {
if(!isset($this->data[$key])) $this->data[$key] = array();
$this->data[$key][] = $value;
}
}

View File

@ -1,33 +1,37 @@
<?php
/**
* holds a copy of all produced outputs of a TestRequest
*/
class TestResponse {
/**
* @var string
*/
private $content;
/** @var string */
protected $content;
/** @var array */
protected $headers;
/** @var phpQueryObject */
protected $pq = null;
/** @var array */
protected $data = array();
/**
* @var array
* Constructor
*
* @param $content string the response body
* @param $headers array the headers sent in the response
* @param array $data any optional data passed back to the test system
*/
private $headers;
/**
* @var phpQueryObject
*/
private $pq = null;
/**
* @param $content string
* @param $headers array
*/
function __construct($content, $headers) {
function __construct($content, $headers, $data = array()) {
$this->content = $content;
$this->headers = $headers;
$this->data = $data;
}
/**
* Returns the response body
*
* @return string
*/
public function getContent() {
@ -35,6 +39,8 @@ class TestResponse {
}
/**
* Returns the headers set in the response
*
* @return array
*/
public function getHeaders() {
@ -42,13 +48,15 @@ class TestResponse {
}
/**
* Return a single header
*
* @param $name string, the name of the header without the ':', e.g. 'Content-Type', 'Pragma'
* @return mixed if exactly one header, the header (string); otherwise an array of headers, empty when no headers
*/
public function getHeader($name) {
$result = array();
foreach ($this->headers as $header) {
if (substr($header,0,strlen($name)+1) == $name.':') {
foreach($this->headers as $header) {
if(substr($header, 0, strlen($name) + 1) == $name . ':') {
$result[] = $header;
}
}
@ -57,26 +65,28 @@ class TestResponse {
}
/**
* @return int http status code
* Access the http status code
*
* in the test environment, only status codes explicitly set by dokuwiki are likely to be returned
* this means succcessful status codes (e.g. 200 OK) will not be present, but error codes will be
*
* @return int http status code
*/
public function getStatusCode() {
$headers = $this->getHeader('Status');
$code = null;
if ($headers) {
if($headers) {
// if there is more than one status header, use the last one
$status = is_array($headers) ? array_pop($headers) : $headers;
$matches = array();
preg_match('/^Status: ?(\d+)/',$status,$matches);
if ($matches){
preg_match('/^Status: ?(\d+)/', $status, $matches);
if($matches) {
$code = $matches[1];
}
}
}
return $code;
return $code;
}
/**
@ -86,8 +96,19 @@ class TestResponse {
* @param $selector string
* @return phpQueryObject
*/
public function queryHTML($selector){
public function queryHTML($selector) {
if(is_null($this->pq)) $this->pq = phpQuery::newDocument($this->content);
return $this->pq->find($selector);
}
/**
* Returns all collected data for the given key
*
* @param string $key
* @return array
*/
public function getData($key) {
if(!isset($this->data[$key])) return array();
return $this->data[$key];
}
}

View File

@ -5,6 +5,15 @@
*/
class TestUtils {
/**
* converts path to unix-like on windows OS
* @param string $path UNIX-like path to be converted
* @return string
*/
public static function w2u($path) {
return isWindows() ? str_replace('\\', '/', $path) : $path;
}
/**
* helper for recursive copy()
*

View File

@ -0,0 +1,16 @@
This is a test page for testing the redirect happening on the ''edit and save'' workflow.
This page is required for the tests in **_tests/test/test/edit_and_save.test.php**. Do not edit this file.
====== Headline1 ======
Headline 1 content.
====== Headline2 ======
Headline 2a content.
====== Headline2 ======
Headline 2b content.
====== Headline3 ======
Headline 3 content.
It is essential for the tests that there are two headlines with the title **Headline2**!

View File

@ -4,6 +4,7 @@
convertNoticesToExceptions="false"
colors="true"
stderr="true"
backupGlobals="true"
>
<testsuites>

View File

@ -0,0 +1,182 @@
<?php
use dokuwiki\Action\AbstractAclAction;
use dokuwiki\Action\AbstractUserAction;
use dokuwiki\Action\Exception\ActionAclRequiredException;
use dokuwiki\Action\Exception\ActionDisabledException;
use dokuwiki\Action\Exception\ActionUserRequiredException;
class action_general extends DokuWikiTest {
public function dataProvider() {
return array(
array('Login', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Logout', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Search', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Recent', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Profile', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('ProfileDelete', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Index', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Sitemap', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Denied', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Register', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Resendpwd', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Backlink', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Revert', AUTH_ADMIN, array('exists' => true, 'ismanager' => false)),
array('Revert', AUTH_EDIT, array('exists' => true, 'ismanager' => true)),
array('Admin', AUTH_ADMIN, array('exists' => true, 'ismanager' => false)),
array('Admin', AUTH_READ, array('exists' => true, 'ismanager' => true)), // let in, check later again
array('Check', AUTH_READ, array('exists' => true, 'ismanager' => false)), // sensible?
array('Diff', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Show', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Subscribe', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Locked', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Source', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Export', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Media', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Revisions', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Draftdel', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
// aliases
array('Cancel', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Recover', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
// EDITING existing page
array('Save', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
array('Conflict', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
array('Draft', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
//the edit function will check again and do a source show
//when no AUTH_EDIT available:
array('Edit', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Preview', AUTH_READ, array('exists' => true, 'ismanager' => false)),
// EDITING new page
array('Save', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Conflict', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Draft', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Edit', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Preview', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
);
}
/**
* @dataProvider dataProvider
* @param $name
* @param $expected
* @param $info
*/
public function testMinimumPermissions($name, $expected, $info) {
global $INFO;
$INFO = $info;
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
$this->assertSame($expected, $class->minimumPermission());
}
/**
* All actions should handle the disableactions setting
*
* @dataProvider dataProvider
* @param $name
*/
public function testBaseClassActionOkPermission($name) {
$this->assertTrue(true); // mark as not risky
if($name == 'Show') return; // disabling show does not work
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
global $conf;
$conf['useacl'] = 1;
$conf['subscribers'] = 1;
$conf['disableactions'] = '';
$_SERVER['REMOTE_USER'] = 'someone';
try {
\dokuwiki\ActionRouter::getInstance(true)->checkAction($class);
} catch(\Exception $e) {
$this->assertNotSame(ActionDisabledException::class, get_class($e));
}
$conf['disableactions'] = $class->getActionName();
try {
\dokuwiki\ActionRouter::getInstance(true)->checkAction($class);
} catch(\Exception $e) {
$this->assertSame(ActionDisabledException::class, get_class($e), $e);
}
}
/**
* Actions inheriting from AbstractAclAction should have an ACL enabled check
*
* @dataProvider dataProvider
* @param $name
*/
public function testBaseClassAclPermission($name) {
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
$this->assertTrue(true); // mark as not risky
if(!is_a($class, AbstractAclAction::class)) return;
global $conf;
$conf['useacl'] = 1;
$conf['subscribers'] = 1;
try {
$class->checkPreconditions();
} catch(\Exception $e) {
$this->assertNotSame(ActionAclRequiredException::class, get_class($e));
}
$conf['useacl'] = 0;
try {
$class->checkPreconditions();
} catch(\Exception $e) {
$this->assertSame(ActionAclRequiredException::class, get_class($e));
}
}
/**
* Actions inheriting from AbstractUserAction should have user check
*
* @dataProvider dataProvider
* @param $name
*/
public function testBaseClassUserPermission($name) {
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
$this->assertTrue(true); // mark as not risky
if(!is_a($class, AbstractUserAction::class)) return;
global $conf;
$conf['useacl'] = 1;
$conf['subscribers'] = 1;
$_SERVER['REMOTE_USER'] = 'test';
try {
$class->checkPreconditions();
} catch(\Exception $e) {
$this->assertNotSame(ActionUserRequiredException::class, get_class($e));
}
unset($_SERVER['REMOTE_USER']);
try {
$class->checkPreconditions();
} catch(\Exception $e) {
$this->assertSame(ActionUserRequiredException::class, get_class($e));
}
}
}

View File

@ -2,7 +2,7 @@
class auth_acl_test extends DokuWikiTest {
var $oldAuthAcl;
protected $oldAuthAcl;
function setUp() {
parent::setUp();

View File

@ -2,102 +2,112 @@
class auth_password_test extends DokuWikiTest {
// hashes for the password foo$method, using abcdefgh12345678912345678912345678 as salt
var $passes = array(
'smd5' => '$1$abcdefgh$SYbjm2AEvSoHG7Xapi8so.',
'apr1' => '$apr1$abcdefgh$C/GzYTF4kOVByYLEoD5X4.',
'md5' => '8fa22d62408e5351553acdd91c6b7003',
'sha1' => 'b456d3b0efd105d613744ffd549514ecafcfc7e1',
'ssha' => '{SSHA}QMHG+uC7bHNYKkmoLbNsNI38/dJhYmNk',
'lsmd5' => '{SMD5}HGbkPrkWgy9KgcRGWlrsUWFiY2RlZmdo',
'crypt' => 'ablvoGr1hvZ5k',
'mysql' => '4a1fa3780bd6fd55',
'my411' => '*E5929347E25F82E19E4EBE92F1DC6B6E7C2DBD29',
'kmd5' => 'a579299436d7969791189acadd86fcb716',
'djangomd5' => 'md5$abcde$d0fdddeda8cd92725d2b54148ac09158',
'djangosha1' => 'sha1$abcde$c8e65a7f0acc9158843048a53dcc5a6bc4d17678',
/**
* precomputed hashes
*
* for the password foo$method, using abcdefgh12345678912345678912345678 as salt
*
* @return array
*/
public function hashes() {
);
$passes = array(
array('smd5', '$1$abcdefgh$SYbjm2AEvSoHG7Xapi8so.'),
array('apr1', '$apr1$abcdefgh$C/GzYTF4kOVByYLEoD5X4.'),
array('md5', '8fa22d62408e5351553acdd91c6b7003'),
array('sha1', 'b456d3b0efd105d613744ffd549514ecafcfc7e1'),
array('ssha', '{SSHA}QMHG+uC7bHNYKkmoLbNsNI38/dJhYmNk'),
array('lsmd5', '{SMD5}HGbkPrkWgy9KgcRGWlrsUWFiY2RlZmdo'),
array('crypt', 'ablvoGr1hvZ5k'),
array('mysql', '4a1fa3780bd6fd55'),
array('my411', '*E5929347E25F82E19E4EBE92F1DC6B6E7C2DBD29'),
array('kmd5', 'a579299436d7969791189acadd86fcb716'),
array('djangomd5', 'md5$abcde$d0fdddeda8cd92725d2b54148ac09158'),
array('djangosha1', 'sha1$abcde$c8e65a7f0acc9158843048a53dcc5a6bc4d17678'),
);
function __construct() {
if(defined('CRYPT_SHA512') && CRYPT_SHA512 == 1) {
// Check SHA512 only if available in this PHP
$this->passes['sha512'] = '$6$abcdefgh12345678$J9.zOcgx0lotwZdcz0uulA3IVQMinZvFZVjA5vapRLVAAqtay23XD4xeeUxQ3B4JvDWYFBIxVWW1tOYlHX13k1';
$passes[] = array('sha512', '$6$abcdefgh12345678$J9.zOcgx0lotwZdcz0uulA3IVQMinZvFZVjA5vapRLVAAqtay23XD4xeeUxQ3B4JvDWYFBIxVWW1tOYlHX13k1');
}
if(function_exists('hash_pbkdf2')) {
if(in_array('sha256', hash_algos())) {
$this->passes['djangopbkdf2_sha256'] = 'pbkdf2_sha256$24000$abcdefgh1234$R23OyZJ0nGHLG6MvPNfEkV5AOz3jUY5zthByPXs2gn0=';
$passes[] = array('djangopbkdf2_sha256', 'pbkdf2_sha256$24000$abcdefgh1234$R23OyZJ0nGHLG6MvPNfEkV5AOz3jUY5zthByPXs2gn0=');
}
if(in_array('sha1', hash_algos())) {
$this->passes['djangopbkdf2_sha1'] = 'pbkdf2_sha1$24000$abcdefgh1234$pOliX4vV1hgOv7lFNURIHHx41HI=';
$passes[] = array('djangopbkdf2_sha1', 'pbkdf2_sha1$24000$abcdefgh1234$pOliX4vV1hgOv7lFNURIHHx41HI=');
}
}
return $passes;
}
function test_cryptPassword(){
foreach($this->passes as $method => $hash){
$info = "testing method $method";
$this->assertEquals(
$hash,
auth_cryptPassword('foo'.$method, $method,'abcdefgh12345678912345678912345678'),
$info);
}
/**
* @dataProvider hashes
* @param $method
* @param $hash
*/
function test_cryptPassword($method, $hash) {
$this->assertEquals(
$hash,
auth_cryptPassword('foo' . $method, $method, 'abcdefgh12345678912345678912345678')
);
}
function test_verifyPassword(){
foreach($this->passes as $method => $hash){
$info = "testing method $method";
$this->assertTrue(auth_verifyPassword('foo'.$method, $hash), $info);
$this->assertFalse(auth_verifyPassword('bar'.$method, $hash), $info);
}
/**
* @dataProvider hashes
* @param $method
* @param $hash
*/
function test_verifyPassword($method, $hash) {
$this->assertTrue(auth_verifyPassword('foo' . $method, $hash));
$this->assertFalse(auth_verifyPassword('bar' . $method, $hash));
}
function test_verifySelf(){
foreach($this->passes as $method => $hash){
$info = "testing method $method";
$hash = auth_cryptPassword('foo'.$method,$method);
$this->assertTrue(auth_verifyPassword('foo'.$method, $hash), $info);
}
/**
* @dataProvider hashes
* @param $method
* @param $hash
*/
function test_verifySelf($method, $hash) {
$hash = auth_cryptPassword('foo' . $method, $method);
$this->assertTrue(auth_verifyPassword('foo' . $method, $hash));
}
function test_bcrypt_self(){
$hash = auth_cryptPassword('foobcrypt','bcrypt');
$this->assertTrue(auth_verifyPassword('foobcrypt',$hash));
function test_bcrypt_self() {
$hash = auth_cryptPassword('foobcrypt', 'bcrypt');
$this->assertTrue(auth_verifyPassword('foobcrypt', $hash));
}
function test_verifyPassword_fixedbcrypt(){
$this->assertTrue(auth_verifyPassword('foobcrypt','$2a$12$uTWercxbq4sjp2xAzv3we.ZOxk51m5V/Bv5bp2H27oVFJl5neFQoC'));
function test_verifyPassword_fixedbcrypt() {
$this->assertTrue(auth_verifyPassword('foobcrypt', '$2a$12$uTWercxbq4sjp2xAzv3we.ZOxk51m5V/Bv5bp2H27oVFJl5neFQoC'));
}
function test_verifyPassword_nohash(){
$this->assertTrue(auth_verifyPassword('foo','$1$$n1rTiFE0nRifwV/43bVon/'));
function test_verifyPassword_nohash() {
$this->assertTrue(auth_verifyPassword('foo', '$1$$n1rTiFE0nRifwV/43bVon/'));
}
function test_verifyPassword_fixedpmd5(){
$this->assertTrue(auth_verifyPassword('test12345','$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'));
$this->assertTrue(auth_verifyPassword('test12345','$H$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'));
function test_verifyPassword_fixedpmd5() {
$this->assertTrue(auth_verifyPassword('test12345', '$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'));
$this->assertTrue(auth_verifyPassword('test12345', '$H$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0'));
}
function test_veryPassword_mediawiki(){
function test_veryPassword_mediawiki() {
$this->assertTrue(auth_verifyPassword('password', ':B:838c83e1:e4ab7024509eef084cdabd03d8b2972c'));
}
/**
* pmd5 checking should throw an exception when a hash with a too high
* iteration count is passed
*/
function test_verifyPassword_pmd5Exception(){
function test_verifyPassword_pmd5Exception() {
$except = false;
try{
try {
auth_verifyPassword('foopmd5', '$H$abcdefgh1ZbJodHxmeXVAhEzTG7IAp.');
}catch (Exception $e){
} catch(Exception $e) {
$except = true;
}
$this->assertTrue($except);
}
}
//Setup VIM: ex: et ts=4 :

View File

@ -1,33 +0,0 @@
<?php
/**
* Test for blowfish encryption.
*/
class blowfish_test extends DokuWikiTest {
public function testEncryptDecryptNumbers() {
$secret = '$%ÄüfuDFRR';
$string = '12345678';
$this->assertEquals(
$string,
PMA_blowfish_decrypt(PMA_blowfish_encrypt($string, $secret), $secret)
);
}
public function testEncryptDecryptChars() {
$secret = '$%ÄüfuDFRR';
$string = 'abcDEF012!"§$%&/()=?`´"\',.;:-_#+*~öäüÖÄÜ^°²³';
$this->assertEquals(
$string,
PMA_blowfish_decrypt(PMA_blowfish_encrypt($string, $secret), $secret)
);
}
// FS#1690 FS#1713
public function testEncryptDecryptBinary() {
$secret = '$%ÄüfuDFRR';
$string = "this is\0binary because of\0zero bytes";
$this->assertEquals(
$string,
PMA_blowfish_decrypt(PMA_blowfish_encrypt($string, $secret), $secret)
);
}
}

View File

@ -0,0 +1,85 @@
<?php
require_once DOKU_INC.'inc/DifferenceEngine.php';
/**
* Class difference_engine_test
*/
class difference_engine_test extends DokuWikiTest {
public $x = "zzz\n\naaa\n\nbbb\n\nccc\n\nddd\n\nddd\n\nddd\n\neee\n\nfff";
public $y = "ddd\n\naaa\n\nbbb\n\nbbb\n\nccc\n\nccc\n\neee";
function test_render_table(){
$diff = new Diff(explode("\n", $this->x), explode("\n", $this->y));
$diffformatter = new TableDiffFormatter();
$actual = $diffformatter->format($diff);
$expected = '<tr><td class="diff-blockheader" colspan="2">Line 1:</td>
<td class="diff-blockheader" colspan="2">Line 1:</td>
</tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"><strong class="diff-mark">zzz</strong></td><td class="diff-lineheader">+</td><td class="diff-addedline"><strong class="diff-mark">ddd</strong></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">aaa</td><td class="diff-lineheader">&#160;</td><td class="diff-context">aaa</td></tr>
<tr><td colspan="2">&#160;</td><td class="diff-lineheader">+</td><td class="diff-addedline"></td></tr>
<tr><td colspan="2">&#160;</td><td class="diff-lineheader">+</td><td class="diff-addedline">bbb</td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">bbb</td><td class="diff-lineheader">&#160;</td><td class="diff-context">bbb</td></tr>
<tr><td class="diff-blockheader" colspan="2">Line 7:</td>
<td class="diff-blockheader" colspan="2">Line 9:</td>
</tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">ccc</td><td class="diff-lineheader">&#160;</td><td class="diff-context">ccc</td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"><strong class="diff-mark">ddd </strong></td><td class="diff-lineheader">+</td><td class="diff-addedline"><strong class="diff-mark">ccc</strong></td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"><strong class="diff-mark"> </strong></td><td class="diff-lineheader">+</td><td class="diff-addedline"></td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"><strong class="diff-mark">ddd </strong></td><td class="diff-lineheader">+</td><td class="diff-addedline"></td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"><strong class="diff-mark"> </strong></td><td class="diff-lineheader">+</td><td class="diff-addedline"></td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"><strong class="diff-mark">ddd</strong></td><td class="diff-lineheader">+</td><td class="diff-addedline"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">eee</td><td class="diff-lineheader">&#160;</td><td class="diff-context">eee</td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline"></td><td colspan="2">&#160;</td></tr>
<tr><td class="diff-lineheader">-</td><td class="diff-deletedline">fff</td><td colspan="2">&#160;</td></tr>
';
$this->assertEquals($expected, $actual);
}
function test_render_inline(){
$diff = new Diff(explode("\n", $this->x), explode("\n", $this->y));
$diffformatter = new InlineDiffFormatter();
$actual = $diffformatter->format($diff);
$expected = '<tr><td colspan="2" class="diff-blockheader">@@ Line -1,5 +1,7 @@&#160;<span class="diff-deletedline"><del>removed</del></span>&#160;<span class="diff-addedline">created</span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td><span class="diff-deletedline"><del>zzz</del></span><span class="diff-addedline">ddd</span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">aaa</td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-addedline"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-addedline">bbb</td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">bbb</td></tr>
<tr><td colspan="2" class="diff-blockheader">@@ Line -7,11 +9,5 @@&#160;<span class="diff-deletedline"><del>removed</del></span>&#160;<span class="diff-addedline">created</span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">ccc</td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td><span class="diff-deletedline"><del>ddd </del></span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td><span class="diff-deletedline"><del> </del></span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td><span class="diff-deletedline"><del>ddd </del></span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td><span class="diff-deletedline"><del> </del></span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td><span class="diff-deletedline"><del>ddd</del></span><span class="diff-addedline">ccc</span></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context"></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-context">eee</td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-deletedline"><del></del></td></tr>
<tr><td class="diff-lineheader">&#160;</td><td class="diff-deletedline"><del>fff</del></td></tr>
';
$this->assertEquals($expected, $actual);
}
function test_engine_diag(){
// initialize
$eng = new _DiffEngine;
$eng->diff(explode("\n", $this->x), explode("\n", $this->y));
// check
$this->assertEquals(
array(9, array(array(0,0),array(1,2),array(3,4),array(4,5),array(5,7),array(6,9),array(7,10),array(9,12),array(15,13))),
$eng->_diag(0, 15, 0, 13, 8)
);
}
}
//Setup VIM: ex: et ts=4 :

View File

@ -129,6 +129,21 @@ class form_dropdownelement_test extends DokuWikiTest {
$this->assertEquals('label of third option', $selected->text());
}
/**
* Prevent double select that might occur because `'Auto' == 0` is true
*/
public function test_doubleselect() {
$form = new Form\Form();
$form->addDropdown('foo', ['Auto', 0, 1]);
$html = $form->toHTML();
$pq = phpQuery::newDocumentXHTML($html);
$selected = $pq->find('option[selected=selected]');
$this->assertEquals(1, $selected->length);
$this->assertEquals('Auto', $selected->text());
}
/**
* Ensure that there is always only a single one selected option
*/

View File

@ -0,0 +1,104 @@
<?php
// must be run within Dokuwiki
if (!defined('DOKU_INC')) {
die();
}
/**
* Test cases for the link index
*
* @author Michael Große <grosse@cosmocode.de>
*
* @group fulltext
*/
class fulltext_query_test extends DokuWikiTest
{
public function test_parse_query()
{
$Indexer = idx_get_indexer();
$inputQuery = 'test -baz "foo bar" @abc ^def';
$actualParsedQuery = ft_queryParser($Indexer, $inputQuery);
$expectedParsedQuery = [
'query' => 'test -baz "foo bar" @abc ^def',
'parsed_str' => '(W+:test)ANDNOT((W-:baz))AND((W_:foo)AND(W_:bar)AND(P+:foo bar))AND(N+:abc)ANDNOT(N-:def)',
'parsed_ary' => [
'W+:test',
'W-:baz',
'NOT',
'AND',
'W_:foo',
'W_:bar',
'AND',
'P+:foo bar',
'AND',
'AND',
'N+:abc',
'AND',
'N-:def',
'NOT',
'AND',
],
'words' => [
'test',
'baz',
'foo',
'bar',
],
'highlight' => [
'test',
'foo bar',
],
'and' => [
'test',
],
'phrases' => [
'foo bar',
],
'ns' => [
'abc',
],
'notns' => [
'def',
],
'not' => [
'baz',
],
];
$this->assertEquals($expectedParsedQuery, $actualParsedQuery);
}
public function test_unparse_query()
{
$input = [
'and' => [
'test',
],
'not' => [
'baz'
],
'phrases' => [
'foo bar',
],
'ns' => [
'abc',
],
'notns' => [
'def'
],
];
$actualQuery = ft_queryUnparser_simple(
$input['and'],
$input['not'],
$input['phrases'],
$input['ns'],
$input['notns']
);
$expectedQuery = 'test -baz "foo bar" @abc ^def';
$this->assertEquals($expectedQuery, $actualQuery);
}
}

View File

@ -0,0 +1,70 @@
<?php
class html_scedit_pattern_test extends DokuWikiTest {
public function dataProviderForTestSecEditPattern() {
return [
[
'<!-- EDIT{"target":"SECTION","name":"Plugins","hid":"plugins","codeblockOffset":0,"secid":5,"range":"1406-"} -->',
[
'secid' => 5,
'target' => 'SECTION',
'name' => 'Plugins',
'hid' => 'plugins',
'range' => '1406-',
],
'basic section edit',
],
[
'<!-- EDIT{"target":"TABLE","name":"","hid":"table4","codeblockOffset":0,"secid":10,"range":"11908-14014"} -->',
[
'secid' => 10,
'target' => 'TABLE',
'name' => '',
'hid' => 'table4',
'range' => '11908-14014',
],
'table edit'
],
[
'<!-- EDIT{"target":"PLUGIN_DATA","name":"","hid":"","codeblockOffset":0,"secid":2,"range":"27-432"} -->',
[
'secid' => 2,
'target' => 'PLUGIN_DATA',
'name' => '',
'hid' => '',
'range' => '27-432',
],
'data plugin'
],
];
}
/**
* @dataProvider dataProviderForTestSecEditPattern
*
* @param $text
* @param $expectedMatches
* @param $msg
*/
public function testSecEditPattern($text, $expectedMatches, $msg) {
preg_match(SEC_EDIT_PATTERN, $text, $matches);
$data = json_decode($matches[1], true);
foreach ($expectedMatches as $key => $expected_value) {
$this->assertSame($expected_value, $data[$key], $msg);
}
}
public function testSecEditHTMLInjection() {
$ins = p_get_instructions("====== Foo ======\n\n===== } --> <script> =====\n\n===== Bar =====\n");
$info = array();
$xhtml = p_render('xhtml', $ins, $info);
$this->assertNotNull($xhtml);
$xhtml_without_secedit = html_secedit($xhtml, false);
$this->assertFalse(strpos($xhtml_without_secedit, '<script>'), 'Plain <script> tag found in output - HTML/JS injection might be possible!');
}
}

View File

@ -16,7 +16,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('args',$resp);
@ -33,7 +33,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('args',$resp);
@ -50,7 +50,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('gzipped',$resp);
@ -67,7 +67,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('form',$resp);
@ -84,7 +84,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('url',$resp);
@ -101,7 +101,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('url',$resp);
@ -118,7 +118,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertTrue($data === false, $http->errorInfo());
$this->assertEquals('Maximum number of redirects exceeded',$http->error);
}
@ -138,7 +138,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('cookies',$resp);
@ -155,7 +155,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertTrue($data === false, $http->errorInfo());
$this->assertEquals(418,$http->status);
}
@ -172,7 +172,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertTrue($data === false, $http->errorInfo());
// this should read just the needed bytes
$http->max_bodysize_abort = false;
@ -182,7 +182,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
/* should read no more than max_bodysize+1 */
$this->assertLessThanOrEqual(251,strlen($data));
}
@ -198,14 +198,14 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data !== false, 'HTTP response '.$http->error);
$this->assertTrue($data !== false, $http->errorInfo());
$http->max_bodysize_abort = false;
$data = $http->get($this->server.'/stream/5');
if($http->noconnection()) {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data !== false, 'HTTP response '.$http->error);
$this->assertTrue($data !== false, $http->errorInfo());
}
/**
@ -220,7 +220,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertEquals(array('authenticated'=>true,'user'=>'user'), $resp);
@ -238,7 +238,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertTrue($data === false, $http->errorInfo());
$this->assertEquals(401,$http->status);
}
@ -249,7 +249,7 @@ class httpclient_http_test extends DokuWikiTest {
$http = new HTTPMockClient();
$http->timeout = 5;
$data = $http->get($this->server.'/delay/10');
$this->assertTrue($data === false, 'HTTP response '.$http->error);
$this->assertTrue($data === false, $http->errorInfo());
$this->assertEquals(-100,$http->status);
}
@ -263,7 +263,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$resp = json_decode($data, true);
$this->assertTrue(is_array($resp), 'JSON response');
$this->assertArrayHasKey('baz',$http->resp_headers);
@ -281,7 +281,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertFalse($data === false, 'HTTP response '.$http->error);
$this->assertFalse($data === false, $http->errorInfo());
$this->assertEquals(2550,strlen($data));
}
@ -298,7 +298,7 @@ class httpclient_http_test extends DokuWikiTest {
$this->markTestSkipped('connection timed out');
return;
}
$this->assertTrue($data !== false, 'HTTP response '.$http->error);
$this->assertTrue($data !== false, $http->errorInfo());
}
function test_postencode(){

View File

@ -15,7 +15,7 @@ class httpclient_http_proxy_test extends DokuWikiTest {
$http->proxy_port = 8080;
$data = $http->get($this->url);
$this->assertFalse($data === false, 'HTTP response: '.$http->error.' ['.$this->url.']');
$this->assertFalse($data === false, $http->errorInfo($this->url));
$this->assertTrue(strpos($data,'DokuWiki') !== false, 'response content');
}
}

View File

@ -7,11 +7,12 @@
*/
class HTTPMockClient extends HTTPClient {
protected $tries;
protected $lasturl;
/**
* Sets shorter timeout
*/
function __construct() {
public function __construct() {
parent::__construct();
$this->timeout = 8; // slightly faster timeouts
}
@ -21,7 +22,7 @@ class HTTPMockClient extends HTTPClient {
*
* @return bool
*/
function noconnection() {
public function noconnection() {
return ($this->tries === 0);
}
@ -33,14 +34,34 @@ class HTTPMockClient extends HTTPClient {
* @param string $method
* @return bool
*/
function sendRequest($url, $data = '', $method = 'GET') {
public function sendRequest($url, $data = '', $method = 'GET') {
$this->lasturl = $url;
$this->tries = 2; // configures the number of retries
$return = false;
while($this->tries) {
$return = parent::sendRequest($url, $data, $method);
if($this->status != -100) break;
if($this->status != -100 && $this->status != 408) break;
usleep((3 - $this->tries) * 250000);
$this->tries--;
}
return $return;
}
}
/**
* Return detailed error data
*
* @param string $info optional additional info
* @return string
*/
public function errorInfo($info = '') {
return json_encode(
array(
'URL' => $this->lasturl,
'Error' => $this->error,
'Status' => $this->status,
'Body' => $this->resp_body,
'Info' => $info
), JSON_PRETTY_PRINT
);
}
}

View File

@ -9,6 +9,7 @@ class io_getSizeFile_test extends DokuWikiTest {
if (!DOKU_HAS_GZIP) {
$this->markTestSkipped('skipping all zlib tests. Need zlib extension');
}
$this->assertTrue(true); // avoid being marked as risky for having no assertion
}
/*
@ -18,6 +19,7 @@ class io_getSizeFile_test extends DokuWikiTest {
if (!DOKU_HAS_BZIP) {
$this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension');
}
$this->assertTrue(true); // avoid being marked as risky for having no assertion
}
function test_plain(){

View File

@ -8,7 +8,9 @@ class io_readfile_test extends DokuWikiTest {
public function test_ext_zlib() {
if (!DOKU_HAS_GZIP) {
$this->markTestSkipped('skipping all zlib tests. Need zlib extension');
return;
}
$this->assertTrue(true);
}
/*
@ -17,7 +19,9 @@ class io_readfile_test extends DokuWikiTest {
public function test_ext_bz2() {
if (!DOKU_HAS_BZIP) {
$this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension');
return;
}
$this->assertTrue(true);
}
function test_plain(){

View File

@ -10,7 +10,9 @@ class io_replaceinfile_test extends DokuWikiTest {
public function test_ext_zlib() {
if (!DOKU_HAS_GZIP) {
$this->markTestSkipped('skipping all zlib tests. Need zlib extension');
return;
}
$this->assertTrue(true);
}
/*
@ -19,7 +21,9 @@ class io_replaceinfile_test extends DokuWikiTest {
public function test_ext_bz2() {
if (!DOKU_HAS_BZIP) {
$this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension');
return;
}
$this->assertTrue(true);
}
function _write($file){
@ -97,11 +101,16 @@ class io_replaceinfile_test extends DokuWikiTest {
/**
* Test passing an invalid parameter.
*
* @expectedException PHPUnit_Framework_Error_Warning
*/
function test_badparam()
{
if (class_exists('PHPUnit\Framework\Error\Warning')) {
$expect = 'PHPUnit\Framework\Error\Warning'; // PHPUnit 6
} else {
$expect = 'PHPUnit_Framework_Error_Warning'; // PHPUnit 5
}
$this->expectException($expect);
/* The empty $oldline parameter should be caught before the file doesn't exist test. */
$this->assertFalse(io_replaceInFile(TMP_DIR.'/not_existing_file.txt', '', '', false, 0));
}

View File

@ -8,7 +8,9 @@ class io_savefile_test extends DokuWikiTest {
public function test_ext_zlib() {
if (!DOKU_HAS_GZIP) {
$this->markTestSkipped('skipping all zlib tests. Need zlib extension');
return;
}
$this->assertTrue(true);
}
/*
@ -17,7 +19,9 @@ class io_savefile_test extends DokuWikiTest {
public function test_ext_bz2() {
if (!DOKU_HAS_BZIP) {
$this->markTestSkipped('skipping all bzip2 tests. Need bz2 extension');
return;
}
$this->assertTrue(true);
}
function _write($file){

View File

@ -1,80 +1,76 @@
<?php
class mail_isvalid extends DokuWikiTest {
class mail_isvalid_test extends DokuWikiTest {
public function provider() {
return array(
// our own tests
array('bugs@php.net', true),
array('~someone@somewhere.com', true),
array('no+body.here@somewhere.com.au', true),
array('username+tag@domain.com', true), // FS#1447
array("rfc2822+allthesechars_#*!'`/-={}are.legal@somewhere.com.au", true),
array('_foo@test.com', true), // FS#1049
array('bugs@php.net1', true), // new ICAN rulez seem to allow this
array('.bugs@php.net1', false),
array('bu..gs@php.net', false),
array('bugs@php..net', false),
array('bugs@.php.net', false),
array('bugs@php.net.', false),
array('bu(g)s@php.net1', false),
array('bu[g]s@php.net1', false),
array('somebody@somewhere.museum', true),
array('somebody@somewhere.travel', true),
array('root@[2010:fb:fdac::311:2101]', true),
array('test@example', true), // we allow local addresses
function test1(){
$tests = array();
// tests from http://code.google.com/p/php-email-address-validation/ below
// our own tests
$tests[] = array('bugs@php.net',true);
$tests[] = array('~someone@somewhere.com',true);
$tests[] = array('no+body.here@somewhere.com.au',true);
$tests[] = array('username+tag@domain.com',true); // FS#1447
$tests[] = array("rfc2822+allthesechars_#*!'`/-={}are.legal@somewhere.com.au",true);
$tests[] = array('_foo@test.com',true); // FS#1049
$tests[] = array('bugs@php.net1',true); // new ICAN rulez seem to allow this
$tests[] = array('.bugs@php.net1',false);
$tests[] = array('bu..gs@php.net',false);
$tests[] = array('bugs@php..net',false);
$tests[] = array('bugs@.php.net',false);
$tests[] = array('bugs@php.net.',false);
$tests[] = array('bu(g)s@php.net1',false);
$tests[] = array('bu[g]s@php.net1',false);
$tests[] = array('somebody@somewhere.museum',true);
$tests[] = array('somebody@somewhere.travel',true);
$tests[] = array('root@[2010:fb:fdac::311:2101]',true);
$tests[] = array('test@example', true); // we allow local addresses
array('test@example.com', true),
array('TEST@example.com', true),
array('1234567890@example.com', true),
array('test+test@example.com', true),
array('test-test@example.com', true),
array('t*est@example.com', true),
array('+1~1+@example.com', true),
array('{_test_}@example.com', true),
array('"[[ test ]]"@example.com', true),
array('test.test@example.com', true),
array('test."test"@example.com', true),
array('"test@test"@example.com', true),
array('test@123.123.123.123', true),
array('test@[123.123.123.123]', true),
array('test@example.example.com', true),
array('test@example.example.example.com', true),
// tests from http://code.google.com/p/php-email-address-validation/ below
$tests[] = array('test@example.com', true);
$tests[] = array('TEST@example.com', true);
$tests[] = array('1234567890@example.com', true);
$tests[] = array('test+test@example.com', true);
$tests[] = array('test-test@example.com', true);
$tests[] = array('t*est@example.com', true);
$tests[] = array('+1~1+@example.com', true);
$tests[] = array('{_test_}@example.com', true);
$tests[] = array('"[[ test ]]"@example.com', true);
$tests[] = array('test.test@example.com', true);
$tests[] = array('test."test"@example.com', true);
$tests[] = array('"test@test"@example.com', true);
$tests[] = array('test@123.123.123.123', true);
$tests[] = array('test@[123.123.123.123]', true);
$tests[] = array('test@example.example.com', true);
$tests[] = array('test@example.example.example.com', true);
$tests[] = array('test.example.com', false);
$tests[] = array('test.@example.com', false);
$tests[] = array('test..test@example.com', false);
$tests[] = array('.test@example.com', false);
$tests[] = array('test@test@example.com', false);
$tests[] = array('test@@example.com', false);
$tests[] = array('-- test --@example.com', false); // No spaces allowed in local part
$tests[] = array('[test]@example.com', false); // Square brackets only allowed within quotes
$tests[] = array('"test\test"@example.com', false); // Quotes cannot contain backslash
$tests[] = array('"test"test"@example.com', false); // Quotes cannot be nested
$tests[] = array('()[]\;:,<>@example.com', false); // Disallowed Characters
$tests[] = array('test@.', false);
$tests[] = array('test@example.', false);
$tests[] = array('test@.org', false);
$tests[] = array('12345678901234567890123456789012345678901234567890123456789012345@example.com', false); // 64 characters is maximum length for local part. This is 65.
$tests[] = array('test@123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012.com', false); // 255 characters is maximum length for domain. This is 256.
$tests[] = array('test@[123.123.123.123', false);
$tests[] = array('test@123.123.123.123]', false);
foreach($tests as $test){
$info = 'Testing '.$test[0];
if($test[1]){
$this->assertTrue((bool) mail_isvalid($test[0]), $info);
}else{
$this->assertFalse((bool) mail_isvalid($test[0]), $info);
}
}
array('test.example.com', false),
array('test.@example.com', false),
array('test..test@example.com', false),
array('.test@example.com', false),
array('test@test@example.com', false),
array('test@@example.com', false),
array('-- test --@example.com', false), // No spaces allowed in local part
array('[test]@example.com', false), // Square brackets only allowed within quotes
array('"test\test"@example.com', false), // Quotes cannot contain backslash
array('"test"test"@example.com', false), // Quotes cannot be nested
array('()[]\;:,<>@example.com', false), // Disallowed Characters
array('test@.', false),
array('test@example.', false),
array('test@.org', false),
array('12345678901234567890123456789012345678901234567890123456789012345@example.com', false), // 64 characters is maximum length for local part. This is 65.
array('test@123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012.com', false), // 255 characters is maximum length for domain. This is 256.
array('test@[123.123.123.123', false),
array('test@123.123.123.123]', false),
);
}
/**
* @dataProvider provider
* @param string $input
* @param bool $success
*/
function test1($input, $success) {
$result = mail_isvalid($input);
$this->assertSame($success, $result);
}
}
//Setup VIM: ex: et ts=4 :

View File

@ -73,6 +73,10 @@ class mailer_test extends DokuWikiTest {
}
function test_addresses(){
if (isWindows()) {
$this->markTestSkipped();
}
$mail = new TestMailer();
$mail->to('andi@splitbrain.org');
@ -241,6 +245,7 @@ class mailer_test extends DokuWikiTest {
}
}
$this->assertTrue(true); // avoid being marked as risky for having no assertion
}
function test_simplemailsignature() {

View File

@ -0,0 +1,258 @@
<?php
class media_searchlist_test extends DokuWikiTest {
/**
* @var string namespace used for testing
*/
protected $upload_ns = 'media_searchlist_test';
/**
* Save the file
*
* @param $name name of saving file
* @param $copy file used as a content of uploaded file
*/
protected function save($name, $copy) {
$media_id = $this->upload_ns.':'.$name;
media_save(array('name' => $copy), $media_id, true, AUTH_UPLOAD, 'copy');
}
/**
* Called for each test
*
* @throws Exception
*/
function setUp() {
//create some files to search
$png = mediaFN('wiki:kind_zu_katze.png');
$ogv = mediaFN('wiki:kind_zu_katze.ogv');
$webm = mediaFN('wiki:kind_zu_katze.webm');
$this->save('a.png', $png);
$this->save('aa.png', $png);
$this->save('ab.png', $png);
$this->save('a.ogv', $ogv);
$this->save('aa.ogv', $ogv);
$this->save('ab.ogv', $ogv);
$this->save('a:a.png', $png);
$this->save('b:a.png', $png);
$this->save('0.webm', $webm);
}
/*
* Reset media_printfile static variable $twibble to stat state
*/
protected function reset_media_printfile() {
$reflect = new ReflectionFunction('media_printfile');
$static = $reflect->getStaticVariables();
if ($static['twibble'] == -1) {
ob_start();
@media_printfile(array(), 0, '');
ob_end_clean();
}
}
/**
* Build search result header as in media_searchlist() with $fullscreen = false
*
* @param $query search query
* @param $ns namespece where we search
*
* @return string
*/
protected function media_searchlist_header($query, $ns) {
global $lang;
$header = '<h1 id="media__ns">'.sprintf($lang['searchmedia_in'],hsc($ns).':*').'</h1>'.NL;
ob_start();
media_searchform($ns,$query);
$header .= ob_get_contents();
ob_end_clean();
return $header;
}
/**
* Wrap around media_printfile: return the result.
*
* @param $item
* @return string
*/
protected function media_printfile($item) {
ob_start();
media_printfile($item,$item['perm'],'',true);
$out = ob_get_contents();
ob_end_clean();
return $out;
}
/**
* Wrap around media_searchlist: return the result
* Reset media_printfile static variables afterwards
*
* @param $query
* @param $ns
* @return string
*/
protected function media_searchlist($query, $ns) {
ob_start();
media_searchlist($query, $ns);
$out = ob_get_contents();
ob_end_clean();
//reset media_printfile static variables
$this->reset_media_printfile();
return $out;
}
/**
*
* @param array[string] $rel_ids media ids relative to $this->upload_ns
* @return array $items as required by media_printfile
*/
protected function create_media_items($rel_ids) {
$items = array();
foreach ($rel_ids as $rel_id){
$file = mediaFN($this->upload_ns . ':' . $rel_id);
$info = array();
$info['id'] = $this->upload_ns . ':' . $rel_id;
$info['perm'] = auth_quickaclcheck(getNS($info['id']).':*');
$info['file'] = utf8_basename($file);
$info['size'] = filesize($file);
$info['mtime'] = filemtime($file);
$info['writable'] = is_writable($file);
if(preg_match("/\.(jpe?g|gif|png)$/",$file)){
$info['isimg'] = true;
$info['meta'] = new JpegMeta($file);
}else{
$info['isimg'] = false;
}
$info['hash'] = md5(io_readFile(mediaFN($info['id']),false));
$items[] = $info;
}
return $items;
}
/**
* Output result as in 'media_searchlist' but use an arbitrary media IDs list instead of actual searching
* Reset media_printfile static variables afterwards
*
* @param array[string] $rel_ids media ids relative to $this->upload_ns
* @param string $query actual seqrch query (used for filling search filed input)
* @param string $ns
* @return string
*/
protected function media_searchlist_except($rel_ids, $query, $ns) {
//build a search result header
$expect = $this->media_searchlist_header($query, $ns);
//get the items list
$items = $this->create_media_items($rel_ids);
foreach ($items as $item) {
$expect .= $this->media_printfile($item);
}
//reset media_printfile static variables
$this->reset_media_printfile();
return $expect;
}
public function test_noglobbing(){
$query = 'a.png';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('a:a.png', 'b:a.png', 'a.png', 'aa.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_asterisk(){
$query = 'a*.png';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('a:a.png', 'b:a.png', 'a.png', 'aa.png', 'ab.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_find_by_ext(){
$query = '*.ogv';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('a.ogv', 'aa.ogv', 'ab.ogv'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_question_mark(){
$query = 'a?.png';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('aa.png', 'ab.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_question_mark_and_asterisk(){
$query = 'a?.*';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('aa.ogv', 'aa.png', 'ab.ogv', 'ab.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_question_mark_on_the_begining(){
$query = '?.png';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('a:a.png', 'b:a.png', 'a.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_two_question_marks_on_the_begining(){
$query = '??.png';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('aa.png', 'ab.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_globbing_two_letter_file_names(){
$query = '??.*';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('aa.ogv', 'aa.png', 'ab.ogv', 'ab.png'), $query, $ns);
$this->assertEquals($expect, $result);
}
public function test_zero_search(){
$query = '0';
$ns = $this->upload_ns;
$result = $this->media_searchlist($query, $ns);
$expect = $this->media_searchlist_except(array('0.webm'), $query, $ns);
$this->assertEquals($expect, $result);
}
}

View File

@ -2,7 +2,7 @@
class pageutils_findnearest_test extends DokuWikiTest {
var $oldAuthAcl;
protected $oldAuthAcl;
function setUp() {
parent::setUp();

View File

@ -4,13 +4,13 @@ class wikifn_test extends DokuWikiTest {
function test_cache_cleaning_cleanToUnclean(){
$this->assertEquals(wikiFN('wiki:',null,false),DOKU_TMP_DATA.'pages/wiki/.txt');
$this->assertEquals(wikiFN('wiki:',null,true),DOKU_TMP_DATA.'pages/wiki.txt');
$this->assertEquals(wikiFN('wiki:',null,false), TestUtils::w2u(DOKU_TMP_DATA.'pages/wiki/.txt'));
$this->assertEquals(wikiFN('wiki:',null,true), TestUtils::w2u(DOKU_TMP_DATA.'pages/wiki.txt'));
}
function test_cache_cleaning_uncleanToClean(){
$this->assertEquals(wikiFN('wiki:',null,true),DOKU_TMP_DATA.'pages/wiki.txt');
$this->assertEquals(wikiFN('wiki:',null,false),DOKU_TMP_DATA.'pages/wiki/.txt');
$this->assertEquals(wikiFN('wiki:',null,true), TestUtils::w2u(DOKU_TMP_DATA.'pages/wiki.txt'));
$this->assertEquals(wikiFN('wiki:',null,false), TestUtils::w2u(DOKU_TMP_DATA.'pages/wiki/.txt'));
}
}

View File

@ -0,0 +1,56 @@
<?php
class TestOfDoku_Handler_ParseHighlightOptions extends DokuWikiTest {
public function dataProvider() {
return [
['', null],
['something weird', null],
['enable_line_numbers', ['enable_line_numbers' => true]],
['enable_line_numbers=1', ['enable_line_numbers' => true]],
['enable_line_numbers="1"', ['enable_line_numbers' => true]],
['enable_line_numbers=0', ['enable_line_numbers' => false]],
['enable_line_numbers="0"', ['enable_line_numbers' => false]],
['enable_line_numbers=false', ['enable_line_numbers' => false]],
['enable_line_numbers="false"', ['enable_line_numbers' => false]],
['highlight_lines_extra', ['highlight_lines_extra' => [1]]],
['highlight_lines_extra=17', ['highlight_lines_extra' => [17]]],
['highlight_lines_extra=17,19', ['highlight_lines_extra' => [17, 19]]],
['highlight_lines_extra="17,19"', ['highlight_lines_extra' => [17, 19]]],
['highlight_lines_extra="17,19,17"', ['highlight_lines_extra' => [17, 19]]],
['start_line_numbers_at', ['start_line_numbers_at' => 1]],
['start_line_numbers_at=12', ['start_line_numbers_at' => 12]],
['start_line_numbers_at="12"', ['start_line_numbers_at' => 12]],
['enable_keyword_links', ['enable_keyword_links' => true]],
['enable_keyword_links=1', ['enable_keyword_links' => true]],
['enable_keyword_links="1"', ['enable_keyword_links' => true]],
['enable_keyword_links=0', ['enable_keyword_links' => false]],
['enable_keyword_links="0"', ['enable_keyword_links' => false]],
['enable_keyword_links=false', ['enable_keyword_links' => false]],
['enable_keyword_links="false"', ['enable_keyword_links' => false]],
[
'enable_line_numbers weird nothing highlight_lines_extra=17,19 start_line_numbers_at="12" enable_keyword_links=false',
[
'enable_line_numbers' => true,
'highlight_lines_extra' => [17, 19],
'start_line_numbers_at' => 12,
'enable_keyword_links' => false
]
],
];
}
/**
* @dataProvider dataProvider
* @param string $input options to parse
* @param array|null $expect expected outcome
* @throws ReflectionException
*/
public function testOptionParser($input, $expect) {
$h = new Doku_Handler();
$output = $this->callInaccessibleMethod($h, 'parse_highlight_options', [$input]);
$this->assertEquals($expect, $output);
}
}

View File

@ -5,14 +5,16 @@ require_once DOKU_INC . 'inc/parser/handler.php';
abstract class TestOfDoku_Parser extends DokuWikiTest {
var $P;
var $H;
/** @var Doku_Parser */
protected $P;
/** @var Doku_Handler */
protected $H;
function setUp() {
parent::setUp();
$this->P = new Doku_Parser();
$this->H = new Doku_Handler();
$this->P->Handler = & $this->H;
$this->P->Handler = $this->H;
}
function tearDown() {

View File

@ -1,6 +1,11 @@
<?php
require_once 'parser.inc.php';
/**
* Tests to ensure functionality of the <code> syntax tag.
*
* @group parser_code
*/
class TestOfDoku_Parser_Code extends TestOfDoku_Parser {
function setUp() {
@ -68,5 +73,281 @@ class TestOfDoku_Parser_Code extends TestOfDoku_Parser {
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_OneOption() {
$this->P->parse('Foo <code C [enable_line_numbers]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => 1)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_TwoOptions() {
$this->P->parse('Foo <code C [enable_line_numbers highlight_lines_extra="3"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'highlight_lines_extra' => array(3)
))),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_UnknownOption() {
$this->P->parse('Foo <code C [unknown="I will be deleted/ignored!"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null, null)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_EnableLineNumbers1() {
$this->P->parse('Foo <code C [enable_line_numbers]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_EnableLineNumbers2() {
$this->P->parse('Foo <code C [enable_line_numbers="1"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_EnableLineNumbers3() {
$this->P->parse('Foo <code C [enable_line_numbers="0"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => false)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_EnableLineNumbers4() {
$this->P->parse('Foo <code C [enable_line_numbers=""]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_HighlightLinesExtra1() {
$this->P->parse('Foo <code C [enable_line_numbers highlight_lines_extra="42, 123, 456, 789"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'highlight_lines_extra' => array(42, 123, 456, 789)
))),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_HighlightLinesExtra2() {
$this->P->parse('Foo <code C [enable_line_numbers highlight_lines_extra]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'highlight_lines_extra' => array(1))
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_HighlightLinesExtra3() {
$this->P->parse('Foo <code C [enable_line_numbers highlight_lines_extra=""]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'highlight_lines_extra' => array(1))
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_StartLineNumbersAt1() {
$this->P->parse('Foo <code C [enable_line_numbers [enable_line_numbers start_line_numbers_at="42"]]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'start_line_numbers_at' => 42)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_StartLineNumbersAt2() {
$this->P->parse('Foo <code C [enable_line_numbers [enable_line_numbers start_line_numbers_at]]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'start_line_numbers_at' => 1)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_StartLineNumbersAt3() {
$this->P->parse('Foo <code C [enable_line_numbers [enable_line_numbers start_line_numbers_at=""]]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_line_numbers' => true,
'start_line_numbers_at' => 1)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_EnableKeywordLinks1() {
$this->P->parse('Foo <code C [enable_keyword_links="false"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_keyword_links' => false)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
function testCodeOptionsArray_EnableKeywordLinks2() {
$this->P->parse('Foo <code C [enable_keyword_links="true"]>Test</code> Bar');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('p_close',array()),
array('code',array('Test','C', null,
array('enable_keyword_links' => true)
)),
array('p_open',array()),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$this->H->calls),$calls);
}
}

View File

@ -1,6 +1,11 @@
<?php
require_once 'parser.inc.php';
/**
* Tests for the implementation of link syntax
*
* @group parser_links
*/
class TestOfDoku_Parser_Links extends TestOfDoku_Parser {
function testExternalLinkSimple() {
@ -139,6 +144,35 @@ class TestOfDoku_Parser_Links extends TestOfDoku_Parser {
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalWWWLinkInPath() {
$this->P->addMode('externallink',new Doku_Parser_Mode_ExternalLink());
// See issue #936. Should NOT generate a link!
$this->P->parse("Foo /home/subdir/www/www.something.de/somedir/ Bar");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo /home/subdir/www/www.something.de/somedir/ Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalWWWLinkFollowingPath() {
$this->P->addMode('externallink',new Doku_Parser_Mode_ExternalLink());
$this->P->parse("Foo /home/subdir/www/ www.something.de/somedir/ Bar");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo /home/subdir/www/ ')),
array('externallink',array('http://www.something.de/somedir/', 'www.something.de/somedir/')),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalFTPLink() {
$this->P->addMode('externallink',new Doku_Parser_Mode_ExternalLink());
$this->P->parse("Foo ftp.sunsite.com Bar");
@ -153,6 +187,36 @@ class TestOfDoku_Parser_Links extends TestOfDoku_Parser {
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalFTPLinkInPath() {
$this->P->addMode('externallink',new Doku_Parser_Mode_ExternalLink());
// See issue #936. Should NOT generate a link!
$this->P->parse("Foo /home/subdir/www/ftp.something.de/somedir/ Bar");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo /home/subdir/www/ftp.something.de/somedir/ Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalFTPLinkFollowingPath() {
$this->P->addMode('externallink',new Doku_Parser_Mode_ExternalLink());
$this->P->parse("Foo /home/subdir/www/ ftp.something.de/somedir/ Bar");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo /home/subdir/www/ ')),
array('externallink',array('ftp://ftp.something.de/somedir/', 'ftp.something.de/somedir/')),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testEmail() {
$this->P->addMode('emaillink',new Doku_Parser_Mode_Emaillink());
$this->P->parse("Foo <bugs@php.net> Bar");
@ -274,6 +338,36 @@ class TestOfDoku_Parser_Links extends TestOfDoku_Parser {
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testInternalLinkCodeFollows() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[wiki:internal:link|Test]] Bar <code>command [arg1 [arg2 [arg3]]]</code>");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('internallink',array('wiki:internal:link','Test')),
array('cdata',array(' Bar <code>command [arg1 [arg2 [arg3]]]</code>')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testInternalLinkCodeFollows2() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[wiki:internal:link|[Square brackets in title] Test]] Bar <code>command [arg1 [arg2 [arg3]]]</code>");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('internallink',array('wiki:internal:link','[Square brackets in title] Test')),
array('cdata',array(' Bar <code>command [arg1 [arg2 [arg3]]]</code>')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalInInternalLink() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[http://www.google.com|Google]] Bar");
@ -289,6 +383,54 @@ class TestOfDoku_Parser_Links extends TestOfDoku_Parser {
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalInInternalLink2() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[http://www.google.com?test[]=squarebracketsinurl|Google]] Bar");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('externallink',array('http://www.google.com?test[]=squarebracketsinurl','Google')),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testExternalInInternalLink2CodeFollows() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[http://www.google.com?test[]=squarebracketsinurl|Google]] Bar <code>command [arg1 [arg2 [arg3]]]</code>");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('externallink',array('http://www.google.com?test[]=squarebracketsinurl','Google')),
array('cdata',array(' Bar <code>command [arg1 [arg2 [arg3]]]</code>')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testTwoInternalLinks() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[foo:bar|one]] and [[bar:foo|two]] Bar");
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('cdata',array("\n".'Foo ')),
array('internallink',array('foo:bar','one')),
array('cdata',array(' and ')),
array('internallink',array('bar:foo','two')),
array('cdata',array(' Bar')),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testInterwikiLink() {
$this->P->addMode('internallink',new Doku_Parser_Mode_InternalLink());
$this->P->parse("Foo [[iw>somepage|Some Page]] Bar");
@ -393,7 +535,7 @@ class TestOfDoku_Parser_Links extends TestOfDoku_Parser {
);
$this->assertEquals(array_map('stripByteIndex',$this->H->calls),$calls);
}
function testWindowsShareLinkHyphen() {
$this->P->addMode('windowssharelink',new Doku_Parser_Mode_WindowsShareLink());
$this->P->parse('Foo \\\server\share-hyphen Bar');

View File

@ -4,6 +4,7 @@ require_once 'parser.inc.php';
/**
* Tests for the implementation of audio and video files
*
* @group parser_media
* @author Michael Große <grosse@cosmocode.de>
*/
class TestOfDoku_Parser_Media extends TestOfDoku_Parser {
@ -131,4 +132,64 @@ class TestOfDoku_Parser_Media extends TestOfDoku_Parser {
$substr_start = strlen($url) - strlen($rest);
$this->assertEquals($rest, substr($url, $substr_start));
}
function testSimpleLinkText() {
$file = 'wiki:dokuwiki-128.png';
$parser_response = p_get_instructions('{{' . $file . '|This is a simple text.}}');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('internalmedia',array($file,'This is a simple text.',null,null,null,'cache','details')),
array('cdata',array(null)),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$parser_response),$calls);
}
function testLinkTextWithWavedBrackets_1() {
$file = 'wiki:dokuwiki-128.png';
$parser_response = p_get_instructions('{{' . $file . '|We got a { here.}}');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('internalmedia',array($file,'We got a { here.',null,null,null,'cache','details')),
array('cdata',array(null)),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$parser_response),$calls);
}
function testLinkTextWithWavedBrackets_2() {
$file = 'wiki:dokuwiki-128.png';
$parser_response = p_get_instructions('{{' . $file . '|We got a } here.}}');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('internalmedia',array($file,'We got a } here.',null,null,null,'cache','details')),
array('cdata',array(null)),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$parser_response),$calls);
}
function testLinkTextWithWavedBrackets_3() {
$file = 'wiki:dokuwiki-128.png';
$parser_response = p_get_instructions('{{' . $file . '|We got a { and a } here.}}');
$calls = array (
array('document_start',array()),
array('p_open',array()),
array('internalmedia',array($file,'We got a { and a } here.',null,null,null,'cache','details')),
array('cdata',array(null)),
array('p_close',array()),
array('document_end',array()),
);
$this->assertEquals(array_map('stripbyteindex',$parser_response),$calls);
}
}

View File

@ -0,0 +1,83 @@
<?php
/**
* Class parserutils_set_metadata_test
*/
class parserutils_set_metadata_test extends DokuWikiTest {
// the id used for this test case
private $id;
/**
* Set up fake user environment with for the gieven user
*
* @param string $user
*/
function helper_prepare_user($user = '1') {
global $INFO, $USERINFO;
// prepare fake users
static $users = [
'1' => [
'pass' => '179ad45c6ce2cb97cf1029e212046e81',
'name' => 'Tester1',
'mail' => 'tester1@example.com',
'grps' => array('admin', 'user'),
]
,
'tester2' => [
'pass' => '179ad45c6ce2cb97cf1029e212046e81',
'name' => 'Tester2',
'mail' => 'tester2@example.com',
'grps' => array('user'),
]
];
if(!isset($users[$user])) throw new RuntimeException('requested non-existing user');
// set up globals
$_SERVER['REMOTE_ADDR'] = '1.2.3.4';
$USERINFO = $users[$user];
$INFO['userinfo'] = $USERINFO;
$_SERVER['REMOTE_USER'] = $user;
}
/**
* test array merge, including contributors with numeric keys and array data overwritting
*/
function test_array_replace(){
// prepare user
$this->helper_prepare_user('1');
// prepare page
$this->id = 'test:set_metadata_array_replace';
saveWikiText($this->id, 'Test', 'Test data setup');
$meta = p_get_metadata($this->id);
$this->assertEquals('1', $meta['user'], 'Initial page has wrong user ID');
// $this->assertEquals(empty($meta['contributor']), true, 'Initial page should have no contributors');
// first revision with numeric user
$this->waitForTick();
saveWikiText($this->id, 'Test1', 'Test first edit');
$meta = p_get_metadata($this->id);
$last_edit_date = $meta['date']['modified'];
$this->assertEquals(array('1'=>'Tester1'), $meta['contributor'], 'First edit contributors error');
// second revision with alphabetic user
$this->waitForTick();
$this->helper_prepare_user('tester2');
saveWikiText($this->id, 'Test2', 'Test second edit');
$meta = p_get_metadata($this->id);
$this->assertNotEquals($last_edit_date, $meta['date']['modified'], 'First edit date merge error');
$this->assertEquals(array('tester2'=>'Tester2', '1'=>'Tester1'), $meta['contributor'], 'Second edit contributors error');
// third revision with the first user
$this->waitForTick();
$this->helper_prepare_user('1');
saveWikiText($this->id, 'Test3', 'Test third edit');
$meta = p_get_metadata($this->id);
$this->assertEquals(array('tester2'=>'Tester2', '1'=>'Tester1'), $meta['contributor'], 'Third edit contributors error');
}
}

View File

@ -129,10 +129,10 @@ class remote_plugin_testplugin2 extends DokuWiki_Remote_Plugin {
class remote_test extends DokuWikiTest {
var $userinfo;
protected $userinfo;
/** @var RemoteAPI */
var $remote;
protected $remote;
function setUp() {
parent::setUp();
@ -256,6 +256,7 @@ class remote_test extends DokuWikiTest {
$conf['remote'] = 1;
$conf['remoteuser'] = '';
$this->remote->forceAccess(); // no exception should occur
$this->assertTrue(true); // avoid being marked as risky for having no assertion
}
/**

View File

@ -0,0 +1,483 @@
<?php
class template_tpl_get_action_test extends DokuWikiTest {
public function setUp() {
parent::setUp();
global $ID;
$ID = 'start'; // run all tests on the start page
}
public function test_edit_edit() {
global $ACT;
global $INFO;
global $REV;
$ACT = 'show';
$REV = '';
$INFO['writable'] = true;
$INFO['exists'] = true;
$INFO['draft'] = '';
$expect = array(
'accesskey' => 'e',
'type' => 'edit',
'id' => 'start',
'method' => 'post',
'params' => array(
'do' => 'edit',
'rev' => '',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('edit'));
}
public function test_edit_edit_rev() {
global $ACT;
global $INFO;
global $REV;
$ACT = 'show';
$REV = '1234';
$INFO['writable'] = true;
$INFO['exists'] = true;
$INFO['draft'] = '';
$expect = array(
'accesskey' => 'e',
'type' => 'edit',
'id' => 'start',
'method' => 'post',
'params' => array(
'do' => 'edit',
'rev' => '1234',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('edit'));
}
public function test_edit_create() {
global $ACT;
global $INFO;
global $REV;
$ACT = 'show';
$REV = '';
$INFO['writable'] = true;
$INFO['exists'] = false;
$INFO['draft'] = '';
$expect = array(
'accesskey' => 'e',
'type' => 'create',
'id' => 'start',
'method' => 'post',
'params' => array(
'do' => 'edit',
'rev' => '',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('edit'));
}
public function test_edit_draft() {
global $ACT;
global $INFO;
global $REV;
$ACT = 'show';
$REV = '';
$INFO['writable'] = true;
$INFO['exists'] = true;
$INFO['draft'] = 'foobar';
$expect = array(
'accesskey' => 'e',
'type' => 'draft',
'id' => 'start',
'method' => 'post',
'params' => array(
'do' => 'draft',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('edit'));
}
public function test_edit_show() {
global $ACT;
global $INFO;
global $REV;
$ACT = 'edit';
$REV = '';
$INFO['writable'] = true;
$INFO['exists'] = true;
$INFO['draft'] = '';
$expect = array(
'accesskey' => 'v',
'type' => 'show',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => '',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('edit'));
}
public function test_revisions() {
$expect = array(
'accesskey' => 'o',
'type' => 'revs',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'revisions',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('history'));
$this->assertEquals($expect, tpl_get_action('revisions'));
}
public function test_recent() {
$expect = array(
'accesskey' => 'r',
'type' => 'recent',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'recent',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('recent'));
}
public function test_login() {
$expect = array(
'accesskey' => null,
'type' => 'login',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'login',
'sectok' => '',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('login'));
$_SERVER['REMOTE_USER'] = 'someone'; // logged in user
$expect = array(
'accesskey' => null,
'type' => 'logout',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'logout',
'sectok' => getSecurityToken(),
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('login'));
}
public function test_profile() {
$expect = false;
$this->assertEquals($expect, tpl_get_action('profile'));
$_SERVER['REMOTE_USER'] = 'someone'; // logged in user
$expect = array(
'accesskey' => null,
'type' => 'profile',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'profile',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('profile'));
}
public function test_index() {
$expect = array(
'accesskey' => 'x',
'type' => 'index',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'index',
),
'nofollow' => false,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('index'));
global $ID;
$ID = 'wiki:syntax'; // change to different page
$expect = array(
'accesskey' => 'x',
'type' => 'index',
'id' => 'wiki:syntax',
'method' => 'get',
'params' => array(
'do' => 'index',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('index'));
}
public function test_admin() {
$expect = false;
$this->assertEquals($expect, tpl_get_action('admin'));
// logged in super user
global $INFO;
$_SERVER['REMOTE_USER'] = 'testuser';
$INFO['ismanager'] = true;
$expect = array(
'accesskey' => null,
'type' => 'admin',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'admin',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('admin'));
}
public function test_top() {
$expect = array(
'accesskey' => 't',
'type' => 'top',
'id' => '#dokuwiki__top',
'method' => 'get',
'params' => array(
'do' => '',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('top'));
}
public function test_back() {
$expect = false;
$this->assertEquals($expect, tpl_get_action('back'));
global $ID;
$ID = 'wiki:syntax';
$expect = array(
'accesskey' => 'b',
'type' => 'back',
'id' => 'wiki:start',
'method' => 'get',
'params' => array(
'do' => '',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('back'));
}
public function test_backlink() {
$expect = array(
'accesskey' => null,
'type' => 'backlink',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'backlink',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('backlink'));
}
public function test_subscribe() {
$expect = false;
$this->assertEquals($expect, tpl_get_action('subscribe'));
$this->assertEquals($expect, tpl_get_action('subscription'));
$_SERVER['REMOTE_USER'] = 'someone'; // logged in user
$expect = false;
$this->assertEquals($expect, tpl_get_action('subscribe'));
$this->assertEquals($expect, tpl_get_action('subscription'));
// enable subscriptions
global $conf;
$conf['subscribers'] = true;
$expect = array(
'accesskey' => null,
'type' => 'subscribe',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'subscribe',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('subscribe'));
$this->assertEquals($expect, tpl_get_action('subscription'));
}
public function test_register() {
$expect = array(
'accesskey' => null,
'type' => 'register',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'register',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('register'));
$_SERVER['REMOTE_USER'] = 'somebody'; // logged in user
$expect = false;
$this->assertEquals($expect, tpl_get_action('register'));
}
public function test_resendpwd() {
$expect = array(
'accesskey' => null,
'type' => 'resendpwd',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'resendpwd',
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('resendpwd'));
$_SERVER['REMOTE_USER'] = 'somebody'; // logged in user
$expect = false;
$this->assertEquals($expect, tpl_get_action('resendpwd'));
}
public function test_revert() {
$expect = false;
$this->assertEquals($expect, tpl_get_action('revert'));
global $REV;
global $INFO;
$REV = '1234';
$INFO['writable'] = true;
$INFO['ismanager'] = true;
$expect = array(
'accesskey' => null,
'type' => 'revert',
'id' => 'start',
'method' => 'get', // FIXME should this be post?
'params' => array(
'do' => 'revert',
'rev' => '1234',
'sectok' => '' // FIXME is this correct?
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('revert'));
}
public function test_media() {
global $ID;
$ID = 'wiki:syntax';
$expect = array(
'accesskey' => null,
'type' => 'media',
'id' => 'wiki:syntax',
'method' => 'get',
'params' => array(
'do' => 'media',
'ns' => 'wiki'
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('media'));
}
public function test_mediaManager() {
global $IMG;
$IMG = 'wiki:dokuwiki.png';
$expect = array(
'accesskey' => null,
'type' => 'mediaManager',
'id' => 'start',
'method' => 'get',
'params' => array(
'do' => 'media',
'ns' => 'wiki',
'image' => 'wiki:dokuwiki.png'
),
'nofollow' => true,
'replacement' => '',
);
$this->assertEquals($expect, tpl_get_action('mediaManager'));
}
public function test_img_backto() {
$expect = array(
'accesskey' => 'b',
'type' => 'img_backto',
'id' => 'start',
'method' => 'get',
'params' => array(),
'nofollow' => true,
'replacement' => 'start',
);
$this->assertEquals($expect, tpl_get_action('img_backto'));
}
public function test_unknown() {
$expect = '[unknown %s type]';
$this->assertEquals($expect, tpl_get_action('unknown'));
}
}

View File

@ -5,8 +5,8 @@ if(!defined('UTF8_NOMBSTRING')) define('UTF8_NOMBSTRING',1);
class utf8_utf16be_test extends DokuWikiTest {
// some chars from various code regions
var $utf8 = '鈩ℵŁöx';
var $utf16 = "\x92\x29\x21\x35\x1\x41\x0\xf6\x0\x78";
protected $utf8 = '鈩ℵŁöx';
protected $utf16 = "\x92\x29\x21\x35\x1\x41\x0\xf6\x0\x78";
/**
* Convert from UTF-8 to UTF-16BE

View File

@ -0,0 +1,123 @@
<?php
/**
* @group ajax
*/
class ajax_requests_test extends DokuWikiTest {
/**
* DataProvider for the builtin Ajax calls
*
* @return array
*/
public function defaultCalls() {
return [
// TODO: better logic and DOM walks
// Call | POST | regexp pattern to match
[ 'linkwiz', ['q' => ''], '/^<div class="odd type_d/' ],
[ 'suggestions', ['q' => ''], null ],
[ 'lock', ['id' => ''], null ],
[ 'draftdel', ['id' => ''], null ],
[ 'medians', ['ns' => 'some:ns'], null ],
[ 'medialist', ['ns' => '', 'recent' => '', 'do' => ''], null ],
[ 'mediadetails', ['image' => ''], null ],
[ 'mediadiff', ['image' => ''], null ],
[ 'mediaupload', ['mediaid' => '', 'qqfile' => '' ], null ], // $_FILES
[ 'index', ['idx' => ''], null ],
[ 'linkwiz', ['q' => ''], null ],
];
}
/**
* @dataProvider defaultCalls
* @param string $call
* @param array $post
* @param string $regexp
*/
public function test_defaultCallsExist($call, $post, $regexp) {
$request = new TestRequest();
$response = $request->post(['call'=> $call]+$post, '/lib/exe/ajax.php');
$this->assertNotEquals("AJAX call '$call' unknown!\n", $response->getContent());
if (!empty($regexp)) {
$this->assertRegExp($regexp, $response->getContent());
}
}
public function test_CallNotProvided() {
$request = new TestRequest();
$response = $request->post([], '/lib/exe/ajax.php');
$this->assertEquals('', $response->getContent());
}
public function test_UnknownCall() {
$call = 'unknownCALL';
$request = new TestRequest();
$response = $request->post(['call'=> $call], '/lib/exe/ajax.php');
$this->assertEquals("AJAX call '$call' unknown!\n", $response->getContent());
}
public function test_EventOnUnknownCall() {
global $EVENT_HANDLER;
$call = 'unknownCALL';
$request = new TestRequest();
// referenced data from event hook
$hookTriggered = false;
$eventDataTriggered = '';
$dataTriggered = '';
$postTriggered = '';
$hookTriggered_AFTER = false;
$eventDataTriggered_AFTER = '';
$dataTriggered_AFTER = '';
$postTriggered_AFTER = '';
$EVENT_HANDLER->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', null,
function($event, $data) use (&$hookTriggered, &$dataTriggered, &$eventDataTriggered, &$postTriggered) {
/** @var Doku_Event $event */
$hookTriggered = true;
$dataTriggered = $data;
$eventDataTriggered = $event->data;
$postTriggered = $GLOBALS['INPUT']->post->str('q');
$event->preventDefault();
$event->stopPropagation();
echo "captured event BEFORE\n";
}, 'some passed data'
);
$EVENT_HANDLER->register_hook('AJAX_CALL_UNKNOWN', 'AFTER', null,
function($event, $data) use (&$hookTriggered_AFTER , &$dataTriggered_AFTER , &$eventDataTriggered_AFTER , &$postTriggered_AFTER ) {
/** @var Doku_Event $event */
$hookTriggered_AFTER = true;
$dataTriggered_AFTER = $data;
$eventDataTriggered_AFTER = $event->data;
$postTriggered_AFTER = $GLOBALS['INPUT']->post->str('q');
$event->preventDefault();
$event->stopPropagation();
echo "captured event AFTER";
}, 'some passed data AFTER'
);
$response = $request->post(['call'=> $call, 'q' => 'some-post-param'], '/lib/exe/ajax.php');
// BEFORE
$this->assertEquals(true, $hookTriggered, 'Testing plugin did not trigger!');
$this->assertEquals('some passed data', $dataTriggered);
$this->assertEquals($call, $eventDataTriggered, 'Must pass call name as event data');
$this->assertEquals('some-post-param', $postTriggered);
// AFTER
$this->assertEquals(true, $hookTriggered_AFTER, 'Testing plugin did not trigger!');
$this->assertEquals('some passed data AFTER', $dataTriggered_AFTER);
$this->assertEquals($call, $eventDataTriggered_AFTER, 'Must pass call name as event data');
$this->assertEquals('some-post-param', $postTriggered_AFTER);
//output
$this->assertEquals("captured event BEFORE\ncaptured event AFTER", $response->getContent());
}
}

View File

@ -38,10 +38,22 @@ class css_at_import_less_test extends DokuWikiTest {
$this->assertEquals($expected_less, $less);
}
/**
* makes proper relative path to be used in CSS @import
* @param string $path
* @return string
*/
private function importPath($path) {
if (isWindows()) {
return preg_replace('#(^.*[\\\\])#','', $path);
}
return preg_replace('#(^.*[/])#','', $path);
}
public function test_basic() {
$this->setUpFiles();
$import = preg_replace('#(^.*[/])#','',$this->import);
$import = $this->importPath($this->import);
$in_css = '@import "'.$import.'";';
$in_less = '@foo: "bar";
content: @foo;';
@ -56,12 +68,12 @@ content: @foo;';
public function test_subdirectory() {
$this->setUpFiles('/foo/bar');
$import = preg_replace('#(^.*[/])#','',$this->import);
$import = $this->importPath($this->import);
$in_css = '@import "'.$import.'";';
$in_less = '@foo: "bar";
content: @foo;';
$expected_css = '@import "/foo/bar/'.$import.'";';
$expected_css = isWindows() ? '@import "\\foo\\bar/'.$import.'";' : '@import "/foo/bar/'.$import.'";';
$expected_less = 'content: "bar";';
io_saveFile($this->import, $in_less);

View File

@ -77,11 +77,17 @@ class css_css_loadfile_test extends DokuWikiTest {
$this->file = tempnam($dir, 'css');
$this->csstest('@import "test.less"', '@import "/foo/bar/test.less"');
$this->csstest('@import \'test.less\'', '@import \'/foo/bar/test.less\'');
$this->csstest('@import url(test.less)', '@import url(/foo/bar/test.less)');
$this->csstest('@import "abc/test.less"', '@import "/foo/bar/abc/test.less"');
if (isWindows()) {
$this->csstest('@import "test.less"', '@import "\foo\bar/test.less"');
$this->csstest('@import \'test.less\'', '@import \'\foo\bar/test.less\'');
$this->csstest('@import url(test.less)', '@import url(\foo\bar/test.less)');
$this->csstest('@import "abc/test.less"', '@import "\foo\bar/abc/test.less"');
} else {
$this->csstest('@import "test.less"', '@import "/foo/bar/test.less"');
$this->csstest('@import \'test.less\'', '@import \'/foo/bar/test.less\'');
$this->csstest('@import url(test.less)', '@import url(/foo/bar/test.less)');
$this->csstest('@import "abc/test.less"', '@import "/foo/bar/abc/test.less"');
}
}
public function tearDown() {

View File

@ -0,0 +1,173 @@
<?php
/**
* @group integration
*/
class EditAndSaveTest extends DokuWikiTest {
/**
* Execute the following requests:
* - Section edit a page (headline 2, first occurrence)
* - Save a page
* - Redirect
* Check if the header id is transmitted and if the final redirect
* points to the correct header.
*/
function testEditSaveRedirect_Headline2_A() {
$request = new TestRequest();
$input = array(
'id' => 'int:editandsavetest'
);
// Show page
$response = $request->post($input);
$content = $response->getContent();
$this->assertTrue(!empty($content));
// If the test page has got the right content for our test it should have
// two headlines with the title "Headline2"
preg_match_all('#<h1[^>]*>Headline2</h1[^>]*>#', $content, $matches, PREG_SET_ORDER);
$this->assertEquals(2, count($matches));
// Get the header ids
$result = preg_match('/id="(.*)"/', $matches [0][0], $idA);
$this->assertEquals(1, $result);
$result = preg_match('/id="(.*)"/', $matches [1][0], $idB);
$this->assertEquals(1, $result);
$this->assertTrue($idA != $idB);
// Search the section edit form/button for the second id
$pattern = '/<form class="button btn_secedit".*>.*';
$pattern .= '<input type="hidden" name="hid" value="';
$pattern .= $idA[1];
$pattern .= '" \/>.*<\/form>/';
$result = preg_match($pattern, $content, $formA);
$this->assertEquals(1, $result);
// Extract all inputs from the form
$result = preg_match_all('/<input type="hidden" name="([^"]*)" value="([^"]*)" \/>/', $formA[0], $matches, PREG_SET_ORDER);
$input = array();
foreach ($matches as $match) {
$input[$match[1]] = $match[2];
}
$this->assertEquals($input['hid'], $idA[1]);
// Post the input fields (= do a section edit)
$response = $request->post($input, '/doku.php');
$content = $response->getContent();
// Our header id should have been sent back to us in the edit
// form as an hidden input field
$content = str_replace("\n", " ", $content);
$pattern = '/<form id="dw__editform"[^>]*>.*';
$pattern .= '<input type="hidden" name="hid" value="';
$pattern .= $idA[1];
$pattern .= '" \/>.*<\/form>/';
$result = preg_match($pattern, $content, $editForm);
$this->assertEquals(1, $result);
// Extract all inputs from the edit form
$result = preg_match_all('/<input type="hidden" name="([^"]*)" value="([^"]*)" \/>/', $editForm[0], $matches, PREG_SET_ORDER);
$input = array();
foreach ($matches as $match) {
$input[$match[1]] = $match[2];
}
$this->assertEquals($input['hid'], $idA[1]);
$input['do'] = 'save';
// Post the input fields (= save page)
$response = $request->post($input, '/doku.php');
// The response should carry a notification that a redirect
// was executed to our header ID
$found = $response->getData('send_redirect');
$this->assertCount(1, $found);
$hash = strpos($found[0], '#');
$headerID = substr($found[0], $hash);
$this->assertEquals($headerID, '#'.$idA[1]);
}
/**
* Execute the following requests:
* - Section edit a page (headline 2, second occurrence)
* - Save a page
* - Redirect
* Check if the header id is transmitted and if the final redirect
* points to the correct header.
*/
function testEditSaveRedirect_Headline2_B() {
$request = new TestRequest();
$input = array(
'id' => 'int:editandsavetest'
);
// Show page
$response = $request->post($input);
$content = $response->getContent();
$this->assertTrue(!empty($content));
// If the test page has got the right content for our test it should have
// two headlines with the title "Headline2"
preg_match_all('#<h1[^>]*>Headline2</h1[^>]*>#', $content, $matches, PREG_SET_ORDER);
$this->assertEquals(2, count($matches));
// Get the header ids
$result = preg_match('/id="(.*)"/', $matches [0][0], $idA);
$this->assertEquals(1, $result);
$result = preg_match('/id="(.*)"/', $matches [1][0], $idB);
$this->assertEquals(1, $result);
$this->assertTrue($idA != $idB);
// Search the section edit form/button for the second id
$pattern = '/<form class="button btn_secedit".*>.*';
$pattern .= '<input type="hidden" name="hid" value="';
$pattern .= $idB[1];
$pattern .= '" \/>.*<\/form>/';
$result = preg_match($pattern, $content, $formB);
$this->assertEquals(1, $result);
// Extract all inputs from the form
$result = preg_match_all('/<input type="hidden" name="([^"]*)" value="([^"]*)" \/>/', $formB[0], $matches, PREG_SET_ORDER);
$input = array();
foreach ($matches as $match) {
$input[$match[1]] = $match[2];
}
$this->assertEquals($input['hid'], $idB[1]);
// Post the input fields (= do a section edit)
$response = $request->post($input, '/doku.php');
$content = $response->getContent();
// Our header id should have been sent back to us in the edit
// form as an hidden input field
$content = str_replace("\n", " ", $content);
$pattern = '/<form id="dw__editform"[^>]*>.*';
$pattern .= '<input type="hidden" name="hid" value="';
$pattern .= $idB[1];
$pattern .= '" \/>.*<\/form>/';
$result = preg_match($pattern, $content, $editForm);
$this->assertEquals(1, $result);
// Extract all inputs from the edit form
$result = preg_match_all('/<input type="hidden" name="([^"]*)" value="([^"]*)" \/>/', $editForm[0], $matches, PREG_SET_ORDER);
$input = array();
foreach ($matches as $match) {
$input[$match[1]] = $match[2];
}
$this->assertEquals($input['hid'], $idB[1]);
$input['do'] = 'save';
// Post the input fields (= save page)
$response = $request->post($input, '/doku.php');
// The response should carry a notification that a redirect
// was executed to our header ID
$found = $response->getData('send_redirect');
$this->assertCount(1, $found);
$hash = strpos($found[0], '#');
$headerID = substr($found[0], $hash);
$this->assertEquals($headerID, '#'.$idB[1]);
}
}

47
appveyor.yml Normal file
View File

@ -0,0 +1,47 @@
build: false
clone_folder: c:\dokuwiki
max_jobs: 3
platform: x86
pull_requests:
do_not_increment_build_number: true
version: '{build}.{branch}'
environment:
matrix:
- PHP_VERSION: '7.0.21'
VC: 'VC14'
PHPUNIT: '6.3'
- PHP_VERSION: '5.6.30'
VC: 'VC11'
PHPUNIT: '5.7'
cache:
- c:\php -> appveyor.yml
init:
- SET PATH=c:\php\%PHP_VERSION%;%PATH%
install:
- echo %PHP_VERSION%
- IF NOT EXIST c:\php mkdir c:\php
- IF NOT EXIST c:\php\%PHP_VERSION% mkdir c:\php\%PHP_VERSION%
- cd c:\php\%PHP_VERSION%
- IF NOT EXIST php-installed.txt appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-%PHP_VERSION%-Win32-%VC%-x86.zip
- IF NOT EXIST php-installed.txt 7z x php-%PHP_VERSION%-Win32-%VC%-x86.zip -y >nul
- IF NOT EXIST php-installed.txt del /Q *.zip
- IF NOT EXIST php-installed.txt copy /Y php.ini-development php.ini
- IF NOT EXIST php-installed.txt echo max_execution_time=1200 >> php.ini
- IF NOT EXIST php-installed.txt echo date.timezone="UTC" >> php.ini
- IF NOT EXIST php-installed.txt echo extension_dir=ext >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_openssl.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_mbstring.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_gd2.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_bz2.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_pdo_sqlite.dll >> php.ini
- IF NOT EXIST php-installed.txt appveyor DownloadFile https://phar.phpunit.de/phpunit-%PHPUNIT%.phar -FileName phpunit.phar
- IF NOT EXIST php-installed.txt type nul >> php-installed.txt
test_script:
- php -v
- cd c:\dokuwiki\_test
- php c:\php\%PHP_VERSION%\phpunit.phar

View File

@ -1,13 +1,17 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
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/init.php');
/**
* Checkout and commit pages from the command line while maintaining the history
*/
class PageCLI extends DokuCLI {
class PageCLI extends CLI {
protected $force = false;
protected $username = '';
@ -15,10 +19,10 @@ class PageCLI extends DokuCLI {
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
protected function setup(Options $options) {
/* global */
$options->registerOption(
'force',
@ -32,17 +36,17 @@ class PageCLI extends DokuCLI {
'username'
);
$options->setHelp(
'Utility to help command line Dokuwiki page editing, allow '.
'Utility to help command line Dokuwiki page editing, allow ' .
'pages to be checked out for editing then committed after changes'
);
/* 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 '.
'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(
@ -61,7 +65,7 @@ class PageCLI extends DokuCLI {
/* commit command */
$options->registerCommand(
'commit',
'Checks in the working_file into the repository using the specified '.
'Checks in the working_file into the repository using the specified ' .
'wiki id, archiving the previous version.'
);
$options->registerArgument(
@ -121,23 +125,24 @@ class PageCLI extends DokuCLI {
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
$this->force = $options->getOpt('force', false);
protected function main(Options $options) {
$this->force = $options->getOpt('force', false);
$this->username = $options->getOpt('user', $this->getUser());
$command = $options->getCmd();
$args = $options->getArgs();
switch($command) {
case 'checkout':
$wiki_id = array_shift($options->args);
$localfile = array_shift($options->args);
$wiki_id = array_shift($args);
$localfile = array_shift($args);
$this->commandCheckout($wiki_id, $localfile);
break;
case 'commit':
$localfile = array_shift($options->args);
$wiki_id = array_shift($options->args);
$localfile = array_shift($args);
$wiki_id = array_shift($args);
$this->commandCommit(
$localfile,
$wiki_id,
@ -146,12 +151,12 @@ class PageCLI extends DokuCLI {
);
break;
case 'lock':
$wiki_id = array_shift($options->args);
$wiki_id = array_shift($args);
$this->obtainLock($wiki_id);
$this->success("$wiki_id locked");
break;
case 'unlock':
$wiki_id = array_shift($options->args);
$wiki_id = array_shift($args);
$this->clearLock($wiki_id);
$this->success("$wiki_id unlocked");
break;
@ -177,11 +182,11 @@ class PageCLI extends DokuCLI {
}
if(empty($localfile)) {
$localfile = getcwd().'/'.utf8_basename($wiki_fn);
$localfile = getcwd() . '/' . utf8_basename($wiki_fn);
}
if(!file_exists(dirname($localfile))) {
$this->fatal("Directory ".dirname($localfile)." does not exist");
$this->fatal("Directory " . dirname($localfile) . " does not exist");
}
if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) {
@ -204,7 +209,7 @@ class PageCLI extends DokuCLI {
* @param string $localfile
* @param string $wiki_id
* @param string $message
* @param bool $minor
* @param bool $minor
*/
protected function commandCommit($localfile, $wiki_id, $message, $minor) {
$wiki_id = cleanID($wiki_id);
@ -312,7 +317,6 @@ class PageCLI extends DokuCLI {
}
}
// Main
$cli = new PageCLI();
$cli->run();
$cli->run();

View File

@ -1,27 +1,31 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
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/init.php');
/**
* Easily manage DokuWiki git repositories
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
class GitToolCLI extends DokuCLI {
class GitToolCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
protected function setup(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".
"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"
);
@ -33,7 +37,7 @@ class GitToolCLI extends DokuCLI {
$options->registerCommand(
'clone',
'Tries to install a known plugin or template (prefix with template:) via git. Uses the DokuWiki.org '.
'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(
@ -45,7 +49,7 @@ class GitToolCLI extends DokuCLI {
$options->registerCommand(
'install',
'The same as clone, but when no git source repository can be found, the extension is installed via '.
'The same as clone, but when no git source repository can be found, the extension is installed via ' .
'download'
);
$options->registerArgument(
@ -62,7 +66,7 @@ class GitToolCLI extends DokuCLI {
$options->registerCommand(
'*',
'Any unknown commands are assumed to be arguments to git and will be executed in all repositories '.
'Any unknown commands are assumed to be arguments to git and will be executed in all repositories ' .
'found within this DokuWiki installation'
);
}
@ -72,39 +76,40 @@ class GitToolCLI extends DokuCLI {
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
protected function main(Options $options) {
$command = $options->getCmd();
if(!$command) $command = array_shift($options->args);
$args = $options->getArgs();
if(!$command) $command = array_shift($args);
switch($command) {
case '':
echo $options->help();
break;
case 'clone':
$this->cmd_clone($options->args);
$this->cmd_clone($args);
break;
case 'install':
$this->cmd_install($options->args);
$this->cmd_install($args);
break;
case 'repo':
case 'repos':
$this->cmd_repos();
break;
default:
$this->cmd_git($command, $options->args);
$this->cmd_git($command, $args);
}
}
/**
* Tries to install the given extensions using git clone
*
* @param array $extensions
* @param array $extensions
*/
public function cmd_clone($extensions) {
$errors = array();
$errors = array();
$succeeded = array();
foreach($extensions as $ext) {
@ -123,17 +128,17 @@ class GitToolCLI extends DokuCLI {
}
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));
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 array $extensions
* @param array $extensions
*/
public function cmd_install($extensions) {
$errors = array();
$errors = array();
$succeeded = array();
foreach($extensions as $ext) {
@ -156,8 +161,8 @@ class GitToolCLI extends DokuCLI {
}
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));
if($succeeded) $this->success('successfully installed the following extensions: ' . join(', ', $succeeded));
if($errors) $this->error('failed to install the following extensions: ' . join(', ', $errors));
}
/**
@ -179,7 +184,6 @@ class GitToolCLI extends DokuCLI {
continue;
}
echo "\n";
$this->info("executing $shell in $repo");
$ret = 0;
system($shell, $ret);
@ -247,9 +251,9 @@ class GitToolCLI extends DokuCLI {
*/
private function cloneExtension($ext, $repo) {
if(substr($ext, 0, 9) == 'template:') {
$target = fullpath(tpl_incdir().'../'.substr($ext, 9));
$target = fullpath(tpl_incdir() . '../' . substr($ext, 9));
} else {
$target = DOKU_PLUGIN.$ext;
$target = DOKU_PLUGIN . $ext;
}
$this->info("cloning $ext from $repo to $target");
@ -274,15 +278,15 @@ class GitToolCLI extends DokuCLI {
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)
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');
$this->success('Found ' . count($data) . ' .git directories');
}
$data = array_map('fullpath', array_map('dirname', $data));
return $data;
@ -308,7 +312,7 @@ class GitToolCLI extends DokuCLI {
if(preg_match('/github\.com\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
$user = $m[1];
$repo = $m[2];
return 'https://github.com/'.$user.'/'.$repo.'.git';
return 'https://github.com/' . $user . '/' . $repo . '.git';
}
// match gitorious repos
@ -317,14 +321,14 @@ class GitToolCLI extends DokuCLI {
$repo = $m[2];
if(!$repo) $repo = $user;
return 'https://git.gitorious.org/'.$user.'/'.$repo.'.git';
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 'https://bitbucket.org/' . $user . '/' . $repo . '.git';
}
return false;
@ -333,4 +337,4 @@ class GitToolCLI extends DokuCLI {
// Main
$cli = new GitToolCLI();
$cli->run();
$cli->run();

View File

@ -1,13 +1,17 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
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/init.php');
/**
* Update the Search Index from command line
*/
class IndexerCLI extends DokuCLI {
class IndexerCLI extends CLI {
private $quiet = false;
private $clear = false;
@ -15,12 +19,12 @@ class IndexerCLI extends DokuCLI {
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
protected function setup(Options $options) {
$options->setHelp(
'Updates the searchindex by indexing all new or changed pages. When the -c option is '.
'Updates the searchindex by indexing all new or changed pages. When the -c option is ' .
'given the index is cleared first.'
);
@ -41,10 +45,10 @@ class IndexerCLI extends DokuCLI {
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
protected function main(Options $options) {
$this->clear = $options->getOpt('clear');
$this->quiet = $options->getOpt('quiet');
@ -61,7 +65,7 @@ class IndexerCLI extends DokuCLI {
$data = array();
$this->quietecho("Searching pages... ");
search($data, $conf['datadir'], 'search_allpages', array('skipacl' => true));
$this->quietecho(count($data)." pages found.\n");
$this->quietecho(count($data) . " pages found.\n");
foreach($data as $val) {
$this->index($val['id']);
@ -100,4 +104,4 @@ class IndexerCLI extends DokuCLI {
// Main
$cli = new IndexerCLI();
$cli->run();
$cli->run();

103
bin/plugin.php Executable file
View File

@ -0,0 +1,103 @@
#!/usr/bin/php
<?php
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Colors;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
class PluginCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param Options $options
* @return void
*/
protected function setup(Options $options) {
$options->setHelp('Excecutes Plugin command line tools');
$options->registerArgument('plugin', 'The plugin CLI you want to run. Leave off to see list', false);
}
/**
* Your main program
*
* Arguments and options have been parsed when this is run
*
* @param Options $options
* @return void
*/
protected function main(Options $options) {
global $argv;
$argv = $options->getArgs();
if($argv) {
$plugin = $this->loadPlugin($argv[0]);
if($plugin !== null) {
$plugin->run();
} else {
$this->fatal('Command {cmd} not found.', ['cmd' => $argv[0]]);
}
} else {
echo $options->help();
$this->listPlugins();
}
}
/**
* List available plugins
*/
protected function listPlugins() {
/** @var Doku_Plugin_Controller $plugin_controller */
global $plugin_controller;
echo "\n";
echo "\n";
echo $this->colors->wrap('AVAILABLE PLUGINS:', Colors::C_BROWN);
echo "\n";
$list = $plugin_controller->getList('cli');
sort($list);
if(!count($list)) {
echo $this->colors->wrap(" No plugins providing CLI components available\n", Colors::C_RED);
} else {
$tf = new \splitbrain\phpcli\TableFormatter($this->colors);
foreach($list as $name) {
$plugin = $this->loadPlugin($name);
if($plugin === null) continue;
$info = $plugin->getInfo();
echo $tf->format(
[2, '30%', '*'],
['', $name, $info['desc']],
['', Colors::C_CYAN, '']
);
}
}
}
/**
* Instantiate a CLI plugin
*
* @param string $name
* @return DokuWiki_CLI_Plugin|null
*/
protected
function loadPlugin($name) {
// execute the plugin CLI
$class = "cli_plugin_$name";
if(class_exists($class)) {
return new $class();
}
return null;
}
}
// Main
$cli = new PluginCLI();
$cli->run();

View File

@ -1,9 +1,12 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
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
@ -16,20 +19,20 @@ require_once(DOKU_INC.'inc/init.php');
* @license GPL2
* @author Andreas Gohr <andi@splitbrain.org>
*/
class RenderCLI extends DokuCLI {
class RenderCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
protected function setup(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 '.
'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');
@ -40,16 +43,16 @@ class RenderCLI extends DokuCLI {
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @param Options $options
* @throws DokuCLI_Exception
* @return void
*/
protected function main(DokuCLI_Options $options) {
protected function main(Options $options) {
$renderer = $options->getOpt('renderer', 'xhtml');
// do the action
$source = stream_get_contents(STDIN);
$info = array();
$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;
@ -58,4 +61,4 @@ class RenderCLI extends DokuCLI {
// Main
$cli = new RenderCLI();
$cli->run();
$cli->run();

View File

@ -1,25 +1,28 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
define('NOSESSION', 1);
require_once(DOKU_INC.'inc/init.php');
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
define('NOSESSION', 1);
require_once(DOKU_INC . 'inc/init.php');
/**
* Remove unwanted languages from a DokuWiki install
*/
class StripLangsCLI extends DokuCLI {
class StripLangsCLI extends CLI {
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
protected function setup(Options $options) {
$options->setHelp(
'Remove all languages from the installation, besides the ones specified. English language '.
'Remove all languages from the installation, besides the ones specified. English language ' .
'is never removed!'
);
@ -41,10 +44,10 @@ class StripLangsCLI extends DokuCLI {
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
protected function main(Options $options) {
if($options->getOpt('keep')) {
$keep = explode(',', $options->getOpt('keep'));
if(!in_array('en', $keep)) $keep[] = 'en';
@ -56,16 +59,16 @@ class StripLangsCLI extends DokuCLI {
}
// 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);
$this->stripDirLangs(realpath(dirname(__FILE__) . '/../inc/lang'), $keep);
$this->processExtensions(realpath(dirname(__FILE__) . '/../lib/plugins'), $keep);
$this->processExtensions(realpath(dirname(__FILE__) . '/../lib/tpl'), $keep);
}
/**
* Strip languages from extensions
*
* @param string $path path to plugin or template dir
* @param array $keep_langs languages to keep
* @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)) {
@ -73,9 +76,9 @@ class StripLangsCLI extends DokuCLI {
foreach($entries as $entry) {
if($entry != "." && $entry != "..") {
if(is_dir($path.'/'.$entry)) {
if(is_dir($path . '/' . $entry)) {
$plugin_langs = $path.'/'.$entry.'/lang';
$plugin_langs = $path . '/' . $entry . '/lang';
if(is_dir($plugin_langs)) {
$this->stripDirLangs($plugin_langs, $keep_langs);
@ -89,17 +92,17 @@ class StripLangsCLI extends DokuCLI {
/**
* Strip languages from path
*
* @param string $path path to lang dir
* @param array $keep_langs languages to keep
* @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)) {
if($cur_dir != '.' and $cur_dir != '..' and is_dir($path . '/' . $cur_dir)) {
if(!in_array($cur_dir, $keep_langs, true)) {
io_rmdir($path.'/'.$cur_dir, true);
io_rmdir($path . '/' . $cur_dir, true);
}
}
}
@ -108,4 +111,4 @@ class StripLangsCLI extends DokuCLI {
}
$cli = new StripLangsCLI();
$cli->run();
$cli->run();

View File

@ -1,33 +1,56 @@
#!/usr/bin/php
<?php
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/');
use splitbrain\phpcli\CLI;
use splitbrain\phpcli\Options;
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/init.php');
/**
* Find wanted pages
*/
class WantedPagesCLI extends DokuCLI {
class WantedPagesCLI extends CLI {
const DIR_CONTINUE = 1;
const DIR_NS = 2;
const DIR_PAGE = 3;
const DIR_NS = 2;
const DIR_PAGE = 3;
private $skip = false;
private $sort = 'wanted';
private $result = array();
/**
* Register options and arguments on the given $options object
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function setup(DokuCLI_Options $options) {
protected function setup(Options $options) {
$options->setHelp(
'Outputs a list of wanted pages (pages which have internal links but do not yet exist).'
'Outputs a list of wanted pages (pages that do not exist yet) and their origin pages ' .
' (the pages that are linkin to these missing pages).'
);
$options->registerArgument(
'namespace',
'The namespace to lookup. Defaults to root namespace',
false
);
$options->registerOption(
'sort',
'Sort by wanted or origin page',
's',
'(wanted|origin)'
);
$options->registerOption(
'skip',
'Do not show the second dimension',
'k'
);
}
/**
@ -35,29 +58,36 @@ class WantedPagesCLI extends DokuCLI {
*
* Arguments and options have been parsed when this is run
*
* @param DokuCLI_Options $options
* @param Options $options
* @return void
*/
protected function main(DokuCLI_Options $options) {
if($options->args) {
$startdir = dirname(wikiFN($options->args[0].':xxx'));
protected function main(Options $options) {
$args = $options->getArgs();
if($args) {
$startdir = dirname(wikiFN($args[0] . ':xxx'));
} else {
$startdir = dirname(wikiFN('xxx'));
}
$this->skip = $options->getOpt('skip');
$this->sort = $options->getOpt('sort');
$this->info("searching $startdir");
$wanted_pages = array();
foreach($this->get_pages($startdir) as $page) {
$wanted_pages = array_merge($wanted_pages, $this->internal_links($page));
$this->internal_links($page);
}
$wanted_pages = array_unique($wanted_pages);
sort($wanted_pages);
foreach($wanted_pages as $page) {
print $page."\n";
ksort($this->result);
foreach($this->result as $main => $subs) {
if($this->skip) {
print "$main\n";
} else {
$subs = array_unique($subs);
sort($subs);
foreach($subs as $sub) {
printf("%-40s %s\n", $main, $sub);
}
}
}
}
@ -72,7 +102,7 @@ class WantedPagesCLI extends DokuCLI {
if($entry == '.' || $entry == '..') {
return WantedPagesCLI::DIR_CONTINUE;
}
if(is_dir($basepath.'/'.$entry)) {
if(is_dir($basepath . '/' . $entry)) {
if(strpos($entry, '_') === 0) {
return WantedPagesCLI::DIR_CONTINUE;
}
@ -95,7 +125,7 @@ class WantedPagesCLI extends DokuCLI {
static $trunclen = null;
if(!$trunclen) {
global $conf;
$trunclen = strlen($conf['datadir'].':');
$trunclen = strlen($conf['datadir'] . ':');
}
if(!is_dir($dir)) {
@ -103,17 +133,17 @@ class WantedPagesCLI extends DokuCLI {
}
$pages = array();
$dh = opendir($dir);
$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));
$pages = array_merge($pages, $this->get_pages($dir . '/' . $entry));
} else {
$page = array(
'id' => pathID(substr($dir.'/'.$entry, $trunclen)),
'file' => $dir.'/'.$entry,
$page = array(
'id' => pathID(substr($dir . '/' . $entry, $trunclen)),
'file' => $dir . '/' . $entry,
);
$pages[] = $page;
}
@ -123,31 +153,34 @@ class WantedPagesCLI extends DokuCLI {
}
/**
* Parse instructions and returns the non-existing links
* Parse instructions and add the non-existing links to the result array
*
* @param array $page array with page id and file path
* @return array
*/
function internal_links($page) {
global $conf;
$instructions = p_get_instructions(file_get_contents($page['file']));
$links = array();
$cns = getNS($page['id']);
$exists = false;
$cns = getNS($page['id']);
$exists = false;
$pid = $page['id'];
foreach($instructions as $ins) {
if($ins[0] == 'internallink' || ($conf['camelcase'] && $ins[0] == 'camelcaselink')) {
$mid = $ins[1][0];
resolve_pageid($cns, $mid, $exists);
if(!$exists) {
list($mid) = explode('#', $mid); //record pages without hashs
$links[] = $mid;
list($mid) = explode('#', $mid); //record pages without hashes
if($this->sort == 'origin') {
$this->result[$pid][] = $mid;
} else {
$this->result[$mid][] = $pid;
}
}
}
}
return $links;
}
}
// Main
$cli = new WantedPagesCLI();
$cli->run();
$cli->run();

View File

@ -5,12 +5,21 @@
"type": "project",
"license": "GPL v2",
"require": {
"php": ">=5.3",
"php": ">=5.6",
"splitbrain/php-archive": "~1.0",
"easybook/geshi": "~1.0",
"phpseclib/phpseclib": "~2.0",
"paragonie/random_compat": "^2.0",
"simplepie/simplepie": "^1.4"
"simplepie/simplepie": "^1.4",
"geshi/geshi": "^1.0",
"openpsa/universalfeedcreator": "^1.8",
"aziraphale/email-address-validator": "^2",
"marcusschwarz/lesserphp": "^0.5.1",
"splitbrain/php-cli": "^1.1"
},
"config": {
"platform": {
"php": "5.6"
}
},
"suggest": {
"squizlabs/php_codesniffer": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",

291
composer.lock generated
View File

@ -4,66 +4,201 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "e554e0599b74f5057ae2de1300c5bde0",
"content-hash": "d5c15248668d2dd749de47b106049b77",
"packages": [
{
"name": "easybook/geshi",
"version": "v1.0.8.18",
"name": "aziraphale/email-address-validator",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/easybook/geshi.git",
"reference": "4b06bfe8c6fbedd6aad0a0700d650f591386e287"
"url": "https://github.com/aziraphale/email-address-validator.git",
"reference": "fa25bc22c1c0b6491657c91473fae3e40719a650"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/easybook/geshi/zipball/4b06bfe8c6fbedd6aad0a0700d650f591386e287",
"reference": "4b06bfe8c6fbedd6aad0a0700d650f591386e287",
"url": "https://api.github.com/repos/aziraphale/email-address-validator/zipball/fa25bc22c1c0b6491657c91473fae3e40719a650",
"reference": "fa25bc22c1c0b6491657c91473fae3e40719a650",
"shasum": ""
},
"require": {
"php": ">4.3.0"
"require-dev": {
"phpunit/phpunit": "^5.7"
},
"type": "library",
"autoload": {
"psr-0": {
"EmailAddressValidator": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dave Child",
"email": "dave@addedbytes.com"
},
{
"name": "Andrew Gillard",
"email": "andrew@lorddeath.net"
}
],
"description": "Fork of AddedBytes' PHP EmailAddressValidator script, now with Composer support!",
"homepage": "https://github.com/aziraphale/email-address-validator",
"time": "2017-05-22T14:05:57+00:00"
},
{
"name": "geshi/geshi",
"version": "v1.0.9.0",
"source": {
"type": "git",
"url": "https://github.com/GeSHi/geshi-1.0.git",
"reference": "5a7b461338d322d941986a656d4d1651452e73dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/GeSHi/geshi-1.0/zipball/5a7b461338d322d941986a656d4d1651452e73dd",
"reference": "5a7b461338d322d941986a656d4d1651452e73dd",
"shasum": ""
},
"require-dev": {
"phpunit/phpunit": "^5.7"
},
"type": "library",
"autoload": {
"classmap": [
"./"
"src/geshi/",
"src/geshi.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-2.0"
"GPL-2.0+"
],
"authors": [
{
"name": "Nigel McNie",
"email": "nigel@geshi.org"
},
{
"name": "Benny Baumann",
"email": "BenBE@geshi.org"
"email": "BenBE@geshi.org",
"homepage": "http://blog.benny-baumann.de/",
"role": "Developer"
}
],
"description": "GeSHi - Generic Syntax Highlighter. This is an unmodified port of GeSHi project code found on SourceForge.",
"homepage": "http://qbnz.com/highlighter",
"keywords": [
"highlight",
"highlighter",
"syntax"
],
"time": "2016-10-05T07:15:42+00:00"
"description": "Generic Syntax Highlighter",
"homepage": "http://qbnz.com/highlighter/",
"time": "2017-05-05T05:51:25+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.4",
"name": "marcusschwarz/lesserphp",
"version": "v0.5.1",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e"
"url": "https://github.com/MarcusSchwarz/lesserphp.git",
"reference": "e9e3d53980c0e486b07c75e12f2bae5e10bdee44"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e",
"reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e",
"url": "https://api.github.com/repos/MarcusSchwarz/lesserphp/zipball/e9e3d53980c0e486b07c75e12f2bae5e10bdee44",
"reference": "e9e3d53980c0e486b07c75e12f2bae5e10bdee44",
"shasum": ""
},
"require-dev": {
"phpunit/phpunit": "~4.3"
},
"bin": [
"plessc"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.5.1-dev"
}
},
"autoload": {
"classmap": [
"lessc.inc.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT",
"GPL-3.0"
],
"authors": [
{
"name": "Leaf Corcoran",
"email": "leafot@gmail.com",
"homepage": "http://leafo.net"
},
{
"name": "Marcus Schwarz",
"email": "github@maswaba.de",
"homepage": "https://www.maswaba.de"
}
],
"description": "lesserphp is a compiler for LESS written in PHP based on leafo's lessphp.",
"homepage": "http://leafo.net/lessphp/",
"time": "2016-09-30T11:13:18+00:00"
},
{
"name": "openpsa/universalfeedcreator",
"version": "v1.8.3",
"source": {
"type": "git",
"url": "https://github.com/flack/UniversalFeedCreator.git",
"reference": "6261e130446d8f787bbfd229a602fb11e6816a4e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/flack/UniversalFeedCreator/zipball/6261e130446d8f787bbfd229a602fb11e6816a4e",
"reference": "6261e130446d8f787bbfd229a602fb11e6816a4e",
"shasum": ""
},
"require": {
"php": ">=5.0"
},
"require-dev": {
"phpunit/phpunit": "*"
},
"type": "library",
"autoload": {
"classmap": [
"lib"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Andreas Flack",
"email": "flack@contentcontrol-berlin.de",
"homepage": "http://www.contentcontrol-berlin.de/"
}
],
"description": "RSS and Atom feed generator by Kai Blankenhorn",
"keywords": [
"atom",
"georss",
"gpx",
"opml",
"pie",
"rss"
],
"time": "2017-05-18T08:28:48+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.12",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"shasum": ""
},
"require": {
@ -98,20 +233,20 @@
"pseudorandom",
"random"
],
"time": "2016-11-07T23:38:38+00:00"
"time": "2018-04-04T21:24:14+00:00"
},
{
"name": "phpseclib/phpseclib",
"version": "2.0.4",
"version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf"
"reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
"reference": "ab8028c93c03cc8d9c824efa75dc94f1db2369bf",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d305b780829ea4252ed9400b3f5937c2c99b51d4",
"reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4",
"shasum": ""
},
"require": {
@ -119,7 +254,7 @@
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
@ -190,20 +325,20 @@
"x.509",
"x509"
],
"time": "2016-10-04T00:57:04+00:00"
"time": "2018-02-19T04:29:13+00:00"
},
{
"name": "simplepie/simplepie",
"version": "1.4.3",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "2a24b6e74aa9bf33243020f52895fe77efe94ccf"
"reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/2a24b6e74aa9bf33243020f52895fe77efe94ccf",
"reference": "2a24b6e74aa9bf33243020f52895fe77efe94ccf",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"shasum": ""
},
"require": {
@ -250,20 +385,20 @@
"feeds",
"rss"
],
"time": "2016-11-27T01:39:18+00:00"
"time": "2017-11-12T02:03:34+00:00"
},
{
"name": "splitbrain/php-archive",
"version": "1.0.7",
"version": "1.0.9",
"source": {
"type": "git",
"url": "https://github.com/splitbrain/php-archive.git",
"reference": "c075304b44c4aadff0718af445e86bf730f331ff"
"reference": "2a63b8cf0bfc7fdc0d987c9b7348e639e55cce76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/splitbrain/php-archive/zipball/c075304b44c4aadff0718af445e86bf730f331ff",
"reference": "c075304b44c4aadff0718af445e86bf730f331ff",
"url": "https://api.github.com/repos/splitbrain/php-archive/zipball/2a63b8cf0bfc7fdc0d987c9b7348e639e55cce76",
"reference": "2a63b8cf0bfc7fdc0d987c9b7348e639e55cce76",
"shasum": ""
},
"require": {
@ -272,6 +407,10 @@
"require-dev": {
"phpunit/phpunit": "4.5.*"
},
"suggest": {
"ext-iconv": "Used for proper filename encode handling",
"ext-mbstring": "Can be used alternatively for handling filename encoding"
},
"type": "library",
"autoload": {
"psr-4": {
@ -297,7 +436,58 @@
"unzip",
"zip"
],
"time": "2015-08-12T13:24:34+00:00"
"time": "2017-06-11T06:11:38+00:00"
},
{
"name": "splitbrain/php-cli",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/splitbrain/php-cli.git",
"reference": "1d6f0bf9eccbfd79d1f4d185ef27573601185c23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/splitbrain/php-cli/zipball/1d6f0bf9eccbfd79d1f4d185ef27573601185c23",
"reference": "1d6f0bf9eccbfd79d1f4d185ef27573601185c23",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "4.5.*"
},
"suggest": {
"psr/log": "Allows you to make the CLI available as PSR-3 logger"
},
"type": "library",
"autoload": {
"psr-4": {
"splitbrain\\phpcli\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Andreas Gohr",
"email": "andi@splitbrain.org"
}
],
"description": "Easy command line scripts for PHP with opt parsing and color output. No dependencies",
"keywords": [
"argparse",
"cli",
"command line",
"console",
"getopt",
"optparse",
"terminal"
],
"time": "2018-02-02T08:46:12+00:00"
}
],
"packages-dev": [],
@ -307,7 +497,10 @@
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
"php": ">=5.3"
"php": ">=5.6"
},
"platform-dev": []
"platform-dev": [],
"platform-overrides": {
"php": "5.6"
}
}

View File

@ -108,6 +108,7 @@ $conf['subscribe_time'] = 24*60*60; //Time after which digests / lists are
$conf['notify'] = ''; //send change info to this email (leave blank for nobody)
$conf['registernotify'] = ''; //send info about newly registered users to this email (leave blank for nobody)
$conf['mailfrom'] = ''; //use this email when sending mails
$conf['mailreturnpath'] = ''; //use this email as returnpath for bounce mails
$conf['mailprefix'] = ''; //use this as prefix of outgoing mails
$conf['htmlmail'] = 1; //send HTML multipart mails
@ -155,6 +156,8 @@ $conf['broken_iua'] = 0; //Platform with broken ignore_user_abor
$conf['xsendfile'] = 0; //Use X-Sendfile (1 = lighttpd, 2 = standard)
$conf['renderer_xhtml'] = 'xhtml'; //renderer to use for main page generation
$conf['readdircache'] = 0; //time cache in second for the readdir operation, 0 to deactivate.
$conf['search_nslimit'] = 0; //limit the search to the current X namespaces
$conf['search_fragment'] = 'exact'; //specify the default fragment search behavior
/* Network Settings */
$conf['dnslookups'] = 1; //disable to disallow IP to hostname lookups

3
conf/manifest.json Normal file
View File

@ -0,0 +1,3 @@
{
"display": "standalone"
}

View File

@ -15,6 +15,7 @@ wav audio/wav
webm video/webm
ogv video/ogg
mp4 video/mp4
vtt text/vtt
tgz !application/octet-stream
tar !application/x-gtar

View File

@ -6,5 +6,5 @@
#
# Format:
#
# login:passwordhash:Real Name:email:groups,comma,seperated
# login:passwordhash:Real Name:email:groups,comma,separated

View File

@ -2,6 +2,19 @@
# but were removed later. An up to date DokuWiki should not have any of
# the files installed
# removed in 2018-04-22
data/security.png
data/security.xcf
inc/EmailAddressValidator.php
inc/blowfish.php
inc/feedcreator.class.php
inc/lessc.inc.php
inc/plugin.php
lib/images/loading.gif
lib/tpl/dokuwiki/css/_search.css
vendor/easybook/geshi
vendor/phpseclib/phpseclib/composer.lock
# remove in 2017-02-19
inc/SimplePie.php
inc/Tar.class.php

View File

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1,586 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128.17094"
height="128.03864"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.48.1 "
sodipodi:docname="dokuwiki-logo.svg"
version="1.1">
<title
id="title3181">DokuWiki Logo</title>
<defs
id="defs4">
<linearGradient
id="linearGradient2624">
<stop
style="stop-color:#3a9030;stop-opacity:0.83673471;"
offset="0"
id="stop2626" />
<stop
style="stop-color:#3d9c32;stop-opacity:0.79591835;"
offset="1"
id="stop2628" />
</linearGradient>
<linearGradient
id="linearGradient2612">
<stop
style="stop-color:#25901b;stop-opacity:0.83673471;"
offset="0"
id="stop2614" />
<stop
style="stop-color:#25901b;stop-opacity:0.37755102;"
offset="1"
id="stop2616" />
</linearGradient>
<linearGradient
id="linearGradient2600">
<stop
style="stop-color:#e32525;stop-opacity:0.81632656;"
offset="0"
id="stop2602" />
<stop
style="stop-color:#e32525;stop-opacity:0.5714286;"
offset="1"
id="stop2604" />
</linearGradient>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0"
refX="0"
id="TriangleOutL"
style="overflow:visible">
<path
id="path2488"
d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="scale(0.8,0.8)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow2Lstart"
style="overflow:visible">
<path
id="path2571"
style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
transform="matrix(1.1,0,0,1.1,-5.5,0)"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
id="linearGradient2408">
<stop
id="stop2410"
offset="0"
style="stop-color:#000000;stop-opacity:0.17346939;" />
<stop
id="stop2412"
offset="1"
style="stop-color:#c7cec2;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient2389">
<stop
style="stop-color:#000000;stop-opacity:0.17346939;"
offset="0"
id="stop2391" />
<stop
style="stop-color:#c7cec2;stop-opacity:0;"
offset="1"
id="stop2393" />
</linearGradient>
<linearGradient
id="linearGradient2370">
<stop
style="stop-color:#fbfaf9;stop-opacity:1;"
offset="0"
id="stop2372" />
<stop
style="stop-color:#e9dac7;stop-opacity:1;"
offset="1"
id="stop2374" />
</linearGradient>
<linearGradient
id="linearGradient2364">
<stop
id="stop2366"
offset="0"
style="stop-color:#fbf6f0;stop-opacity:1;" />
<stop
id="stop2368"
offset="1"
style="stop-color:#e9dac7;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2348">
<stop
style="stop-color:#fbf6f0;stop-opacity:1;"
offset="0"
id="stop2350" />
<stop
style="stop-color:#e9dac7;stop-opacity:1;"
offset="1"
id="stop2352" />
</linearGradient>
<linearGradient
id="linearGradient2332">
<stop
style="stop-color:#ede1ae;stop-opacity:1;"
offset="0"
id="stop2334" />
<stop
style="stop-color:#fefdfa;stop-opacity:1;"
offset="1"
id="stop2336" />
</linearGradient>
<linearGradient
id="linearGradient2249">
<stop
style="stop-color:#00a423;stop-opacity:1;"
offset="0"
id="stop2251" />
<stop
style="stop-color:#00b427;stop-opacity:1;"
offset="1"
id="stop2253" />
</linearGradient>
<linearGradient
id="linearGradient2229">
<stop
id="stop2231"
offset="0"
style="stop-color:#00b62b;stop-opacity:1;" />
<stop
id="stop2233"
offset="1"
style="stop-color:#a1d784;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2213">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop2215" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop2217" />
</linearGradient>
<linearGradient
id="linearGradient2360">
<stop
style="stop-color:#d69c00;stop-opacity:1;"
offset="0"
id="stop2362" />
<stop
style="stop-color:#ffe658;stop-opacity:1;"
offset="1"
id="stop2364" />
</linearGradient>
<linearGradient
id="linearGradient2352">
<stop
id="stop2354"
offset="0"
style="stop-color:#ce411e;stop-opacity:1;" />
<stop
id="stop2356"
offset="1"
style="stop-color:#ecad8d;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient2336">
<stop
style="stop-color:#8f2a15;stop-opacity:1;"
offset="0"
id="stop2338" />
<stop
style="stop-color:#c8381b;stop-opacity:1;"
offset="1"
id="stop2340" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2336"
id="linearGradient2342"
x1="219.21262"
y1="189.01556"
x2="286.22665"
y2="189.01556"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2352"
id="linearGradient2350"
x1="219.66267"
y1="192.73286"
x2="277.8761"
y2="192.73286"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2360"
id="radialGradient2366"
cx="224.41418"
cy="212.80016"
fx="224.41418"
fy="212.80016"
r="8.6813803"
gradientTransform="matrix(1,0,0,0.984179,0,3.366635)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2249"
id="linearGradient2227"
x1="192.03938"
y1="262.25757"
x2="263.67093"
y2="262.25757"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2229"
id="linearGradient2247"
x1="191.75092"
y1="258.91571"
x2="255.6561"
y2="258.91571"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2360"
id="radialGradient2317"
cx="257.41144"
cy="274.64203"
fx="257.41144"
fy="274.64203"
r="7.1440549"
gradientTransform="matrix(1,0,0,1.631384,0,-173.4045)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2360"
id="linearGradient2325"
x1="184.07063"
y1="246.35907"
x2="201.40646"
y2="246.35907"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2332"
id="linearGradient2346"
x1="162.76369"
y1="184.99277"
x2="240.84924"
y2="289.50323"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2348"
id="linearGradient2354"
x1="140.15784"
y1="303.78967"
x2="136.14151"
y2="195.87151"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2370"
id="linearGradient2362"
x1="286.15598"
y1="262.28729"
x2="185.81258"
y2="172.32423"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2389"
id="linearGradient2395"
x1="213.96568"
y1="220.07191"
x2="244.79126"
y2="265.40363"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2408"
id="linearGradient2406"
x1="184.30582"
y1="241.52789"
x2="224.67441"
y2="307.52844"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2600"
id="linearGradient2606"
x1="202.41772"
y1="222.05145"
x2="206.06017"
y2="210.3558"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2612"
id="linearGradient2618"
x1="248.62152"
y1="234.52202"
x2="251.64362"
y2="213.12164"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2624"
id="linearGradient2630"
x1="275.71765"
y1="251.56442"
x2="255.68353"
y2="217.94008"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2352"
id="linearGradient2640"
gradientUnits="userSpaceOnUse"
x1="219.66267"
y1="192.73286"
x2="277.8761"
y2="192.73286" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2336"
id="linearGradient2643"
gradientUnits="userSpaceOnUse"
x1="219.21262"
y1="189.01556"
x2="286.22665"
y2="189.01556" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2360"
id="radialGradient2647"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.984179,0,3.366635)"
cx="224.41418"
cy="212.80016"
fx="224.41418"
fy="212.80016"
r="8.6813803" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.03"
inkscape:cx="35.144424"
inkscape:cy="83.160427"
inkscape:document-units="px"
inkscape:current-layer="layer3"
inkscape:window-width="1366"
inkscape:window-height="716"
inkscape:window-x="-8"
inkscape:window-y="-8"
showguides="true"
inkscape:guide-bbox="true"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-maximized="1"
inkscape:showpageshadow="false"
showborder="true"
borderlayer="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>DokuWiki Logo</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Esther Brunner</dc:title>
</cc:Agent>
</dc:creator>
<cc:license
rdf:resource="http://www.gnu.org/licenses/gpl-2.0.html" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="paper"
style="display:inline"
transform="translate(-158.10602,-158.67323)">
<g
id="g1419"
transform="matrix(0.99993322,0,0,0.9959778,0.01483419,0.8957919)">
<g
id="g2376">
<path
transform="matrix(0.989976,-0.141236,0.201069,0.979577,0,0)"
style="fill:url(#linearGradient2354);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.7216621px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 120.21543,196.43769 70.90655,-0.79226 -2.40261,109.05308 -71.71761,0.37344 3.21367,-108.63426 z"
id="rect1422"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2362);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 179.20033,182.08731 79.84173,-19.51687 26.61391,101.72428 -82.50312,21.58684 -23.95252,-103.79425 z"
id="rect1425"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.995676,-0.09289891,0.08102261,0.996712,0,0)"
style="fill:url(#linearGradient2346);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00418305px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 159.01353,181.74387 85.58587,0.53396 0,110.47429 -84.53387,-2.5127 -1.052,-108.49555 z"
id="rect1419"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
id="text2382"
d="m 167.55116,214.00773 0,-20.1846 5.34962,0 0,2.37403 -2.48145,0 0,15.43654 2.48145,0 0,2.37403 -5.34962,0 m 7.34767,0 0,-20.1846 5.34961,0 0,2.37403 -2.48144,0 0,15.43654 2.48144,0 0,2.37403 -5.34961,0 m 7.36915,-20.1846 5.81153,0 c 1.31054,2e-5 2.30956,0.10028 2.99707,0.30078 0.92382,0.27216 1.71516,0.75555 2.37403,1.4502 0.65884,0.69468 1.16014,1.54689 1.50391,2.55664 0.34373,1.00262 0.51561,2.24155 0.51562,3.71681 -10e-6,1.29623 -0.16115,2.41342 -0.4834,3.35156 -0.39389,1.14584 -0.95607,2.07325 -1.68652,2.78223 -0.55145,0.53711 -1.29624,0.95606 -2.23438,1.25684 -0.70183,0.222 -1.63999,0.33301 -2.81446,0.33301 l -5.9834,0 0,-15.74807 m 3.17969,2.66407 0,10.43067 2.37402,0 c 0.88802,1e-5 1.52897,-0.0501 1.92286,-0.15039 0.51561,-0.1289 0.94172,-0.34732 1.27832,-0.65527 0.34374,-0.30794 0.62304,-0.81282 0.83789,-1.51465 0.21483,-0.70898 0.32226,-1.6722 0.32227,-2.88965 -1e-5,-1.21744 -0.10744,-2.15201 -0.32227,-2.80372 -0.21485,-0.65168 -0.51563,-1.16014 -0.90234,-1.52539 -0.38673,-0.36522 -0.87729,-0.61229 -1.47168,-0.74121 -0.44402,-0.10025 -1.31414,-0.15038 -2.61036,-0.15039 l -1.42871,0 m 14.96388,13.084 -3.75977,-15.74807 3.25489,0 2.37403,10.8174 2.87891,-10.8174 3.78125,0 2.76074,11.00002 2.417,-11.00002 3.20118,0 -3.82423,15.74807 -3.37305,0 -3.13672,-11.77345 -3.12598,11.77345 -3.44825,0 m 22.76272,-15.74807 0,20.1846 -5.34961,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34961,0 m 7.34767,0 0,20.1846 -5.34962,0 0,-2.37403 2.48145,0 0,-15.45803 -2.48145,0 0,-2.35254 5.34962,0"
style="font-size:12.0000124px;font-style:normal;font-weight:normal;line-height:125%;fill:#6184a3;fill-opacity:1;stroke:none;display:inline;font-family:Bitstream Vera Sans"
transform="matrix(0.995433,-0.09546066,0.09546066,0.995433,0,0)"
inkscape:connector-curvature="0" />
<g
id="g2632"
style="display:inline">
<path
style="fill:url(#linearGradient2606);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker-end:none"
d="m 174.75585,201.60224 c -6.04576,2.46667 -10.16789,4.4194 -12.88454,6.35064 -2.71665,1.93124 -3.19257,4.60007 -3.24631,6.26587 -0.0269,0.8329 0.0809,1.77774 0.63189,2.44014 0.55103,0.6624 1.80769,1.87421 2.75794,2.38558 1.90049,1.02274 7.5417,2.42901 10.51899,3.07308 11.90917,2.57627 26.80568,1.68117 26.80568,1.68117 1.69307,1.2452 2.83283,2.82434 3.269,4.26902 4.5766,-1.88674 11.81084,-6.58439 13.15657,-8.57706 -5.45142,-4.19955 -10.79692,-6.33346 -16.51317,-8.30847 -1.59867,-0.71918 -2.87956,-1.22649 -0.71773,2.55635 0.98506,2.47275 0.85786,5.05143 0.57176,7.41825 0,0 -16.52749,0.40678 -28.23838,-2.1266 -2.92772,-0.63334 -5.46627,-0.95523 -7.21875,-1.89832 -0.87624,-0.47154 -1.48296,-0.8208 -1.91578,-1.3411 -0.43282,-0.5203 -0.2196,-1.29055 -0.20128,-1.85858 0.0366,-1.13607 0.25336,-1.67063 2.86177,-3.52492 2.60841,-1.85429 5.65407,-3.36195 11.65936,-5.81211 -0.0877,-1.29125 -0.29025,-2.5059 -1.29702,-2.99294 z"
id="path2414"
sodipodi:nodetypes="csssssccccccssssscc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2618);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 269.62539,220.7482 c -1.43576,-0.13963 -2.58044,0.30288 -2.56084,1.50218 0.94391,0.85652 1.34942,2.43518 1.48562,3.14008 0.1362,0.7049 0.0359,1.21914 -0.48562,1.89004 -1.043,1.3418 -3.12498,1.56875 -6.5006,2.72063 -6.75124,2.30377 -16.89306,2.52561 -27.90689,3.84639 -22.02767,2.64157 -39.03164,3.76107 -39.03164,3.76107 1.98346,-4.64758 6.32828,-4.41197 6.34903,-8.20969 0.27376,-0.89755 -3.14597,-1.31638 -5.09943,-0.10731 -4.26694,3.70137 -7.59152,6.75353 -10.69418,10.51311 l 1.88795,3.08438 c 0,0 26.13006,-2.88973 48.19776,-5.5361 11.03385,-1.32318 20.95601,-1.99856 27.80968,-4.33728 3.42683,-1.16936 5.95975,-1.49022 7.6409,-3.51958 0.63172,-0.76256 1.35238,-3.04699 1.06804,-4.73369 -0.21951,-1.30213 -1.14979,-3.09774 -2.15978,-4.01423 z"
id="path2608"
sodipodi:nodetypes="ccsssscccccssssc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2630);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 254.36185,220.33948 c -6.84997,3.24198 -7.15311,8.60912 -5.95953,12.79884 1.19358,4.18972 5.26293,8.75677 9.32121,12.40608 8.11656,7.29861 12.06046,9.33163 12.06046,9.33163 -3.71515,-0.10342 -7.89887,-1.41174 -8.13315,0.49304 -0.9483,2.97582 11.49137,3.47486 17.43787,2.70205 -1.39456,-7.57836 -3.79323,-13.21546 -7.73151,-14.90312 -1.68464,-0.14804 0.31242,4.72441 0.76985,9.39604 0,0 -3.62454,-1.73122 -11.60519,-8.90762 -3.99032,-3.5882 -7.37386,-7.3421 -8.47319,-11.20099 -1.09933,-3.85889 0.0776,-6.1205 4.95082,-9.53176 0.92816,-0.99528 -1.28985,-2.45913 -2.63764,-2.58419 z"
id="path2620"
sodipodi:nodetypes="csscccccsscc"
inkscape:connector-curvature="0" />
</g>
<path
sodipodi:nodetypes="cccccc"
id="rect2386"
d="m 213.96569,234.57806 2.18756,-14.42897 15.21982,6.08793 21.49387,29.94828 -20.40591,9.21832 -18.49534,-30.82556 z"
style="fill:url(#linearGradient2395);fill-opacity:1;stroke:none;display:inline"
inkscape:connector-curvature="0" />
<g
id="g2649"
style="display:inline">
<path
style="fill:url(#radialGradient2647);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 232.55816,219.5295 -15.92827,0.32199 3.08809,-15.15716 12.84018,14.83517 z"
id="path1443"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
style="fill:#812310;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 221.60041,219.29315 -4.41205,0.0782 0.85429,-3.98263 3.55776,3.90445 z"
id="path1452"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2643);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 269.44172,159.27421 0.098,8.91471 8.0581,8.72344 7.75906,0.7992 -52.80669,41.84092 -6.66532,-3.30696 -5.08243,-5.618 -1.08987,-5.91194 49.72911,-45.44137 z"
id="rect1437"
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2640);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 268.94766,168.32844 8.3426,8.82719 -51.1007,38.68262 -4.9197,-5.4436 47.6778,-42.06621 z"
id="rect1446"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="fill:#ffe965;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;display:inline"
d="m 285.33776,177.73216 -8.16219,-0.86619 -7.7518,-8.67862 0.0132,-9.14293 8.36213,0.75209 7.18862,9.57682 0.35007,8.35883 z"
id="path1440"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:#cb391c;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 280.72049,168.46367 0.1644,4.05654 -3.81335,-0.71676 -2.87504,-3.18901 -0.28089,-3.53393 3.85447,-0.16637 2.95041,3.54953 z"
id="path1449"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="g2657"
style="display:inline">
<path
style="fill:url(#linearGradient2406);fill-opacity:1;stroke:none"
d="m 183.88617,256.82796 0.99991,-16.30721 17.2878,8.44012 26.05488,38.00946 -29.28095,-1.13363 -15.06164,-29.00874 z"
id="rect2397"
sodipodi:nodetypes="cccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2325);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline"
d="m 200.90647,238.44836 -8.04601,15.77386 -7.05577,-13.57337 15.10178,-2.20049 z"
id="rect2207"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2227);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1"
d="m 201.05389,238.55401 62.11704,24.91912 -7.88689,3.21429 -4.35152,9.30976 1.1716,9.96396 -59.31453,-31.72759 -0.49402,-7.36382 3.09592,-5.82826 5.6624,-2.48746 z"
id="rect1328"
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#radialGradient2317);fill-opacity:1;stroke:#000000;stroke-linejoin:round;stroke-opacity:1;display:inline"
d="m 255.27801,266.53504 7.9241,-3.04772 0.85337,10.24037 -3.9011,8.28983 -8.04601,3.77919 -1.341,-9.63083 4.51064,-9.63084 z"
id="rect2204"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient2247);fill-opacity:1;stroke:none;display:inline"
d="m 195.7549,241.421 59.13059,24.7962 -4.5917,9.76614 -57.48995,-29.00967 2.95106,-5.55267 z"
id="rect2210"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
style="fill:#00b527;fill-opacity:1;stroke:none"
d="m 255.02263,275.21029 2.08411,-4.1069 2.96459,-1.06995 0.69433,3.37197 -1.76759,3.85723 -3.15516,1.38315 -0.82028,-3.4355 z"
id="rect2308"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:#258209;fill-opacity:1;stroke:none;display:inline"
d="m 186.56849,241.00362 3.54963,-0.47312 -2.02297,3.53926 -1.52666,-3.06614 z"
id="rect2327"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -416,7 +416,7 @@ class HelloWorldApp {
}
</code>
The following language strings are currently recognized: //4cs, 6502acme, 6502kickass, 6502tasm, 68000devpac, abap, actionscript-french, actionscript, actionscript3, ada, algol68, apache, applescript, asm, asp, autoconf, autohotkey, autoit, avisynth, awk, bascomavr, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_loadrunner, c_mac, caddcl, cadlisp, cfdg, cfm, chaiscript, cil, clojure, cmake, cobol, coffeescript, cpp, cpp-qt, csharp, css, cuesheet, d, dcs, delphi, diff, div, dos, dot, e, epc, ecmascript, eiffel, email, erlang, euphoria, f1, falcon, fo, fortran, freebasic, fsharp, gambas, genero, genie, gdb, glsl, gml, gnuplot, go, groovy, gettext, gwbasic, haskell, hicest, hq9plus, html, html5, icon, idl, ini, inno, intercal, io, j, java5, java, javascript, jquery, kixtart, klonec, klonecpp, latex, lb, lisp, llvm, locobasic, logtalk, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, magiksf, make, mapbasic, matlab, mirc, modula2, modula3, mmix, mpasm, mxml, mysql, newlisp, nsis, oberon2, objc, objeck, ocaml-brief, ocaml, oobas, oracle8, oracle11, oxygene, oz, pascal, pcre, perl, perl6, per, pf, php-brief, php, pike, pic16, pixelbender, pli, plsql, postgresql, povray, powerbuilder, powershell, proftpd, progress, prolog, properties, providex, purebasic, pycon, python, q, qbasic, rails, rebol, reg, robots, rpmspec, rsplus, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, systemverilog, tcl, teraterm, text, thinbasic, tsql, typoscript, unicon, uscript, vala, vbnet, vb, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, winbatch, whois, xbasic, xml, xorg_conf, xpp, yaml, z80, zxbasic//
The following language strings are currently recognized: //4cs 6502acme 6502kickass 6502tasm 68000devpac abap actionscript3 actionscript ada aimms algol68 apache applescript apt_sources arm asm asp asymptote autoconf autohotkey autoit avisynth awk bascomavr bash basic4gl batch bf biblatex bibtex blitzbasic bnf boo caddcl cadlisp ceylon cfdg cfm chaiscript chapel cil c_loadrunner clojure c_mac cmake cobol coffeescript c cpp cpp-qt cpp-winapi csharp css cuesheet c_winapi dart dcl dcpu16 dcs delphi diff div dos dot d ecmascript eiffel email epc e erlang euphoria ezt f1 falcon fo fortran freebasic freeswitch fsharp gambas gdb genero genie gettext glsl gml gnuplot go groovy gwbasic haskell haxe hicest hq9plus html html4strict html5 icon idl ini inno intercal io ispfpanel java5 java javascript jcl j jquery julia kixtart klonec klonecpp kotlin latex lb ldif lisp llvm locobasic logtalk lolcode lotusformulas lotusscript lscript lsl2 lua m68k magiksf make mapbasic mathematica matlab mercury metapost mirc mk-61 mmix modula2 modula3 mpasm mxml mysql nagios netrexx newlisp nginx nimrod nsis oberon2 objc objeck ocaml-brief ocaml octave oobas oorexx oracle11 oracle8 oxygene oz parasail parigp pascal pcre perl6 perl per pf phix php-brief php pic16 pike pixelbender pli plsql postgresql postscript povray powerbuilder powershell proftpd progress prolog properties providex purebasic pycon pys60 python qbasic qml q racket rails rbs rebol reg rexx robots rpmspec rsplus ruby rust sas sass scala scheme scilab scl sdlbasic smalltalk smarty spark sparql sql standardml stonescript swift systemverilog tclegg tcl teraterm texgraph text thinbasic tsql twig typoscript unicon upc urbi uscript vala vbnet vb vbscript vedit verilog vhdl vim visualfoxpro visualprolog whitespace whois winbatch xbasic xml xojo xorg_conf xpp yaml z80 zxbasic//
==== Downloadable Code Blocks ====

View File

@ -9,7 +9,7 @@
*/
// update message version - always use a string to avoid localized floats!
$updateVersion = "49.5";
$updateVersion = "50";
// xdebug_start_profiling();
@ -35,7 +35,7 @@ require_once(DOKU_INC.'inc/init.php');
//import variables
$INPUT->set('id', str_replace("\xC2\xAD", '', $INPUT->str('id'))); //soft-hyphen
$QUERY = trim($INPUT->str('id'));
$QUERY = trim($INPUT->str('q'));
$ID = getID();
$REV = $INPUT->int('rev');
@ -62,7 +62,7 @@ if($DATE_AT) {
} else { // check for UNIX Timestamp
$date_parse = @date('Ymd',$DATE_AT);
if(!$date_parse || $date_parse === '19700101') {
msg(sprintf($lang['unable_to_parse_date'], htmlspecialchars($DATE_AT)));
msg(sprintf($lang['unable_to_parse_date'], hsc($DATE_AT)));
$DATE_AT = null;
}
}
@ -90,10 +90,6 @@ if($DATE_AT) {
//make infos about the selected page available
$INFO = pageinfo();
//export minimal info to JS, plugins can add more
$JSINFO['id'] = $ID;
$JSINFO['namespace'] = (string) $INFO['namespace'];
// handle debugging
if($conf['allowdebug'] && $ACT == 'debug') {
html_debug();

View File

@ -51,7 +51,7 @@ if($cache->useCache($depends)) {
}
// create new feed
$rss = new DokuWikiFeedCreator();
$rss = new UniversalFeedCreator();
$rss->title = $conf['title'].(($opt['namespace']) ? ' '.$opt['namespace'] : '');
$rss->link = DOKU_URL;
$rss->syndicationURL = DOKU_URL.'feed.php';
@ -85,7 +85,7 @@ if(isset($modes[$opt['feed_mode']])) {
}
rss_buildItems($rss, $data, $opt);
$feed = $rss->createFeed($opt['feed_type'], 'utf-8');
$feed = $rss->createFeed($opt['feed_type']);
// save cachefile
$cache->storeCache($feed);
@ -402,34 +402,30 @@ function rss_buildItems(&$rss, &$data, $opt) {
// add user
# FIXME should the user be pulled from metadata as well?
$user = @$ditem['user']; // the @ spares time repeating lookup
$item->author = '';
if($user && $conf['useacl'] && $auth) {
$userInfo = $auth->getUserData($user);
if($userInfo) {
switch($conf['showuseras']) {
case 'username':
case 'username_link':
$item->author = $userInfo['name'];
break;
default:
$item->author = $user;
break;
}
} else {
$item->author = $user;
}
if($userInfo && !$opt['guardmail']) {
$item->authorEmail = $userInfo['mail'];
} else {
//cannot obfuscate because some RSS readers may check validity
$item->authorEmail = $user.'@'.$ditem['ip'];
}
} elseif($user) {
// this happens when no ACL but some Apache auth is used
$item->author = $user;
$item->authorEmail = $user.'@'.$ditem['ip'];
if(blank($user)) {
$item->author = 'Anonymous';
$item->authorEmail = 'anonymous@undisclosed.example.com';
} else {
$item->authorEmail = 'anonymous@'.$ditem['ip'];
$item->author = $user;
$item->authorEmail = $user . '@undisclosed.example.com';
// get real user name if configured
if($conf['useacl'] && $auth) {
$userInfo = $auth->getUserData($user);
if($userInfo) {
switch($conf['showuseras']) {
case 'username':
case 'username_link':
$item->author = $userInfo['name'];
break;
default:
$item->author = $user;
break;
}
} else {
$item->author = $user;
}
}
}
// add category

View File

@ -0,0 +1,25 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAclRequiredException;
/**
* Class AbstractAclAction
*
* An action that requires the ACL subsystem to be enabled (eg. useacl=1)
*
* @package dokuwiki\Action
*/
abstract class AbstractAclAction extends AbstractAction {
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
global $conf;
global $auth;
if(!$conf['useacl']) throw new ActionAclRequiredException();
if(!$auth) throw new ActionAclRequiredException();
}
}

View File

@ -0,0 +1,88 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionDisabledException;
use dokuwiki\Action\Exception\ActionException;
use dokuwiki\Action\Exception\FatalException;
/**
* Class AbstractAction
*
* Base class for all actions
*
* @package dokuwiki\Action
*/
abstract class AbstractAction {
/** @var string holds the name of the action (lowercase class name, no namespace) */
protected $actionname;
/**
* AbstractAction constructor.
*
* @param string $actionname the name of this action (see getActionName() for caveats)
*/
public function __construct($actionname = '') {
if($actionname !== '') {
$this->actionname = $actionname;
} else {
// http://stackoverflow.com/a/27457689/172068
$this->actionname = strtolower(substr(strrchr(get_class($this), '\\'), 1));
}
}
/**
* Return the minimum permission needed
*
* This needs to return one of the AUTH_* constants. It will be checked against
* the current user and page after checkPermissions() ran through. If it fails,
* the user will be shown the Denied action.
*
* @return int
*/
abstract public function minimumPermission();
/**
* Check conditions are met to run this action
*
* @throws ActionException
* @return void
*/
public function checkPreconditions() {
}
/**
* Process data
*
* This runs before any output is sent to the browser.
*
* Throw an Exception if a different action should be run after this step.
*
* @throws ActionException
* @return void
*/
public function preProcess() {
}
/**
* Output whatever content is wanted within tpl_content();
*
* @fixme we may want to return a Ui class here
*/
public function tplContent() {
throw new FatalException('No content for Action ' . $this->actionname);
}
/**
* Returns the name of this action
*
* This is usually the lowercased class name, but may differ for some actions.
* eg. the export_ modes or for the Plugin action.
*
* @return string
*/
public function getActionName() {
return $this->actionname;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\FatalException;
/**
* Class AbstractAliasAction
*
* An action that is an alias for another action. Skips the minimumPermission check
*
* Be sure to implement preProcess() and throw an ActionAbort exception
* with the proper action.
*
* @package dokuwiki\Action
*/
abstract class AbstractAliasAction extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
public function preProcess() {
throw new FatalException('Alias Actions need to implement preProcess to load the aliased action');
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionUserRequiredException;
/**
* Class AbstractUserAction
*
* An action that requires a logged in user
*
* @package dokuwiki\Action
*/
abstract class AbstractUserAction extends AbstractAclAction {
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
global $INPUT;
if(!$INPUT->server->str('REMOTE_USER')) {
throw new ActionUserRequiredException();
}
}
}

56
inc/Action/Admin.php Normal file
View File

@ -0,0 +1,56 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionException;
/**
* Class Admin
*
* Action to show the admin interface or admin plugins
*
* @package dokuwiki\Action
*/
class Admin extends AbstractUserAction {
/** @inheritdoc */
public function minimumPermission() {
global $INFO;
if($INFO['ismanager']) {
return AUTH_READ; // let in check later
} else {
return AUTH_ADMIN;
}
}
public function checkPreconditions() {
parent::checkPreconditions();
global $INFO;
if(!$INFO['ismanager']) {
throw new ActionException('denied');
}
}
public function preProcess() {
global $INPUT;
global $INFO;
// retrieve admin plugin name from $_REQUEST['page']
if(($page = $INPUT->str('page', '', true)) != '') {
/** @var $plugin \DokuWiki_Admin_Plugin */
if($plugin = plugin_getRequestAdminPlugin()) { // FIXME this method does also permission checking
if($plugin->forAdminOnly() && !$INFO['isadmin']) {
throw new ActionException('denied');
}
$plugin->handle();
}
}
}
public function tplContent() {
tpl_admin();
}
}

24
inc/Action/Backlink.php Normal file
View File

@ -0,0 +1,24 @@
<?php
namespace dokuwiki\Action;
/**
* Class Backlink
*
* Shows which pages link to the current page
*
* @package dokuwiki\Action
*/
class Backlink extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function tplContent() {
html_backlinks();
}
}

21
inc/Action/Cancel.php Normal file
View File

@ -0,0 +1,21 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Cancel
*
* Alias for show. Aborts editing
*
* @package dokuwiki\Action
*/
class Cancel extends AbstractAliasAction {
public function preProcess() {
// continue with draftdel -> redirect -> show
throw new ActionAbort('draftdel');
}
}

26
inc/Action/Check.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Check
*
* Adds some debugging info before aborting to show
*
* @package dokuwiki\Action
*/
class Check extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_READ;
}
public function preProcess() {
check();
throw new ActionAbort();
}
}

34
inc/Action/Conflict.php Normal file
View File

@ -0,0 +1,34 @@
<?php
namespace dokuwiki\Action;
/**
* Class Conflict
*
* Show the conflict resolution screen
*
* @package dokuwiki\Action
*/
class Conflict extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
global $INFO;
if($INFO['exists']) {
return AUTH_EDIT;
} else {
return AUTH_CREATE;
}
}
public function tplContent() {
global $PRE;
global $TEXT;
global $SUF;
global $SUM;
html_conflict(con($PRE, $TEXT, $SUF), $SUM);
html_diff(con($PRE, $TEXT, $SUF), false);
}
}

23
inc/Action/Denied.php Normal file
View File

@ -0,0 +1,23 @@
<?php
namespace dokuwiki\Action;
/**
* Class Denied
*
* Show the access denied screen
*
* @package dokuwiki\Action
*/
class Denied extends AbstractAclAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
public function tplContent() {
html_denied();
}
}

35
inc/Action/Diff.php Normal file
View File

@ -0,0 +1,35 @@
<?php
namespace dokuwiki\Action;
/**
* Class Diff
*
* Show the differences between two revisions
*
* @package dokuwiki\Action
*/
class Diff extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_READ;
}
/** @inheritdoc */
public function preProcess() {
global $INPUT;
// store the selected diff type in cookie
$difftype = $INPUT->str('difftype');
if(!empty($difftype)) {
set_doku_pref('difftype', $difftype);
}
}
/** @inheritdoc */
public function tplContent() {
html_diff();
}
}

39
inc/Action/Draft.php Normal file
View File

@ -0,0 +1,39 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionException;
/**
* Class Draft
*
* Screen to see and recover a draft
*
* @package dokuwiki\Action
* @fixme combine with Recover?
*/
class Draft extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
global $INFO;
if($INFO['exists']) {
return AUTH_EDIT;
} else {
return AUTH_CREATE;
}
}
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
global $INFO;
if(!file_exists($INFO['draft'])) throw new ActionException('edit');
}
/** @inheritdoc */
public function tplContent() {
html_draft();
}
}

36
inc/Action/Draftdel.php Normal file
View File

@ -0,0 +1,36 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Draftdel
*
* Delete a draft
*
* @package dokuwiki\Action
*/
class Draftdel extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_EDIT;
}
/**
* Delete an existing draft if any
*
* Reads draft information from $INFO. Redirects to show, afterwards.
*
* @throws ActionAbort
*/
public function preProcess() {
global $INFO;
@unlink($INFO['draft']);
$INFO['draft'] = null;
throw new ActionAbort('redirect');
}
}

91
inc/Action/Edit.php Normal file
View File

@ -0,0 +1,91 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Edit
*
* Handle editing
*
* @package dokuwiki\Action
*/
class Edit extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
global $INFO;
if($INFO['exists']) {
return AUTH_READ; // we check again below
} else {
return AUTH_CREATE;
}
}
/**
* @inheritdoc falls back to 'source' if page not writable
*/
public function checkPreconditions() {
parent::checkPreconditions();
global $INFO;
// no edit permission? view source
if($INFO['exists'] && !$INFO['writable']) {
throw new ActionAbort('source');
}
}
/** @inheritdoc */
public function preProcess() {
global $ID;
global $INFO;
global $TEXT;
global $RANGE;
global $PRE;
global $SUF;
global $REV;
global $SUM;
global $lang;
global $DATE;
if(!isset($TEXT)) {
if($INFO['exists']) {
if($RANGE) {
list($PRE, $TEXT, $SUF) = rawWikiSlices($RANGE, $ID, $REV);
} else {
$TEXT = rawWiki($ID, $REV);
}
} else {
$TEXT = pageTemplate($ID);
}
}
//set summary default
if(!$SUM) {
if($REV) {
$SUM = sprintf($lang['restored'], dformat($REV));
} elseif(!$INFO['exists']) {
$SUM = $lang['created'];
}
}
// Use the date of the newest revision, not of the revision we edit
// This is used for conflict detection
if(!$DATE) $DATE = @filemtime(wikiFN($ID));
//check if locked by anyone - if not lock for my self
$lockedby = checklock($ID);
if($lockedby) {
throw new ActionAbort('locked');
};
lock($ID);
}
/** @inheritdoc */
public function tplContent() {
html_edit();
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class ActionAbort
*
* Strictly speaking not an Exception but an expected execution path. Used to
* signal when one action is done and another should take over.
*
* If you want to signal the same but under some error condition use ActionException
* or one of it's decendants.
*
* The message will NOT be shown to the enduser
*
* @package dokuwiki\Action\Exception
*/
class ActionAbort extends ActionException {
}

View File

@ -0,0 +1,17 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class ActionAclRequiredException
*
* Thrown by AbstractACLAction when an action requires that the ACL subsystem is
* enabled but it isn't. You should not use it
*
* The message will NOT be shown to the enduser
*
* @package dokuwiki\Action\Exception
*/
class ActionAclRequiredException extends ActionException {
}

View File

@ -0,0 +1,17 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class ActionDisabledException
*
* Thrown when the requested action has been disabled. Eg. through the 'disableactions'
* config setting. You should probably not use it.
*
* The message will NOT be shown to the enduser, but a generic information will be shown.
*
* @package dokuwiki\Action\Exception
*/
class ActionDisabledException extends ActionException {
}

View File

@ -0,0 +1,66 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class ActionException
*
* This exception and its subclasses signal that the current action should be
* aborted and a different action should be used instead. The new action can
* be given as parameter in the constructor. Defaults to 'show'
*
* The message will NOT be shown to the enduser
*
* @package dokuwiki\Action\Exception
*/
class ActionException extends \Exception {
/** @var string the new action */
protected $newaction;
/** @var bool should the exception's message be shown to the user? */
protected $displayToUser = false;
/**
* ActionException constructor.
*
* When no new action is given 'show' is assumed. For requests that originated in a POST,
* a 'redirect' is used which will cause a redirect to the 'show' action.
*
* @param string|null $newaction the action that should be used next
* @param string $message optional message, will not be shown except for some dub classes
*/
public function __construct($newaction = null, $message = '') {
global $INPUT;
parent::__construct($message);
if(is_null($newaction)) {
if(strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post') {
$newaction = 'redirect';
} else {
$newaction = 'show';
}
}
$this->newaction = $newaction;
}
/**
* Returns the action to use next
*
* @return string
*/
public function getNewAction() {
return $this->newaction;
}
/**
* Should this Exception's message be shown to the user?
*
* @param null|bool $set when null is given, the current setting is not changed
* @return bool
*/
public function displayToUser($set = null) {
if(!is_null($set)) $this->displayToUser = $set;
return $set;
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class ActionUserRequiredException
*
* Thrown by AbstractUserAction when an action requires that a user is logged
* in but it isn't. You should not use it.
*
* The message will NOT be shown to the enduser
*
* @package dokuwiki\Action\Exception
*/
class ActionUserRequiredException extends ActionException {
}

View File

@ -0,0 +1,29 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class FatalException
*
* A fatal exception during handling the action
*
* Will abort all handling and display some info to the user. The HTTP status code
* can be defined.
*
* @package dokuwiki\Action\Exception
*/
class FatalException extends \Exception {
protected $status;
/**
* FatalException constructor.
*
* @param string $message the message to send
* @param int $status the HTTP status to send
* @param null|\Exception $previous previous exception
*/
public function __construct($message = 'A fatal error occured', $status = 500, $previous = null) {
parent::__construct($message, $status, $previous);
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace dokuwiki\Action\Exception;
/**
* Class NoActionException
*
* Thrown in the ActionRouter when a wanted action can not be found. Triggers
* the unknown action event
*
* @package dokuwiki\Action\Exception
*/
class NoActionException extends \Exception {
}

112
inc/Action/Export.php Normal file
View File

@ -0,0 +1,112 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Export
*
* Handle exporting by calling the appropriate renderer
*
* @package dokuwiki\Action
*/
class Export extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_READ;
}
/**
* Export a wiki page for various formats
*
* Triggers ACTION_EXPORT_POSTPROCESS
*
* Event data:
* data['id'] -- page id
* data['mode'] -- requested export mode
* data['headers'] -- export headers
* data['output'] -- export output
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michael Klier <chi@chimeric.de>
* @inheritdoc
*/
public function preProcess() {
global $ID;
global $REV;
global $conf;
global $lang;
$pre = '';
$post = '';
$headers = array();
// search engines: never cache exported docs! (Google only currently)
$headers['X-Robots-Tag'] = 'noindex';
$mode = substr($this->actionname, 7);
switch($mode) {
case 'raw':
$headers['Content-Type'] = 'text/plain; charset=utf-8';
$headers['Content-Disposition'] = 'attachment; filename=' . noNS($ID) . '.txt';
$output = rawWiki($ID, $REV);
break;
case 'xhtml':
$pre .= '<!DOCTYPE html>' . DOKU_LF;
$pre .= '<html lang="' . $conf['lang'] . '" dir="' . $lang['direction'] . '">' . DOKU_LF;
$pre .= '<head>' . DOKU_LF;
$pre .= ' <meta charset="utf-8" />' . DOKU_LF; // FIXME improve wrapper
$pre .= ' <title>' . $ID . '</title>' . DOKU_LF;
// get metaheaders
ob_start();
tpl_metaheaders();
$pre .= ob_get_clean();
$pre .= '</head>' . DOKU_LF;
$pre .= '<body>' . DOKU_LF;
$pre .= '<div class="dokuwiki export">' . DOKU_LF;
// get toc
$pre .= tpl_toc(true);
$headers['Content-Type'] = 'text/html; charset=utf-8';
$output = p_wiki_xhtml($ID, $REV, false);
$post .= '</div>' . DOKU_LF;
$post .= '</body>' . DOKU_LF;
$post .= '</html>' . DOKU_LF;
break;
case 'xhtmlbody':
$headers['Content-Type'] = 'text/html; charset=utf-8';
$output = p_wiki_xhtml($ID, $REV, false);
break;
default:
$output = p_cached_output(wikiFN($ID, $REV), $mode, $ID);
$headers = p_get_metadata($ID, "format $mode");
break;
}
// prepare event data
$data = array();
$data['id'] = $ID;
$data['mode'] = $mode;
$data['headers'] = $headers;
$data['output'] =& $output;
trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
if(!empty($data['output'])) {
if(is_array($data['headers'])) foreach($data['headers'] as $key => $val) {
header("$key: $val");
}
print $pre . $data['output'] . $post;
exit;
}
throw new ActionAbort();
}
}

25
inc/Action/Index.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace dokuwiki\Action;
/**
* Class Index
*
* Show the human readable sitemap. Do not confuse with Sitemap
*
* @package dokuwiki\Action
*/
class Index extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function tplContent() {
global $IDX;
html_index($IDX);
}
}

24
inc/Action/Locked.php Normal file
View File

@ -0,0 +1,24 @@
<?php
namespace dokuwiki\Action;
/**
* Class Locked
*
* Show a locked screen when a page is locked
*
* @package dokuwiki\Action
*/
class Locked extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_READ;
}
/** @inheritdoc */
public function tplContent() {
html_locked();
}
}

36
inc/Action/Login.php Normal file
View File

@ -0,0 +1,36 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionException;
/**
* Class Login
*
* The login form. Actual logins are handled in inc/auth.php
*
* @package dokuwiki\Action
*/
class Login extends AbstractAclAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function checkPreconditions() {
global $INPUT;
parent::checkPreconditions();
if($INPUT->server->has('REMOTE_USER')) {
// nothing to do
throw new ActionException();
}
}
/** @inheritdoc */
public function tplContent() {
html_login();
}
}

50
inc/Action/Logout.php Normal file
View File

@ -0,0 +1,50 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionDisabledException;
use dokuwiki\Action\Exception\ActionException;
/**
* Class Logout
*
* Log out a user
*
* @package dokuwiki\Action
*/
class Logout extends AbstractUserAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
/** @var \DokuWiki_Auth_Plugin $auth */
global $auth;
if(!$auth->canDo('logout')) throw new ActionDisabledException();
}
/** @inheritdoc */
public function preProcess() {
global $ID;
global $INPUT;
// when logging out during an edit session, unlock the page
$lockedby = checklock($ID);
if($lockedby == $INPUT->server->str('REMOTE_USER')) {
unlock($ID);
}
// do the logout stuff and redirect to login
auth_logoff();
send_redirect(wl($ID, array('do' => 'login')));
// should never be reached
throw new ActionException('login');
}
}

24
inc/Action/Media.php Normal file
View File

@ -0,0 +1,24 @@
<?php
namespace dokuwiki\Action;
/**
* Class Media
*
* The full screen media manager
*
* @package dokuwiki\Action
*/
class Media extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_READ;
}
/** @inheritdoc */
public function tplContent() {
tpl_media();
}
}

32
inc/Action/Plugin.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace dokuwiki\Action;
/**
* Class Plugin
*
* Used to run action plugins
*
* @package dokuwiki\Action
*/
class Plugin extends AbstractAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/**
* Outputs nothing but a warning unless an action plugin overwrites it
*
* @inheritdoc
* @triggers TPL_ACT_UNKNOWN
*/
public function tplContent() {
$evt = new \Doku_Event('TPL_ACT_UNKNOWN', $this->actionname);
if($evt->advise_before()) {
msg('Failed to handle action: ' . hsc($this->actionname), -1);
}
$evt->advise_after();
}
}

58
inc/Action/Preview.php Normal file
View File

@ -0,0 +1,58 @@
<?php
namespace dokuwiki\Action;
/**
* Class Preview
*
* preview during editing
*
* @package dokuwiki\Action
*/
class Preview extends Edit {
/** @inheritdoc */
public function preProcess() {
header('X-XSS-Protection: 0');
$this->savedraft();
parent::preProcess();
}
/** @inheritdoc */
public function tplContent() {
global $TEXT;
html_edit();
html_show($TEXT);
}
/**
* Saves a draft on preview
*/
protected function savedraft() {
global $INFO;
global $ID;
global $INPUT;
global $conf;
if(!$conf['usedraft']) return;
if(!$INPUT->post->has('wikitext')) return;
// ensure environment (safeguard when used via AJAX)
assert(isset($INFO['client']), 'INFO.client should have been set');
assert(isset($ID), 'ID should have been set');
$draft = array(
'id' => $ID,
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
'text' => $INPUT->post->str('wikitext'),
'suffix' => $INPUT->post->str('suffix'),
'date' => $INPUT->post->int('date'),
'client' => $INFO['client'],
);
$cname = getCacheName($draft['client'] . $ID, '.draft');
if(io_saveFile($cname, serialize($draft))) {
$INFO['draft'] = $cname;
}
}
}

45
inc/Action/Profile.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
use dokuwiki\Action\Exception\ActionDisabledException;
/**
* Class Profile
*
* Handle the profile form
*
* @package dokuwiki\Action
*/
class Profile extends AbstractUserAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
/** @var \DokuWiki_Auth_Plugin $auth */
global $auth;
if(!$auth->canDo('Profile')) throw new ActionDisabledException();
}
/** @inheritdoc */
public function preProcess() {
global $lang;
if(updateprofile()) {
msg($lang['profchanged'], 1);
throw new ActionAbort('show');
}
}
/** @inheritdoc */
public function tplContent() {
html_updateprofile();
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
use dokuwiki\Action\Exception\ActionDisabledException;
/**
* Class ProfileDelete
*
* Delete a user account
*
* @package dokuwiki\Action
*/
class ProfileDelete extends AbstractUserAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
/** @var \DokuWiki_Auth_Plugin $auth */
global $auth;
if(!$auth->canDo('delUser')) throw new ActionDisabledException();
}
/** @inheritdoc */
public function preProcess() {
global $lang;
if(auth_deleteprofile()) {
msg($lang['profdeleted'], 1);
throw new ActionAbort('show');
} else {
throw new ActionAbort('profile');
}
}
}

40
inc/Action/Recent.php Normal file
View File

@ -0,0 +1,40 @@
<?php
namespace dokuwiki\Action;
/**
* Class Recent
*
* The recent changes view
*
* @package dokuwiki\Action
*/
class Recent extends AbstractAction {
/** @var string what type of changes to show */
protected $showType = 'both';
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function preProcess() {
global $INPUT;
$show_changes = $INPUT->str('show_changes');
if(!empty($show_changes)) {
set_doku_pref('show_changes', $show_changes);
$this->showType = $show_changes;
} else {
$this->showType = get_doku_pref('show_changes', 'both');
}
}
/** @inheritdoc */
public function tplContent() {
global $INPUT;
html_recent((int) $INPUT->extract('first')->int('first'), $this->showType);
}
}

21
inc/Action/Recover.php Normal file
View File

@ -0,0 +1,21 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Recover
*
* Recover a draft
*
* @package dokuwiki\Action
*/
class Recover extends AbstractAliasAction {
/** @inheritdoc */
public function preProcess() {
throw new ActionAbort('edit');
}
}

64
inc/Action/Redirect.php Normal file
View File

@ -0,0 +1,64 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Redirect
*
* Used to redirect to the current page with the last edited section as a target if found
*
* @package dokuwiki\Action
*/
class Redirect extends AbstractAliasAction {
/**
* Redirect to the show action, trying to jump to the previously edited section
*
* @triggers ACTION_SHOW_REDIRECT
* @throws ActionAbort
*/
public function preProcess() {
global $PRE;
global $TEXT;
global $INPUT;
global $ID;
global $ACT;
$opts = array(
'id' => $ID,
'preact' => $ACT
);
//get section name when coming from section edit
if($INPUT->has('hid')) {
// Use explicitly transmitted header id
$opts['fragment'] = $INPUT->str('hid');
} else if($PRE && preg_match('/^\s*==+([^=\n]+)/', $TEXT, $match)) {
// Fallback to old mechanism
$check = false; //Byref
$opts['fragment'] = sectionID($match[0], $check);
}
// execute the redirect
trigger_event('ACTION_SHOW_REDIRECT', $opts, array($this, 'redirect'));
// should never be reached
throw new ActionAbort('show');
}
/**
* Execute the redirect
*
* Default action for ACTION_SHOW_REDIRECT
*
* @param array $opts id and fragment for the redirect and the preact
*/
public function redirect($opts) {
$go = wl($opts['id'], '', true);
if(isset($opts['fragment'])) $go .= '#' . $opts['fragment'];
//show it
send_redirect($go);
}
}

45
inc/Action/Register.php Normal file
View File

@ -0,0 +1,45 @@
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
use dokuwiki\Action\Exception\ActionDisabledException;
/**
* Class Register
*
* Self registering a new user
*
* @package dokuwiki\Action
*/
class Register extends AbstractAclAction {
/** @inheritdoc */
public function minimumPermission() {
return AUTH_NONE;
}
/** @inheritdoc */
public function checkPreconditions() {
parent::checkPreconditions();
/** @var \DokuWiki_Auth_Plugin $auth */
global $auth;
global $conf;
if(isset($conf['openregister']) && !$conf['openregister']) throw new ActionDisabledException();
if(!$auth->canDo('addUser')) throw new ActionDisabledException();
}
/** @inheritdoc */
public function preProcess() {
if(register()) { // FIXME could be moved from auth to here
throw new ActionAbort('login');
}
}
/** @inheritdoc */
public function tplContent() {
html_register();
}
}

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