<?php
class MimeTypeDefinition {
var $start;
var $type;
var $pattern;
var $mime;
function __construct($start, $type, $pattern, $mime)
{
$this->start = $start;
$this->type = $type;
$this->pattern = $pattern;
$this->mime = $mime;
}
}
class MimeChecker {
var $data = null;
function __construct()
{
}
function parse($filepath)
{
{
return "mimeタイプの定義ファイルが見つかりません。";
}
$this->data = file($filepath);
'byte','short','long','string','date',
'beshort','belong','bedate',
'leshort','lelong','ledate'
);
foreach($this->data as $line)
{
{
continue;
}
'/^(>?\d+)\s+(' . $ptn_types . ')\s+((\x5c |[^\s])*)\s+([^\s]+)?/',
$line, $match) == 0)
{
continue;
}
else
{
{
$match[5] = null;
}
$this->types[] = new MimeTypeDefinition($match[1], $match[2], $match[3], $match[5]);
}
}
return false;
}
function getMime($path)
{
{
return false;
}
{
return false;
}
$mime = null;
$fp = fopen($path, "rb");
$count = count($this->types);
for($i = 0; $i < $count;)
{
$start = $this->types[$i]->start;
{
$mime = $this->checkMime($fp, $i);
$i++;
if($mime)
{
}
}
else
{
$i++;
}
}
if(!$mime)
{
return 'application/octet-stream';
}
}
function checkMime($fp, $i)
{
$ismatch = false;
switch($this->types[$i]->type)
{
case "byte" :
$ismatch = $this->checkByte($fp, $this->types[$i]);
break;
case "short" :
$ismatch = $this->checkShort($fp, $this->types[$i]);
break;
case "long" :
$ismatch = $this->checkLong($fp, $this->types[$i]);
break;
case "string" :
$ismatch = $this->checkStr($fp, $this->types[$i]);
break;
case "date" :
$ismatch = $this->checkTime($fp, $this->types[$i]);
break;
case "beshort" :
$ismatch = $this->checkBeShort($fp, $this->types[$i]);
break;
case "belong" :
$ismatch = $this->checkBeLong($fp, $this->types[$i]);
break;
case "bedate" :
$ismatch = $this->checkBeTime($fp, $this->types[$i]);
break;
case "leshort" :
$ismatch = $this->checkLeShort($fp, $this->types[$i]);
break;
case "lelong" :
$ismatch = $this->checkLeLong($fp, $this->types[$i]);
break;
case "ledate" :
$ismatch = $this->checkLeTime($fp, $this->types[$i]);
break;
}
if((!$ismatch) && (preg_match('/^\d+$/', $this->types[$i]->start) > 0)) {
return null;
}
if(isset($this->types[$i]->mime)) {
return $this->types[$i]->mime;
}
$count = count($this->types);
for($i++; $i < $count; $i++)
{
if(preg_match('/^\d+$/', $this->types[$i]->start) > 0) {
return null;
}
else
{
$mime = $this->checkMime($fp, $i);
if($mime)
{
return $mime;
}
}
}
}
function checkByte($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data);
}
function checkShort($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data);
}
function checkLong($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data);
}
function checkInt($mode, $num, $data, $packfmt = null)
{
if(preg_match('/^0x([\da-f]+)$/i', $num, $match) > 0) {
}
else if(preg_match('/^0(\d+)$/', $num, $match) > 0) {
}
else if(preg_match('/^(\d+)$/', $num, $match) > 0) {
}
else
{
return false;
}
if($packfmt)
{
switch($packfmt)
{
case "n" :
break;
case "N" :
break;
case "v" :
break;
case "V" :
break;
default:
return false;
}
$num = pack($packfmt, $num); }
if(empty($mode) || ($mode == "=")) {
if($data == $num)
{
return true;
}
}
else if($mode == "<")
{
if($data < $num)
{
return true;
}
}
else if($mode == ">")
{
if($data > $num)
{
return true;
}
}
else if($mode == "&")
{
if(($data & $num) == $num)
{
return true;
}
}
else if($mode == "^")
{
if(($data & $num) != $num)
{
return true;
}
}
else if($mode == "~")
{
if($data == ~$num)
{
return true;
}
}
return false;
}
function checkStr($fp, $type)
{
$start = $type->start;
if(preg_match('/^(=|<|>)?((\x5c |[^\s])*)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
$ptn = $this->unescape($match[2]);
$data = fread($fp, $len);
if(empty($match[1]) || ($match[1] == "=")) {
if(($match[0] == '=\0') && ($data == ""))
{
return true;
}
else if($data == $ptn)
{
return true;
}
else
{
return false;
}
}
else if($match[1] == "<")
{
{
return true;
}
else
{
return false;
}
}
else if($match[1] == ">")
{
if(($match[0] == '>\0') && ($data != ""))
{
return true;
}
else if(strcmp($data, $ptn) > 0) {
return true;
}
else
{
return false;
}
}
}
function checkTime($fp, $type)
{
$start = $type->start;
{
return true;
}
else
{
return false;
}
}
function checkBeShort($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data, "n");
}
function checkBeLong($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data, "N");
}
function checkBeTime($fp, $type)
{
$start = $type->start;
{
return true;
}
else
{
return false;
}
}
function checkLeShort($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data, "v");
}
function checkLeLong($fp, $type)
{
$start = $type->start;
if($type->pattern == "x")
{
return true;
}
else if(preg_match('/^(=|<|>|&|^|~)?(0?x?[\da-f]+)$/i', $type->pattern, $match) == 0) {
return false;
}
{
$match[1] = null;
}
return $this->checkInt($match[1], $match[2], $data, "V");
}
function checkLeTime($fp, $type)
{
$start = $type->start;
{
return true;
}
else
{
return false;
}
}
function unescape($str)
{
'\d{3}', 'x[\da-f]{2}', '0', '01', '02', '03', '04', '05', '06',
'a', 'b', 't', 'n', 'v', 'f','r', '\x5c', '\x3f', '"', '\x27',
);
$str);
}
static function unescapesub($match)
{
switch($match)
{
case "0" :
return "\0";
break;
case "01" :
return "\01";
break;
case "02" :
return "\02";
break;
case "03" :
return "\03";
break;
case "04" :
return "\04";
break;
case "05" :
return "\05";
break;
case "06" :
return "\06";
break;
case "a" :
return "\a";
break;
case "b" :
return "\b";
break;
case "t" :
return "\t";
break;
case "n" :
return "\n";
break;
case "v" :
return "\v";
break;
case "f" :
return "\f";
break;
case "r" :
return "\r";
break;
case "\x5c" :
return "\x5c";
break;
case "?" :
return "?";
break;
case "'" :
return "'";
break;
case '"' :
return '"';
break;
}
if(preg_match('/^(\d{3})$/', $match, $submatch) > 0) {
}
else if(preg_match('/^x([\da-f]{2})$/i', $match, $submatch) > 0) {
}
}
}
?>
PD9waHAKY2xhc3MgTWltZVR5cGVEZWZpbml0aW9uIHsKCXZhciAkc3RhcnQ7Cgl2YXIgJHR5cGU7Cgl2YXIgJHBhdHRlcm47Cgl2YXIgJG1pbWU7CgoJZnVuY3Rpb24gIF9fY29uc3RydWN0KCRzdGFydCwgJHR5cGUsICRwYXR0ZXJuLCAkbWltZSkKCXsKCQkkdGhpcy0+c3RhcnQgPSAkc3RhcnQ7CgkJJHRoaXMtPnR5cGUgPSAkdHlwZTsKCQkkdGhpcy0+cGF0dGVybiA9ICRwYXR0ZXJuOwoJCSR0aGlzLT5taW1lID0gJG1pbWU7Cgl9Cn0KY2xhc3MgTWltZUNoZWNrZXIgewoJdmFyICRkYXRhID0gbnVsbDsKCXZhciAkdHlwZXMgPSBhcnJheSgpOwoJCglmdW5jdGlvbiAgX19jb25zdHJ1Y3QoKQoJewoJfQoJCglmdW5jdGlvbiBwYXJzZSgkZmlsZXBhdGgpCgl7CgkJaWYoKCFmaWxlX2V4aXN0cygkZmlsZXBhdGgpKSB8fCAoaXNfZGlyKCRmaWxlcGF0aCkpKQoJCXsKCQkJcmV0dXJuICJtaW1l44K/44Kk44OX44Gu5a6a576p44OV44Kh44Kk44Or44GM6KaL44Gk44GL44KK44G+44Gb44KT44CCIjsKCQl9CgkJCgkJJHRoaXMtPmRhdGEgPSBmaWxlKCRmaWxlcGF0aCk7CgoJCSR0eXBlcyA9IGFycmF5KAoJCQknYnl0ZScsJ3Nob3J0JywnbG9uZycsJ3N0cmluZycsJ2RhdGUnLAoJCQknYmVzaG9ydCcsJ2JlbG9uZycsJ2JlZGF0ZScsCgkJCSdsZXNob3J0JywnbGVsb25nJywnbGVkYXRlJwoJCSk7CgoJCSRwdG5fdHlwZXMgPSBpbXBsb2RlKCd8JywgJHR5cGVzKTsKCQkKCQlmb3JlYWNoKCR0aGlzLT5kYXRhIGFzICRsaW5lKQoJCXsKCQkJaWYocHJlZ19tYXRjaCgnL14jLycsICRsaW5lKSkKCQkJewkKCQkJCWNvbnRpbnVlOwoJCQl9CgkJCQoJCQlpZihwcmVnX21hdGNoKAoJCQkJJy9eKD4/XGQrKVxzKygnIC4gJHB0bl90eXBlcyAuICcpXHMrKChceDVjIHxbXlxzXSkqKVxzKyhbXlxzXSspPy8nLAoJCQkJICRsaW5lLCAkbWF0Y2gpID09IDApCgkJCXsKCQkJCWNvbnRpbnVlOwoJCQl9CgkJCWVsc2UKCQkJewoJCQkJaWYoZW1wdHkoJG1hdGNoWzVdKSkKCQkJCXsKCQkJCQkkbWF0Y2hbNV0gPSBudWxsOwoJCQkJfQoJCQkJCgkJCQkkdGhpcy0+dHlwZXNbXSA9IG5ldyBNaW1lVHlwZURlZmluaXRpb24oJG1hdGNoWzFdLCAkbWF0Y2hbMl0sICRtYXRjaFszXSwgJG1hdGNoWzVdKTsKCQkJfQoJCX0KCQkKCQlyZXR1cm4gZmFsc2U7Cgl9CgkKCWZ1bmN0aW9uIGdldE1pbWUoJHBhdGgpCgl7CgkJaWYoZW1wdHkoJHRoaXMtPmRhdGEpKQoJCXsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQkKCQlpZigoIWZpbGVfZXhpc3RzKCRwYXRoKSkgfHwgKGlzX2RpcigkcGF0aCkpKQoJCXsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQkKCQkkbWltZSA9IG51bGw7CgkJJGZwID0gZm9wZW4oJHBhdGgsICJyYiIpOwoJCQoJCSRjb3VudCA9IGNvdW50KCR0aGlzLT50eXBlcyk7CgoJCWZvcigkaSA9IDA7ICRpIDwgJGNvdW50OykKCQl7CgkJCSRzdGFydCA9ICR0aGlzLT50eXBlc1skaV0tPnN0YXJ0OwoJCQkKCQkJaWYocHJlZ19tYXRjaCgnL15cZCskLycsICRzdGFydCkgPiAwKQoJCQl7CgkJCQkkbWltZSA9ICR0aGlzLT5jaGVja01pbWUoJGZwLCAkaSk7CgkJCQkkaSsrOwoJCQkJCgkJCQlpZigkbWltZSkKCQkJCXsKCQkJCQlyZXR1cm4gdHJpbSgkbWltZSk7CgkJCQl9CgkJCX0KCQkJZWxzZQoJCQl7CgkJCQkkaSsrOwoJCQl9CgkJfQoJCQoJCWlmKCEkbWltZSkKCQl7CgkJCXJldHVybiAnYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJzsKCQl9Cgl9CgkKCWZ1bmN0aW9uIGNoZWNrTWltZSgkZnAsICRpKQoJewoJCSRpc21hdGNoID0gZmFsc2U7CgkJCgkJc3dpdGNoKCR0aGlzLT50eXBlc1skaV0tPnR5cGUpCgkJewoJCQljYXNlICJieXRlIiA6IAoJCQkJJGlzbWF0Y2ggPSAkdGhpcy0+Y2hlY2tCeXRlKCRmcCwgJHRoaXMtPnR5cGVzWyRpXSk7CgkJCWJyZWFrOwoJCQljYXNlICJzaG9ydCIgOiAKCQkJCSRpc21hdGNoID0gJHRoaXMtPmNoZWNrU2hvcnQoJGZwLCAkdGhpcy0+dHlwZXNbJGldKTsKCQkJYnJlYWs7CgkJCWNhc2UgImxvbmciIDogCgkJCQkkaXNtYXRjaCA9ICR0aGlzLT5jaGVja0xvbmcoJGZwLCAkdGhpcy0+dHlwZXNbJGldKTsKCQkJYnJlYWs7CgkJCWNhc2UgInN0cmluZyIgOiAKCQkJCSRpc21hdGNoID0gJHRoaXMtPmNoZWNrU3RyKCRmcCwgJHRoaXMtPnR5cGVzWyRpXSk7CgkJCWJyZWFrOwoJCQljYXNlICJkYXRlIiA6IAoJCQkJJGlzbWF0Y2ggPSAkdGhpcy0+Y2hlY2tUaW1lKCRmcCwgJHRoaXMtPnR5cGVzWyRpXSk7CgkJCWJyZWFrOwoJCQljYXNlICJiZXNob3J0IiA6IAoJCQkJJGlzbWF0Y2ggPSAkdGhpcy0+Y2hlY2tCZVNob3J0KCRmcCwgJHRoaXMtPnR5cGVzWyRpXSk7CgkJCWJyZWFrOwoJCQljYXNlICJiZWxvbmciIDogCgkJCQkkaXNtYXRjaCA9ICR0aGlzLT5jaGVja0JlTG9uZygkZnAsICR0aGlzLT50eXBlc1skaV0pOwoJCQlicmVhazsKCQkJY2FzZSAiYmVkYXRlIiA6IAoJCQkJJGlzbWF0Y2ggPSAkdGhpcy0+Y2hlY2tCZVRpbWUoJGZwLCAkdGhpcy0+dHlwZXNbJGldKTsKCQkJYnJlYWs7CgkJCWNhc2UgImxlc2hvcnQiIDogCgkJCQkkaXNtYXRjaCA9ICR0aGlzLT5jaGVja0xlU2hvcnQoJGZwLCAkdGhpcy0+dHlwZXNbJGldKTsKCQkJYnJlYWs7CgkJCWNhc2UgImxlbG9uZyIgOiAKCQkJCSRpc21hdGNoID0gJHRoaXMtPmNoZWNrTGVMb25nKCRmcCwgJHRoaXMtPnR5cGVzWyRpXSk7CgkJCWJyZWFrOwoJCQljYXNlICJsZWRhdGUiIDogCgkJCQkkaXNtYXRjaCA9ICR0aGlzLT5jaGVja0xlVGltZSgkZnAsICR0aGlzLT50eXBlc1skaV0pOwoJCQlicmVhazsKCQl9CgkJCgkJaWYoKCEkaXNtYXRjaCkgJiYgKHByZWdfbWF0Y2goJy9eXGQrJC8nLCAkdGhpcy0+dHlwZXNbJGldLT5zdGFydCkgPiAwKSkKCQl7CgkJCXJldHVybiBudWxsOwoJCX0KCQkKCQlpZihpc3NldCgkdGhpcy0+dHlwZXNbJGldLT5taW1lKSkKCQl7CgkJCXJldHVybiAkdGhpcy0+dHlwZXNbJGldLT5taW1lOwoJCX0KCQkKCQkkY291bnQgPSBjb3VudCgkdGhpcy0+dHlwZXMpOwoJCQoJCWZvcigkaSsrOyAkaSA8ICRjb3VudDsgJGkrKykKCQl7CgkJCWlmKHByZWdfbWF0Y2goJy9eXGQrJC8nLCAkdGhpcy0+dHlwZXNbJGldLT5zdGFydCkgPiAwKQoJCQl7CgkJCQlyZXR1cm4gbnVsbDsKCQkJfQoJCQllbHNlCgkJCXsKCQkJCSRtaW1lID0gJHRoaXMtPmNoZWNrTWltZSgkZnAsICRpKTsKCQkJCQoJCQkJaWYoJG1pbWUpCgkJCQl7CgkJCQkJcmV0dXJuICRtaW1lOwoJCQkJfQoJCQl9CgkJfQoJfQoJCglmdW5jdGlvbiBjaGVja0J5dGUoJGZwLCAkdHlwZSkKCXsKCQkkc3RhcnQgPSAkdHlwZS0+c3RhcnQ7CgkJCgkJaWYoJHR5cGUtPnBhdHRlcm4gPT0gIngiKQoJCXsKCQkJcmV0dXJuIHRydWU7CgkJfQoJCWVsc2UgaWYocHJlZ19tYXRjaCgnL14oPXw8fD58JnxefH4pPygwP3g/W1xkYS1mXSspJC9pJywgJHR5cGUtPnBhdHRlcm4sICRtYXRjaCkgPT0gMCkKCQl7CgkJCXJldHVybiBmYWxzZTsKCQl9CgkJCgkJaWYoZW1wdHkoJG1hdGNoWzFdKSkKCQl7CgkJCSRtYXRjaFsxXSA9IG51bGw7CgkJfQoJCQoJCWZzZWVrKCRmcCwgJHN0YXJ0KTsKCQkkZGF0YSA9IGZyZWFkKCRmcCwgMSk7CgkJCgkJcmV0dXJuICR0aGlzLT5jaGVja0ludCgkbWF0Y2hbMV0sICRtYXRjaFsyXSwgJGRhdGEpOwoJCQoJfQoJCglmdW5jdGlvbiBjaGVja1Nob3J0KCRmcCwgJHR5cGUpCgl7CgkJJHN0YXJ0ID0gJHR5cGUtPnN0YXJ0OwoJCQoJCWlmKCR0eXBlLT5wYXR0ZXJuID09ICJ4IikKCQl7CgkJCXJldHVybiB0cnVlOwoJCX0KCQllbHNlIGlmKHByZWdfbWF0Y2goJy9eKD18PHw+fCZ8Xnx+KT8oMD94P1tcZGEtZl0rKSQvaScsICR0eXBlLT5wYXR0ZXJuLCAkbWF0Y2gpID09IDApCgkJewoJCQlyZXR1cm4gZmFsc2U7CgkJfQoJCQoJCWlmKGVtcHR5KCRtYXRjaFsxXSkpCgkJewoJCQkkbWF0Y2hbMV0gPSBudWxsOwoJCX0KCQkKCQlmc2VlaygkZnAsICRzdGFydCk7CgkJJGRhdGEgPSBmcmVhZCgkZnAsIDIpOwoJCQoJCXJldHVybiAkdGhpcy0+Y2hlY2tJbnQoJG1hdGNoWzFdLCAkbWF0Y2hbMl0sICRkYXRhKTsKCQkKCX0KCQoJZnVuY3Rpb24gY2hlY2tMb25nKCRmcCwgJHR5cGUpCgl7CgkJJHN0YXJ0ID0gJHR5cGUtPnN0YXJ0OwoJCQoJCWlmKCR0eXBlLT5wYXR0ZXJuID09ICJ4IikKCQl7CgkJCXJldHVybiB0cnVlOwoJCX0KCQllbHNlIGlmKHByZWdfbWF0Y2goJy9eKD18PHw+fCZ8Xnx+KT8oMD94P1tcZGEtZl0rKSQvaScsICR0eXBlLT5wYXR0ZXJuLCAkbWF0Y2gpID09IDApCgkJewoJCQlyZXR1cm4gZmFsc2U7CgkJfQoJCQoJCWlmKGVtcHR5KCRtYXRjaFsxXSkpCgkJewoJCQkkbWF0Y2hbMV0gPSBudWxsOwoJCX0KCQkKCQlmc2VlaygkZnAsICRzdGFydCk7CgkJJGRhdGEgPSBmcmVhZCgkZnAsIDQpOwoJCQoJCXJldHVybiAkdGhpcy0+Y2hlY2tJbnQoJG1hdGNoWzFdLCAkbWF0Y2hbMl0sICRkYXRhKTsKCQkKCX0KCQoJZnVuY3Rpb24gY2hlY2tJbnQoJG1vZGUsICRudW0sICRkYXRhLCAkcGFja2ZtdCA9IG51bGwpCgl7CgkJaWYocHJlZ19tYXRjaCgnL14weChbXGRhLWZdKykkL2knLCAkbnVtLCAkbWF0Y2gpID4gMCkKCQl7CgkJCSRudW0gPSBpbnR2YWwoJG1hdGNoWzFdLCAxNik7CgkJfQoJCWVsc2UgaWYocHJlZ19tYXRjaCgnL14wKFxkKykkLycsICRudW0sICRtYXRjaCkgPiAwKQoJCXsKCQkJJG51bSA9IGludHZhbCgkbWF0Y2hbMV0sIDgpOwoJCX0KCQllbHNlIGlmKHByZWdfbWF0Y2goJy9eKFxkKykkLycsICRudW0sICRtYXRjaCkgPiAwKQoJCXsKCQkJJG51bSA9IGludHZhbCgkbnVtLCAxMCk7CgkJfQoJCWVsc2UKCQl7CgkJCXJldHVybiBmYWxzZTsKCQl9CgkJCgkJaWYoJHBhY2tmbXQpCgkJewoJCQlzd2l0Y2goJHBhY2tmbXQpCgkJCXsKCQkJCWNhc2UgIm4iIDoKCQkJCWJyZWFrOwoJCQkJCgkJCQljYXNlICJOIiA6CgkJCQlicmVhazsKCQkJCQoJCQkJY2FzZSAidiIgOgoJCQkJYnJlYWs7CgkJCQkKCQkJCWNhc2UgIlYiIDoKCQkJCWJyZWFrOwoJCQkJCgkJCQlkZWZhdWx0OgoJCQkJIHJldHVybiBmYWxzZTsKCQkJfQoJCQkKCQkJJG51bSA9IHBhY2soJHBhY2tmbXQsICRudW0pOwoJCX0KCQkKCQlpZihlbXB0eSgkbW9kZSkgfHwgKCRtb2RlID09ICI9IikpCgkJewoJCQlpZigkZGF0YSA9PSAkbnVtKQoJCQl7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX0KCQllbHNlIGlmKCRtb2RlID09ICI8IikKCQl7CgkJCWlmKCRkYXRhIDwgJG51bSkKCQkJewoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9CgkJZWxzZSBpZigkbW9kZSA9PSAiPiIpCgkJewoJCQlpZigkZGF0YSA+ICRudW0pCgkJCXsKCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJfQoJCWVsc2UgaWYoJG1vZGUgPT0gIiYiKQoJCXsKCQkJaWYoKCRkYXRhICYgJG51bSkgPT0gJG51bSkKCQkJewoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQl9CgkJZWxzZSBpZigkbW9kZSA9PSAiXiIpCgkJewoJCQlpZigoJGRhdGEgJiAkbnVtKSAhPSAkbnVtKQoJCQl7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX0KCQllbHNlIGlmKCRtb2RlID09ICJ+IikKCQl7CgkJCWlmKCRkYXRhID09IH4kbnVtKQoJCQl7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCX0KCQkKCQlyZXR1cm4gZmFsc2U7Cgl9CgkKCWZ1bmN0aW9uIGNoZWNrU3RyKCRmcCwgJHR5cGUpCgl7CgkJJHN0YXJ0ID0gJHR5cGUtPnN0YXJ0OwoKCQlpZihwcmVnX21hdGNoKCcvXig9fDx8Pik/KChceDVjIHxbXlxzXSkqKSQvaScsICR0eXBlLT5wYXR0ZXJuLCAkbWF0Y2gpID09IDApCgkJewoJCQlyZXR1cm4gZmFsc2U7CgkJfQoJCQoJCWlmKGVtcHR5KCRtYXRjaFsxXSkpCgkJewoJCQkkbWF0Y2hbMV0gPSBudWxsOwoJCX0KCQkKCQkkbWF0Y2hbMl0gPSBwcmVnX3JlcGxhY2UoJy9ceDVjIC8nLCAnICcsICRtYXRjaFsyXSk7CgkJJG1hdGNoWzJdID0gcHJlZ19yZXBsYWNlKCcvXHg1YzwvJywgJzwnLCAkbWF0Y2hbMl0pOwoJCSRtYXRjaFsyXSA9IHByZWdfcmVwbGFjZSgnL1x4NWM+LycsICc+JywgJG1hdGNoWzJdKTsKCQkkbWF0Y2hbMl0gPSBwcmVnX3JlcGxhY2UoJy9ceDVjPS8nLCAnPScsICRtYXRjaFsyXSk7CgkJCgkJJHB0biA9ICR0aGlzLT51bmVzY2FwZSgkbWF0Y2hbMl0pOwoJCSRsZW4gPSBzdHJsZW4oJHB0bik7CgkJCgkJZnNlZWsoJGZwLCAkc3RhcnQpOwoJCSRkYXRhID0gZnJlYWQoJGZwLCAkbGVuKTsKCQkKCQlpZihlbXB0eSgkbWF0Y2hbMV0pIHx8ICgkbWF0Y2hbMV0gPT0gIj0iKSkKCQl7CgkJCWlmKCgkbWF0Y2hbMF0gPT0gJz1cMCcpICYmICgkZGF0YSA9PSAiIikpCgkJCXsKCQkJCXJldHVybiB0cnVlOwoJCQl9CgkJCWVsc2UgaWYoJGRhdGEgPT0gJHB0bikKCQkJewoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQkJZWxzZQoJCQl7CgkJCQlyZXR1cm4gZmFsc2U7CgkJCX0KCQkJCgkJfQoJCWVsc2UgaWYoJG1hdGNoWzFdID09ICI8IikKCQl7CgkJCWlmKHN0cmNtcCgkZGF0YSwgJHB0bikgPCAwKQoJCQl7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCQllbHNlCgkJCXsKCQkJCXJldHVybiBmYWxzZTsKCQkJfQoJCX0KCQllbHNlIGlmKCRtYXRjaFsxXSA9PSAiPiIpCgkJewoJCQlpZigoJG1hdGNoWzBdID09ICc+XDAnKSAmJiAoJGRhdGEgIT0gIiIpKQoJCQl7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCQllbHNlIGlmKHN0cmNtcCgkZGF0YSwgJHB0bikgPiAwKQoJCQl7CgkJCQlyZXR1cm4gdHJ1ZTsKCQkJfQoJCQllbHNlCgkJCXsKCQkJCXJldHVybiBmYWxzZTsKCQkJfQoJCX0KCX0KCQoJZnVuY3Rpb24gY2hlY2tUaW1lKCRmcCwgJHR5cGUpCgl7CgkJJHN0YXJ0ID0gJHR5cGUtPnN0YXJ0OwoKCQlmc2VlaygkZnAsICRzdGFydCk7CgkJJGRhdGEgPSBmcmVhZCgkZnAsIDQpOwoKCQlpZihpbnR2YWwoJGRhdGEpID09IGludHZhbCgkdGhpcy0+cGF0dGVybikpCgkJewoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJZWxzZQoJCXsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCX0KCQoJZnVuY3Rpb24gY2hlY2tCZVNob3J0KCRmcCwgJHR5cGUpCgl7CgkJJHN0YXJ0ID0gJHR5cGUtPnN0YXJ0OwoJCQoJCWlmKCR0eXBlLT5wYXR0ZXJuID09ICJ4IikKCQl7CgkJCXJldHVybiB0cnVlOwoJCX0KCQllbHNlIGlmKHByZWdfbWF0Y2goJy9eKD18PHw+fCZ8Xnx+KT8oMD94P1tcZGEtZl0rKSQvaScsICR0eXBlLT5wYXR0ZXJuLCAkbWF0Y2gpID09IDApCgkJewoJCQlyZXR1cm4gZmFsc2U7CgkJfQoJCQoJCWlmKGVtcHR5KCRtYXRjaFsxXSkpCgkJewoJCQkkbWF0Y2hbMV0gPSBudWxsOwoJCX0KCQkKCQlmc2VlaygkZnAsICRzdGFydCk7CgkJJGRhdGEgPSBmcmVhZCgkZnAsIDIpOwoJCQoJCXJldHVybiAkdGhpcy0+Y2hlY2tJbnQoJG1hdGNoWzFdLCAkbWF0Y2hbMl0sICRkYXRhLCAibiIpOwoJCQoJfQoJCglmdW5jdGlvbiBjaGVja0JlTG9uZygkZnAsICR0eXBlKQoJewoJCSRzdGFydCA9ICR0eXBlLT5zdGFydDsKCQkKCQlpZigkdHlwZS0+cGF0dGVybiA9PSAieCIpCgkJewoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJZWxzZSBpZihwcmVnX21hdGNoKCcvXig9fDx8PnwmfF58fik/KDA/eD9bXGRhLWZdKykkL2knLCAkdHlwZS0+cGF0dGVybiwgJG1hdGNoKSA9PSAwKQoJCXsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQkKCQlpZihlbXB0eSgkbWF0Y2hbMV0pKQoJCXsKCQkJJG1hdGNoWzFdID0gbnVsbDsKCQl9CgkJCgkJZnNlZWsoJGZwLCAkc3RhcnQpOwoJCSRkYXRhID0gZnJlYWQoJGZwLCA0KTsKCQkKCQlyZXR1cm4gJHRoaXMtPmNoZWNrSW50KCRtYXRjaFsxXSwgJG1hdGNoWzJdLCAkZGF0YSwgIk4iKTsKCQkKCX0KCQoJZnVuY3Rpb24gY2hlY2tCZVRpbWUoJGZwLCAkdHlwZSkKCXsKCQkkc3RhcnQgPSAkdHlwZS0+c3RhcnQ7CgoJCWZzZWVrKCRmcCwgJHN0YXJ0KTsKCQkkZGF0YSA9IGZyZWFkKCRmcCwgNCk7CgoJCWlmKHBhY2soIk4iLCBpbnR2YWwoJGRhdGEpKSA9PSBpbnR2YWwoJHRoaXMtPnBhdHRlcm4pKQoJCXsKCQkJcmV0dXJuIHRydWU7CgkJfQoJCWVsc2UKCQl7CgkJCXJldHVybiBmYWxzZTsKCQl9Cgl9CgkKCWZ1bmN0aW9uIGNoZWNrTGVTaG9ydCgkZnAsICR0eXBlKQoJewoJCSRzdGFydCA9ICR0eXBlLT5zdGFydDsKCQkKCQlpZigkdHlwZS0+cGF0dGVybiA9PSAieCIpCgkJewoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJZWxzZSBpZihwcmVnX21hdGNoKCcvXig9fDx8PnwmfF58fik/KDA/eD9bXGRhLWZdKykkL2knLCAkdHlwZS0+cGF0dGVybiwgJG1hdGNoKSA9PSAwKQoJCXsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQkKCQlpZihlbXB0eSgkbWF0Y2hbMV0pKQoJCXsKCQkJJG1hdGNoWzFdID0gbnVsbDsKCQl9CgkJCgkJZnNlZWsoJGZwLCAkc3RhcnQpOwoJCSRkYXRhID0gZnJlYWQoJGZwLCAyKTsKCQkKCQlyZXR1cm4gJHRoaXMtPmNoZWNrSW50KCRtYXRjaFsxXSwgJG1hdGNoWzJdLCAkZGF0YSwgInYiKTsKCQkKCX0KCQoJZnVuY3Rpb24gY2hlY2tMZUxvbmcoJGZwLCAkdHlwZSkKCXsKCQkkc3RhcnQgPSAkdHlwZS0+c3RhcnQ7CgkJCgkJaWYoJHR5cGUtPnBhdHRlcm4gPT0gIngiKQoJCXsKCQkJcmV0dXJuIHRydWU7CgkJfQoJCWVsc2UgaWYocHJlZ19tYXRjaCgnL14oPXw8fD58JnxefH4pPygwP3g/W1xkYS1mXSspJC9pJywgJHR5cGUtPnBhdHRlcm4sICRtYXRjaCkgPT0gMCkKCQl7CgkJCXJldHVybiBmYWxzZTsKCQl9CgkJCgkJaWYoZW1wdHkoJG1hdGNoWzFdKSkKCQl7CgkJCSRtYXRjaFsxXSA9IG51bGw7CgkJfQoJCQoJCWZzZWVrKCRmcCwgJHN0YXJ0KTsKCQkkZGF0YSA9IGZyZWFkKCRmcCwgNCk7CgkJCgkJcmV0dXJuICR0aGlzLT5jaGVja0ludCgkbWF0Y2hbMV0sICRtYXRjaFsyXSwgJGRhdGEsICJWIik7CgkJCgl9CgkKCWZ1bmN0aW9uIGNoZWNrTGVUaW1lKCRmcCwgJHR5cGUpCgl7CgkJJHN0YXJ0ID0gJHR5cGUtPnN0YXJ0OwoKCQlmc2VlaygkZnAsICRzdGFydCk7CgkJJGRhdGEgPSBmcmVhZCgkZnAsIDQpOwoKCQlpZihwYWNrKCJWIiwgaW50dmFsKCRkYXRhKSkgPT0gaW50dmFsKCR0aGlzLT5wYXR0ZXJuKSkKCQl7CgkJCXJldHVybiB0cnVlOwoJCX0KCQllbHNlCgkJewoJCQlyZXR1cm4gZmFsc2U7CgkJfQoJfQoJCglmdW5jdGlvbiB1bmVzY2FwZSgkc3RyKQoJewoJCSRwdG4gPSBhcnJheSgKCQkJJ1xkezN9JywgJ3hbXGRhLWZdezJ9JywgJzAnLCAnMDEnLCAnMDInLCAnMDMnLCAnMDQnLCAnMDUnLCAnMDYnLAoJCQknYScsICdiJywgJ3QnLCAnbicsICd2JywgJ2YnLCdyJywgJ1x4NWMnLCAnXHgzZicsICciJywgJ1x4MjcnLCAKCQkpOwoJCSRwdG4gPSBpbXBsb2RlKCd8JywgJHB0bik7CgkJCgkJcmV0dXJuIHByZWdfcmVwbGFjZV9jYWxsYmFjaygnL1x4NWMoJyAuICRwdG4gLiAnKS9pJywgLy8nXFwn44Go6KiY6L+w44GX44Gm44KC5q2j5bi444Gr5YuV5L2c44GX44Gq44GE44Gf44KB44CBXHg1Y+OBqOiomOi/sAoJCQljcmVhdGVfZnVuY3Rpb24oJyRtYXRjaCcsICdyZXR1cm4gTWltZUNoZWNrZXI6OnVuZXNjYXBlc3ViKCRtYXRjaFsxXSk7JyksCgkJCSRzdHIpOwoJfQoJCglzdGF0aWMgZnVuY3Rpb24gdW5lc2NhcGVzdWIoJG1hdGNoKQoJewoJCXN3aXRjaCgkbWF0Y2gpCgkJewoJCQljYXNlICIwIiA6CgkJCQlyZXR1cm4gIlwwIjsKCQkJYnJlYWs7CgkJCWNhc2UgIjAxIiA6CgkJCQlyZXR1cm4gIlwwMSI7CgkJCWJyZWFrOwoJCQljYXNlICIwMiIgOgoJCQkJcmV0dXJuICJcMDIiOwoJCQlicmVhazsKCQkJY2FzZSAiMDMiIDoKCQkJCXJldHVybiAiXDAzIjsKCQkJYnJlYWs7CgkJCWNhc2UgIjA0IiA6CgkJCQlyZXR1cm4gIlwwNCI7CgkJCWJyZWFrOwoJCQljYXNlICIwNSIgOgoJCQkJcmV0dXJuICJcMDUiOwoJCQlicmVhazsKCQkJY2FzZSAiMDYiIDoKCQkJCXJldHVybiAiXDA2IjsKCQkJYnJlYWs7CgkJCWNhc2UgImEiIDoKCQkJCXJldHVybiAiXGEiOwoJCQlicmVhazsKCQkJY2FzZSAiYiIgOgoJCQkJcmV0dXJuICJcYiI7CgkJCWJyZWFrOwoJCQljYXNlICJ0IiA6CgkJCQlyZXR1cm4gIlx0IjsKCQkJYnJlYWs7CgkJCWNhc2UgIm4iIDoKCQkJCXJldHVybiAiXG4iOwoJCQlicmVhazsKCQkJY2FzZSAidiIgOgoJCQkJcmV0dXJuICJcdiI7CgkJCWJyZWFrOwoJCQljYXNlICJmIiA6CgkJCQlyZXR1cm4gIlxmIjsKCQkJYnJlYWs7CgkJCWNhc2UgInIiIDoKCQkJCXJldHVybiAiXHIiOwoJCQlicmVhazsKCQkJY2FzZSAiXHg1YyIgOgoJCQkJcmV0dXJuICJceDVjIjsKCQkJYnJlYWs7CgkJCWNhc2UgIj8iIDoKCQkJCXJldHVybiAiPyI7CgkJCWJyZWFrOwoJCQljYXNlICInIiA6CgkJCQlyZXR1cm4gIiciOwoJCQlicmVhazsKCQkJY2FzZSAnIicgOgoJCQkJcmV0dXJuICciJzsKCQkJYnJlYWs7CgkJfQoJCQoJCWlmKHByZWdfbWF0Y2goJy9eKFxkezN9KSQvJywgJG1hdGNoLCAkc3VibWF0Y2gpID4gMCkKCQl7CgkJCXJldHVybiBwYWNrKCJDIiwgaW50dmFsKCRzdWJtYXRjaFsxXSwgOCkpOwoJCX0KCQllbHNlIGlmKHByZWdfbWF0Y2goJy9eeChbXGRhLWZdezJ9KSQvaScsICRtYXRjaCwgJHN1Ym1hdGNoKSA+IDApCgkJewoJCQlyZXR1cm4gcGFjaygiQyIsIGludHZhbCgkc3VibWF0Y2hbMV0sIDE2KSk7CgkJfQoJfQp9Cj8+