#!/usr/bin/php
<?php
//error_reporting(0);

/***
 * Configuration options
 */
$template = "templates/odt/blank_template_v0.3.odt";
$CHECKtemplate = "templates/odt/blank_template_check_v0.3.odt";
$vulnTemplate = "templates/odt/vuln_template.xml";

/***
 * Main program - Don't edit below
 */
echo "_____ _____ _____ Gen\n||_// ||==  ||_// \n|| \\  ||___ ||    \n\n";

foreach (glob("classes/*.php") as $filename)
    include $filename;

$definitions = new \Clapp\CommandLineArgumentDefinition(
    array(
        "help|h"            => "Shows help message",
        "path|p=s"          => "/path/to/configs/", // should contain config.json and all vuln.json files
    )
);

$filter = new \Clapp\CommandArgumentFilter($definitions, $argv);

if ($filter->getParam('h') === true || $argc < 2) {
    fwrite(STDERR, $definitions->getUsage());
    exit(0);
} 

// see if doc exists 
if ($filter->getParam("path") == false)
	die("[-] no path set\n");

echo "[!] path: ".$filter->getParam("path")."\n";
if(!is_dir($filter->getParam("path")))
	die("[-] no such folder! \n");

//get config file
$config = json_decode(file_get_contents($filter->getParam("path")."config.conf")); 
if(isset($config->checkRef) && trim($config->checkRef) <> ""){
    $template = $CHECKtemplate; // if checkRefset use CHECK template
    echo "[+] using CHECK template\n";
}

// extract doc and get contents
$rand = uniqid();
mkdir("/tmp/$rand");
if(unzipFolder($template, "/tmp/$rand/")) {
    $source = file_get_contents("/tmp/$rand/content.xml");
    echo "[+] doc extracted\n";
} else {
	die("[-] unable to extract doc\n");
}
	


// add config into template
$source = file_get_contents("/tmp/$rand/content.xml");
foreach ($config as $key => $value) {
	$source = str_replace('{'.$key.'}', $value, $source);
}
file_put_contents("/tmp/$rand/content.xml", $source);
echo "[+] added config values\n";

// get all vulns
$vuln = array();
$files = glob($filter->getParam("path")."*.json");
foreach($files as $finding){
    $vuln[] = $found = json_decode(file_get_contents($finding), true);
}

echo "[+] sorting vulns by CVSS\n";
usort($vuln, 'order_by_cvss');
function order_by_cvss($a, $b) {
    return $b['cvss_score'] > $a['cvss_score'] ? 1 : -1;
}

if(empty($vuln))
    echo "[-] no vulns found!\n";

// create vulns for odf
$templateOrig = file_get_contents($vulnTemplate);
$Serious = $High = $Medium = $Low = $Informational = ""; 
foreach ($vuln as $singlevuln) {
	$templateSource = $templateOrig;
	$togo = $singlevuln['risk'];
	foreach ($singlevuln as $key => $value){
        $value = str_replace("<", "&lt;", $value);
        $value = str_replace(">", "&gt;", $value);
		$value = str_replace("\n", "</text:p><text:p text:style-name=\"Text_20_body\">", $value);
		$templateSource = str_replace('{'.$key.'}', $value, $templateSource);
	}
	$$togo .= $templateSource;
	echo "[+] added $togo: ".$singlevuln['title']."\n";
}

// squash vulns into one bbig xml
$value = "";
if(!empty($Serious)){
	$value .= '<text:list  text:continue-numbering="true" text:style-name="Outline">
    <text:list-item>
        <text:list>
            <text:list-item>
                <text:h text:outline-level="2">Serious Risk Vulnerabilities</text:h>
            </text:list-item>
        </text:list>
    </text:list-item>
</text:list>';
	$value .= $Serious;
}

if(!empty($High)){
	$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
    <text:list-item>
        <text:list>
            <text:list-item>
                <text:h text:outline-level="2">High Risk Vulnerabilities</text:h>
            </text:list-item>
        </text:list>
    </text:list-item>
</text:list>';
	$value .= $High;
}
if(!empty($Medium)){
	$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
    <text:list-item>
        <text:list>
            <text:list-item>
                <text:h text:outline-level="2">Medium Risk Vulnerabilities</text:h>
            </text:list-item>
        </text:list>
    </text:list-item>
</text:list>';
	$value .= $Medium;
}
if(!empty($Low)){
	$value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
    <text:list-item>
        <text:list>
            <text:list-item>
                <text:h text:outline-level="2">Low Risk Vulnerabilities</text:h>
            </text:list-item>
        </text:list>
    </text:list-item>
</text:list>';
	$value .= $Low;
}
if(!empty($Informational)){
    $value .= '<text:list text:continue-numbering="true" text:style-name="Outline">
    <text:list-item>
        <text:list>
            <text:list-item>
                <text:h text:outline-level="2">Informational Risk Vulnerabilities</text:h>
            </text:list-item>
        </text:list>
    </text:list-item>
</text:list>';
    $value .= $Informational;
}
// add to template
$source = file_get_contents("/tmp/$rand/content.xml");
$source = str_replace('{vuln}', $value, $source);
file_put_contents("/tmp/$rand/content.xml", $source);

// create report and tidying
zipFolder("/tmp/$rand", $filter->getParam("path")."repgen.odt");
echo "[=] generated report: ".$filter->getParam("path")."repgen.odt\n";
delTree("/tmp/$rand");
echo "[+] temp files removed\n";

function unzipFolder($zipInputFile, $outputFolder) {
    $zip = new ZipArchive;
    $res = $zip->open($zipInputFile);
    if ($res === true) {
        $zip->extractTo($outputFolder);
        $zip->close();
        return true;
    }
    else {
        return false;
    }
}

function XML2Array(SimpleXMLElement $parent){
    $array = array();

    foreach ($parent as $name => $element) {
        ($node = & $array[$name])
            && (1 === count($node) ? $node = array($node) : 1)
            && $node = & $node[];

        $node = $element->count() ? XML2Array($element) : trim($element);
    }

    return $array;
}

function delTree($dir){ 
    $files = array_diff(scandir($dir), array('.', '..')); 

    foreach ($files as $file) { 
        (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); 
    }

    return rmdir($dir); 
} 

function zipFolder($inputFolder, $zipOutputFile) {
    if (!extension_loaded('zip') || !file_exists($inputFolder)) {
        return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($zipOutputFile, ZIPARCHIVE::CREATE)) {
        return false;
    }

    $inputFolder = str_replace('\\', "/", realpath($inputFolder));

    if (is_dir($inputFolder) === true) {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($inputFolder), RecursiveIteratorIterator::SELF_FIRST);

        foreach ($files as $file) {
            $file = str_replace('\\', "/", $file);

            if (in_array(substr($file, strrpos($file, '/')+1), array('.', '..'))) {
                continue;
            }

            $file = realpath($file);

            if (is_dir($file) === true) {
                $dirName = str_replace($inputFolder."/", '', $file."/");
                $zip->addEmptyDir($dirName);
            }
            else if (is_file($file) === true) {
                $fileName = str_replace($inputFolder."/", '', $file);
                $zip->addFromString($fileName, file_get_contents($file));
            }
        }
    }
    else if (is_file($inputFolder) === true) {
        $zip->addFromString(basename($inputFolder), file_get_contents($inputFolder));
    }

    return $zip->close();
}

?>
