[pmwiki-users] Markup Processing Order

Patrick R. Michaud pmichaud at pobox.com
Sun Aug 20 14:34:22 CDT 2006

On Sun, Aug 20, 2006 at 11:44:31AM -0400, The Editor wrote:
> I have a markup (:data Group.Name:) which pulls all the data fields
> off a given wiki page and sets them as page variables.  Currently the
> processing order is set to
> '<{$var}'
> It works perfect for normal uses.  The problem is, for some
> applications I need this:
> (:data Group.{$Name}:)
> When I actually got around to trying some of these applications I
> discovered it processes the data markup before translating $Name--thus
> giving me error messages as it tries to fread from literal:
> Group.{$Name}.
> I tried setting it to
> '>{$var}'
> thinking this would then set all the variables just after {$Name}--and
> it does gets rid of all the error messages--but too late to do
> anything with the page variables!  That is, they show up blank,
> because the function is run after all the $var's have already been
> translated.  I guess it's a problem of the chicken or the egg.

However, PmWiki already fixes this for you.  :-)

You want it set to '>{$var}', so that it will occur after
page variable substitution, and the {$Name} will get correctly
substituted.  However, as part of processing the (:data ...:)
directive, be sure to make a call to the PRR() function.  This
tells the markup engine to *immediately restart* processing 
the text with the first markup rule again.  As a result, any 
page variables that were included by the (:data:) markup will 
get handled by this second pass through the {$var} rule (as well
as passing through the $[...] rule, the [=...=] rule, etc.)

Or, you can leave it set to '<{$var}', and have your ReadData
function do page variable substitutions on the parameter before
opening the appropriate page or file.  Thus:

    # Function called by directive to retrieve form data
    function ReadData($l) {
      global $WorkDir, $FmtPV;
      $l = preg_replace('/\\{(!?[-\\w.\\/]*)(\\$\\w+)\\}/e',
        "htmlspecialchars(PageVar(\$pagename, '$2', '$1'), ENT_NOQUOTES)");
      $datapage = substr($l, 1);
      if ($dr = fopen("$WorkDir/$datapage", "rb")){
    	$pc = fread($dr, filesize("$WorkDir/$datapage"));

Also, I should note that as written this function looks somewhat
insecure, since an author can pass any argument to ReadData()
and hence to fopen.  For example:

    (:data ../../../../../../etc/passwd :)

In fact, someone can easily use this to bypass PmWiki's
security checks and grab data from any read-protected page:

    (:data ../wiki.d/Group.SomePage :)

Granted, the later processing will restrict what a malicious
person is able to access, but still, it's better to prevent
the opening of arbitrary files in the first place.

    (:data ../../../../../dev/random:)   # could read from here for a long time


More information about the pmwiki-users mailing list