<?php

$games = array(
    'td',
    'ra',
    'ts',
    'dta',
    'yr',
    'd2',
);

header('Content-type: text/plain');

$game = isset($_POST['game']) ? $_POST['game'] : false;

if (!in_array($game, $games)) {
    header('400 Bad Request');
    echo 'Game not supported';
    exit;
}

if (count($_FILES) == 0) {
    header('400 Bad Request');
    echo 'Zip file missing.';
    exit;
}

$upload = array_pop($_FILES);

if ($upload['error']) {
    header('500 Internal Server Error');
    echo 'Something went wrong on server side while processing upload. The uploaded file could have been too big.';
    exit;
}

if ($upload['size'] > 1024 * 1024) {
    header('400 Bad Request');
    echo 'Uploaded file over size limit.';
    exit;
}

if (!preg_match('/^([a-z0-9]+).zip$/i', $upload['name'], $m)) {
    header('400 Bad Request');
    echo 'Zip file name not a valid hex value.';
    exit;
}

$sha1 = strtolower($m[1]);
$zipName = $game . '/' . $sha1 . '.zip';

if (file_exists($zipName)) {
    echo 'Map already uploaded, but thanks anyway.<br>';
    //exit;
}

// Creates new variable of zip archive type and opens .zip file of uploader.
$zip = new ZipArchive();
$res = $zip->open($upload['tmp_name']);

if ($res !== true) {
    header('400 Bad Request');
    echo 'Uploaded file not a valid Zip.';
    exit;
}

if ($game == 'd2') {
	
	// Extraction of temporary files to check validity.
	$tempDir = "$game/tmp/";
	$zip->extractTo($tempDir);		
	$tempZipName = $tempDir . "/" . $sha1;	
	$map = "$tempZipName.map";	
	$ini = "$tempZipName.ini";
	$tempZipMisName = $tempDir . "/_" . $sha1;
	$mis = "$tempZipMisName.mis";	
	$handle = fopen($map, "rb");
	
	$height = unpack('s', fread($handle, 2))[1];
	$width = unpack('s', fread($handle, 2))[1];
	
	$returnVal = 1;
	
	// Check if height is valid.
	if ($height > 128)
	{
		$returnVal = 0;		
	}
	
	// Check if width is valid.
	if ($width > 128)
	{
		$returnVal = 0;		
	}
	
	// Check if file size is valid.
	if (($height * $width * 4) + 4 != filesize($map))
	{
		$returnVal = 0;		
	}
	
	$cellCount = $height * $width;
	
	if ($returnVal == 1)
	{
		// Check if all cells are valid.
		for ($iter = 1; $iter<= $cellCount; $iter++)
		{
			$tile = unpack('s', fread($handle, 2))[1];
			
			//Check tile index value of the cell.
			if ($tile >= 800)
			{
				//$returnVal = 0;				
			}
			
			$special = unpack('s', fread($handle, 2))[1];
			
			//Check special index value of the cell.
			if ($special >= 1000)
			{
				//$returnVal = 0;				
			}
		}
	}
	
	// Check if the .ini file is of text type.
	if (strcmp(mime_content_type($ini),"text/plain") != 0) {
		//$returnVal = 0;		
	}
	
	//echo $returnVal;
	
	// Check if .mis file size is 68066.
	if (filesize($mis) != 68066 ) {
		//$returnVal = 0;		
	}	
	
	// Removal of temporary files for file checks
	fclose($handle);
	unlink ($map);
	unlink ($mis);
	unlink ($ini);	
	rmdir($tempDir);
	
    $mapData = null;
    $iniData = null;
    $misData = null;

    for ($i = 0; $i < 3; $i++) {
        $tmp = $zip->statIndex($i);

        if ($tmp['size'] > 128 * 128 * 8) {
            header('400 Bad Request');
            echo 'Map file larger than expected.';
            exit;
        }
// Loads file content into variable.
        if (is_array($tmp) && preg_match('/\.map$/i', $tmp['name'])) {
            $mapData = $zip->getFromIndex($i);            
        } else if (is_array($tmp) && preg_match('/\.ini$/i', $tmp['name'])) {
            $iniData = $zip->getFromIndex($i);
        } else if (is_array($tmp) && preg_match('/\.mis$/i', $tmp['name'])) {
            $misData = $zip->getFromIndex($i);
        }
    }

    if ($mapData === null) {
        header('400 Bad Request');
        echo 'Map file not found in Zip.';
        exit;
    }
    
    if ($iniData === null) {
        header('400 Bad Request');
        echo 'Map ini file not found in Zip.';
        exit;
    }

    $res = $zip->open($zipName, ZipArchive::CREATE);    
    if ($res !== true) {
        header('500 Internal Server Error');
        echo 'Server failed to save map zip, sorry.';
        exit;
    }

// Adds files to zip file and saves them.
    $zip->addFromString($sha1 . '.map', $mapData);

    $zip->addFromString($sha1 . '.ini', $iniData);

    
    if ($misData)
        $zip->addFromString('_' . $sha1 . '.mis', $misData);
    
        
    $zip->close();

    echo 'Upload succeeded!';
    
    
    exit;
}

header('500 Internal Server Error');
echo 'Request not handled for some reason';
?>