<?php

namespace Hp;

//  PROJECT HONEY POT ADDRESS DISTRIBUTION SCRIPT
//  For more information visit: http://www.projecthoneypot.org/
//  Copyright (C) 2004-2022, Unspam Technologies, Inc.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
//  02111-1307  USA
//
//  If you choose to modify or redistribute the software, you must
//  completely disconnect it from the Project Honey Pot Service, as
//  specified under the Terms of Service Use. These terms are available
//  here:
//
//  http://www.projecthoneypot.org/terms_of_service_use.php
//
//  The required modification to disconnect the software from the
//  Project Honey Pot Service is explained in the comments below. To find the
//  instructions, search for:  *** DISCONNECT INSTRUCTIONS ***
//
//  Generated On: Sat, 05 Mar 2022 06:15:16 -0500
//  For Domain: pletzer.name
//
//

//  *** DISCONNECT INSTRUCTIONS ***
//
//  You are free to modify or redistribute this software. However, if
//  you do so you must disconnect it from the Project Honey Pot Service.
//  To do this, you must delete the lines of code below located between the
//  *** START CUT HERE *** and *** FINISH CUT HERE *** comments. Under the
//  Terms of Service Use that you agreed to before downloading this software,
//  you may not recreate the deleted lines or modify this software to access
//  or otherwise connect to any Project Honey Pot server.
//
//  *** START CUT HERE ***

define('__REQUEST_HOST', 'hpr3.projecthoneypot.org');
define('__REQUEST_PORT', '80');
define('__REQUEST_SCRIPT', '/cgi/serve.php');

//  *** FINISH CUT HERE ***

interface Response
{
    public function getBody();
    public function getLines(): array;
}

class TextResponse implements Response
{
    private $content;

    public function __construct(string $content)
    {
        $this->content = $content;
    }

    public function getBody()
    {
        return $this->content;
    }

    public function getLines(): array
    {
        return explode("\n", $this->content);
    }
}

interface HttpClient
{
    public function request(string $method, string $url, array $headers = [], array $data = []): Response;
}

class ScriptClient implements HttpClient
{
    private $proxy;
    private $credentials;

    public function __construct(string $settings)
    {
        $this->readSettings($settings);
    }

    private function getAuthorityComponent(string $authority = null, string $tag = null)
    {
        if(is_null($authority)){
            return null;
        }
        if(!is_null($tag)){
            $authority .= ":$tag";
        }
        return $authority;
    }

    private function readSettings(string $file)
    {
        if(!is_file($file) || !is_readable($file)){
            return;
        }

        $stmts = file($file);

        $settings = array_reduce($stmts, function($c, $stmt){
            list($key, $val) = \array_pad(array_map('trim', explode(':', $stmt)), 2, null);
            $c[$key] = $val;
            return $c;
        }, []);

        $this->proxy       = $this->getAuthorityComponent($settings['proxy_host'], $settings['proxy_port']);
        $this->credentials = $this->getAuthorityComponent($settings['proxy_user'], $settings['proxy_pass']);
    }

    public function request(string $method, string $uri, array $headers = [], array $data = []): Response
    {
        $options = [
            'http' => [
                'method' => strtoupper($method),
                'header' => $headers + [$this->credentials ? 'Proxy-Authorization: Basic ' . base64_encode($this->credentials) : null],
                'proxy' => $this->proxy,
                'content' => http_build_query($data),
            ],
        ];

        $context = stream_context_create($options);
        $body = file_get_contents($uri, false, $context);

        if($body === false){
            trigger_error(
                "Unable to contact the Server. Are outbound connections disabled? " .
                "(If a proxy is required for outbound traffic, you may configure " .
                "the honey pot to use a proxy. For instructions, visit " .
                "http://www.projecthoneypot.org/settings_help.php)",
                E_USER_ERROR
            );
        }

        return new TextResponse($body);
    }
}

trait AliasingTrait
{
    private $aliases = [];

    public function searchAliases($search, array $aliases, array $collector = [], $parent = null): array
    {
        foreach($aliases as $alias => $value){
            if(is_array($value)){
                return $this->searchAliases($search, $value, $collector, $alias);
            }
            if($search === $value){
                $collector[] = $parent ?? $alias;
            }
        }

        return $collector;
    }

    public function getAliases($search): array
    {
        $aliases = $this->searchAliases($search, $this->aliases);
    
        return !empty($aliases) ? $aliases : [$search];
    }

    public function aliasMatch($alias, $key)
    {
        return $key === $alias;
    }

    public function setAlias($key, $alias)
    {
        $this->aliases[$alias] = $key;
    }

    public function setAliases(array $array)
    {
        array_walk($array, function($v, $k){
            $this->aliases[$k] = $v;
        });
    }
}

abstract class Data
{
    protected $key;
    protected $value;

    public function __construct($key, $value)
    {
        $this->key = $key;
        $this->value = $value;
    }

    public function key()
    {
        return $this->key;
    }

    public function value()
    {
        return $this->value;
    }
}

class DataCollection
{
    use AliasingTrait;

    private $data;

    public function __construct(Data ...$data)
    {
        $this->data = $data;
    }

    public function set(Data ...$data)
    {
        array_map(function(Data $data){
            $index = $this->getIndexByKey($data->key());
            if(is_null($index)){
                $this->data[] = $data;
            } else {
                $this->data[$index] = $data;
            }
        }, $data);
    }

    public function getByKey($key)
    {
        $key = $this->getIndexByKey($key);
        return !is_null($key) ? $this->data[$key] : null;
    }

    public function getValueByKey($key)
    {
        $data = $this->getByKey($key);
        return !is_null($data) ? $data->value() : null;
    }

    private function getIndexByKey($key)
    {
        $result = [];
        array_walk($this->data, function(Data $data, $index) use ($key, &$result){
            if($data->key() == $key){
                $result[] = $index;
            }
        });

        return !empty($result) ? reset($result) : null;
    }
}

interface Transcriber
{
    public function transcribe(array $data): DataCollection;
    public function canTranscribe($value): bool;
}

class StringData extends Data
{
    public function __construct($key, string $value)
    {
        parent::__construct($key, $value);
    }
}

class CompressedData extends Data
{
    public function __construct($key, string $value)
    {
        parent::__construct($key, $value);
    }

    public function value()
    {
        $url_decoded = base64_decode(str_replace(['-','_'],['+','/'],$this->value));
        if(substr(bin2hex($url_decoded), 0, 6) === '1f8b08'){
            return gzdecode($url_decoded);
        } else {
            return $this->value;
        }
    }
}

class FlagData extends Data
{
    private $data;

    public function setData($data)
    {
        $this->data = $data;
    }

    public function value()
    {
        return $this->value ? ($this->data ?? null) : null;
    }
}

class CallbackData extends Data
{
    private $arguments = [];

    public function __construct($key, callable $value)
    {
        parent::__construct($key, $value);
    }

    public function setArgument($pos, $param)
    {
        $this->arguments[$pos] = $param;
    }

    public function value()
    {
        ksort($this->arguments);
        return \call_user_func_array($this->value, $this->arguments);
    }
}

class DataFactory
{
    private $data;
    private $callbacks;

    private function setData(array $data, string $class, DataCollection $dc = null)
    {
        $dc = $dc ?? new DataCollection;
        array_walk($data, function($value, $key) use($dc, $class){
            $dc->set(new $class($key, $value));
        });
        return $dc;
    }

    public function setStaticData(array $data)
    {
        $this->data = $this->setData($data, StringData::class, $this->data);
    }

    public function setCompressedData(array $data)
    {
        $this->data = $this->setData($data, CompressedData::class, $this->data);
    }

    public function setCallbackData(array $data)
    {
        $this->callbacks = $this->setData($data, CallbackData::class, $this->callbacks);
    }

    public function fromSourceKey($sourceKey, $key, $value)
    {
        $keys = $this->data->getAliases($key);
        $key = reset($keys);
        $data = $this->data->getValueByKey($key);

        switch($sourceKey){
            case 'directives':
                $flag = new FlagData($key, $value);
                if(!is_null($data)){
                    $flag->setData($data);
                }
                return $flag;
            case 'email':
            case 'emailmethod':
                $callback = $this->callbacks->getByKey($key);
                if(!is_null($callback)){
                    $pos = array_search($sourceKey, ['email', 'emailmethod']);
                    $callback->setArgument($pos, $value);
                    $this->callbacks->set($callback);
                    return $callback;
                }
            default:
                return new StringData($key, $value);
        }
    }
}

class DataTranscriber implements Transcriber
{
    private $template;
    private $data;
    private $factory;

    private $transcribingMode = false;

    public function __construct(DataCollection $data, DataFactory $factory)
    {
        $this->data = $data;
        $this->factory = $factory;
    }

    public function canTranscribe($value): bool
    {
        if($value == '<BEGIN>'){
            $this->transcribingMode = true;
            return false;
        }

        if($value == '<END>'){
            $this->transcribingMode = false;
        }

        return $this->transcribingMode;
    }

    public function transcribe(array $body): DataCollection
    {
        $data = $this->collectData($this->data, $body);

        return $data;
    }

    public function collectData(DataCollection $collector, array $array, $parents = []): DataCollection
    {
        foreach($array as $key => $value){
            if($this->canTranscribe($value)){
                $value = $this->parse($key, $value, $parents);
                $parents[] = $key;
                if(is_array($value)){
                    $this->collectData($collector, $value, $parents);
                } else {
                    $data = $this->factory->fromSourceKey($parents[1], $key, $value);
                    if(!is_null($data->value())){
                        $collector->set($data);
                    }
                }
                array_pop($parents);
            }
        }
        return $collector;
    }

    public function parse($key, $value, $parents = [])
    {
        if(is_string($value)){
            if(key($parents) !== NULL){
                $keys = $this->data->getAliases($key);
                if(count($keys) > 1 || $keys[0] !== $key){
                    return \array_fill_keys($keys, $value);
                }
            }

            end($parents);
            if(key($parents) === NULL && false !== strpos($value, '=')){
                list($key, $value) = explode('=', $value, 2);
                return [$key => urldecode($value)];
            }

            if($key === 'directives'){
                return explode(',', $value);
            }

        }

        return $value;
    }
}

interface Template
{
    public function render(DataCollection $data): string;
}

class ArrayTemplate implements Template
{
    public $template;

    public function __construct(array $template = [])
    {
        $this->template = $template;
    }

    public function render(DataCollection $data): string
    {
        $output = array_reduce($this->template, function($output, $key) use($data){
            $output[] = $data->getValueByKey($key) ?? null;
            return $output;
        }, []);
        ksort($output);
        return implode("\n", array_filter($output));
    }
}

class Script
{
    private $client;
    private $transcriber;
    private $template;
    private $templateData;
    private $factory;

    public function __construct(HttpClient $client, Transcriber $transcriber, Template $template, DataCollection $templateData, DataFactory $factory)
    {
        $this->client = $client;
        $this->transcriber = $transcriber;
        $this->template = $template;
        $this->templateData = $templateData;
        $this->factory = $factory;
    }

    public static function run(string $host, int $port, string $script, string $settings = '')
    {
        $client = new ScriptClient($settings);

        $templateData = new DataCollection;
        $templateData->setAliases([
            'doctype'   => 0,
            'head1'     => 1,
            'robots'    => 8,
            'nocollect' => 9,
            'head2'     => 1,
            'top'       => 2,
            'legal'     => 3,
            'style'     => 5,
            'vanity'    => 6,
            'bottom'    => 7,
            'emailCallback' => ['email','emailmethod'],
        ]);

        $factory = new DataFactory;
        $factory->setStaticData([
            'doctype' => '<!DOCTYPE html>',
            'head1'   => '<html><head>',
            'head2'   => '<title>http://pletzer.name</title></head>',
            'top'     => '<body><div align="center">',
            'bottom'  => '</div></body></html>',
        ]);
        $factory->setCompressedData([
            'robots'    => 'H4sIAAAAAAAAA7PJTS1JVMhLzE21VSrKT8ovKVZSSM7PK0nNK7FVSsvPyckvV7KzwacoLz-xKDkjsyxVJy8_My8ltULJDgCVbwwrVQAAAA',
            'nocollect' => 'H4sIAAAAAAAAA7PJTS1JVMhLzE21VcrL103NTczM0U3Oz8lJTS7JzM9TUkjOzytJzSuxVdJXsgMAKsBXli0AAAA',
            'legal'     => 'H4sIAAAAAAAAA61abW_bOBL-fr-Clx6yLZCmTZqmCZQN4E3dxotu0rPdFv1IS7TNqyRqScle76-_eaMlJ7bb3bsCRWRK4svwmWeeGeqq1pPcqNTkeah0asvZzwcvD9TE-cx4usRblc4yuXV9Vfvrf1zV2fXV1JW1murU_HyQusZb4w-uD8tJqBIlf64m8lTqcud_fvKO_l1Pr15g6_XVi4m8sH7eSwNejedGLc0k4HXt1Mo1iq5dPTde1Qavv8B9C5f7RoHHvDl8cvkmyRS8ir_1zJT14ZOTk9eJctQ__Hh5lhj8c5kcq8MnF2fJHO-Urnxee112RjvGa_6_dX0ujrzv3nrt_6OVRpVJrcZ5X_CtO5jwbVNoeoyWWFnYTL48wtYKr88SN_Oa10tm1Q1Z5CQpdG3jCvuFtrnSGV4P8PZ5omxQnq2YuxI7OAGDfcWGuQ5Kq0Vn6NrxWGBwGnohM22MctPuYx7wpXhrvDEFbsTJyyROYxNWD0HWNUdfp7yVqtI8NHeqbSlDbbO17WDl6cGvTWZTG2d3ngAOvZlRQ8CWN0k6V7leUs9kgZcwHJn45SmN56Zqypbhu8avnz09SRTM7PIyYSuPjF9c_fP5c1U3vlSweps2OVwb9fz5taUHGXD1nHtUeuIWDwyzA0LpY7DtQdJXcLDUlUEWDrggp1kp-lNVvOeTJphjNcbrzxa8wXmafeHq3KzUXJdZcAVNPsRJfh6MBuRQh0_eXCbDEQ9w8TLpDcdf1f2QzPDpl1H_35_69E6cNbDMd6lmx9LrXUvf9ULWeSFO_DvMMvWuwMeayX9MWquamKZgmO1D2cwtjBgZ0OAYUkqnKbUWZE9b1sZb5-HC1lbnKrNBV5XD9gyty6tJBeRm2uC7UyVEJlCxRFuG-g60H0Fwia5_eZHkpuWyFgs_ylwPwHQ96hpPJiZeB7BmZ4q3wGUYP-3AE1eHI8Xcs2UCWiaQmWBn3AXNPhVOyVfHnbHB67wJPLoJBPUUTf3yVUIu-zr50_Bj5LANo5z87VtJk8obsWLp6o6rAMJfwL60DZEkZCyl2VutxJcvhizd0omCHpT54ztBZAuAdzyp90Cdh6hXimiVJ2YU83yMhbnqpbV1a3o7T5jKTiBe9lqOVho4SVdkLV-YbJ9nmFJ6xqVy0C7VxAvUZ63tmHNasje8DThZpqDvWOnbzrU_IjrqvtxK_9HWAMY99iU5oL1CfiPuB0sOMuyyxQb5bkgdmCrUtvy2Usu5zgF_6LEEPliZKjcdrvd-2O8zpXLDqH_3FrjyVXL3niL6WP0y7Pdu_jI37nDT7xlyc3bLuYVwt6JN3PZmiMYTCaWmBCUOC5XRQcMr4Iowt5TiQomhXqekRIA1JawFAmMOTqx6JY2W2YXNGsJD3k7Hk-_DQDU79T6qWlrxTdfUXZ4DG3zs35CFex9a6EAztAFFdUMABEQF4KUlgXucnW-l9mg-FF-kGjNwcDKAtwUQ-MIoWxQWFBd4WqlmOs-NX6mFTSGAroANQGKibYwPpJNAqTrFaJpab5bOfwuwyaCSYKNdgwoMGR37hcjr_FKvVNA5ODp0khKLdRcsHhajg91tuhij6rmulVgPn10yx5psJgQnv0OAHdS8XQFYnriOYlGWwaYHw1EHIymJHM3a4CfhFNr0Ch_MV2oTd7vVHvUYJ6e3enSM5jQzDKIqZdJrqaY8gN0Edg_goG3MKCDewjpoWrndznK2pQskVNgfmDwxQq1rSKYcrX9eC5dpjsISHrYzUNslrVDkLy_xeLtddjhy2Jc2EIMt0P9WjhkMiErQbadAHdt6NNIjR02RNwiqGkHatA34_7Y3Vrc92msEROMnugS3z432JQgXrzML6E3BtXOrS4TC8HOHCe--qt_6JBBv9y3u_h1naLf_N70YI9e4P_xtQ8ZAgAL1xL7scnDlFMKad3mu0hwyUbTlwvgShlDTmly4NUieu2XMa1JyFfdIN4gcK4K4Fd2SHA4bnoZnBPXLhH2Xe-DUDSBSx0jdvrwmYpzJKaPodIMOwAaDm_7dqP-A-y5ON7gPUjlQaDxNggumlSVa_jyxHUZ2ExEUnRxTSD22kKStddxzedHoDfVJzwJTqChqyRUCLEQkcQauluLGWg98mQGsXDkDnVzAvYWBgDvTwIUqtxOvPVFhQS5omZJbEVSqTyP1r8Mnr18lL9mHwQkgacPrYzUou1tTtrpVkmHKhmMSPbcTK0zv0qaYgIODYCybEruEGawDz9rOvY8fPwxuel1Ll8DejQX7nXG-WpqUptQSrSJiFUE6Y3tTFqh5enbB9_YJmMMn52-Sjt4Gc_BLkG_HkUCqA6aB01sJXwdan_nDFFUudhVpwCtPdYVRcqI9_sE109uhVnNbsJ43ueGc1ztOF_WsNOBLar4KmOigU-GWWlo27KYOYr_yAXCH_Zv7Iaiji1dJF718v9lKYJFcB5hTiTgPqtIdHcrClF3K_s6_TN4CeVu3803hY8WD-aXzy2Q0Fg13RPs46r3vP6V5c9yhNpB9RDh_kcUQRXdvN7z35v6ui6ggyY3CtRL_iAbIbAvu14wGTAm-SKENvCR14GgErXIfmih7457LmqQ9wDQWD5AxqGLHpqQoHLMxtfT2wab20VbAPgOC6HjQXYn_aXdGHQscueXcmeoRYXcKGYVh6vUyZyywmY7gwaLamJYk2ABpm7E2BddfJ5Ydup2LCyqms2P1ld2zUZyUg3kDMxjLOAi6WO0KVFRC9ENchEl2HUu3mSm4AfhGyppaWBVUlbhV1q1F_vJhk9A_9L58ryq0uVidbmCD-Wdp67lkjJz1GorkE9LoZa2BkJ-2FFmCLJ-YmtSQUb2ssCI9W4KJWhRQ12MyBiMD49FqUxUkIi4egoSqR-82VoiVpfEGkQq75JWHiVlOOAwqsQvYNkd43VrTqdYceQZBNZbaDvB5LIBhKqrrdG7aUt3U1iXGdBiglbtqGmfyvje-7Q8Hd3g9vlfIBadJXw1aa4OIGfVZ_fyY78OC3w7Gg_u7Ec1ikuvyG6j-hSPkPGbDfTpHr7PRNffDpoRjNZ6b0O5VbbAWfn6esDqvBRnydHfjpdAbdTkDhmtiRxzQ34BdnW8Hy7CKzzWIWuoOpWKxwq7Z2Xtcc3fj390PH69XZrV1f2etwCZJ0D5PcSmXQFY60O_gnc5mGNBricNg3iYzzOPhSM21j-EWeQEktIeUrjvlWEDZ53_Qf8VUHai2QlzKsWQf7xpUITRGzTDQ4HKZCwR1PBnhuJZ5EaJBql95znOiFdG4mETyPs0eRtmH0eXXT0PW9KswbUrqAmuSpoa5ABkAi1VNhRPYoG4wS5RJzM_aM4BCVMWRQsXfpKgOzADJ2fnrBOiDPBaA0ZPrEUNFIzLp0AHaSzWq17tKG7aU0ETHDHvcvXoEtA1cXX8aUSjfaNtQbg76lUQ9XU0gfa_AZ4Eb8mIF5kk9WCgHPQPRpTBlaDwmiGAm1pBYPaJX9QLsqCeQE0EGDzyC5VKs88KLc0jwCxSVqKsgR6MlKz4PExtrkI_rdYDaGI3vh8Qzb_t3lCYN3g0oURrc0GqO_xLl3L97mCW8TpiAMqPreY6sBy4TKlWbEpJnnGj_sXOKjFZPD2J-wiGibhMgbICMQ5gHIBKxMAaJL9df-PFJ4OMYJccPpVlOdTnLyWZ4XBcsHvGpYH5vdGqxYrIOrk7ELf3ArgOfAR7KmQcBlH1nIxB2UHJ3D4Y9e53ckjV-20BEypmeODI0TJo65i8ul53cV0PSQh7MNsKMwq5H66lSydlj6NzgHWvEPzwzNpDMgleRmawT6SFcRTHB4sysCyotp4dmEtixOkkQ0x8HCfsnGFzv1mfdM9iO-UZvBzcYx7pmE71q2SFC6ZZq5kCMAsRM5sGJKnAu1Ak52m-mJmv1dgqBvVBdVO0LAJDlofJg4THCgs1B55ra5RyMIxPSDDQQ_GBQ0x4TzNn_8WBlT3bgWTIY7UFGVbAaeGpG-Y4Ihy6s3u6rv_R--cQZ-3qzEWiyjSkrM6lpWbbLPuajDhSlRHxIpMG6azV5955yUTVmeipXkPmxmBr2SNIMFUl1iMvjwXoFP0gpXckJDgSZFrozDuQbz4apJVxsjeXRtFFadgonTyEWaC4fB0zoR8IuvJVY6-M8JWdzLS2EzaIFksLTWJtGFztJGCzusRK92GvczwNK9Abj-w2IK_6AgPDm9tYBc8vRjsmddWuN3DGVeNqdEfs37GSes4re1_M0Svk515f2iqVYSYJ5d6M11jjpZatJVZxuT5Cj0OFsEgn9SGQSVpZcrjeK8pvhIh4VzWvJNB7RdVgLAclOSHo_U1O3twjQIWbwH8usI4c4JVY095WTOXKkTr4lENcuM1NA4kJ5M6oP5MQMj4SxPB-aqnK-JqquGlgzNmJdg88UDcGU-51pn0Vh1EHbj55WOy-LyY45sVri6IHP7SEH-gh6dgM3o3f9IWQodMY0_kRKoT9SJLzu_p5PHzzDr0NYVGVZDORubx2h3dxCA737ZywDiGLZew-eHXfE4sRQ0KMo0fgKlIdBrS7p3lQXNl9hvZlMGT9DYIU2y90C39Y515kCQLmEnYOnvolaVk0QYaL9OjG6TOQ7Fx-LhJ3tGY4ei52ttBXdQVeVHHagxJNiydE6QT6LwV6RCVxBSUKh-OAW2fKB78PrDbAmZ04deuDA3anhRq-hvE56J-6vbK5jVhATdhskEcSvraRtRqVdqpUKXz44Vtudd0ZKCU2KYRAfm3bZVgrCWGspI1dSyTO0RYP24wE8OcLIJVuFj4ARAAokcUAco7EW7F-GjwpEQmou5WtQ5ng4-Y2O3iAHRgUJ2h1EBgttF5PDXdLGbZU2onUVJGnreccPs9JaVS4muswjVE3eSEGE5qjWoXpqfLvLoJEBejcs6j-OyXH_nt-6hRV5iMeOZYdwJUH_CA7FjoHfknU-nBBJvS57xFRum1mYfZYcSxqpxWJAfPwK7EPNn3NIuDpcH6pAysnfKB19zzQy9_azDekLG-PnGdvmCUOzEyNSXJaBMILMtEwNhiyzLttFAZfGb9nk4wWa3NbMPzoBpChkivhNjLieKTnoGfluJ0Q3I3utiybbpqy5_MRxls8zTZAPsybEgsfdxwdDAEv8JgW0zA3TKSyyJkk0MfTBJ04_114tXcHnNn2FhYGtEHtB34W-oO9J4QLu_xe0HygkXCoAAA',
            'style'     => 'H4sIAAAAAAAAAyXMQQqEMAwF0KsIs7Wjs23FZe8RNTKFkF-aLBTx7i58B3iT-Sk809cq_A8TWL1WCFr85JzTDvW4QLbuN9ajo1ZIeiO1YNzKnpwPDxuvaOQFGhXK6Z6Gt30Afcze_V4AAAA',
            'vanity'    => 'H4sIAAAAAAAAA22S207DMAyGX8XKbtk6TpOWtRViGkJIsInDBZdpk7VhIY4cs7K3Jy3jBlBkKU7i7__jJGdVOQO1cS4GVVvfFGIq-jQorY9phaQN9bPIB2cKUal61xB-eC1H8_l80VnNrTw7n4bPhShzphQa9srZxheCMfwUHqESTsMnnKW4THGRqr4lxmSblmVEZ_VwZLRcLnti8ubhyNiiZ1mh09DrgSKr3ElUPo6jIbtd1OiQ5Gg2my2Ssuw9BYyWLXpJxim2e5OYV3nWU8s8Y_3HLhznzmxZwC_z50l1msbF920VtGS2hWiZg8yyrusmgfDN1NyiN4eAPEFqMgG1UzEWIqaVFqPDGER5v7q_Xj3C-gY2j-u71fIZbtcPq1fYrJ_zTJV5Rf8KfPjk_X1S47v4j_qUNuFW0d5ENgQbQk52UgPgwXCHtOu5yeTeaqOhOsDLwBsUh3Zk_RNmw98ovwCPYVRuIwIAAA',
        ]);
        $factory->setCallbackData([
            'emailCallback' => function($email, $style = null){
                $value = $email;
                $display = 'style="display:' . ['none',' none'][random_int(0,1)] . '"';
                $style = $style ?? random_int(0,5);
                $props[] = "href=\"mailto:$email\"";
        
                $wrap = function($value, $style) use($display){
                    switch($style){
                        case 2: return "<!-- $value -->";
                        case 4: return "<span $display>$value</span>";
                        case 5:
                            $id = 'wr7wreh9r7p';
                            return "<div id=\"$id\">$value</div>\n<script>document.getElementById('$id').innerHTML = '';</script>";
                        default: return $value;
                    }
                };
        
                switch($style){
                    case 0: $value = ''; break;
                    case 3: $value = $wrap($email, 2); break;
                    case 1: $props[] = $display; break;
                }
        
                $props = implode(' ', $props);
                $link = "<a $props>$value</a>";
        
                return $wrap($link, $style);
            }
        ]);

        $transcriber = new DataTranscriber($templateData, $factory);

        $template = new ArrayTemplate([
            'doctype',
            'injDocType',
            'head1',
            'injHead1HTMLMsg',
            'robots',
            'injRobotHTMLMsg',
            'nocollect',
            'injNoCollectHTMLMsg',
            'head2',
            'injHead2HTMLMsg',
            'top',
            'injTopHTMLMsg',
            'actMsg',
            'errMsg',
            'customMsg',
            'legal',
            'injLegalHTMLMsg',
            'altLegalMsg',
            'emailCallback',
            'injEmailHTMLMsg',
            'style',
            'injStyleHTMLMsg',
            'vanity',
            'injVanityHTMLMsg',
            'altVanityMsg',
            'bottom',
            'injBottomHTMLMsg',
        ]);

        $hp = new Script($client, $transcriber, $template, $templateData, $factory);
        $hp->handle($host, $port, $script);
    }

    public function handle($host, $port, $script)
    {
        $data = [
            'tag1' => '3ab9263ed97038ea5ed2245f7ee4c84e',
            'tag2' => 'c8f78c2dcd045542ceae6ba78ed5c1e3',
            'tag3' => '3649d4e9bcfd3422fb4f9d22ae0a2a91',
            'tag4' => md5_file(__FILE__),
            'version' => "php-".phpversion(),
            'ip'      => $_SERVER['REMOTE_ADDR'],
            'svrn'    => $_SERVER['SERVER_NAME'],
            'svp'     => $_SERVER['SERVER_PORT'],
            'sn'      => $_SERVER['SCRIPT_NAME']     ?? '',
            'svip'    => $_SERVER['SERVER_ADDR']     ?? '',
            'rquri'   => $_SERVER['REQUEST_URI']     ?? '',
            'phpself' => $_SERVER['PHP_SELF']        ?? '',
            'ref'     => $_SERVER['HTTP_REFERER']    ?? '',
            'uagnt'   => $_SERVER['HTTP_USER_AGENT'] ?? '',
        ];

        $headers = [
            "User-Agent: PHPot {$data['tag2']}",
            "Content-Type: application/x-www-form-urlencoded",
            "Cache-Control: no-store, no-cache",
            "Accept: */*",
            "Pragma: no-cache",
        ];

        $subResponse = $this->client->request("POST", "http://$host:$port/$script", $headers, $data);
        $data = $this->transcriber->transcribe($subResponse->getLines());
        $response = new TextResponse($this->template->render($data));

        $this->serve($response);
    }

    public function serve(Response $response)
    {
        header("Cache-Control: no-store, no-cache");
        header("Pragma: no-cache");

        print $response->getBody();
    }
}

Script::run(__REQUEST_HOST, __REQUEST_PORT, __REQUEST_SCRIPT, __DIR__ . '/phpot_settings.php');

