Source for file mib_compiler.php

Documentation is available at mib_compiler.php

  1. <?php
  2. /**
  3. * phpsnmp - a PHP SNMP library
  4. *
  5. * Copyright (C) 2004 David Eder <david@eder,us>
  6. *
  7. * Based on snmp - a Python SNMP library
  8. * Copyright (C) 2003 Unicity Pty Ltd <libsnmp@unicity.com.au>
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. * @author David Eder <david@eder.us>
  25. * @copyright 2004 David Eder
  26. * @package phpSNMP
  27. * @subpackage mib_compiler
  28. * @version .7
  29. */
  30.  
  31. /**
  32. */
  33.  
  34. set_time_limit(0);
  35. ini_set('memory_limit', '256M');
  36. error_reporting(E_ALL);
  37.  
  38. $mc = new mib_compiler();
  39. $mc->add_mibs('/usr/share/snmp/mibs');
  40. $mc->compile();
  41.  
  42. /**
  43. * Asn1Objects
  44. *
  45. * Base class for all Asn1Objects. This is only intended to support a specific subset of ASN1 stuff as
  46. * defined by the RFCs to keep things as simple as possible.
  47. *
  48. * @package phpSNMP
  49. * @subpackage mib_compiler
  50. */
  51. class mib_compiler
  52. {
  53. var $parsed = array();
  54. var $outfile = 'oid_format.data';
  55.  
  56. /**
  57. * Constructor
  58. */
  59. function mib_compiler()
  60. {
  61. }
  62.  
  63. /**
  64. * Add mibs
  65. *
  66. * @param string $path
  67. */
  68. function add_mibs($path)
  69. {
  70. foreach(glob("$path/*") as $mib)
  71. {
  72. if(is_dir($mib))
  73. $this->add_mibs($mib);
  74. else
  75. $this->add_mib($mib);
  76. }
  77. }
  78.  
  79. /**
  80. * Add a mib
  81. *
  82. * @param string $filename
  83. */
  84. function add_mib($filename)
  85. {
  86. echo "Loading $filename\n";
  87. $this->parse(file_get_contents($filename));
  88. }
  89.  
  90. /**
  91. * Compile mibs
  92. */
  93. function compile()
  94. {
  95. echo 'Found ' . count($this->parsed) . " objects\n";
  96. echo "Building node list\n";
  97.  
  98. $nodes[''] = array(1=>'iso');
  99. $found['iso'] = 1;
  100. $found[''] = 1;
  101. foreach($this->parsed as $obj)
  102. {
  103. if(isset($obj['VALUE'][0]) && !is_numeric($obj['VALUE'][0]))
  104. {
  105. if(isset($obj['VALUE'][1]) && is_numeric($obj['VALUE'][1]))
  106. {
  107. $nodes[$obj['VALUE'][0]][$obj['VALUE'][1]] = $obj['NAME'];
  108. $found[$obj['NAME']] = 1;
  109. }
  110. }
  111. }
  112.  
  113. echo "Trimming disconnected nodes\n";
  114. foreach(array_keys($nodes) as $key)
  115. {
  116. if(!isset($found[$key]))
  117. {
  118. echo "deleting $key\n";
  119. unset($nodes[$key]);
  120. }
  121. }
  122.  
  123. echo "Writing {$this->outfile}\n";
  124. $fp = fopen($this->outfile, 'w');
  125. fputs($fp, serialize($nodes));
  126. fclose($fp);
  127. }
  128.  
  129. // // // // // // // // //
  130. // NOTHING PUBLIC BELOW //
  131. // // // // // // // // //
  132.  
  133. /**
  134. * Parse a MIB file
  135. *
  136. * @param string $mibtext
  137. * @param boolean $full
  138. */
  139. function parse($mibtext, $full=false)
  140. {
  141. $tokens = $this->get_tokens($mibtext);
  142. $cnt = count($tokens);
  143. echo "Found $cnt tokens\n";
  144. $rec = array();
  145. for($index = 0; $index < $cnt; $index++)
  146. {
  147. echo number_format(100 *$index / $cnt, 2) . "% \r";
  148. if($tokens[$index] == 'OBJECT-IDENTITY' || $tokens[$index] == 'OBJECT-TYPE' || $tokens[$index] == 'MODULE-IDENTITY')
  149. {
  150. if($tokens[$index-1] != ',' && $tokens[$index+1] != 'FROM' && $tokens[$index+1] != 'MACRO')
  151. {
  152. if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
  153. $rec = array('NAME'=>$tokens[$index-1]);
  154. }
  155. }
  156. elseif($tokens[$index] == 'OBJECT')
  157. {
  158. if($tokens[$index+1] == 'IDENTIFIER' && $tokens[$index-1] != '(' && $tokens[$index-1] != '::=' && $tokens[$index-1] != 'SYNTAX' && $tokens[$index-2] != '(')
  159. {
  160. if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
  161. $rec = array('NAME'=>$tokens[$index-1]);
  162. }
  163. }
  164. elseif($tokens[$index] == '{')
  165. $this->parse_bracket_token($tokens, $index, '{', '}');
  166. elseif(isset($rec['NAME']))
  167. {
  168. if($tokens[$index] == '::=')
  169. {
  170. $rec['VALUE'] = $this->parse_simple_token($tokens, $index);
  171. $this->parsed[] = $rec;
  172. $rec = array();
  173. }
  174. elseif($full)
  175. {
  176. if($tokens[$index] == 'ACCESS')
  177. $rec['ACCESS'] = $this->parse_simple_token($tokens, $index, array('read-only', 'not-accessible', 'read-write'));
  178. elseif($tokens[$index] == 'DEFVAL')
  179. $rec['DEFVAL'] = $this->parse_simple_token($tokens, $index);
  180. elseif($tokens[$index] == 'DESCRIPTION')
  181. $rec['DESCRIPTION'] = $tokens[++$index];
  182. elseif($tokens[$index] == 'INDEX')
  183. $rec['INDEX'] = $this->parse_simple_token($tokens, $index);
  184. elseif($tokens[$index] == 'MAX-ACCESS')
  185. $rec['MAX-ACCESS'] = $this->parse_simple_token($tokens, $index, array('read-only', 'not-accessible', 'read-write', 'read-create', 'accessible-for-notify'));
  186. elseif($tokens[$index] == 'REFERENCE')
  187. $rec['REFERENCE'] = $this->parse_simple_token($tokens, $index);
  188. elseif($tokens[$index] == 'STATUS')
  189. $rec['STATUS'] = $this->parse_simple_token($tokens, $index, array('current', 'deprecated', 'obsolete', 'mandatory'));
  190. elseif($tokens[$index] == 'SYNTAX')
  191. $rec['SYNTAX'] = $this->parse_SYNTAX_token($tokens, $index);
  192. elseif($tokens[$index] == 'UNITS')
  193. $rec['UNITS'] = $this->parse_simple_token($tokens, $index);
  194. }
  195. }
  196. }
  197. echo number_format(100, 2) . "% \r";
  198. if(isset($rec['NAME']) && isset($rec['VALUE'])) $this->parsed[] = $rec;
  199. }
  200.  
  201. /**
  202. * Get Tokens
  203. *
  204. * @param string $text
  205. * @return array
  206. */
  207. function get_tokens($text)
  208. {
  209. $in_quote = false;
  210. $in_comment = false;
  211. $token = '';
  212. $tokens = array();
  213. $length = strlen($text);
  214. for($i = 0; $i < $length; $i++)
  215. {
  216. if($in_quote)
  217. {
  218. if($text{$i} == '"')
  219. {
  220. $in_quote = false;
  221. if($token != '')
  222. {
  223. $tokens[] = $token;
  224. $token = '';
  225. }
  226. }
  227. else
  228. $token .= $text{$i};
  229. }
  230. elseif($in_comment)
  231. {
  232. if($text{$i} == "\n" || $text{$i} == "\r")
  233. $in_comment = false;
  234. }
  235. else
  236. {
  237. switch($text{$i})
  238. {
  239. case ':':
  240. if($text{$i+1} == ':' && $text{$i+2} == '=')
  241. {
  242. if($token != '')
  243. {
  244. $tokens[] = $token;
  245. $token = '';
  246. }
  247. $tokens[] = '::=';
  248. $i += 2;
  249. }
  250. else
  251. $token .= $text{$i};
  252. break;
  253. case '.':
  254. if($text{$i+1} == '.')
  255. {
  256. if($token != '')
  257. {
  258. $tokens[] = $token;
  259. $token = '';
  260. }
  261. $tokens[] = '..';
  262. $i++;
  263. }
  264. else
  265. $token .= $text{$i};
  266. break;
  267. case ',':
  268. case ';':
  269. case '{':
  270. case '}':
  271. case '(':
  272. case ')':
  273. case '|':
  274. if($token != '')
  275. {
  276. $tokens[] = $token;
  277. $token = '';
  278. }
  279. $tokens[] = $text{$i};
  280. break;
  281. case ' ':
  282. case "\t":
  283. case "\n":
  284. case "\r":
  285. if($token != '')
  286. {
  287. $tokens[] = $token;
  288. $token = '';
  289. }
  290. break;
  291. case '-':
  292. if($text{$i+1} == '-')
  293. $in_comment = true;
  294. else
  295. $token .= $text{$i};
  296. break;
  297. case '"';
  298. $in_quote = true;
  299. break;
  300. default:
  301. $token .= $text{$i};
  302. }
  303. }
  304. }
  305. if($token != '')
  306. $tokens[] = $token;
  307. return $tokens;
  308. }
  309.  
  310. /**
  311. * Parse simple token
  312. *
  313. * @param array $tokens
  314. * @param integer $index
  315. * @param array $allowed
  316. * @return array
  317. */
  318. function parse_simple_token($tokens, &$index, $allowed=NULL)
  319. {
  320. if(is_array($allowed))
  321. {
  322. if(in_array(strtolower($tokens[$index+1]), $allowed))
  323. return $tokens[++$index];
  324. }
  325. elseif(is_null($allowed))
  326. {
  327. if($tokens[$index+1] == '{')
  328. return $this->parse_bracket_token($tokens, ++$index, '{', '}');
  329. else
  330. return $tokens[++$index];
  331. }
  332. trigger_error("unknown token {$tokens[$index]} {$tokens[$index+1]}", E_USER_ERROR);
  333. return $tokens[++$index];
  334. }
  335.  
  336. /**
  337. * Parse SYNTAX token
  338. *
  339. * @param array $tokens
  340. * @param integer $index
  341. * @return array
  342. */
  343. function parse_SYNTAX_token($tokens, &$index)
  344. {
  345. $ret = NULL;
  346. switch($tokens[$index+1])
  347. {
  348. case 'SEQUENCE':
  349. if($tokens[$index+2] == 'OF')
  350. {
  351. $index += 2;
  352. if($tokens[$index+1] == '{')
  353. $ret = array('SEQUENCE OF'=>$this->parse_bracket_token($tokens, ++$index, '{', '}'));
  354. else
  355. $ret = array('SEQUENCE OF'=>$tokens[++$index]);
  356. }
  357. break;
  358. case 'OCTET':
  359. if($tokens[$index+2] == 'STRING')
  360. {
  361. $index += 2;
  362. if($tokens[$index+1] == '{')
  363. $ret = array('OCTET STRING'=>$this->parse_bracket_token($tokens, ++$index, '{', '}'));
  364. elseif($tokens[$index+1] == '(')
  365. $ret = array('OCTET STRING'=>$this->parse_bracket_token($tokens, ++$index, '(', ')'));
  366. else
  367. $ret = 'OCTET STRING';
  368. }
  369. break;
  370. case 'OBJECT':
  371. if($tokens[$index+2] == 'IDENTIFIER')
  372. $ret = $tokens[++$index] . ' ' . $tokens[++$index];
  373. else
  374. trigger_error("unknown token {$tokens[$index+1]} {$tokens[$index+2]}", E_USER_ERROR);
  375. break;
  376. case 'INTEGER':
  377. case 'Counter':
  378. case 'Counter32':
  379. case 'Counter64':
  380. case 'Integer32':
  381. case 'Gauge':
  382. case 'Gauge32':
  383. case 'TimeStamp':
  384. case 'TimeTicks':
  385. case 'PhysAddress':
  386. case 'IpAddress':
  387. case 'DateAndTime':
  388. case 'TimeInterval':
  389. case 'Unsigned32':
  390. case 'DisplayString':
  391. $ret = $tokens[++$index];
  392. if($tokens[$index+1] == '{')
  393. $ret = array($ret=>$this->parse_bracket_token($tokens, ++$index, '{', '}'));
  394. elseif($tokens[$index+1] == '(')
  395. $ret = array($ret=>$this->parse_bracket_token($tokens, ++$index, '(', ')'));
  396. break;
  397. default:
  398. $ret = $tokens[++$index];
  399. if($tokens[$index+1] == '{')
  400. $ret = array($ret=>$this->parse_bracket_token($tokens, ++$index, '{', '}'));
  401. elseif($tokens[$index+1] == '(')
  402. $ret = array($ret=>$this->parse_bracket_token($tokens, ++$index, '(', ')'));
  403. break;
  404. }
  405. return $ret;
  406. }
  407.  
  408. /**
  409. * Parse bracket token
  410. *
  411. * @param array $tokens
  412. * @param integer $index
  413. * @param integer $start
  414. * @param integer $end
  415. * @return array
  416. */
  417. function parse_bracket_token($tokens, &$index, $start, $end)
  418. {
  419. $begin = $index + 1;
  420. while($index + 1 < count($tokens) && $tokens[$index] != $end)
  421. {
  422. $index++;
  423. if($tokens[$index] == $start)
  424. {
  425. $this->parse_bracket_token($tokens, $index, $start, $end);
  426. $index++;
  427. }
  428. }
  429. return array_slice($tokens, $begin, $index - $begin);
  430. }
  431. }

Documentation generated on Mon, 14 Nov 2005 17:54:52 -0700 by phpDocumentor 1.3.0RC3