If the HTML file you included in your module with the methods shown in Section 21.5 contains links to HTML files that you would also like to have included, you will need to apply some additional handwork. The problem here is that, although the included file will show correctly inside your module (and your theme), as soon as you click on one of its HTML links, you will be shown the target HTML file as is, i.e. outside your PHP-Nuke environment, like any other file independent of PHP-Nuke. This is certainly not something you are going to like - otherwise, why go into the trouble of including the first HTML file anyway? It is clear that, for a collection of interlinked HTML documents, a better approach is needed.
See the PHP-Nuke HOWTO module! | |
---|---|
For a real world example of including a large collection of HTML documents in a PHP-Nuke module, download and install the PHP-Nuke HOWTO module. Then, see how modules/PHP-Nuke_HOWTO/index.php is programmed, as well as how the HTML links to files of the HOWTO were set up. |
In the method we will present here, we use an URL parameter (“page”) to find out which file to include in index.php. Every link to a file of our collection is changed to contain this URL parameter. The page URL parameter is validated through an associative array, minimizing the risk for SQL injection and other cracking attacks (see Section 23.3.2). For a simpler, but not universal, method using iframes, see Section 21.7.
Proceed in two steps as follows:
Change every HTML link that appears in your HTML documents and points to another document of the same collection (links to other documents should be left unchanged) For example, a link to somefile.html like the following one
<a href="somefile.html"> |
should be changed to
<a href="modules.php?name=Your_Module&page=somefile.html"> |
where you should replace "Your_Module" with the name of your module, of course. This link passes the filename as the value of the page URL parameter to Your_Module. You should do this for every link in your HTML document collection that points to another file of the same collection.
As a next step, you modify the index.php file of your PHP-Nuke module slightly (this is the file modules/Your_Module/index.php, if we stay with the module naming of our example). You add a line for every file that was involved in a link modification above. This means that for every file like somefile.html in the above example, you add a line
$ACCEPT_FILE['somefile.html'] = 'somefile.html'; |
Thus, if your HTML file collection consists of the files
accelerating-php-nuke.html add-on-blocks.html add-on-modules.html administration-functions.html admin-management.html |
then, following the above step 1, you should change every HTML link in those files as shown in Table 21-1.
Table 21-1. Changing HTML links for use in a custom PHP-Nuke module
Original link | Changed link |
<a href="accelerating-php-nuke.html"> | <a href="modules.php?name=Your_Module &page=accelerating-php-nuke.html"> |
<a href="add-on-blocks.html"> | <a href="modules.php?name=Your_Module &page=add-on-blocks.html"> |
<a href="add-on-modules.html"> | <a href="modules.php?name=Your_Module &page=add-on-modules.html"> |
<a href="administration-functions.html"> | <a href="modules.php?name=Your_Module &page=administration-functions.html"> |
<a href="admin-management.html"> | <a href="modules.php?name=Your_Module &page=admin-management.html"> |
After that, following step 2 above, you should insert the following lines in the index.php file of Your_Module:
$ACCEPT_FILE['accelerating-php-nuke.html'] = 'accelerating-php-nuke.html'; $ACCEPT_FILE['add-on-blocks.html'] = 'add-on-blocks.html'; $ACCEPT_FILE['add-on-modules.html'] = 'add-on-modules.html'; $ACCEPT_FILE['administration-functions.html'] = 'administration-functions.html'; $ACCEPT_FILE['admin-management.html'] = 'admin-management.html'; |
The ACCEPT_FILE plays the role of a validator for the page URL parameter. It connects a value of “page”, as passed by some URL, with the name of a file that has to be selected. The way we programmed it above, ACCEPT_FILE points to the file accelerating-php-nuke.html when given the “page” argument 'accelerating-php-nuke.html' (i.e. when “page” was 'accelerating-php-nuke.html' on the URL). This may look trivial, but is not. What's more, there is nothing that would prevent you from choosing a different (and less intuitive) mapping from the values of “page” to the selected filenames.
Thus, you could decide that a “page” (URL parameter) value of “1” means the accelerating-php-nuke.html file, a vlaue of “2” the add-on-blocks.html file etc. Then, the ACCEPT_FILE assignments would look as follows:
$ACCEPT_FILE['1'] = 'accelerating-php-nuke.html'; $ACCEPT_FILE['2'] = 'add-on-blocks.html'; $ACCEPT_FILE['3'] = 'add-on-modules.html'; $ACCEPT_FILE['4'] = 'administration-functions.html'; $ACCEPT_FILE['5'] = 'admin-management.html'; |
while the HTML links in the files themselves should be changed as indicated by Table 21-2.
Table 21-2. Alternative way of changing HTML links for use in a custom PHP-Nuke module
Original link | Changed link |
<a href="accelerating-php-nuke.html"> | <a href="modules.php?name=Your_Module &page=1"> |
<a href="add-on-blocks.html"> | <a href="modules.php?name=Your_Module &page=2"> |
<a href="add-on-modules.html"> | <a href="modules.php?name=Your_Module &page=3"> |
<a href="administration-functions.html"> | <a href="modules.php?name=Your_Module &page=4"> |
<a href="admin-management.html"> | <a href="modules.php?name=Your_Module &page=5"> |
The idea is that you retain control of what filename is selected. If you would blindly set the name of the selected file to be equal to the passed parameter value of “page”, then a malicious user could use the URL
modules.php?name=Your_Module&page=/etc/passwd |
and read the contents of the system's password file (or whatever other file readable by the web server, for that matter). The use of an associative mapping between URL parameters and filenames, as the one implemented by the ACCEPT_FILE array above, is thus not a gimmic, but a necessity. It protects your module from SQL injections and other attacks that rely on the programmer being too lazy to verify user input. See Chapter 23 for more on PHP-Nuke security in general and Section 23.3.2 for SQL injections with PHP-Nuke in particular.
However, even with these precautions in place, the module is still vulnerable to a serious attack, as waraxe has pointed out in a security advisory (to be published): if the $ACCEPT_FILE array is not initialized, one could “poison” it. This means that an attacker could pass the parameters '...&page=xxx&ACCEPT_FILE[xxx]=/etc/passwd' on the URL and could still get /etc/passwd (or any other file for that matter) back! This will not work if safe_mode is ON in php.ini, but it still poses a very serious threat. For this reason, we must initialize the array first:
// We initialize the array, to avoid attacks based on poisoning the // <acronym>PHP</acronym> global variable space. Thanks to waraxe for pointing this out! // See http://www.waraxe.us // $ACCEPT_FILE = array(); |
Now you can hopefully see how important is the following rule:
Don't forget: | |
---|---|
Always initialize your variables! |
The complete code of modules/Your_Module/index.php is thus:
<?php /************************************************************************/ /* PHP-NUKE: Web Portal System */ /* =========================== */ /* */ /* PHP-Nuke-HOWTO module for <application>PHP-Nuke</application> */ /* */ /* Copyright (c) 2003 index.php */ /* by Chris Karakas */ /* http://www.karakas-online.de */ /* */ /* See licence.html for the Licence of the other files */ /* distributed together with this index.php file. */ /* */ /* This program is free software. You can redistribute it and/or modify */ /* it under the terms of the <acronym>GNU</acronym> General Public License as published by */ /* the Free Software Foundation; either version 2 of the License. */ /************************************************************************/ if (!eregi("modules.php", $PHP_SELF)) { die ("You can't access this file directly..."); } $index = 0; // 0 : do not show right blocks - 1:show right blocks require_once("mainfile.php"); $module_name = basename(dirname(__FILE__)); include("header.php"); // We initialize the array, to avoid attacks based on poisoning the // <acronym>PHP</acronym> global variable space. Thanks to waraxe for pointing this out! // See http://www.waraxe.us // $ACCEPT_FILE = array(); $ACCEPT_FILE['accelerating-php-nuke.html'] = 'accelerating-php-nuke.html'; $ACCEPT_FILE['add-on-blocks.html'] = 'add-on-blocks.html'; $ACCEPT_FILE['add-on-modules.html'] = 'add-on-modules.html'; $ACCEPT_FILE['administration-functions.html'] = 'administration-functions.html'; $ACCEPT_FILE['admin-management.html'] = 'admin-management.html'; OpenTable(); $php_ver = phpversion(); $php_ver = explode(".", $php_ver); $phpver = "$php_ver[0]$php_ver[1]"; if ($phpver >= 41) { $page = $_GET['page']; } else { $page = $HTTP_GET_VARS['page']; } $pagename = $ACCEPT_FILE[$page]; if (!isSet($pagename)) $pagename = "accelerating-php-nuke.html"; // default file include("modules/Your_Module/$pagename"); CloseTable(); include("footer.php"); ?> |
As you can easily deduce from the above code, the "page" URL parameter is firtst extracted using either the GET superglobal, if the PHP version is at least 4.1, or the $HTTP_GET_VARS array otherwise. The associated filename is then computed from the ACCEPT_FILE array. If the user (maliciously or not) entered a value for “page” that could not be mapped to a filename, a default file is used (the accelerating-php-nuke.html in the example). Finally, the computed filename is included, just as we have seen in the simpler examples of Section 21.5.
Automate! | |
---|---|
Most of the work in the method we presented, will revolve around changing links in the various files and adding the right ACCEPT_FILE line for each file in index.php. This is an error prone procedure, even with just a few files. You should thus automate it with whatever tools you have at your disposal. For the creation of the PHP-Nuke HOWTO module, for example, a shell script is used to produce dynamically the right sed commands, which are then executed to produce the link substitutions. The ACCEPT_FILE lines are also produced automatically. The result is a perfectly integrated PHP-Nuke module, even with the hundreds of files that comprise this HOWTO. |