source: trunk/src/inc/KMLFile.class.php@ 7776

Last change on this file since 7776 was 7776, checked in by Pieter Naber, 15 years ago

Oke... Couldn't resist it... Found the "Nodes in the ocean" bug and we have green placemarkers in the KML file :-)
See example.kml

  • Property svn:eol-style set to native
File size: 15.5 KB
Line 
1<?php
2/*
3 * Project: NodeMap2.0
4 * File: KMLHandler.class.php
5 * Purpose: Creating of editing KML files
6 */
7
8define('NODE_STATUS_UP', 0);
9define('NODE_STATUS_ERROR', 1);
10define('NODE_STATUS_UNREACHABLE', 2);
11
12class KMLFile {
13 private $template = '
14 <kml xmlns="http://www.opengis.net/kml/2.2">
15 <Document>
16 <name>Wireless Leiden Interactive Nodemap 2.0</name>
17 <open>1</open>
18 <description>Wireless Leiden Interactive Nodemap 2.0</description>
19 <LookAt>
20 <longitude>%OVERALL_LONGITUDE%</longitude>
21 <latitude>%OVERALL_LATITUDE%</latitude>
22 <altitude>%OVERALL_ALTITUDE%</altitude>
23 <heading>%OVERALL_HEADING%</heading>
24 <tilt>%OVERALL_TILT%</tilt>
25 <range>%OVERALL_RANGE%</range>
26 </LookAt>
27 <Style id="blackLine">
28 <LineStyle>
29 <color>%LINE_BLACK%</color>
30 <width>3</width>
31 </LineStyle>
32 </Style>
33 <Style id="greenArrowIcon">
34 <IconStyle>
35 <Icon>
36 <href>%NODE_GREEN%</href>
37 </Icon>
38 </IconStyle>
39 </Style>
40 <Style id="orangeArrowIcon">
41 <IconStyle>
42 <Icon>
43 <href>%NODE_ORANGE%</href>
44 </Icon>
45 </IconStyle>
46 </Style>
47 <Style id="redArrowIcon">
48 <IconStyle>
49 <Icon>
50 <href>%NODE_RED%</href>
51 </Icon>
52 </IconStyle>
53 </Style>
54 <Folder id="nodes">
55 <name>Nodes</name>
56 <description>Nodes from the Wireless Leiden network</description>
57 <LookAt>
58 <longitude>%OVERALL_LONGITUDE%</longitude>
59 <latitude>%OVERALL_LATITUDE%</latitude>
60 <altitude>%OVERALL_ALTITUDE%</altitude>
61 <heading>%OVERALL_HEADING%</heading>
62 <tilt>%OVERALL_TILT%</tilt>
63 <range>%OVERALL_RANGE%</range>
64 </LookAt>
65 %NODESCONTENT%
66 </Folder>
67 <Folder id="lines">
68 <name>Lines</name>
69 <description>Lines from nodes to nodes from the Wireless Leiden network</description>
70 <LookAt>
71 <longitude>%OVERALL_LONGITUDE%</longitude>
72 <latitude>%OVERALL_LATITUDE%</latitude>
73 <altitude>%OVERALL_ALTITUDE%</altitude>
74 <heading>%OVERALL_HEADING%</heading>
75 <tilt>%OVERALL_TILT%</tilt>
76 <range>%OVERALL_RANGE%</range>
77 </LookAt>
78 %LINESCONTENT%
79 </Folder>
80 </Document>
81 </kml>';
82
83 // First line of the status file must be like this:
84 static $fileFirst = 'type,host_name,has_been_checked,check_execution_time,current_state,last_hard_state,last_check,problem_has_been_acknowledged';
85 // Every following line will be checked using these functions
86 private $fileContent = array('string', 'string', 'int', 'double', 'int', 'int', 'int', 'int');
87
88 private $KMLNodes;
89 private $KMLLines;
90 private $NetworkList;
91
92 /*
93 * Function: __construct (constructor)
94 * Description: Creating a new KMLFile
95 * Parameters: -
96 * Returns: -
97 */
98 public function __construct() {
99 $this->KMLNodes = array();
100 $this->KMLLines = array();
101 $this->NetworkList = new NetworkList();
102 }
103
104 /*
105 * Function: addNode
106 * Description: Add a node to the local node array
107 * Parameters: KMLNode $node
108 * Returns: -
109 */
110 public function addNode(KMLNode $node) {
111 $this->KMLNodes[] = $node;
112 }
113
114 /*
115 * Function: addLIne
116 * Description: Add a line to the local line array
117 * Parameters: KMLLine $line
118 * Returns: -
119 */
120 public function addLine(KMLLine $line) {
121 $this->KMLLines[] = $line;
122 }
123
124 /*
125 * Function: toString
126 * Description: Converts the content of this file and the placemarks to a KML valid string
127 * Parameters: -
128 * Returns: KML valid string
129 */
130 public function toString() {
131 global $config;
132
133 $toString = $this->template;
134
135 // Add all nodes to the string
136 $nodeString = '';
137 $nodeCount = count($this->KMLNodes);
138 for ($i = 0; $i < $nodeCount; $i++) {
139 $nodeString .= $this->KMLNodes[$i]->toString();
140 }
141
142 // Add all connected lines to the string
143 $lineString = '';
144 $lineCount = count($this->KMLLines);
145 for ($i = 0; $i < $lineCount; $i++) {
146 // If longitude2 and latitude2 aren't set, ignore the lines
147 // This happens with all the connections that don't connect 2 nodes
148 if ($this->KMLLines[$i]->isConnected()) {
149 $lineString .= $this->KMLLines[$i]->toString();
150 }
151 }
152
153 $toString = str_replace('%NODE_GREEN%', $config['node_green'], $toString);
154 $toString = str_replace('%NODE_ORANGE%', $config['node_orange'], $toString);
155 $toString = str_replace('%NODE_RED%', $config['node_red'], $toString);
156 $toString = str_replace('%LINE_BLACK%', $config['line_black'], $toString);
157 $toString = str_replace('%NODESCONTENT%', $nodeString, $toString);
158 $toString = str_replace('%LINESCONTENT%', $lineString, $toString);
159
160 $toString = str_replace('%OVERALL_LONGITUDE%', $config['overall_longitude'], $toString);
161 $toString = str_replace('%OVERALL_LATITUDE%', $config['overall_latitude'], $toString);
162 $toString = str_replace('%OVERALL_ALTITUDE%', $config['overall_altitude'], $toString);
163 $toString = str_replace('%OVERALL_HEADING%', $config['overall_heading'], $toString);
164 $toString = str_replace('%OVERALL_TILT%', $config['overall_tilt'], $toString);
165 $toString = str_replace('%OVERALL_RANGE%', $config['overall_range'], $toString);
166
167 return $toString;
168 }
169
170 /*
171 * Function: getNodeByName
172 * Description: Find the first KMLNode with the name $name and return its position. If not found, return false
173 * Parameters: string $name
174 * Returns: Position of node in our array, if not found false
175 */
176 public function getNodeByName($name) {
177 $nodesCount = count($this->KMLNodes);
178 for ($i = 0; $i < $nodesCount; $i++) {
179 if ($this->KMLNodes[$i]->getName() == $name) {
180 return $i;
181 }
182 }
183
184 return false;
185 }
186
187 /*
188 * Function: parseLocationFile
189 * Description: Parse the node location file updating or adding KMLNode objects to the current KMLFile object
190 * Parameters: string $file
191 * Returns: true is successfull, otherwise false
192 */
193 public function parseLocationFile($file) {
194 // We want to find all the nodes in the location file and store information of the nodes...
195 $nodesCount = preg_match_all('/\[[a-zA-Z0-9]*\]/i', $file, $nodes, PREG_OFFSET_CAPTURE);
196 for ($i = 0; $i < $nodesCount; $i++) {
197 // Looking for "location" of the node
198 if (!$location = $this->findInLocationFile($file, 'location = ', $nodes[0][$i][1])) {
199 trigger_log(SYSLOG_WARNING, 'Could not find the "location" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
200 continue;
201 }
202 // Looking for "status" of the node
203 if (!$status = $this->findInLocationFile($file, 'status = ', $nodes[0][$i][1])) {
204 trigger_log(SYSLOG_WARNING, 'Could not find the "status" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
205 continue;
206 }
207 // Looking for "latitude" of the node
208 if (!$latitude = $this->findInLocationFile($file, 'latitude = ', $nodes[0][$i][1])) {
209 trigger_log(SYSLOG_WARNING, 'Could not find the "latitude" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
210 continue;
211 }
212 // Looking for "longitude" of the node
213 if (!$longitude = $this->findInLocationFile($file, 'longitude = ', $nodes[0][$i][1])) {
214 trigger_log(SYSLOG_WARNING, 'Could not find the "longitude" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
215 continue;
216 }
217 // Looking for "interfaces" of the node
218 if (!$interfaces = $this->findInLocationFile($file, 'interfaces = ', $nodes[0][$i][1])) {
219 trigger_log(SYSLOG_WARNING, 'Could not find the "interfaces" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
220 continue;
221 }
222 // Looking for "masterip" of the node
223 if (!$masterip = $this->findInLocationFile($file, 'masterip = ', $nodes[0][$i][1])) {
224 trigger_log(SYSLOG_WARNING, 'Could not find the "masterip" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
225 continue;
226 }
227 // Looking for "nodetype" of the node
228 if (!$nodetype = $this->findInLocationFile($file, 'nodetype = ', $nodes[0][$i][1])) {
229 trigger_log(SYSLOG_WARNING, 'Could not find the "nodetype" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
230 continue;
231 }
232 // Looking for "name" of the node
233 if (!$name = $this->findInLocationFile($file, 'name = ', $nodes[0][$i][1])) {
234 trigger_log(SYSLOG_WARNING, 'Could not find the "name" of node "' . $i . '", skipping to next', __FILE__, __LINE__);
235 continue;
236 }
237
238 // Creating a string with the complete description of the node using all data in the location file
239 $dataLocation = '
240 <Data name="location">
241 <value>
242 <![CDATA[
243 ' . $location . '
244 ]]>
245 </value>
246 </Data>
247 <Data name="status">
248 <value>' . $status . '</value>
249 </Data>
250 <Data name="interfaces">
251 <value>' . $interfaces . '</value>
252 </Data>
253 <Data name="masterIP">
254 <value>' . $masterip . '</value>
255 </Data>
256 <Data name="nodeType">
257 <value>' . $nodetype . '</value>
258 </Data>';
259
260 if ($placemarkPosition = $this->getNodeByName($name)) {
261 // Updating an excisting placemark
262 $this->KMLNodes[$placemarkPosition]->setDataLocation($dataLocation);
263 $this->KMLNodes[$placemarkPosition]->setLongitude($longitude);
264 $this->KMLNodes[$placemarkPosition]->setLatitude($latitude);
265 } else {
266 // Adding a new placemark
267 $placemark = new KMLNode();
268 $placemark->setID($name);
269 $placemark->setName($name);
270 $placemark->setDataLocation($dataLocation);
271 $placemark->setLongitude($longitude);
272 $placemark->setLatitude($latitude);
273 $this->addNode($placemark);
274 }
275
276 // Now let's find all interlinks with this node
277 $position = $nodes[0][$i][1];
278 while (($position = strpos($file, 'ip=', $position + 1)) && (isset($nodes[0][$i + 1][1]) && $position < $nodes[0][$i + 1][1])) {
279 $ipAddress = $this->findInLocationFile($file, 'ip=', $position);
280 $posSlash = strpos($ipAddress, '/');
281 $ip = substr($ipAddress, 0, $posSlash);
282 $netmask = substr($ipAddress, $posSlash + 1);
283
284 $posNetwork = $this->NetworkList->find($ip);
285 if ($posNetwork) {
286 // Network already excists in list, just need to add longitude2 en latitude2 to KMLLine
287 // and add the node name to the name of the line.
288 // Position in network equals position in KMLLine array :-)
289
290 $this->KMLLines[$posNetwork]->setName($this->KMLLines[$posNetwork]->getName() . $name);
291 $this->KMLLines[$posNetwork]->setLongitude2($longitude);
292 $this->KMLLines[$posNetwork]->setLatitude2($latitude);
293 } else {
294 // Network doesn't excist. We create a new network and a new line.
295
296 $network = new Network($ip, $netmask);
297 $this->NetworkList->add($network);
298
299 $data = '
300 <Data name="netmaskDecimal">
301 <value>' . $network->netmaskDecimal . '</value>
302 </Data>
303 <Data name="netmaskBinary">
304 <value>' . $network->netmaskBinary . '</value>
305 </Data>
306 <Data name="wildcardDecimal">
307 <value>' . $network->wildcardDecimal . '</value>
308 </Data>
309 <Data name="wildcardBinary">
310 <value>' . $network->wildcardBinary . '</value>
311 </Data>
312 <Data name="networkDecimal">
313 <value>' . $network->networkDecimal . '</value>
314 </Data>
315 <Data name="networkBinary">
316 <value>' . $network->networkBinary . '</value>
317 </Data>
318 <Data name="broadcastDecimal">
319 <value>' . $network->broadcastDecimal . '</value>
320 </Data>
321 <Data name="broadcastBinary">
322 <value>' . $network->broadcastBinary . '</value>
323 </Data>
324 <Data name="hostMinDecimal">
325 <value>' . $network->hostminDecimal . '</value>
326 </Data>
327 <Data name="hostMinBinary">
328 <value>' . $network->hostminBinary . '</value>
329 </Data>
330 <Data name="hostMaxDecimal">
331 <value>' . $network->hostmaxDecimal . '</value>
332 </Data>
333 <Data name="hostMaxBinary">
334 <value>' . $network->hostmaxBinary . '</value>
335 </Data>
336 <Data name="hosts">
337 <value>' . $network->numberHosts . '</value>
338 </Data>';
339
340 $line = new KMLLine();
341 $line->setID(str_replace('.', '', $network->networkDecimal));
342 $line->setName('Link: Van ' . $name . ' naar ');
343 $line->setData($data);
344 $line->setLongitude1($longitude);
345 $line->setLatitude1($latitude);
346 $this->KMLLines[] = $line;
347 }
348 }
349 }
350 }
351
352 /*
353 * Function: findInLocationFile
354 * Description: Find the $keyword in $file and return the value of $keyword, starting at $offset
355 * Parameters: string $file, string $keyword, integer $offset
356 * Returns: The value of the keyword if found, otherwise return false
357 */
358 private function findInLocationFile($file, $keyword, $offset) {
359 $start = strpos($file, $keyword, $offset) + strlen($keyword);
360 $end = strpos($file, "\n", $start);
361
362 if ($start && $end && ($start < $end)) {
363 return substr($file, $start, $end - $start);
364 } else {
365 return false;
366 }
367 }
368
369 /*
370 * Function: parseStatusFile
371 * Description: Parse the node status file updating or adding KMLNode objects to the current KMLFile object
372 * Parameters: string $file
373 * Returns: true is successfull, otherwise false
374 */
375 public function parseStatusFile($file) {
376 $fileContents = explode("\r\n", $file);
377
378 if ($fileContents[0] != KMLFile::$fileFirst) {
379 trigger_log(SYSLOG_WARNING, 'Contents of file do not match with template of first line', __FILE__, __LINE__);
380 }
381
382 // For loop for all the lines in the file. Skipping first line (headers) and last line (blank)
383 $linesCount = count($fileContents);
384 for ($i = 1; $i < $linesCount - 1; $i++) {
385 $lineContent = explode(',', $fileContents[$i]);
386 $lineContent[1] = str_replace('CNode', '', $lineContent[1]);
387 echo $lineContent[1];
388
389 if (count($lineContent) != count($this->fileContent)) {
390 trigger_log(LOG_WARNING, 'Contents of the file do not match with template of lines on line "' . $i . '"', __FILE__, __LINE__);
391 continue;
392 }
393
394 // Checking for valid entries on this line
395 for ($j = 0; $j < 8; $j++) {
396 try {
397 switch ($this->fileContent[$j]) {
398 case 'string':
399 $lineContent[$j] = (string) $lineContent[$j];
400 break;
401 case 'int':
402 $lineContent[$j] = (int) $lineContent[$j];
403 break;
404 case 'double':
405 $lineContent[$j] = (double) $lineContent[$j];
406 break;
407 default:
408 break;
409 }
410 } catch (Exception $err) {
411 trigger_log(SYSLOG_WARNING, 'The value "' . $j . '" on line "' . $i . '" is not valid, skipping to next line', __FILE__, __LINE__);
412 continue;
413 }
414 }
415
416 // Creating a string with the complete description of the node using all data in the status file
417 $dataStatus = '
418 <Data name="type">
419 <value>' . $lineContent[0] . '</value>
420 </Data>
421 <Data name="hostName">
422 <value>' . $lineContent[1] . '</value>
423 </Data>
424 <Data name="hasBeenChecked">
425 <value>' . $lineContent[2] . '</value>
426 </Data>
427 <Data name="checkExecutionTime">
428 <value>' . $lineContent[3] . '</value>
429 </Data>
430 <Data name="currentState">
431 <value>' . $lineContent[4] . '</value>
432 </Data>
433 <Data name="lastHardState">
434 <value>' . $lineContent[5] . '</value>
435 </Data>
436 <Data name="lastCheck">
437 <value>' . $lineContent[6] . '</value>
438 </Data>
439 <Data name="problemHasBeenAcknowledged">
440 <value>' . $lineContent[7] . '</value>
441 </Data>';
442
443 $style = NODE_RED;
444 if ($lineContent[4] == NODE_STATUS_ERROR) {
445 $style = NODE_ORANGE;
446 } elseif ($lineContent[4] == NODE_STATUS_UP) {
447 $style = NODE_GREEN;
448 }
449
450 if ($placemarkPosition = $this->getNodeByName($lineContent[1])) {
451 // Updating an excisting placemark
452 $this->KMLNodes[$placemarkPosition]->setDataStatus($dataStatus);
453 $this->KMLNodes[$placemarkPosition]->setStyle($style);
454 } else {
455 // Adding a new placemark
456 $placemark = new KMLNode();
457 $placemark->setID($lineContent[1]);
458 $placemark->setName($lineContent[1]);
459 $placemark->setDataStatus($dataStatus);
460 $placemark->setStyle($style);
461 $this->addNode($placemark);
462 }
463 }
464 }
465}
466?>
Note: See TracBrowser for help on using the repository browser.