====== 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 [[http://ktyp.com/dev/doku/dokuwiki/hacks/hidephp|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 Hack http://ktyp.com/dev/doku/ global $INFO; if(!$INFO['writable']) $text = preg_replace("/(.|\s)*?<\/php>/i", "[You Do Not Have Permission to View this Code]",$text); return htmlspecialchars($text); } * This is the [[http://ktyp.com/dev/doku/dokuwiki/hacks/hidephp|hidephp]] hack. == rawWiki() == function rawWiki($id,$rev=''){ $text=io_readFile(wikiFN($id,$rev)); global $INFO; if(!$INFO['writable']) $text = preg_replace("/(.|\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("/(.|\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: - The $conf['phpok'] directive is set to 1, **and** - The page was last edited by a superuser (prevents 'normal' users adding PHP), **and** - 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@brookfamily.org.uk|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: [[echo $ID;:talk|Discussions]] will be linked to php_echo_id:php_:talk any idea? thanks. --- //[[codronm@gmail.com|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/]]\\ --- [[user>clso|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"); } }