api.itsatrap.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. <?php
  2. /**
  3. * SNMP traps processing class
  4. */
  5. class ItSaTrap {
  6. /**
  7. * Contains SNMP data log path or
  8. *
  9. * @var string
  10. */
  11. protected $dataSource = '';
  12. /**
  13. * Contains billing.ini config file as key=>value
  14. *
  15. * @var array
  16. */
  17. protected $billingCfg = array();
  18. /**
  19. * Contains default limit of lines received from local data source
  20. *
  21. * @var int
  22. */
  23. protected $lineLimit = 200;
  24. /**
  25. * Contains available trap types as id=>data
  26. *
  27. * @var array
  28. */
  29. protected $allTrapTypes = array();
  30. /**
  31. * System messages object placeholder
  32. *
  33. * @var object
  34. */
  35. protected $messages = '';
  36. /**
  37. * Trap types data model placeholder
  38. *
  39. * @var object
  40. */
  41. protected $trapTypesDb = '';
  42. /**
  43. * key-value storage key of file path/URL of traps source
  44. */
  45. const DATA_SOURCE_KEY = 'ITSATRAPSOURCE';
  46. /**
  47. * key-value storage key of lines parse limit of traps data source
  48. */
  49. const DATA_LINES_KEY = 'ITSATRAPLINES';
  50. /**
  51. * Contains control module basic URL
  52. */
  53. const URL_ME = '?module=itsatrap';
  54. /**
  55. * Contains configuration controller URL
  56. */
  57. const URL_CONFIG = '&config=true';
  58. /**
  59. * Contains raw data controller URL
  60. */
  61. const URL_RAW = '&rawdata=true';
  62. /**
  63. * Contains processed data controller URL
  64. */
  65. const URL_AJTRAPS = '&ajaxtrapslist=true';
  66. /**
  67. * Contains siwtch by IP search URL
  68. */
  69. const URL_SWITCHSRCH = '?module=switches&gotoswitchbyip=';
  70. /**
  71. * Contains database table name of available trap types settings
  72. */
  73. const TABLE_TYPES = 'traptypes';
  74. public function __construct() {
  75. $this->loadConfig();
  76. $this->initMessages();
  77. $this->initTrapTypesDb();
  78. $this->loadTrapTypes();
  79. }
  80. /**
  81. * Loads some configuration files and options for further usage
  82. *
  83. * @return void
  84. */
  85. protected function loadConfig() {
  86. global $ubillingConfig;
  87. $this->dataSource = zb_StorageGet(self::DATA_SOURCE_KEY);
  88. $lineLimitCfg = zb_StorageGet(self::DATA_LINES_KEY);
  89. if (!empty($lineLimitCfg)) {
  90. $this->lineLimit = $lineLimitCfg;
  91. }
  92. $this->billingCfg = $ubillingConfig->getBilling();
  93. }
  94. /**
  95. * Inits system messages object
  96. *
  97. * @return void
  98. */
  99. protected function initMessages() {
  100. $this->messages = new UbillingMessageHelper();
  101. }
  102. /**
  103. * Inits trap types data model in protected property for further usage
  104. *
  105. * @return void
  106. */
  107. protected function initTrapTypesDb() {
  108. $this->trapTypesDb = new NyanORM(self::TABLE_TYPES);
  109. }
  110. /**
  111. * Loads existing SNMP trap types configuration from database
  112. *
  113. * @return void
  114. */
  115. protected function loadTrapTypes() {
  116. $this->allTrapTypes = $this->trapTypesDb->getAll('id');
  117. }
  118. /**
  119. * Returns raw data from data source if defined
  120. *
  121. * @return string
  122. */
  123. public function getRawData() {
  124. $result = '';
  125. if (!empty($this->dataSource)) {
  126. if (ispos($this->dataSource, 'http')) {
  127. $result = file_get_contents($this->dataSource);
  128. } else {
  129. if (file_exists($this->dataSource)) {
  130. $command = $this->billingCfg['SUDO'] . ' ' . $this->billingCfg['TAIL'] . ' -n ' . $this->lineLimit . ' ' . $this->dataSource;
  131. $result = shell_exec($command);
  132. }
  133. }
  134. }
  135. return($result);
  136. }
  137. /**
  138. * Checks availability of datasource and display some error notices on error
  139. *
  140. * @return
  141. */
  142. public function renderDataSourceCheck() {
  143. if (!empty($this->dataSource)) {
  144. if (ispos($this->dataSource, 'http')) {
  145. //remote source
  146. @$remoteResult = file_get_contents($this->dataSource);
  147. if (empty($remoteResult)) {
  148. show_warning(__('Result') . ' ' . __('from') . ' ' . $this->dataSource . ' ' . __('is empty'));
  149. }
  150. } else {
  151. if (!file_exists($this->dataSource)) {
  152. show_error(__('File not exist') . ': ' . $this->dataSource);
  153. }
  154. }
  155. } else {
  156. show_warning(__('Data source file path or URL') . ' ' . __('is empty'));
  157. }
  158. }
  159. /**
  160. * Returns module configuration form
  161. *
  162. * @return string
  163. */
  164. public function renderConfigForm() {
  165. $result = '';
  166. $inputs = wf_TextInput('newdatasource', __('Data source file path or URL'), $this->dataSource, true, 40);
  167. $inputs .= wf_TextInput('newlineslimit', __('Lines limit for processing'), $this->lineLimit, true, 4, 'digits');
  168. $inputs .= wf_delimiter(0);
  169. $inputs .= wf_Submit(__('Save'));
  170. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  171. return($result);
  172. }
  173. /**
  174. * Saves data source configuration if its changed
  175. *
  176. * @return void
  177. */
  178. public function saveBasicConfig() {
  179. $newDataSource = ubRouting::post('newdatasource', 'mres');
  180. if ($newDataSource != $this->dataSource) {
  181. zb_StorageSet(self::DATA_SOURCE_KEY, $newDataSource);
  182. log_register('ITSATRAP CHANGE DATASOURCE');
  183. }
  184. $newLinesLimit = ubRouting::post('newlineslimit', 'int');
  185. if ($newLinesLimit != $this->lineLimit) {
  186. zb_StorageSet(self::DATA_LINES_KEY, $newLinesLimit);
  187. log_register('ITSATRAP CHANGE LIMIT `' . $newLinesLimit . '`');
  188. }
  189. }
  190. /**
  191. * Renders available trap types list with some controls
  192. *
  193. * @return string
  194. */
  195. public function renderTrapTypesList() {
  196. $result = '';
  197. if (!empty($this->allTrapTypes)) {
  198. $cells = wf_TableCell('ID');
  199. $cells .= wf_TableCell(__('Name'));
  200. $cells .= wf_TableCell(__('Filter'));
  201. $cells .= wf_TableCell(__('Color'));
  202. $cells .= wf_TableCell(__('Actions'));
  203. $rows = wf_TableRow($cells, 'row1');
  204. foreach ($this->allTrapTypes as $io => $each) {
  205. $cells = wf_TableCell($each['id']);
  206. $cells .= wf_TableCell($each['name']);
  207. $cells .= wf_TableCell($each['match']);
  208. $cells .= wf_TableCell($this->colorize($each['color'], $each['color']));
  209. $trapControls = wf_JSAlert(self::URL_ME . self::URL_CONFIG . '&deletetrapid=' . $each['id'], web_delete_icon(), $this->messages->getDeleteAlert()) . ' ';
  210. $trapControls .= wf_modalAuto(web_edit_icon(), __('Edit') . ' ' . $each['name'], $this->renderTrapEditForm($each['id']));
  211. $cells .= wf_TableCell($trapControls);
  212. $rows .= wf_TableRow($cells, 'row5');
  213. }
  214. $result .= wf_TableBody($rows, '100%', 0, 'sortable');
  215. } else {
  216. $result .= $this->messages->getStyledMessage(__('Nothing to show'), 'warning');
  217. }
  218. return($result);
  219. }
  220. /**
  221. * Performs data coloring if some custom color set
  222. *
  223. * @param string $data
  224. * @param string $color
  225. *
  226. * @return string
  227. */
  228. protected function colorize($data, $color = '') {
  229. $result = $data;
  230. if (!empty($color)) {
  231. $result = wf_tag('font', false, '', 'color="' . $color . '"') . $data . wf_tag('font', true);
  232. }
  233. return($result);
  234. }
  235. /**
  236. * Render new trap type creation form
  237. *
  238. * @return string
  239. */
  240. public function renderTrapCreateForm() {
  241. $result = '';
  242. $inputs = wf_TextInput('newname', __('Name'), '', true, 20);
  243. $inputs .= wf_TextInput('newmatch', __('Filter'), '', true, 20);
  244. $inputs .= wf_ColPicker('newcolor', __('Color'), '', true, 8);
  245. $inputs .= wf_delimiter(0);
  246. $inputs .= wf_Submit(__('Create'));
  247. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  248. return($result);
  249. }
  250. /**
  251. * Renders existing trap type editing form
  252. *
  253. * @param int $trapTypeId
  254. *
  255. * @return string
  256. */
  257. protected function renderTrapEditForm($trapTypeId) {
  258. $result = '';
  259. if (isset($this->allTrapTypes[$trapTypeId])) {
  260. $trapData = $this->allTrapTypes[$trapTypeId];
  261. $inputs = wf_HiddenInput('edittraptypeid', $trapTypeId);
  262. $inputs .= wf_TextInput('editname', __('Name'), $trapData['name'], true, 20);
  263. $inputs .= wf_TextInput('editmatch', __('Filter'), $trapData['match'], true, 20);
  264. $inputs .= wf_TextInput('editcolor', __('Color'), $trapData['color'], true, 8); //some issues with colpicker in modal windows
  265. $inputs .= wf_delimiter(0);
  266. $inputs .= wf_Submit(__('Save'));
  267. $result .= wf_Form('', 'POST', $inputs, 'glamour');
  268. }
  269. return($result);
  270. }
  271. /**
  272. * Creates new trap type in database
  273. *
  274. * @return void
  275. */
  276. public function createTrapType() {
  277. if (ubRouting::checkPost(array('newname', 'newmatch', 'newcolor'))) {
  278. $newNameF = ubRouting::post('newname', 'mres');
  279. $newMatchF = ubRouting::post('newmatch', 'mres');
  280. $newColorF = ubRouting::post('newcolor', 'mres');
  281. $this->trapTypesDb->data('match', $newMatchF);
  282. $this->trapTypesDb->data('name', $newNameF);
  283. $this->trapTypesDb->data('color', $newColorF);
  284. $this->trapTypesDb->create();
  285. $newId = $this->trapTypesDb->getLastId();
  286. log_register('ITSATRAP CREATE TRAPTYPE [' . $newId . '] `' . ubRouting::post('newname') . '`');
  287. }
  288. }
  289. /**
  290. * Saves existing trap type changes into database
  291. *
  292. * @return void
  293. */
  294. public function saveTrapType() {
  295. if (ubRouting::checkPost(array('edittraptypeid', 'editname', 'editmatch', 'editcolor'))) {
  296. $editId = ubRouting::post('edittraptypeid', 'int');
  297. if (isset($this->allTrapTypes[$editId])) {
  298. $newNameF = ubRouting::post('editname', 'mres');
  299. $newMatchF = ubRouting::post('editmatch', 'mres');
  300. $newColorF = ubRouting::post('editcolor', 'mres');
  301. $this->trapTypesDb->data('match', $newMatchF);
  302. $this->trapTypesDb->data('name', $newNameF);
  303. $this->trapTypesDb->data('color', $newColorF);
  304. $this->trapTypesDb->where('id', '=', $editId);
  305. $this->trapTypesDb->save();
  306. log_register('ITSATRAP CHANGE TRAPTYPE [' . $editId . ']');
  307. }
  308. }
  309. }
  310. /**
  311. * Deletes existing trap type from database
  312. *
  313. * @param int $trapTypeId
  314. *
  315. * @return void/string on error
  316. */
  317. public function deleteTrapType($trapTypeId) {
  318. $result = '';
  319. $trapTypeId = ubRouting::filters($trapTypeId, 'int');
  320. if (isset($this->allTrapTypes[$trapTypeId])) {
  321. $this->trapTypesDb->where('id', ' = ', $trapTypeId);
  322. $this->trapTypesDb->delete();
  323. log_register('ITSATRAP DELETE TRAPTYPE [' . $trapTypeId . ']');
  324. } else {
  325. $result .= __('Something went wrong') . ': EX_TRAPID_NOT_EXISTS';
  326. }
  327. return($result);
  328. }
  329. /**
  330. * Renders module control panel
  331. *
  332. * @return string
  333. */
  334. public function renderControls() {
  335. $result = '';
  336. $result .= wf_Link(self::URL_ME, web_icon_search() . ' ' . __('Events'), false, 'ubButton') . ' ';
  337. if (cfr('ITSATRAPCFG')) {
  338. $result .= wf_Link(self::URL_ME . self::URL_RAW, wf_img('skins/icon_raw.gif') . ' ' . __('RAW') . ' ' . __('Data'), false, 'ubButton') . ' ';
  339. $result .= wf_Link(self::URL_ME . self::URL_CONFIG, web_icon_extended() . ' ' . __('Settings'), false, 'ubButton') . ' ';
  340. }
  341. return($result);
  342. }
  343. /**
  344. * Renders raw data received from data source
  345. *
  346. * @return string
  347. */
  348. public function renderRawData() {
  349. $result = '';
  350. $lineCount = 0;
  351. if (!empty($this->dataSource)) {
  352. $rawData = $this->getRawData();
  353. if (!empty($rawData)) {
  354. $rawData = explodeRows($rawData);
  355. $cells = wf_TableCell(__('Number'));
  356. $cells .= wf_TableCell(__('Data'));
  357. $rows = wf_TableRow($cells, 'row1');
  358. foreach ($rawData as $io => $eachLine) {
  359. if (!empty($eachLine)) {
  360. $cells = wf_TableCell($lineCount);
  361. $cells .= wf_TableCell($eachLine);
  362. $rows .= wf_TableRow($cells, 'row5');
  363. $lineCount++;
  364. }
  365. }
  366. $result = wf_TableBody($rows, '100%', 0, 'sortable');
  367. }
  368. } else {
  369. $result .= $this->messages->getStyledMessage(__('Data source file path or URL') . ' ' . __('is empty'), 'error');
  370. }
  371. return($result);
  372. }
  373. /**
  374. * Renders preprocessed trap events container
  375. *
  376. * @return string
  377. */
  378. public function renderTrapEventsList() {
  379. $result = '';
  380. if (!empty($this->dataSource)) {
  381. $columns = array('Date', 'IP', 'Event', 'Actions');
  382. $opts = '"order": [[ 0, "desc" ]]';
  383. $result .= wf_JqDtLoader($columns, self::URL_ME . self::URL_AJTRAPS, false, __('Events'), 100, $opts);
  384. } else {
  385. $result .= $this->messages->getStyledMessage(__('Data source file path or URL') . ' ' . __('is empty'), 'error');
  386. }
  387. return($result);
  388. }
  389. /**
  390. * Returns preprocessed current trap events data
  391. *
  392. * @return void
  393. */
  394. public function ajTrapList() {
  395. $json = new wf_JqDtHelper();
  396. $rawData = $this->getRawData();
  397. $data = array();
  398. if (!empty($rawData)) {
  399. $rawData = explodeRows($rawData);
  400. if (!empty($rawData)) {
  401. foreach ($rawData as $io => $eachLine) {
  402. if (!empty($eachLine)) {
  403. $ip = zb_ExtractIpAddress($eachLine);
  404. if (!empty($ip)) {
  405. $line = explode(' ', $eachLine);
  406. $dateF = $line[0] . ' ' . $line[1];
  407. $dateF = trim($dateF);
  408. if (@zb_checkDate($line[0])) {
  409. //ok seems it normal log trap record
  410. if (!empty($this->allTrapTypes)) {
  411. foreach ($this->allTrapTypes as $ia => $eachTrapType) {
  412. if (ispos($eachLine, $eachTrapType['match'])) {
  413. $data[] = $dateF;
  414. $ipControls = '';
  415. $ipControls .= wf_Link(self::URL_SWITCHSRCH . $ip, web_edit_icon(__('Go to switch')));
  416. $ipControls .= wf_Link('http://' . $ip, wf_img('skins/ymaps/globe.png', __('Go to the web interface')), false, '', 'target="_BLANK"') . ' ';
  417. $data[] = $ip;
  418. $data[] = $this->colorize($eachTrapType['name'], $eachTrapType['color']);
  419. $data[] = $ipControls;
  420. $json->addRow($data);
  421. unset($data);
  422. }
  423. }
  424. }
  425. }
  426. }
  427. }
  428. }
  429. }
  430. }
  431. $json->getJson();
  432. }
  433. // __...------------._
  434. // ,-' `-.
  435. // ,-' `.
  436. // ,' ,-`.
  437. // ; `-' `.
  438. // ; .-. \
  439. // ; .-. `-' \
  440. // ; `-' \
  441. // ; `.
  442. // ; :
  443. // ; |
  444. // ; ;
  445. // ; ___ ;
  446. // ; ,-;-','.`.__ |
  447. // _..; ,-' ;`,'.`,'.--`. |
  448. // ///; ,-' `. ,-' ;` ;`,','_.--=: /
  449. // |'': ,' : ;` ;,;,,-'_.-._`. ,'
  450. // ' : ;_.-. `. :' ;;;'.ee. \| /
  451. // \.' _..-'/8o. `. : :! ' ':8888) || /
  452. // ||`-'' \\88o\ : : :! : :`""' ;;/
  453. // || \"88o\; `. \ `. `. ;,'
  454. // /) ___ `."'/(--.._ `. `.`. `-..-' ;--.
  455. // \(.="""""==.. `'-' `.| `-`-..__.-' `. `.
  456. // | `"==.__ ) ) ;
  457. // | || `"=== ' .' .'
  458. // /\,,|||| | | \ .' .'
  459. // | |||'|' |'|' \| .' _.' \
  460. // | |\' | | || || .' .' \
  461. // ' | \ ' |' . ``-- `| || .' .' \
  462. // ' | ' | . ``-.._ | ; .' .' `.
  463. // _.--,;`. . -- ...._,' .' .' `.__
  464. // ,' ,'; `. . --..__..--'.' .' __/_\
  465. // ,' ; ; | . --..__.._.' .' ,' `.
  466. // / ; : ; . -.. _.' _.' / `
  467. // / : `-._ | . _.--' _.' |
  468. /// `. `--....--'' _.' |
  469. // `._ _..-' |
  470. // `-..____...-'' |
  471. // |
  472. /**
  473. * Returns preprocessed last traps of some type acceptable for watchdog monitoring / telegram sending
  474. *
  475. * @param string/array $trapId
  476. * @param int $count
  477. *
  478. * @return string
  479. */
  480. public function getLastTraps($trapId, $count) {
  481. $rawData = $this->getRawData();
  482. $trapsTmp = array();
  483. $trapFilters = array();
  484. $result = '' . '\r\n';
  485. //trapId may be integer/string or array
  486. $trapFilters = (is_array($trapId)) ? array_flip($trapId) : array($trapId => 'onlyou');
  487. if (!empty($rawData)) {
  488. $rawData = explodeRows($rawData);
  489. if (!empty($rawData)) {
  490. foreach ($rawData as $io => $eachLine) {
  491. if (!empty($eachLine)) {
  492. $ip = zb_ExtractIpAddress($eachLine);
  493. if (!empty($ip)) {
  494. $line = explode(' ', $eachLine);
  495. $dateF = $line[0] . ' ' . $line[1];
  496. $dateF = trim($dateF);
  497. if (@zb_checkDate($line[0])) {
  498. //ok seems it normal log trap record
  499. if (!empty($this->allTrapTypes)) {
  500. foreach ($this->allTrapTypes as $ia => $eachTrapType) {
  501. if (ispos($eachLine, $eachTrapType['match'])) {
  502. if (isset($trapFilters[$eachTrapType['id']])) {
  503. //only required types
  504. $trapsTmp[] = $dateF . ' ' . $eachTrapType['name'] . ' ' . $ip . '\r\n';
  505. }
  506. }
  507. }
  508. }
  509. }
  510. }
  511. }
  512. }
  513. }
  514. if (!empty($trapsTmp)) {
  515. $trapsCount = sizeof($trapsTmp);
  516. $i = 0;
  517. $showLast = $trapsCount - $count;
  518. foreach ($trapsTmp as $io => $each) {
  519. if ($i >= $showLast) {
  520. $result .= $each;
  521. }
  522. $i++;
  523. }
  524. }
  525. }
  526. return($result);
  527. }
  528. }