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:
Manually set the permissions to read-only for any pages or namespaces in which I will be using PHP.
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:
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); }
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); }
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; }
I have modified the code so that PHP code is only executed if:
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:
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"); } }
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
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:
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
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"); } }