User:Quietust/wtf23a.php

From Dwarf Fortress Wiki
Jump to navigation Jump to search
<?php
function readByte ($file)
{
	$x = fread($file, 1);
	$pck = @unpack('Cdata', $x);
	return $pck['data'];
}

function readLong ($file)
{
	$x = fread($file, 4);
	$pck = @unpack('Vdata', $x);
	return $pck['data'];
}

function writeLong ($file, $data)
{
	$x = @pack('V', $data);
	fwrite($file, $x, 4);
}

class rng
{
	var $data = array();
	var $index = 0;

	function init ($data)
	{
		for ($i = 0; $i < 624; $i++)
			$this->data[$i] = $data[$i];
		$this->index = $data[624] / 4;
	}
	function get ($i)
	{
		$x = $this->next();
		if ($x < 0)
			return (int)fmod($x + 4294967296.0, $i);
		return $x % $i;
	}
	function next()
	{
		if ($this->index == 624)
			$this->generate();
		return $this->data[$this->index++];
	}
	function generate()
	{
		for ($i = 0; $i < 624; $i++)
		{
			$y = ($this->data[$i] & 0x80000000) | ($this->data[($i+1) % 624] & 0x7FFFFFFF);
			$this->data[$i] = $this->data[($i + 397) % 624] ^ (($y >> 1) & 0x7FFFFFFF);
			if ($y & 1)
				$this->data[$i] ^= 0x9908b0df;
		}
		$this->index = 0;
	}
}

function _readCrypt ($file)
{
	// read mt state
	$state = array();
	for ($i = 0; $i < 625; $i++)
		$state[$i] = readLong($file);
	if (feof($file))
		return false;

	// read header
	$len = readLong($file);
	$data = range(0, $len - 1);

	$rng = new rng;

	// read data, skipping dummy bytes
	$rng->init($state);
	for ($i = $len - 1; $i >= 0; $i--)
	{
		$data[$i] = readByte($file);
		if ($rng->get(2))
		{
			$rng->get(256);
			readByte($file);
		}
	}

	// decode data
	$rng->init($state);
	for ($i = $len - 1; $i >= 0; $i--)
		$data[$i] -= $rng->get(10);

	// convert to string
	$out = '';
	for ($i = 0; $i < $len; $i++)
		$out .= chr($data[$i] & 0xFF);
	return $out;
}

function _writeCrypt ($file, $data)
{
	// write mt state
	for ($i = 0; $i < 625; $i++)
		writeLong($file, 0);

	// write header
	$len = strlen($data);
	writeLong($file, $len);

	// write data
	// since mt state is null, this is much simpler than above
	for ($i = $len; $i > 0; $i--)
		fwrite($file, $data[$i-1], 1);
}

function compress_file ($in, $out)
{
	while (1)
	{
		$data = fread($in, 20000);
		$comp = gzcompress($data, 9);
		if ($comp === FALSE)
			return false;

		_writeCrypt($out, $comp);
		if (feof($in))
			break;
	}
	return true;
}

function decompress_file ($in, $out)
{
	while (1)
	{
		$block = _readCrypt($in);
		if ($block === FALSE)
			break;
		$decomp = gzuncompress($block);
		if ($decomp === FALSE)
			return false;
		fwrite($out, $decomp);
	}
	return true;
}

function unpack_file ($in, $out)
{
	$numrecords = readLong($in);
	for ($i = 0; $i < $numrecords; $i++)
	{
		$len = readLong($in);
		if ($len < 1)
			return false;
		$str = fread($in, $len);
		if (feof($in))
			return false;
		if ($out)
			fwrite($out, "$str\r\n");
		else	echo "$str\n";
		fread($in, 1);
	}
	return true;
}

function pack_file ($in, $out)
{
	$data = explode("\n", trim(stream_get_contents($in)));
	$numrecords = count($data);
	writeLong($out, $numrecords);
	for ($i = 0; $i < $numrecords; $i++)
	{
		$line = trim($data[$i]);
		$len = strlen($line);
		writeLong($out, $len);
		fwrite($out, $line, $len);
		fwrite($out, chr(0), 1);
	}
	return true;
}

function decompack_file ($in, $out)
{
	$tmp = tmpfile();
	if (!decompress_file($in, $tmp))
		return false;
	rewind($tmp);
	if (!unpack_file($tmp, $out))
		return false;
	fclose($tmp);
	return true;
}

function compack_file ($in, $out)
{
	$tmp = tmpfile();
	if (!pack_file($in, $tmp))
		return false;
	rewind($tmp);
	if (!compress_file($tmp, $out))
		return false;
	fclose($tmp);
	return true;
}

function copy_file ($in, $out)
{
	while (!feof($in))
	{
		$data = fread($in, 1048576);
		fwrite($out, $data);
	}
	return true;
}

function error ($str)
{
	fprintf(STDERR, "ERROR: %s\n", $str);
	exit(2);
}

function usage ($command = '')
{
	global $argv;
	switch ($command)
	{
	case 'decompress':
		fprintf(STDERR, "Syntax: %s decompress <infile> [outfile]\n", $argv[0]);
		fprintf(STDERR, "Omit [outfile] to decompress the file in-place.\n");
		break;
	case 'compress':
		fprintf(STDERR, "Syntax: %s compress <infile> [outfile]\n", $argv[0]);
		fprintf(STDERR, "Omit [outfile] to compress the file in-place.\n");
		break;
	case 'recompress':
		fprintf(STDERR, "Syntax: %s recompress <file>\n", $argv[0]);
		break;
	case 'unpack':
		fprintf(STDERR, "Syntax: %s unpack <infile> [outfile]\n", $argv[0]);
		fprintf(STDERR, "Omit [outfile] to unpack the file in-place.\n");
		fprintf(STDERR, "Specify an outfile of '-' to print directly to the screen.\n");
		break;
	case 'pack':
		fprintf(STDERR, "Syntax: %s pack <infile> [outfile]\n", $argv[0]);
		fprintf(STDERR, "Omit [outfile] to pack the file in-place.\n");
		break;
	case 'decompack':
		fprintf(STDERR, "Syntax: %s decompack <infile> [outfile]\n", $argv[0]);
		fprintf(STDERR, "Omit [outfile] to decompress and unpack the file in-place.\n");
		fprintf(STDERR, "Specify an outfile of '-' to print directly to the screen.\n");
		break;
	case 'compack':
		fprintf(STDERR, "Syntax: %s compack <infile> [outfile]\n", $argv[0]);
		fprintf(STDERR, "Omit [outfile] to pack and compress the file in-place.\n");
		break;
	default:
		fprintf(STDERR, "Syntax: %s <command> args...\n", $argv[0]);
		fprintf(STDERR, "Valid commands:\n");
		fprintf(STDERR, "  decompress <infile> [outfile] - decrypts and extracts a binary file.\n");
		fprintf(STDERR, "  compress <infile> [outfile] - compresses and encrypts a binary file.\n");
		fprintf(STDERR, "  recompress <file> - recompresses a compressed a binary file in place.\n");
		fprintf(STDERR, "  unpack <infile> [outfile] - converts packed text into plain text.\n");
		fprintf(STDERR, "  pack <infile> [outfile] - converts plain text into packed text.\n");
		fprintf(STDERR, "  decompack <infile> [outfile] - decrypts, extracts, and unpacks text.\n");
		fprintf(STDERR, "  compack <infile> [outfile] - packs, compresses, and encrypts text.\n");
		break;
	}
	exit(1);
}

function operation ($infn, $inmode, $outfn, $outmode, $op1, $op1desc, $op2, $op2desc)
{
	$in_place = ($infn == $outfn);

	$ts = filemtime($infn);
	$infile = fopen($infn, $inmode);
	if (!$infile)
		error("Unable to open input file '$infn'!");

	if ($in_place)
		$outfile = tmpfile();
	else
	{
		if ($outfn)
		{
			$outfile = fopen($outfn, $outmode);
			if (!$outfile)
				error("Unable to create output file '$outfn'!");
		}
		else	$outfile = NULL;
	}

	if (!$op1($infile, $outfile))
		error("Failed to $op1desc '$infn'!");
	fclose($infile);

	if ($in_place)
	{
		$infile = $outfile;
		rewind($infile);
		$outfile = fopen($outfn, $outmode);
		if (!$op2($infile, $outfile))
			error("Failed to $op2desc '$outfn'!");
		fclose($infile);
	}

	if ($outfile)
	{
		fclose($outfile);
		touch($outfn, $ts);
	}
}


if ($argc < 2)
	usage();

switch ($argv[1])
{
case 'decompress':
	if ($argc < 3)
		usage($argv[1]);

	$infn = $argv[2];
	$outfn = ($argc < 4) ? $infn : $argv[3];
	operation($infn, 'rb', $outfn, 'wb', 'decompress_file', 'decompress', 'copy_file', 'copy output back to');
	break;

case 'compress':
	if ($argc < 3)
		usage($argv[1]);

	$infn = $argv[2];
	$outfn = ($argc < 4) ? $infn : $argv[3];
	operation($infn, 'rb', $outfn, 'wb', 'compress_file', 'compress', 'copy_file', 'copy output back to');
	break;

case 'recompress':
	if ($argc < 3)
		usage($argv[1]);

	$fn = $argv[2];
	operation($fn, 'rb', $fn, 'wb', 'decompress_file', 'decompress', 'compress_file', 'recompress');
	break;

case 'unpack':
	if ($argc < 3)
		usage($argv[1]);

	$infn = $argv[2];
	$outfn = ($argc < 4) ? $infn : (($argv[3] == '-') ? '' : $argv[3]);
	operation($infn, 'rb', $outfn, 'w', 'unpack_file', 'unpack', 'copy_file', 'copy output back to');
	break;
case 'pack':
	if ($argc < 3)
		usage($argv[1]);

	$infn = $argv[2];
	$outfn = ($argc < 4) ? $infn : $argv[3];
	operation($infn, 'r', $outfn, 'wb', 'pack_file', 'unpack', 'copy_file', 'copy output back to');
	break;
case 'decompack':
	if ($argc < 3)
		usage($argv[1]);

	$infn = $argv[2];
	$outfn = ($argc < 4) ? $infn : (($argv[3] == '-') ? '' : $argv[3]);
	operation($infn, 'rb', $outfn, 'w', 'decompack_file', 'decompress and unpack', 'copy_file', 'copy output back to');
	break;
case 'compack':
	if ($argc < 3)
		usage($argv[1]);

	$infn = $argv[2];
	$outfn = ($argc < 4) ? $infn : $argv[3];
	operation($infn, 'r', $outfn, 'wb', 'compack_file', 'pack and compress', 'copy_file', 'copy output back to');
	break;
default:
	fprintf(STDERR, "Invalid command '%s'!\n", $mode);
	break;
}
?>