1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4/**
5 * Parses a Nmap XML output file
6 *
7 * PHP version 5
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA
22 *
23 * @category  Net
24 * @package   Net_Nmap
25 * @author    Luca Corbo <lucor@ortro.net>
26 * @copyright 2008 Luca Corbo
27 * @license   GNU/LGPL v2.1
28 * @link      http://pear.php.net/packages/Net_Nmap
29 */
30
31require_once 'XML/Parser.php';
32require_once 'Net/Nmap/Host.php';
33require_once 'Net/Nmap/Service.php';
34require_once 'Net/Nmap/Stats.php';
35
36/**
37 * Parses a Nmap XML output file
38 *
39 * @category  Net
40 * @package   Net_Nmap
41 * @author    Luca Corbo <lucor@ortro.net>
42 * @copyright 2008 Luca Corbo
43 * @license   GNU/LGPL v2.1
44 * @link      http://pear.php.net/packages/Net_Nmap
45 * @link      http://nmap.org/data/nmap.dtd
46 */
47class Net_Nmap_Parser extends XML_Parser
48{
49    /**
50     * Container for the host objects
51     * @var ArrayIterator
52     */
53    private $_hosts;
54
55    /**
56     * Nmap Stats object
57     * @var Net_Nmap_Stats
58     */
59    private $_stats;
60
61    /**
62     * start handler
63     *
64     * @param resource $parser  xml parser resource
65     * @param string   $name    element name
66     * @param array    $attribs attributes
67     *
68     * @return void
69     */
70    public function startHandler($parser, $name, $attribs)
71    {
72        switch ($name) {
73        case 'nmaprun':
74            if (isset($this->_stats)) {
75                $this->_stats = new Net_Nmap_Stats();
76            }
77            $this->_stats->scanner = @$attribs['scanner'];
78            $this->_stats->args    = @$attribs['args'];
79            $this->_stats->version = @$attribs['version'];
80            $this->_stats->start   = @$attribs['start'];
81            $this->_stats->xmloutputversion = @$attribs['xmloutputversion'];
82            break;
83        case 'host':
84            if (!$this->_hosts instanceof ArrayIterator) {
85                $this->_hosts = new ArrayIterator();
86            }
87            $this->_hosts->append(new Net_Nmap_Host());
88            if ($this->_hosts->count() > 1) {
89                $this->_hosts->next();
90            }
91            $this->_host = $this->_hosts->current();
92            break;
93        case 'status':
94            $this->_host->setStatus($attribs['state']);
95            break;
96        case 'address':
97            $this->_host->addAddress($attribs['addrtype'], $attribs['addr']);
98            break;
99        case 'hostname':
100            $this->_host->addHostname($attribs['name']);
101            break;
102        case 'port':
103            $this->_service = new Net_Nmap_Service();
104
105            $this->_service->protocol = @$attribs['protocol'];
106            $this->_service->port     = @$attribs['portid'];
107            break;
108        case 'service':
109            $this->_service->name      = @$attribs['name'];
110            $this->_service->product   = @$attribs['product'];
111            $this->_service->version   = @$attribs['version'];
112            $this->_service->extrainfo = @$attribs['extrainfo'];
113            if (isset($attribs['ostype'])) {
114                $this->_host->addOS('0', $attribs['ostype']);
115            }
116            break;
117        case 'osmatch':
118            $this->_host->addOS($attribs['accuracy'], $attribs['name']);
119            break;
120        case 'finished':
121            $this->_stats->finished = @$attribs['time'];
122            break;
123        case 'hosts':
124            $this->_stats->hosts_up     = @$attribs['up'];
125            $this->_stats->hosts_down   = @$attribs['down'];
126            $this->_stats->hosts_total  = @$attribs['total'];
127            break;
128        default:
129            $this->currentTag = $name;
130            break;
131        }
132    }
133
134    /**
135     * end handler
136     *
137     * @param resource $parser xml parser resource
138     * @param string   $name   element name
139     *
140     * @return void
141     */
142    public function endHandler($parser, $name)
143    {
144        switch ($name) {
145        case 'port':
146            $this->_host->addService($this->_service);
147            break;
148        default:
149            break;
150        }
151
152        $this->currentTag = null;
153    }
154
155    /**
156     * handle character data
157     *
158     * @param resource $parser xml parser resource
159     * @param string   $data   data
160     *
161     * @return void | true if $data is empty
162     */
163    public function cdataHandler($parser, $data)
164    {
165        $data = trim($data);
166        if (empty($data)) {
167            return true;
168        }
169    }
170
171    /**
172     * Get all the discovered hosts
173     *
174     * @return ArrayIterator The discovered hosts
175     */
176    public function getHosts()
177    {
178        return $this->_hosts;
179    }
180
181    /**
182     * Get Nmap Statistics
183     *
184     * @return Net_Nmap_Stats   Return an Nmap Stats Object
185     */
186    public function getStats()
187    {
188        return $this->_stats;
189    }
190}