2 // $Id: RPC2.php,v 1.2 2002-09-04 19:33:36 dairiki Exp $
3 /* Copyright (C) 2002, Lawrence Akka <lakka@users.sourceforge.net>
7 * This file is part of PhpWiki.
9 * PhpWiki is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * PhpWiki is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with PhpWiki; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * LIBRARY USED - POSSIBLE PROBLEMS
24 * ================================
26 * This file provides an XML-RPC interface for PhpWiki. It uses the XML-RPC
27 * library for PHP by Edd Dumbill - see http://xmlrpc.usefulinc.com/php.html
30 * PHP >= 4.1.0 includes experimental support for the xmlrpc-epi c library
31 * written by Dan Libby (see http://uk2.php.net/manual/en/ref.xmlrpc.php). This
32 * is not compiled into PHP by default. If it *is* compiled into your installation
33 * (ie you have --with-xmlrpc) there may well be namespace conflicts with the xml-rpc
34 * library used by this code, and you will get errors.
36 * INTERFACE SPECIFICTION
37 * ======================
39 * The interface specification is that discussed at
40 * http://www.ecyrd.com/JSPWiki/Wiki.jsp?page=WikiRPCInterface
42 * See also http://www.usemod.com/cgi-bin/mb.pl?XmlRpc
44 * NB: All XMLRPC methods should be prefixed with "wiki."
51 // Remove all warnings from xmlrpc.inc
52 // Return list of external links in listLinks
55 // Intercept GET requests from confused users. Only POST is allowed here!
56 // There is some indication that $HTTP_SERVER_VARS is deprecated in php > 4.1.0
57 // in favour of $_Server, but as far as I know, it still works.
58 if ($HTTP_SERVER_VARS['REQUEST_METHOD'] != "POST")
60 die('This is the address of the XML-RPC interface.' .
61 ' You must use XML-RPC calls to access information here');
64 // Include the php XML-RPC library
65 include("lib/XMLRPC/xmlrpc.inc");
66 include("lib/XMLRPC/xmlrpcs.inc");
68 // Constant defined to indicate to phpwiki that it is being accessed via XML-RPC
69 define ("WIKI_XMLRPC", "true");
71 define ("WIKI_XMLRPC_VERSION", 1);
72 // Start up the main code
73 include_once("index.php");
74 include_once("lib/main.php");
77 * Helper function: Looks up a page revision (most recent by default) in the wiki database
79 * @param xmlrpcmsg $params : string pagename [int version]
80 * @return WikiDB _PageRevision object, or false if no such page
83 function _getPageRevision ($params)
86 $ParamPageName = $params->getParam(0);
87 $ParamVersion = $params->getParam(1);
88 // ?? really need utf8_decode here?
89 $pagename = utf8_decode($ParamPageName->scalarval());
90 $version = ($ParamVersion) ? ($ParamVersion->scalarval()):(0);
91 // FIXME: test for version <=0 ??
92 $dbh = $request->getDbh();
93 if ($dbh->isWikiPage($pagename)) {
94 $page = $dbh->getPage($pagename);
96 $revision = $page->getCurrentRevision();
98 $revision = $page->getRevision($version);
105 // ****************************************************************************
106 // Main API functions follow
107 // ****************************************************************************
111 * int getRPCVersionSupported(): Returns 1 for this version of the API
114 // Method signature: An array of possible signatures. Each signature is
115 // an array of types. The first entry is the return type. The other
116 // entries (if any) are the parameter types
117 $getRPCVersionSupported_sig = array(array($xmlrpcInt));
118 // Doc string: A string containing documentation for the method. The
119 // documentation may contain HTML markup
120 $getRPCVersionSupported_doc = 'Get the version of the wiki API';
122 // The function must be a function in the global scope which services the XML-RPC
124 function getRPCVersionSupported($params)
126 return new xmlrpcresp(new xmlrpcval(WIKI_XMLRPC_VERSION, "int"));
130 * array getRecentChanges(Date timestamp) : Get list of changed pages since
131 * timestamp, which should be in UTC. The result is an array, where each element
133 * name (string) : Name of the page. The name is UTF-8 with URL encoding to make it ASCII.
134 * lastModified (date) : Date of last modification, in UTC.
135 * author (string) : Name of the author (if available). Again, name is UTF-8 with URL encoding.
136 * version (int) : Current version.
137 * A page MAY be specified multiple times. A page MAY NOT be specified multiple
138 * times with the same modification date.
140 $getRecentChanges_sig = array(array($xmlrpcArray, $xmlrpcDateTime));
141 $getRecentChanges_doc = 'Get a list of changed pages since [timestamp]';
143 function getRecentChanges($params)
145 global $request, $xmlrpcerruser;
146 // Get the first parameter as an ISO 8601 date. Assume UTC
147 $encoded_date = $params->getParam(0);
148 $datetime = iso8601_decode($encoded_date->scalarval(), 1);
149 $dbh = $request->getDbh();
151 $iterator = $dbh->mostRecent(array('since' => $datetime));
152 while ($page = $iterator->next()) {
153 // $page contains a WikiDB_PageRevision object
154 // no need to url encode $name, because it is already stored in that format ???
155 $name = new xmlrpcval(utf8_encode($page->getPageName()));
156 $lastmodified = new xmlrpcval(iso8601_encode($page->get('mtime')), "dateTime.iso8601");
157 $author = new xmlrpcval(utf8_encode($page->get('author')));
158 $version = new xmlrpcval($page->getVersion, 'int');
160 // Build an array of xmlrpc structs
161 $pages[] = new xmlrpcval(array('name'=>$name,
162 'lastModified'=>$lastmodified,
164 'version'=>$version),
167 return new xmlrpcresp(new xmlrpcval($pages, "array"));
172 * base64 getPage( String pagename ): Get the raw Wiki text of page, latest version.
173 * Page name must be UTF-8, with URL encoding. Returned value is a binary object,
174 * with UTF-8 encoded page data.
177 $getPage_sig = array(array($xmlrpcBase64, $xmlrpcString));
178 $getPage_doc = 'Get the raw Wiki text of the current version of a page';
180 function getPage($params)
182 global $request, $xmlrpcerruser;
183 $revision = _getPageRevision($params);
186 // fixme : need urlencoding here?
187 $content = ($revision->getPackedContent());
188 return new xmlrpcresp(new xmlrpcval($content, "base64"));
191 // return an errror response
192 return new xmlrpcresp(0, $xmlrpcerruser + 1, "No such page");
199 * base64 getPageVersion( String pagename, int version ): Get the raw Wiki text of page.
200 * Returns UTF-8, expects UTF-8 with URL encoding.
203 $getPageVersion_sig = array(array($xmlrpcBase64, $xmlrpcString, $xmlrpcInt));
204 $getPageVersion_doc = 'Get the raw Wiki text of a page version';
206 function getPageVersion($params)
208 global $request, $xmlrpcerruser;
209 return getPage($params);
210 // error checking is done in getPage
214 * base64 getPageHTML( String pagename ): Return page in rendered HTML.
215 * Returns UTF-8, expects UTF-8 with URL encoding.
218 $getPageHTML_sig = array(array($xmlrpcString, $xmlrpcString));
219 $getPageHTML_doc = 'Get the current version of a page rendered in HTML';
221 function getPageHTML($params)
223 global $request, $xmlrpcerruser;
224 $revision = _getPageRevision($params);
226 include_once('lib/display.php');
227 // This is a bit hacky. Start output buffering, fake a request, and get phpWiki
228 // to render the page. Then return it via XMLRPC.
229 $request->setArg('pagename',$revision->getPageName());
230 $request->setArg('version',$revision->getVersion());
232 displayPage($request);
233 $output = ob_get_contents();
235 // xmlrpc_debugmsg("$output");
236 return new xmlrpcresp(new xmlrpcval(utf8_encode($output), "string"));
239 return new xmlrpcresp(0, $xmlrpcerruser + 1, "No such page");
244 * base64 getPageHTMLVersion( String pagename, int version ): Return page in rendered HTML, UTF-8.
247 $getPageHTMLVersion_sig = array(array($xmlrpcBase64, $xmlrpcString, $xmlrpcInt));
248 $getPageHTMLVersion_doc = 'Get a version of a page rendered in HTML';
250 function getPageHTMLVersion($params)
252 global $request, $xmlrpcerruser;
253 return getPageHTML($params);
257 * getAllPages(): Returns a list of all pages. The result is an array of strings.
260 $getAllPages_sig = array(array($xmlrpcArray));
261 $getAllPages_doc = 'Returns a list of all pages as an array of strings';
263 function getAllPages($params)
265 global $request, $xmlrpcerruser;
266 $dbh = $request->getDbh();
267 $iterator = $dbh->getAllPages();
269 while ($page = $iterator->next()) {
270 $pages[] = new xmlrpcval($page->getName());
272 return new xmlrpcresp(new xmlrpcval($pages, "array"));
276 * struct getPageInfo( string pagename ) : returns a struct with elements:
277 * name (string): the canonical page name
278 * lastModified (date): Last modification date
279 * version (int): current version
280 * author (string): author name
283 $getPageInfo_sig = array(array($xmlrpcStruct, $xmlrpcString));
284 $getPageInfo_doc = 'Gets info about the current version of a page';
286 function getPageInfo($params)
288 global $xmlrpcerruser;
289 $revision = _getPageRevision($params);
291 $name = new xmlrpcval($params->getParam(0));
292 $version = new xmlrpcval ($revision->getVersion(), "int");
293 $lastmodified = new xmlrpcval(iso8601_encode($revision->get('mtime'), 0), "dateTime.iso8601");
294 $author = new xmlrpcval($revision->get('author'));
296 return new xmlrpcresp(new xmlrpcval(array('name' => $name,
297 'lastModified' => $lastmodified,
298 'version' => $version,
299 'author' => $author),
303 return new xmlrpcresp(0, $xmlrpcerruser + 1, "No such page");
308 * struct getPageInfoVersion( string pagename, int version ) : returns a struct just like plain getPageInfo(),
309 * but this time for a specific version.
312 $getPageInfoVersion_sig = array(array($xmlrpcStruct, $xmlrpcString, $xmlrpcInt));
313 $getPageInfoVersion_doc = 'Gets info about a page version';
315 function getPageInfoVersion($params)
317 global $request, $xmlrpcerruser;
318 return getPageInfo($params);
322 /* array listLinks( string pagename ): Lists all links for a given page. The
323 * returned array contains structs, with the following elements:
324 * name (string) : The page name or URL the link is to.
325 * type (int) : The link type. Zero (0) for internal Wiki link,
326 * one (1) for external link (URL - image link, whatever).
329 $listLinks_sig = array(array($xmlrpcArray, $xmlrpcString));
330 $listLinks_doc = 'Lists all links for a given page';
332 function listLinks($params)
334 global $request, $xmlrpcerruser;
335 $ParamPageName = $params->getParam(0);
336 // ?? really need utf8_decode here?
337 $pagename = utf8_decode($ParamPageName->scalarval());
338 $dbh = $request->getDbh();
339 if ($dbh->isWikiPage($pagename)) {
340 $page = $dbh->getPage($pagename);
341 $linkiterator = $page->getLinks();
342 $linkstruct = array();
343 while ($currentpage = $linkiterator->next()) {
344 $currentname = $currentpage->getName();
345 $name = new xmlrpcval($currentname, "string");
346 // NB no clean way to extract a list of external links yet, so
347 // only internal links returned. ie all type 0.
348 $type = new xmlrpcval(0, "int");
349 $linkstruct[] = new xmlrpcval(array('name'=> $name,
353 return new xmlrpcresp(new xmlrpcval ($linkstruct, "array"));
355 return new xmlrpcresp(0, $xmlrpcerruser + 1, "No such page");
358 // Construct the server instance, and set up the despatch map, which maps
359 // the XML-RPC methods onto the wiki functions
360 $s = new xmlrpc_server(array("wiki.getRPCVersionSupported" =>
361 array("function" => "getRPCVersionSupported",
362 "signature" => $getRPCVersionSupported_sig,
363 "docstring" => $getRPCVersionSupported_doc),
364 "wiki.getRecentChanges" =>
365 array("function" => "getRecentChanges",
366 "signature" => $getRecentChanges_sig,
367 "docstring" => $getRecentChanges_doc),
369 array("function" => "getPage",
370 "signature" => $getPage_sig,
371 "docstring" => $getPage_doc),
372 "wiki.getPageVersion" =>
373 array("function" => "getPageVersion",
374 "signature" => $getPageVersion_sig,
375 "docstring" => $getPageVersion_doc),
376 "wiki.getPageHTML" =>
377 array("function" => "getPageHTML",
378 "signature" => $getPageHTML_sig,
379 "docstring" => $getPageHTML_doc),
380 "wiki.getPageHTMLVersion" =>
381 array("function" => "getPageHTMLVersion",
382 "signature" => $getPageHTMLVersion_sig,
383 "docstring" => $getPageHTMLVersion_doc),
384 "wiki.getAllPages" =>
385 array("function" => "getAllPages",
386 "signature" => $getAllPages_sig,
387 "docstring" => $getAllPages_doc),
388 "wiki.getPageInfo" =>
389 array("function" => "getPageInfo",
390 "signature" => $getPageInfo_sig,
391 "docstring" => $getPageInfo_doc),
392 "wiki.getPageInfoVersion" =>
393 array("function" => "getPageInfoVersion",
394 "signature" => $getPageInfoVersion_sig,
395 "docstring" => $getPageInfoVersion_doc),
397 array("function" => "listLinks",
398 "signature" => $listLinks_sig,
399 "docstring" => $listLinks_doc)
402 // (c-file-style: "gnu")
407 // c-hanging-comment-ender-p: nil
408 // indent-tabs-mode: nil