Frame.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Queue
  17. * @subpackage Adapter
  18. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Stomp.php 14504 2009-03-27 05:32:18Z danlo $
  21. */
  22. /**
  23. * This class represents a Stomp Frame
  24. *
  25. * @category Zend
  26. * @package Zend_Queue
  27. * @subpackage Adapter
  28. * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. require_once 'Zend/Queue/Stomp/FrameInterface.php';
  32. class Zend_Queue_Stomp_Frame
  33. implements Zend_Queue_Stomp_FrameInterface
  34. {
  35. const END_OF_FRAME = "\x00\n";
  36. const CONTENT_LENGTH = 'content-length';
  37. const EOL = "\n";
  38. /**
  39. * Headers for the frame
  40. *
  41. * @var array
  42. */
  43. protected $_headers = array();
  44. /**
  45. * The command for the frame
  46. *
  47. * @var string
  48. */
  49. protected $_command = null;
  50. /**
  51. * The body of the frame
  52. *
  53. * @var string
  54. */
  55. protected $_body = null;
  56. /**
  57. * Do the content-length automatically?
  58. */
  59. protected $_autoContentLength = null;
  60. /**
  61. * Constructor
  62. */
  63. public function __construct()
  64. {
  65. $this->setHeaders(array());
  66. $this->setBody(null);
  67. $this->setCommand(null);
  68. $this->setAutoContentLength(true);
  69. }
  70. /**
  71. * get the status of the auto content length
  72. *
  73. * If AutoContentLength is true this code will automatically put the
  74. * content-length header in, even if it is already set by the user.
  75. *
  76. * This is done to make the message sending more reliable.
  77. *
  78. * @return boolean
  79. */
  80. public function getAutoContentLength()
  81. {
  82. return $this->_autoContentLength;
  83. }
  84. /**
  85. * setAutoContentLength()
  86. *
  87. * Set the value on or off.
  88. *
  89. * @param boolean $auto
  90. * @return $this;
  91. * @throws Zend_Queue_Exception
  92. */
  93. public function setAutoContentLength($auto)
  94. {
  95. if (!is_bool($auto)) {
  96. require_once 'Zend/Queue/Exception.php';
  97. throw new Zend_Queue_Exception('$auto is not a boolean');
  98. }
  99. $this->_autoContentLength = $auto;
  100. return $this;
  101. }
  102. /**
  103. * Get the headers
  104. *
  105. * @return array
  106. */
  107. public function getHeaders()
  108. {
  109. return $this->_headers;
  110. }
  111. /**
  112. * Set the headers
  113. *
  114. * Throws an exception if the array values are not strings.
  115. *
  116. * @param array $headers
  117. * @return $this
  118. * @throws Zend_Queue_Exception
  119. */
  120. public function setHeaders(array $headers)
  121. {
  122. foreach ($headers as $header => $value) {
  123. $this->setHeader($header, $value);
  124. }
  125. return $this;
  126. }
  127. /**
  128. * Sets a value for a header
  129. *
  130. * @param string $header
  131. * @param string $value
  132. * @return Zend_Queue_Stomp_Frame
  133. * @throws Zend_Queue_Exception
  134. */
  135. public function setHeader($header, $value) {
  136. if (!is_string($header)) {
  137. require_once 'Zend/Queue/Exception.php';
  138. throw new Zend_Queue_Exception('$header is not a string: ' . print_r($header, true));
  139. }
  140. if (!is_scalar($value)) {
  141. require_once 'Zend/Queue/Exception.php';
  142. throw new Zend_Queue_Exception('$value is not a string: ' . print_r($value, true));
  143. }
  144. $this->_headers[$header] = $value;
  145. return $this;
  146. }
  147. /**
  148. * Returns a value for a header
  149. *
  150. * Returns false if the header does not exist.
  151. *
  152. * @param string $header
  153. * @return string|false
  154. * @throws Zend_Queue_Exception
  155. */
  156. public function getHeader($header)
  157. {
  158. if (!is_string($header)) {
  159. require_once 'Zend/Queue/Exception.php';
  160. throw new Zend_Queue_Exception('$header is not a string');
  161. }
  162. return isset($this->_headers[$header])
  163. ? $this->_headers[$header]
  164. : false;
  165. }
  166. /**
  167. * Return the body for this frame
  168. *
  169. * Returns false if the body does not exist
  170. *
  171. * @return false|string
  172. */
  173. public function getBody()
  174. {
  175. return is_null($this->_body)
  176. ? false
  177. : $this->_body;
  178. }
  179. /**
  180. * Set the body for this frame
  181. *
  182. * Set to null for no body.
  183. *
  184. * @param string|null $body
  185. * @return Zend_Queue_Stomp_Frame
  186. * @throws Zend_Queue_Exception
  187. */
  188. public function setBody($body)
  189. {
  190. if (!is_string($body) && !is_null($body)) {
  191. require_once 'Zend/Queue/Exception.php';
  192. throw new Zend_Queue_Exception('$body is not a string or null');
  193. }
  194. $this->_body = $body;
  195. return $this;
  196. }
  197. /**
  198. * Return the command for this frame
  199. *
  200. * Return false if the command does not exist
  201. *
  202. * @return string|false
  203. */
  204. public function getCommand()
  205. {
  206. return is_null($this->_command)
  207. ? false
  208. : $this->_command;
  209. }
  210. /**
  211. * Set the body for this frame
  212. *
  213. * @param string|null
  214. * @return Zend_Queue_Stomp_Frame
  215. * @throws Zend_Queue_Exception
  216. */
  217. public function setCommand($command)
  218. {
  219. if (!is_string($command) && !is_null($command)) {
  220. require_once 'Zend/Queue/Exception.php';
  221. throw new Zend_Queue_Exception('$command is not a string or null');
  222. }
  223. $this->_command = $command;
  224. return $this;
  225. }
  226. /**
  227. * Takes the current parameters and returns a Stomp Frame
  228. *
  229. * @return string
  230. * @throws Zend_Queue_Exception
  231. */
  232. public function toFrame()
  233. {
  234. if ($this->getCommand() === false) {
  235. require_once 'Zend/Queue/Exception.php';
  236. throw new Zend_Queue_Exception('You must set the command');
  237. }
  238. $command = $this->getCommand();
  239. $headers = $this->getHeaders();
  240. $body = $this->getBody();
  241. $frame = '';
  242. // add a content-length to the SEND command.
  243. // @see http://stomp.codehaus.org/Protocol
  244. if ($this->getAutoContentLength()) {
  245. $headers[self::CONTENT_LENGTH] = strlen($this->getBody());
  246. }
  247. // Command
  248. $frame = $command . self::EOL;
  249. // Headers
  250. foreach ($headers as $key=>$value) {
  251. $frame .= $key . ': ' . $value . self::EOL;
  252. }
  253. // Seperator
  254. $frame .= self::EOL; // blank line required by protocol
  255. // add the body if any
  256. if ($body !== false) {
  257. $frame .= $body;
  258. }
  259. $frame .= self::END_OF_FRAME;
  260. return $frame;
  261. }
  262. /**
  263. * @see toFrame()
  264. * @return string
  265. */
  266. public function __toString()
  267. {
  268. try {
  269. $return = $this->toFrame();
  270. } catch (Zend_Queue_Exception $e) {
  271. $return = '';
  272. }
  273. return $return;
  274. }
  275. /**
  276. * Accepts a frame and deconstructs the frame into its component parts
  277. *
  278. * @param string $frame - a stomp frame
  279. * @return $this
  280. */
  281. public function fromFrame($frame)
  282. {
  283. if (!is_string($frame)) {
  284. require_once 'Zend/Queue/Exception.php';
  285. throw new Zend_Queue_Exception('$frame is not a string');
  286. }
  287. $headers = array();
  288. $body = null;
  289. $command = false;
  290. $header = '';
  291. // separate the headers and the body
  292. $match = self::EOL . self::EOL;
  293. if (preg_match('/' . $match . '/', $frame)) {
  294. list ($header, $body) = explode($match, $frame, 2);
  295. } else {
  296. $header = $frame;
  297. }
  298. // blow up headers
  299. $headers = explode(self::EOL, $header);
  300. unset($header);
  301. // get the command (first line)
  302. $this->setCommand(array_shift($headers));
  303. // set each of the headers.
  304. foreach ($headers as $header) {
  305. if (strpos($header, ':') > 0) {
  306. list($name, $value) = explode(':', $header, 2);
  307. $this->setHeader($name, $value);
  308. }
  309. }
  310. // crop the body if content-length is present
  311. if ($this->getHeader(self::CONTENT_LENGTH) !== false ) {
  312. $length = (int) $this->getHeader(self::CONTENT_LENGTH);
  313. $body = substr($body, 0, $length);
  314. }
  315. $this->setBody($body);
  316. return $this;
  317. }
  318. }