1<?php 2 3namespace dokuwiki\test\Remote; 4 5use dokuwiki\Extension\Event; 6use dokuwiki\Remote\Api; 7use dokuwiki\Remote\ApiCore; 8use dokuwiki\test\mock\AuthDeletePlugin; 9use dokuwiki\test\mock\AuthPlugin; 10 11/** 12 * Class remoteapicore_test 13 */ 14class ApiCoreTest extends \DokuWikiTest 15{ 16 17 protected $userinfo; 18 protected $oldAuthAcl; 19 /** @var Api */ 20 protected $remote; 21 22 public function setUp(): void 23 { 24 // we need a clean setup before each single test: 25 \DokuWikiTest::setUpBeforeClass(); 26 27 parent::setUp(); 28 global $conf; 29 global $USERINFO; 30 global $AUTH_ACL; 31 global $auth; 32 $this->oldAuthAcl = $AUTH_ACL; 33 $this->userinfo = $USERINFO; 34 $auth = new AuthPlugin(); 35 36 $conf['remote'] = 1; 37 $conf['remoteuser'] = '@user'; 38 $conf['useacl'] = 0; 39 40 $this->remote = new Api(); 41 } 42 43 public function tearDown(): void 44 { 45 parent::tearDown(); 46 47 global $USERINFO; 48 global $AUTH_ACL; 49 50 $USERINFO = $this->userinfo; 51 $AUTH_ACL = $this->oldAuthAcl; 52 } 53 54 /** Delay writes of old revisions by a second. */ 55 public function handle_write(Event $event, $param) 56 { 57 if ($event->data[3] !== false) { 58 $this->waitForTick(); 59 } 60 } 61 62 public function testGetVersion() 63 { 64 $this->assertEquals(getVersion(), $this->remote->call('dokuwiki.getVersion')); 65 } 66 67 public function testGetPageList() 68 { 69 $file1 = wikiFN('wiki:dokuwiki'); 70 $file2 = wikiFN('wiki:syntax'); 71 $expected = [ 72 [ 73 'id' => 'wiki:dokuwiki', 74 'rev' => filemtime($file1), 75 'mtime' => filemtime($file1), 76 'size' => filesize($file1), 77 'hash' => md5(trim(rawWiki('wiki:dokuwiki'))) 78 ], 79 [ 80 'id' => 'wiki:syntax', 81 'rev' => filemtime($file2), 82 'mtime' => filemtime($file2), 83 'size' => filesize($file2), 84 'hash' => md5(trim(rawWiki('wiki:syntax'))) 85 ] 86 ]; 87 $params = [ 88 'wiki:', 89 [ 90 'depth' => 0, // 0 for all 91 'hash' => 1, 92 'skipacl' => 1 // is ignored 93 ] 94 ]; 95 $this->assertEquals($expected, $this->remote->call('dokuwiki.getPagelist', $params)); 96 } 97 98 public function testSearch() 99 { 100 $id = 'wiki:syntax'; 101 $file = wikiFN($id); 102 103 idx_addPage($id); //full text search depends on index 104 $expected = [ 105 [ 106 'id' => $id, 107 'score' => 1, 108 'rev' => filemtime($file), 109 'mtime' => filemtime($file), 110 'size' => filesize($file), 111 'snippet' => ' a footnote)) by using double parentheses. 112 113===== <strong class="search_hit">Sectioning</strong> ===== 114 115You can use up to five different levels of', 116 'title' => 'wiki:syntax' 117 ] 118 ]; 119 $params = ['Sectioning']; 120 $this->assertEquals($expected, $this->remote->call('dokuwiki.search', $params)); 121 } 122 123 public function testGetTime() 124 { 125 $timeexpect = time(); 126 $timeactual = $this->remote->call('dokuwiki.getTime'); 127 $this->assertTrue(($timeexpect <= $timeactual) && ($timeactual <= $timeexpect + 1)); 128 } 129 130 public function testSetLocks() 131 { 132 $expected = [ 133 'locked' => ['wiki:dokuwiki', 'wiki:syntax', 'nonexisting'], 134 'lockfail' => [], 135 'unlocked' => [], 136 'unlockfail' => [], 137 ]; 138 $params = [ 139 [ 140 'lock' => ['wiki:dokuwiki', 'wiki:syntax', 'nonexisting'], 141 'unlock' => [] 142 ] 143 ]; 144 $this->assertEquals($expected, $this->remote->call('dokuwiki.setLocks', $params)); 145 146 $expected = [ 147 'locked' => [], 148 'lockfail' => [], 149 'unlocked' => ['wiki:dokuwiki', 'wiki:syntax', 'nonexisting'], 150 'unlockfail' => ['nonexisting2'], 151 ]; 152 $params = [ 153 [ 154 'lock' => [], 155 'unlock' => ['wiki:dokuwiki', 'wiki:syntax', 'nonexisting', 'nonexisting2'] 156 ] 157 ]; 158 $this->assertEquals($expected, $this->remote->call('dokuwiki.setLocks', $params)); 159 } 160 161 public function testGetTitle() 162 { 163 global $conf; 164 $this->assertEquals($conf['title'], $this->remote->call('dokuwiki.getTitle')); 165 } 166 167 public function testPutPage() 168 { 169 $id = 'putpage'; 170 171 $content = "====Title====\nText"; 172 $params = [ 173 $id, 174 $content, 175 [ 176 'minor' => false, 177 'sum' => 'Summary of nice text' 178 ] 179 ]; 180 $this->assertTrue($this->remote->call('wiki.putPage', $params)); 181 $this->assertEquals($content, rawWiki($id)); 182 183 //remove page 184 $params = [ 185 $id, 186 '', 187 [ 188 'minor' => false, 189 ] 190 ]; 191 $this->assertTrue($this->remote->call('wiki.putPage', $params)); 192 $this->assertFileNotExists(wikiFN($id)); 193 } 194 195 public function testGetPage() 196 { 197 $id = 'getpage'; 198 $content = 'a test'; 199 saveWikiText($id, $content, 'test for getpage'); 200 201 $params = [$id]; 202 $this->assertEquals($content, $this->remote->call('wiki.getPage', $params)); 203 } 204 205 public function testAppendPage() 206 { 207 $id = 'appendpage'; 208 $content = 'a test'; 209 $morecontent = "\nOther text"; 210 saveWikiText($id, $content, 'local'); 211 212 $params = [ 213 $id, 214 $morecontent, 215 [] 216 ]; 217 $this->assertEquals(true, $this->remote->call('dokuwiki.appendPage', $params)); 218 $this->assertEquals($content . $morecontent, rawWiki($id)); 219 } 220 221 public function testGetPageVersion() 222 { 223 $id = 'pageversion'; 224 $file = wikiFN($id); 225 226 saveWikiText($id, 'first version', 'first'); 227 $rev1 = filemtime($file); 228 clearstatcache(false, $file); 229 $this->waitForTick(true); 230 saveWikiText($id, 'second version', 'second'); 231 $rev2 = filemtime($file); 232 233 $params = [$id, '']; 234 $this->assertEquals('second version', $this->remote->call('wiki.getPageVersion', $params), 'no revision given'); 235 236 $params = [$id, $rev1]; 237 $this->assertEquals('first version', $this->remote->call('wiki.getPageVersion', $params), '1st revision given'); 238 239 $params = [$id, $rev2]; 240 $this->assertEquals('second version', $this->remote->call('wiki.getPageVersion', $params), '2nd revision given'); 241 242 $params = [$id, 1234]; 243 $this->assertEquals('', $this->remote->call('wiki.getPageVersion', $params), 'Non existing revision given'); 244 245 $params = ['foobar', 1234]; 246 $this->assertEquals('', $this->remote->call('wiki.getPageVersion', $params), 'Non existing page given'); 247 } 248 249 public function testGetPageHTML() 250 { 251 $id = 'htmltest'; 252 $content = "====Title====\nText"; 253 $html = "\n<h3 class=\"sectionedit1\" id=\"title\">Title</h3>\n<div class=\"level3\">\n\n<p>\nText\n</p>\n\n</div>\n"; 254 255 saveWikiText($id, $content, 'htmltest'); 256 257 $params = [$id]; 258 $this->assertEquals($html, $this->remote->call('wiki.getPageHTML', $params)); 259 } 260 261 public function testGetPageHTMLVersion() 262 { 263 $id = 'htmltest'; 264 $file = wikiFN($id); 265 266 $content1 = "====Title====\nText"; 267 $html1 = "\n<h3 class=\"sectionedit1\" id=\"title\">Title</h3>\n<div class=\"level3\">\n\n<p>\nText\n</p>\n\n</div>\n"; 268 $content2 = "====Foobar====\nText Bamm"; 269 $html2 = "\n<h3 class=\"sectionedit1\" id=\"foobar\">Foobar</h3>\n<div class=\"level3\">\n\n<p>\nText Bamm\n</p>\n\n</div>\n"; 270 271 saveWikiText($id, $content1, 'first'); 272 $rev1 = filemtime($file); 273 clearstatcache(false, $file); 274 $this->waitForTick(true); 275 saveWikiText($id, $content2, 'second'); 276 $rev2 = filemtime($file); 277 278 $params = [$id, '']; 279 $this->assertEquals($html2, $this->remote->call('wiki.getPageHTMLVersion', $params), 'no revision given'); 280 281 $params = [$id, $rev1]; 282 $this->assertEquals($html1, $this->remote->call('wiki.getPageHTMLVersion', $params), '1st revision given'); 283 284 $params = [$id, $rev2]; 285 $this->assertEquals($html2, $this->remote->call('wiki.getPageHTMLVersion', $params), '2nd revision given'); 286 287 $params = [$id, 1234]; 288 $this->assertEquals('', $this->remote->call('wiki.getPageHTMLVersion', $params), 'Non existing revision given'); 289 290 $params = ['foobar', 1234]; 291 $this->assertEquals('', $this->remote->call('wiki.getPageHTMLVersion', $params), 'Non existing page given'); 292 } 293 294 public function testGetAllPages() 295 { 296 // all pages depends on index 297 idx_addPage('wiki:syntax'); 298 idx_addPage('wiki:dokuwiki'); 299 300 $file1 = wikiFN('wiki:syntax'); 301 $file2 = wikiFN('wiki:dokuwiki'); 302 303 $expected = [ 304 [ 305 'id' => 'wiki:syntax', 306 'perms' => 8, 307 'size' => filesize($file1), 308 'lastModified' => filemtime($file1) 309 ], 310 [ 311 'id' => 'wiki:dokuwiki', 312 'perms' => 8, 313 'size' => filesize($file2), 314 'lastModified' => filemtime($file2) 315 ] 316 ]; 317 $this->assertEquals($expected, $this->remote->call('wiki.getAllPages')); 318 } 319 320 public function testGetBacklinks() 321 { 322 saveWikiText('linky', '[[wiki:syntax]]', 'test'); 323 // backlinks need index 324 idx_addPage('wiki:syntax'); 325 idx_addPage('linky'); 326 327 $params = ['wiki:syntax']; 328 $result = $this->remote->call('wiki.getBackLinks', $params); 329 $this->assertTrue(count($result) > 0); 330 $this->assertEquals(ft_backlinks('wiki:syntax'), $result); 331 } 332 333 public function testGetPageInfo() 334 { 335 $id = 'pageinfo'; 336 $file = wikiFN($id); 337 338 saveWikiText($id, 'test', 'test'); 339 340 $expected = [ 341 'name' => $id, 342 'lastModified' => filemtime($file), 343 'author' => clientIP(), 344 'version' => filemtime($file) 345 ]; 346 $params = [$id]; 347 $this->assertEquals($expected, $this->remote->call('wiki.getPageInfo', $params)); 348 } 349 350 public function testGetPageInfoVersion() 351 { 352 $id = 'pageinfo'; 353 $file = wikiFN($id); 354 355 saveWikiText($id, 'first version', 'first'); 356 $rev1 = filemtime($file); 357 clearstatcache(false, $file); 358 $this->waitForTick(true); 359 saveWikiText($id, 'second version', 'second'); 360 $rev2 = filemtime($file); 361 362 $expected = [ 363 'name' => $id, 364 'lastModified' => $rev2, 365 'author' => clientIP(), 366 'version' => $rev2 367 ]; 368 $params = [$id, '']; 369 $this->assertEquals($expected, $this->remote->call('wiki.getPageInfoVersion', $params), 'no revision given'); 370 371 $expected = [ 372 'name' => $id, 373 'lastModified' => $rev1, 374 'author' => clientIP(), 375 'version' => $rev1 376 ]; 377 $params = [$id, $rev1]; 378 $this->assertEquals($expected, $this->remote->call('wiki.getPageInfoVersion', $params), '1st revision given'); 379 380 $expected = [ 381 'name' => $id, 382 'lastModified' => $rev2, 383 'author' => clientIP(), 384 'version' => $rev2 385 ]; 386 $params = [$id, $rev2]; 387 $this->assertEquals($expected, $this->remote->call('wiki.getPageInfoVersion', $params), '2nd revision given'); 388 } 389 390 public function testGetRecentChanges() 391 { 392 393 saveWikiText('pageone', 'test', 'test'); 394 $rev1 = filemtime(wikiFN('pageone')); 395 saveWikiText('pagetwo', 'test', 'test'); 396 $rev2 = filemtime(wikiFN('pagetwo')); 397 398 $expected = [ 399 [ 400 'name' => 'pageone', 401 'lastModified' => $rev1, 402 'author' => '', 403 'version' => $rev1, 404 'perms' => 8, 405 'size' => 4 406 ], 407 [ 408 'name' => 'pagetwo', 409 'lastModified' => $rev2, 410 'author' => '', 411 'version' => $rev2, 412 'perms' => 8, 413 'size' => 4 414 ] 415 ]; 416 $params = [strtotime("-1 year")]; 417 $this->assertEquals($expected, $this->remote->call('wiki.getRecentChanges', $params)); 418 } 419 420 public function testGetPageVersions() 421 { 422 /** @var $EVENT_HANDLER \dokuwiki\Extension\EventHandler */ 423 global $EVENT_HANDLER; 424 $EVENT_HANDLER->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle_write'); 425 global $conf; 426 427 $id = 'revpage'; 428 $file = wikiFN($id); 429 430 $rev = []; 431 for ($i = 0; $i < 6; $i++) { 432 $this->waitForTick(); 433 saveWikiText($id, "rev$i", "rev$i"); 434 clearstatcache(false, $file); 435 $rev[$i] = filemtime($file); 436 } 437 438 $params = [$id, 0]; 439 $versions = $this->remote->call('wiki.getPageVersions', $params); 440 $this->assertEquals(6, count($versions)); 441 $this->assertEquals($rev[5], $versions[0]['version']); 442 $this->assertEquals($rev[4], $versions[1]['version']); 443 $this->assertEquals($rev[3], $versions[2]['version']); 444 $this->assertEquals($rev[2], $versions[3]['version']); 445 $this->assertEquals($rev[1], $versions[4]['version']); 446 $this->assertEquals($rev[0], $versions[5]['version']); 447 448 $params = [$id, 1]; // offset 1 449 $versions = $this->remote->call('wiki.getPageVersions', $params); 450 $this->assertEquals(5, count($versions)); 451 $this->assertEquals($rev[4], $versions[0]['version']); 452 $this->assertEquals($rev[3], $versions[1]['version']); 453 $this->assertEquals($rev[2], $versions[2]['version']); 454 $this->assertEquals($rev[1], $versions[3]['version']); 455 $this->assertEquals($rev[0], $versions[4]['version']); 456 457 $conf['recent'] = 3; //set number of results per page 458 459 $params = [$id, 0]; // first page 460 $versions = $this->remote->call('wiki.getPageVersions', $params); 461 $this->assertEquals(3, count($versions)); 462 $this->assertEquals($rev[5], $versions[0]['version']); 463 $this->assertEquals($rev[4], $versions[1]['version']); 464 $this->assertEquals($rev[3], $versions[2]['version']); 465 466 $params = [$id, $conf['recent']]; // second page 467 $versions = $this->remote->call('wiki.getPageVersions', $params); 468 $this->assertEquals(3, count($versions)); 469 $this->assertEquals($rev[2], $versions[0]['version']); 470 $this->assertEquals($rev[1], $versions[1]['version']); 471 $this->assertEquals($rev[0], $versions[2]['version']); 472 473 $params = [$id, $conf['recent'] * 2]; // third page 474 $versions = $this->remote->call('wiki.getPageVersions', $params); 475 $this->assertEquals(0, count($versions)); 476 } 477 478 public function testDeleteUser() 479 { 480 global $conf, $auth; 481 $auth = new AuthDeletePlugin(); 482 $conf['remote'] = 1; 483 $conf['remoteuser'] = 'testuser'; 484 $_SERVER['REMOTE_USER'] = 'testuser'; 485 $params = [ 486 ['testuser'] 487 ]; 488 $actualCallResult = $this->remote->call('dokuwiki.deleteUsers', $params); 489 $this->assertTrue($actualCallResult); 490 } 491 492 public function testAclCheck() 493 { 494 $id = 'aclpage'; 495 496 $params = [$id]; 497 $this->assertEquals(AUTH_UPLOAD, $this->remote->call('wiki.aclCheck', $params)); 498 499 global $conf; 500 global $AUTH_ACL, $USERINFO; 501 $conf['useacl'] = 1; 502 $_SERVER['REMOTE_USER'] = 'john'; 503 $USERINFO['grps'] = ['user']; 504 $AUTH_ACL = [ 505 '* @ALL 0', 506 '* @user 2', //edit 507 ]; 508 509 $params = [$id]; 510 $this->assertEquals(AUTH_EDIT, $this->remote->call('wiki.aclCheck', $params)); 511 } 512 513 public function testGetXMLRPCAPIVersion() 514 { 515 $this->assertEquals(ApiCore::API_VERSION, $this->remote->call('dokuwiki.getXMLRPCAPIVersion')); 516 } 517 518 public function testGetRPCVersionSupported() 519 { 520 $this->assertEquals(2, $this->remote->call('wiki.getRPCVersionSupported')); 521 } 522 523 public function testListLinks() 524 { 525 $localdoku = [ 526 'type' => 'local', 527 'page' => 'DokuWiki', 528 'href' => DOKU_BASE . DOKU_SCRIPT . '?id=DokuWiki' 529 ]; 530 $expected = [ //no local links 531 $localdoku, 532 [ 533 'type' => 'extern', 534 'page' => 'http://www.freelists.org', 535 'href' => 'http://www.freelists.org' 536 ], 537 [ 538 'type' => 'extern', 539 'page' => 'https://tools.ietf.org/html/rfc1855', 540 'href' => 'https://tools.ietf.org/html/rfc1855' 541 ], 542 [ 543 'type' => 'extern', 544 'page' => 'http://www.catb.org/~esr/faqs/smart-questions.html', 545 'href' => 'http://www.catb.org/~esr/faqs/smart-questions.html' 546 ], 547 $localdoku, 548 $localdoku 549 ]; 550 $params = ['mailinglist']; 551 $this->assertEquals($expected, $this->remote->call('wiki.listLinks', $params)); 552 } 553 554 public function testCoreattachments() 555 { 556 global $conf; 557 global $AUTH_ACL, $USERINFO; 558 559 $filecontent = io_readFile(mediaFN('wiki:dokuwiki-128.png'), false); 560 $params = ['test:dokuwiki-128_2.png', $filecontent, ['ow' => false]]; 561 $this->assertEquals('test:dokuwiki-128_2.png', $this->remote->call('wiki.putAttachment', $params)); //prints a success div 562 563 $params = ['test:dokuwiki-128_2.png']; 564 $this->assertEquals($filecontent, $this->remote->call('wiki.getAttachment', $params)); 565 $rev = filemtime(mediaFN('test:dokuwiki-128_2.png')); 566 567 $expected = [ 568 'lastModified' => $rev, 569 'size' => 27895, 570 ]; 571 $params = ['test:dokuwiki-128_2.png']; 572 $this->assertEquals($expected, $this->remote->call('wiki.getAttachmentInfo', $params)); 573 574 $params = [strtotime("-5 year")]; 575 $expected = [ 576 [ 577 'name' => 'test:dokuwiki-128_2.png', 578 'lastModified' => $rev, 579 'author' => '', 580 'version' => $rev, 581 'perms' => 8, 582 'size' => 27895 //actual size, not size change 583 ] 584 ]; 585 $this->assertEquals($expected, $this->remote->call('wiki.getRecentMediaChanges', $params)); 586 587 $this->waitForTick(true); 588 $conf['useacl'] = 1; 589 $_SERVER['REMOTE_USER'] = 'john'; 590 $USERINFO['grps'] = ['user']; 591 $AUTH_ACL = [ 592 '* @ALL 0', 593 '* @user 16', 594 ]; 595 596 $params = ['test:dokuwiki-128_2.png']; 597 $this->assertEquals(0, $this->remote->call('wiki.deleteAttachment', $params)); 598 599 $rev2 = filemtime($conf['media_changelog']); 600 $expected = [ 601 'lastModified' => $rev2, 602 'size' => 0, 603 ]; 604 $params = ['test:dokuwiki-128_2.png']; 605 $this->assertEquals($expected, $this->remote->call('wiki.getAttachmentInfo', $params)); 606 607 $expected = [ 608 'lastModified' => 0, 609 'size' => 0, 610 ]; 611 $params = ['test:nonexisting.png']; 612 $this->assertEquals($expected, $this->remote->call('wiki.getAttachmentInfo', $params)); 613 614 $media1 = mediaFN('wiki:dokuwiki-128.png'); 615 $expected = [ 616 [ 617 'id' => 'wiki:dokuwiki-128.png', 618 'file' => 'dokuwiki-128.png', 619 'size' => filesize($media1), 620 'mtime' => filemtime($media1), 621 'writable' => 1, 622 'isimg' => 1, 623 'hash' => md5(io_readFile($media1, false)), 624 'perms' => 16, 625 'lastModified' => filemtime($media1) 626 ] 627 ]; 628 $params = [ 629 'wiki:', 630 [ 631 'depth' => 0, // 0 for all 632 'hash' => 1, 633 'skipacl' => 1, // is ignored 634 'showmsg' => true, //useless?? 635 'pattern' => '/128/' //filter 636 ] 637 ]; 638 $this->assertEquals($expected, $this->remote->call('wiki.getAttachments', $params)); 639 } 640 641} 642