<?php

if( $_REQUEST['src'] == '' || $_REQUEST['dest'] == '' ) {
	echo '
<html>
<head><title>FastBacklinks starter</title></head>
<body>
<h1>FastBacklinks starter</h1>
<h2>Goal:</h2>
<p>The script was created to make the
<a href="http://pmwiki.org/wiki/Cookbook/FastBacklinks">FastBacklinks</a> recipe for
<a href="http://pmwiki.org">PmWiki</a> easier to use. It pre-generates all data
required by the script, so that you don\'t need to manually touch every Wiki page
after installing the recipe. Follow the instructions below to use it.</p>

<h2>Usage:</h2>
<p>This script should be executed <b>after</b> you install the
<a href="http://pmwiki.org/wiki/Cookbook/FastBacklinks">FastBacklinks</a> recipe in
your PmWiki installation. It prepares all required backlinks data, based on existing
Wiki data in a specified directory.</p>
<p>The script should be best put in your main PmWiki directory - in the same directory
where you have the <tt>pmwiki.php</tt> file.</p>
<p>The script should be run for each directory you have Wiki data, that is
in a standard, non-WikiFarm installation, you should run it two times, with the
<em>Source Directory</em> option set to, in specified order:</p>
<ol>
<li><tt>wikilib.d</tt></li>
<li><tt>wiki.d</tt></li>
</ol>
<p>Two steps with those directories already set have been prepared below for your
convenience. If you have your data in other directories, you must change the
<em>Source Directory</em> options in those steps accordingly.</p>

<h2>Note:</h2>
<ul>
<li>This script may take a fairly <b>long time</b> to proceed in Step 2, especially if your
Wiki is big. Please note also, that the script is <b>not guaranteed to succeed</b>,
especially on big Wikis. That\'s because PHP scripts execution time is often
limited, usually to 30 seconds. You might want to talk to your webspace
provider to extend that time temporarily to allow full script execution if you
notice the script doesn\'t finish it\'s work.</li>
<li><b>Never</b> link to this page from anywhere! You may safely remove this file
after you\'ve used it, and you should do so, unless you know what you\'re doing.</li>
</ul>';

TimeoutExtend();

echo '

<hr />

<h2>Step 1:</h2>
<form action="' . $PHP_SELF . '" method="GET">
<label for="src">Source Directory:</label>
<input id="src" name="src" value="wikilib.d" />
<br />
<label for="src">Destination Directory:</label>
<input id="src" name="dest" value="backlinks.d" />
<br />
<input type="submit" value="Generate" />
</form>

<hr />

<h2>Step 2:</h2>
<form action="' . $PHP_SELF . '" method="GET">
<label for="src">Source Directory:</label>
<input id="src" name="src" value="wiki.d" />
<br />
<label for="src">Destination Directory:</label>
<input id="src" name="dest" value="backlinks.d" />
<br />
<input type="submit" value="Generate" />
</form>

</body>
</html>
';
exit;
}

echo( '<html><head><title>FastBacklinks generation</title></head>
<body><h2>FastBacklinks generation started, please wait...</h2>
');

## Trying to extend the PHP's script execution timeout
TimeoutExtend();

flush();
ob_flush();

$src =  rtrim( $_REQUEST['src'], '/' );
$dest = rtrim( $_REQUEST['dest'], '/' );

mkdirp($dest);

$dh = opendir( $src );
if( $dh === false )
	Abort( "Error opening directory \'<tt>$src</tt>\'." );

$targets_str = 'targets=';
$targets_len = strlen( $targets_str );

## Start measuring time.
$starttime = microtime();

while (($wikifname = readdir($dh)) !== false) {
	$wikifile = $src . '/' . $wikifname;
#	echo( trim($wikifile) . ' = ' );

	$wikifile = @file( $wikifile );
/* #### Version 1 - substr()
	foreach( $wikifile as $line ) {
		if( substr( $line, 0, $targets_len ) == $targets_str ) {
			echo( $line );
			break;
		}
	}
*/ ####
/* #### Version 2 - strpos()
	foreach( $wikifile as $line ) {
		if( strpos( $line, 'targets=' ) === 0 ) {
			echo( $line );
			break;
		}
	}
*/ ####
/* #### Version 3 - preg_match() + implode()
	$wikifile = implode( '', $wikifile );
	$matches = array();
	if( preg_match( '/\ntargets=.*?\n/', $wikifile, $matches ) ) {
		echo( $matches[0] );
	}
*/ ####
 #### Version 4 - strpos() + implode()
	$wikifile = implode( '', $wikifile );
	$start = strpos( $wikifile, 'targets=' );
	if( $start !== false ) {
		$start += $targets_len;
		$end = strpos( $wikifile, "\n", $start );
		if( $end !== false ) {
			#echo( substr( $wikifile, $start, $end-$start ) );
			$targets = substr( $wikifile, $start, $end-$start );
		}
	}
 ####

	$targets = trim($targets);
	if( !$targets ) continue;
	$targets = explode( ',', $targets );

	## Adding backlink info to each target.
	foreach( $targets as $t ) {
		$fh = @fopen( $dest . '/' . $t, 'a' );
		if( $fh === false ) {
			Warn( "Error opening file '<tt>$dest/$t</tt>' for appending!" );
			break;
		}
		fwrite( $fh, $wikifname . "\n" );
		fclose( $fh );
		fixperms( $dest . '/' . $t );
	}

#	echo( '<br />' );
}

## Stop measuring time, show the result.
$stoptime = microtime();

$starttime = array_sum( explode( ' ', $starttime ) );
$stoptime  = array_sum( explode( ' ', $stoptime  ) );

closedir($dh);

echo '<h2>FastBacklinks generation ended</h2>';
echo '<p>Please, press the "Back" button and proceed to next step, if any.</p>';

echo '<div style="font-style: italic; border: 2px solid black; font-size: large;">
Backlinks generated in ' . 
sprintf("%01.5f",$stoptime-$starttime) .
' sec</div>';

echo "<p>Source directory was: <tt>$src</tt>, Destination directory was: <tt>$dest</tt>.</p>";



function Warn( $t ) {
	echo "<b>Warning: $t</b> - Backlinks generation may not be completed!<br /> ";
}

## Thanks to haganfox at gmail.com for the idea. Hope it helps.
function TimeoutExtend() {
	$timeout = ini_get('max_execution_time');
	echo( '<p>PHP script execution timeout defaults here to: ' . $timeout . ' sec. ' );
	if( ini_get('safe_mode') ) {
		echo 'Unfortunately, <tt>safe_mode</tt> is set, so we cannot extend it, ' .
			'but don\'t worry, there may not be any problem.';
	} else {
		$timeout = max( $timeout, 10*60 );
		echo 'New timeout will now be set to: ' . 
			$timeout . ' sec (' . $timeout/60 . ' min).';
		ini_set( 'max_execution_time', $timeout );
	}
	echo '</p>';

}

###############################################
## Required PmWiki functions extract
## (from: pmwiki.php, by Patrick Michaud)

## mkdirp creates a directory and its parents as needed, and sets
## permissions accordingly.
function mkdirp($dir) {
  global $ScriptUrl;
  if (file_exists($dir)) return;
  if (!file_exists(dirname($dir))) mkdirp(dirname($dir));
  if (mkdir($dir, 0777)) {
    fixperms($dir);
    if (@touch("$dir/xxx")) { unlink("$dir/xxx"); return; }
    rmdir($dir);
  }
  $parent = realpath(dirname($dir)); 
  $perms = decoct(fileperms($parent) & 03777);
  $msg = "PmWiki needs to have a writable <tt>$dir/</tt> directory 
    before it can continue.  You can create the directory manually 
    by executing the following commands on your server:
    <pre>    mkdir $parent/$dir\n    chmod 777 $parent/$dir</pre>
    Then, <a href='$ScriptUrl'>reload this page</a>.";
  $safemode = ini_get('safe_mode');
  if (!$safemode) $msg .= "<br /><br />Or, for a slightly more 
    secure installation, try executing <pre>    chmod 2777 $parent</pre> 
    on your server and following <a target='_blank' href='$ScriptUrl'>
    this link</a>.  Afterwards you can restore the permissions to 
    their current setting by executing <pre>    chmod $perms $parent</pre>.";
  Abort($msg);
}

## fixperms attempts to correct permissions on a file or directory
## so that both PmWiki and the account (current dir) owner can manipulate it
function fixperms($fname, $add = 0) {
  clearstatcache();
  if (!file_exists($fname)) Abort('no such file');
  $bp = 0;
  if (fileowner($fname)!=fileowner('.')) $bp = (is_dir($fname)) ? 007 : 006;
  if (filegroup($fname)==filegroup('.')) $bp <<= 3;
  $bp |= $add;
  if ($bp && (fileperms($fname) & $bp) != $bp)
    @chmod($fname,fileperms($fname)|$bp);
}


function Abort($msg) {
  # exit pmwiki with an abort message
  echo "<h3>FastBacklinks-starter script can't process your request</h3>
    <p>$msg</p><p>We are sorry for any inconvenience.</p>";
  exit;
}