first commit. dokuwiki.
[h2N7SspZmY.git] / lib / exe / xmlrpc.php
blobd3913482f1da023c4cdc334b18d0e11a0aebcb9d
1 <?php
2 if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
4 // fix when '<?xml' isn't on the very first line
5 if(isset($HTTP_RAW_POST_DATA)) $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
7 /**
8 * Increased whenever the API is changed
9 */
10 define('DOKU_XMLRPC_API_VERSION',2);
12 require_once(DOKU_INC.'inc/init.php');
13 require_once(DOKU_INC.'inc/common.php');
14 require_once(DOKU_INC.'inc/auth.php');
15 session_write_close(); //close session
17 if(!$conf['xmlrpc']) die('XML-RPC server not enabled.');
19 require_once(DOKU_INC.'inc/IXR_Library.php');
22 /**
23 * Contains needed wrapper functions and registers all available
24 * XMLRPC functions.
26 class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
27 var $methods = array();
28 var $public_methods = array();
30 /**
31 * Checks if the current user is allowed to execute non anonymous methods
33 function checkAuth(){
34 global $conf;
35 global $USERINFO;
37 if(!$conf['useacl']) return true; //no ACL - then no checks
39 $allowed = explode(',',$conf['xmlrpcuser']);
40 $allowed = array_map('trim', $allowed);
41 $allowed = array_unique($allowed);
42 $allowed = array_filter($allowed);
44 if(!count($allowed)) return true; //no restrictions
46 $user = $_SERVER['REMOTE_USER'];
47 $groups = (array) $USERINFO['grps'];
49 if(in_array($user,$allowed)) return true; //user explicitly mentioned
51 //check group memberships
52 foreach($groups as $group){
53 if(in_array('@'.$group,$allowed)) return true;
56 //still here? no access!
57 return false;
60 /**
61 * Adds a callback, extends parent method
63 * add another parameter to define if anonymous access to
64 * this method should be granted.
66 function addCallback($method, $callback, $args, $help, $public=false){
67 if($public) $this->public_methods[] = $method;
68 return parent::addCallback($method, $callback, $args, $help);
71 /**
72 * Execute a call, extends parent method
74 * Checks for authentication first
76 function call($methodname, $args){
77 if(!in_array($methodname,$this->public_methods) && !$this->checkAuth()){
78 return new IXR_Error(-32603, 'server error. not authorized to call method "'.$methodname.'".');
80 return parent::call($methodname, $args);
83 /**
84 * Constructor. Register methods and run Server
86 function dokuwiki_xmlrpc_server(){
87 $this->IXR_IntrospectionServer();
89 /* DokuWiki's own methods */
90 $this->addCallback(
91 'dokuwiki.getXMLRPCAPIVersion',
92 'this:getAPIVersion',
93 array('integer'),
94 'Returns the XMLRPC API version.',
95 true
98 $this->addCallback(
99 'dokuwiki.getVersion',
100 'getVersion',
101 array('string'),
102 'Returns the running DokuWiki version.',
103 true
106 $this->addCallback(
107 'dokuwiki.login',
108 'this:login',
109 array('integer','string','string'),
110 'Tries to login with the given credentials and sets auth cookies.',
111 true
114 $this->addCallback(
115 'dokuwiki.getPagelist',
116 'this:readNamespace',
117 array('struct','string','struct'),
118 'List all pages within the given namespace.'
121 $this->addCallback(
122 'dokuwiki.getTime',
123 'time',
124 array('int'),
125 'Return the current time at the wiki server.'
128 $this->addCallback(
129 'dokuwiki.setLocks',
130 'this:setLocks',
131 array('struct','struct'),
132 'Lock or unlock pages.'
135 /* Wiki API v2 http://www.jspwiki.org/wiki/WikiRPCInterface2 */
136 $this->addCallback(
137 'wiki.getRPCVersionSupported',
138 'this:wiki_RPCVersion',
139 array('int'),
140 'Returns 2 with the supported RPC API version.',
141 true
143 $this->addCallback(
144 'wiki.getPage',
145 'this:rawPage',
146 array('string','string'),
147 'Get the raw Wiki text of page, latest version.'
149 $this->addCallback(
150 'wiki.getPageVersion',
151 'this:rawPage',
152 array('string','string','int'),
153 'Get the raw Wiki text of page.'
155 $this->addCallback(
156 'wiki.getPageHTML',
157 'this:htmlPage',
158 array('string','string'),
159 'Return page in rendered HTML, latest version.'
161 $this->addCallback(
162 'wiki.getPageHTMLVersion',
163 'this:htmlPage',
164 array('string','string','int'),
165 'Return page in rendered HTML.'
167 $this->addCallback(
168 'wiki.getAllPages',
169 'this:listPages',
170 array('struct'),
171 'Returns a list of all pages. The result is an array of utf8 pagenames.'
173 $this->addCallback(
174 'wiki.getAttachments',
175 'this:listAttachments',
176 array('struct', 'string', 'struct'),
177 'Returns a list of all media files.'
179 $this->addCallback(
180 'wiki.getBackLinks',
181 'this:listBackLinks',
182 array('struct','string'),
183 'Returns the pages that link to this page.'
185 $this->addCallback(
186 'wiki.getPageInfo',
187 'this:pageInfo',
188 array('struct','string'),
189 'Returns a struct with infos about the page.'
191 $this->addCallback(
192 'wiki.getPageInfoVersion',
193 'this:pageInfo',
194 array('struct','string','int'),
195 'Returns a struct with infos about the page.'
197 $this->addCallback(
198 'wiki.getPageVersions',
199 'this:pageVersions',
200 array('struct','string','int'),
201 'Returns the available revisions of the page.'
203 $this->addCallback(
204 'wiki.putPage',
205 'this:putPage',
206 array('int', 'string', 'string', 'struct'),
207 'Saves a wiki page.'
209 $this->addCallback(
210 'wiki.listLinks',
211 'this:listLinks',
212 array('struct','string'),
213 'Lists all links contained in a wiki page.'
215 $this->addCallback(
216 'wiki.getRecentChanges',
217 'this:getRecentChanges',
218 array('struct','int'),
219 'Returns a struct about all recent changes since given timestamp.'
221 $this->addCallback(
222 'wiki.getRecentMediaChanges',
223 'this:getRecentMediaChanges',
224 array('struct','int'),
225 'Returns a struct about all recent media changes since given timestamp.'
227 $this->addCallback(
228 'wiki.aclCheck',
229 'this:aclCheck',
230 array('int', 'string'),
231 'Returns the permissions of a given wiki page.'
233 $this->addCallback(
234 'wiki.putAttachment',
235 'this:putAttachment',
236 array('struct', 'string', 'base64', 'struct'),
237 'Upload a file to the wiki.'
239 $this->addCallback(
240 'wiki.deleteAttachment',
241 'this:deleteAttachment',
242 array('int', 'string'),
243 'Delete a file from the wiki.'
245 $this->addCallback(
246 'wiki.getAttachment',
247 'this:getAttachment',
248 array('base64', 'string'),
249 'Download a file from the wiki.'
251 $this->addCallback(
252 'wiki.getAttachmentInfo',
253 'this:getAttachmentInfo',
254 array('struct', 'string'),
255 'Returns a struct with infos about the attachment.'
259 * Trigger XMLRPC_CALLBACK_REGISTER, action plugins can use this event
260 * to extend the XMLRPC interface and register their own callbacks.
262 * Event data:
263 * The XMLRPC server object:
265 * $event->data->addCallback() - register a callback, the second
266 * paramter has to be of the form "plugin:<pluginname>:<plugin
267 * method>"
269 * $event->data->callbacks - an array which holds all awaylable
270 * callbacks
272 trigger_event('XMLRPC_CALLBACK_REGISTER', $this);
274 $this->serve();
278 * Return a raw wiki page
280 function rawPage($id,$rev=''){
281 if(auth_quickaclcheck($id) < AUTH_READ){
282 return new IXR_Error(1, 'You are not allowed to read this page');
284 $text = rawWiki($id,$rev);
285 if(!$text) {
286 $data = array($id);
287 return trigger_event('HTML_PAGE_FROMTEMPLATE',$data,'pageTemplate',true);
288 } else {
289 return $text;
294 * Return a media file encoded in base64
296 * @author Gina Haeussge <osd@foosel.net>
298 function getAttachment($id){
299 $id = cleanID($id);
300 if (auth_quickaclcheck(getNS($id).':*') < AUTH_READ)
301 return new IXR_Error(1, 'You are not allowed to read this file');
303 $file = mediaFN($id);
304 if (!@ file_exists($file))
305 return new IXR_Error(1, 'The requested file does not exist');
307 $data = io_readFile($file, false);
308 $base64 = base64_encode($data);
309 return $base64;
313 * Return info about a media file
315 * @author Gina Haeussge <osd@foosel.net>
317 function getAttachmentInfo($id){
318 $id = cleanID($id);
319 $info = array(
320 'lastModified' => 0,
321 'size' => 0,
324 $file = mediaFN($id);
325 if ((auth_quickaclcheck(getNS($id).':*') >= AUTH_READ) && file_exists($file)){
326 $info['lastModified'] = new IXR_Date(filemtime($file));
327 $info['size'] = filesize($file);
330 return $info;
334 * Return a wiki page rendered to html
336 function htmlPage($id,$rev=''){
337 if(auth_quickaclcheck($id) < AUTH_READ){
338 return new IXR_Error(1, 'You are not allowed to read this page');
340 return p_wiki_xhtml($id,$rev,false);
344 * List all pages - we use the indexer list here
346 function listPages(){
347 global $conf;
349 $list = array();
350 $pages = file($conf['indexdir'] . '/page.idx');
351 $pages = array_filter($pages, 'isVisiblePage');
353 foreach(array_keys($pages) as $idx) {
354 if(page_exists($pages[$idx])) {
355 $perm = auth_quickaclcheck($pages[$idx]);
356 if($perm >= AUTH_READ) {
357 $page = array();
358 $page['id'] = trim($pages[$idx]);
359 $page['perms'] = $perm;
360 $page['size'] = @filesize(wikiFN($pages[$idx]));
361 $page['lastModified'] = new IXR_Date(@filemtime(wikiFN($pages[$idx])));
362 $list[] = $page;
367 return $list;
371 * List all pages in the given namespace (and below)
373 function readNamespace($ns,$opts){
374 global $conf;
376 if(!is_array($opts)) $opts=array();
378 $ns = cleanID($ns);
379 $dir = utf8_encodeFN(str_replace(':', '/', $ns));
380 $data = array();
381 require_once(DOKU_INC.'inc/search.php');
382 $opts['skipacl'] = 0; // no ACL skipping for XMLRPC
383 search($data, $conf['datadir'], 'search_allpages', $opts, $dir);
384 return $data;
388 * List all media files.
390 * Available options are 'recursive' for also including the subnamespaces
391 * in the listing, and 'pattern' for filtering the returned files against
392 * a regular expression matching their name.
394 * @author Gina Haeussge <osd@foosel.net>
396 function listAttachments($ns, $options = array()) {
397 global $conf;
398 global $lang;
400 $ns = cleanID($ns);
402 if (!is_array($options)) $options = array();
403 $options['skipacl'] = 0; // no ACL skipping for XMLRPC
406 if(auth_quickaclcheck($ns.':*') >= AUTH_READ) {
407 $dir = utf8_encodeFN(str_replace(':', '/', $ns));
409 $data = array();
410 require_once(DOKU_INC.'inc/search.php');
411 search($data, $conf['mediadir'], 'search_media', $options, $dir);
412 $len = count($data);
413 if(!$len) return array();
415 for($i=0; $i<$len; $i++) {
416 unset($data[$i]['meta']);
417 $data[$i]['lastModified'] = new IXR_Date($data[$i]['mtime']);
419 return $data;
420 } else {
421 return new IXR_Error(1, 'You are not allowed to list media files.');
426 * Return a list of backlinks
428 function listBackLinks($id){
429 require_once(DOKU_INC.'inc/fulltext.php');
430 return ft_backlinks($id);
434 * Return some basic data about a page
436 function pageInfo($id,$rev=''){
437 if(auth_quickaclcheck($id) < AUTH_READ){
438 return new IXR_Error(1, 'You are not allowed to read this page');
440 $file = wikiFN($id,$rev);
441 $time = @filemtime($file);
442 if(!$time){
443 return new IXR_Error(10, 'The requested page does not exist');
446 $info = getRevisionInfo($id, $time, 1024);
448 $data = array(
449 'name' => $id,
450 'lastModified' => new IXR_Date($time),
451 'author' => (($info['user']) ? $info['user'] : $info['ip']),
452 'version' => $time
455 return ($data);
459 * Save a wiki page
461 * @author Michael Klier <chi@chimeric.de>
463 function putPage($id, $text, $params) {
464 global $TEXT;
465 global $lang;
466 global $conf;
468 $id = cleanID($id);
469 $TEXT = cleanText($text);
470 $sum = $params['sum'];
471 $minor = $params['minor'];
473 if(empty($id))
474 return new IXR_Error(1, 'Empty page ID');
476 if(!page_exists($id) && trim($TEXT) == '' ) {
477 return new IXR_ERROR(1, 'Refusing to write an empty new wiki page');
480 if(auth_quickaclcheck($id) < AUTH_EDIT)
481 return new IXR_Error(1, 'You are not allowed to edit this page');
483 // Check, if page is locked
484 if(checklock($id))
485 return new IXR_Error(1, 'The page is currently locked');
487 // SPAM check
488 if(checkwordblock())
489 return new IXR_Error(1, 'Positive wordblock check');
491 // autoset summary on new pages
492 if(!page_exists($id) && empty($sum)) {
493 $sum = $lang['created'];
496 // autoset summary on deleted pages
497 if(page_exists($id) && empty($TEXT) && empty($sum)) {
498 $sum = $lang['deleted'];
501 lock($id);
503 saveWikiText($id,$TEXT,$sum,$minor);
505 unlock($id);
507 // run the indexer if page wasn't indexed yet
508 if(!@file_exists(metaFN($id, '.indexed'))) {
509 // try to aquire a lock
510 $lock = $conf['lockdir'].'/_indexer.lock';
511 while(!@mkdir($lock,$conf['dmode'])){
512 usleep(50);
513 if(time()-@filemtime($lock) > 60*5){
514 // looks like a stale lock - remove it
515 @rmdir($lock);
516 }else{
517 return false;
520 if($conf['dperm']) chmod($lock, $conf['dperm']);
522 require_once(DOKU_INC.'inc/indexer.php');
524 // do the work
525 idx_addPage($id);
527 // we're finished - save and free lock
528 io_saveFile(metaFN($id,'.indexed'),INDEXER_VERSION);
529 @rmdir($lock);
532 return 0;
536 * Uploads a file to the wiki.
538 * Michael Klier <chi@chimeric.de>
540 function putAttachment($id, $file, $params) {
541 global $conf;
542 global $lang;
544 $auth = auth_quickaclcheck(getNS($id).':*');
545 if($auth >= AUTH_UPLOAD) {
546 if(!isset($id)) {
547 return new IXR_ERROR(1, 'Filename not given.');
550 $ftmp = $conf['tmpdir'] . '/' . $id;
552 // save temporary file
553 @unlink($ftmp);
554 $buff = base64_decode($file);
555 io_saveFile($ftmp, $buff);
557 // get filename
558 list($iext, $imime,$dl) = mimetype($id);
559 $id = cleanID($id);
560 $fn = mediaFN($id);
562 // get filetype regexp
563 $types = array_keys(getMimeTypes());
564 $types = array_map(create_function('$q','return preg_quote($q,"/");'),$types);
565 $regex = join('|',$types);
567 // because a temp file was created already
568 if(preg_match('/\.('.$regex.')$/i',$fn)) {
569 //check for overwrite
570 $overwrite = @file_exists($fn);
571 if($overwrite && (!$params['ow'] || $auth < AUTH_DELETE)) {
572 return new IXR_ERROR(1, $lang['uploadexist'].'1');
574 // check for valid content
575 @require_once(DOKU_INC.'inc/media.php');
576 $ok = media_contentcheck($ftmp, $imime);
577 if($ok == -1) {
578 return new IXR_ERROR(1, sprintf($lang['uploadexist'].'2', ".$iext"));
579 } elseif($ok == -2) {
580 return new IXR_ERROR(1, $lang['uploadspam']);
581 } elseif($ok == -3) {
582 return new IXR_ERROR(1, $lang['uploadxss']);
585 // prepare event data
586 $data[0] = $ftmp;
587 $data[1] = $fn;
588 $data[2] = $id;
589 $data[3] = $imime;
590 $data[4] = $overwrite;
592 // trigger event
593 require_once(DOKU_INC.'inc/events.php');
594 return trigger_event('MEDIA_UPLOAD_FINISH', $data, array($this, '_media_upload_action'), true);
596 } else {
597 return new IXR_ERROR(1, $lang['uploadwrong']);
599 } else {
600 return new IXR_ERROR(1, "You don't have permissions to upload files.");
605 * Deletes a file from the wiki.
607 * @author Gina Haeussge <osd@foosel.net>
609 function deleteAttachment($id){
610 $auth = auth_quickaclcheck(getNS($id).':*');
611 if($auth < AUTH_DELETE) return new IXR_ERROR(1, "You don't have permissions to delete files.");
612 global $conf;
613 global $lang;
615 // check for references if needed
616 $mediareferences = array();
617 if($conf['refcheck']){
618 require_once(DOKU_INC.'inc/fulltext.php');
619 $mediareferences = ft_mediause($id,$conf['refshow']);
622 if(!count($mediareferences)){
623 $file = mediaFN($id);
624 if(@unlink($file)){
625 require_once(DOKU_INC.'inc/changelog.php');
626 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE);
627 io_sweepNS($id,'mediadir');
628 return 0;
630 //something went wrong
631 return new IXR_ERROR(1, 'Could not delete file');
632 } else {
633 return new IXR_ERROR(1, 'File is still referenced');
638 * Moves the temporary file to its final destination.
640 * Michael Klier <chi@chimeric.de>
642 function _media_upload_action($data) {
643 global $conf;
645 if(is_array($data) && count($data)===5) {
646 io_createNamespace($data[2], 'media');
647 if(rename($data[0], $data[1])) {
648 chmod($data[1], $conf['fmode']);
649 media_notify($data[2], $data[1], $data[3]);
650 // add a log entry to the media changelog
651 require_once(DOKU_INC.'inc/changelog.php');
652 if ($data[4]) {
653 addMediaLogEntry(time(), $data[2], DOKU_CHANGE_TYPE_EDIT);
654 } else {
655 addMediaLogEntry(time(), $data[2], DOKU_CHANGE_TYPE_CREATE);
657 return $data[2];
658 } else {
659 return new IXR_ERROR(1, 'Upload failed.');
661 } else {
662 return new IXR_ERROR(1, 'Upload failed.');
667 * Returns the permissions of a given wiki page
669 function aclCheck($id) {
670 return auth_quickaclcheck($id);
674 * Lists all links contained in a wiki page
676 * @author Michael Klier <chi@chimeric.de>
678 function listLinks($id) {
679 if(auth_quickaclcheck($id) < AUTH_READ){
680 return new IXR_Error(1, 'You are not allowed to read this page');
682 $links = array();
684 // resolve page instructions
685 $ins = p_cached_instructions(wikiFN(cleanID($id)));
687 // instantiate new Renderer - needed for interwiki links
688 include(DOKU_INC.'inc/parser/xhtml.php');
689 $Renderer = new Doku_Renderer_xhtml();
690 $Renderer->interwiki = getInterwiki();
692 // parse parse instructions
693 foreach($ins as $in) {
694 $link = array();
695 switch($in[0]) {
696 case 'internallink':
697 $link['type'] = 'local';
698 $link['page'] = $in[1][0];
699 $link['href'] = wl($in[1][0]);
700 array_push($links,$link);
701 break;
702 case 'externallink':
703 $link['type'] = 'extern';
704 $link['page'] = $in[1][0];
705 $link['href'] = $in[1][0];
706 array_push($links,$link);
707 break;
708 case 'interwikilink':
709 $url = $Renderer->_resolveInterWiki($in[1][2],$in[1][3]);
710 $link['type'] = 'extern';
711 $link['page'] = $url;
712 $link['href'] = $url;
713 array_push($links,$link);
714 break;
718 return ($links);
722 * Returns a list of recent changes since give timestamp
724 * @author Michael Hamann <michael@content-space.de>
725 * @author Michael Klier <chi@chimeric.de>
727 function getRecentChanges($timestamp) {
728 if(strlen($timestamp) != 10)
729 return new IXR_Error(20, 'The provided value is not a valid timestamp');
731 require_once(DOKU_INC.'inc/changelog.php');
732 require_once(DOKU_INC.'inc/pageutils.php');
734 $recents = getRecentsSince($timestamp);
736 $changes = array();
738 foreach ($recents as $recent) {
739 $change = array();
740 $change['name'] = $recent['id'];
741 $change['lastModified'] = new IXR_Date($recent['date']);
742 $change['author'] = $recent['user'];
743 $change['version'] = $recent['date'];
744 $change['perms'] = $recent['perms'];
745 $change['size'] = @filesize(wikiFN($recent['id']));
746 array_push($changes, $change);
749 if (!empty($changes)) {
750 return $changes;
751 } else {
752 // in case we still have nothing at this point
753 return new IXR_Error(30, 'There are no changes in the specified timeframe');
758 * Returns a list of recent media changes since give timestamp
760 * @author Michael Hamann <michael@content-space.de>
761 * @author Michael Klier <chi@chimeric.de>
763 function getRecentMediaChanges($timestamp) {
764 if(strlen($timestamp) != 10)
765 return new IXR_Error(20, 'The provided value is not a valid timestamp');
767 require_once(DOKU_INC.'inc/changelog.php');
768 require_once(DOKU_INC.'inc/pageutils.php');
770 $recents = getRecentsSince($timestamp, null, '', RECENTS_MEDIA_CHANGES);
772 $changes = array();
774 foreach ($recents as $recent) {
775 $change = array();
776 $change['name'] = $recent['id'];
777 $change['lastModified'] = new IXR_Date($recent['date']);
778 $change['author'] = $recent['user'];
779 $change['version'] = $recent['date'];
780 $change['perms'] = $recent['perms'];
781 $change['size'] = @filesize(mediaFN($recent['id']));
782 array_push($changes, $change);
785 if (!empty($changes)) {
786 return $changes;
787 } else {
788 // in case we still have nothing at this point
789 return new IXR_Error(30, 'There are no changes in the specified timeframe');
794 * Returns a list of available revisions of a given wiki page
796 * @author Michael Klier <chi@chimeric.de>
798 function pageVersions($id, $first) {
799 global $conf;
801 $versions = array();
803 if(empty($id))
804 return new IXR_Error(1, 'Empty page ID');
806 require_once(DOKU_INC.'inc/changelog.php');
808 $revisions = getRevisions($id, $first, $conf['recent']+1);
810 if(count($revisions)==0 && $first!=0) {
811 $first=0;
812 $revisions = getRevisions($id, $first, $conf['recent']+1);
815 if(count($revisions)>0 && $first==0) {
816 array_unshift($revisions, ''); // include current revision
817 array_pop($revisions); // remove extra log entry
820 $hasNext = false;
821 if(count($revisions)>$conf['recent']) {
822 $hasNext = true;
823 array_pop($revisions); // remove extra log entry
826 if(!empty($revisions)) {
827 foreach($revisions as $rev) {
828 $file = wikiFN($id,$rev);
829 $time = @filemtime($file);
830 // we check if the page actually exists, if this is not the
831 // case this can lead to less pages being returned than
832 // specified via $conf['recent']
833 if($time){
834 $info = getRevisionInfo($id, $time, 1024);
835 if(!empty($info)) {
836 $data['user'] = $info['user'];
837 $data['ip'] = $info['ip'];
838 $data['type'] = $info['type'];
839 $data['sum'] = $info['sum'];
840 $data['modified'] = new IXR_Date($info['date']);
841 $data['version'] = $info['date'];
842 array_push($versions, $data);
846 return $versions;
847 } else {
848 return array();
853 * The version of Wiki RPC API supported
855 function wiki_RPCVersion(){
856 return 2;
861 * Locks or unlocks a given batch of pages
863 * Give an associative array with two keys: lock and unlock. Both should contain a
864 * list of pages to lock or unlock
866 * Returns an associative array with the keys locked, lockfail, unlocked and
867 * unlockfail, each containing lists of pages.
869 function setLocks($set){
870 $locked = array();
871 $lockfail = array();
872 $unlocked = array();
873 $unlockfail = array();
875 foreach((array) $set['lock'] as $id){
876 if(checklock($id)){
877 $lockfail[] = $id;
878 }else{
879 lock($id);
880 $locked[] = $id;
884 foreach((array) $set['unlock'] as $id){
885 if(unlock($id)){
886 $unlocked[] = $id;
887 }else{
888 $unlockfail[] = $id;
892 return array(
893 'locked' => $locked,
894 'lockfail' => $lockfail,
895 'unlocked' => $unlocked,
896 'unlockfail' => $unlockfail,
900 function getAPIVersion(){
901 return DOKU_XMLRPC_API_VERSION;
904 function login($user,$pass){
905 global $conf;
906 global $auth;
907 if(!$conf['useacl']) return 0;
908 if(!$auth) return 0;
909 if($auth->canDo('external')){
910 return $auth->trustExternal($user,$pass,false);
911 }else{
912 return auth_login($user,$pass,false,true);
919 $server = new dokuwiki_xmlrpc_server();
921 // vim:ts=4:sw=4:et:enc=utf-8: