Advertisement
Guest User

Untitled

a guest
Aug 7th, 2016
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.64 KB | None | 0 0
  1. <?php
  2. /**
  3. * Název: MobilniPlatby.cz - PHP script pro zaslání RCON příkazů na MineCraft server po odeslání prémiové SMS
  4. * Autor: Mysteria - http://www.mysty.cz
  5. * Verze: 1.0.0-beta2
  6. * Poslední update: 27. 7. 2014
  7. * Více informací & download: http://forum.fakaheda.eu/viewtopic.php?f=85&t=20682#p134652
  8. */
  9.  
  10. $settings = (object)[ // Nastavení serverového RCONu
  11. 'ip' => '85.207.***.**',
  12. 'port' => '*****',
  13. 'password' => '****'
  14. ];
  15.  
  16. $messages = (object)[ // Nastavení chybových SMS zpráv
  17. 'sms_bad_price' => 'Litujeme, ale poslali jste SMS za :REALPRICE:Kc misto SMS za :PRICE:Kc.',
  18. 'sms_not_found' => 'Litujeme, ale poslali jste SMS, ktera nebyla automaticky rozpoznana. Kontaktujte prosim administratory.'
  19. ];
  20.  
  21. $levels = [ // Nastavení SMS levelů
  22. [
  23. 'price' => 50, // Cena SMSky
  24. 'text' => 'PM 30VIP :NICK:', // Text SMSky, :NICK: bude nahrazen skutečným nickem uvedeným v SMS, musí být unikátní v rámci všech platebních levelů
  25. 'answer' => 'Dekujeme za zakoupeni VIP za 50Kc.', // Odpověď na správně zaslanou SMS
  26. 'commands' => [ // RCON příkazy vykonané po úspěšném zpracování SMSky, :NICK: bude nahrazen skutečným nickem uvedeným v SMS
  27. 'pex user :NICK: group add VIP 2592000',
  28. 'bcast &f:NICK:&a si prave zakoupil VIP na mesic a tim prispel do projektu ****.',
  29. 'tell Server :NICK: Testovaci &2zprava do MSG!'
  30. ]
  31. ], [
  32. 'price' => 99,
  33. 'text' => 'PM 90VIP :NICK:',
  34. 'answer' => 'Dekujeme za zakoupeni VIP za 99Kc.',
  35. 'commands' => [
  36. 'pex user :NICK: group add VIP 7776000',
  37. 'bcast &f:NICK:&a si prave zakoupil VIP na 3 mesice a tim prispel do projektu ****.',
  38. 'tell Server :NICK: Testovaci zprava do MSG!'
  39. ]
  40. ]
  41. ];
  42.  
  43. /* Do not make any changes below this line if you don't know what are you doing! */
  44. $rcon = new Rcon($settings->ip, $settings->port, $settings->password, 3);
  45. if (!$rcon->connect()) exit('Cannot connect to server RCON. Please check your settings.');
  46. $url = (object)filter_input_array(INPUT_GET);
  47. try {
  48. if (isset($url->shortcode)) {
  49. $url->sms = trim($url->sms);
  50. if (mb_strlen($url->shortcode) === 7) {
  51. $realPrice = (int)substr($url->shortcode, -2, 2);
  52. foreach ($levels as $level) {
  53. $level = (object)$level;
  54. if ($level->price >= 100) continue;
  55. $realNick = explode(' ', $url->sms)[array_search(':NICK:', explode(' ', $level->text))];
  56. if (strtolower($url->sms) === strtolower(str_replace(':NICK:', $realNick, $level->text))) {
  57. if ($realPrice === $level->price) {
  58. foreach ($level->commands as $command) $rcon->send_command(str_replace(':NICK:', $realNick, $command));
  59. File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [SUCCESS] SMS zpráva s obsahem '$url->sms' s cenou {$realPrice}Kč byla úspěšně zpracována." . PHP_EOL);
  60. header('Content-type:text/plain');
  61. header('Content-length:' . mb_strlen($level->answer));
  62. exit($level->answer);
  63. } else {
  64. File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [!ERROR!] SMS zpráva s obsahem '$url->sms' s cenou {$realPrice}Kč nebyla zpracována, protože měla mít cenu {$level->price}Kč." . PHP_EOL);
  65. $answer = str_replace(':PRICE:', $level->price, str_replace(':REALPRICE:', $realPrice, $messages->sms_bad_price));
  66. header('Content-type:text/plain');
  67. header('Content-length:' . mb_strlen($answer));
  68. exit($answer);
  69. }
  70. }
  71. }
  72. File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [!ERROR!] SMS zpráva s obsahem '$url->sms' s cenou {$realPrice}Kč nebyla zpracována, protože nebyla rozpoznána." . PHP_EOL);
  73. header('Content-type:text/plain');
  74. header('Content-length:' . mb_strlen($messages->sms_not_found));
  75. exit($messages->sms_not_found);
  76. } else {
  77. foreach ($levels as $level) {
  78. $level = (object)$level;
  79. if ($level->price <= 99) continue;
  80. $realNick = explode(' ', $url->sms)[array_search(':NICK:', explode(' ', $level->text))];
  81. if (strtolower($url->sms) === strtolower(str_replace(':NICK:', $realNick, $level->text))) {
  82. $file = "./database/$url->id.txt";
  83. $commands = NULL;
  84. foreach ($level->commands as $command) $commands .= str_replace(':NICK:', $realNick, $command) . ';;;';
  85. File::write($file, $commands);
  86. $level->answer .= ";90333$level->price";
  87. File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [SUCCESS] SMS zpráva ID $url->id s obsahem '$url->sms' s cenou {$level->price}Kč byla úspěšně zpracována." . PHP_EOL);
  88. header('Content-type:text/plain');
  89. header('Content-length:' . mb_strlen($level->answer));
  90. exit($level->answer);
  91. }
  92. }
  93. File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [!ERROR!] SMS zpráva ID $url->id s obsahem '$url->sms' s cenou {$level->price}Kč nebyla zpracována, protože nebyla rozpoznána." . PHP_EOL);
  94. header('Content-type:text/plain');
  95. header('Content-length:' . mb_strlen($messages->sms_not_found));
  96. exit("$messages->sms_not_found;FREE90333199");
  97. }
  98. } elseif (isset($url->request)) {
  99. if ($url->status === 'DELIVERED') {
  100. $file = "./database/$url->request.txt";
  101. if (is_array($commands = explode(';;;', File::read($file)))) foreach ($commands as $command) $rcon->send_command($command);
  102. File::remove($file);
  103. File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [SUCCESS] Doručenka SMS zprávy ID $url->request byla úspěšně zpracována." . PHP_EOL);
  104. } else File::write('./mobilni-platby.log', date('d. m. Y H:i:s', time()) . " => [!ERROR!] Doručenka SMS zprávy ID $url->request nebyla zpracována, protože přišla se statusem $url->status ($url->message)." . PHP_EOL);
  105. header('HTTP/1.1 204 No Content');
  106. exit;
  107. }
  108. } catch (\FileException $e) { exit($e->getMessage()); }
  109. class File {
  110. public static function read($source, $mode = 'r') {
  111. if (file_exists($source)) {
  112. if ($file = fopen($source, $mode)) {
  113. if ($content = fread($file, filesize($source))) {
  114. if (fclose($file)) {
  115. return $content;
  116. } else throw new \FileException("Cannot close file $source.");
  117. } else throw new \FileException("Cannot read file $source.");
  118. } else throw new \FileException("Cannot open file $source.");
  119. } else throw new \FileException("Cannot find file $source.");
  120. }
  121.  
  122. public static function write($destination, $content, $mode = 'a') {
  123. if (!is_dir(dirname($destination))) if (!mkdir(dirname($destination), 0777, TRUE)) throw new \FileException("Cannot create path $destination.");
  124. if ($file = fopen($destination, $mode)) {
  125. if (fwrite($file, $content)) {
  126. if (fclose($file)) {
  127. return TRUE;
  128. } else throw new \FileException("Cannot close file $destination.");
  129. } else throw new \FileException("Cannot write file $destination.");
  130. } else throw new \FileException("Cannot find file $destination.");
  131. }
  132.  
  133. public static function remove($source) {
  134. if (file_exists($source)) {
  135. if (unlink($source)) {
  136. return TRUE;
  137. } else throw new \FileException("Cannot remove file $source.");
  138. } else throw new \FileException("Cannot find file $source.");
  139. }
  140. }
  141. class FileException extends \Exception { }
  142. class Rcon {
  143. private $host;
  144. private $port;
  145. private $password;
  146. private $timeout;
  147. private $socket;
  148. private $authorized;
  149. private $last_response;
  150.  
  151. const PACKET_AUTHORIZE = 5;
  152. const PACKET_COMMAND = 6;
  153. const SERVERDATA_AUTH = 3;
  154. const SERVERDATA_AUTH_RESPONSE = 2;
  155. const SERVERDATA_EXECCOMMAND = 2;
  156. const SERVERDATA_RESPONSE_VALUE = 0;
  157.  
  158. public function __construct($host, $port, $password, $timeout) {
  159. $this->host = $host;
  160. $this->port = $port;
  161. $this->password = $password;
  162. $this->timeout = $timeout;
  163. }
  164.  
  165. public function get_response() {
  166. return $this->last_response;
  167. }
  168.  
  169. public function connect() {
  170.  
  171. $this->socket = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
  172.  
  173. if (!$this->socket) {
  174. $this->last_response = $errstr;
  175. return false;
  176. }
  177.  
  178. //set timeout
  179. stream_set_timeout($this->socket, 3, 0);
  180.  
  181. //authorize
  182. $auth = $this->authorize();
  183.  
  184. if ($auth) {
  185. return true;
  186. }
  187.  
  188. return false;
  189. }
  190.  
  191. public function disconnect() {
  192. if ($this->socket) {
  193. fclose($this->socket);
  194. }
  195. }
  196.  
  197. public function is_connected() {
  198. return $this->authorized;
  199. }
  200.  
  201. public function send_command($command) {
  202. if (!$this->is_connected()) return false;
  203.  
  204. // send command packet.
  205. $this->write_packet(Rcon::PACKET_COMMAND, Rcon::SERVERDATA_EXECCOMMAND, $command);
  206.  
  207. // get response.
  208. $response_packet = $this->read_packet();
  209. if ($response_packet['id'] == Rcon::PACKET_COMMAND) {
  210. if ($response_packet['type'] == Rcon::SERVERDATA_RESPONSE_VALUE) {
  211. $this->last_response = $response_packet['body'];
  212. return $response_packet['body'];
  213. }
  214. }
  215.  
  216. return false;
  217. }
  218.  
  219. private function authorize() {
  220. $this->write_packet(Rcon::PACKET_AUTHORIZE, Rcon::SERVERDATA_AUTH, $this->password);
  221. $response_packet = $this->read_packet();
  222.  
  223. if ($response_packet['type'] == Rcon::SERVERDATA_AUTH_RESPONSE) {
  224. if ($response_packet['id'] == Rcon::PACKET_AUTHORIZE) {
  225. $this->authorized = true;
  226. return true;
  227. }
  228. }
  229.  
  230. $this->disconnect();
  231. return false;
  232. }
  233.  
  234. /**
  235. * Writes a packet to the socket stream..
  236. */
  237. private function write_packet($packet_id, $packet_type, $packet_body) {
  238. /*
  239. Size 32-bit little-endian Signed Integer Varies, see below.
  240. ID 32-bit little-endian Signed Integer Varies, see below.
  241. Type 32-bit little-endian Signed Integer Varies, see below.
  242. Body Null-terminated ASCII String Varies, see below.
  243. Empty String Null-terminated ASCII String 0x00
  244. */
  245.  
  246. //create packet
  247. $packet = pack("VV", $packet_id, $packet_type);
  248. $packet = $packet . $packet_body . "\x00";
  249. $packet = $packet . "\x00";
  250.  
  251. // get packet size.
  252. $packet_size = strlen($packet);
  253.  
  254. // attach size to packet.
  255. $packet = pack("V", $packet_size) . $packet;
  256.  
  257. // write packet.
  258. fwrite($this->socket, $packet, strlen($packet));
  259. }
  260.  
  261. private function read_packet() {
  262. //get packet size.
  263. $size_data = fread($this->socket, 4);
  264. $size_pack = unpack("V1size", $size_data);
  265. $size = $size_pack['size'];
  266.  
  267. // if size is > 4096, the response will be in multiple packets.
  268. // this needs to be address. get more info about multi-packet responses
  269. // from the RCON protocol specification at
  270. // https://developer.valvesoftware.com/wiki/Source_RCON_Protocol
  271. // currently, this script does not support multi-packet responses.
  272.  
  273. $packet_data = fread($this->socket, $size);
  274. $packet_pack = unpack("V1id/V1type/a*body", $packet_data);
  275.  
  276. return $packet_pack;
  277. }
  278. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement