DokuWiki

It's better when it's simple

User Tools

Site Tools


tips:safely_include_php_code

Safely include PHP code

I have tweaked my Dokuwiki installation to allow me to include PHP code on 'special' pages in the wiki (ones which normal users cannot edit).

The changes I have made are as follows:

Use ACL to prevent users editing PHP pages

Manually set the permissions to read-only for any pages or namespaces in which I will be using PHP.

Keep the PHP code secret

I found hidephp which is a simple change to the formtext() function in inc/common.php which prevents users clicking the view source button and seeing your PHP code.

I took this code and added some extra changes to the rawWiki() and rawWikiSlices() functions to prevent users seeing the PHP code when looking at comparisons of old revisions.

Here are the changes:

inc/common.php

formText()
function formText($text){
  $text = preg_replace("/\012/","\015\012",$text);
 
  // Hide <php> Hack  http://ktyp.com/dev/doku/
  global $INFO;
  if(!$INFO['writable'])
    $text = preg_replace("/<php>(.|\s)*?<\/php>/i",
        "[You Do Not Have Permission to View this Code]",$text);
 
  return htmlspecialchars($text);
}
rawWiki()
function rawWiki($id,$rev=''){
  $text=io_readFile(wikiFN($id,$rev));
  global $INFO;
  if(!$INFO['writable'])
    $text = preg_replace("/<php>(.|\s)*?<\/php>/i",
        "[You Do Not Have Permission to View this Code]",$text);
 
  return ($text);
}
rawWikiSlices()
function rawWikiSlices($range,$id,$rev=''){
  list($from,$to) = split('-',$range,2);
  $text = io_readFile(wikiFN($id,$rev));
  if(!$from) $from = 0;
  if(!$to)   $to   = strlen($text)+1;
 
  $slices[0] = substr($text,0,$from-1);
  $slices[1] = substr($text,$from-1,$to-$from);
  $slices[2] = substr($text,$to);
 
  global $INFO;
  if(!$INFO['writable'])
    $slices = preg_replace("/<php>(.|\s)*?<\/php>/i",
        "[You Do Not Have Permission to View this Code]",$slices);
 
  return $slices;
}

2. Limit execution of PHP code

I have modified the code so that PHP code is only executed if:

  1. The $conf['phpok'] directive is set to 1, and
  2. The page was last edited by a superuser (prevents 'normal' users adding PHP), and
  3. The page being viewed is the current revision (prevents old versions of your code being executed).

In the case that PHP code cannot be executed, DokuWiki used to simply output the code. Instead I've just inserted the message “This dynamic content cannot be displayed”.

Here's the new version of the function:

inc/parser/xhtml.php
    function php($text) {
        global $conf;
	global $ID, $INFO;
	$user=$INFO['editor'];
	$data=auth_getUserData($user);
	if ($conf['phpok'] and auth_aclcheck($id,$user,$data['grps'])==AUTH_ADMIN and !$INFO['rev']) {
            ob_start();
            eval($text);
            $this->doc .= ob_get_contents();
            ob_end_clean();
        }else{
            $this->file("This dynamic content cannot be displayed");
        }
    }

Disable caching of PHP pages

I include the special NOCACHE directive

~~NOCACHE~~

on every page in which I include any PHP. This ensures that the dynamic content is generated on-the-fly every time the page is loaded.

I hope you find this useful! — Martin Brook

Discussions

with the very last RC version of DW (dokuwiki-rc2007-05-24), it doesn't work because auth_getUserData isn't defined. I have done a small improvement that seems working:

inc/parser/xhtml.php
    function php($text) {
        global $conf;
	global $INFO;
        if ($conf['phpok'] and $INFO['isadmin'] and !$INFO['rev']) {
            ob_start();
            eval($text);
            $this->doc .= ob_get_contents();
            ob_end_clean();
        }else{
            $this->file("This dynamic content cannot be displayed");
        }
    }

nevertheless, this is correctly interpreted in text, but not in a link:

[[<php>echo $ID;</php>:talk|Discussions]]

will be linked to php_echo_id:php_:talk

any idea? thanks.

Mat 2007-27-05 00:30


The New function php

I fixed some wrong and stale code,
It's works great on DokuWiki “Greebo”(2018).

https://clso.fun/
clso 2019-10-06 09:11

function php($text) {
    global $conf;
    global $INFO;
 
    $editor = $INFO['editor'];
 
    /* @var Doku_Plugin_Controller $plugin_controller */
    global $plugin_controller;
    /* @var DokuWiki_Auth_Plugin $users */
    $users = null;
    foreach ($plugin_controller->getList('auth') as $plugin) {
        if ($conf['authtype'] === $plugin) {
            $users = $plugin_controller->load('auth', $plugin);
            break;
        }
    }
    $is_admin = false;
    if(!empty($users)){
        $user = $users->getUserData($editor);
        $is_admin = auth_isMember($conf['superuser'], $editor, $user['grps']);
    }
 
    // disable revisions is not good idea
    // if ($conf['phpok'] and $is_admin and !$INFO['rev'])
    if ($conf['phpok'] and $is_admin) {
        ob_start();
        eval($text);
        $this->doc .= ob_get_contents();
        ob_end_clean();
    }else{
        $this->file("This dynamic content cannot be displayed");
    }
}
tips/safely_include_php_code.txt · Last modified: 2019-10-06 09:21 by clso

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki