mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-04 00:55:14 +00:00
First commit
This commit is contained in:
115
classes/MinecraftInterface.class.php
Normal file
115
classes/MinecraftInterface.class.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class MinecraftInterface{
|
||||
var $pstruct, $name, $server, $protocol;
|
||||
|
||||
function __construct($server, $protocol = CURRENT_PROTOCOL, $port = 25565, $listen = false){
|
||||
$this->server = new Socket($server, $port, (bool) $listen);
|
||||
$this->protocol = (int) $protocol;
|
||||
require("pstruct/RakNet.php");
|
||||
require("pstruct/packetName.php");
|
||||
$this->pstruct = $pstruct;
|
||||
$this->name = $packetName;
|
||||
}
|
||||
|
||||
public function close(){
|
||||
return $this->server->close();
|
||||
}
|
||||
|
||||
protected function getStruct($pid){
|
||||
if(isset($this->pstruct[$pid])){
|
||||
return $this->pstruct[$pid];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function writeDump($pid, $raw, $data, $origin = "client", $ip = "", $port = 0){
|
||||
if(LOG === true and DEBUG >= 2){
|
||||
$p = "[".microtime(true)."] [".($origin === "client" ? "CLIENT->SERVER":"SERVER->CLIENT")." ".$ip.":".$port."]: ".$this->name[$pid]." (0x".Utils::strTohex(chr($pid)).") [lenght ".strlen($raw)."]".PHP_EOL;
|
||||
$p .= hexdump($raw, false, false, true);
|
||||
if(is_array($data)){
|
||||
foreach($data as $i => $d){
|
||||
$p .= $i ." => ".(!is_array($d) ? $this->pstruct[$pid][$i]."(".(($this->pstruct[$pid][$i] === "magic" or substr($this->pstruct[$pid][$i], 0, 7) === "special") ? Utils::strToHex($d):$d).")":$this->pstruct[$pid][$i]."(***)").PHP_EOL;
|
||||
}
|
||||
}
|
||||
$p .= PHP_EOL;
|
||||
logg($p, "packets", false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function readPacket($port = false){
|
||||
if($this->server->connected === false){
|
||||
//return array("pid" => "ff", "data" => array(0 => 'Connection error'));
|
||||
}
|
||||
$data = $this->server->read();
|
||||
if($data[3] === false){
|
||||
return false;
|
||||
}
|
||||
$pid = $data[0]{0};
|
||||
$pid = ord($pid);
|
||||
$struct = $this->getStruct($pid);
|
||||
if($struct === false){
|
||||
$p = "[".microtime(true)."] [SERVER->CLIENT]: Error, bad packet id 0x".Utils::strToHex(chr($pid)).PHP_EOL;
|
||||
$p .= hexdump($data[0], false, false, true);
|
||||
$p .= PHP_EOL . "--------------- (1024 byte max extract) ----------" .PHP_EOL;
|
||||
logg($p, "packets", true, 3);
|
||||
|
||||
$this->buffer = "";
|
||||
//$this->server->recieve("\xff".Utils::writeString('Bad packet id '.$pid.''));
|
||||
//$this->writePacket("ff", array(0 => 'Bad packet id '.$pid.''));
|
||||
//return array("pid" => "ff", "data" => array(0 => 'Bad packet id '.$pid.''));
|
||||
return false;
|
||||
}
|
||||
|
||||
$packet = new Packet($pid, $struct, $data[0]);
|
||||
$packet->protocol = $this->protocol;
|
||||
$packet->parse();
|
||||
$this->writeDump($pid, $data[0], $packet->data, "server", $data[1], $data[2]);
|
||||
return array("pid" => $pid, "data" => $packet->data, "raw" => $data[0], "ip" => $data[1], "port" => $data[2]);
|
||||
}
|
||||
|
||||
public function writePacket($pid, $data = array(), $raw = false, $dest = false, $port = false){
|
||||
$struct = $this->getStruct($pid);
|
||||
if($raw === false){
|
||||
$packet = new Packet($pid, $struct);
|
||||
$packet->protocol = $this->protocol;
|
||||
$packet->data = $data;
|
||||
$packet->create();
|
||||
$write = $this->server->write($packet->raw, $dest, $port);
|
||||
$this->writeDump($pid, $packet->raw, $data, "client");
|
||||
}else{
|
||||
$write = $this->server->write($data, $dest, $port);
|
||||
$this->writeDump($pid, $data, false, "client", $dest, $port);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
192
classes/Packet.class.php
Normal file
192
classes/Packet.class.php
Normal file
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class Packet{
|
||||
private $struct, $sock;
|
||||
protected $pid, $packet;
|
||||
public $data, $raw, $protocol;
|
||||
|
||||
function __construct($pid, $struct, $data = ""){
|
||||
$this->pid = $pid;
|
||||
$this->offset = 1;
|
||||
$this->raw = $data;
|
||||
$this->data = array();
|
||||
if($pid !== false){
|
||||
$this->addRaw(chr($pid));
|
||||
}
|
||||
$this->struct = $struct;
|
||||
$this->sock = $sock;
|
||||
}
|
||||
|
||||
public function create($raw = false){
|
||||
foreach($this->struct as $field => $type){
|
||||
if(!isset($this->data[$field])){
|
||||
$this->data[$field] = "";
|
||||
}
|
||||
if($raw === true){
|
||||
$this->addRaw($this->data[$field]);
|
||||
continue;
|
||||
}
|
||||
if(is_int($type)){
|
||||
$this->addRaw($this->data[$field]);
|
||||
continue;
|
||||
}
|
||||
switch($type){
|
||||
case "special1":
|
||||
switch($this->pid){
|
||||
case 0x05:
|
||||
$this->addRaw($this->data[$field]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "magic":
|
||||
$this->addRaw(MAGIC);
|
||||
break;
|
||||
case "float":
|
||||
$this->addRaw(Utils::writeFloat($this->data[$field]));
|
||||
break;
|
||||
case "int":
|
||||
$this->addRaw(Utils::writeInt($this->data[$field]));
|
||||
break;
|
||||
case "double":
|
||||
$this->addRaw(Utils::writeDouble($this->data[$field]));
|
||||
break;
|
||||
case "long":
|
||||
$this->addRaw(Utils::writeLong($this->data[$field]));
|
||||
break;
|
||||
case "bool":
|
||||
case "boolean":
|
||||
$this->addRaw(Utils::writeBool($this->data[$field]));
|
||||
break;
|
||||
case "ubyte":
|
||||
case "byte":
|
||||
$this->addRaw(Utils::writeByte($this->data[$field]));
|
||||
break;
|
||||
case "short":
|
||||
$this->addRaw(Utils::writeShort($this->data[$field]));
|
||||
break;
|
||||
case "byteArray":
|
||||
$this->addRaw($this->data[$field]);
|
||||
break;
|
||||
case "string":
|
||||
$this->addRaw(Utils::writeShort(strlen($this->data[$field])));
|
||||
$this->addRaw($this->data[$field]);
|
||||
break;
|
||||
case "slotData":
|
||||
$this->addRaw(Utils::writeShort($this->data[$field][0]));
|
||||
if($this->data[$field][0]!=-1){
|
||||
$this->addRaw(Utils::writeByte($this->data[$field][1]));
|
||||
$this->addRaw(Utils::writeShort($this->data[$field][2]));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->addRaw(Utils::writeByte($this->data[$field]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function get($len = true){
|
||||
if($len === true){
|
||||
$data = substr($this->raw, $this->offset);
|
||||
$this->offset = strlen($this->raw);
|
||||
return $data;
|
||||
}
|
||||
$data = substr($this->raw, $this->offset, $len);
|
||||
$this->offset += $len;
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function addRaw($str){
|
||||
$this->raw .= $str;
|
||||
return $str;
|
||||
}
|
||||
|
||||
public function parse(){
|
||||
$continue = true;
|
||||
foreach($this->struct as $field => $type){
|
||||
if(is_int($type)){
|
||||
$this->data[] = $this->get($type);
|
||||
continue;
|
||||
}
|
||||
switch($type){
|
||||
case "special1":
|
||||
switch($this->pid){
|
||||
case 0x05:
|
||||
$this->data[] = $this->get(true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "magic":
|
||||
$this->data[] = $this->get(16);
|
||||
break;
|
||||
case "int":
|
||||
$this->data[] = Utils::readInt($this->get(4));
|
||||
if($field === 5 and $this->pid === "17" and $this->data[$field] === 0){
|
||||
$continue = false;
|
||||
}
|
||||
break;
|
||||
case "string":
|
||||
$this->data[] = $this->get(Utils::readShort($this->get(2)) << 1);
|
||||
break;
|
||||
case "long":
|
||||
$this->data[] = Utils::readLong($this->get(8));
|
||||
break;
|
||||
case "byte":
|
||||
$this->data[] = Utils::readByte($this->get(1));
|
||||
break;
|
||||
case "ubyte":
|
||||
$this->data[] = ord($this->get(1));
|
||||
break;
|
||||
case "float":
|
||||
$this->data[] = Utils::readFloat($this->get(4));
|
||||
break;
|
||||
case "double":
|
||||
$this->data[] = Utils::readDouble($this->get(8));
|
||||
break;
|
||||
case "ushort":
|
||||
$this->data[] = Utils::readShort($this->get(2), false);
|
||||
break;
|
||||
case "short":
|
||||
$this->data[] = Utils::readShort($this->get(2));
|
||||
break;
|
||||
case "bool":
|
||||
case "boolean":
|
||||
$this->data[] = Utils::readBool($this->get(1));
|
||||
break;
|
||||
}
|
||||
if($continue === false){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
33
classes/PocketMinecraftClient.class.php
Normal file
33
classes/PocketMinecraftClient.class.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class PocketMinecraftClient{
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
153
classes/PocketMinecraftServer.class.php
Normal file
153
classes/PocketMinecraftServer.class.php
Normal file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class PocketMinecraftServer{
|
||||
protected $interface, $protocol, $entities, $player, $cnt, $events, $username, $version;
|
||||
function __construct($username, $protocol = CURRENT_PROTOCOL, $version = CURRENT_VERSION){
|
||||
//$this->player = new Player($username);
|
||||
$this->version = (int) $version;
|
||||
$this->username = $username;
|
||||
$this->cnt = 1;
|
||||
$this->serverID = Utils::readDouble(substr(Utils::generateKey(), 0, 8));
|
||||
$this->events = array("disabled" => array());
|
||||
$this->protocol = (int) $protocol;
|
||||
$this->interface = new MinecraftInterface("255.255.255.255", $this->protocol, 19132, true);
|
||||
console("[INFO] Creating Minecraft Server");
|
||||
console("[INFO] Username: ".$this->username);
|
||||
console("[INFO] Protocol: ".$this->protocol);
|
||||
$this->stop = false;
|
||||
}
|
||||
|
||||
public function start(){
|
||||
$this->event("onReceivedPacket", "packetHandler", true);
|
||||
$this->process();
|
||||
}
|
||||
|
||||
public function packetHandler($packet, $event){
|
||||
$data =& $packet["data"];
|
||||
switch($packet["pid"]){
|
||||
case 0x02:
|
||||
$this->send(0x1c, array(
|
||||
$data[0],
|
||||
$this->serverID,
|
||||
MAGIC,
|
||||
"MCCPP;Demo;". $this->username,
|
||||
), false, $packet["ip"], $packet["port"]);
|
||||
break;
|
||||
case 0x05:
|
||||
$version = $data[1];
|
||||
$size = strlen($data[2]);
|
||||
console("[DEBUG] ".$packet["ip"].":".$packet["port"]." v".$version." handshake (".$size.")", true, true, 2);
|
||||
$this->send(0x06, array(
|
||||
MAGIC,
|
||||
$this->serverID,
|
||||
$this->version,
|
||||
$size,
|
||||
), false, $packet["ip"], $packet["port"]);
|
||||
break;
|
||||
case 0x07:
|
||||
$bytes = $data[1];
|
||||
$port = $data[2];
|
||||
$size = $data[3];
|
||||
$x = $data[4];
|
||||
$sess = $data[5];
|
||||
//console("[DEBUG] ".$packet["ip"].":".$packet["port"]." v".$version." response (".$size.")", true, true, 2);
|
||||
$sess2 = Utils::readInt(substr(Utils::generateKey(), 0, 4));
|
||||
$this->send(0x08, array(
|
||||
MAGIC,
|
||||
$x,
|
||||
$sess2,
|
||||
$bytes,
|
||||
$packet["port"],
|
||||
$size,
|
||||
0x00
|
||||
), false, $packet["ip"], $packet["port"]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function send($pid, $data = array(), $raw = false, $dest = false, $port = false){
|
||||
$this->trigger($pid, $data);
|
||||
$this->trigger("onSentPacket", $data);
|
||||
$this->interface->writePacket($pid, $data, $raw, $dest, $port);
|
||||
}
|
||||
|
||||
public function process(){
|
||||
while($this->stop === false){
|
||||
$packet = $this->interface->readPacket();
|
||||
if($packet !== false){
|
||||
$this->trigger("onReceivedPacket", $packet);
|
||||
$this->trigger($packet["pid"], $packet);
|
||||
}
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
public function trigger($event, $data = ""){
|
||||
console("[INTERNAL] Event ". $event, true, true, 3);
|
||||
if(isset($this->events[$event]) and !isset($this->events["disabled"][$event])){
|
||||
foreach($this->events[$event] as $eid => $ev){
|
||||
if(isset($ev[1]) and ($ev[1] === true or is_object($ev[1]))){
|
||||
$this->responses[$eid] = call_user_func(array(($ev[1] === true ? $this:$ev[1]), $ev[0]), $data, $event, $this);
|
||||
}else{
|
||||
$this->responses[$eid] = call_user_func($ev[0], $data, $event, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public function toggleEvent($event){
|
||||
if(isset($this->events["disabled"][$event])){
|
||||
unset($this->events["disabled"][$event]);
|
||||
console("[INTERNAL] Enabled event ".$event, true, true, 3);
|
||||
}else{
|
||||
$this->events["disabled"][$event] = false;
|
||||
console("[INTERNAL] Disabled event ".$event, true, true, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public function event($event, $func, $in = false){
|
||||
++$this->cnt;
|
||||
if(!isset($this->events[$event])){
|
||||
$this->events[$event] = array();
|
||||
}
|
||||
$this->events[$event][$this->cnt] = array($func, $in);
|
||||
console("[INTERNAL] Attached to event ".$event, true, true, 3);
|
||||
return $this->cnt;
|
||||
}
|
||||
|
||||
public function deleteEvent($event, $id = -1){
|
||||
if($id === -1){
|
||||
unset($this->events[$event]);
|
||||
}else{
|
||||
unset($this->events[$event][$id]);
|
||||
if(isset($this->events[$event]) and count($this->events[$event]) === 0){
|
||||
unset($this->events[$event]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
33
classes/Session.class.php
Normal file
33
classes/Session.class.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class Session{
|
||||
|
||||
|
||||
|
||||
}
|
98
classes/Socket.class.php
Normal file
98
classes/Socket.class.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class Socket{
|
||||
private $encrypt;
|
||||
var $buffer, $connected, $errors, $sock, $server;
|
||||
|
||||
function __construct($server, $port, $listen = false, $socket = false){
|
||||
$this->errors = array_fill(88,(125 - 88) + 1, true);
|
||||
$this->server = $server;
|
||||
$this->port = $port;
|
||||
if($socket !== false){
|
||||
$this->sock = $socket;
|
||||
$this->connected = true;
|
||||
$this->buffer = array();
|
||||
$this->unblock();
|
||||
}else{
|
||||
$this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||
socket_set_option($this->sock, SOL_SOCKET, SO_BROADCAST, 1);
|
||||
if($listen !== true){
|
||||
$this->connected = true;
|
||||
$this->buffer = array();
|
||||
$this->unblock();
|
||||
}else{
|
||||
socket_bind($this->sock, "0.0.0.0", $port);
|
||||
$this->unblock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function listenSocket(){
|
||||
$sock = @socket_accept($this->sock);
|
||||
if($sock !== false){
|
||||
$sock = new Socket(false, false, false, $sock);
|
||||
$sock->unblock();
|
||||
return $sock;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function close($error = 125){
|
||||
$this->connected = false;
|
||||
if($error === false){
|
||||
console("[ERROR] [Socket] Socket closed, Error: End of Stream");
|
||||
}else{
|
||||
console("[ERROR] [Socket] Socket closed, Error $error: ".socket_strerror($error));
|
||||
}
|
||||
return @socket_close($this->sock);
|
||||
}
|
||||
|
||||
public function block(){
|
||||
socket_set_block($this->sock);
|
||||
}
|
||||
|
||||
public function unblock(){
|
||||
socket_set_nonblock($this->sock);
|
||||
}
|
||||
|
||||
public function read(){
|
||||
$source = false;
|
||||
$port = 1;
|
||||
$len = @socket_recvfrom($this->sock, $buf, 65536, 0, $source, $port);
|
||||
return array($buf, $source, $port, $len);
|
||||
}
|
||||
|
||||
public function write($data, $dest = false, $port = false){
|
||||
return @socket_sendto($this->sock, $data, strlen($data), 0, ($dest === false ? $this->server:$dest), ($port === false ? $this->port:$port));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
314
classes/Utils.class.php
Normal file
314
classes/Utils.class.php
Normal file
@ -0,0 +1,314 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
-
|
||||
/ \
|
||||
/ \
|
||||
/ POCKET \
|
||||
/ MINECRAFT PHP \
|
||||
|\ @shoghicp /|
|
||||
|. \ / .|
|
||||
| .. \ / .. |
|
||||
| .. | .. |
|
||||
| .. | .. |
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
\ | /
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
if(!defined("GMPEXT")){
|
||||
@define("GMPEXT", false);
|
||||
}
|
||||
if(!defined("HEX2BIN")){
|
||||
@define("HEX2BIN", false);
|
||||
}
|
||||
|
||||
define("BIG_ENDIAN", 0x00);
|
||||
define("LITTLE_ENDIAN", 0x01);
|
||||
define("ENDIANNESS", (pack('d', 1) === "\77\360\0\0\0\0\0\0" ? BIG_ENDIAN:LITTLE_ENDIAN));
|
||||
console("[DEBUG] Endianness: ".(ENDIANNESS === LITTLE_ENDIAN ? "Little Endian":"Big Endian"), true, true, 2);
|
||||
|
||||
class Utils{
|
||||
public static $hexToBin = array(
|
||||
"0" => "0000",
|
||||
"1" => "0001",
|
||||
"2" => "0010",
|
||||
"3" => "0011",
|
||||
"4" => "0100",
|
||||
"5" => "0101",
|
||||
"6" => "0110",
|
||||
"7" => "0111",
|
||||
"8" => "1000",
|
||||
"9" => "1001",
|
||||
"a" => "1010",
|
||||
"b" => "1011",
|
||||
"c" => "1100",
|
||||
"d" => "1101",
|
||||
"e" => "1110",
|
||||
"f" => "1111",
|
||||
);
|
||||
|
||||
public static function round($number){
|
||||
return round($number, 0, PHP_ROUND_HALF_DOWN);
|
||||
}
|
||||
|
||||
public static function generateKey($startEntropy = ""){
|
||||
//not much entropy, but works ^^
|
||||
$entropy = array(
|
||||
implode(stat(__FILE__)),
|
||||
lcg_value(),
|
||||
print_r($_SERVER, true),
|
||||
implode(mt_rand(0,394),get_defined_constants()),
|
||||
get_current_user(),
|
||||
print_r(ini_get_all(),true),
|
||||
(string) memory_get_usage(),
|
||||
php_uname(),
|
||||
phpversion(),
|
||||
zend_version(),
|
||||
getmypid(),
|
||||
mt_rand(),
|
||||
rand(),
|
||||
implode(get_loaded_extensions()),
|
||||
sys_get_temp_dir(),
|
||||
disk_free_space("."),
|
||||
disk_total_space("."),
|
||||
(function_exists("openssl_random_pseudo_bytes") and version_compare(PHP_VERSION, "5.3.4", ">=")) ? openssl_random_pseudo_bytes(16):microtime(true),
|
||||
function_exists("mcrypt_create_iv") ? mcrypt_create_iv(16, MCRYPT_DEV_URANDOM):microtime(true),
|
||||
uniqid(microtime(true),true),
|
||||
file_exists("/dev/urandom") ? fread(fopen("/dev/urandom", "rb"),16):microtime(true),
|
||||
);
|
||||
shuffle($entropy);
|
||||
$value = Utils::hexToStr(md5((string) $startEntropy));
|
||||
unset($startEntropy);
|
||||
foreach($entropy as $c){
|
||||
$c = (string) $c;
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$value ^= md5($i . $c . microtime(true), true);
|
||||
$value ^= substr(sha1($i . $c . microtime(true), true),$i,16);
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function sha1($input){
|
||||
$binary = Utils::hexToBin(sha1($input));
|
||||
$negative = false;
|
||||
$len = strlen($binary);
|
||||
if($binary{0} === "1"){
|
||||
$negative = true;
|
||||
for($i = 0; $i < $len; ++$i){
|
||||
$binary{$i} = $binary{$i} === "1" ? "0":"1";
|
||||
}
|
||||
for($i = $len - 1; $i >= 0; --$i){
|
||||
if($binary{$i} === "1"){
|
||||
$binary{$i} = "0";
|
||||
}else{
|
||||
$binary{$i} = "1";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$hash = Utils::binToHex($binary);
|
||||
$len = strlen($hash);
|
||||
for($i = 0; $i < $len; ++$i){
|
||||
if($hash{$i} === "0"){
|
||||
$hash{$i} = "x";
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ($negative === true ? "-":"").str_replace("x", "", $hash);
|
||||
}
|
||||
|
||||
public static function microtime(){
|
||||
return microtime(true);
|
||||
}
|
||||
|
||||
public static function curl_get($page){
|
||||
$ch = curl_init($page);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Minecraft PHP Client 2'));
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
$ret = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function curl_post($page, $args, $timeout = 10){
|
||||
$ch = curl_init($page);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('User-Agent: Minecraft PHP Client 2'));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout);
|
||||
$ret = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function strToBin($str){
|
||||
return Utils::hexToBin(Utils::strToHex($str));
|
||||
}
|
||||
|
||||
public static function hexToBin($hex){
|
||||
$bin = "";
|
||||
$len = strlen($hex);
|
||||
for($i = 0; $i < $len; ++$i){
|
||||
$bin .= Utils::$hexToBin[$hex{$i}];
|
||||
}
|
||||
return $bin;
|
||||
}
|
||||
|
||||
public static function binToStr($bin){
|
||||
$len = strlen($bin);
|
||||
if(($len % 8) != 0){
|
||||
$bin = substr($bin, 0, -($len % 8));
|
||||
}
|
||||
$str = "";
|
||||
for($i = 0; $i < $len; $i += 8){
|
||||
$str .= chr(bindec(substr($bin, $i, 8)));
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
public static function binToHex($bin){
|
||||
$len = strlen($bin);
|
||||
if(($len % 8) != 0){
|
||||
$bin = substr($bin, 0, -($len % 8));
|
||||
}
|
||||
$hex = "";
|
||||
for($i = 0; $i < $len; $i += 4){
|
||||
$hex .= dechex(bindec(substr($bin, $i, 4)));
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
|
||||
public static function strToHex($str){
|
||||
return bin2hex($str);
|
||||
}
|
||||
|
||||
public static function hexToStr($hex){
|
||||
if(HEX2BIN === true){
|
||||
return hex2bin($hex);
|
||||
}
|
||||
return pack("H*" , $hex);
|
||||
}
|
||||
|
||||
public static function readString($str){
|
||||
return preg_replace('/\x00(.)/s', '$1', $str);
|
||||
}
|
||||
|
||||
public static function writeString($str){
|
||||
return preg_replace('/(.)/s', "\x00$1", $str);
|
||||
}
|
||||
|
||||
public static function readBool($b){
|
||||
return Utils::readByte($b, false) === 0 ? false:true;
|
||||
}
|
||||
|
||||
public static function writeBool($b){
|
||||
return Utils::writeByte($b === true ? 1:0);
|
||||
}
|
||||
|
||||
public static function readByte($c, $signed = true){
|
||||
$b = ord($c{0});
|
||||
if($signed === true and ($b & 0x80) === 0x80){ //calculate Two's complement
|
||||
$b = -0x80 + ($b & 0x7f);
|
||||
}
|
||||
return $b;
|
||||
}
|
||||
|
||||
public static function writeByte($c){
|
||||
if($c > 0xff){
|
||||
return false;
|
||||
}
|
||||
if($c < 0 and $c >= -0x80){
|
||||
$c = 0xff + $c + 1;
|
||||
}
|
||||
return chr($c);
|
||||
}
|
||||
|
||||
public static function readShort($str, $signed = true){
|
||||
list(,$unpacked) = unpack("n", $str);
|
||||
if($unpacked > 0x7fff and $signed === true){
|
||||
$unpacked -= 0x10000; // Convert unsigned short to signed short
|
||||
}
|
||||
return $unpacked;
|
||||
}
|
||||
|
||||
public static function writeShort($value){
|
||||
if($value < 0){
|
||||
$value += 0x10000;
|
||||
}
|
||||
return pack("n", $value);
|
||||
}
|
||||
|
||||
public static function readInt($str){
|
||||
list(,$unpacked) = unpack("N", $str);
|
||||
return (int) $unpacked;
|
||||
}
|
||||
|
||||
public static function writeInt($value){
|
||||
if($value < 0){
|
||||
$value += 0x100000000;
|
||||
}
|
||||
return pack("N", $value);
|
||||
}
|
||||
|
||||
public static function readFloat($str){
|
||||
list(,$value) = ENDIANNESS === BIG_ENDIAN?unpack('f', $str):unpack('f', strrev($str));
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function writeFloat($value){
|
||||
return ENDIANNESS === BIG_ENDIAN?pack('f', $value):strrev(pack('f', $value));
|
||||
}
|
||||
|
||||
public static function readDouble($str){
|
||||
list(,$value) = ENDIANNESS === BIG_ENDIAN?unpack('d', $str):unpack('d', strrev($str));
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function writeDouble($value){
|
||||
return ENDIANNESS === BIG_ENDIAN?pack('d', $value):strrev(pack('d', $value));
|
||||
}
|
||||
|
||||
public static function readLong($str){
|
||||
list(,$firstHalf,$secondHalf) = unpack("N*", $str);
|
||||
if(GMPEXT === true){
|
||||
$value = gmp_add($secondHalf, gmp_mul($firstHalf, "0x100000000"));
|
||||
if(gmp_cmp($value, "0x8000000000000000") >= 0){
|
||||
$value = gmp_sub($value, "0x10000000000000000");
|
||||
}
|
||||
return gmp_strval($value);
|
||||
}else{
|
||||
$value = bcadd($secondHalf, bcmul($firstHalf, "4294967296"));
|
||||
if(bccomp($value, "9223372036854775808") >= 0){
|
||||
$value = bcsub($value, "18446744073709551616");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
public static function writeLong($value){
|
||||
return ENDIANNESS === BIG_ENDIAN?pack('d', $value):strrev(pack('d', $value));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user