debug) { echo $text . "\n"; } } /** * * * @param string $length * * @return void */ public function encodeLength($length) { if ($length < 0x80) { $length = chr($length); } elseif ($length < 0x4000) { $length |= 0x8000; $length = chr(($length >> 8) & 0xFF) . chr($length & 0xFF); } elseif ($length < 0x200000) { $length |= 0xC00000; $length = chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); } elseif ($length < 0x10000000) { $length |= 0xE0000000; $length = chr(($length >> 24) & 0xFF) . chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); } elseif ($length >= 0x10000000) { $length = chr(0xF0) . chr(($length >> 24) & 0xFF) . chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); } return $length; } /** * Login to RouterOS * * @param string $ip Hostname (IP or domain) of the RouterOS server * @param string $login The RouterOS username * @param string $password The RouterOS password * * @return boolean If we are connected or not */ public function connect($ip, $login, $password) { for ($ATTEMPT = 1; $ATTEMPT <= $this->attempts; $ATTEMPT++) { $this->connected = false; $PROTOCOL = ($this->ssl ? 'ssl://' : '' ); $context = stream_context_create(array('ssl' => array('ciphers' => 'ADH:ALL', 'verify_peer' => false, 'verify_peer_name' => false))); $this->debug('Connection attempt #' . $ATTEMPT . ' to ' . $PROTOCOL . $ip . ':' . $this->port . '...'); $this->socket = @stream_socket_client($PROTOCOL . $ip.':'. $this->port, $this->error_no, $this->error_str, $this->timeout, STREAM_CLIENT_CONNECT,$context); if ($this->socket) { socket_set_timeout($this->socket, $this->timeout); $this->write('/login', false); $this->write('=name=' . $login, false); $this->write('=password=' . $password); $RESPONSE = $this->read(false); if (isset($RESPONSE[0])) { if ($RESPONSE[0] == '!done') { if (!isset($RESPONSE[1])) { // Login method post-v6.43 $this->connected = true; break; } else { // Login method pre-v6.43 $MATCHES = array(); if (preg_match_all('/[^=]+/i', $RESPONSE[1], $MATCHES)) { if ($MATCHES[0][0] == 'ret' && strlen($MATCHES[0][1]) == 32) { $this->write('/login', false); $this->write('=name=' . $login, false); $this->write('=response=00' . md5(chr(0) . $password . pack('H*', $MATCHES[0][1]))); $RESPONSE = $this->read(false); if (isset($RESPONSE[0]) && $RESPONSE[0] == '!done') { $this->connected = true; break; } } } } } } fclose($this->socket); } sleep($this->delay); } if ($this->connected) { $this->debug('Connected...'); } else { $this->debug('Error...'); } return $this->connected; } /** * Disconnect from RouterOS * * @return void */ public function disconnect() { // let's make sure this socket is still valid. it may have been closed by something else if( is_resource($this->socket) ) { fclose($this->socket); } $this->connected = false; $this->debug('Disconnected...'); } /** * Parse response from Router OS * * @param array $response Response data * * @return array Array with parsed data */ public function parseResponse($response) { if (is_array($response)) { $PARSED = array(); $CURRENT = null; $singlevalue = null; foreach ($response as $x) { if (in_array($x, array('!fatal','!re','!trap'))) { if ($x == '!re') { $CURRENT =& $PARSED[]; } else { $CURRENT =& $PARSED[$x][]; } } elseif ($x != '!done') { $MATCHES = array(); if (preg_match_all('/[^=]+/i', $x, $MATCHES)) { if ($MATCHES[0][0] == 'ret') { $singlevalue = $MATCHES[0][1]; } $CURRENT[$MATCHES[0][0]] = (isset($MATCHES[0][1]) ? $MATCHES[0][1] : ''); } } } if (empty($PARSED) && !is_null($singlevalue)) { $PARSED = $singlevalue; } return $PARSED; } else { return array(); } } /** * Parse response from Router OS * * @param array $response Response data * * @return array Array with parsed data */ public function parseResponse4Smarty($response) { if (is_array($response)) { $PARSED = array(); $CURRENT = null; $singlevalue = null; foreach ($response as $x) { if (in_array($x, array('!fatal','!re','!trap'))) { if ($x == '!re') { $CURRENT =& $PARSED[]; } else { $CURRENT =& $PARSED[$x][]; } } elseif ($x != '!done') { $MATCHES = array(); if (preg_match_all('/[^=]+/i', $x, $MATCHES)) { if ($MATCHES[0][0] == 'ret') { $singlevalue = $MATCHES[0][1]; } $CURRENT[$MATCHES[0][0]] = (isset($MATCHES[0][1]) ? $MATCHES[0][1] : ''); } } } foreach ($PARSED as $key => $value) { $PARSED[$key] = $this->arrayChangeKeyName($value); } return $PARSED; if (empty($PARSED) && !is_null($singlevalue)) { $PARSED = $singlevalue; } } else { return array(); } } /** * Change "-" and "/" from array key to "_" * * @param array $array Input array * * @return array Array with changed key names */ public function arrayChangeKeyName(&$array) { if (is_array($array)) { foreach ($array as $k => $v) { $tmp = str_replace("-", "_", $k); $tmp = str_replace("/", "_", $tmp); if ($tmp) { $array_new[$tmp] = $v; } else { $array_new[$k] = $v; } } return $array_new; } else { return $array; } } /** * Read data from Router OS * * @param boolean $parse Parse the data? default: true * * @return array Array with parsed or unparsed data */ public function read($parse = true) { $RESPONSE = array(); $receiveddone = false; while (true) { // Read the first byte of input which gives us some or all of the length // of the remaining reply. $BYTE = ord(fread($this->socket, 1)); $LENGTH = 0; // If the first bit is set then we need to remove the first four bits, shift left 8 // and then read another byte in. // We repeat this for the second and third bits. // If the fourth bit is set, we need to remove anything left in the first byte // and then read in yet another byte. if ($BYTE & 128) { if (($BYTE & 192) == 128) { $LENGTH = (($BYTE & 63) << 8) + ord(fread($this->socket, 1)); } else { if (($BYTE & 224) == 192) { $LENGTH = (($BYTE & 31) << 8) + ord(fread($this->socket, 1)); $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); } else { if (($BYTE & 240) == 224) { $LENGTH = (($BYTE & 15) << 8) + ord(fread($this->socket, 1)); $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); } else { $LENGTH = ord(fread($this->socket, 1)); $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); } } } } else { $LENGTH = $BYTE; } $_ = ""; // If we have got more characters to read, read them in. if ($LENGTH > 0) { $_ = ""; $retlen = 0; while ($retlen < $LENGTH) { $toread = $LENGTH - $retlen; $_ .= fread($this->socket, $toread); $retlen = strlen($_); } $RESPONSE[] = $_; $this->debug('>>> [' . $retlen . '/' . $LENGTH . '] bytes read.'); } // If we get a !done, make a note of it. if ($_ == "!done") { $receiveddone = true; } $STATUS = socket_get_status($this->socket); if ($LENGTH > 0) { $this->debug('>>> [' . $LENGTH . ', ' . $STATUS['unread_bytes'] . ']' . $_); } if ((!$this->connected && !$STATUS['unread_bytes']) || ($this->connected && !$STATUS['unread_bytes'] && $receiveddone)) { break; } } if ($parse) { $RESPONSE = $this->parseResponse($RESPONSE); } return $RESPONSE; } /** * Write (send) data to Router OS * * @param string $command A string with the command to send * @param mixed $param2 If we set an integer, the command will send this data as a "tag" * If we set it to boolean true, the funcion will send the comand and finish * If we set it to boolean false, the funcion will send the comand and wait for next command * Default: true * * @return boolean Return false if no command especified */ public function write($command, $param2 = true) { if ($command) { $data = explode("\n", $command); foreach ($data as $com) { $com = trim($com); fwrite($this->socket, $this->encodeLength(strlen($com)) . $com); $this->debug('<<< [' . strlen($com) . '] ' . $com); } if (gettype($param2) == 'integer') { fwrite($this->socket, $this->encodeLength(strlen('.tag=' . $param2)) . '.tag=' . $param2 . chr(0)); $this->debug('<<< [' . strlen('.tag=' . $param2) . '] .tag=' . $param2); } elseif (gettype($param2) == 'boolean') { fwrite($this->socket, ($param2 ? chr(0) : '')); } return true; } else { return false; } } /** * Write (send) data to Router OS * * @param string $com A string with the command to send * @param array $arr An array with arguments or queries * * @return array Array with parsed */ public function comm($com, $arr = array()) { $count = count($arr); $this->write($com, !$arr); $i = 0; if ($this->isIterable($arr)) { foreach ($arr as $k => $v) { switch ($k[0]) { case "?": $el = "$k=$v"; break; case "~": $el = "$k~$v"; break; default: $el = "=$k=$v"; break; } $last = ($i++ == $count - 1); $this->write($el, $last); } } return $this->read(); } /** * Standard destructor * * @return void */ public function __destruct() { $this->disconnect(); } } // encrypt decript function encrypt($string, $key=128) { $result = ''; for($i=0, $k= strlen($string); $i<$k; $i++) { $char = substr($string, $i, 1); $keychar = substr($key, ($i % strlen($key))-1, 1); $char = chr(ord($char)+ord($keychar)); $result .= $char; } return base64_encode($result); } function decrypt($string, $key=128) { $result = ''; $string = base64_decode($string); for($i=0, $k=strlen($string); $i< $k ; $i++) { $char = substr($string, $i, 1); $keychar = substr($key, ($i % strlen($key))-1, 1); $char = chr(ord($char)-ord($keychar)); $result .= $char; } return $result; } // Reformat date time MikroTik // by Laksamadi Guko function formatInterval($dtm){ $val_convert = $dtm; $new_format = str_replace("s", "", str_replace("m", "m ", str_replace("h", "h ", str_replace("d", "d ", str_replace("w", "w ", $val_convert))))); return $new_format; } function formatDTM($duration) { // Menyusun regex untuk mencocokkan durasi preg_match('/(?:(\d+)w)?(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/', $duration, $matches); // Jika ada nilai minggu, hari, jam, menit, detik $weeks = isset($matches[1]) ? (int)$matches[1] : 0; $days = isset($matches[2]) ? (int)$matches[2] : 0; $hours = isset($matches[3]) ? (int)$matches[3] : 0; $minutes = isset($matches[4]) ? (int)$matches[4] : 0; $seconds = isset($matches[5]) ? (int)$matches[5] : 0; // Format yang lebih mudah dibaca $formatted = []; if ($weeks) $formatted[] = "{$weeks} Mingg" . ($weeks > 1 ? 'u' : ''); if ($days) $formatted[] = "{$days} Har" . ($days > 1 ? 'i' : ''); if ($hours) $formatted[] = "{$hours} Ja" . ($hours > 1 ? 'm' : ''); if ($minutes) $formatted[] = "{$minutes} Meni" . ($minutes > 1 ? 't' : ''); if ($seconds) $formatted[] = "{$seconds} Deti" . ($seconds > 1 ? 'k' : ''); return implode(' ', $formatted); } function randN($length) { $chars = "23456789"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function randUC($length) { $chars = "ABCDEFGHJKLMNPRSTUVWXYZ"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function randLC($length) { $chars = "abcdefghijkmnprstuvwxyz"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function randULC($length) { $chars = "ABCDEFGHJKLMNPRSTUVWXYZabcdefghijkmnprstuvwxyz"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function randNLC($length) { $chars = "23456789abcdefghijkmnprstuvwxyz"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function randNUC($length) { $chars = "23456789ABCDEFGHJKLMNPRSTUVWXYZ"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function randNULC($length) { $chars = "23456789ABCDEFGHJKLMNPRSTUVWXYZabcdefghijkmnprstuvwxyz"; $charArray = str_split($chars); $charCount = strlen($chars); $result = ""; for($i=1;$i<=$length;$i++) { $randChar = rand(0,$charCount-1); $result .= $charArray[$randChar]; } return $result; } function formatBytes($bytes) { $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; $power = $bytes > 0 ? floor(log($bytes, 1024)) : 0; $formatted = number_format($bytes / pow(1024, $power), 2); return $formatted . ' ' . $units[$power]; } ?>