Table of Contents
DokuWiki Plugin: phpinc
Compatible with DokuWiki
- 2024-02-06 "Kaos" unknown
- 2023-04-04 "Jack Jackrum" unknown
- 2022-07-31 "Igor" unknown
- 2020-07-29 "Hogfather" no
The missing download url means that this extension cannot be installed via the Extension Manager. Please see Publishing a Plugin on dokuwiki.org. Recommended are public repository hosts like GitHub, GitLab or Bitbucket.
Important
I do not maintain this plugin anymore, it has some security issues which you should be aware of.
Please read the notes of other users carefully.
The download link is very outdated and I won't support a download anymore. Please copy paste the code from this page if you want to use it.
— lazyfrosch 2010/01/30 17:12
The idea
Instead of writing PHP code directly into the wikipage, which is very insecure in my opinion, you can include a PHP file in a special directory in the installation directory of DokuWiki. So the serveradmin can define which dynamic content can be loaded!
Only files in /phpincludes in your DokuWiki installation can be included!
The included scripts are given the $_GET, $_POST, and $_REQUEST superglobals to play with, plus access to the Common Plugin Functions. What they output via $stdout is passed unmangled to the end user.
Requirements
I've developed the plugin under 2006-03-09 and it should work in any future release!
Download / Installation
Here you can download phpinc: not longer available
I didn't test the installation via the plugin manager, but it should work!
Installation is very simple:
- Create the directory “phpinc” in the plugin directory
- Create the file “syntax.php” and paste the source code in
- Create the directory “phpincludes” in the root directory of your DokuWiki Installation
Syntax
The Syntax is very simple:
<phpinc=filename>
Sourcecode
Here is the source code. Feel free to improve it, but please inform me!
- Release 20060511 - initial release
- Release 20060703 - ability to use sub-directories in the includes directory (see also comment below)
- syntax.php
<?php /** * PHP Includes via Syntax * * Please create the directory "phpincludes" in your installation of * DokuWiki. Now you can put there any HTML or PHP File you want to * this directory. * * <phpinc=filename> * * The syntax includes the PHP file per include an puts the result into * the wiki page. * * @license GNU_GPL_v2 * @author Markus Frosch <markus [at] lazyfrosch [dot] de> */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); class syntax_plugin_phpinc extends DokuWiki_Syntax_Plugin { function getInfo(){ return array( 'author' => 'Markus Frosch', 'email' => 'markus@lazyfrosch.de', 'date' => '2006-05-11', 'name' => 'PHP Include', 'desc' => 'Allows you to make an include of an PHP File on Server', 'url' => 'http://www.dokuwiki.org/plugin:phpinc', ); } function getType(){ return 'container'; } function getPType(){ return 'normal'; } function getAllowedTypes() { return array('substition','protected','disabled'); } function getSort(){ return 195; } function connectTo($mode) { $this->Lexer->addSpecialPattern('<phpinc=.*?>',$mode,'plugin_phpinc'); } function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_SPECIAL : return array($state, $match); default: return array($state); } } function render($mode, &$renderer, $indata) { if($mode == 'xhtml'){ list($state, $data) = $indata; switch ($state) { case DOKU_LEXER_SPECIAL : preg_match("#^<phpinc=(.+)>$#", $data, $matches); $file = $matches[1]; if(preg_match("#^[a-z0-9\-_ \./]+$#i", $file) and strstr("..", $file) == false and file_exists(DOKU_INC."phpincludes/".$file)) { $renderer->info['cache'] = FALSE; ob_start(); include(DOKU_INC."phpincludes/".$file); $content = ob_get_contents(); ob_end_clean(); $renderer->doc .= $content; } else $renderer->doc .= $renderer->_xmlEntities($data); break; } return true; } // unsupported $mode return false; } } ?>
Credits
The plugin was developed by Markus Frosch markus [at] lazyfrosch [dot] de for the internal DokuWiki of the IP-Exchange GmbH.
Many thanks to the developers of DokuWiki! It's a great software!
And also many thanks to the developers of the note plugin your plugin helped me on the first steps to build this plugin!
Scripts
I thought it could be a good idea to add a section here to share everyone's scripts; at least the ones that are easy to re-use (maybe it's then a sign to make a plugin out of them…). hopefully this way others can make use of them and maybe some can improve posted scripts. – Stephane Chamberland 2009-01-16
- Contact Form
This is a simple contact form with CAPTCHA, fields validation and limited “To:” selection (hopefully this limits what a spam bot can do with it). You'll have to modify it to set the “To:” list ($allowed array).
Please let me know if you can make it safer.– Stephane Chamberland 2009-01-16
Comments
Feel free to add your comments and suggestions here!
You did a good work! I had similar code prepared – some difference: I look for the included files in data/media/phpincludes, so that they can be uploaded like any media file. And I expect a function doOutput() in the included file, so you have less restrictions than I have
Maybe you could give a hint what the included files should look like. As far as I see, the included file does its output via echo or sprintf() or whatever , this output is captured and merged into the XHTML code of the page. You do not call a function inside the file, but you let the file be parsed by DokuWiki's PHP abilities, so that one may use the built-in variables of DokuWiki. Is this correct? – Werner 2006-05-12
Thank you! My idea was to forbid custom PHP code for the users, so only the sysadmin is able to insert scripts. Because when a user can upload scripts this will be very similar to the <php> syntax.
The files should be standard PHP scripts with echo output, the output should be normal XHTML code, you are right. Yeah you can use DokuWiki's internal variables. The plugin is not made to protect DokuWiki, it's only made for the sysadmins.
My company uses this plugin for inserting special data into the wikipages. The user can edit pages, but he's not able to use custom PHP code. — Markus Frosch 2006-05-14 17:47
A user contacted me via mail and told me he extended the Regular Expression for the filename with a “/”, so subdirectories can be used in the phpincludes directory. I've agreed with that and updated my script, but I also made an improvement to the idea. I added a protection, that no “..” can be used in the file name, so no file outside the phpincludes directory can be accessed. — Markus Frosch 2006-07-03 17:50
Syntax comment: The tag syntax <phpinc=myfile.php>
is a bit non-conforming to other DokuWiki syntax. All the built in tag constructions (sub, sup, del, nowiki, file, code, html, php) have endtags, i.e. <tag>...</tag>. Have you considered using curly brackets, {{phpinc>myfile.php}}
instead? — Viktor 2006-10-15 00:12
I agree, the syntax should be {{phpinc>myfile.php}}
. I prefer {{include>myfile.php}}
: more simple and intuitive. Here's the modified version, working with {{include>myfile.php}}
. — Emmanuel 2007-12-01
<?php /** * PHP Includes via Syntax * * Please create the directory "phpincludes" in your installation of * DokuWiki. Now you can put there any HTML or PHP File you want to * this directory. * * <phpinc=filename> * * The syntax includes the PHP file per include an puts the result into * the wiki page. * * @license GNU_GPL_v2 * @author Markus Frosch <markus [at] lazyfrosch [dot] de> */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); class syntax_plugin_phpinc extends DokuWiki_Syntax_Plugin { function getInfo(){ return array( 'author' => 'Markus Frosch', 'email' => 'markus@lazyfrosch.de', 'date' => '2006-05-11', 'name' => 'PHP Include', 'desc' => 'Allows you to make an include of an PHP File on Server', 'url' => 'http://www.dokuwiki.org/plugin:phpinc', ); } function getType(){ return 'container'; } function getPType(){ return 'normal'; } function getAllowedTypes() { return array('substition','protected','disabled'); } function getSort(){ return 195; } function connectTo($mode) { $this->Lexer->addSpecialPattern('{{include>.*?}}',$mode,'plugin_phpinc'); } function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_SPECIAL : return array($state, $match); default: return array($state); } } function render($mode, &$renderer, $indata) { if($mode == 'xhtml'){ list($state, $data) = $indata; switch ($state) { case DOKU_LEXER_SPECIAL : preg_match("#^{{include>(.+)}}$#", $data, $matches); $file = $matches[1]; if(preg_match("#^[a-z0-9\-_ \./]+$#i", $file) and strstr("..", $file) == false and file_exists(DOKU_INC."phpincludes/".$file)) { $renderer->info['cache'] = FALSE; ob_start(); include(DOKU_INC."phpincludes/".$file); $content = ob_get_contents(); ob_end_clean(); $renderer->doc .= $content; } else $renderer->doc .= $renderer->_xmlEntities($data); break; } return true; } // unsupported $mode return false; } } ?>
General comment: Is there a possibility to parse DokuWiki syntax created by the included PHP file? I read the API document and found some render, handle and other functions, but couldn't get it working. I want to generate tables or other stuff using the wikisyntax and then call a parser which processes the output. — Petz 2006-11-14 12:56
You can use normal HTML table tags with the inline class from DokuWiki.
I use following code to print out ORACLE tables in DokuWiki - haedae
echo '<table class=inline> <th>IP</th><th>AID</th><th>TYPE</th><th>TIME</th><th>Severity</th><th>Condition</th><th>Description</th>'; while ($row = oci_fetch_array($s, OCI_RETURN_NULLS)) { echo '<tr> <td>'.$row[0].'</td> <td>'.$row[1].'</td> <td>'.$row[2].'</td> <td>'.$row[3].'</td> <td>'.$row[4].'</td> <td>'.$row[5].'</td> <td>'.$row[6].'</td> </tr>'; } echo "</table>";
If you for some reason don't want people to be able to snoop around in the /phpincludes/
folder and are using Apache with the proper privileges. You can add a .htaccess
file to the folder with the following content:
order allow,deny deny from all
Keeps people from listing the files of that folder and executing them directly. It might also be worth considering to move the folder out of your web accessible folders. Just remember to edit the plugin so it knows where to look if you do the latter. — David Lorentsen 2007-01-16 11:36
Can I ask a stupid question … where do I put <phpinc=filename> — MD 2007-02-04 05:36
If I understand it correctly, you can put it everywhere in every wikipage you want. You may put it below a heading to include some scripting. But it totally depends on your purpose and the included file. — eModul 2007-04-03 01:03
Excellent plugin, thanks for sharing. I've added a small bit that allows the use of 1 parameter to be passed in the filename.php?var=something manner. I'm more of a PHP-coder than a PHP-programmer so there's probably room for code compaction:
<?php /** * PHP Includes via Syntax * * Please create the directory "phpincludes" in your installation of * DokuWiki. Now you can put there any HTML or PHP File you want to * this directory. * * <phpinc=filename> * * The syntax includes the PHP file per include an puts the result into * the wiki page. * * @license GNU_GPL_v2 * @author Markus Frosch <markus [at] lazyfrosch [dot] de> */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); class syntax_plugin_phpinc extends DokuWiki_Syntax_Plugin { function getInfo(){ return array( 'author' => 'Markus Frosch', 'email' => 'markus@lazyfrosch.de', 'date' => '2006-05-11', 'name' => 'PHP Include', 'desc' => 'Allows you to make an include of an PHP File on Server', 'url' => 'http://www.dokuwiki.org/plugin:phpinc', ); } function getType(){ return 'container'; } function getPType(){ return 'normal'; } function getAllowedTypes() { return array('substition','protected','disabled'); } function getSort(){ return 195; } function connectTo($mode) { $this->Lexer->addSpecialPattern('<phpinc=.*?>',$mode,'plugin_phpinc'); } function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_SPECIAL : return array($state, $match); default: return array($state); } } function render($mode, &$renderer, $indata) { if($mode == 'xhtml'){ list($state, $data) = $indata; switch ($state) { case DOKU_LEXER_SPECIAL : preg_match("#^<phpinc=(.+)>$#", $data, $matches); $file = $matches[1]; $file_ = substr($file,0,stripos($file,'.php')+4); $question = substr($file,stripos($file,'=')+1); // if(preg_match("#^[a-z0-9\-_ \./]+$#i", $file) and strstr("..", $file) == false and file_exists(DOKU_INC."phpincludes/".$file)) { if(preg_match("#^[a-z0-9\-_ \./\?\=]+$#i", $file) and strstr("..", $file) == false and file_exists(DOKU_INC."phpincludes/".$file_)) { $renderer->info['cache'] = FALSE; ob_start(); $_GET['var'] = $question; include(DOKU_INC."phpincludes/".$file_); $content = ob_get_contents(); ob_end_clean(); $renderer->doc .= $content; } else $renderer->doc .= $renderer->_xmlEntities($data); break; } return true; } // unsupported $mode return false; } } ?>
— Hi, please give an example of use for those of us who can't read regular expressions… Thanks for sharing !
suppose your phpfile is test.php, use this syntax:
<phpinc=test.php?variable=hello>
<phpinc=test.php?hihi=haha>
Whatever you use as postname (in the examples “variable” and “hihi”), it gets transformed to “var”, so inside your phpscript you use something like if(isset('var')) $input = $_GET['var'];
Here's a little extra on this last modification… forms. If you add this on a page…
<html> <form action="/doku.php" accept-charset="utf-8" id="dw__search" name="example"> <input type="hidden" name="do" value="example" /> <input id="gsearch__in" name="id" type="text" accesskey="f" value="" /> <input type='button' class="searchButton" id="searchGoButton" value="Enter Genus" onclick="document.location.href='/phpincludes/yourphpfile.php?variable=' + document.example.gsearch__in.value;" /> </form> </html>
… you'll get a text field and button that takes the search as postvariable for the phpincluded php script.
Demo: terrorchid wiki… enter “disa” or “Epipactis”
Here's an idea. wiki editors don't want long repetitive words or words that refer to a programming environment…
so instead of <phpinc=filename.php?var=this> use the expression <do:action=this>
you replace “phpinc=” by “do:” and “.php?” by “”, they're always the same so why bother typing them in ?
This way you won't give the casual editor the idea he's about to launch a technical thing with scripts
and other stuff he rather has nothing to do with … we're programmers and have a natural liking and feel for
this stuff, but 99 % of the visitors think twice before typing that in – Fred
Wollte einfach nur ein Kompliment hinterlassen! – Bernd
.
Just got to know DokuWiki and I love it! Looking for plugins to make things perfect I stumbled over PHPinc and it's just the missing link. I like this charming simplicity
Though it might be syntactic more right I prefer the <phpinc> syntax (maybe because I'm still new to DokuWiki syntax and this looks more familiar).
Inspired by the comments here I added four lines to Markus' original code to “parse” variables to the PHP. And I'm lazy like Fred. My function render()
looks like this (with my additions marked by +++++)
function render($mode, &$renderer, $indata){ if($mode == 'xhtml'){ list($state, $data) = $indata; switch ($state) { case DOKU_LEXER_SPECIAL : preg_match("#^<phpinc=(.+)>$#", $data, $matches); $file = $matches[1]; +++++ $a = explode('?', $file); +++++ $file = $a[0].'.php'; // here's where the .php extension goes in +++++ if (!empty($a[1])) { parse_str($a[1], $query); } +++++ else { $query = ''; } if(preg_match("#^[a-z0-9\-_\./]+$#i", $file) and strstr("..", $file) == false and file_exists(DOKU_INC."phpincludes/".$file)) { $renderer->info['cache'] = FALSE; ob_start(); include(DOKU_INC."phpincludes/".$file); $content = ob_get_contents(); ob_end_clean(); $renderer->doc .= $content; } else $renderer->doc .= $renderer->_xmlEntities($data); break; } return true; }
No further changes in the plugin required. This results in:
- no need for
.php
extention (only filename will do) - querystring is stored as an array in
$query
which is in the scope of the included file
Extended syntax: <phpinc=file?var1=foo&var2=bar&what=ever&you=want>
It might be a good idea to start the included PHP script with checking the vars:
if ( count($query) == ## // count for sufficient number of elements && array_key_exists('var1', $query) // check for needed vars && array_key_exists('var2', $query) ) { .....
Cheers and thanks again!
Henk-Sjoerd — 2008-10-29 — Running DokuWiki 2008-05-05
For both the monobook and sidebar themes, using phpinc messes up the sidebar column formatting, pushing the content below the main column in monobook and placing the footer on top in the sidebar theme. This is in Firefox 3. Do you have any fixes for this?
thanks
skarred — 2008-10-29
—
This plugin seems to be useful; however as it produces direct XHTML output to “accompany” DokuWiki's renderer output, the result does not look consistent with DokuWiki (styles and such). I think merging the capabilities of this plugin with phpwikify could me something very interesting to do, and thus have started some experiments. If there's anyone interested in the changes I'll probably post a full Plugin Manager package sometime soon. — Luis 2010/02/08 00:51
I'm interested, Luis! Did you make any progress onphpinc+phpwikify
? — Rik Blok 2011/03/04 20:30Haven't needed to do much with it, sincephpwikify
can stand quite well by itself (and can even userequire_once
). In my setup, I keep aphpincludes/
directory where the includes allowed by phpwikify are stored and I'm trying to modify the code of that plugin so that it can take parameters like this one does, but I've met up the detail that since Anteater normal pages can take parameters too. Should document those later… — Luis Machuca Bezzaza 2011/03/05 06:17