EnableHTML

<< BuildForms | Forms-related | Forms >>

Summary: How to include HTML markup in wiki pages
Version:
Prerequisites:
Status:
Users: +2 (view / edit)
Maintainer:
Discussion: EnableHTML-Talk
Categories: Forms, Markup

Question

Is it possible to include HTML markup in wiki pages?

Answer

By default (and by design), PmWiki does not support the use of HTML elements in the editable markup for wiki pages. There are a number of reasons for this described in the PmWikiPhilosophy and PmWiki.Audiences. Basically, Pm feels that enabling HTML markup within wiki pages in a collaborative environment has the effect of excluding some potential authors from being able to edit pages, as well as posing a number of display and security issues. Indeed, for complex markup sequences it's often better to design a CustomMarkup to provide the desired functionality, as this allows things to be easily customized and changed in the future without having to re-edit a lot of pages.

There's also a security issue involved with that. If visitors can add elements such as <script> and <meta>, or insert CSS styles for positioning or coloring text, this may have unwanted side-effects and even pose threats to browser and user security. See http://www.cert.org/advisories/CA-2000-02.html for additional information on the types of risks this may pose.

However, there are a number of administrative pages where only selected people have edit passwords. It's entirely reasonable to unlock as much power as can be trusted to them, and as much complexity as they are willing to handle.

So for those cases where this is warranted, here is how to do it:

Install enablehtml.phpΔ into your cookbook directory.

Edit your local/config.php and add the following line:

  include_once("$FarmD/cookbook/enablehtml.php");

This will give you a new function EnableHtml($tag) for your config.php that will make PmWiki allow through any HTML tags that are listed in $tag. Examples:

  
  EnableHtml('img');
  EnableHtml('b|i|u|sup|sub|a|iframe|small');
  

You can also allow HTML comment tags via

  
  EnableHtml('!');
  

Here's a version that will work with php5.5. (the existing version will break with deprecation errors.

function EnableHtml($tag) {
  Markup_e(
  "html-$tag",
  '>{$var}',
  '/&lt;(\/?('.$tag.')(?![a-z!])(([\'"]).*?\4|.*?)*?)&gt;/i',
  'Keep(\'<\'.$m[1].\'>\')');
}

Here's the code for it if for any reason the download-link does not work. (Just put it in your cookbook/ as a text file of your own, naming the file enablehtml.php, and carry on with the instructions below):

<?php if (!defined('PmWiki')) exit();
function EnableHtml($tag) {
Markup(
"html-$tag",
'>{$var}',
'/&lt;(\/?('.$tag.')(?![a-z!])(([\'"]).*?\4|.*?)*?)&gt;/ie',
'Keep(PSS(\'<$1>\'))');
}

HTH - it's the best I can do -- TeganDowling

Same code as presented, but this one works with linebreaks enabled in config.php (e.g. $HTMLPNewline = '<br />'; ) and allows all html tags:

<?php if (!defined('PmWiki')) exit();

$HTMLPNewline = '<br />'; 
Markup(
"html-allow",
'>{$var}',
'/&lt;(\/?([\w]+)(?![a-z!])(([\'"]).*?\4|.*?)*?)&gt;/ie',
"'<:block>'.Keep(PSS('<$1>'))"
);

Not secure!!! I only use it for my personal wiki. MikeStopContinues

As an option, here's some text combining info from two other pages. I like it because you can enable it sitewide, and anyone who is not an admin will have their html disabled when they save. Easy to use! Caveman

Markup('html', 'fulltext', '/\\(:html:\\)(.*?)\\(:htmlend:\\)/esi',
  "'<:block>'.Keep(str_replace(array('&gt;','&lt;','&amp;'), array('>','<','&'), PSS('$1')))");

array_unshift($EditFunctions, 'MaybeDisableHtml');
function MaybeDisableHtml($pagename,&$page,&$new)
{ if (!CondAuth($pagename,"admin"))
  { $ROSPatterns["/\\(:html:\\)/i"] = "[:html:]";
    $ROSPatterns["/\\(:htmlend:\\)/i"] = "[:htmlend:]";
  }
}

Sorry, but this doesn't work! cg 2008-08-28

It works for me, but I use the following:

Markup('html', 'fulltext', '/\\(:html:\\)(.*?)\\(:htmlend:\\)/esi',
  "'<:block>'.Keep(str_replace(array('&gt;','&lt;','&amp;'), array('>','<','&'), PSS('$1')))");

if (!CondAuth($pagename,"admin"))
  { $ROSPatterns["/\\(:html:\\)/i"] = "[:html:]";
    $ROSPatterns["/\\(:htmlend:\\)/i"] = "[:htmlend:]";
  }

Which version you use depends on where you put the condition in your local/config.php or local/farmconfig.php file.

See this mailing list discussion for more details.

Matt L? August 31, 2008, at 09:27 AM

This is a consolidation of some tips on the EnableHTML-Talk page. It enables raw HTML between (:html:) and (:htmlend:) tags only if the page is saved by somebody with admin privileges. Cut and paste the below code into your config.php file. -- AdamShand, 8 Nov 2012

# enable (:html:) & (:htmlend:) for admins
# From http://www.pmwiki.org/wiki/Cookbook/EnableHTML-Talk
Markup(
  'html',
  'fulltext',
  '/\\(:html:\\)(.*?)\\(:htmlend:\\)/esi',
  "'<:block>'.Keep(str_replace(array('&gt;', '&lt;', '&amp;'),
  array('>', '<', '&'), PSS('$1')))");

array_unshift($EditFunctions, 'MaybeDisableEmbedhtml');
function MaybeDisableEmbedhtml($pagename,&$page,&$new) { 
        global $ROSPatterns;
	if (!CondAuth($pagename,"admin")) { 
		$ROSPatterns["/\\(:html:\\)/i"] = "[:html:]";
	    $ROSPatterns["/\\(:htmlend:\\)/i"] = "[:htmlend:]";
	}
}

NB: 2014-7-7 added global declaration to code above; otherwise, this snippet does not work. —Anonymous

I modified the above to work also with PHP 5.5 -- Klonk, 10 Oct 2015

# enable (:html:) & (:htmlend:) for admins
# From http://www.pmwiki.org/wiki/Cookbook/EnableHTML-Talk
Markup_e(
  'html',
  'fulltext',
  '/\\(:html:\\)(.*?)\\(:htmlend:\\)/si',
  "'<:block>'.Keep(str_replace(array('&gt;', '&lt;', '&amp;'),
  array('>', '<', '&'), PSS(\$m[1])))");

array_unshift($EditFunctions, 'MaybeDisableEmbedhtml');
function MaybeDisableEmbedhtml($pagename,&$page,&$new) { 
        global $ROSPatterns;
	if (!CondAuth($pagename,"admin")) { 
		$ROSPatterns["/\\(:html:\\)/i"] = "[:html:]";
	    $ROSPatterns["/\\(:htmlend:\\)/i"] = "[:htmlend:]";
	}
}

Details

This does not validate element attributes.

The style attribute is particularly dangerous, because it allows positioning an HTML element anywhere on the screen; a fraudulent visitor could (with some effort) write HTML that overlays all the navigational elements of the wiki. Later visitors would then see an unchanged page where every link leads to a place that the malicious visitor has determined, instead of triggering the functions that your wiki normally offers.

It also doesn't validate whether opening and closing tags are properly nested. If the pages contains invalid HTML markup, it will simply be passed through unchanged.
This offers an inroad to another kind of abuse: if the <div> tag is allowed, a vandalic visitor could add a "sufficient" number of </div> tags, and would disturb the display of all elements that come after the wiki text (this will affect the footer, and the wikitext itself if the vandal edits the side bar).

(In case I haven't said this already, this means: Don't allow this on pages that aren't password-protected!)

The parameter of EnableHtml is actually a regular expression that describes the HTML tags that you wish to match. If you don't know regular expressions, here's a short list of things that you can do:

  • Say EnableHtml('b|i|u|sup|sub'); to match any of the b, i, u, sup and sub tags.
  • Say EnableHtml('script'); to allow editors to insert JavaScript on the page. Note that this is dangerous: many browsers have security issues with JavaScript, and visitors may be tempted to leave malware on your page (in the worst case, this may lead to legal liabilities for the site administrator if he cannot say who placed the malware on his site). In other words, this is a solution for the case where PmWiki isn't used as a collaboration platform, but as a publishing tool with a small group of known and trusted editors, or if you have a registration process and can find out who changed what.
  • Say [a-z!]+ to match all HTML tags (including comments). This opens the road for online HTML editors like FCKEdit. The security issues are the same as when enabling <script> tags.

If EnableHtml enables an HTML tag <foo>, it will also automatically enable the corresponding ending tag </foo>. There is no need to write something like

  EnableHtml('b|/b');

(in fact that would not work because / is a reserved character in a regular expression, but even if you rewrote that expression, this would get you a pass-through for <b>, </b>, and <//b>, which isn't particularly useful).

EnableHtml will copy through any attributes that it finds within a tag. So EnableHtml('form') will also allow through

  <form action="http://domain.tld/path/to/cgi?query=value" method="POST">

EnableHtml tries to be smart about attribute values. It will correctly handle cases like

  <input title="Tell me more about the < b > tag in HTML">

and not replace that < b > with anything else, or take the > in < b > as the end of the < form > tag.

If EnableHtml finds a HTML tag, only the {$some_variable} markup will be recognised between the angle brackes, nothing else. That is,

  <input title="Tell me ''more'' about you">

will not make PmWiki emit something like

  <input title="Tell me <i>more</i> about you">

EnableHtml does no rigorous validity checking: full checking is beyond the capabilities of a recipe, so it doesn't even try.
As a result, it will accept some forms that aren't valid HTML, such as <form method="Post"/> or </b/>.

To be precise, EnableHtml will accept any sequence of characters that

  • starts with the left angle bracket ("less-than character") < and an optional slash /,
  • continues with a token that matches any pattern ever defined with EnableHtml('...');,
  • continues with an arbitrary sequence of characters, and
  • finishes with an optional slash / and a right angle bracket ("greater-than character") > outside of strings.

See Also

Contributors

  • Pm, 15-Mar-2004, original code
  • Pm, 02-Dec-2004, updated for PmWiki 2
  • Joachim Durchholz 11-Apr-2005, wrapped it up in a downloadable recipe, made it incremental, and made it not match end-of-tag within string-valued tag attributes.
  • Joachim Durchholz, 30-Apr-2005, now also handles HTML comments.
  • Susan, 22-Dec-2005, specific example of WebRing code added (and fixed half the page showing in bold).

Comments

See discussion at EnableHTML-Talk