PageRenderTime 42ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/app/lib/Net_DNS2-1.3.2/Net/DNS2/RR.php

https://bitbucket.org/IrrVoi/dropbox
PHP | 641 lines | 247 code | 86 blank | 308 comment | 40 complexity | 42bbbdfb70dec0332eee12df6e0bc6de MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * DNS Library for handling lookups and updates.
  5. *
  6. * PHP Version 5
  7. *
  8. * Copyright (c) 2010, Mike Pultz <mike@mikepultz.com>.
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * * Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in
  20. * the documentation and/or other materials provided with the
  21. * distribution.
  22. *
  23. * * Neither the name of Mike Pultz nor the names of his contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * @category Networking
  41. * @package Net_DNS2
  42. * @author Mike Pultz <mike@mikepultz.com>
  43. * @copyright 2010 Mike Pultz <mike@mikepultz.com>
  44. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  45. * @version SVN: $Id: RR.php 188 2013-03-31 01:25:46Z mike.pultz $
  46. * @link http://pear.php.net/package/Net_DNS2
  47. * @since File available since Release 0.6.0
  48. *
  49. */
  50. /**
  51. * This is the base class for DNS Resource Records
  52. *
  53. * Each resource record type (defined in RR/*.php) extends this class for
  54. * base functionality.
  55. *
  56. * This class handles parsing and constructing the common parts of the DNS
  57. * resource records, while the RR specific functionality is handled in each
  58. * child class.
  59. *
  60. * DNS resource record format - RFC1035 section 4.1.3
  61. *
  62. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  63. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  64. * | |
  65. * / /
  66. * / NAME /
  67. * | |
  68. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  69. * | TYPE |
  70. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  71. * | CLASS |
  72. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  73. * | TTL |
  74. * | |
  75. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  76. * | RDLENGTH |
  77. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
  78. * / RDATA /
  79. * / /
  80. * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  81. *
  82. * @category Networking
  83. * @package Net_DNS2
  84. * @author Mike Pultz <mike@mikepultz.com>
  85. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  86. * @link http://pear.php.net/package/Net_DNS2
  87. *
  88. */
  89. abstract class Net_DNS2_RR
  90. {
  91. /*
  92. * The name of the resource record
  93. */
  94. public $name;
  95. /*
  96. * The resource record type
  97. */
  98. public $type;
  99. /*
  100. * The resouce record class
  101. */
  102. public $class;
  103. /*
  104. * The time to live for this resource record
  105. */
  106. public $ttl;
  107. /*
  108. * The length of the rdata field
  109. */
  110. public $rdlength;
  111. /*
  112. * The resource record specific data as a packed binary string
  113. */
  114. public $rdata;
  115. /**
  116. * abstract definition - method to return a RR as a string; not to
  117. * be confused with the __toString() magic method.
  118. *
  119. * @return string
  120. * @access protected
  121. *
  122. */
  123. abstract protected function rrToString();
  124. /**
  125. * abstract definition - parses a RR from a standard DNS config line
  126. *
  127. * @param array $rdata a string split line of values for the rdata
  128. *
  129. * @return boolean
  130. * @access protected
  131. *
  132. */
  133. abstract protected function rrFromString(array $rdata);
  134. /**
  135. * abstract definition - sets a Net_DNS2_RR from a Net_DNS2_Packet object
  136. *
  137. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
  138. *
  139. * @return boolean
  140. * @access protected
  141. *
  142. */
  143. abstract protected function rrSet(Net_DNS2_Packet &$packet);
  144. /**
  145. * abstract definition - returns a binary packet DNS RR object
  146. *
  147. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
  148. * compressed names
  149. *
  150. * @return mixed either returns a binary packed string or
  151. * null on failure
  152. * @access protected
  153. *
  154. */
  155. abstract protected function rrGet(Net_DNS2_Packet &$packet);
  156. /**
  157. * Constructor - builds a new Net_DNS2_RR object
  158. *
  159. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet or null to create
  160. * an empty object
  161. * @param array $rr an array with RR parse values or null to
  162. * create an empty object
  163. *
  164. * @throws Net_DNS2_Exception
  165. * @access public
  166. *
  167. */
  168. public function __construct(Net_DNS2_Packet &$packet = null, array $rr = null)
  169. {
  170. if ( (!is_null($packet)) && (!is_null($rr)) ) {
  171. if ($this->set($packet, $rr) == false) {
  172. throw new Net_DNS2_Exception(
  173. 'failed to generate resource record',
  174. Net_DNS2_Lookups::E_RR_INVALID
  175. );
  176. }
  177. } else {
  178. $class = Net_DNS2_Lookups::$rr_types_class_to_id[get_class($this)];
  179. if (isset($class)) {
  180. $this->type = Net_DNS2_Lookups::$rr_types_by_id[$class];
  181. }
  182. $this->class = 'IN';
  183. $this->ttl = 86400;
  184. }
  185. }
  186. /**
  187. * magic __toString() method to return the Net_DNS2_RR object object as a string
  188. *
  189. * @return string
  190. * @access public
  191. *
  192. */
  193. public function __toString()
  194. {
  195. return $this->name . '. ' . $this->ttl . ' ' . $this->class .
  196. ' ' . $this->type . ' ' . $this->rrToString();
  197. }
  198. /**
  199. * return a formatted string; if a string has spaces in it, then return
  200. * it with double quotes around it, otherwise, return it as it was passed in.
  201. *
  202. * @param string $string the string to format
  203. *
  204. * @return string
  205. * @access protected
  206. *
  207. */
  208. protected function formatString($string)
  209. {
  210. return '"' . str_replace('"', '\"', trim($string, '"')) . '"';
  211. }
  212. /**
  213. * builds an array of strings from an array of chunks of text split by spaces
  214. *
  215. * @param array $chunks an array of chunks of text split by spaces
  216. *
  217. * @return array
  218. * @access protected
  219. *
  220. */
  221. protected function buildString(array $chunks)
  222. {
  223. $data = array();
  224. $c = 0;
  225. $in = false;
  226. foreach ($chunks as $r) {
  227. $r = trim($r);
  228. if (strlen($r) == 0) {
  229. continue;
  230. }
  231. if ( ($r[0] == '"')
  232. && ($r[strlen($r) - 1] == '"')
  233. && ($r[strlen($r) - 2] != '\\')
  234. ) {
  235. $data[$c] = $r;
  236. ++$c;
  237. $in = false;
  238. } else if ($r[0] == '"') {
  239. $data[$c] = $r;
  240. $in = true;
  241. } else if ( ($r[strlen($r) - 1] == '"')
  242. && ($r[strlen($r) - 2] != '\\')
  243. ) {
  244. $data[$c] .= ' ' . $r;
  245. ++$c;
  246. $in = false;
  247. } else {
  248. if ($in == true) {
  249. $data[$c] .= ' ' . $r;
  250. } else {
  251. $data[$c++] = $r;
  252. }
  253. }
  254. }
  255. foreach ($data as $index => $string) {
  256. $data[$index] = str_replace('\"', '"', trim($string, '"'));
  257. }
  258. return $data;
  259. }
  260. /**
  261. * builds a new Net_DNS2_RR object
  262. *
  263. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet or null to create
  264. * an empty object
  265. * @param array $rr an array with RR parse values or null to
  266. * create an empty object
  267. *
  268. * @return boolean
  269. * @throws Net_DNS2_Exception
  270. * @access public
  271. *
  272. */
  273. public function set(Net_DNS2_Packet &$packet, array $rr)
  274. {
  275. $this->name = $rr['name'];
  276. $this->type = Net_DNS2_Lookups::$rr_types_by_id[$rr['type']];
  277. //
  278. // for RR OPT (41), the class value includes the requestors UDP payload size,
  279. // and not a class value
  280. //
  281. if ($this->type == 'OPT') {
  282. $this->class = $rr['class'];
  283. } else {
  284. $this->class = Net_DNS2_Lookups::$classes_by_id[$rr['class']];
  285. }
  286. $this->ttl = $rr['ttl'];
  287. $this->rdlength = $rr['rdlength'];
  288. $this->rdata = substr($packet->rdata, $packet->offset, $rr['rdlength']);
  289. return $this->rrSet($packet);
  290. }
  291. /**
  292. * returns a binary packed DNS RR object
  293. *
  294. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet used for
  295. * compressing names
  296. *
  297. * @return string
  298. * @throws Net_DNS2_Exception
  299. * @access public
  300. *
  301. */
  302. public function get(Net_DNS2_Packet &$packet)
  303. {
  304. $data = '';
  305. $rdata = '';
  306. //
  307. // pack the name
  308. //
  309. $data = $packet->compress($this->name, $packet->offset);
  310. //
  311. // pack the main values
  312. //
  313. if ($this->type == 'OPT') {
  314. //
  315. // pre-build the TTL value
  316. //
  317. $this->preBuild();
  318. //
  319. // the class value is different for OPT types
  320. //
  321. $data .= pack(
  322. 'nnN',
  323. Net_DNS2_Lookups::$rr_types_by_name[$this->type],
  324. $this->class,
  325. $this->ttl
  326. );
  327. } else {
  328. $data .= pack(
  329. 'nnN',
  330. Net_DNS2_Lookups::$rr_types_by_name[$this->type],
  331. Net_DNS2_Lookups::$classes_by_name[$this->class],
  332. $this->ttl
  333. );
  334. }
  335. //
  336. // increase the offset, and allow for the rdlength
  337. //
  338. $packet->offset += 10;
  339. //
  340. // get the RR specific details
  341. //
  342. if ($this->rdlength != -1) {
  343. $rdata = $this->rrGet($packet);
  344. }
  345. //
  346. // add the RR
  347. //
  348. $data .= pack('n', strlen($rdata)) . $rdata;
  349. return $data;
  350. }
  351. /**
  352. * parses a binary packet, and returns the appropriate Net_DNS2_RR object,
  353. * based on the RR type of the binary content.
  354. *
  355. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet used for
  356. * decompressing names
  357. *
  358. * @return mixed returns a new Net_DNS2_RR_* object for
  359. * the given RR
  360. * @throws Net_DNS2_Exception
  361. * @access public
  362. *
  363. */
  364. public static function parse(Net_DNS2_Packet &$packet)
  365. {
  366. $object = array();
  367. //
  368. // expand the name
  369. //
  370. $object['name'] = $packet->expand($packet, $packet->offset);
  371. if (is_null($object['name'])) {
  372. throw new Net_DNS2_Exception(
  373. 'failed to parse resource record: failed to expand name.',
  374. Net_DNS2_Lookups::E_PARSE_ERROR
  375. );
  376. }
  377. if ($packet->rdlength < ($packet->offset + 10)) {
  378. throw new Net_DNS2_Exception(
  379. 'failed to parse resource record: packet too small.',
  380. Net_DNS2_Lookups::E_PARSE_ERROR
  381. );
  382. }
  383. //
  384. // unpack the RR details
  385. //
  386. $object['type'] = ord($packet->rdata[$packet->offset++]) << 8 |
  387. ord($packet->rdata[$packet->offset++]);
  388. $object['class'] = ord($packet->rdata[$packet->offset++]) << 8 |
  389. ord($packet->rdata[$packet->offset++]);
  390. $object['ttl'] = ord($packet->rdata[$packet->offset++]) << 24 |
  391. ord($packet->rdata[$packet->offset++]) << 16 |
  392. ord($packet->rdata[$packet->offset++]) << 8 |
  393. ord($packet->rdata[$packet->offset++]);
  394. $object['rdlength'] = ord($packet->rdata[$packet->offset++]) << 8 |
  395. ord($packet->rdata[$packet->offset++]);
  396. if ($packet->rdlength < ($packet->offset + $object['rdlength'])) {
  397. return null;
  398. }
  399. //
  400. // lookup the class to use
  401. //
  402. $o = null;
  403. $class = Net_DNS2_Lookups::$rr_types_id_to_class[$object['type']];
  404. if (isset($class)) {
  405. $o = new $class($packet, $object);
  406. if ($o) {
  407. $packet->offset += $object['rdlength'];
  408. }
  409. } else {
  410. throw new Net_DNS2_Exception(
  411. 'un-implemented resource record type: ' . $object['type'],
  412. Net_DNS2_Lookups::E_RR_INVALID
  413. );
  414. }
  415. return $o;
  416. }
  417. /**
  418. * cleans up some RR data
  419. *
  420. * @param string $data the text string to clean
  421. *
  422. * @return string returns the cleaned string
  423. *
  424. * @access public
  425. *
  426. */
  427. public function cleanString($data)
  428. {
  429. return strtolower(rtrim($data, '.'));
  430. }
  431. /**
  432. * parses a standard RR format lines, as defined by rfc1035 (kinda)
  433. *
  434. * In our implementation, the domain *must* be specified- format must be
  435. *
  436. * <name> [<ttl>] [<class>] <type> <rdata>
  437. * or
  438. * <name> [<class>] [<ttl>] <type> <rdata>
  439. *
  440. * name, title, class and type are parsed by this function, rdata is passed
  441. * to the RR specific classes for parsing.
  442. *
  443. * @param string $line a standard DNS config line
  444. *
  445. * @return mixed returns a new Net_DNS2_RR_* object for the given RR
  446. * @throws Net_DNS2_Exception
  447. * @access public
  448. *
  449. */
  450. public static function fromString($line)
  451. {
  452. if (strlen($line) == 0) {
  453. throw new Net_DNS2_Exception(
  454. 'empty config line provided.',
  455. Net_DNS2_Lookups::E_PARSE_ERROR
  456. );
  457. }
  458. $name = '';
  459. $type = '';
  460. $class = 'IN';
  461. $ttl = 86400;
  462. //
  463. // split the line by spaces
  464. //
  465. $values = preg_split('/[\s]+/', $line);
  466. if (count($values) < 3) {
  467. throw new Net_DNS2_Exception(
  468. 'failed to parse config: minimum of name, type and rdata required.',
  469. Net_DNS2_Lookups::E_PARSE_ERROR
  470. );
  471. }
  472. //
  473. // assume the first value is the name
  474. //
  475. $name = trim(strtolower(array_shift($values)), '.');
  476. //
  477. // The next value is either a TTL, Class or Type
  478. //
  479. foreach ($values as $value) {
  480. switch($value) {
  481. case is_numeric($value):
  482. $ttl = array_shift($values);
  483. break;
  484. //
  485. // PHP SUCKS!
  486. //
  487. case ($value === 0):
  488. $ttl = array_shift($values);
  489. break;
  490. case isset(Net_DNS2_Lookups::$classes_by_name[strtoupper($value)]):
  491. $class = strtoupper(array_shift($values));
  492. break;
  493. case isset(Net_DNS2_Lookups::$rr_types_by_name[strtoupper($value)]):
  494. $type = strtoupper(array_shift($values));
  495. break 2;
  496. break;
  497. default:
  498. throw new Net_DNS2_Exception(
  499. 'invalid config line provided: unknown file: ' . $value,
  500. Net_DNS2_Lookups::E_PARSE_ERROR
  501. );
  502. }
  503. }
  504. //
  505. // lookup the class to use
  506. //
  507. $o = null;
  508. $class_name = Net_DNS2_Lookups::$rr_types_id_to_class[
  509. Net_DNS2_Lookups::$rr_types_by_name[$type]
  510. ];
  511. if (isset($class_name)) {
  512. $o = new $class_name;
  513. if (!is_null($o)) {
  514. //
  515. // set the parsed values
  516. //
  517. $o->name = $name;
  518. $o->class = $class;
  519. $o->ttl = $ttl;
  520. //
  521. // parse the rdata
  522. //
  523. if ($o->rrFromString($values) === false) {
  524. throw new Net_DNS2_Exception(
  525. 'failed to parse rdata for config: ' . $line,
  526. Net_DNS2_Lookups::E_PARSE_ERROR
  527. );
  528. }
  529. } else {
  530. throw new Net_DNS2_Exception(
  531. 'failed to create new RR record for type: ' . $type,
  532. Net_DNS2_Lookups::E_RR_INVALID
  533. );
  534. }
  535. } else {
  536. throw new Net_DNS2_Exception(
  537. 'un-implemented resource record type: '. $type,
  538. Net_DNS2_Lookups::E_RR_INVALID
  539. );
  540. }
  541. return $o;
  542. }
  543. }
  544. /*
  545. * Local variables:
  546. * tab-width: 4
  547. * c-basic-offset: 4
  548. * c-hanging-comment-ender-p: nil
  549. * End:
  550. */
  551. ?>