Reply.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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_Reply
  25. * @brief Provides methods to analyze and format a ServerQuery reply.
  26. */
  27. class TeamSpeak3_Adapter_ServerQuery_Reply
  28. {
  29. /**
  30. * Stores the command used to get this reply.
  31. *
  32. * @var TeamSpeak3_Helper_String
  33. */
  34. protected $cmd = null;
  35. /**
  36. * Stores the servers reply (if available).
  37. *
  38. * @var TeamSpeak3_Helper_String
  39. */
  40. protected $rpl = null;
  41. /**
  42. * Stores connected TeamSpeak3_Node_Host object.
  43. *
  44. * @var TeamSpeak3_Node_Host
  45. */
  46. protected $con = null;
  47. /**
  48. * Stores an assoc array containing the error info for this reply.
  49. *
  50. * @var array
  51. */
  52. protected $err = array();
  53. /**
  54. * Sotres an array of events that occured before or during this reply.
  55. *
  56. * @var array
  57. */
  58. protected $evt = array();
  59. /**
  60. * Indicates whether exceptions should be thrown or not.
  61. *
  62. * @var boolean
  63. */
  64. protected $exp = TRUE;
  65. /**
  66. * Creates a new TeamSpeak3_Adapter_ServerQuery_Reply object.
  67. *
  68. * @param array $rpl
  69. * @param string $cmd
  70. * @param boolean $exp
  71. * @param TeamSpeak3_Node_Host $con
  72. * @return TeamSpeak3_Adapter_ServerQuery_Reply
  73. */
  74. public function __construct(array $rpl, $cmd = null, TeamSpeak3_Node_Host $con = null, $exp = TRUE)
  75. {
  76. $this->cmd = new TeamSpeak3_Helper_String($cmd);
  77. $this->con = $con;
  78. $this->exp = (bool) $exp;
  79. $this->fetchError(array_pop($rpl));
  80. $this->fetchReply($rpl);
  81. }
  82. /**
  83. * Returns the reply as an TeamSpeak3_Helper_String object.
  84. *
  85. * @return TeamSpeak3_Helper_String
  86. */
  87. public function toString()
  88. {
  89. return (!func_num_args()) ? $this->rpl->unescape() : $this->rpl;
  90. }
  91. /**
  92. * Returns the reply as a standard PHP array where each element represents one item.
  93. *
  94. * @return array
  95. */
  96. public function toLines()
  97. {
  98. if(!count($this->rpl)) return array();
  99. $list = $this->toString(0)->split(TeamSpeak3::SEPARATOR_LIST);
  100. if(!func_num_args())
  101. {
  102. for($i = 0; $i < count($list); $i++) $list[$i]->unescape();
  103. }
  104. return $list;
  105. }
  106. /**
  107. * Returns the reply as a standard PHP array where each element represents one item in table format.
  108. *
  109. * @return array
  110. */
  111. public function toTable()
  112. {
  113. $table = array();
  114. foreach($this->toLines(0) as $cells)
  115. {
  116. $pairs = $cells->split(TeamSpeak3::SEPARATOR_CELL);
  117. if(!func_num_args())
  118. {
  119. for($i = 0; $i < count($pairs); $i++) $pairs[$i]->unescape();
  120. }
  121. $table[] = $pairs;
  122. }
  123. return $table;
  124. }
  125. /**
  126. * Returns a multi-dimensional array containing the reply splitted in multiple rows and columns.
  127. *
  128. * @return array
  129. */
  130. public function toArray()
  131. {
  132. $array = array();
  133. $table = $this->toTable(1);
  134. for($i = 0; $i < count($table); $i++)
  135. {
  136. foreach($table[$i] as $pair)
  137. {
  138. if(!count($pair))
  139. {
  140. continue;
  141. }
  142. if(!$pair->contains(TeamSpeak3::SEPARATOR_PAIR))
  143. {
  144. $array[$i][$pair->toString()] = null;
  145. }
  146. else
  147. {
  148. list($ident, $value) = $pair->split(TeamSpeak3::SEPARATOR_PAIR, 2);
  149. $array[$i][$ident->toString()] = $value->isInt() ? $value->toInt() : (!func_num_args() ? $value->unescape() : $value);
  150. }
  151. }
  152. }
  153. return $array;
  154. }
  155. /**
  156. * Returns a multi-dimensional assoc array containing the reply splitted in multiple rows and columns.
  157. * The identifier specified by key will be used while indexing the array.
  158. *
  159. * @param $key
  160. * @return array
  161. */
  162. public function toAssocArray($ident)
  163. {
  164. $nodes = (func_num_args() > 1) ? $this->toArray(1) : $this->toArray();
  165. $array = array();
  166. foreach($nodes as $node)
  167. {
  168. if(isset($node[$ident]))
  169. {
  170. $array[(is_object($node[$ident])) ? $node[$ident]->toString() : $node[$ident]] = $node;
  171. }
  172. else
  173. {
  174. throw new TeamSpeak3_Adapter_ServerQuery_Exception("invalid parameter", 0x602);
  175. }
  176. }
  177. return $array;
  178. }
  179. /**
  180. * Returns an array containing the reply splitted in multiple rows and columns.
  181. *
  182. * @return array
  183. */
  184. public function toList()
  185. {
  186. $array = func_num_args() ? $this->toArray(1) : $this->toArray();
  187. if(count($array) == 1)
  188. {
  189. return array_shift($array);
  190. }
  191. return $array;
  192. }
  193. /**
  194. * Returns an array containing stdClass objects.
  195. *
  196. * @return ArrayObject
  197. */
  198. public function toObjectArray()
  199. {
  200. $array = (func_num_args() > 1) ? $this->toArray(1) : $this->toArray();
  201. for($i = 0; $i < count($array); $i++)
  202. {
  203. $array[$i] = (object) $array[$i];
  204. }
  205. return $array;
  206. }
  207. /**
  208. * Returns the command used to get this reply.
  209. *
  210. * @return TeamSpeak3_Helper_String
  211. */
  212. public function getCommandString()
  213. {
  214. return new TeamSpeak3_Helper_String($this->cmd);
  215. }
  216. /**
  217. * Returns an array of events that occured before or during this reply.
  218. *
  219. * @return array
  220. */
  221. public function getNotifyEvents()
  222. {
  223. return $this->evt;
  224. }
  225. /**
  226. * Returns the value for a specified error property.
  227. *
  228. * @param string $ident
  229. * @param mixed $default
  230. * @return mixed
  231. */
  232. public function getErrorProperty($ident, $default = null)
  233. {
  234. return (array_key_exists($ident, $this->err)) ? $this->err[$ident] : $default;
  235. }
  236. /**
  237. * Parses a ServerQuery error and throws a TeamSpeak3_Adapter_ServerQuery_Exception object if
  238. * there's an error.
  239. *
  240. * @param string $err
  241. * @throws TeamSpeak3_Adapter_ServerQuery_Exception
  242. * @return void
  243. */
  244. protected function fetchError($err)
  245. {
  246. $cells = $err->section(TeamSpeak3::SEPARATOR_CELL, 1, 3);
  247. foreach($cells->split(TeamSpeak3::SEPARATOR_CELL) as $pair)
  248. {
  249. list($ident, $value) = $pair->split(TeamSpeak3::SEPARATOR_PAIR);
  250. $this->err[$ident->toString()] = $value->isInt() ? $value->toInt() : $value->unescape();
  251. }
  252. TeamSpeak3_Helper_Signal::getInstance()->emit("notifyError", $this);
  253. if($this->getErrorProperty("id", 0x00) != 0x00 && $this->exp)
  254. {
  255. if($permid = $this->getErrorProperty("failed_permid"))
  256. {
  257. if($permsid = key($this->con->request("permget permid=" . $permid, FALSE)->toAssocArray("permsid")))
  258. {
  259. $suffix = " (failed on " . $permsid . ")";
  260. }
  261. else
  262. {
  263. $suffix = " (failed on " . $this->cmd->section(TeamSpeak3::SEPARATOR_CELL) . " " . $permid . "/0x" . strtoupper(dechex($permid)) . ")";
  264. }
  265. }
  266. elseif($details = $this->getErrorProperty("extra_msg"))
  267. {
  268. $suffix = " (" . trim($details) . ")";
  269. }
  270. else
  271. {
  272. $suffix = "";
  273. }
  274. throw new TeamSpeak3_Adapter_ServerQuery_Exception($this->getErrorProperty("msg") . $suffix, $this->getErrorProperty("id"), $this->getErrorProperty("return_code"));
  275. }
  276. }
  277. /**
  278. * Parses a ServerQuery reply and creates a TeamSpeak3_Helper_String object.
  279. *
  280. * @param string $rpl
  281. * @return void
  282. */
  283. protected function fetchReply($rpl)
  284. {
  285. foreach($rpl as $key => $val)
  286. {
  287. if($val->startsWith(TeamSpeak3::TS3_MOTD_PREFIX) || $val->startsWith(TeamSpeak3::TEA_MOTD_PREFIX) || (defined("CUSTOM_MOTD_PREFIX") && $val->startsWith(CUSTOM_MOTD_PREFIX)))
  288. {
  289. unset($rpl[$key]);
  290. }
  291. elseif($val->startsWith(TeamSpeak3::EVENT))
  292. {
  293. $this->evt[] = new TeamSpeak3_Adapter_ServerQuery_Event($rpl[$key], $this->con);
  294. unset($rpl[$key]);
  295. }
  296. }
  297. $this->rpl = new TeamSpeak3_Helper_String(implode(TeamSpeak3::SEPARATOR_LIST, $rpl));
  298. }
  299. }