Skip to content

Instantly share code, notes, and snippets.

@Alemiz112
Created August 8, 2020 11:38
Show Gist options
  • Save Alemiz112/e2785465bc0e492a055a9a42298fd566 to your computer and use it in GitHub Desktop.
Save Alemiz112/e2785465bc0e492a055a9a42298fd566 to your computer and use it in GitHub Desktop.
<?php
function virion_infect(Phar $virus, Phar $host, string $virusName): void{
$host->startBuffering();
/* Check to make sure virion.yml exists in the virion */
if(!isset($virus["virion.yml"])){
echo "virion.yml not found";
return;
}
$virusPath = "phar://" . str_replace(DIRECTORY_SEPARATOR, "/", $virus->getPath()) . "/";
$virionYml = yaml_parse(file_get_contents($virusPath . "virion.yml"));
if(!is_array($virionYml)){
echo "Corrupted virion.yml, could not activate virion $virusName";
return;
}
/* Check to make sure plugin.yml exists in the plugin */
if(!isset($host["plugin.yml"])){
echo "plugin.yml not found in host";
return;
}
$hostPath = "phar://" . str_replace(DIRECTORY_SEPARATOR, "/", $host->getPath()) . "/";
$pluginYml = yaml_parse(file_get_contents($hostPath . "plugin.yml"));
if(!is_array($pluginYml)){
echo "Corrupted plugin.yml found in plugin host";
return;
}
/* Infection Log. File that keeps all the virions injected into the plugin */
$infectionLog = isset($host["virus-infections.json"]) ? json_decode(file_get_contents($hostPath . "virus-infections.json"), true) : [];
/* Virion injection process now starts */
$genus = $virionYml["name"];
$antigen = $virionYml["antigen"];
foreach($infectionLog as $old){
if($old["antigen"] === $antigen){
echo "Plugin is already infected with $virusName";
return;
}
}
$antibody = getPrefix($pluginYml) . $antigen;
$infectionLog[$antibody] = $virionYml;
echo "Using antibody $antibody for virion $genus ({$antigen})";
$hostPharPath = "phar://" . str_replace(DIRECTORY_SEPARATOR, "/", $host->getPath());
$hostChanges = 0;
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($hostPharPath)) as $name => $chromosome){
if($chromosome->isDir()){
continue;
}
if($chromosome->getExtension() !== "php"){
continue;
}
$rel = cut_prefix($name, $hostPharPath);
$data = change_dna($original = file_get_contents($name), $antigen, $antibody, $hostChanges);
if($data !== ""){
$host[$rel] = $data;
}
}
$restriction = "src/" . str_replace("\\", "/", $antigen) . "/";
$ligase = "src/" . str_replace("\\", "/", $antibody) . "/";
$viralChanges = 0;
foreach(new RecursiveIteratorIterator($virus) as $name => $genome){
if($genome->isDir()){
continue;
}
$rel = cut_prefix($name, "phar://" . str_replace(DIRECTORY_SEPARATOR, "/", $virus->getPath()) . "/");
if(strpos($rel, "resources/") === 0){
$host[$rel] = file_get_contents($name);
}elseif(strpos($rel, "src/") === 0){
if(strpos($rel, $restriction) !== 0){
echo "Warning: File $rel in virion is not under the antigen $antigen ($restriction)";
$newRel = $rel;
}else{
$newRel = $ligase . cut_prefix($rel, $restriction);
}
$data = change_dna(file_get_contents($name), $antigen, $antibody, $viralChanges);
$host[$newRel] = $data;
}
}
$host["virus-infections.json"] = json_encode($infectionLog);
//$virus->stopBuffering();
$host->stopBuffering();
echo "Shaded $hostChanges references in plugin and $viralChanges references in $virusName.";
}
function getPrefix(array $pluginYml): string{
$main = $pluginYml["main"];
$mainArray = explode("\\", $main);
array_pop($mainArray);
$path = implode("\\", $mainArray);
return $path . "\\libs\\";
}
function cut_prefix(string $string, string $prefix): string{
if(strpos($string, $prefix) !== 0){
throw new AssertionError("\$string does not start with \$prefix:\n$string\n$prefix");
}
return substr($string, strlen($prefix));
}
function change_dna(string $chromosome, string $antigen, string $antibody, &$count = 0): string{
$tokens = token_get_all($chromosome);
$tokens[] = ""; // should not be valid though
foreach($tokens as $offset => $token){
if(!is_array($token) or $token[0] !== T_WHITESPACE){
list($id, $str, $line) = is_array($token) ? $token : [
-1,
$token,
$line ?? 1
];
if(isset($init, $current, $prefixToken)){
if($current === "" && $prefixToken === T_USE and $id === T_FUNCTION || $id === T_CONST){
continue;
}elseif($id === T_NS_SEPARATOR || $id === T_STRING){
$current .= $str;
}elseif(!($current === "" && $prefixToken === T_USE and $id === T_FUNCTION || $id === T_CONST)){
// end of symbol reference
if(strpos($current, $antigen) === 0){ // case-sensitive!
$new = $antibody . substr($current, strlen($antigen));
for($o = $init + 1; $o < $offset; ++$o){
if($tokens[$o][0] === T_NS_SEPARATOR || $tokens[$o][0] === T_STRING){
$tokens[$o][1] = $new;
$new = ""; // will write nothing after the first time
}
}
++$count;
}elseif(stripos($current, $antigen) === 0){
throw new RuntimeException("[WARNING] Not replacing FQN $current case-insensitively.");
}
unset($init, $current, $prefixToken);
}
}else{
if($id === T_NS_SEPARATOR || $id === T_NAMESPACE || $id === T_USE){
$init = $offset;
$current = "";
$prefixToken = $id;
}
}
}
}
$ret = "";
foreach($tokens as $token){
$ret .= is_array($token) ? $token[1] : $token;
}
return $ret;
}
$virus = new Phar($argv[1]);
$host = new Phar($argv[2]);
virion_infect($virus, $host, $argv[1]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment