if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){ ?> } else { ?> } ?>
DokuWiki supports WikiRPCInterface2 Remote Procedure Calls (RPC), speaking the Extensible Markup Language (XML). documented at dokwiki's XMLRPC.
As heavy DokuWiki user I am very interested to make use of this interface for various purposes. Starting with some basics, here is was a “hello world, what's your Dokuwiki version number?” example in PHP. - Now it exercises the DokuWiki and trac RPC interface, includes HTTP basic & digest authentication and HTTPS certificate checking; good enough to start building on top of it..
<?php $dw_host="example.org"; $dw_path="/dokuwiki/"; $dw_user=NULL; $dw_pass=NULL; $dw_opts=array('cert'=>'', 'transport'=>'ssl://', 'port' => 443); $trac_host="example.org"; $trac_path="/trac"; $trac_project="/"; $trac_user=NULL; $trac_pass=NULL; $trac_opts=array('cert'=>'', 'transport'=>'ssl://', 'port' => 443); if (file_exists('dokurpc.conf.php')) require 'dokurpc.conf.php'; # END OF CONFIG ####################################################################### srand(microtime()*1000000); $dw_pass=NULL; # safeguard ;) #$req = xmlrpc_encode_request("dokuwiki.getVersion", array()); $req = xmlrpc_encode_request("wiki.getPageInfo", array("robin:start")); #$req = xmlrpc_encode_request("wiki.getPageInfo", array("wiki:start")); $req = xmlrpc_encode_request("wiki.listLinks", array("wiki:start")); $req = xmlrpc_encode_request("wiki.getBackLinks", array("wiki:start")); $req = xmlrpc_encode_request("wiki.getRecentChanges", array(1219500627)); $req = xmlrpc_encode_request("wiki.getAttachments", array("wiki:", array('recursive'=>true, 'pattern'=>'/dif/'))); $req = xmlrpc_encode_request("wiki.getAllPages", array()); $req = xmlrpc_encode_request("wiki.getPageVersions", array("wiki:start", 0)); $req = xmlrpc_encode_request("wiki.getPageVersion", array("wiki:start", 1214855941)); $res= dokuXmlRpc($req); $req = xmlrpc_encode_request("wiki.putPage", array("wiki:rpctest", $res, "rpc test")); #$res= dokuXmlRpc($req); print_r($res); echo "\n\n"; #$req = xmlrpc_encode_request("wiki.getRPCVersionSupported", array()); #$req = xmlrpc_encode_request("wiki.getAllPages", array()); #$req = xmlrpc_encode_request("system.listMethods", array()); #$req = xmlrpc_encode_request("wiki.getPageInfo", array("TracGuide")); $req = xmlrpc_encode_request("wiki.getPage", array("TracGuide", 1)); $res= tracXmlRpc($req); print_r($res); ######################################################################## # XML-RPC ## function tracXmlRpc($request) { global $trac_host, $trac_project, $trac_path, $trac_user, $trac_pass, $trac_opts; $path=$trac_path.'/'.$trac_project.'/login/xmlrpc'; $x = httpPost($trac_host, $path, $request, $trac_opts, array('username'=>$trac_user, 'password'=>$trac_pass)); return parseXmlRpcResponse($x); } function dokuXmlRpc($request) { global $dw_host, $dw_path, $dw_user, $dw_pass, $dw_opts; $path=$dw_path.'lib/exe/xmlrpc.php?'; if ($dw_user) $path.='u='.urlencode($dw_user).'&'; if ($dw_pass) $path.='p='.urlencode($dw_pass).'&'; $path=preg_replace('![?&]$!', '', $path); $x = httpPost($dw_host, $path, $request, $dw_opts); return parseXmlRpcResponse($x); } function parseXmlRpcResponse($x) { $response = xmlrpc_decode($x); if (xmlrpc_is_fault($response)) { trigger_error("xmlrpc: $response[faultString] ($response[faultCode])"); } return($response); } /*********************************************************************** * HTTP[s] POST request * * $host: hostname ; eg 'example.org' * $path: request' eg '/index.php?id=123' * $data_to_send : data to POST after the HTTP header. * * @param $host: hostname ; eg 'example.org' * @param $path: request' eg '/index.php?id=123' * @param $data_to_send : data to POST after the HTTP header. * @param $opts various transport layer options (ssl, port, cert,..) * @param $auth optional username, password and type ('basic', 'nodigest') * @param $head custom http header * if $opts is an empty array() a standard HTTP to port 80 request is performed. * * set auth['type']='basic' to use plain-text auth, * digest-auth will be handled automatically if $auth['username'] is set and a 401 * status is encountered. - use auth['type']='nodigest' to override. * **/ function httpPost($host, $path, $data_to_send, $opts=array('cert'=>"", 'transport' =>'ssl://', 'port'=>443, 'headers'=>0), $auth=array('username'=>"", 'password'=>"", 'type'=>""), $head=array('Content-type' =>'text/xml') ){ $transport=''; $port=80; if (!empty($opts['transport'])) $transport=$opts['transport']; if (!empty($opts['port'])) $port=$opts['port']; $remote=$transport.$host.':'.$port; $context = stream_context_create(); $result = stream_context_set_option($context, 'ssl', 'verify_host', true); if (!empty($opts['cert'])) { $result = stream_context_set_option($context, 'ssl', 'cafile', $opts['cert']); $result = stream_context_set_option($context, 'ssl', 'verify_peer', true); } else { $result = stream_context_set_option($context, 'ssl', 'allow_self_signed', true); } $fp = stream_socket_client($remote, $err, $errstr, 60, STREAM_CLIENT_CONNECT, $context); if (!$fp) { trigger_error('httpPost error: '.$errstr); return NULL; } $req=''; $req.="POST $path HTTP/1.1\r\n"; $req.="Host: $host\r\n"; if ($auth['type']=='basic' && !empty($auth['username'])) { $req.="Authorization: Basic "; $req.=base64_encode($auth['username'].':'.$auth['password'])."\r\n"; } elseif ($auth['type']=='digest' && !empty($auth['username'])) { $req.='Authorization: Digest '; foreach ($auth as $k => $v) { if (empty($k) || empty($v)) continue; if ($k=='password') continue; $req.=$k.'="'.$v.'", '; } $req.="\r\n"; } foreach ($head as $k => $v) { $req.=$k.': '.$v."\r\n"; } if (empty($head['Content-type'])) { $ct='text/xml'; $req.="Content-type: $ct\r\n"; } $req.='Content-length: '. strlen($data_to_send) ."\r\n"; $req.="Connection: close\r\n\r\n"; fputs($fp, $req); fputs($fp, $data_to_send); while(!feof($fp)) { $res .= fgets($fp, 128); } fclose($fp); if ($auth['type']!='nodigest' && !empty($auth['username']) && $auth['type']!='digest' # prev. digest AUTH failed. && preg_match("/^HTTP\/[0-9\.]* 401 /", $res)) { if (1 == preg_match("/WWW-Authenticate: Digest ([^\n\r]*)\r\n/Us", $res, $matches)) { foreach (split(",", $matches[1]) as $i) { $ii=split("=",trim($i),2); if (!empty($ii[1]) && !empty($ii[0])) { $auth[$ii[0]]=preg_replace("/^\"/",'', preg_replace("/\"$/",'', $ii[1])); } } $auth['type']='digest'; $auth['uri']='https://'.$host.$path; $auth['cnonce']=randomNonce(); $auth['nc']=1; $a1=md5($auth['username'].':'.$auth['realm'].':'.$auth['password']); $a2=md5('POST'.':'.$auth['uri']); $auth['response']=md5($a1.':'.$auth['nonce'].':'.$auth['nc'].':'.$auth['cnonce'].':'.$auth['qop'].':'.$a2); return httpPost($host, $path, $data_to_send, $opts, $auth); } } if (1 != preg_match("/^HTTP\/[0-9\.]* ([0-9]{3}) ([^\r\n]*)/", $res, $matches)) { trigger_error('httpPost: invalid HTTP reply.'); return NULL; } if (1 != preg_match("/^2[0-9]{2}$/", $matches[1])) { trigger_error('httpPost: HTTP error: '.$matches[1].' '.$matches[2]); return NULL; } if (!$opts['headers']) { $res=preg_replace("/^.*\r\n\r\n/Us",'',$res); } return $res; } function randomNonce($len=0) { $chars = "ABCDEFGHIJKMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz023456789"; $i=0; $rv=''; if ($len < 1) $len= (6+rand()%10); while ($i++ < $len) { $rv.=$chars[rand() % strlen($chars)]; } return $rv; } // vi: set sw=2 ts=4 sts=4 et :
Just googled for more example code. obviously there's plenty eg. http://snippets.dzone.com/tag/xmlrpc and I found this nice blog on the way: dokuwimki I'm gonna get side tracked.