Automatically exported from code.google.com/p/planningalerts
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

629 行
22 KiB

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2002 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/2_02.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Shane Caraveo <shane@caraveo.com> |
  17. // | Ralf Hofmann <ralf.hofmann@verdisoft.com> |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: DIME.php,v 1.5 2002/09/29 01:55:16 shane Exp $
  21. //
  22. require_once 'PEAR.php';
  23. /**
  24. *
  25. * DIME Encoding/Decoding
  26. *
  27. * What is it?
  28. * This class enables you to manipulate and build
  29. * a DIME encapsulated message.
  30. *
  31. * http://www.ietf.org/internet-drafts/draft-nielsen-dime-02.txt
  32. *
  33. * 09/18/02 Ralf - A huge number of changes to be compliant
  34. * with the DIME Specification Release 17 June 2002
  35. *
  36. * TODO: lots of stuff needs to be tested.
  37. * Definitily have to go through DIME spec and
  38. * make things work right, most importantly, sec 3.3
  39. * make examples, document
  40. *
  41. * see test/dime_mesage_test.php for example of usage
  42. *
  43. * @author Shane Caraveo <shane@caraveo.com>,
  44. * Ralf Hofmann <ralf.hofmann@verdisoft.com>
  45. * @version $Revision: 1.5 $
  46. * @package Net_DIME
  47. */
  48. define('NET_DIME_TYPE_UNCHANGED',0x00);
  49. define('NET_DIME_TYPE_MEDIA',0x01);
  50. define('NET_DIME_TYPE_URI',0x02);
  51. define('NET_DIME_TYPE_UNKNOWN',0x03);
  52. define('NET_DIME_TYPE_NONE',0x04);
  53. define('NET_DIME_VERSION',0x0001);
  54. define('NET_DIME_RECORD_HEADER',12);
  55. define('NET_DIME_FLAGS', 0);
  56. define('NET_DIME_OPTS_LEN', 1);
  57. define('NET_DIME_ID_LEN', 2);
  58. define('NET_DIME_TYPE_LEN', 3);
  59. define('NET_DIME_DATA_LEN', 4);
  60. define('NET_DIME_OPTS', 5);
  61. define('NET_DIME_ID', 6);
  62. define('NET_DIME_TYPE', 7);
  63. define('NET_DIME_DATA', 8);
  64. class Net_DIME_Record extends PEAR
  65. {
  66. // these are used to hold the padded length
  67. var $OPTS_LENGTH = 0;
  68. var $ID_LENGTH = 0;
  69. var $TYPE_LENGTH = 0;
  70. var $DATA_LENGTH = 0;
  71. var $_haveOpts = FALSE;
  72. var $_haveID = FALSE;
  73. var $_haveType = FALSE;
  74. var $_haveData = FALSE;
  75. var $debug = FALSE;
  76. var $padstr = "\0";
  77. /**
  78. * Elements
  79. * [NET_DIME_FLAGS], 16 bits: VERSION:MB:ME:CF:TYPE_T
  80. * [NET_DIME_OPTS_LEN], 16 bits: OPTIONS_LENGTH
  81. * [NET_DIME_ID_LEN], 16 bits: ID_LENGTH
  82. * [NET_DIME_TYPE_LEN], 16 bits: TYPE_LENGTH
  83. * [NET_DIME_DATA_LEN], 32 bits: DATA_LENGTH
  84. * [NET_DIME_OPTS] : OPTIONS
  85. * [NET_DIME_ID] : ID
  86. * [NET_DIME_TYPE] : TYPE
  87. * [NET_DIME_DATA] : DATA
  88. */
  89. var $Elements = array(NET_DIME_FLAGS => 0, NET_DIME_OPTS_LEN => 0,
  90. NET_DIME_ID_LEN => 0, NET_DIME_TYPE_LEN => 0,
  91. NET_DIME_DATA_LEN => 0,
  92. NET_DIME_OPTS => '',
  93. NET_DIME_ID => '',
  94. NET_DIME_TYPE => '',
  95. NET_DIME_DATA => '');
  96. function Net_DIME_Record($debug = FALSE)
  97. {
  98. $this->debug = $debug;
  99. if ($debug) $this->padstr = '*';
  100. }
  101. function setMB()
  102. {
  103. $this->Elements[NET_DIME_FLAGS] |= 0x0400;
  104. }
  105. function setME()
  106. {
  107. $this->Elements[NET_DIME_FLAGS] |= 0x0200;
  108. }
  109. function setCF()
  110. {
  111. $this->Elements[NET_DIME_FLAGS] |= 0x0100;
  112. }
  113. function isChunk()
  114. {
  115. return $this->Elements[NET_DIME_FLAGS] & 0x0100;
  116. }
  117. function isEnd()
  118. {
  119. return $this->Elements[NET_DIME_FLAGS] & 0x0200;
  120. }
  121. function isStart()
  122. {
  123. return $this->Elements[NET_DIME_FLAGS] & 0x0400;
  124. }
  125. function getID()
  126. {
  127. return $this->Elements[NET_DIME_ID];
  128. }
  129. function getType()
  130. {
  131. return $this->Elements[NET_DIME_TYPE];
  132. }
  133. function getData()
  134. {
  135. return $this->Elements[NET_DIME_DATA];
  136. }
  137. function getDataLength()
  138. {
  139. return $this->Elements[NET_DIME_DATA_LEN];
  140. }
  141. function setType($typestring, $type=NET_DIME_TYPE_UNKNOWN)
  142. {
  143. $typelen = strlen($typestring) & 0xFFFF;
  144. $type = $type << 4;
  145. $this->Elements[NET_DIME_FLAGS] = ($this->Elements[NET_DIME_FLAGS] & 0xFF0F) | $type;
  146. $this->Elements[NET_DIME_TYPE_LEN] = $typelen;
  147. $this->TYPE_LENGTH = $this->_getPadLength($typelen);
  148. $this->Elements[NET_DIME_TYPE] = $typestring;
  149. }
  150. function generateID()
  151. {
  152. $id = md5(time());
  153. $this->setID($id);
  154. return $id;
  155. }
  156. function setID($id)
  157. {
  158. $idlen = strlen($id) & 0xFFFF;
  159. $this->Elements[NET_DIME_ID_LEN] = $idlen;
  160. $this->ID_LENGTH = $this->_getPadLength($idlen);
  161. $this->Elements[NET_DIME_ID] = $id;
  162. }
  163. function setData($data, $size=0)
  164. {
  165. $datalen = $size?$size:strlen($data);
  166. $this->Elements[NET_DIME_DATA_LEN] = $datalen;
  167. $this->DATA_LENGTH = $this->_getPadLength($datalen);
  168. $this->Elements[NET_DIME_DATA] = $data;
  169. }
  170. function encode()
  171. {
  172. // insert version
  173. $this->Elements[NET_DIME_FLAGS] = ($this->Elements[NET_DIME_FLAGS] & 0x07FF) | (NET_DIME_VERSION << 11);
  174. // the real dime encoding
  175. $format = '%c%c%c%c%c%c%c%c%c%c%c%c'.
  176. '%'.$this->OPTS_LENGTH.'s'.
  177. '%'.$this->ID_LENGTH.'s'.
  178. '%'.$this->TYPE_LENGTH.'s'.
  179. '%'.$this->DATA_LENGTH.'s';
  180. return sprintf($format,
  181. ($this->Elements[NET_DIME_FLAGS]&0x0000FF00)>>8,
  182. ($this->Elements[NET_DIME_FLAGS]&0x000000FF),
  183. ($this->Elements[NET_DIME_OPTS_LEN]&0x0000FF00)>>8,
  184. ($this->Elements[NET_DIME_OPTS_LEN]&0x000000FF),
  185. ($this->Elements[NET_DIME_ID_LEN]&0x0000FF00)>>8,
  186. ($this->Elements[NET_DIME_ID_LEN]&0x000000FF),
  187. ($this->Elements[NET_DIME_TYPE_LEN]&0x0000FF00)>>8,
  188. ($this->Elements[NET_DIME_TYPE_LEN]&0x000000FF),
  189. ($this->Elements[NET_DIME_DATA_LEN]&0xFF000000)>>24,
  190. ($this->Elements[NET_DIME_DATA_LEN]&0x00FF0000)>>16,
  191. ($this->Elements[NET_DIME_DATA_LEN]&0x0000FF00)>>8,
  192. ($this->Elements[NET_DIME_DATA_LEN]&0x000000FF),
  193. str_pad($this->Elements[NET_DIME_OPTS], $this->OPTS_LENGTH, $this->padstr),
  194. str_pad($this->Elements[NET_DIME_ID], $this->ID_LENGTH, $this->padstr),
  195. str_pad($this->Elements[NET_DIME_TYPE], $this->TYPE_LENGTH, $this->padstr),
  196. str_pad($this->Elements[NET_DIME_DATA], $this->DATA_LENGTH, $this->padstr));
  197. }
  198. function _getPadLength($len)
  199. {
  200. $pad = 0;
  201. if ($len) {
  202. $pad = $len % 4;
  203. if ($pad) $pad = 4 - $pad;
  204. }
  205. return $len + $pad;
  206. }
  207. function decode(&$data)
  208. {
  209. // REAL DIME decoding
  210. $this->Elements[NET_DIME_FLAGS] = (hexdec(bin2hex($data[0]))<<8) + hexdec(bin2hex($data[1]));
  211. $this->Elements[NET_DIME_OPTS_LEN] = (hexdec(bin2hex($data[2]))<<8) + hexdec(bin2hex($data[3]));
  212. $this->Elements[NET_DIME_ID_LEN] = (hexdec(bin2hex($data[4]))<<8) + hexdec(bin2hex($data[5]));
  213. $this->Elements[NET_DIME_TYPE_LEN] = (hexdec(bin2hex($data[6]))<<8) + hexdec(bin2hex($data[7]));
  214. $this->Elements[NET_DIME_DATA_LEN] = (hexdec(bin2hex($data[8]))<<24) +
  215. (hexdec(bin2hex($data[9]))<<16) +
  216. (hexdec(bin2hex($data[10]))<<8) +
  217. hexdec(bin2hex($data[11]));
  218. $p = 12;
  219. $version = (($this->Elements[NET_DIME_FLAGS]>>11) & 0x001F);
  220. if ($version == NET_DIME_VERSION)
  221. {
  222. $this->OPTS_LENGTH = $this->_getPadLength($this->Elements[NET_DIME_OPTS_LEN]);
  223. $this->ID_LENGTH = $this->_getPadLength($this->Elements[NET_DIME_ID_LEN]);
  224. $this->TYPE_LENGTH = $this->_getPadLength($this->Elements[NET_DIME_TYPE_LEN]);
  225. $this->DATA_LENGTH = $this->_getPadLength($this->Elements[NET_DIME_DATA_LEN]);
  226. $datalen = strlen($data);
  227. $this->Elements[NET_DIME_OPTS] = substr($data,$p,$this->Elements[NET_DIME_OPTS_LEN]);
  228. $this->_haveOpts = (strlen($this->Elements[NET_DIME_OPTS]) == $this->Elements[NET_DIME_OPTS_LEN]);
  229. if ($this->_haveOpts) {
  230. $p += $this->OPTS_LENGTH;
  231. $this->Elements[NET_DIME_ID] = substr($data,$p,$this->Elements[NET_DIME_ID_LEN]);
  232. $this->_haveID = (strlen($this->Elements[NET_DIME_ID]) == $this->Elements[NET_DIME_ID_LEN]);
  233. if ($this->_haveID) {
  234. $p += $this->ID_LENGTH;
  235. $this->Elements[NET_DIME_TYPE] = substr($data,$p,$this->Elements[NET_DIME_TYPE_LEN]);
  236. $this->_haveType = (strlen($this->Elements[NET_DIME_TYPE]) == $this->Elements[NET_DIME_TYPE_LEN]);
  237. if ($this->_haveType) {
  238. $p += $this->TYPE_LENGTH;
  239. $this->Elements[NET_DIME_DATA] = substr($data,$p,$this->Elements[NET_DIME_DATA_LEN]);
  240. $this->_haveData = (strlen($this->Elements[NET_DIME_DATA]) == $this->Elements[NET_DIME_DATA_LEN]);
  241. if ($this->_haveData) {
  242. $p += $this->DATA_LENGTH;
  243. } else {
  244. $p += strlen($this->Elements[NET_DIME_DATA]);
  245. }
  246. } else {
  247. $p += strlen($this->Elements[NET_DIME_TYPE]);
  248. }
  249. } else {
  250. $p += strlen($this->Elements[NET_DIME_ID]);
  251. }
  252. } else {
  253. $p += strlen($this->Elements[NET_DIME_OPTS]);
  254. }
  255. }
  256. return substr($data, $p);
  257. }
  258. function addData(&$data)
  259. {
  260. $datalen = strlen($data);
  261. $p = 0;
  262. if (!$this->_haveOpts) {
  263. $have = strlen($this->Elements[NET_DIME_OPTS]);
  264. $this->Elements[NET_DIME_OPTS] .= substr($data,$p,$this->Elements[NET_DIME_OPTS_LEN]-$have);
  265. $this->_haveOpts = (strlen($this->Elements[NET_DIME_OPTS]) == $this->Elements[DIME_OTPS_LEN]);
  266. if (!$this->_haveOpts) return NULL;
  267. $p += $this->OPTS_LENGTH-$have;
  268. }
  269. if (!$this->_haveID) {
  270. $have = strlen($this->Elements[NET_DIME_ID]);
  271. $this->Elements[NET_DIME_ID] .= substr($data,$p,$this->Elements[NET_DIME_ID_LEN]-$have);
  272. $this->_haveID = (strlen($this->Elements[NET_DIME_ID]) == $this->Elements[NET_DIME_ID_LEN]);
  273. if (!$this->_haveID) return NULL;
  274. $p += $this->ID_LENGTH-$have;
  275. }
  276. if (!$this->_haveType && $p < $datalen) {
  277. $have = strlen($this->Elements[NET_DIME_TYPE]);
  278. $this->Elements[NET_DIME_TYPE] .= substr($data,$p,$this->Elements[NET_DIME_TYPE_LEN]-$have);
  279. $this->_haveType = (strlen($this->Elements[NET_DIME_TYPE]) == $this->Elements[NET_DIME_TYPE_LEN]);
  280. if (!$this->_haveType) return NULL;
  281. $p += $this->TYPE_LENGTH-$have;
  282. }
  283. if (!$this->_haveData && $p < $datalen) {
  284. $have = strlen($this->Elements[NET_DIME_DATA]);
  285. $this->Elements[NET_DIME_DATA] .= substr($data,$p,$this->Elements[NET_DIME_DATA_LEN]-$have);
  286. $this->_haveData = (strlen($this->Elements[NET_DIME_DATA]) == $this->Elements[NET_DIME_DATA_LEN]);
  287. if (!$this->_haveData) return NULL;
  288. $p += $this->DATA_LENGTH-$have;
  289. }
  290. return substr($data,$p);
  291. }
  292. }
  293. class Net_DIME_Message extends PEAR
  294. {
  295. var $record_size = 4096;
  296. #var $records =array();
  297. var $parts = array();
  298. var $currentPart = -1;
  299. var $stream = NULL;
  300. var $_currentRecord;
  301. var $_proc = array();
  302. var $type;
  303. var $typestr;
  304. var $mb = 1;
  305. var $me = 0;
  306. var $cf = 0;
  307. var $id = NULL;
  308. var $debug = FALSE;
  309. /**
  310. * constructor
  311. *
  312. * this currently takes a file pointer as provided
  313. * by fopen
  314. *
  315. * TODO: integrate with the php streams stuff
  316. */
  317. function Net_DIME_Message($stream=NULL, $record_size = 4096, $debug = FALSE)
  318. {
  319. $this->stream = $stream;
  320. $this->record_size = $record_size;
  321. $this->debug = $debug;
  322. }
  323. function _makeRecord(&$data, $typestr='', $id=NULL, $type=NET_DIME_TYPE_UNKNOWN)
  324. {
  325. $record = new Net_DIME_Record($this->debug);
  326. if ($this->mb) {
  327. $record->setMB();
  328. // all subsequent records are not message begin!
  329. $this->mb = 0;
  330. }
  331. if ($this->me) $record->setME();
  332. if ($this->cf) $record->setCF();
  333. $record->setData($data);
  334. $record->setType($typestr,$type);
  335. if ($id) $record->setID($id);
  336. #if ($this->debug) {
  337. # print str_replace('\0','*',$record->encode());
  338. #}
  339. return $record->encode();
  340. }
  341. function startChunk(&$data, $typestr='', $id=NULL, $type=NET_DIME_TYPE_UNKNOWN)
  342. {
  343. $this->me = 0;
  344. $this->cf = 1;
  345. $this->type = $type;
  346. $this->typestr = $typestr;
  347. if ($id) {
  348. $this->id = $id;
  349. } else {
  350. $this->id = md5(time());
  351. }
  352. return $this->_makeRecord($data, $this->typestr, $this->id, $this->type);
  353. }
  354. function doChunk(&$data)
  355. {
  356. $this->me = 0;
  357. $this->cf = 1;
  358. return $this->_makeRecord($data, NULL, NULL, NET_DIME_TYPE_UNCHANGED);
  359. }
  360. function endChunk()
  361. {
  362. $this->cf = 0;
  363. $data = NULL;
  364. $rec = $this->_makeRecord($data, NULL, NULL, NET_DIME_TYPE_UNCHANGED);
  365. $this->id = 0;
  366. $this->cf = 0;
  367. $this->id = 0;
  368. $this->type = NET_DIME_TYPE_UNKNOWN;
  369. $this->typestr = NULL;
  370. return $rec;
  371. }
  372. function endMessage()
  373. {
  374. $this->me = 1;
  375. $data = NULL;
  376. $rec = $this->_makeRecord($data, NULL, NULL, NET_DIME_TYPE_NONE);
  377. $this->me = 0;
  378. $this->mb = 1;
  379. $this->id = 0;
  380. return $rec;
  381. }
  382. /**
  383. * sendRecord
  384. *
  385. * given a chunk of data, it creates DIME records
  386. * and writes them to the stream
  387. *
  388. */
  389. function sendData(&$data, $typestr='', $id=NULL, $type=NET_DIME_TYPE_UNKNOWN)
  390. {
  391. $len = strlen($data);
  392. if ($len > $this->record_size) {
  393. $chunk = substr($data, 0, $this->record_size);
  394. $p = $this->record_size;
  395. $rec = $this->startChunk($chunk,$typestr,$id,$type);
  396. fwrite($this->stream, $rec);
  397. while ($p < $len) {
  398. $chunk = substr($data, $p, $this->record_size);
  399. $p += $this->record_size;
  400. $rec = $this->doChunk($chunk);
  401. fwrite($this->stream, $rec);
  402. }
  403. $rec = $this->endChunk();
  404. fwrite($this->stream, $rec);
  405. return;
  406. }
  407. $rec = $this->_makeRecord($data, $typestr,$id,$type);
  408. fwrite($this->stream, $rec);
  409. }
  410. function sendEndMessage()
  411. {
  412. $rec = $this->endMessage();
  413. fwrite($this->stream, $rec);
  414. }
  415. /**
  416. * sendFile
  417. *
  418. * given a filename, it reads the file,
  419. * creates records and writes them to the stream
  420. *
  421. */
  422. function sendFile($filename, $typestr='', $id=NULL, $type=NET_DIME_TYPE_UNKNOWN)
  423. {
  424. $f = fopen($filename, "rb");
  425. if ($f) {
  426. if ($data = fread($f, $this->record_size)) {
  427. $this->startChunk($data,$typestr,$id,$type);
  428. }
  429. while ($data = fread($f, $this->record_size)) {
  430. $this->doChunk($data,$typestr,$id,$type);
  431. }
  432. $this->endChunk();
  433. fclose($f);
  434. }
  435. }
  436. /**
  437. * encodeData
  438. *
  439. * given data, encode it in DIME
  440. *
  441. */
  442. function encodeData($data, $typestr='', $id=NULL, $type=NET_DIME_TYPE_UNKNOWN)
  443. {
  444. $len = strlen($data);
  445. $resp = '';
  446. if ($len > $this->record_size) {
  447. $chunk = substr($data, 0, $this->record_size);
  448. $p = $this->record_size;
  449. $resp .= $this->startChunk($chunk,$typestr,$id,$type);
  450. while ($p < $len) {
  451. $chunk = substr($data, $p, $this->record_size);
  452. $p += $this->record_size;
  453. $resp .= $this->doChunk($chunk);
  454. }
  455. $resp .= $this->endChunk();
  456. } else {
  457. $resp .= $this->_makeRecord($data, $typestr,$id,$type);
  458. }
  459. return $resp;
  460. }
  461. /**
  462. * sendFile
  463. *
  464. * given a filename, it reads the file,
  465. * creates records and writes them to the stream
  466. *
  467. */
  468. function encodeFile($filename, $typestr='', $id=NULL, $type=NET_DIME_TYPE_UNKNOWN)
  469. {
  470. $f = fopen($filename, "rb");
  471. if ($f) {
  472. if ($data = fread($f, $this->record_size)) {
  473. $resp = $this->startChunk($data,$typestr,$id,$type);
  474. }
  475. while ($data = fread($f, $this->record_size)) {
  476. $resp = $this->doChunk($data,$typestr,$id,$type);
  477. }
  478. $resp = $this->endChunk();
  479. fclose($f);
  480. }
  481. return $resp;
  482. }
  483. /**
  484. * _processData
  485. *
  486. * creates Net_DIME_Records from provided data
  487. *
  488. */
  489. function _processData(&$data)
  490. {
  491. $leftover = NULL;
  492. if (!$this->_currentRecord) {
  493. $this->_currentRecord = new Net_DIME_Record($this->debug);
  494. $data = $this->_currentRecord->decode($data);
  495. } else {
  496. $data = $this->_currentRecord->addData($data);
  497. }
  498. if ($this->_currentRecord->_haveData) {
  499. if (count($this->parts)==0 && !$this->_currentRecord->isStart()) {
  500. // raise an error!
  501. return PEAR::raiseError('First Message is not a DIME begin record!');
  502. }
  503. if ($this->_currentRecord->isEnd() && $this->_currentRecord->getDataLength()==0) {
  504. return NULL;
  505. }
  506. if ($this->currentPart < 0 && !$this->_currentRecord->isChunk()) {
  507. $this->parts[] = array();
  508. $this->currentPart = count($this->parts)-1;
  509. $this->parts[$this->currentPart]['id'] = $this->_currentRecord->getID();
  510. $this->parts[$this->currentPart]['type'] = $this->_currentRecord->getType();
  511. $this->parts[$this->currentPart]['data'] = $this->_currentRecord->getData();
  512. $this->currentPart = -1;
  513. } else {
  514. if ($this->currentPart < 0) {
  515. $this->parts[] = array();
  516. $this->currentPart = count($this->parts)-1;
  517. $this->parts[$this->currentPart]['id'] = $this->_currentRecord->getID();
  518. $this->parts[$this->currentPart]['type'] = $this->_currentRecord->getType();
  519. $this->parts[$this->currentPart]['data'] = $this->_currentRecord->getData();
  520. } else {
  521. $this->parts[$this->currentPart]['data'] .= $this->_currentRecord->getData();
  522. if (!$this->_currentRecord->isChunk()) {
  523. // we reached the end of the chunk
  524. $this->currentPart = -1;
  525. }
  526. }
  527. }
  528. #$this->records[] = $this->_currentRecord;
  529. if (!$this->_currentRecord->isEnd()) $this->_currentRecord = NULL;
  530. }
  531. return NULL;
  532. }
  533. /**
  534. * decodeData
  535. *
  536. * decodes a DIME encrypted string of data
  537. *
  538. */
  539. function decodeData(&$data) {
  540. while (strlen($data) >= NET_DIME_RECORD_HEADER) {
  541. $err = $this->_processData($data);
  542. if (PEAR::isError($err)) {
  543. return $err;
  544. }
  545. }
  546. }
  547. /**
  548. * read
  549. *
  550. * reads the stream and creates
  551. * an array of records
  552. *
  553. * it can accept the start of a previously read buffer
  554. * this is usefull in situations where you need to read
  555. * headers before discovering that the data is DIME encoded
  556. * such as in the case of reading an HTTP response.
  557. */
  558. function read($buf=NULL)
  559. {
  560. while ($data = fread($this->stream, 8192)) {
  561. if ($buf) {
  562. $data = $buf.$data;
  563. $buf = NULL;
  564. }
  565. if ($this->debug)
  566. echo "read: ".strlen($data)." bytes\n";
  567. $err = $this->decodeData($data);
  568. if (PEAR::isError($err)) {
  569. return $err;
  570. }
  571. // store any leftover data to be used again
  572. // should be < NET_DIME_RECORD_HEADER bytes
  573. $buf = $data;
  574. }
  575. if (!$this->_currentRecord || !$this->_currentRecord->isEnd()) {
  576. return PEAR::raiseError('reached stream end without end record');
  577. }
  578. return NULL;
  579. }
  580. }
  581. ?>