Difference between revisions of "Xmlwiki.php"

From Organic Design wiki
Line 128: Line 128:
 
$xwSave = $xwEdit = false;
 
$xwSave = $xwEdit = false;
 
$wgTitle = Title::newFromText('Sorry, the requested article was not readable.');
 
$wgTitle = Title::newFromText('Sorry, the requested article was not readable.');
 +
}
 +
 +
 +
# ---------------------------------------------------------------------------------------------------------------------- #
 +
# INPUT HOOK
 +
 +
# Parse and process input from forms
 +
function xwInputHook() {
 +
 +
global $xwArticle, $xwArticleXML, $xwArticleTitle, $xwWritable, $_REQUEST;
 +
global $xwDebug, $xwSave, $xwEdit, $action, $xwUserName, $wgArticle;
 +
if ($xwDebug) xwMessage('xwInputHook()','green');
 +
 +
# If not writable, change action to view
 +
if (!$xwWritable && ($action != 'view')) {
 +
xwMessage('Sorry, article not writable, action changed to "view".', 'red');
 +
$action = 'view';
 +
$xwSave = $xwEdit = false;
 +
}
 +
 +
# Parse POST for XPath inputs
 +
# - Form-input-name is "xw:[[@]node]:XPathQuery" which directs the value into xwArticle (if DOM)
 +
# - if "node" exists, then a new element (or att if "@node") is created for the value
 +
# - hidden-inputs can direct input-handlers into the transform list
 +
foreach ($_REQUEST as $k => $v) {
 +
if (is_object($xwArticleXML) && preg_match("/^xw:(@?)(\\w*):(.+)$/", $k, $m)) {
 +
list(, $att, $node, $xpath) = $m;
 +
foreach (xwXPathQuery($xwArticleXML, $xpath) as $result)
 +
if ($node) {
 +
# create new element/attribute in result-node
 +
if ($att) $node = $xwArticleXML->create_attribute($node, $v);
 +
else {
 +
$node = $xwArticleXML->create_element($node);
 +
$node->set_content($v);
 +
}
 +
$result->append_child($node);
 +
}
 +
else $result->set_content($v); # node not set, just replace current-result-value
 +
}
 +
}
 +
 +
# if it's a pseudo-namespace...
 +
if (preg_match('/^(xml)|(sys):/', $xwArticleTitle)) {
 +
 +
# wpSave should be valid XML to be saved
 +
if ($xwSave) {
 +
xwDomificate($wpSave);
 +
if (!is_object($wpSave)) {
 +
xwMessage('A meta-article must be valid XML! changing action to "edit"', 'red');
 +
$action='edit';
 +
}
 +
}
 +
 +
}
 +
 +
}
 +
 +
# ---------------------------------------------------------------------------------------------------------------------- #
 +
# OUTPUT HOOK
 +
 +
# Generate output to send back to client
 +
# - if article is not XML, then wiki's parsed content is used
 +
function xwOutputHook() {
 +
 +
global $wgOut, $wgUser, $xwParserHookCalled, $xwSkinHookCalled, $xwDebug;
 +
global $xwArticle, $xwArticleXML, $xwArticleTitle, $xwReadable, $xwWritable;
 +
global $xwView, $xwPreview, $xwSave, $xwRaw, $xwUserLinks, $xwArticleLinks;
 +
if ($xwDebug) xwMessage('xwOutputHook()','green');
 +
 +
# Generate output page
 +
$wgUser->setOption('skin', 'xwskin');
 +
$wgOut->output();
 +
 +
# NOTE - Why not move this into INPUT-HOOK???????? - or maybe not....?
 +
# If saving, check the publishing list
 +
if ($xwSave) {
 +
 +
# Check publish-list and process if any
 +
if (false) {
 +
xwMessage('Publishing...');
 +
# Publish each item
 +
foreach ($xwArticlePublish as $url) {
 +
if ($FH = fopen($url, 'a')) {
 +
# ftp example: ftp://user:password@example.com/file.txt
 +
fwrite($FH, $xwArticle);
 +
fclose($FH);
 +
xwMessage("Article published to $url");
 +
}
 +
else xwMessage("Failed to publish to $url", 'red');
 +
}
 +
}
 +
 +
# Check mirror-list and process if any
 +
# - allows articles in separate wiki's to be syncronised
 +
# - does rudimentary security by sending a salt and response being a hash of the password generated from the salt
 +
# - this could be done for login too using ECMA-MD5 on browser
 +
if (false) {
 +
xwMessage('Mirroring...');
 +
}
 +
}
 +
 +
 +
# Insert messages into final html and output
 +
if ($xwDebug) {
 +
if (!$xwParserHookCalled) xwMessage('PARSER-HOOK was not called','green');
 +
if (!$xwSkinHookCalled) xwMessage('SKIN-HOOK was not called','green');
 +
if (is_object($xwArticleXML)) xwMessage($xwArticleXML->dump_mem(true),'purple');
 +
}
 +
xwAddMessages();
 +
print $xwArticle;
 
}
 
}

Revision as of 22:06, 18 June 2005

<?php

  1. xmlWiki - MediaWiki XML Hack
  2. Nad - 2005-05-18

$xwDebug=1;

  1. INIT
  2. SECURITY
  3. INPUT HOOK
  4. OUTPUT HOOK
  5. PARSER HOOK
  6. SKIN HOOK
  7. ARTICLE FUNCTIONS
  8. UTILITY FUNCTIONS
  1. ---------------------------------------------------------------------------------------------------------------------- #
  1. TODO:
  2. - Undomificate: validation, xslt
  3. - Transform: check perms on php-execution
  4. Publish:
  5. - xml:article - holds article publish-list
  6. - mirror/wiki-sync
  7. Transforms:
  8. - xml:article - now transforms are in here (main article is now like <body>)
  9. - so we don't do the "its one of ours" thing anymore
  1. LATER:
  2. - allow XIncludes to build large docs from others
  3. - allow docBook and DSSSL content
  4. - Maybe only use XML transforms and use PHP via PI's
  1. ---------------------------------------------------------------------------------------------------------------------- #
  2. INIT
  1. Exit if not included from index.php

defined('MEDIAWIKI') or die('xmlwiki.php must be included from MediaWiki\'s index.php!');

  1. Allows Geshi to be installed by PARSER-HOOK if not installed th usual way already

if (!@is_object($wgGeshiSyntaxSettings)) $wgGeshiSyntaxSettings = false;

  1. Otherwise set up xmlWiki global environment ready for input and output processing

$xwMessages = array(); $xwEdit = isset($_REQUEST['action']) && ($_REQUEST['action'] == 'edit'); $xwView = (!isset($_REQUEST['action']) || (isset($_REQUEST['action']) && ($_REQUEST['action'] == 'view'))); $xwRaw = isset($_REQUEST['action']) && ($_REQUEST['action'] == 'raw'); $xwPreview = isset($_REQUEST['wpPreview']); $xwSave = isset($_REQUEST['wpSave']); $xwUserName = $wgUser->mName; $xwUserGroups = array(strtolower($xwUserName), 'anyone', 'everyone', 'nobody', 'world'); $xwArticleReadableBy = array('anyone'); $xwArticleWritableBy = array('anyone'); $xwArticle = $xwPreview ? $wgRequest->gettext('wpTextbox1') : $wgArticle->getContent(false); $xwArticleTitle = $wgTitle->getPrefixedURL(); $xwArticleCache = array(); $xwArticleLinks = array(); $xwUserLinks = array(); $xwMetaArticle = false; $xwMsgToken = ; $xwTemplate = null; $xwParserHookCalled = false; $xwSkinHookCalled = false;

  1. ---------------------------------------------------------------------------------------------------------------------- #
  2. SECURITY
  1. Not currently used: R/W by user, for xmlWiki prefs etc

if ($xwUserXML = xwArticleContent(strtolower("xml:$xwUserName"))) xwDomificateArticle($xwUserXML, "xml:$xwUserName");

  1. R/W by admin only, holds users groups and other system info like stats
  2. - no sys:user means "anyone" in group "everyone" as far as perms goes

if ($xwUserSYS = xwArticleContent(strtolower("sys:$xwUserName"))) xwDomificateArticle($xwUserSYS, "sys:$xwUserName");

  1. If sys:user exists, get users' group-list

if (is_object($xwUserSYS)) { $xwRoot = $xwUserSYS->document_element(); if (count($xwList = $xwRoot->get_elements_by_tagname('groups'))) $xwUserGroups = array_merge($xwUserGroups, split(',', strtolower($xwList[0]->get_content()))); }

  1. - Security info is: owner, read-groups, write-groups (default values are "world")
  2. - Users and groups are interchangeable
  3. - Default user is "anyone", default group is "everyone"

if (ereg('^xml:(.+)$', $xwArticleTitle)) { # This is an xml-pseudo-namespace # - its perms apply to its 'parent' and to itself aswell $xwXML = $xwArticle; xwDomificateArticle($xwXML, $xwArticleTitle); if (is_object($xwXML)) { $xwRoot = $xwXML->document_element(); if (count($xwList = $xwRoot->get_elements_by_tagname('read'))) $xwArticleReadableBy = split(',', strtolower($xwList[0]->get_content())); if (count($xwList = $xwRoot->get_elements_by_tagname('write'))) $xwArticleWritableBy = split(',', strtolower($xwList[0]->get_content())); } } elseif (ereg('^sys:(.+)$', $xwArticleTitle)) { # This is a sys-pseudo-namespace # - only admin can read/write sys: $xwArticleReadableBy = $articleWritableBy = array('admin'); } else { # This is a normal article, get xml:article if ($xwArticleXML = xwArticleContent(strtolower("xml:$xwArticleTitle"))) xwDomificateArticle($xwArticleXML, "xml:$xwArticleTitle"); if (is_object($xwArticleXML)) { $xwRoot = $xwArticleXML->document_element(); if (count($xwList = $xwRoot->get_elements_by_tagname('read'))) $xwArticleReadableBy = split(',', $xwList = strtolower($xwList[0]->get_content())); if (count($xwList = $xwRoot->get_elements_by_tagname('write'))) $xwArticleWritableBy = split(',', $xwList = strtolower($xwList[0]->get_content())); } }

  1. Set perms for this request

$xwReadable = 0 < count(array_intersect($xwArticleReadableBy, $xwUserGroups)); $xwWritable = 0 < count(array_intersect($xwArticleWritableBy, $xwUserGroups)); if ($xwDebug) { xwMessage('Groups: '.join(', ', $xwUserGroups)); xwMessage("Readable ($xwReadable): ".join(', ', $xwArticleReadableBy)); xwMessage("Writable ($xwWritable): ".join(', ', $xwArticleWritableBy)); }

  1. Divert to access-denied article if not readable

if (!$xwReadable) { xwMessage('no'); $action = 'view'; $xwSave = $xwEdit = false; $wgTitle = Title::newFromText('Sorry, the requested article was not readable.'); }


  1. ---------------------------------------------------------------------------------------------------------------------- #
  2. INPUT HOOK
  1. Parse and process input from forms

function xwInputHook() {

global $xwArticle, $xwArticleXML, $xwArticleTitle, $xwWritable, $_REQUEST; global $xwDebug, $xwSave, $xwEdit, $action, $xwUserName, $wgArticle; if ($xwDebug) xwMessage('xwInputHook()','green');

# If not writable, change action to view if (!$xwWritable && ($action != 'view')) { xwMessage('Sorry, article not writable, action changed to "view".', 'red'); $action = 'view'; $xwSave = $xwEdit = false; }

# Parse POST for XPath inputs # - Form-input-name is "xw:[[@]node]:XPathQuery" which directs the value into xwArticle (if DOM) # - if "node" exists, then a new element (or att if "@node") is created for the value # - hidden-inputs can direct input-handlers into the transform list foreach ($_REQUEST as $k => $v) { if (is_object($xwArticleXML) && preg_match("/^xw:(@?)(\\w*):(.+)$/", $k, $m)) { list(, $att, $node, $xpath) = $m; foreach (xwXPathQuery($xwArticleXML, $xpath) as $result) if ($node) { # create new element/attribute in result-node if ($att) $node = $xwArticleXML->create_attribute($node, $v); else { $node = $xwArticleXML->create_element($node); $node->set_content($v); } $result->append_child($node); } else $result->set_content($v); # node not set, just replace current-result-value } }

# if it's a pseudo-namespace... if (preg_match('/^(xml)|(sys):/', $xwArticleTitle)) {

# wpSave should be valid XML to be saved if ($xwSave) { xwDomificate($wpSave); if (!is_object($wpSave)) { xwMessage('A meta-article must be valid XML! changing action to "edit"', 'red'); $action='edit'; } }

}

}

  1. ---------------------------------------------------------------------------------------------------------------------- #
  2. OUTPUT HOOK
  1. Generate output to send back to client
  2. - if article is not XML, then wiki's parsed content is used

function xwOutputHook() {

global $wgOut, $wgUser, $xwParserHookCalled, $xwSkinHookCalled, $xwDebug; global $xwArticle, $xwArticleXML, $xwArticleTitle, $xwReadable, $xwWritable; global $xwView, $xwPreview, $xwSave, $xwRaw, $xwUserLinks, $xwArticleLinks; if ($xwDebug) xwMessage('xwOutputHook()','green');

# Generate output page $wgUser->setOption('skin', 'xwskin'); $wgOut->output();

# NOTE - Why not move this into INPUT-HOOK???????? - or maybe not....? # If saving, check the publishing list if ($xwSave) {

# Check publish-list and process if any if (false) { xwMessage('Publishing...'); # Publish each item foreach ($xwArticlePublish as $url) { if ($FH = fopen($url, 'a')) { # ftp example: ftp://user:password@example.com/file.txt fwrite($FH, $xwArticle); fclose($FH); xwMessage("Article published to $url"); } else xwMessage("Failed to publish to $url", 'red'); } }

# Check mirror-list and process if any # - allows articles in separate wiki's to be syncronised # - does rudimentary security by sending a salt and response being a hash of the password generated from the salt # - this could be done for login too using ECMA-MD5 on browser if (false) { xwMessage('Mirroring...'); } }


# Insert messages into final html and output if ($xwDebug) { if (!$xwParserHookCalled) xwMessage('PARSER-HOOK was not called','green'); if (!$xwSkinHookCalled) xwMessage('SKIN-HOOK was not called','green'); if (is_object($xwArticleXML)) xwMessage($xwArticleXML->dump_mem(true),'purple'); } xwAddMessages(); print $xwArticle; }