Advertisement
Guest User

Untitled

a guest
Aug 16th, 2016
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.67 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4. * This file is part of devMX TeamSpeak3 Webviewer.
  5. * Copyright (C) 2011 - 2012 Max Rath and Maximilian Narr
  6. *
  7. * devMX TeamSpeak3 Webviewer is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * TeamSpeak3 Webviewer is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with devMX TeamSpeak3 Webviewer. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. class TSQuery
  21. {
  22.  
  23. private $connection;
  24. protected $sock_error;
  25. protected $sock_error_string;
  26. protected $loggedin = false;
  27. protected $actual_vserver;
  28. private $ip;
  29. private $query_port;
  30. private $timeout;
  31. private $ftid;
  32. private $ftconn;
  33. private $cmds;
  34. private $cmd_sent;
  35.  
  36. /**
  37. The consructor opens a new Connection to the host and logs in with name and password
  38. @throws Exception throws if connection or login failed.
  39. @param string $host: the hostname or the ip-adress e.g. "localhost" or "127.0.0.1"
  40. @param int $port: the server query port e.g. 10011 (standart query port)
  41. */
  42. function __construct($host, $port)
  43. {
  44. $this->ip = gethostbyname($host);
  45. $this->query_port = $port;
  46. $this->timeout = 5;
  47. $this->actual_vserver = NULL;
  48.  
  49. $this->open_new_connection();
  50. $this->ftconn = NULL;
  51. $this->caching = false;
  52. $this->standard_cachetime = 5;
  53.  
  54. if ($this->connection == NULL || $this->connection == false)
  55. {
  56. if (false)
  57. {
  58. throw new QueryNoResponseException(sprintf("Establishing a connection on the server at %s:%s failed.", (string) $this->ip, (string) $this->query_port));
  59. }
  60. else
  61. {
  62. throw new QueryNotAvailableException(sprintf("The server at %s:%s is currently offline", (string) $this->ip, (string) $this->query_port));
  63. }
  64. }
  65.  
  66. // Read the TS3 sequence
  67. fread($this->connection, 6);
  68. $this->ftid = 0;
  69. $this->cmds = array();
  70. }
  71. /**
  72. Wrapper for the Querycommand use with port=$port i had to choose another name
  73. so the function is called use_vserver
  74. @param integer $port: is a valid port of a virtual server
  75. @return array|boolean parsed response of the query if port is an integer, if not an integer: false
  76. */
  77. public function use_by_port($port)
  78. {
  79. if (is_numeric($port))
  80. {
  81.  
  82. $resp = $this->send_cmd("use port=" . $port);
  83. if ($resp['error']['id'] === 0)
  84. {
  85. $this->cachepath .= $port . "/";
  86. }
  87. return $resp;
  88. }
  89. return false;
  90. }
  91.  
  92. /**
  93. * Selects a virtual server by its id
  94. * @param int $id valid id of a virtual server
  95. * @return array|boolean Array with parsed response, if not numeric false.
  96. */
  97. public function use_by_id($id)
  98. {
  99. if (is_numeric($id))
  100. {
  101. return $this->send_cmd("use sid=" . $id);
  102. }
  103. return false;
  104. }
  105.  
  106. /**
  107. * Sends the logout-command to the query
  108. * @return array parsed response
  109. */
  110. public function logout()
  111. {
  112. return $this->send_cmd("logout");
  113. }
  114.  
  115. /**
  116. * Sends the quit-command to the query
  117. * @return array parsed response
  118. */
  119. public function quit()
  120. {
  121. return $this->send_cmd("quit");
  122. }
  123.  
  124. /**
  125. * Sends a command that logins to the serverquery
  126. * @param string $username valid server query username
  127. * @param string $password
  128. * @return array parsed command
  129. */
  130. public function login($username, $password)
  131. {
  132.  
  133. $username = $this->ts3query_escape($username);
  134. $password = $this->ts3query_escape($password);
  135. return $this->send_cmd("login client_login_name=" . $username . " client_login_password=" . $password);
  136. }
  137.  
  138. /**
  139. * Sends the serverinfo-command to the server
  140. * @param bool $caching If command should be cached
  141. * @return boolean|array returns parsed response as an array, if command failes, false
  142. */
  143. public function serverinfo()
  144. {
  145. $ret = $this->send_cmd("serverinfo");
  146. if ($ret == false) return false;
  147.  
  148. $ret['return'] = $this->ts3_to_hash($ret['return']);
  149. return $ret;
  150. }
  151.  
  152. /**
  153. * Downloads the file specified in $path from the server query
  154. * @param string $path path to the file
  155. * @param int $cid channel id
  156. * @param string $cpw channel password
  157. * @param type $seek
  158. * @return boolean|mixed returns false on failure else the downloaded file
  159. */
  160. public function download($path, $cid, $cpw = "", $seek = 0)
  161. {
  162.  
  163. $this->ftid++;
  164. $cmd = "ftinitdownload clientftfid=$this->ftid name=" . $this->ts3query_escape($path) . " cid=" . intval($cid) . " cpw=" . $this->ts3query_escape($cpw) . " seekpos=" . intval($seek);
  165. $ret = $this->send_cmd($cmd);
  166. if ($ret['error']['id'] != 0) return false;
  167. $ret = $this->ts3_to_hash($ret['return']);
  168. $key = $this->ts3query_unescape($ret['ftkey']);
  169. $size = $ret['size'];
  170.  
  171. if ($this->ftconn == NULL || $this->ftconn == false) $this->ftconn = fsockopen($this->ip, $ret['port']);
  172. if ($this->ftconn == false) return false;
  173.  
  174. fputs($this->ftconn, $key);
  175. $downloaded = 0;
  176. $download = "";
  177. while ($downloaded < $size - $seek)
  178. {
  179. $akt = fgets($this->ftconn, 8096);
  180. $downloaded += strlen($akt);
  181. $download .= $akt;
  182. }
  183. return $download;
  184. }
  185.  
  186. /**
  187. * Sends the channellist-command to the query
  188. * @param string $options options
  189. * @param bool $caching If command should be cached
  190. * @return boolean|array Returns parsed response, on failure false
  191. */
  192. public function channellist($options = "")
  193. {
  194. if ($this->are_options($options))
  195. {
  196. $ret = $this->send_cmd("channellist " . $options);
  197. if ($ret == false) return false;
  198. if ($ret['error']['id'] == 0)
  199. {
  200. $ret['return'] = $this->ts3_to_hash(explode("|", $ret['return']));
  201. return $ret;
  202. }
  203. return false;
  204. }
  205. return false;
  206. }
  207.  
  208. /**
  209. * Sends the clientlist-command to the query
  210. * @param string $options options
  211. * @param bool $caching If command should be cached
  212. * @return boolean|array Returns parsed command, on failure false
  213. */
  214. public function clientlist($options = "")
  215. {
  216. if ($this->are_options($options))
  217. {
  218. $ret = $this->send_cmd("clientlist " . $options);
  219. if ($ret == false) return false;
  220. if ($ret['error']['id'] == 0)
  221. {
  222. $ret['return'] = $this->ts3_to_hash(explode("|", $ret['return']));
  223. return $ret;
  224. }
  225. return false;
  226. }
  227. }
  228.  
  229. /**
  230. * Sends the servergrouplist-command to the query
  231. * @param bool $caching If command should be cached
  232. * @return array Returns parsed command
  233. */
  234. public function servergrouplist()
  235. {
  236. $ret = $this->send_cmd("servergrouplist");
  237. $ret['return'] = $this->ts3_to_hash(explode("|", $ret['return']));
  238. return $ret;
  239. }
  240.  
  241. /**
  242. * Sends the channelgrouplist-command to the query
  243. * @param bool $caching If command should be cached
  244. * @return array Returns parsed command
  245. */
  246. public function channelgrouplist()
  247. {
  248. $ret = $this->send_cmd("channelgrouplist");
  249. $ret['return'] = $this->ts3_to_hash(explode("|", $ret['return']));
  250. return $ret;
  251. }
  252.  
  253. /**
  254. * Sends the clientinfo-command to the query
  255. * @param int $clid clientid
  256. * @param bool $caching If command should be cached
  257. * @return array parsed response
  258. */
  259. public function clientinfo($clid)
  260. {
  261.  
  262. $ret = $this->send_cmd("clientinfo clid=" . $clid);
  263. $ret['return'] = $this->ts3_to_hash($ret['return']);
  264. return $ret;
  265. }
  266.  
  267. /**
  268. This function parses a response given by the query the
  269. @param string $response: a response of a TS3 Query (example response: "helpfilestuff error id=0 msg=nothing\susefull"
  270. @return array splitTED into ['return'] (in this example "helpfilestuff") ['error']['id'] (here zero) and ['error']['msg']
  271. (here "nothing usefull") Note that ['error']['msg'] is escaped by @see ts3_response_escape()
  272. */
  273. protected function parse_ts3_response($response)
  274. {
  275. $result = preg_match("#.*error id=([[:digit:]]{1,4}) msg=(.*)$#Ds", $response, $buff);
  276. if ($result == 0)
  277. {
  278. $ret['return'] = $response;
  279. $ret['error'] = false;
  280. }
  281. else
  282. {
  283. $ret['return'] = preg_replace("#error id=[[:digit:]]{1,4} msg=.*$#Ds", '', $response);
  284. $ret['error']['id'] = (int) $buff[1];
  285. $ret['error']['msg'] = $this->ts3query_unescape($buff[2]);
  286. }
  287. return $ret;
  288. }
  289.  
  290. /**
  291. * @todo documentate
  292. * @param type $ts3
  293. * @return boolean
  294. */
  295. public function ts3_to_hash($ts3)
  296. {
  297. if (is_array($ts3))
  298. {
  299. foreach ($ts3 as $key => $value)
  300. {
  301. $ret[$key] = $this->ts3_to_hash($value);
  302. }
  303. }
  304. else
  305. {
  306. $pairs = explode(" ", trim($ts3));
  307. foreach ($pairs as $pair)
  308. {
  309. if (@strpos($pair, "=", 2) !== false)
  310. {
  311. $pair = explode("=", $pair, 2);
  312. $ret[$pair[0]] = $this->ts3query_unescape($pair[1]);
  313. }
  314. else
  315. {
  316. $ret[$pair] = false;
  317. }
  318. }
  319. }
  320. return $ret;
  321. }
  322.  
  323. /**
  324. * Escapes a TeamSpeak3 Query Command
  325. * @param type $text
  326. * @return type escaped string
  327. */
  328. public function ts3query_escape($text)
  329. {
  330. $to_escape = Array("\\", "/", "\n", " ", "|", "\a", "\b", "\f", "\n", "\r", "\t", "\v");
  331. $replace_with = Array("\\\\", "\/", "\\n", "\\s", "\\p", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v");
  332. return str_replace($to_escape, $replace_with, $text);
  333. }
  334.  
  335. /**
  336. * Unescapes a TeamSpeak3 Query Result
  337. * @param type $text
  338. * @return type unescaped string
  339. */
  340. public function ts3query_unescape($text)
  341. {
  342. if (is_numeric($text)) return (int) $text;
  343. $to_unescape = Array("\\/", "\\\\\\", "\\n", "\\s", "\\p", "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v");
  344. $replace_with = Array("/", "\\", "\n", " ", "|", "\a", "\b", "\f", "\n", "\r", "\t", "\v");
  345. return str_replace($to_unescape, $replace_with, $text);
  346. }
  347.  
  348. /**
  349. * Checks if $options are real query options
  350. * @param string $options query options
  351. * @return boolean true if option else false
  352. */
  353. public function are_options($options)
  354. {
  355. if ($options == "")
  356. {
  357. return true;
  358. }
  359. if (preg_match("/^[[:alpha:] -]*$/D", $options))
  360. {
  361. return true;
  362. }
  363. return false;
  364. }
  365.  
  366. /**
  367. * Sends a command to the TeamSpeak3 Query
  368. * @param string $cmd command
  369. * @param bool $caching If the command should be cached
  370. * @return mixed response
  371. */
  372. public function send_cmd($cmd)
  373. {
  374.  
  375. if (preg_match("/[\r\n]/", $cmd)) return false;
  376. if (is_array($this->cmds))
  377. {
  378. foreach ($this->cmds as $key => $command)
  379. {
  380. $this->send_raw($cmd . "\n");
  381. ts3_check($this->send_raw($command . "\n"), $command);
  382. unset($this->cmds[$key]);
  383. }
  384. }
  385.  
  386. $this->cmd_sent = TRUE;
  387. $response = $this->send_raw($cmd . "\n");
  388. if ($response === false)
  389. {
  390. return false;
  391. }
  392. $response = $this->parse_ts3_response($response);
  393. return $response;
  394. }
  395.  
  396. /**
  397. * Sends raw command to the query
  398. * @param string $text command
  399. * @return mixed raw query response
  400. */
  401. private function send_raw($text)
  402. {
  403. $i = -1;
  404. $ret = '';
  405. if ($this->connection === NULL)
  406. {
  407. $this->open_new_connection();
  408. }
  409. stream_set_timeout($this->connection, 0, 300000);
  410. fputs($this->connection, $text);
  411.  
  412. do
  413. {
  414. $ret .= fgets($this->connection, 8096);
  415. }
  416. while (strstr($ret, "error id=") === false);
  417.  
  418. return $ret;
  419. }
  420.  
  421. /**
  422. * Opens a new TeamSpeak3 Query Connection
  423. * @throws QueryNoResponseException
  424. */
  425. private function open_new_connection()
  426. {
  427.  
  428. $this->connection = fsockopen($this->ip, $this->query_port, $this->sock_error, $this->sock_error_string, $this->timeout);
  429. if ($this->sock_error != 0)
  430. {
  431. throw new QueryNoResponseException(sprintf("Can't open connection to the server at %s:%s. It might be offline at the moment.", $this->ip, $this->query_port));
  432. }
  433. }
  434.  
  435. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement