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 == ''){ $this->transcribingMode = true; return false; } if($value == ''){ $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' => '', 'head1' => '', 'head2' => 'Afferent www.mxchange.org', 'top' => '
', 'bottom' => '
', ]); $factory->setCompressedData([ 'robots' => 'H4sIAAAAAAAAA7PJTS1JVMhLzE21VSrKT8ovKVZSSM7PK0nNK7FVSsvPyckvV7KzwacoLz-xKDkjsyxVJy8_My8ltULJDgCVbwwrVQAAAA', 'nocollect' => 'H4sIAAAAAAAAA7PJTS1JVMhLzE21VcrL103NTczM0U3Oz8lJTS7JzM9TUkjOzytJzSuxVdJXsgMAKsBXli0AAAA', 'legal' => 'H4sIAAAAAAAAA51abXMTORL-fr9CF664UJUEwgJJdjiqvMGAt9iEiw1b-1EzI3u0mRn5JE2M99ff090avwQSZ_ngxPbopdUvTz_d8uuo89qowtR1mOvCtrP_7D3bU7nzpfH8lh7NdVmmR2_-8Tp6-lOqEJe1-c_e1LXxcKobWy9_VoXrvDX-QDWudbSiyfbePG7zMM9e529e45u2n1e42vmfH7179w5DitdP6dmb10_zNFw9bPydI6bfrHjvguW3Anz3372L2L95is3xr3O_ktO_mVRGLUz--NHx8csMf5-9zKJR9OY5fTx-wX-Ps0Yt6MsXmaVZ0aml61To8j9NQQNeZUr-ORUrGuFiZbyKxtOssyzwkj9l7vU_Dw_VvNbRlCpa8ghnWzVz9VQdHr65Mb61Lc3_3eTBRpp0nPFe-vGjs7OsMPOoIi8SbZNji7LTtdIhmBAa00Y1dz7iGyxGy3ijy7vVopNaIGujCu3NtKvr5RFr6NHZSTaT_Vs5WlBuitMZZdvSsghBx44ENlhdWx9UUXW-qJRucL7O42y-rCEYH02Uy9rDdkdqIvo0u62mi4IW8XZGs1vXHkavSaZnWZgar8l6z04zEXa3Ky9sZA3L-GR6Gw2fe-0dD3LEb53_-968Xmv8aXg--tYPx3NTWNjNmxC9qKqI1rUiHY24EEdsDz90DaT5YkNyV-dl0JGiYWFugSjhAA53dpqcN4aDu49QpSPAquYrrTD3MmvmdZO2v3OySZNLk6QRN2_NPV7Xz4mOdmNDnuAU8Blb6N7_6DVs2Ast_LssPe8AYQz8UIyv2I4jCYdQGzNXRvswr22MQFHyOlGwiAYPMoWbtfYvir2K1-4lgPu41jx-9AKB_AdFWyGLOkSksbNW5botVaNnCDGtymULGC54A8w9yVq3qHFkjhtyai2iKq1udN3d4-LXSReti0rEgKezGWFWneLvQGHzp2IUwaTd1iytiMAquuHDlKa2syqq3Mxm2tdLEp-kk7DmIXkNLwCsNfRMTAr4Ye33QpFiBQ8qG-6WY57kEBwza0jxRlYFWMkyu-GJVG--sltiYvh-mP7dfw-JbnNn2hhqwNxcizXikpVXID8TAi90u-1-GoeG10pi0DNt2xAZSCVJCODv8xqNKSkI1I0NhS1pib1fO3xF0DAgQBDP34OnHmcqgSn8emYDcg38ekBKepY1smjoimRYHeCvup11tfaUOgzj8sKG-RLOrkvTLNcC13wwylrICYo_PM8QVmxGssbc-KmTw0NihVNbv9KBbTs6_rRrIRHk5lMunK9L8TleBT4nSdYArTCInYN8L_K7mLYi4QgGVb6ZjLuZhFlUmrHTyMMbW5gjDt-iB04j-uIoiCnhKJ0jrO-2euzdjswGN-WDTV19HVSoHOFzsm5kvLjljg92qIeMjw9LLz-49Wqav2deDyg0CqrdHfGCnLXDMOjItaG3wYohiR3Yzjfip42Goedzw9_53cKIcZ1wK7OAf4m_5F2ABxCnG5XklFNBfn6IhMmECv7jg0pgJJCScA4gfPfWoc9avb2_jMZC5sDDQ4RrW6QH22p2V3pvCLR0G-gzNDGaXF6NKT5PjrOr4ZD4z8nzbDBh_X8aXE3-UJePH50-z9R4iFz_6jQbYcRp9p7nnGZ_CIae_pR9_mU8_O_n4cVE_XI1HJx_UJfvWKinsfyhguEuZ5oMr7DzSTbeovaDi7dbn88vL3p8pBdwkekqOJtYKXC2Ra7ghLoAgc11ca2s9zYyDV4iaSs3Ny2FVdfmVtOURGANRV7tFvQMUV0KJ4bt6eGMtklZAfjqGFShopMMWYcGVIZ3BWUEQSm8BXn2NgB429q5a9AkzHDedbOK9uvzHZC0AfS1AqW7-SnLtYYA2O4lc-bnWOvCbRA2IZ5lJ-mYIB6g2moP57e-8HoaJSfvhydqUTkcOIWOd_WaCFYxKHCzlksIKUQ6_t4lKsXkhk9ivgp2ewZ7b3sjyevN4OPuw30cnZM7wu2GW2aHa7w6y8Z48iK7Gp1PRptOIKNc-4DcTqnOglf8OyQCJKWFWRrw9JbkLvTcUknTuOIake6EeBUc1BvqTSTPrvjwbtbO-mCy7F3uIuz_4kWmYAiwOb8-B9cfsiZGoqI6gGWa-ZY2q8S3VM_KU96kAoerNU9IEO0NaqXCgZ-Gap1v4UDBirelIkaYJJWVcOmUypRp9IoLs_vfk8Q2uZMWUo5shtV0BEm-H_LjBsqC5qVSS30eq3-9fCYJdtr1Ir5IBsMB5-YvB9KiS7AP8BGvYQrVzQCNTDwryCKBnXcMkk4YAB0RMal7_syYEY7UiOkUBgo9OJOYh5-s9dDHflKRYpMEbDgX0Vwlwt1oMK5rswQ386ZyyBJgRDNFqRwowCL1Ziu_XwauUXHw6RNiYvDLx-Fu7X8c_P5wdskZLEpmEpUvQcWtWOGAz4EK3ZAZ19QS7CjVhTvy-HwNVq0RTrVIZ64U7MSaq7SkNB0C5a9r1DWtAiUlQxbUmxKvrWsUEWpGxZEICrPmS1qhrzpge3sfx-rPfo4UhTPsTrv7Ap0EeImXJWgMECUu-tLrNFvuLraE3FokpZYzxoAcVq1NTqkyJo9a2L7YafuyBxM4-oTHV7Zhndl2CkgGlFM6qx3SVYm60UbY0DF9X9mMVyJ3lhPAGryALsC1bXChIG4O6KZej3h_yoUyHRrAgCLRbeRNL5RjivTelqGyc1WbOeW2QuN0pZcFkEPa1HwyOkBU-hJQGoy_2UKybzoWTEqG55dXb7eJAFjH5kfwodFk05dnapnougQjB7RvTVSfpFiYuxqMncAb4jY2BEstUm2p0MabyuibZTAsqIubaUUlKm-D1GAAtwfw-f1VWtzj1pi6r37t_a5r7f86A0RpdGSrVVK-KMm1wTC3ITBKaI-ENe018GFw9WUoKXJ08f5AvR9MPgyvRhfrs_w2HI8H74f74ydqcqnwVI3WD_FxzDwRifbqtzFoHqjh1Zcf5How0VvQuZ-yCfHKs-xi25r83bZFP4_vgbjyO-i1Ue5yL3J_b6Xy303ew_uzLBzt7tJNOClEs6r7nqV69AGASkAUUQhAc68AoswwrGw9242Q-1KTUFAFtU8AsTe5JYZjEzt_jwNNV10uwpjd47YavpzeD5TuiJ4GgmcpojlQkUU949Yk1R-Oer6CFAtbXCNiGo2SxAWnUPVfc80NRrtbBhTlY3bviMzLORTCpA52QnaqZnaTxlVmv0U4L2853bvLq63PF5cXhx8-_za4uIUsm07Wkls4lZrCpIffzdq1irorzYG0C4gKUwOjTV3Q3dG-ZiAHShonlfaNylGAMDP3N4b6LCCMMIlmNwFQpU5IavHrxNiISXJHKLW5NjSReMs9PdI-Csi4iWXJnEjVQvJlaZKAK_EpE9N3N5ZY1tT5VI0xW9qdFDfpVI-vphcW8qdvvKTfvn_KfSzOzFRiQJLQ5SFSA4y153KQB0ICuvCAS5Wmjk76WqnrWq8zdy20BJrXSfXgrtTaAuCzJgOnAraBbUXZrADu66bGMzd3WbRA3dfbFQ_XZlxObxexv36-Go3fUhkj2Lj5UCbD4DBGYUy6-6jBfpjZggQRLaq1nzExQ-bPUVKKPNLywwDuiPlVDxcBJSG8WWfEPp7_TAQtXHc1J2-MrPXibiPOVgH8gAYGFgtiUx2lSFZ7g1KEetw38Ynwj6Ne2_4423sCr-KKCZbcntDS2EiNyFT-cFuun9435RJRDeQQQueId437jt-qdRdW3bqX6cKs0gWRG62m-itFvutWLVbQWB4yq10uTAfEbrcW-HYEtVxR0X0Chwo3wtnGITE6hLqF3YNprLcz-O2cwqtlOtca1DQ5JVqRA14oapppX96GPaZQt3Irp_VvOisPaH2xByOxUXr-1k0xabM0SjSWIsSXHKnbnTEBF5jWTtXCSOJJbQWBUC-0TVwiYdDuwudTj6TH97XzzKpIXfba04Fatxtt1fdSlAuLQrrg2NOxqKicM2VX6JT6cucauZEBx5HOGV2CUXticDF-N7yi1d4OLyajd6PhFXGDkwz5iCIeYz5PhqycczbL0Q9zLBGarjxIp0E8plzfDVGsUCHF8Z3akUrwDplFl1MtKNcuNwhVXw2CKrfGP-kxV56OicAX2O5IfSJqz48qLTUadxbAF6QKtoWmZiUTglJyx-4U1OhrTKGSWViPv-lBAmz4AcRGS2-WrjsWkH43_5Jb5lshNOb26bf-nt_qt9A9xVLJ1WItj5qeVkmHBQ8P6MqfRiyJV0ll7XDIosZHVVS2Lmt7Tdprmo5ruHTT19-_cf-ni5vgPZV7lg7UyU_rpGUPlxSGkq_vRwkRN09XU-KTYIMbp4xPxCtKD_FovUnVCepCg9I2k0sjG6Y2KvgU9Ev8gHYOD2sHbN-Cr3RJ-Zbq282iuJnLEV1JfRQcEw5poqffT9CmdZd7OFgqLCWlc2weiKZLy22him_CjBDcGZElQlC54hTO4mopaMkP-jpv2xvkdQ8M9aQmT11YugfbvK7D7IZ_zpCCh7MafUYCS4044m3k4Mnrk917Y1ryNwHLnuAFugYzcr0JL0P2cGsQ7E-S-P2fnURkmJu6RhJhogPNec25pcJkuKFuhVHYUNr0K5P-ApAFpjTq1s3eG9N2Jt0mTjf6hneryfW1VnK4dN2fjkyJTa_vHIEBVHl8zxLlkbTZO_pFSv-Dj81m-FbrMvRqAUebw_XV3HGjTzMX9C5SDutvE6cYv2qCJDgsRcXbKe5oUyDU2O8F-y_VAGX16OotMxI1uFCD8_Php8ng4nyoKOH2swTsn_Jvrp7yj7XwBg_-DwOSdti5JQAA', 'style' => 'H4sIAAAAAAAAAyXMywmAMAwA0FUEr9bPtRWP3SO2EQolkSRCRdzdg2-At6rdFTcYjZNc-iSuLL6PMYaDyfzONXfLfLYOpEAdFEidopQjGDZzGRMLWGHyxIThXad__AA6EcQHWQAAAA', 'vanity' => 'H4sIAAAAAAAAA22S224jIQyGX8Uit5tMethIIZPRaqNUVaU2UQ8XvWQGMsOGYmScTPP2C9P0pq2QJRvh7_8NlKxqZ6AxzsWgGuvbpZiKXAal9bmskbShnEU-ObMUtWr2LeHBazmaz-eL3mru5OXVNLwvRFUypdBwVM62fikYw2fjGSrhIrzDZYrfKa5T14fEmGzbsYzorB6OjFarVSYmbx7OjB16ljU6DVkPFFnlfkXl4zgasrtFgw5Jjmaz2SIpy-wpYLRs0UsyTrE9msT8UxaZWpUF62924Zw7s2MBX8xfJdVpWtcf0yroyOyWomMOsij6vp8Ewn-m4Q69OQXkCVJbCGicijHzGzpEUd2v7_-uH2FzA9vHzd169Qy3m4f1K2w3z2WhqrKmH9kHn2y_TRp8E1-AT2kfbhUdTWRDsCXkZCKNDQ-Ge6R9RiZrR6uNhvoELwNqEBsuocgPVww_ovoPibVy8RkCAAA', ]); $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 ""; case 4: return "$value"; case 5: $id = '55juhus9c3'; return "
$value
\n"; 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 = "$value"; 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' => '7b8a66bc336b69c9af3e1af568a2b17d', 'tag2' => 'ec4aa0ce192bb26dc2a4b650b0247c5f', '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');