refactor: use native json_encode for $JSINFO
[dokuwiki.git] / inc / RemoteAPICore.php
blob0ff358cf952162f75f2a9155640227942cc1f7bf
1 <?php
3 /**
4 * Increased whenever the API is changed
5 */
6 define('DOKU_API_VERSION', 10);
8 /**
9 * Provides the core methods for the remote API.
10 * The methods are ordered in 'wiki.<method>' and 'dokuwiki.<method>' namespaces
12 class RemoteAPICore {
14 private $api;
16 /**
17 * @param RemoteAPI $api
19 public function __construct(RemoteAPI $api) {
20 $this->api = $api;
23 /**
24 * Returns details about the core methods
26 * @return array
28 public function __getRemoteInfo() {
29 return array(
30 'dokuwiki.getVersion' => array(
31 'args' => array(),
32 'return' => 'string',
33 'doc' => 'Returns the running DokuWiki version.'
34 ), 'dokuwiki.login' => array(
35 'args' => array('string', 'string'),
36 'return' => 'int',
37 'doc' => 'Tries to login with the given credentials and sets auth cookies.',
38 'public' => '1'
39 ), 'dokuwiki.logoff' => array(
40 'args' => array(),
41 'return' => 'int',
42 'doc' => 'Tries to logoff by expiring auth cookies and the associated PHP session.'
43 ), 'dokuwiki.getPagelist' => array(
44 'args' => array('string', 'array'),
45 'return' => 'array',
46 'doc' => 'List all pages within the given namespace.',
47 'name' => 'readNamespace'
48 ), 'dokuwiki.search' => array(
49 'args' => array('string'),
50 'return' => 'array',
51 'doc' => 'Perform a fulltext search and return a list of matching pages'
52 ), 'dokuwiki.getTime' => array(
53 'args' => array(),
54 'return' => 'int',
55 'doc' => 'Returns the current time at the remote wiki server as Unix timestamp.',
56 ), 'dokuwiki.setLocks' => array(
57 'args' => array('array'),
58 'return' => 'array',
59 'doc' => 'Lock or unlock pages.'
60 ), 'dokuwiki.getTitle' => array(
61 'args' => array(),
62 'return' => 'string',
63 'doc' => 'Returns the wiki title.',
64 'public' => '1'
65 ), 'dokuwiki.appendPage' => array(
66 'args' => array('string', 'string', 'array'),
67 'return' => 'bool',
68 'doc' => 'Append text to a wiki page.'
69 ), 'wiki.getPage' => array(
70 'args' => array('string'),
71 'return' => 'string',
72 'doc' => 'Get the raw Wiki text of page, latest version.',
73 'name' => 'rawPage',
74 ), 'wiki.getPageVersion' => array(
75 'args' => array('string', 'int'),
76 'name' => 'rawPage',
77 'return' => 'string',
78 'doc' => 'Return a raw wiki page'
79 ), 'wiki.getPageHTML' => array(
80 'args' => array('string'),
81 'return' => 'string',
82 'doc' => 'Return page in rendered HTML, latest version.',
83 'name' => 'htmlPage'
84 ), 'wiki.getPageHTMLVersion' => array(
85 'args' => array('string', 'int'),
86 'return' => 'string',
87 'doc' => 'Return page in rendered HTML.',
88 'name' => 'htmlPage'
89 ), 'wiki.getAllPages' => array(
90 'args' => array(),
91 'return' => 'array',
92 'doc' => 'Returns a list of all pages. The result is an array of utf8 pagenames.',
93 'name' => 'listPages'
94 ), 'wiki.getAttachments' => array(
95 'args' => array('string', 'array'),
96 'return' => 'array',
97 'doc' => 'Returns a list of all media files.',
98 'name' => 'listAttachments'
99 ), 'wiki.getBackLinks' => array(
100 'args' => array('string'),
101 'return' => 'array',
102 'doc' => 'Returns the pages that link to this page.',
103 'name' => 'listBackLinks'
104 ), 'wiki.getPageInfo' => array(
105 'args' => array('string'),
106 'return' => 'array',
107 'doc' => 'Returns a struct with info about the page, latest version.',
108 'name' => 'pageInfo'
109 ), 'wiki.getPageInfoVersion' => array(
110 'args' => array('string', 'int'),
111 'return' => 'array',
112 'doc' => 'Returns a struct with info about the page.',
113 'name' => 'pageInfo'
114 ), 'wiki.getPageVersions' => array(
115 'args' => array('string', 'int'),
116 'return' => 'array',
117 'doc' => 'Returns the available revisions of the page.',
118 'name' => 'pageVersions'
119 ), 'wiki.putPage' => array(
120 'args' => array('string', 'string', 'array'),
121 'return' => 'bool',
122 'doc' => 'Saves a wiki page.'
123 ), 'wiki.listLinks' => array(
124 'args' => array('string'),
125 'return' => 'array',
126 'doc' => 'Lists all links contained in a wiki page.'
127 ), 'wiki.getRecentChanges' => array(
128 'args' => array('int'),
129 'return' => 'array',
130 'Returns a struct about all recent changes since given timestamp.'
131 ), 'wiki.getRecentMediaChanges' => array(
132 'args' => array('int'),
133 'return' => 'array',
134 'Returns a struct about all recent media changes since given timestamp.'
135 ), 'wiki.aclCheck' => array(
136 'args' => array('string', 'string', 'array'),
137 'return' => 'int',
138 'doc' => 'Returns the permissions of a given wiki page. By default, for current user/groups'
139 ), 'wiki.putAttachment' => array(
140 'args' => array('string', 'file', 'array'),
141 'return' => 'array',
142 'doc' => 'Upload a file to the wiki.'
143 ), 'wiki.deleteAttachment' => array(
144 'args' => array('string'),
145 'return' => 'int',
146 'doc' => 'Delete a file from the wiki.'
147 ), 'wiki.getAttachment' => array(
148 'args' => array('string'),
149 'doc' => 'Return a media file',
150 'return' => 'file',
151 'name' => 'getAttachment',
152 ), 'wiki.getAttachmentInfo' => array(
153 'args' => array('string'),
154 'return' => 'array',
155 'doc' => 'Returns a struct with info about the attachment.'
156 ), 'dokuwiki.getXMLRPCAPIVersion' => array(
157 'args' => array(),
158 'name' => 'getAPIVersion',
159 'return' => 'int',
160 'doc' => 'Returns the XMLRPC API version.',
161 'public' => '1',
162 ), 'wiki.getRPCVersionSupported' => array(
163 'args' => array(),
164 'name' => 'wiki_RPCVersion',
165 'return' => 'int',
166 'doc' => 'Returns 2 with the supported RPC API version.',
167 'public' => '1'
174 * @return string
176 public function getVersion() {
177 return getVersion();
181 * @return int unix timestamp
183 public function getTime() {
184 return time();
188 * Return a raw wiki page
190 * @param string $id wiki page id
191 * @param int|string $rev revision timestamp of the page or empty string
192 * @return string page text.
193 * @throws RemoteAccessDeniedException if no permission for page
195 public function rawPage($id,$rev=''){
196 $id = $this->resolvePageId($id);
197 if(auth_quickaclcheck($id) < AUTH_READ){
198 throw new RemoteAccessDeniedException('You are not allowed to read this file', 111);
200 $text = rawWiki($id,$rev);
201 if(!$text) {
202 return pageTemplate($id);
203 } else {
204 return $text;
209 * Return a media file
211 * @author Gina Haeussge <osd@foosel.net>
213 * @param string $id file id
214 * @return mixed media file
215 * @throws RemoteAccessDeniedException no permission for media
216 * @throws RemoteException not exist
218 public function getAttachment($id){
219 $id = cleanID($id);
220 if (auth_quickaclcheck(getNS($id).':*') < AUTH_READ) {
221 throw new RemoteAccessDeniedException('You are not allowed to read this file', 211);
224 $file = mediaFN($id);
225 if (!@ file_exists($file)) {
226 throw new RemoteException('The requested file does not exist', 221);
229 $data = io_readFile($file, false);
230 return $this->api->toFile($data);
234 * Return info about a media file
236 * @author Gina Haeussge <osd@foosel.net>
238 * @param string $id page id
239 * @return array
241 public function getAttachmentInfo($id){
242 $id = cleanID($id);
243 $info = array(
244 'lastModified' => $this->api->toDate(0),
245 'size' => 0,
248 $file = mediaFN($id);
249 if(auth_quickaclcheck(getNS($id) . ':*') >= AUTH_READ) {
250 if(file_exists($file)) {
251 $info['lastModified'] = $this->api->toDate(filemtime($file));
252 $info['size'] = filesize($file);
253 } else {
254 //Is it deleted media with changelog?
255 $medialog = new MediaChangeLog($id);
256 $revisions = $medialog->getRevisions(0, 1);
257 if(!empty($revisions)) {
258 $info['lastModified'] = $this->api->toDate($revisions[0]);
263 return $info;
267 * Return a wiki page rendered to html
269 * @param string $id page id
270 * @param string|int $rev revision timestamp or empty string
271 * @return null|string html
272 * @throws RemoteAccessDeniedException no access to page
274 public function htmlPage($id,$rev=''){
275 $id = $this->resolvePageId($id);
276 if(auth_quickaclcheck($id) < AUTH_READ){
277 throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
279 return p_wiki_xhtml($id,$rev,false);
283 * List all pages - we use the indexer list here
285 * @return array
287 public function listPages(){
288 $list = array();
289 $pages = idx_get_indexer()->getPages();
290 $pages = array_filter(array_filter($pages,'isVisiblePage'),'page_exists');
292 foreach(array_keys($pages) as $idx) {
293 $perm = auth_quickaclcheck($pages[$idx]);
294 if($perm < AUTH_READ) {
295 continue;
297 $page = array();
298 $page['id'] = trim($pages[$idx]);
299 $page['perms'] = $perm;
300 $page['size'] = @filesize(wikiFN($pages[$idx]));
301 $page['lastModified'] = $this->api->toDate(@filemtime(wikiFN($pages[$idx])));
302 $list[] = $page;
305 return $list;
309 * List all pages in the given namespace (and below)
311 * @param string $ns
312 * @param array $opts
313 * $opts['depth'] recursion level, 0 for all
314 * $opts['hash'] do md5 sum of content?
315 * @return array
317 public function readNamespace($ns,$opts){
318 global $conf;
320 if(!is_array($opts)) $opts=array();
322 $ns = cleanID($ns);
323 $dir = utf8_encodeFN(str_replace(':', '/', $ns));
324 $data = array();
325 $opts['skipacl'] = 0; // no ACL skipping for XMLRPC
326 search($data, $conf['datadir'], 'search_allpages', $opts, $dir);
327 return $data;
331 * List all pages in the given namespace (and below)
333 * @param string $query
334 * @return array
336 public function search($query){
337 $regex = array();
338 $data = ft_pageSearch($query,$regex);
339 $pages = array();
341 // prepare additional data
342 $idx = 0;
343 foreach($data as $id => $score){
344 $file = wikiFN($id);
346 if($idx < FT_SNIPPET_NUMBER){
347 $snippet = ft_snippet($id,$regex);
348 $idx++;
349 }else{
350 $snippet = '';
353 $pages[] = array(
354 'id' => $id,
355 'score' => intval($score),
356 'rev' => filemtime($file),
357 'mtime' => filemtime($file),
358 'size' => filesize($file),
359 'snippet' => $snippet,
360 'title' => useHeading('navigation') ? p_get_first_heading($id) : $id
363 return $pages;
367 * Returns the wiki title.
369 * @return string
371 public function getTitle(){
372 global $conf;
373 return $conf['title'];
377 * List all media files.
379 * Available options are 'recursive' for also including the subnamespaces
380 * in the listing, and 'pattern' for filtering the returned files against
381 * a regular expression matching their name.
383 * @author Gina Haeussge <osd@foosel.net>
385 * @param string $ns
386 * @param array $options
387 * $options['depth'] recursion level, 0 for all
388 * $options['showmsg'] shows message if invalid media id is used
389 * $options['pattern'] check given pattern
390 * $options['hash'] add hashes to result list
391 * @return array
392 * @throws RemoteAccessDeniedException no access to the media files
394 public function listAttachments($ns, $options = array()) {
395 global $conf;
397 $ns = cleanID($ns);
399 if (!is_array($options)) $options = array();
400 $options['skipacl'] = 0; // no ACL skipping for XMLRPC
402 if(auth_quickaclcheck($ns.':*') >= AUTH_READ) {
403 $dir = utf8_encodeFN(str_replace(':', '/', $ns));
405 $data = array();
406 search($data, $conf['mediadir'], 'search_media', $options, $dir);
407 $len = count($data);
408 if(!$len) return array();
410 for($i=0; $i<$len; $i++) {
411 unset($data[$i]['meta']);
412 $data[$i]['perms'] = $data[$i]['perm'];
413 unset($data[$i]['perm']);
414 $data[$i]['lastModified'] = $this->api->toDate($data[$i]['mtime']);
416 return $data;
417 } else {
418 throw new RemoteAccessDeniedException('You are not allowed to list media files.', 215);
423 * Return a list of backlinks
425 * @param string $id page id
426 * @return array
428 function listBackLinks($id){
429 return ft_backlinks($this->resolvePageId($id));
433 * Return some basic data about a page
435 * @param string $id page id
436 * @param string|int $rev revision timestamp or empty string
437 * @return array
438 * @throws RemoteAccessDeniedException no access for page
439 * @throws RemoteException page not exist
441 public function pageInfo($id,$rev=''){
442 $id = $this->resolvePageId($id);
443 if(auth_quickaclcheck($id) < AUTH_READ){
444 throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
446 $file = wikiFN($id,$rev);
447 $time = @filemtime($file);
448 if(!$time){
449 throw new RemoteException('The requested page does not exist', 121);
452 // set revision to current version if empty, use revision otherwise
453 // as the timestamps of old files are not necessarily correct
454 if($rev === '') {
455 $rev = $time;
458 $pagelog = new PageChangeLog($id, 1024);
459 $info = $pagelog->getRevisionInfo($rev);
461 $data = array(
462 'name' => $id,
463 'lastModified' => $this->api->toDate($rev),
464 'author' => (($info['user']) ? $info['user'] : $info['ip']),
465 'version' => $rev
468 return ($data);
472 * Save a wiki page
474 * @author Michael Klier <chi@chimeric.de>
476 * @param string $id page id
477 * @param string $text wiki text
478 * @param array $params parameters: summary, minor edit
479 * @return bool
480 * @throws RemoteAccessDeniedException no write access for page
481 * @throws RemoteException no id, empty new page or locked
483 public function putPage($id, $text, $params) {
484 global $TEXT;
485 global $lang;
487 $id = $this->resolvePageId($id);
488 $TEXT = cleanText($text);
489 $sum = $params['sum'];
490 $minor = $params['minor'];
492 if(empty($id)) {
493 throw new RemoteException('Empty page ID', 131);
496 if(!page_exists($id) && trim($TEXT) == '' ) {
497 throw new RemoteException('Refusing to write an empty new wiki page', 132);
500 if(auth_quickaclcheck($id) < AUTH_EDIT) {
501 throw new RemoteAccessDeniedException('You are not allowed to edit this page', 112);
504 // Check, if page is locked
505 if(checklock($id)) {
506 throw new RemoteException('The page is currently locked', 133);
509 // SPAM check
510 if(checkwordblock()) {
511 throw new RemoteException('Positive wordblock check', 134);
514 // autoset summary on new pages
515 if(!page_exists($id) && empty($sum)) {
516 $sum = $lang['created'];
519 // autoset summary on deleted pages
520 if(page_exists($id) && empty($TEXT) && empty($sum)) {
521 $sum = $lang['deleted'];
524 lock($id);
526 saveWikiText($id,$TEXT,$sum,$minor);
528 unlock($id);
530 // run the indexer if page wasn't indexed yet
531 idx_addPage($id);
533 return true;
537 * Appends text to a wiki page.
539 * @param string $id page id
540 * @param string $text wiki text
541 * @param array $params such as summary,minor
542 * @return bool|string
544 public function appendPage($id, $text, $params) {
545 $currentpage = $this->rawPage($id);
546 if (!is_string($currentpage)) {
547 return $currentpage;
549 return $this->putPage($id, $currentpage.$text, $params);
553 * Uploads a file to the wiki.
555 * Michael Klier <chi@chimeric.de>
557 * @param string $id page id
558 * @param string $file
559 * @param array $params such as overwrite
560 * @return false|string
561 * @throws RemoteException
563 public function putAttachment($id, $file, $params) {
564 $id = cleanID($id);
565 $auth = auth_quickaclcheck(getNS($id).':*');
567 if(!isset($id)) {
568 throw new RemoteException('Filename not given.', 231);
571 global $conf;
573 $ftmp = $conf['tmpdir'] . '/' . md5($id.clientIP());
575 // save temporary file
576 @unlink($ftmp);
577 io_saveFile($ftmp, $file);
579 $res = media_save(array('name' => $ftmp), $id, $params['ow'], $auth, 'rename');
580 if (is_array($res)) {
581 throw new RemoteException($res[0], -$res[1]);
582 } else {
583 return $res;
588 * Deletes a file from the wiki.
590 * @author Gina Haeussge <osd@foosel.net>
592 * @param string $id page id
593 * @return int
594 * @throws RemoteAccessDeniedException no permissions
595 * @throws RemoteException file in use or not deleted
597 public function deleteAttachment($id){
598 $id = cleanID($id);
599 $auth = auth_quickaclcheck(getNS($id).':*');
600 $res = media_delete($id, $auth);
601 if ($res & DOKU_MEDIA_DELETED) {
602 return 0;
603 } elseif ($res & DOKU_MEDIA_NOT_AUTH) {
604 throw new RemoteAccessDeniedException('You don\'t have permissions to delete files.', 212);
605 } elseif ($res & DOKU_MEDIA_INUSE) {
606 throw new RemoteException('File is still referenced', 232);
607 } else {
608 throw new RemoteException('Could not delete file', 233);
613 * Returns the permissions of a given wiki page for the current user or another user
615 * @param string $id page id
616 * @param string|null $user username
617 * @param array|null $groups array of groups
618 * @return int permission level
620 public function aclCheck($id, $user = null, $groups = null) {
621 /** @var DokuWiki_Auth_Plugin $auth */
622 global $auth;
624 $id = $this->resolvePageId($id);
625 if($user === null) {
626 return auth_quickaclcheck($id);
627 } else {
628 if($groups === null) {
629 $userinfo = $auth->getUserData($user);
630 if($userinfo === false) {
631 $groups = array();
632 } else {
633 $groups = $userinfo['grps'];
636 return auth_aclcheck($id, $user, $groups);
641 * Lists all links contained in a wiki page
643 * @author Michael Klier <chi@chimeric.de>
645 * @param string $id page id
646 * @return array
647 * @throws RemoteAccessDeniedException no read access for page
649 public function listLinks($id) {
650 $id = $this->resolvePageId($id);
651 if(auth_quickaclcheck($id) < AUTH_READ){
652 throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
654 $links = array();
656 // resolve page instructions
657 $ins = p_cached_instructions(wikiFN($id));
659 // instantiate new Renderer - needed for interwiki links
660 $Renderer = new Doku_Renderer_xhtml();
661 $Renderer->interwiki = getInterwiki();
663 // parse parse instructions
664 foreach($ins as $in) {
665 $link = array();
666 switch($in[0]) {
667 case 'internallink':
668 $link['type'] = 'local';
669 $link['page'] = $in[1][0];
670 $link['href'] = wl($in[1][0]);
671 array_push($links,$link);
672 break;
673 case 'externallink':
674 $link['type'] = 'extern';
675 $link['page'] = $in[1][0];
676 $link['href'] = $in[1][0];
677 array_push($links,$link);
678 break;
679 case 'interwikilink':
680 $url = $Renderer->_resolveInterWiki($in[1][2],$in[1][3]);
681 $link['type'] = 'extern';
682 $link['page'] = $url;
683 $link['href'] = $url;
684 array_push($links,$link);
685 break;
689 return ($links);
693 * Returns a list of recent changes since give timestamp
695 * @author Michael Hamann <michael@content-space.de>
696 * @author Michael Klier <chi@chimeric.de>
698 * @param int $timestamp unix timestamp
699 * @return array
700 * @throws RemoteException no valid timestamp
702 public function getRecentChanges($timestamp) {
703 if(strlen($timestamp) != 10) {
704 throw new RemoteException('The provided value is not a valid timestamp', 311);
707 $recents = getRecentsSince($timestamp);
709 $changes = array();
711 foreach ($recents as $recent) {
712 $change = array();
713 $change['name'] = $recent['id'];
714 $change['lastModified'] = $this->api->toDate($recent['date']);
715 $change['author'] = $recent['user'];
716 $change['version'] = $recent['date'];
717 $change['perms'] = $recent['perms'];
718 $change['size'] = @filesize(wikiFN($recent['id']));
719 array_push($changes, $change);
722 if (!empty($changes)) {
723 return $changes;
724 } else {
725 // in case we still have nothing at this point
726 throw new RemoteException('There are no changes in the specified timeframe', 321);
731 * Returns a list of recent media changes since give timestamp
733 * @author Michael Hamann <michael@content-space.de>
734 * @author Michael Klier <chi@chimeric.de>
736 * @param int $timestamp unix timestamp
737 * @return array
738 * @throws RemoteException no valid timestamp
740 public function getRecentMediaChanges($timestamp) {
741 if(strlen($timestamp) != 10)
742 throw new RemoteException('The provided value is not a valid timestamp', 311);
744 $recents = getRecentsSince($timestamp, null, '', RECENTS_MEDIA_CHANGES);
746 $changes = array();
748 foreach ($recents as $recent) {
749 $change = array();
750 $change['name'] = $recent['id'];
751 $change['lastModified'] = $this->api->toDate($recent['date']);
752 $change['author'] = $recent['user'];
753 $change['version'] = $recent['date'];
754 $change['perms'] = $recent['perms'];
755 $change['size'] = @filesize(mediaFN($recent['id']));
756 array_push($changes, $change);
759 if (!empty($changes)) {
760 return $changes;
761 } else {
762 // in case we still have nothing at this point
763 throw new RemoteException('There are no changes in the specified timeframe', 321);
768 * Returns a list of available revisions of a given wiki page
769 * Number of returned pages is set by $conf['recent']
770 * However not accessible pages are skipped, so less than $conf['recent'] could be returned
772 * @author Michael Klier <chi@chimeric.de>
774 * @param string $id page id
775 * @param int $first skip the first n changelog lines (0 = from current(if exists), 1 = from 1st old rev, 2 = from 2nd old rev, etc)
776 * @return array
777 * @throws RemoteAccessDeniedException no read access for page
778 * @throws RemoteException empty id
780 public function pageVersions($id, $first) {
781 $id = $this->resolvePageId($id);
782 if(auth_quickaclcheck($id) < AUTH_READ) {
783 throw new RemoteAccessDeniedException('You are not allowed to read this page', 111);
785 global $conf;
787 $versions = array();
789 if(empty($id)) {
790 throw new RemoteException('Empty page ID', 131);
793 $first = (int) $first;
794 $first_rev = $first - 1;
795 $first_rev = $first_rev < 0 ? 0 : $first_rev;
796 $pagelog = new PageChangeLog($id);
797 $revisions = $pagelog->getRevisions($first_rev, $conf['recent']);
799 if($first == 0) {
800 array_unshift($revisions, ''); // include current revision
801 if ( count($revisions) > $conf['recent'] ){
802 array_pop($revisions); // remove extra log entry
806 if(!empty($revisions)) {
807 foreach($revisions as $rev) {
808 $file = wikiFN($id,$rev);
809 $time = @filemtime($file);
810 // we check if the page actually exists, if this is not the
811 // case this can lead to less pages being returned than
812 // specified via $conf['recent']
813 if($time){
814 $pagelog->setChunkSize(1024);
815 $info = $pagelog->getRevisionInfo($rev ? $rev : $time);
816 if(!empty($info)) {
817 $data = array();
818 $data['user'] = $info['user'];
819 $data['ip'] = $info['ip'];
820 $data['type'] = $info['type'];
821 $data['sum'] = $info['sum'];
822 $data['modified'] = $this->api->toDate($info['date']);
823 $data['version'] = $info['date'];
824 array_push($versions, $data);
828 return $versions;
829 } else {
830 return array();
835 * The version of Wiki RPC API supported
837 public function wiki_RPCVersion(){
838 return 2;
843 * Locks or unlocks a given batch of pages
845 * Give an associative array with two keys: lock and unlock. Both should contain a
846 * list of pages to lock or unlock
848 * Returns an associative array with the keys locked, lockfail, unlocked and
849 * unlockfail, each containing lists of pages.
851 * @param array[] $set list pages with array('lock' => array, 'unlock' => array)
852 * @return array
854 public function setLocks($set){
855 $locked = array();
856 $lockfail = array();
857 $unlocked = array();
858 $unlockfail = array();
860 foreach((array) $set['lock'] as $id){
861 $id = $this->resolvePageId($id);
862 if(auth_quickaclcheck($id) < AUTH_EDIT || checklock($id)){
863 $lockfail[] = $id;
864 }else{
865 lock($id);
866 $locked[] = $id;
870 foreach((array) $set['unlock'] as $id){
871 $id = $this->resolvePageId($id);
872 if(auth_quickaclcheck($id) < AUTH_EDIT || !unlock($id)){
873 $unlockfail[] = $id;
874 }else{
875 $unlocked[] = $id;
879 return array(
880 'locked' => $locked,
881 'lockfail' => $lockfail,
882 'unlocked' => $unlocked,
883 'unlockfail' => $unlockfail,
888 * Return API version
890 * @return int
892 public function getAPIVersion(){
893 return DOKU_API_VERSION;
897 * Login
899 * @param string $user
900 * @param string $pass
901 * @return int
903 public function login($user,$pass){
904 global $conf;
905 /** @var DokuWiki_Auth_Plugin $auth */
906 global $auth;
908 if(!$conf['useacl']) return 0;
909 if(!$auth) return 0;
911 @session_start(); // reopen session for login
912 if($auth->canDo('external')){
913 $ok = $auth->trustExternal($user,$pass,false);
914 }else{
915 $evdata = array(
916 'user' => $user,
917 'password' => $pass,
918 'sticky' => false,
919 'silent' => true,
921 $ok = trigger_event('AUTH_LOGIN_CHECK', $evdata, 'auth_login_wrapper');
923 session_write_close(); // we're done with the session
925 return $ok;
929 * Log off
931 * @return int
933 public function logoff(){
934 global $conf;
935 global $auth;
936 if(!$conf['useacl']) return 0;
937 if(!$auth) return 0;
939 auth_logoff();
941 return 1;
945 * Resolve page id
947 * @param string $id page id
948 * @return string
950 private function resolvePageId($id) {
951 $id = cleanID($id);
952 if(empty($id)) {
953 global $conf;
954 $id = cleanID($conf['start']);
956 return $id;