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 3 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, see .
*/
/**
* Parses mirc code
*
* @author stefys
*/
//due to no static in PHP4 OOP, i'm gonna have to put some variables outside the class
//Uncomment to have debug turned on
//define('WITH_DEBUG', 1);
//pattern to match identifiers with parameters
//\x28 = '('
//\x29 = ')'
//those are used so they don't break my syntax highlighting ;)
//$1 = identifier name
//$2 = parameters list
//$3 = optional prop
$_mircparser_identfier_regexp =
'@' .
'(\$[^\s\x28]+)' . // identifier name
'\x28' . // identifier open paranthesis
'((?:[^\x29]*,)*' . // all parameters but last
'[^\x29]*)' . // last parameter
'\x29' . //identifier close paranthesis
'(?:(\.[^\s]+)|())' . // optional prop
'@i';
$_mircparser_directory_tree = array(
//d: = directory
//f: = file
//every directory name and file name has to be lowercase
//for case insensitivity
'C' => array(
'd:windows' => array(
'd:system32' => array(
'f:winsock32.dll'
),
'd:system'
),
'd:documents and settings' => array(
'd:administrator' => array(
'd:desktop' => 'f:secret.txt'
)
),
'd:program files',
'd:mirc' => array(
'd:downloads',
'd:sounds',
'd:logs',
'f:mirc.ini',
'f:mirc.exe',
'f:script.ini'
),
'f:ntdetect.com',
'f:msdos.sys',
'f:io.sys',
'f:command.com'
),
'D' => array(
'd:games' => array('d:solitaire' => array('f:solitaire.exe'))
)
);
$_mircparser_partition_info = array(
'C' => array(
'type' => 'ntfs',
'free' => 1024*1024*1024*3.1, // 3.1 GB
'label' => 'local',
'size' => 4.5*1024*1024*1024 //4.5 GB (used 1.4GB)
),
'D' => array(
'type' => 'fat32',
'free' => 1024*1024*200, // 200mb free
'label' => 'other',
'size' => 1024*1024*512 //512 mb total
)
);
$_mircparser_mirc_dir = "C:\\mirc\\";
/**
* Public functions of the class:
* constructor (string $code_to_evaluate, array $variables_to_use,
* string $nick, string $addr, string $addr_server,
* string $chan, string $name, string $me,
* int $port, string $s_string, string $mirc_version)
* bool iswm (string wildcard, string string)
* string get_parsed_string()
* array get_used_commands()
* ** returns an array where each value
* ** is a command used with $findfile or $finddir
*/
class Mircparser {
var $_str, $_info, $_used_commands, $_used_identifiers, $_variables;
/**
* Class constructor
*/
function Mircparser ($mirc_code, $variables, $nick, $addr, $addr_server, $chan, $name, $me, $port, $s_string, $version) {
// constructor
$this->_str = $mirc_code;
$this->_info = array(
'nick' => $nick,
'addr' => $addr,
'addr_server' => $addr_server,
'chan' => $chan,
'name' => $name,
'me' => $me,
'port' => $port,
's_string' => $s_string,
'version' => $version
);
$this->_used_commands = array();
$this->_used_identifiers = array();
$this->_variables = $variables;
//if the mirc code to parse starts wtih $ or %, we prepend a space
if (substr($this->_str,0,1) == '$' ||
substr($this->_str,0,1) == '%')
$this->_str = ' '. $this->_str;
$this->_str = &$this->_eval($this->_str);
$this->_str = &$this->_tomirc($this->_str);
}
// no double spaces, no spaces at beginning, no spaces at the end
function _tomirc ($str) {
$str = str_replace(array("\r", "\n"), "", $str);
$str = str_replace(' ', ' ', $str);
$str = preg_replace('@^\s+@', '', $str);
$str = preg_replace('@\s+$@', '', $str);
return $str;
}
function _eval ($mirc_code) {
global $_mircparser_identfier_regexp;
$str = $mirc_code;
//first we replace identifiers with parameters in the following way
//$id(param1,param2,...,paramN) becomes
//$id( param1 , param2 , param3 , ... , paramN)
//we add spaces so we can then do the basic replace
if (defined('WITH_DEBUG')) echo "_eval($str)
";
$str = preg_replace($_mircparser_identfier_regexp."e", "'$1( ' . str_replace(',', ' , ', '$2') . ' )$3'", $str);
if (defined('WITH_DEBUG')) echo "added spaces to identifiers: $str
";
// we did add spaces between parameters of identifiers, we now do the basic replace
$str = $this->_basic($str);
if (defined('WITH_DEBUG')) echo "after basic parse: $str
";
//we replace all the variables
//first, we replace the one that exist with their corresponding values
foreach ($this->_variables as $var => $val)
$str = str_replace(' %'.$var, ' '.$val, $str);
if (defined('WITH_DEBUG')) echo "after variables replacement[1]: $str
";
//then we replace the ones that do not exist with null
$str = preg_replace('@%(?:[^ ]+)@', ' ', $str);
if (defined('WITH_DEBUG')) echo "[2]: $str
";
//we've done basic replace, now we do replace for identifiers that have parameters
//we do so by calling the _adv_replacel function for each identifier
$str = preg_replace($_mircparser_identfier_regexp."e", '$this->_adv_replace(\'$0\')', $str);
if (defined('WITH_DEBUG')) echo "finally, the result: $str
";
return $str;
}
function _adv_replace ($str) {
$id_name = substr($str, 1, strpos($str, '(')-1); // everything after $ until (
$id_params = substr($str, ($s = strpos($str, '(') +1), strpos($str,')')-$s);
$id_params_a = array();
$id_params_arr = explode(',', $id_params);
foreach ($id_params_arr as $param)
$id_params_a[] = $this->_tomirc($param);
if (($s=strpos($str, ').')) !== false)
//we have a prop
$id_prop = substr($str, $s+2);
else $id_prop = '';
return $this->_adv_replace_call($id_name, $id_params_a, $id_prop);
}
//called when we have an identifier with parameters
function _adv_replace_call ($id_name, $id_params, $prop) {
if (count($id_params) < 1)
return '';
global $_mircparser_partition_info;
switch ($id_name) {
case 'chr':
return chr( (int)$id_params[0] );
break;
case 'asc':
return ord( substr($id_params[0],0,1) );
break;
case 'disk':
$exists = isset($_mircparser_partition_info[strtoupper(substr($id_params[0],0,1))]);
if ($exists) $ref = &$_mircparser_partition_info[strtoupper(substr($id_params[0],0,1))];
else $ref = null;
if ($prop == null) return $exists?'$true':'$false';
elseif (isset($ref[$prop])) return $ref[$prop];
else return '';
break;
case 'len':
return strlen($id_params[0]);
break;
case 'calc':
//simple calc only
$m = array();
//$1 = first number
//$2 = sign
//$3 = second number
if (!preg_match('@(\d+)\s*([+*/-^])\s*(\d+)@', $id_params[0], $m))
return 0;
elseif ($m[2] == '+') return $m[1]+$m[3];
elseif ($m[2] == '-') return $m[1]-$m[3];
elseif ($m[2] == '*') return $m[1]*$m[3];
elseif ($m[2] == '/' && $m[3] == 0) return 0;
elseif ($m[2] == '/') return $m[1]/$m[3];
elseif ($m[2] == '^') return pow($m[1],$m[2]);
break;
case 'findfile':
return $this->_find($id_params, 'f:');
break;
case 'finddir':
return $this->_find($id_params, 'd:');
break;
case 'abs':
return abs((float)$id_params[0]);
break;
case 'and':
if (count($id_params) < 2) return '';
return (int)$id_params[0] & (int)$id_params[1];
break;
case 'base':
if (count($id_params) < 3) return '';
$d = base_convert((float)$id_params[0], (int)$id_params[1], (int)$id_params[2]);
if (isset($id_params[3]) &&
intval($id_params[3]) == $id_params[3] &&
( $to_add=$id_params[3]-strlen($d) ) > 0)
$d = str_repeat('0', $to_add) . $d;
return $d;
break;
case 'ceil':
return ceil((float)$id_params[3]);
case 'encode':
if (count($id_params) != 2) return '';
if ($id_params[1] != 'm') return '';
return base64_encode($id_params[0]);
break;
case 'decode':
if (count($id_params) != 2) return '';
if ($id_params[1] != 'm') return '';
return base64_decode($id_params[0]);
break;
case 'int':
return (int)$id_params[0];
break;
case 'lower':
return strtolower($id_params[0]);
break;
case 'upper':
return strtoupper($id_params[0]);
break;
case 'mid':
return substr($id_params[0], (int)$id_params[1], (int)$id_params[2]);
break;
case 'left':
return substr($id_params[0], 0, (int)$id_params[1]);
break;
case 'right':
return substr($id_params[0], strlen($id_params[0])-(int)$id_params[1], (int)$id_params[1]);
break;
default:
return '';
}
}
function iswm ($wildcard, $string) {
$regex = '@^';
for ($i=0; $i $v) {
if (is_array($v)) $item_name = $i;
else $item_name = $v;
if ($this->iswm($to_find, $item_name)) {
$matches++;
if ( ($cmd_or_win != '' && $cmd_or_win{0}!='@') &&
($matches == $nth || $nth == 0) ) {
$this->_used_commands[] = $cmd_or_win;
}
if ($matches == $nth)
return $path . substr($item_name,strlen($start_with));
}
}
if ($nth == 0) return $matches;
return '';
}
//by weekend
function _basic ($str)
{
//function to convert sertant mirc stuffs
//its just a replace...
//NOTE: this WILL do newline and whatnot so remove that if needed!
global $_mircparser_mirc_dir;
$from = array();
$to = array();
$nick = &$this->_info['nick'];
$addr = &$this->_info['addr'];
$addr_server = &$this->_info['addr_server'];
$chan = &$this->_info['chan'];
$name = &$this->_info['name'];
$me = &$this->_info['me'];
$port = &$this->_info['port'];
$s_string = &$this->_info['s_string'];
$version = &$this->_info['version'];
//stefys:
//would have been nicer to store them only once instead of initializing array everytime the function is called
$from[] = ' $address'; $to[] = $addr;
$from[] = ' $nick'; $to[] = $nick;
$from[] = ' $server'; $to[] = $addr_server;
$from[] = ' $serverip'; $to[] = '127.0.0.1';
$from[] = ' $status'; $to[] = 'connected';
$from[] = ' $show'; $to[] = '$true';
$from[] = ' $ulevel'; $to[] = '1';
$from[] = ' $snicks'; $to[] = '';
$from[] = ' $snotify'; $to[] = '';
$from[] = ' $sreq'; $to[] = 'ask';
$from[] = ' $ssl'; $to[] = '$true';
$from[] = ' $sslready'; $to[] = '$true';
$from[] = ' $ticks'; $to[] = '42569'.rand(111,999);
$from[] = ' $time'; $to[] = date("H:i:s");
$from[] = '$timestamp'; $to[] = date("[H:i:s]");
$from[] = '$timestampfmt'; $to[] = '[HH:nn:ss]';
$from[] = '$timezone'; $to[] = '25200';
$from[] = ' $titlebar'; $to[] = '';
$from[] = ' $url'; $to[] = 'http://www.hackthissite.org';
$from[] = ' $usermode'; $to[] = '+iwghrsOxqBzt';
$from[] = ' $vcmdver'; $to[] = '$null';
$from[] = ' $vcmdstat'; $to[] = '0';
$from[] = ' $version'; $to[] = $version;
$from[] = ' $wid'; $to[] = '6';
$from[] = ' $site'; $to[] = '';
$from[] = ' $wildsite'; $to[] = '';
$from[] = ' $active'; $to[] = $chan;
$from[] = ' $activecid'; $to[] = '1';
$from[] = ' $cid'; $to[] = '1';
$from[] = ' $activewid'; $to[] = '7';
$from[] = ' $agentname'; $to[] = '';
$from[] = ' $anick'; $to[] = 'altnick';
$from[] = ' $aop'; $to[] = '$false';
$from[] = ' $appactive'; $to[] = '$true';
$from[] = ' $appstate'; $to[] = 'maximized';
$from[] = ' $avoice'; $to[] = '$false';
$from[] = ' $away'; $to[] = '$false';
$from[] = ' $cb'; $to[] = '';
$from[] = ' $cr'; $to[] = "\r";
$from[] = ' $crlf'; $to[] = "\r\n";
$from[] = ' $chan'; $to[] = $chan;
$from[] = ' $chanmodes'; $to[] = 'beI,kfL,lj,psmntirRcOAQKVCuzNSMTG';
$from[] = ' $chantypes'; $to[] = '#';
$from[] = ' $cid'; $to[] = '1';
$from[] = ' $cmdbox'; $to[] = '$false';
$from[] = ' $creq'; $to[] = 'ask';
$from[] = ' $ctime'; $to[] = time();
$from[] = ' $date'; $to[] = date("d/m/Y");
$from[] = ' $adate'; $to[] = date("m/d/Y");
$from[] = ' $day'; $to[] = date("l");
$from[] = ' $daylight'; $to[] = ((date("I") == 1) ? "3600" : "0");
$from[] = ' $dccignore'; $to[] = '$false';
$from[] = ' $dccport'; $to[] = '59';
$from[] = ' $dlevel'; $to[] = '1';
$from[] = ' $emailaddr'; $to[] = 'moo@cowland.com';
$from[] = ' $ferr'; $to[] = '0';
$from[] = ' $filtered'; $to[] = '0';
$from[] = ' $fulladdress'; $to[] = $addr;
$from[] = ' $fulldate'; $to[] = date("D M j G:i:s Y");
$from[] = ' $fullname'; $to[] = $name;
$from[] = ' $gmt'; $to[] = time();
$from[] = ' $highlight'; $to[] = '$false';
$from[] = ' $host'; $to[] = 'www.hackthissite.org';
$from[] = ' $idle'; $to[] = '0';
$from[] = ' $ip'; $to[] = '127.0.0.1';
$from[] = ' $lf'; $to[] = "\n";
$from[] = ' $locked'; $to[] = '$false';
$from[] = ' $logdir'; $to[] = $_mircparser_mirc_dir.'logs\\';
$from[] = ' $logstamp'; $to[] = date("[H:i:s]");
$from[] = ' $logstampfnt'; $to[] = '[HH:nn:ss]';
$from[] = ' $ltimer'; $to[] = '4';
$from[] = ' $me'; $to[] = $me;
$from[] = ' $mididir'; $to[] = $_mircparser_mirc_dir.'sounds\\';
$from[] = ' $mircdir'; $to[] = $_mircparser_mirc_dir;
$from[] = ' $mircexe'; $to[] = $_mircparser_mirc_dir.'mirc.exe';
$from[] = ' $mircini'; $to[] = $_mircparser_mirc_dir.'mirc.ini';
$from[] = ' $mnick'; $to[] = $me;
$from[] = ' $network'; $to[] = 'HackThisSite';
$from[] = ' $os'; $to[] = 'XP';
$from[] = ' $passivedcc'; $to[] = '$false';
$from[] = ' $port'; $to[] = $port;
$from[] = ' $portable'; $to[] = '$false';
$from[] = ' $prefix'; $to[] = '~&@%+';
$from[] = ' $rawline'; $to[] = $s_string;
$from[] = ' $script'; $to[] = 'script.mrc';
$from[] = ' $scriptdir'; $to[] = $_mircparser_mirc_dir;
$from[] = ' $scriptline'; $to[] = '40';
//that should do..
return str_replace($from, $to, $str);
}
function get_parsed_string () {
return $this->_str;
}
//the one replaced by _basic() are not shown here
function get_used_identifiers () {
return $this->_used_identifiers;
}
// an array with commands executed with $finddir() or $findfile
function get_used_commands () {
return $this->_used_commands;
}
}
/* Usage
$code = '$findfile(.,*,1,lol) $finddir(c:/,*w*,1,echo -a found!) $right(abcdef,2)';
$vars = array('d' => 'omg var worked', 'a' => 5, 'b' => 6);
//function Mircparser ($mirc_code, $variables, $nick, $addr, $addr_server, $chan, $name, $me, $port, $s_string, $version)
$mircparser = new Mircparser($code, $vars, 'YourNick', 'Addr', 'AddrServer', '#Chan', 'Name', 'MyNick', '12345', 'S_string', 4);
echo $mircparser->get_parsed_string();
print_r($mircparser->get_used_commands());
*/
?>