Wikka : RESTHandler

HomePage :: Categories :: Index :: Changes :: Comments :: Documentation :: Blog :: Login/Register
Most recent edit on 2008-06-30 17:15:14 by DomBonj [1.1.6.5 compatibility]

Additions:
- Wikka 1.1.6.4 & 1.1.6.5
2. In wikka.php, go to line 378 [version 1.1.6.4 only] or to line 385 [version 1.1.6.5 only] and replace the following code block:


Deletions:
- Wikka 1.1.6.4
2. In wikka.php, go to line 378 and replace the following code block:




Edited on 2008-06-22 10:01:30 by DomBonj [added PHP version check to Wakka.class.php]

Additions:
$output = (version_compare(PHP_VERSION, '5.0.0', '<')) ? '<Error>Unsupported: requires PHP version 5.0.0 or higher</Error>' : $this->Method('rest');
print ($output);


Deletions:
print($this->Method('rest'));




Edited on 2008-06-20 15:30:15 by DomBonj [v0.94: replaced empty parameter with '*' for mod_rewrite compatibity; HTTP status codes; error messa]

Additions:
# @version 0.94 # @output returns a XML document formatted as a UTF-8 string
# @uses Wakka::Format()
if (!defined('REST_ERROR_NOT_SUPPORTED')) define('REST_ERROR_NOT_SUPPORTED', 'MethodUnsupported');
if (!defined('REST_ERROR_SYNTAX')) define('REST_ERROR_SYNTAX', 'SyntaxError');
if (!defined('REST_ERROR_BAD_PARAMETERS')) define('REST_ERROR_BAD_PARAMETERS', 'IllegalParameters');
if (!defined('REST_ERROR_XPATH_FAILURE')) define('REST_ERROR_XPATH_FAILURE', 'XPathFailure');
if (!defined('REST_FORMAT_ERROR_MSG')) define('REST_FORMAT_ERROR_MSG', '<Error><Code>%s</Code><Message>%s</Message><Resource>%s %s</Resource></Error>');
$REST_RETURN_CODES_ARRAY = array(
'MethodUnsupported' => array('Method not supported', 'HTTP/1.1 501 Not Implemented'),
'SyntaxError' => array('Could not parse request string', 'HTTP/1.1 400 Bad Request'),
'IllegalParameters' => array('Illegal parameter(s) value', 'HTTP/1.1 400 Bad Request'),
'XPathFailure' => array('Could not process query', 'HTTP/1.1 500 Server Error')
);
function numeric_html_entities($string)
function uri_suffix_to_xpath_request(array $params)
$tag = isset($params[1]) ? ($params[1]!='*' ? $params[1] : ) : ;
$attr = isset($params[3]) ? ($params[3]!='*' ? $params[3] : ) : ;
$val = isset($params[5]) ? ($params[5]!='*' ? $params[5] : ) : ;
|| (!preg_match('/^([1-9][0-9]*)?$/', $rank))
$error_code = REST_ERROR_BAD_PARAMETERS;
$xpath .= $attr ? (($val ? '[contains(concat(concat(" ", @'. $attr. '), " "), concat(concat(" ", \. $val .'\'), " "))]' : '[@'. $attr .']')) : ;
$error_code = ;
return(array($xpath, $rank, $error_code));
if ($_SERVER['REQUEST_METHOD'] != 'GET')
{ not supported
$error_code = REST_ERROR_NOT_SUPPORTED;
elseif (preg_match('/^([a-zA-Z_\*][A-Za-z0-9:_\-\.]*)?(\/([a-zA-Z_*][A-Za-z0-9:_\-\.]*)?(\/([^\/]*))?(\/([^\/]*))?)?/', $this->RESTreq, $matches))
list($xpath_req, $rank, $error_code) = uri_suffix_to_xpath_request($matches);
$error_code = REST_ERROR_SYNTAX;
if (!$error_code)
$my_page = '<div class="page">'. "\n";
$my_page .= '<div style="clear: both"></div>'. "\n";
$error_code = REST_ERROR_XPATH_FAILURE;
if ($error_code)
{ send 'Status' HTTP Header
header($REST_RETURN_CODES_ARRAY[$error_code][1]);
$output = sprintf(REST_FORMAT_ERROR_MSG, $error_code, $REST_RETURN_CODES_ARRAY[$error_code][0], $_SERVER['REQUEST_METHOD'], numeric_html_entities($this->RESTreq));
$output = '<wikkapage>'. $output .'</wikkapage>';
the 'Content-Type' HTTP Header is sent in libs/Wakka.class.php
print ('<?xml version="1.0" encoding="utf-8" ?>'. "\n". $output);


Deletions:
# @version 0.93 # @output returns a UTF-8 string (empty if no match)
function numeric_html_entities ($string)
function uri_suffix_to_xpath_request (array $params)
$tag = isset($params[1]) ? $params[1] : ;
$attr = isset($params[3]) ? $params[3] : ;
$val = isset($params[5]) ? $params[5] : ;
|| (!preg_match('/^[0-9]*$/', $rank))
$xpath .= $attr ? ('[@'. $attr .($val ? '=\.$val.'\ : ) .']') : ;
return(array($xpath, $rank));
if (preg_match('/^([a-zA-Z_][A-Za-z0-9:_\-\.]*)?(\/([a-zA-Z_][A-Za-z0-9:_\-\.]*)?(\/([^\/]*))?(\/([^\/]*))?)?/', $this->RESTreq, $matches))
list($xpath_req, $rank) = uri_suffix_to_xpath_request($matches);
if ($xpath_req)
$my_page = '<div class="page">'."\n";
$my_page .= '<div style="clear: both"></div>'."\n";
{ silent failure
$output = ;
HTTP Header is sent in libs/Wakka.class.php
if ($output)
echo ('<page>'. $output .'</page>');
else error message ?




Edited on 2008-06-09 16:18:00 by DomBonj [v0.93: bugfix: HTTP header sent twice; XML cleaning]

Additions:
# @version 0.93 # @uses Wakka::Href()
if a '< ?xml version="1.0"? >' first line has been added, remove it
$output = preg_replace('/^\<\?xml[^\>]*?\>/i', , $output);
HTTP Header is sent in libs/Wakka.class.php
if ($output)
echo ('<page>'. $output .'</page>');
else error message ?
header("Content-Type: text/xml; charset=utf-8");


Deletions:
# @version 0.92
Header("Content-Type: text/xml; charset=utf-8");
echo ('<page>'. $output .'</page>');




Edited on 2008-06-08 08:49:45 by DomBonj [v0.92: bugfix]

Additions:
# @version 0.92
Header("Content-Type: text/xml; charset=utf-8");
echo ('<page>'. $output .'</page>');


Deletions:
# @version 0.91
echo ($output);




Oldest known version of this page was edited on 2008-06-08 07:57:31 by DomBonj [v0.91: first upload]
Page view:

REST Handler

See also:
- Documentation: RESTHandlerInfo
works with:
- Wikka 1.1.6.4
NOT included in any Wikka version
This is the development page for the REST handler.

Installation

- Save the first code block below as handlers/page/rest.php
- Give it the same file permissions as the other php files in that directory
- Modify wikka.php as shown on the second code block below
- Modify libs/Wakka.class.php as shown on the third code block below

Code


1. New handlers/page/rest.php file

<?php
#
# Selects and returns the requested XML chunk(s) of the page
#
# @package      Handlers
# @name         REST
#
# @authors      DomBonj
#
# @version      0.91
#
# @input        Parameters in URL : [tag][/attr[/value]]
#                    if attr = index, value must be an integer
#
# @output        returns a UTF-8 string (empty if no match)
#
# @uses            Wakka::HasAccess()
#

function numeric_html_entities ($string)
{
    $trans_tbl1 = get_html_translation_table(HTML_ENTITIES);
    foreach ($trans_tbl1 as $ascii => $html_entity)
    {
        $trans_tbl2[$html_entity] = '&#'. ord($ascii) .';';
        $trans_tbl3[$ascii] = '&#'. ord($ascii) .';';
    }
    // keep XML entities
    unset($trans_tbl3['<']);
    unset($trans_tbl3['>']);
    unset($trans_tbl3['"']);
    unset($trans_tbl3['\'']);
    unset($trans_tbl3['&']);
    $ret = strtr (strtr ($string, $trans_tbl2), $trans_tbl3);
    // translate '&' character if not part of a numeric entity
    $ret = preg_replace('/&(?!#[x]?[0-9a-f]+;)/i', '&amp;', $ret);
    return($ret);
}

function uri_suffix_to_xpath_request (array $params)
{ // empty return value means parameter error
    $tag = isset($params[1]) ? $params[1] : '';
    $attr = isset($params[3]) ? $params[3] : '';
    $val = isset($params[5]) ? $params[5] : '';
    $rank = isset($params[7]) ? $params[7] : '';
    if ((($val != '') && ($attr == ''))
        || (!preg_match('/^[0-9]*$/', $rank))
        || (($tag == '') && ($attr == '') && ($rank !== '')) )
    { // semantically incorrect request
        $xpath = '';
    }
    else
    { // correct request
        $xpath = $tag ? ('//'. $tag) : ((!$attr && !$val) ? '/*' : '//*');
        $xpath .= $attr ? ('[@'. $attr .($val ? '=\''.$val.'\'' : '') .']') : '';
    }
    return(array($xpath, $rank));
}
   
if ($this->HasAccess('read') && $this->page)
{
    if (preg_match('/^([a-zA-Z_][A-Za-z0-9:_\-\.]*)?(\/([a-zA-Z_][A-Za-z0-9:_\-\.]*)?(\/([^\/]*))?(\/([^\/]*))?)?/', $this->RESTreq, $matches))
    { // well-formed request
        list($xpath_req, $rank) = uri_suffix_to_xpath_request($matches);
    }
    else
    { // syntactically incorrect request
        $xpath_req = '';
    }

    if ($xpath_req)
    { // build (x)html page. This code block is supposed to output the same html as the 'show' handler (bar transcoding)
        $my_page = '<div class="page">'."\n";
        $my_page .= $this->Format($this->page['body'], 'wakka');
        $my_page .= '<div style="clear: both"></div>'."\n";
        // Footnote action
        if (function_exists('FNprint'))
        {
            $my_page .= (FNprint($this, 'list', '', $this->Href()));
        }
        $my_page .= '</div>'."\n";
        $my_page = utf8_encode(numeric_html_entities($my_page));
   
        $output = '';   
        try
        { // suppress WARNING messages
            $xml = new SimpleXMLElement($my_page, LIBXML_NOERROR);
        }
        catch (Exception $e)
        { // $xml is NULL
        }
        if ($xml)
        {
            $cnt_obj = 1;
            foreach ($xml->xpath($xpath_req) as $xml_obj)
            {
                if ($rank === '')
                { // false if $rank=0
                    $output .= $xml_obj->asXML() ."\n";
                }
                elseif ($cnt_obj++ == (int)$rank)
                { // only keep object #rank
                    $output = $xml_obj->asXML() ."\n";
                }
            }
        }
    }
    else
    { // silent failure
        $output = '';
    }
    echo ($output);
}
?>

2. In wikka.php, go to line 378 and replace the following code block:

if (!preg_match("/(xml|raw|mm|grabcode)$/", $method))
{

with the following code block:

if ((!preg_match("/(xml|raw|mm|grabcode)$/", $method)) && (!preg_match("/^rest(\W|$)/", $method)))
{

3. In libs/Wakka.class.php, go to line 1743 and replace the following code block:

// raw page handler
elseif ($this->method == "raw")
{
    header("Content-type: text/plain");
    print($this->Method($this->method));
}
// grabcode page handler
 

with the following code block:

// raw page handler
elseif ($this->method == "raw")
{
    header("Content-type: text/plain");
    print($this->Method($this->method));
}
// REST handler
elseif (preg_match('/^rest(\W|$)/', $this->method))
{
    preg_match('/^rest(\/(.*))?/', $this->method, $matches);
    header("Content-type: text/plain");
    $this->RESTreq = $matches[2];
    print($this->Method('rest'));
}
// grabcode page handler
 
Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by WikkaWiki
Page was generated in 0.4783 seconds