Difference between revisions of "Xmlwiki.php"
| Line 238: | Line 238: | ||
xwAddMessages(); | xwAddMessages(); | ||
print $xwArticle; | print $xwArticle; | ||
| + | } | ||
| + | |||
| + | # ---------------------------------------------------------------------------------------------------------------------- # | ||
| + | # PARSER HOOK | ||
| + | |||
| + | function xwParserHook(&$text) { | ||
| + | |||
| + | global $xwRaw, $xwParserHookCalled, $xwDebug, $xwArticleTitle, $xwArticle; | ||
| + | if ($xwDebug) xwMessage('xwParserHook(TEXT)','green'); | ||
| + | $xwParserHookCalled = true; | ||
| + | $transformed = false; | ||
| + | |||
| + | # If this text-fragment is our article, apply transforms | ||
| + | if ((strncmp($text, $xwArticle, 100) == 0) || (strncmp($text, xwArticleContent($xwArticleTitle), 100) == 0)) { | ||
| + | if ($xwDebug) xwMessage("PARSER-HOOK: \"$xwArticleTitle\" text-fragment recognised and intercepted."); | ||
| + | $xwArticle = $text; # needed because xwTransform works on global article | ||
| + | # If attempted xml encountered, try to domificate and transform | ||
| + | if (preg_match("/^<\\?xml/i", $xwArticle)) { | ||
| + | $transformed = true; | ||
| + | xwDomificateArticle($xwArticle, 'ParserHook/text'); | ||
| + | xwTransformArticle(); | ||
| + | } | ||
| + | # If not a 'raw' request, try some Geshi on | ||
| + | if (!$xwRaw) { | ||
| + | global $wgGeshiSyntaxSettings; | ||
| + | if (!is_object($wgGeshiSyntaxSettings)) require_once('extensions/geshi/geshi.php'); | ||
| + | if ($lang = xwArticleType($xwArticleTitle, $xwArticle)) { | ||
| + | if ($xwDebug) xwMessage("Geshi: This is \"$lang\"."); | ||
| + | # Replace tabs with spaces (better than geshi) | ||
| + | $xwArticle = preg_replace_callback("/^(.*?)(\\t+)/m", 'xwReplaceTabs', $xwArticle); | ||
| + | # Set up a geshi-parser | ||
| + | $geshi = new GeSHi($xwArticle, $lang == 'xslt' ? 'xml' : $lang, 'extensions/geshi/geshi'); | ||
| + | $geshi->set_header_type(GESHI_HEADER_DIV); | ||
| + | #$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); | ||
| + | #@$geshi->set_line_style('color:#aaaaaa'); | ||
| + | #@$geshi->set_code_style('color:black'); | ||
| + | @$geshi->set_keyword_group_style(1, 'color:blue', true); | ||
| + | @$geshi->set_keyword_group_style(2, 'color:blue', true); | ||
| + | @$geshi->set_keyword_group_style(3, 'color:blue', true); | ||
| + | @$geshi->set_comments_style(1,'font-style: italic; color:#d00000;',true); | ||
| + | @$geshi->set_comments_style(2,'font-style: italic; color:#d00000;',true); | ||
| + | @$geshi->set_comments_style(3,'font-style: italic; color:#d00000;',true); | ||
| + | @$geshi->set_escape_characters_style('color:red',true); | ||
| + | @$geshi->set_brackets_style('color:black',true); | ||
| + | @$geshi->set_strings_style('color:#008080',true); | ||
| + | @$geshi->set_numbers_style('color:black',true); | ||
| + | @$geshi->set_methods_style('color:black',true); | ||
| + | @$geshi->set_symbols_style('color:black',true); | ||
| + | @$geshi->set_regexps_style('color:green',true); | ||
| + | # Do the parse | ||
| + | $xwArticle = preg_replace("/^<div.*?>/", '<div class="xwcode">', $geshi->parse_code()); | ||
| + | $transformed = true; | ||
| + | } | ||
| + | elseif ($xwDebug) xwMessage('Geshi: Not my problem.'); | ||
| + | } | ||
| + | $text = $xwArticle; | ||
| + | } | ||
| + | elseif ($xwDebug) xwMessage('Parsing other content'); | ||
| + | |||
| + | # Return this back to wiki-parser so it can do wiki-markup if it wasn't one of ours | ||
| + | return $transformed; | ||
| + | } | ||
| + | |||
| + | # Converts tabs to spaces better than geshi | ||
| + | function xwReplaceTabs($m) { return $m[1].str_repeat(' ',strlen($m[2])*4-strlen($m[1])%4); } | ||
| + | |||
| + | # ---------------------------------------------------------------------------------------------------------------------- # | ||
| + | # SKIN HOOK | ||
| + | |||
| + | # If attempted xml encountered, try to domificate and transform | ||
| + | # - Raw requests don't get here | ||
| + | function xwSkinHook(&$tmpl) { | ||
| + | |||
| + | global $xwArticle, $xwTemplate, $xwDebug, $xwSkinHookCalled; | ||
| + | if ($xwDebug) xwMessage('xwSkinHook(TEMPLATE)','green'); | ||
| + | $xwSkinHookCalled = true; | ||
| + | $xwTemplate = $tmpl; | ||
| + | $xwArticle = $xwTemplate->data['bodytext']; | ||
| + | #$xslt = xwArticleContent('xmlwiki.xslt'); | ||
| + | |||
| + | # Do xmlWiki page-layout transform | ||
| + | |||
| + | xwTransformPageLayout(); # should be: xwApplyXSLT($xwArticle, $xslt, 'xmlwiki.xslt'); | ||
| + | |||
} | } | ||
Revision as of 22:07, 18 June 2005
<?php
- xmlWiki - MediaWiki XML Hack
- Nad - 2005-05-18
$xwDebug=1;
- INIT
- SECURITY
- INPUT HOOK
- OUTPUT HOOK
- PARSER HOOK
- SKIN HOOK
- ARTICLE FUNCTIONS
- UTILITY FUNCTIONS
- ---------------------------------------------------------------------------------------------------------------------- #
- TODO:
- - Undomificate: validation, xslt
- - Transform: check perms on php-execution
- Publish:
- - xml:article - holds article publish-list
- - mirror/wiki-sync
- Transforms:
- - xml:article - now transforms are in here (main article is now like <body>)
- - so we don't do the "its one of ours" thing anymore
- LATER:
- - allow XIncludes to build large docs from others
- - allow docBook and DSSSL content
- - Maybe only use XML transforms and use PHP via PI's
- ---------------------------------------------------------------------------------------------------------------------- #
- INIT
- Exit if not included from index.php
defined('MEDIAWIKI') or die('xmlwiki.php must be included from MediaWiki\'s index.php!');
- Allows Geshi to be installed by PARSER-HOOK if not installed th usual way already
if (!@is_object($wgGeshiSyntaxSettings)) $wgGeshiSyntaxSettings = false;
- 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;
- ---------------------------------------------------------------------------------------------------------------------- #
- SECURITY
- Not currently used: R/W by user, for xmlWiki prefs etc
if ($xwUserXML = xwArticleContent(strtolower("xml:$xwUserName"))) xwDomificateArticle($xwUserXML, "xml:$xwUserName");
- R/W by admin only, holds users groups and other system info like stats
- - no sys:user means "anyone" in group "everyone" as far as perms goes
if ($xwUserSYS = xwArticleContent(strtolower("sys:$xwUserName"))) xwDomificateArticle($xwUserSYS, "sys:$xwUserName");
- 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()))); }
- - Security info is: owner, read-groups, write-groups (default values are "world")
- - Users and groups are interchangeable
- - 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())); } }
- 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)); }
- 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.'); }
- ---------------------------------------------------------------------------------------------------------------------- #
- 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;
}
- ---------------------------------------------------------------------------------------------------------------------- #
- PARSER HOOK
function xwParserHook(&$text) {
global $xwRaw, $xwParserHookCalled, $xwDebug, $xwArticleTitle, $xwArticle; if ($xwDebug) xwMessage('xwParserHook(TEXT)','green'); $xwParserHookCalled = true; $transformed = false;
# If this text-fragment is our article, apply transforms if ((strncmp($text, $xwArticle, 100) == 0) || (strncmp($text, xwArticleContent($xwArticleTitle), 100) == 0)) { if ($xwDebug) xwMessage("PARSER-HOOK: \"$xwArticleTitle\" text-fragment recognised and intercepted."); $xwArticle = $text; # needed because xwTransform works on global article # If attempted xml encountered, try to domificate and transform if (preg_match("/^<\\?xml/i", $xwArticle)) { $transformed = true; xwDomificateArticle($xwArticle, 'ParserHook/text'); xwTransformArticle(); } # If not a 'raw' request, try some Geshi on if (!$xwRaw) { global $wgGeshiSyntaxSettings; if (!is_object($wgGeshiSyntaxSettings)) require_once('extensions/geshi/geshi.php'); if ($lang = xwArticleType($xwArticleTitle, $xwArticle)) { if ($xwDebug) xwMessage("Geshi: This is \"$lang\"."); # Replace tabs with spaces (better than geshi) $xwArticle = preg_replace_callback("/^(.*?)(\\t+)/m", 'xwReplaceTabs', $xwArticle); # Set up a geshi-parser $geshi = new GeSHi($xwArticle, $lang == 'xslt' ? 'xml' : $lang, 'extensions/geshi/geshi'); $geshi->set_header_type(GESHI_HEADER_DIV); #$geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); #@$geshi->set_line_style('color:#aaaaaa'); #@$geshi->set_code_style('color:black'); @$geshi->set_keyword_group_style(1, 'color:blue', true); @$geshi->set_keyword_group_style(2, 'color:blue', true); @$geshi->set_keyword_group_style(3, 'color:blue', true); @$geshi->set_comments_style(1,'font-style: italic; color:#d00000;',true); @$geshi->set_comments_style(2,'font-style: italic; color:#d00000;',true); @$geshi->set_comments_style(3,'font-style: italic; color:#d00000;',true); @$geshi->set_escape_characters_style('color:red',true); @$geshi->set_brackets_style('color:black',true); @$geshi->set_strings_style('color:#008080',true); @$geshi->set_numbers_style('color:black',true); @$geshi->set_methods_style('color:black',true); @$geshi->set_symbols_style('color:black',true); @$geshi->set_regexps_style('color:green',true); # Do the parse
$xwArticle = preg_replace("/^<div.*?>/", '
$transformed = true; } elseif ($xwDebug) xwMessage('Geshi: Not my problem.'); } $text = $xwArticle; } elseif ($xwDebug) xwMessage('Parsing other content');
# Return this back to wiki-parser so it can do wiki-markup if it wasn't one of ours return $transformed; }
- Converts tabs to spaces better than geshi
function xwReplaceTabs($m) { return $m[1].str_repeat(' ',strlen($m[2])*4-strlen($m[1])%4); }
- ---------------------------------------------------------------------------------------------------------------------- #
- SKIN HOOK
- If attempted xml encountered, try to domificate and transform
- - Raw requests don't get here
function xwSkinHook(&$tmpl) {
global $xwArticle, $xwTemplate, $xwDebug, $xwSkinHookCalled; if ($xwDebug) xwMessage('xwSkinHook(TEMPLATE)','green'); $xwSkinHookCalled = true; $xwTemplate = $tmpl; $xwArticle = $xwTemplate->data['bodytext']; #$xslt = xwArticleContent('xmlwiki.xslt');
# Do xmlWiki page-layout transform
xwTransformPageLayout(); # should be: xwApplyXSLT($xwArticle, $xslt, 'xmlwiki.xslt');
}



