First, make sure we don't have residual junk configs, resulting in ConfigParser
values coming back as lists instead of strings. Then offer the user the option
to copy the global config file, which should be uncorrupted.
Sometimes (all the time?) hosts are "cloned" or deep-copied instead of being
copied by reference, so testing whether a host is "in" a scan is insufficient.
Now we check by address, the same way that Zenmap uses to determine 2 hosts are
the "same" for merging their output.
Also, avoid considering a scan as having unsaved changes if the comment field is
merely focused but unchanged.
The following steps caused the bug with the r32936 code:
1. Start a scan (say Quick Scan for simplicity) for a certain target (say A)
2. Wait for scan to complete
3. Start a scan for a different target (say B).
4. Wait for scan to complete
5. Click on host A in the Hosts list on the left (while scan B is still visible on the right)
6. BOOM!
Instead of loading the entire output into a new string with
gtk.TextBuffer.get_text, we use the gtk.TextIter.forward_search method.
This works because we don't need to use regular expressions to find a
static string.
http://seclists.org/nmap-dev/2014/q2/318
Essentially, we import the xml name, then override its search path,
stripping out the _xmlplus paths that PyXML uses. This leaves only the
Python 2 standard library path, which is what Zenmap was written for.
In general, it's better to use explicit flow control than to throw
and/or catch generic exceptions. Example:
try:
thing = d["key"]
except:
pass
This 1. catches an inspecific exception (probably KeyError), 2. can be
replaced with a check for ("key" is in d), and 3. can often be replaced
with d.get("key", some_default_value).
Replaced instances of this pattern:
if 'key' in somedict:
var = somedict['key']
else:
var = ""
...with this much simpler pattern:
var = somedict.get('key', "")
Some variations, like returning None if the key is not found were also
replaced.