ServerQuery.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <?php
  2. /**
  3. * @file
  4. * TeamSpeak 3 PHP Framework
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. * @package TeamSpeak3
  20. * @author Sven 'ScP' Paulsen
  21. * @copyright Copyright (c) Planet TeamSpeak. All rights reserved.
  22. */
  23. /**
  24. * @class TeamSpeak3_Adapter_ServerQuery
  25. * @brief Provides low-level methods for ServerQuery communication with a TeamSpeak 3 Server.
  26. */
  27. class TeamSpeak3_Adapter_ServerQuery extends TeamSpeak3_Adapter_Abstract
  28. {
  29. /**
  30. * Stores a singleton instance of the active TeamSpeak3_Node_Host object.
  31. *
  32. * @var TeamSpeak3_Node_Host
  33. */
  34. protected $host = null;
  35. /**
  36. * Stores the timestamp of the last command.
  37. *
  38. * @var integer
  39. */
  40. protected $timer = null;
  41. /**
  42. * Number of queries executed on the server.
  43. *
  44. * @var integer
  45. */
  46. protected $count = 0;
  47. /**
  48. * Stores an array with unsupported commands.
  49. *
  50. * @var array
  51. */
  52. protected $block = array("help");
  53. /**
  54. * Connects the TeamSpeak3_Transport_Abstract object and performs initial actions on the remote
  55. * server.
  56. *
  57. * @throws TeamSpeak3_Adapter_Exception
  58. * @return void
  59. */
  60. protected function syn()
  61. {
  62. $this->initTransport($this->options);
  63. $this->transport->setAdapter($this);
  64. TeamSpeak3_Helper_Profiler::init(spl_object_hash($this));
  65. $rdy = $this->getTransport()->readLine();
  66. if(!$rdy->startsWith(TeamSpeak3::TS3_PROTO_IDENT) && !$rdy->startsWith(TeamSpeak3::TEA_PROTO_IDENT) && !(defined("CUSTOM_PROTO_IDENT") && $rdy->startsWith(CUSTOM_PROTO_IDENT)))
  67. {
  68. throw new TeamSpeak3_Adapter_Exception("invalid reply from the server (" . $rdy . ")");
  69. }
  70. TeamSpeak3_Helper_Signal::getInstance()->emit("serverqueryConnected", $this);
  71. }
  72. /**
  73. * The TeamSpeak3_Adapter_ServerQuery destructor.
  74. *
  75. * @return void
  76. */
  77. public function __destruct()
  78. {
  79. if($this->getTransport() instanceof TeamSpeak3_Transport_Abstract && $this->transport->isConnected())
  80. {
  81. try
  82. {
  83. $this->request("quit");
  84. }
  85. catch(Exception $e)
  86. {
  87. return;
  88. }
  89. }
  90. }
  91. /**
  92. * Sends a prepared command to the server and returns the result.
  93. *
  94. * @param string $cmd
  95. * @param boolean $throw
  96. * @throws TeamSpeak3_Adapter_Exception
  97. * @return TeamSpeak3_Adapter_ServerQuery_Reply
  98. */
  99. public function request($cmd, $throw = TRUE)
  100. {
  101. $query = TeamSpeak3_Helper_String::factory($cmd)->section(TeamSpeak3::SEPARATOR_CELL);
  102. if(strstr($cmd, "\r") || strstr($cmd, "\n"))
  103. {
  104. throw new TeamSpeak3_Adapter_Exception("illegal characters in command '" . $query . "'");
  105. }
  106. elseif(in_array($query, $this->block))
  107. {
  108. throw new TeamSpeak3_Adapter_ServerQuery_Exception("command not found", 0x100);
  109. }
  110. TeamSpeak3_Helper_Signal::getInstance()->emit("serverqueryCommandStarted", $cmd);
  111. $this->getProfiler()->start();
  112. $this->getTransport()->sendLine($cmd);
  113. $this->timer = time();
  114. $this->count++;
  115. $rpl = array();
  116. do {
  117. $str = $this->getTransport()->readLine();
  118. $rpl[] = $str;
  119. } while($str instanceof TeamSpeak3_Helper_String && $str->section(TeamSpeak3::SEPARATOR_CELL) != TeamSpeak3::ERROR);
  120. $this->getProfiler()->stop();
  121. $reply = new TeamSpeak3_Adapter_ServerQuery_Reply($rpl, $cmd, $this->getHost(), $throw);
  122. TeamSpeak3_Helper_Signal::getInstance()->emit("serverqueryCommandFinished", $cmd, $reply);
  123. return $reply;
  124. }
  125. /**
  126. * Waits for the server to send a notification message and returns the result.
  127. *
  128. * @throws TeamSpeak3_Adapter_Exception
  129. * @return TeamSpeak3_Adapter_ServerQuery_Event
  130. */
  131. public function wait()
  132. {
  133. if($this->getTransport()->getConfig("blocking"))
  134. {
  135. throw new TeamSpeak3_Adapter_Exception("only available in non-blocking mode");
  136. }
  137. do {
  138. $evt = $this->getTransport()->readLine();
  139. } while($evt instanceof TeamSpeak3_Helper_String && !$evt->section(TeamSpeak3::SEPARATOR_CELL)->startsWith(TeamSpeak3::EVENT));
  140. return new TeamSpeak3_Adapter_ServerQuery_Event($evt, $this->getHost());
  141. }
  142. /**
  143. * Uses given parameters and returns a prepared ServerQuery command.
  144. *
  145. * @param string $cmd
  146. * @param array $params
  147. * @return string
  148. */
  149. public function prepare($cmd, array $params = array())
  150. {
  151. $args = array();
  152. $cells = array();
  153. foreach($params as $ident => $value)
  154. {
  155. $ident = is_numeric($ident) ? "" : strtolower($ident) . TeamSpeak3::SEPARATOR_PAIR;
  156. if(is_array($value))
  157. {
  158. $value = array_values($value);
  159. for($i = 0; $i < count($value); $i++)
  160. {
  161. if($value[$i] === null) continue;
  162. elseif($value[$i] === FALSE) $value[$i] = 0x00;
  163. elseif($value[$i] === TRUE) $value[$i] = 0x01;
  164. elseif($value[$i] instanceof TeamSpeak3_Node_Abstract) $value[$i] = $value[$i]->getId();
  165. $cells[$i][] = $ident . TeamSpeak3_Helper_String::factory($value[$i])->escape()->toUtf8();
  166. }
  167. }
  168. else
  169. {
  170. if($value === null) continue;
  171. elseif($value === FALSE) $value = 0x00;
  172. elseif($value === TRUE) $value = 0x01;
  173. elseif($value instanceof TeamSpeak3_Node_Abstract) $value = $value->getId();
  174. $args[] = $ident . TeamSpeak3_Helper_String::factory($value)->escape()->toUtf8();
  175. }
  176. }
  177. foreach(array_keys($cells) as $ident) $cells[$ident] = implode(TeamSpeak3::SEPARATOR_CELL, $cells[$ident]);
  178. if(count($args)) $cmd .= " " . implode(TeamSpeak3::SEPARATOR_CELL, $args);
  179. if(count($cells)) $cmd .= " " . implode(TeamSpeak3::SEPARATOR_LIST, $cells);
  180. return trim($cmd);
  181. }
  182. /**
  183. * Returns the timestamp of the last command.
  184. *
  185. * @return integer
  186. */
  187. public function getQueryLastTimestamp()
  188. {
  189. return $this->timer;
  190. }
  191. /**
  192. * Returns the number of queries executed on the server.
  193. *
  194. * @return integer
  195. */
  196. public function getQueryCount()
  197. {
  198. return $this->count;
  199. }
  200. /**
  201. * Returns the total runtime of all queries.
  202. *
  203. * @return mixed
  204. */
  205. public function getQueryRuntime()
  206. {
  207. return $this->getProfiler()->getRuntime();
  208. }
  209. /**
  210. * Returns the TeamSpeak3_Node_Host object of the current connection.
  211. *
  212. * @return TeamSpeak3_Node_Host
  213. */
  214. public function getHost()
  215. {
  216. if($this->host === null)
  217. {
  218. $this->host = new TeamSpeak3_Node_Host($this);
  219. }
  220. return $this->host;
  221. }
  222. }