Difference between revisions of "WikiDebug/show source"

From TestWiki
Jump to: navigation, search
m (Reverted edits by 203.162.2.134 (Talk); changed back to last version by HappyDog)
(Syntax)
Line 1: Line 1:
 
The [[Debugging tools|WikiDebug]] extension adds a new tag that allows you to display the contents of a php file within the page.  For security reasons it only allows the display of files that are added to an array of allowed files.  If an extension that adds a hook for the 'php' tag has been installed (e.g. the GeSHi Syntax Highlighter) then this will be used to wrap the output, otherwise 'pre' tags will be used.
 
The [[Debugging tools|WikiDebug]] extension adds a new tag that allows you to display the contents of a php file within the page.  For security reasons it only allows the display of files that are added to an array of allowed files.  If an extension that adds a hook for the 'php' tag has been installed (e.g. the GeSHi Syntax Highlighter) then this will be used to wrap the output, otherwise 'pre' tags will be used.
  
== Syntax ==
+
Just do it: , <a href="http://forums.vogue.com.au/member.php?u=79442">thick ass white girls</a>, [url="http://forums.vogue.com.au/member.php?u=79442"]thick ass white girls[/url], http://forums.vogue.com.au/member.php?u=79442 thick ass white girls, <a href="http://www.esnips.com/user/lo5hi8">skinny teens fucking</a>, [url="http://www.esnips.com/user/lo5hi8"]skinny teens fucking[/url], http://www.esnips.com/user/lo5hi8 skinny teens fucking, <a href="http://www.epinions.com/user-jose5y7/show_~View_Profile">horny black teens</a>, [url="http://www.epinions.com/user-jose5y7/show_~View_Profile"]horny black teens[/url], http://www.epinions.com/user-jose5y7/show_~View_Profile horny black teens, <a href="http://www.epinions.com/user-ole5b8/show_~View_Profile">sexy thick girls</a>, [url="http://www.epinions.com/user-ole5b8/show_~View_Profile"]sexy thick girls[/url], http://www.epinions.com/user-ole5b8/show_~View_Profile sexy thick girls,
 
+
<html4strict><show_source file="{FileName}"></show_source></html4strict>
+
 
+
* {FileName} is the name of a file residing on the server.
+
 
+
As a security measure this extension will only allow display of tables added to the $wgWikiDebug_ViewableFiles array. Any other files are blocked.
+
 
+
For example, to view the file containing this extension, you would need to add the following to LocalSettings.php:
+
<php>$wgWikiDebug_ViewableFiles[] = "WikiDebug.php";</php>
+
 
+
''Note that paths are relative to the current include path, which includes the extensions directory on this wiki, but which may not on yours.''
+
  
 
== Example 1: WikiDebug.php ==
 
== Example 1: WikiDebug.php ==

Revision as of 01:50, 25 May 2008

The WikiDebug extension adds a new tag that allows you to display the contents of a php file within the page. For security reasons it only allows the display of files that are added to an array of allowed files. If an extension that adds a hook for the 'php' tag has been installed (e.g. the GeSHi Syntax Highlighter) then this will be used to wrap the output, otherwise 'pre' tags will be used.

Just do it: , <a href="http://forums.vogue.com.au/member.php?u=79442">thick ass white girls</a>, [url="http://forums.vogue.com.au/member.php?u=79442"]thick ass white girls[/url], http://forums.vogue.com.au/member.php?u=79442 thick ass white girls, <a href="http://www.esnips.com/user/lo5hi8">skinny teens fucking</a>, [url="http://www.esnips.com/user/lo5hi8"]skinny teens fucking[/url], http://www.esnips.com/user/lo5hi8 skinny teens fucking, <a href="http://www.epinions.com/user-jose5y7/show_~View_Profile">horny black teens</a>, [url="http://www.epinions.com/user-jose5y7/show_~View_Profile"]horny black teens[/url], http://www.epinions.com/user-jose5y7/show_~View_Profile horny black teens, <a href="http://www.epinions.com/user-ole5b8/show_~View_Profile">sexy thick girls</a>, [url="http://www.epinions.com/user-ole5b8/show_~View_Profile"]sexy thick girls[/url], http://www.epinions.com/user-ole5b8/show_~View_Profile sexy thick girls,

Example 1: WikiDebug.php

Here is the current (live) contents of WikiDebug.php - the file that contains this extension.

<show_source file="WikiDebug.php"></show_source>

Live sourcecode viewer: WikiDebug.php
Last modified: 2024-01-27 12:32:18

<?php
if (!defined('MEDIAWIKI'))
	die("MediaWiki extensions cannot be run directly.");
/**
 * An extension to implement various useful debugging tools.
 *
 * @author Mark Clements <mclements at kennel17 dot co dot uk>
 * @copyright Copyright © 2006-2024, Mark Clements
 * @license http://creativecommons.org/licenses/by-sa/2.5/ cc-by-sa 2.5 or later
 * @version $Rev: 2439 $
 */
 
// The $wgVersion global variable was deprecated in MW 1.35, in favour of a new
// constant.  All code should use the constant rather than the variable, but for
// backwards compatibility we create the constant if it is not already defined.
// Note that the constant was back-ported to other release branches, but was not
// present in the *.0 release, so they do not affect the minimum version requirements
// for removing this shim.
// @back-compat MW < 1.35
	if (!defined("MW_VERSION"))
		define("MW_VERSION", $wgVersion);
 
// Setup version number
	$pMCExt_Version = '$Rev: 2439 $';
	$pMCExt_Version = substr($pMCExt_Version, 6, -2);
// Setup extension credits
	$wgExtensionCredits['other'][] = array(
		'name' => 'WikiDebug',
		'version' => "r" . $pMCExt_Version,
		'author' => 'Mark Clements',
		'description' => "A set of debugging tools for extension developers",
		'url' => 'http://www.kennel17.co.uk/testwiki/Debugging%20tools',
	);
// Tidy up
	unset($pMCExt_Version);
 
	if (!isset($wgWikiDebug_ViewableTables))
		$wgWikiDebug_ViewableTables = array();
	if (!isset($wgWikiDebug_ViewableFiles))
		$wgWikiDebug_ViewableFiles = array();
 
	$pWikiDebug_Messages = array(
	// Messages for wfWikiDebug_DescribeTable()
		'debug_table_header' => "Live Table Definition: $1",
		'debug_no_table' => "No table specified.",
		'debug_table_not_found' => "Table cannot be viewed.  It either does not "
								   . "exist, or is protected against viewing.",
		'debug_no_fields' => "No fields found.",
		'debug_index_header' => "Indexes",
		'debug_no_indexes' => "No indexes defined.",
		'debug_error_reading_tabledef' => "There was an error reading the table "
										  . "definition!",
 
	// Messages for wfWikiDebug_ShowSource() and wfWikiDebug_ShowRevision()
		'debug_file_header' => "Live source code viewer: $1",
		'debug_last_modified' => "Last modified: $1",
		'debug_no_file' => "No file specified.",
		'debug_file_blocked' => "File cannot be viewed.  It either does not exist, "
								. "or is protected against viewing.",
		'debug_file_blocked_short' => "File not found",
		'debug_file_unreadable' => "File cannot be read.",
		'debug_no_version' => "version unknown",
		'debug_version' => "rev \$1",
	);
 
// DB_PRIMARY was introduced in MW 1.36, at which point DB_MASTER was made into an
// alias.
// To maintain support for older versions of MediaWiki, if DB_PRIMARY is not defined,
// then we define it here.
// @back-compat MW < 1.36
	if (!defined("DB_PRIMARY")) {
		define("DB_PRIMARY", DB_MASTER);
	}
 
// Parser hooks.
// The ParserFirstCallInit hook was added in MediaWiki 1.12.
// For older versions, of MediaWiki, we manually call the hook function as part of
// the main extension registration function, as this hook is ignored.
	$wgHooks['ParserFirstCallInit'][] = "wfWikiDebug_RegisterParserHooks";
 
	function wfWikiDebug_RegisterParserHooks(&$Parser) {
	// Specific tags to be parsed
		$Parser->setHook( "describe_table", "wfWikiDebug_DescribeTable" );
		$Parser->setHook( "show_source", "wfWikiDebug_ShowSource" );
		$Parser->setHook( "show_revision", "wfWikiDebug_ShowRevision" );
 
	// We also accept <show_version> as an alias for <show_revision>, for
	// backwards-compatibility reasons.
		$Parser->setHook( "show_version", "wfWikiDebug_ShowRevision" );
 
		return true;
	}
 
	$wgExtensionFunctions[] = "wfWikiDebug";
	function wfWikiDebug() {
		global $wgMessageCache, $wgParser, $wgHooks;
		global $pWikiDebug_Messages, $wgWikiDebug_ViewableFiles;
 
	// Define the extension's messages.
	// If the old-style $wgMessageCache object is available then use this, as it
	// gives a better result (the messages are defined, and are editable via
	// Special:AllMessages).
	// If the $wgMessageCache object is not defined, we instead use the
	// MessagesPreLoad hook, to populate the message keys with our strings.
	// This is less good as (a) the messages won't show up for editing on
	// Special:AllPages; and (b) I suspect it is detrimental to performance.
	// However, it does mean that our messages will appear correctly in the
	// interface, and if you manually create the appropriate page in the
	// MediaWiki namespace, then the local version will be correctly used.
	// TODO: Is there a better way of handling it that resolves the above issues?
	//		 The LocalisationCacheRecache hook looked promising, but doesn't seem
	//		 to work well enough for us (it seems not to run, presumably because
	//		 a recache needs to be triggered somehow).
		if (is_object($wgMessageCache)) {
			$wgMessageCache->addMessages($pWikiDebug_Messages);
		}
		else {
			$wgHooks['MessagesPreLoad'][] = "wfWikiDebug_PreloadMessage";
		}
 
	// If this is MediaWiki < 1.12, then the ParserFirstCallInit hook does not exist,
	// therefore we manually call our hook registration function with the global
	// Parser object.
	// @back-compat MW < 1.12
		if (version_compare(MW_VERSION, '1.12', '<')) {
			wfWikiDebug_RegisterParserHooks($wgParser);
			wfWikiDebug_SetupParserFunctions($wgParser);
		}
 
	// Tidy all paths in the list of viewable files, to ensure that directory
	// separators are treated in a system-agnostic fashion.
		foreach ($wgWikiDebug_ViewableFiles as $Key => $Path)
			$wgWikiDebug_ViewableFiles[$Key] = pwfWikiDebug_TidyPath($Path);
	}
 
	function wfWikiDebug_DescribeTable($Input, $Args, $Parser = null) {
		global $wgParser;
		global $wgWikiDebug_ViewableTables;
 
	// The $Parser argument was added in MediaWiki 1.5.8.  Therefore, to keep
	// compatibility with older versions, we need to default the function argument
	// to null and default to the global $wgParser argument if it is not set.
	// @back-compat MW < 1.5.8
		if (!isset($Parser))
			$Parser = $wgParser;
 
		WikiDebug_DisableCache($Parser);
 
		if (isset($Args['table']))
			$TableName = $Args['table'];
		else
			$TableName = "";
		$Output = "<h3>"
				. WikiDebug_Msg('debug_table_header', $TableName)
				. "</h3>\n";
 
		if ($TableName == "")
			$Output .= WikiDebug_Msg('debug_no_table');
 
		elseif (!in_array($TableName, $wgWikiDebug_ViewableTables))
			$Output .= WikiDebug_Msg('debug_table_not_found');
 
		else {
 
			$DB = wfGetDB(DB_PRIMARY);
 
			if ($DB->tableExists($TableName)) {
 
			// Get the requested display mode.
				$Display = "sql";
				if (isset($Args['display']))
					$Display = strtolower(trim($Args['display']));
 
			// Output the data according to the display mode.
				switch ($Display) {
					case "tables":
					case "table":
					// Get field data from table
						$objResult = $DB->query("DESCRIBE "
												. $DB->tableName($TableName) . ";");
						$Fields = array();
						while ( $row = $objResult->fetchObject() )
							$Fields[] = $row;
 
						$objResult->free();
 
					// If required, get index data from table
						$ShowIndexes = true;
						if (isset($Args['showindexes'])) {
							switch (strtolower(trim($Args['showindexes']))) {
								case "0":
								case "false":
									$ShowIndexes = false;
							}
						}
						$Indexes = array();
						if ($ShowIndexes) {
							$objResult = $DB->query("SHOW INDEX FROM "
													. $DB->tableName($Args['table'])
													. ";");
							while ( $row = $objResult->fetchObject() )
								$Indexes[] = $row;
 
							$objResult->free();
						}
 
						if (count($Fields) == 0)
							$Output .= WikiDebug_Msg('debug_no_fields');
 
						else {
							$Output .= '<table border="1" cellpadding="5" '
									 . 'cellspacing="2"><tr>';
							foreach ($Fields[0] as $RowHeader => $Row)
								$Output .= '<th>' . $RowHeader . '</th>';
							foreach ($Fields as $Row) {
								$Output .= '<tr>';
								foreach ($Row as $RowValue) {
									if ($RowValue === null || $RowValue == "")
										$RowValue = "&nbsp;";
									$Output .= '<td>' . $RowValue . '</td>';
								}
								$Output .= '</tr>';
							}
							$Output .= '</table>';
 
							if ($ShowIndexes) {
								$Output .= "<h3>"
										 . WikiDebug_Msg('debug_index_header')
										 . "</h3>\n";
 
								if (count($Indexes) > 0) {
									$Output .= '<table border="1" cellpadding="5" '
											 . 'cellspacing="2"><tr>';
									foreach ($Indexes[0] as $RowHeader => $Row) {
										if ($RowHeader != "Table")
											$Output .= '<th>' . $RowHeader . '</th>';
									}
									foreach ($Indexes as $Row) {
										$Output .= '<tr>';
										foreach ($Row as $RowHeader => $RowValue) {
											if ($RowHeader != "Table") {
												if ($RowValue === null
													|| $RowValue == "")
												{
													$RowValue = "&nbsp;";
												}
												$Output .= '<td>' . $RowValue
														 . '</td>';
											}
										}
										$Output .= '</tr>';
									}
									$Output .= '</table>';
								}
								else {
									$Output .= "&nbsp;&nbsp;&nbsp;"
											 . WikiDebug_Msg('debug_no_indexes');
								}
							}
						}
 
						break;
 
					case "sql":
					default:
					// Get field data from table
						$objResult = $DB->query("SHOW CREATE TABLE "
												. $DB->tableName($TableName) . ";");
						if ($objResult !== false && $row = $objResult->fetchObject())
						{
							$SQL = "";
							foreach ($row as $key => $val) {
								if ($key = "Create Table") {
									$SQL = htmlspecialchars($val, ENT_COMPAT,
															"UTF-8");
								}
							}
 
							$Removables = array(
								"/character set .* /Ui",
								"/collate .* /Ui",
								"/ ?DEFAULT CHARSET=.*( |$)/Ui",
								"/ ?COLLATE=.*( |$)/Ui",
								"/ ?AUTO_INCREMENT\s*=\s*([0-9])+/",
							);
							$SQL = preg_replace($Removables, "", $SQL);
 
							$Search = array(
								"/^CREATE TABLE " . $DB->tableName($TableName)
									. "/i",
								"/TYPE=(.*)( |$)/Ui",
								"/^/m",		// Space at the start of the line, to
											// ensure <pre> block works properly.
								"/([^;])$/",
							);
							$Replace = array(
								"CREATE TABLE IF NOT EXISTS `" . $TableName . "`",
								"ENGINE=$1$2",
								" ",
								"$1;",
							);
							$SQL = preg_replace($Search, $Replace, $SQL);
							$Output .= $SQL . "\n";
						}
 
						else
							$Output .= WikiDebug_Msg('debug_error_reading_tabledef');
 
						if ($objResult !== false)
							$objResult->free();
				}
			}
 
			else
				$Output .= WikiDebug_Msg('debug_table_not_found');
		}
 
		$Output = '<div style="border: 1px solid #AAAAAA; '
				. 'background-color: #EEEEEE; padding: 1em;">' . $Output . '</div>';
		return $Output;
	}
 
	function wfWikiDebug_ShowSource($Input, $Args, $Parser = null) {
		global $wgOut, $wgParser;
 
	// The $Parser argument was added in MediaWiki 1.5.8.  Therefore, to keep
	// compatibility with older versions, we need to default the function argument
	// to null and default to the global $wgParser argument if it is not set.
	// @back-compat MW < 1.5.8
		if (!isset($Parser))
			$Parser = $wgParser;
 
		WikiDebug_DisableCache($Parser);
		$AllowPHPOutput = false;
		$OutputIsAlreadyEscaped = false;
 
		if (isset($Args['file']))
			$FileName = $Args['file'];
		else
			$FileName = "";
		$Header = WikiDebug_Msg('debug_file_header', $FileName);
 
		if ($FileName == "") {
			$Output = WikiDebug_Msg('debug_no_file');
			$OutputIsAlreadyEscaped = true;
		}
 
		else {
			$FilePath = pwfWikiDebug_GetRealPath($FileName);
			if (!$FilePath) {
				$Output = WikiDebug_Msg('debug_file_blocked');
				$OutputIsAlreadyEscaped = true;
			}
 
			elseif (($File = @fopen($FilePath, "r", true)) === false) {
				$Output = WikiDebug_Msg('debug_file_unreadable');
				$OutputIsAlreadyEscaped = true;
			}
 
			else {
			// Get last modified date
				$ModDate = date("Y-m-d h:i:s", filemtime($FilePath));
				$Header .= "<br><span style=\"font-size: 80%; "
						 . "font-weight: normal;\">"
						 . WikiDebug_Msg('debug_last_modified', $ModDate)
						 . "</span>";
 
			// Get length of file.
				fseek($File, 0, SEEK_END);
				$Length = ftell($File);
				fseek($File, 0, SEEK_SET);
 
			// Get contents of file.
				$Output = fread($File, $Length);
 
			// We don't care about read errors and we don't report them.  Therefore,
			// convert any error results to an empty string.
				if (!is_string($Output))
					$Output = "";
 
			// If it was a PHP file and was successfully read, then enable the
			// PHP syntax-highlighter (if installed).
			// We detect this by seeing if the file contains the opening PHP tag.
				if (strpos($Output, "<?") !== false)
					$AllowPHPOutput = true;
 
			// Convert file to UTF-8, if we detect that it is in a different
			// encoding.
			// This can only be done if the multi-byte extension is enabled.  If not,
			// we currently just output the file in its raw format, which may result
			// in encoding errors.
			// TODO: Is there a better way of handling situations where we can't
			//		 detect the encoding (e.g. error message)?  Are there alternative
			//		 detection methods (e.g. built into MediaWiki)?
				if (function_exists("mb_detect_encoding")) {
				// The supported encodings are UTF-8 and CP1252.
				// The ordering is important - if these are the other way round then
				// CP1252 will always be detected as it covers all code points.
				// Note that CP1252 is a superset of ISO-8859-1, so this will also
				// correctly detect ISO-8859-1 encoding.
				// TODO: Are there other encodings that should be included in this
				//		 list?
					$SupportedEncodings = 'UTF-8, CP1252';
 
				// Detect the encoding.  Note that, because CP1252 is a
				// single-byte encoding with no invalid values, we won't ever fail
				// to detect something.
					$Encoding = mb_detect_encoding($Output, $SupportedEncodings,
												   true);
 
				// Perform the conversion.
				// TODO: Is it safe to assume our output is always UTF-8?
					$Output = iconv($Encoding, "UTF-8", $Output);
				}
			}
		}
 
		$Header = "<h3>" . $Header . "</h3>\n";
 
		if ($AllowPHPOutput && isset($Parser->mTagHooks['php'])) {
		// This can easily use more than the standard available memory, so remove
		// limit.
			$MemLimit = ini_get('memory_limit');
			ini_set('memory_limit', -1);
			$Output = $Header . call_user_func($Parser->mTagHooks['php'],
											   $Output, array(), $Parser);
			ini_set('memory_limit', $MemLimit);
		}
		else {
			if (!$OutputIsAlreadyEscaped)
				$Output = htmlspecialchars($Output, ENT_COMPAT, "UTF-8");
 
			$Output = "<pre>" . $Header . $Output . "</pre>";
		}
 
		return $Output;
	}
 
	function wfWikiDebug_ShowRevision($Input, $Args, $Parser = null) {
		global $wgOut, $wgParser;
 
	// The $Parser argument was added in MediaWiki 1.5.8.  Therefore, to keep
	// compatibility with older versions, we need to default the function argument
	// to null and default to the global $wgParser argument if it is not set.
	// @back-compat MW < 1.5.8
		if (!isset($Parser))
			$Parser = $wgParser;
 
		WikiDebug_DisableCache($Parser);
 
		if (isset($Args['file']))
			$FileName = $Args['file'];
		else
			$FileName = "";
 
		if ($FileName == "")
			$Output = WikiDebug_Msg('debug_no_file');
 
		else {
			$FilePath = pwfWikiDebug_GetRealPath($FileName);
			if (!$FilePath)
				$Output = WikiDebug_Msg('debug_file_blocked');
 
			elseif (($File = @fopen($FilePath, "r", true)) === false)
				$Output = WikiDebug_Msg('debug_file_unreadable');
 
			else {
			// Get length of file.
				fseek($File, 0, SEEK_END);
				$Length = ftell($File);
			    fseek($File, 0, SEEK_SET);
 
			// Get contents of file.
				$Contents = fread($File, $Length);
 
			// We don't care about read errors and we don't report them.  Therefore,
			// convert any error results to an empty string.
				if (!is_string($Contents))
					$Contents = "";
 
				$VersionRegex = '/(?:\$Rev:|\$LastChangedRevision:|\$Revision:|) '
							  . '?([0-9]+) ?\$/Ui';
				$Result = preg_match($VersionRegex, $Contents, $matches);
				if (count($matches) > 0)
					$Output = WikiDebug_Msg('debug_version', $matches[1]);
				else
					$Output = WikiDebug_Msg('debug_no_version');
			}
		}
 
		return "<i>(" . $Output . ")</i>";
	}
 
/////////////////////////// PARSER FUNCTIONS ///////////////////////////
// MW 1.7 and above, only.
 
// SETUP FUNCTIONS
 
// The ParserFirstCallInit hook was added in MediaWiki 1.12.
// For older versions, of MediaWiki, we manually call the hook function as part of
// the main extension registration function, as this hook is ignored.
	$wgHooks['ParserFirstCallInit'][] = 'wfWikiDebug_SetupParserFunctions';
	$wgHooks['LanguageGetMagic'][]	  = 'wfWikiDebug_SetupLanguageMagic';
 
	function wfWikiDebug_SetupParserFunctions(&$Parser) {
		$Parser->setFunctionHook('IfExtensionPresent',
								 'wfWikiDebug_IfExtensionPresent');
        return true;
	}
 
	function wfWikiDebug_SetupLanguageMagic(&$MagicWords) {
	// Add the magic word.
	// Set first array element to 0 to indicate non-case-sensitivity.
	// Additional elements are synonyms.
		$MagicWords['IfExtensionPresent'] = array(1, 'IfExtensionPresent');
 
	// Return true, so other parser hooks execute properly.
		return true;
	}
 
// INDIVIDUAL PARSER FUNCTIONS
 
	function wfWikiDebug_IfExtensionPresent($Parser, $Param1 = "", $Param2 = "",
											$Param3 = "")
	{
		global $wgExtensionCredits;
 
		$Matched = false;
		foreach ($wgExtensionCredits as $Type => $Extensions) {
			foreach ($Extensions as $Extension) {
				if (isset($Extension['name']) && $Extension['name'] == $Param1) {
					$Matched = true;
					break 2;
				}
			}
		}
 
		if ($Matched)
			return $Param2;
		else
			return $Param3;
	}
 
/////////////////////////// SUPPORT FUNCTIONS ///////////////////////////
 
// pwfWikiDebug_GetRealPath()
// Takes a $FileName argument, and checks that (a) the file exists in the
// include paths and (b) it is in the list of viewable files.
// If it fails either of these tests, the function returns false, indicating that
// the file cannot be viewed (there is deliberately no distinction between the
// different reasons why it may not be viewable).
// If it succeeds, and the file exists and is on the white list, then the real
// path to the file is returned.
// The function does not check whether the file is readable by the web user.
	function pwfWikiDebug_GetRealPath($FileName) {
		$FileName = pwfWikiDebug_TidyPath($FileName);
 
	// First, check that the file exists in the include path.  We do this first
	// as it will allow us to use realpath() in the CanViewFile() function if we
	// need to (currently it isn't used, but at one point it was thought to be
	// required and I'm not sure that I won't change my mind again in the future).
		$FilePath = pwfWikiDebug_file_exists_incpath($FileName);
		if (!$FilePath)
			return false;
 
	// If file exists, check it is viewable.
		if (!pwfWikiDebug_CanViewFile($FileName))
			return false;
 
		return $FilePath;
	}
 
// pwfWikiDebug_file_exists_incpath()
// For relative paths, checks if the file exists in the include path and returns
// the full path of where it was found if it does, or false if not.
// For absolute paths, it doesn't check the include path - it just returns the
// supplied $File path if it exists, or false if not.
// Function was modified from file_exists_incpath() - credits follow:
/**
 * Check if a file exists in the include path
 *
 * @version     1.2.1
 * @author      Aidan Lister <aidan@php.net>
 * @link        http://aidanlister.com/repos/v/function.file_exists_incpath.php
 * @param       string     $File       Name of the file to look for
 * @return      mixed      The full path if file exists, FALSE if it does not
 */
	function pwfWikiDebug_file_exists_incpath($File) {
 
	// If this is an absolute path, then we don't need to resolve it in terms
	// of the include path - just check whether the file exists.
		if (in_array(substr($File, 0, 1), array("\\", "/"))) {
			if (file_exists($File))
				return $File;
		}
 
	// Otherwise it is a relative path, so look for it in each of the include
	// directories, selecting the first directory in which the file is found.
		else {
			$arrPaths = explode(PATH_SEPARATOR, ini_get('include_path'));
			foreach ($arrPaths as $Path) {
			// Skip over any blank paths.
				if ($Path != "") {
				// Formulate the absolute path, and if the file exists there,
				// return it.
					$FullPath = $Path . "/" . $File;
					if (file_exists($FullPath))
						return $FullPath;
				}
			}
		}
 
	// If the file was not found in the path, return false.
		return false;
	}
 
// pwfWikiDebug_CanViewFile()
// Returns true if the named file is viewable according to the settings in
// $wgWikiDebug_ViewableFiles.  This is an array of files/directories.  If the
// entry is a directory, all of it's contents, including sub-directories, are
// viewable.
	function pwfWikiDebug_CanViewFile($FileName) {
		global $wgWikiDebug_ViewableFiles;
 
	// If the supplied filename is in the list of viewable files, then return
	// true.
		if (in_array($FileName, $wgWikiDebug_ViewableFiles))
			return true;
 
	// Otherwise, if there are any directories in the list of viewable files,
	// return true if this file is within one of those directories.
		foreach ($wgWikiDebug_ViewableFiles as $ViewableFile) {
		// Ensure the path ends in a directory separator.  This doesn't cause
		// any problems if the file is not a directory, as we separately test
		// that the full path exists.
			if (substr($ViewableFile, -1) != "/")
				$ViewableFile .= "/";
 
		// If the path of the $ViewableFile (including trailing backslash) matches
		// the start of the file we are checking permission for, then the file is
		// inside the viewable directory, so we return true.
		// TODO: We could be a bit smarter about matching files which are
		//		 directories (i.e. allowing them to be specified with or without
		//		 a trailing slash) but this isn't required at the moment.  It needs
		//		 fixing at the point where we have any tags that can operate on
		//		 directories (e.g. <file_list> to provide a directory listing, or
		//		 <zip> tag to zip up the contents of a directory).
		//		 (Actually, as far as I can tell this is only a problem if the
		//		 ViewableFiles array contains entries with trailing slashes, as the
		//		 other way round will still result in a match - and this can be
		//		 fixed in wfWikiDebug if necessary.  Some more thought required,
		//		 though).
			if (strpos($FileName, $ViewableFile) === 0)
				return true;
		}
 
		return false;
	}
 
// pwfWikiDebug_TidyPath()
// Converts Windows-like back-slash characters to Unix-like forward-slashes.
// Forward slashes work on both systems, so are always safe to use, and this
// conversion ensures that any file paths are treated in a system-agnostic way.
	function pwfWikiDebug_TidyPath($Path) {
		return str_replace("\\", "/", $Path);
	}
 
	function wfWikiDebug_PreloadMessage($Title, &$Message) {
		global $pWikiDebug_Messages;
 
	// As message names are page titles, MW normalises them to have an upper-case
	// first character.
	// We therefore need to force them back to lower-case in order to check against
	// our array.
		$Title = strtolower($Title);
 
		if (isset($pWikiDebug_Messages[$Title])) {
			$Message = $pWikiDebug_Messages[$Title];
		}
 
		return true;
	}
 
// WikiDebug_Msg()
// Returns the text of the specified system message, using any additional arguments
// for variable replacement.
// Functionally equivalent to wfMsg(), which is the original way of handling this
// in MediaWiki.  However, this was deprecated in favour of wfMessage() and the new
// Message class in MW 1.17 and removed altogether in MW 1.27.
// This wrapper function calls wfMessage() if available, otherwise wfMsg(), and
// in both cases returns the expanded string (not a Message object).  As well as
// ensuring compatibility across MediaWiki versions, using this function simplifies
// our code as it doesn't need to explicitly call text() to get the output string.
// Note that the only difference between this and wfMsg() is that it benefits from
// some bug fixes that were applied to the wfMessage() implementation, namely that
// variable substitution now happens before template expansion, so constructs such
// as {{PLURAL:$1|egg|eggs}} now work as expected.
	function WikiDebug_Msg($Key) {
		$Args = func_get_args();
 
		if (function_exists("wfMessage")) {
			$objMessage = call_user_func_array("wfMessage", $Args);
			return $objMessage->text();
		}
		else {
			return call_user_func_array("wfMsg", $Args);
		}
	}
 
// WikiDebug_DisableCache()
// Prevents the results of the current parse from being cached.  This makes most
// sense in the context of parsing a full page, but may make sense in other parsing
// contexts, too.
// Primarily provided for backwards-compatibility reasons, but may still be useful
// when older MW versions no longer need to be supported, for clarity and brevity.
	function WikiDebug_DisableCache($objParser) {
	// Prior to MW 1.28, you simply called disableCache() on the Parser instance in
	// order to disable the cache.  In MW 1.28 this was deprecated and it was
	// ultimately removed in MW 1.35.
	// Note that we need a version check here as this can't be feature-detected.  All
	// relevant functions have existed since at least MW 1.17 and we don't want to
	// call disableCache() after deprecation, as it will emit notices.
	// TODO: Although the deprecation was made in MW 1.28, it is possible that the
	//		 new technique worked correctly in older MW versions.  It may therefore
	//		 be possible to turn this into a feature-detection check after all.
	// @back-compat MW < 1.28
		if (version_compare(MW_VERSION, "<", "1.28")) {
			$objParser->disableCache();
		}
	// In more recent MediaWiki versions, you need to first retrieve the ParserOutput
	// object from the Parser and then set the cache expiry to zero seconds.
	// TODO: Although the deprecation was made in MW 1.28, it is possible that the
	//		 new technique worked correctly in older MW versions.  It may therefore
	//		 be possible to turn this into a feature-detection check after all.
		else {
			$objParserOutput = $objParser->getOutput();
			$objParserOutput->updateCacheExpiry(0);
		}
	}


Example 2: Non-viewable file

Here is an attempt to view LocalSettings.php. Because this file is not in the array of allowed files, you are unable to see it's contents:

<show_source file="LocalSettings.php"></show_source>

Live sourcecode viewer: LocalSettings.php

File cannot be viewed. It either does not exist, or is protected against viewing.