| 1 | # Copyright (C) 2007 Insecure.Com LLC. |
|---|
| 2 | # |
|---|
| 3 | # Author: Luis A. Bastiao Silva <luis.kop@gmail.com> |
|---|
| 4 | # |
|---|
| 5 | # This program is free software; you can redistribute it and/or modify |
|---|
| 6 | # it under the terms of the GNU General Public License as published by |
|---|
| 7 | # the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | # (at your option) any later version. |
|---|
| 9 | # |
|---|
| 10 | # This program is distributed in the hope that it will be useful, |
|---|
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | # GNU General Public License for more details. |
|---|
| 14 | # |
|---|
| 15 | # You should have received a copy of the GNU General Public License |
|---|
| 16 | # along with this program; if not, write to the Free Software |
|---|
| 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 18 | |
|---|
| 19 | from types import StringTypes |
|---|
| 20 | from xml.dom import minidom |
|---|
| 21 | #import xml.dom.ext |
|---|
| 22 | # Testing at devel |
|---|
| 23 | from os.path import split, join |
|---|
| 24 | |
|---|
| 25 | from umitCore.Paths import Path |
|---|
| 26 | #Path.set_umit_conf(join(split(__file__)[0], 'config', 'umit.conf')) |
|---|
| 27 | #END DEV TEST |
|---|
| 28 | options = Path.options |
|---|
| 29 | #from umitCore.NmapCommand import CommandConstructor |
|---|
| 30 | from umitCore.NmapOptions import NmapOptions |
|---|
| 31 | #from umitGUI.OptionBuilder import OptionBuilder |
|---|
| 32 | |
|---|
| 33 | |
|---|
| 34 | ''' |
|---|
| 35 | ProfileCore manage all of the profile.xml |
|---|
| 36 | - Supports the reading of options |
|---|
| 37 | - Supports the writing ordenabled options and groups |
|---|
| 38 | - Add/Remove a group |
|---|
| 39 | - Add options for each group |
|---|
| 40 | |
|---|
| 41 | ## Special info: |
|---|
| 42 | - If delete a group all options on this group should be |
|---|
| 43 | deleted too. |
|---|
| 44 | - A feauture that should be have it's delete a option |
|---|
| 45 | if it's deleted by options.xml |
|---|
| 46 | - Solve all problems with options dependentions |
|---|
| 47 | ''' |
|---|
| 48 | |
|---|
| 49 | |
|---|
| 50 | class ProfileOption(object): |
|---|
| 51 | ''' |
|---|
| 52 | This class contains a option on Profile and Wizard |
|---|
| 53 | It is a bridge between ProfileCore and Profile (Editable Box) |
|---|
| 54 | ''' |
|---|
| 55 | def __init__(self, type, label, option=None, arg_type=None , option_list=None ): |
|---|
| 56 | self._type = type |
|---|
| 57 | self._label = label |
|---|
| 58 | self._option = option |
|---|
| 59 | self._arg_type = arg_type |
|---|
| 60 | self._option_list = option_list |
|---|
| 61 | self._section = None |
|---|
| 62 | self._next_opt = None |
|---|
| 63 | def set_section(self, section): |
|---|
| 64 | self._section = section |
|---|
| 65 | def set_type(self, type): |
|---|
| 66 | self._type = type |
|---|
| 67 | def set_next_opt(self, opt): |
|---|
| 68 | self._next_opt= opt |
|---|
| 69 | def get_next_opt(self): |
|---|
| 70 | return self._next_opt |
|---|
| 71 | def get_type(self): |
|---|
| 72 | return self._type |
|---|
| 73 | def get_label(self): |
|---|
| 74 | return self._label |
|---|
| 75 | def get_option(self): |
|---|
| 76 | return self._option |
|---|
| 77 | def get_arg_type(self): |
|---|
| 78 | return self._arg_type |
|---|
| 79 | def get_option_list(self): |
|---|
| 80 | return self._option_list |
|---|
| 81 | def get_hint(self): |
|---|
| 82 | pass |
|---|
| 83 | def get_section(self): |
|---|
| 84 | return self._section |
|---|
| 85 | |
|---|
| 86 | |
|---|
| 87 | def option_to_profileoption(option): |
|---|
| 88 | ''' |
|---|
| 89 | This is a simples method to create a new ProfileOption from |
|---|
| 90 | a new Option. |
|---|
| 91 | It's a very primitive and useful when you create a new option at |
|---|
| 92 | profile based on a option |
|---|
| 93 | WHEN USE: example when do drag-n-drop, and received a Option |
|---|
| 94 | as we working with Profile, it's need a ProfileOption |
|---|
| 95 | ''' |
|---|
| 96 | from umitInterfaceEditor.OptionsCore import Option |
|---|
| 97 | o = option |
|---|
| 98 | o = Option() |
|---|
| 99 | result = ProfileOption('option_check', o.get_name(), o.get_name(), |
|---|
| 100 | o.get_arg_type()) |
|---|
| 101 | return result |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | |
|---|
| 106 | |
|---|
| 107 | class ProfileCore(object): |
|---|
| 108 | def __init__(self, xml_file): |
|---|
| 109 | ''' |
|---|
| 110 | Open XML file |
|---|
| 111 | It should be inheritance of OptionBuilder But I don't need |
|---|
| 112 | a function that update command. |
|---|
| 113 | So I implement a new way of read elements like OptionBuilder |
|---|
| 114 | with support of write in XML |
|---|
| 115 | |
|---|
| 116 | |
|---|
| 117 | @param xml_file: String with a path of file |
|---|
| 118 | @type xml_file: str |
|---|
| 119 | ''' |
|---|
| 120 | |
|---|
| 121 | xml_desc = open(xml_file) |
|---|
| 122 | self.xml_parse = minidom.parse(xml_desc) |
|---|
| 123 | xml_desc.close() |
|---|
| 124 | self.root_tag = "interface" |
|---|
| 125 | self.xml = self.xml_parse.getElementsByTagName(self.root_tag)[0] |
|---|
| 126 | self.options = NmapOptions(options) |
|---|
| 127 | |
|---|
| 128 | self.groups = self.__parse_groups() |
|---|
| 129 | self.section_names = self.__parse_section_names() |
|---|
| 130 | self.tabs = self.__parse_tabs() |
|---|
| 131 | |
|---|
| 132 | # Private API |
|---|
| 133 | |
|---|
| 134 | def __parse_section_names(self): |
|---|
| 135 | dic = {} |
|---|
| 136 | for group in self.groups: |
|---|
| 137 | grp = self.xml.getElementsByTagName(group)[0] |
|---|
| 138 | dic[group] = grp.getAttribute(u'label') |
|---|
| 139 | return dic |
|---|
| 140 | |
|---|
| 141 | def __parse_groups(self): |
|---|
| 142 | return [g_name.getAttribute(u'name') for g_name in \ |
|---|
| 143 | self.xml.getElementsByTagName(u'groups')[0].\ |
|---|
| 144 | getElementsByTagName(u'group')] |
|---|
| 145 | |
|---|
| 146 | def __parse_tabs(self): |
|---|
| 147 | ''' |
|---|
| 148 | |
|---|
| 149 | This part should be interact with BoxEditable of Items |
|---|
| 150 | ''' |
|---|
| 151 | |
|---|
| 152 | #XXX fix OptionTab - implement new way |
|---|
| 153 | dic = {} |
|---|
| 154 | for tab_name in self.groups: |
|---|
| 155 | #dic[tab_name] = OptionTab(self.xml.getElementsByTagName(tab_name)[0], |
|---|
| 156 | # self.options, self.constructor, self.update_func) |
|---|
| 157 | dic[tab_name] = self.xml.getElementsByTagName(tab_name)[0] |
|---|
| 158 | return dic |
|---|
| 159 | |
|---|
| 160 | |
|---|
| 161 | |
|---|
| 162 | #Public API |
|---|
| 163 | def get_group(self): |
|---|
| 164 | |
|---|
| 165 | for root_tab in self.tabs: |
|---|
| 166 | print root_tab |
|---|
| 167 | for option_element in self.tabs[root_tab].childNodes: |
|---|
| 168 | try:option_element.tagName |
|---|
| 169 | except:pass |
|---|
| 170 | else: |
|---|
| 171 | print option_element.tagName |
|---|
| 172 | #self.widgets_list.append(actions[option_element.tagName](option_element, options_used)) |
|---|
| 173 | #print ".." |
|---|
| 174 | |
|---|
| 175 | def get_section_node(self, section): |
|---|
| 176 | ''' |
|---|
| 177 | get section node |
|---|
| 178 | ''' |
|---|
| 179 | |
|---|
| 180 | element = self.xml.getElementsByTagName('groups')[0] |
|---|
| 181 | element_group = element.getElementsByTagName(u'group') |
|---|
| 182 | result = None |
|---|
| 183 | for i in element_group: |
|---|
| 184 | result = i |
|---|
| 185 | if i.getAttribute('name') == section: |
|---|
| 186 | break |
|---|
| 187 | |
|---|
| 188 | |
|---|
| 189 | return result |
|---|
| 190 | def get_section(self, section): |
|---|
| 191 | ''' |
|---|
| 192 | @param section: a section name |
|---|
| 193 | @type section: str |
|---|
| 194 | @return: a list of options |
|---|
| 195 | @rtype: a list of ProfileOption |
|---|
| 196 | |
|---|
| 197 | ''' |
|---|
| 198 | result = [] |
|---|
| 199 | for option in self.tabs[section].childNodes: |
|---|
| 200 | try: option.tagName |
|---|
| 201 | except:pass |
|---|
| 202 | else: |
|---|
| 203 | tagName = option.tagName |
|---|
| 204 | if tagName == 'option_check': |
|---|
| 205 | tmp_po = ProfileOption(tagName, option.getAttribute(u'label'), |
|---|
| 206 | option.getAttribute(u'option'), |
|---|
| 207 | option.getAttribute(u'arg_type'), |
|---|
| 208 | None) |
|---|
| 209 | elif tagName == 'option_list': |
|---|
| 210 | |
|---|
| 211 | option_list = [] |
|---|
| 212 | for k in option.getElementsByTagName('option'): |
|---|
| 213 | option_list.append(k.getAttribute(u'name')) |
|---|
| 214 | tmp_po = ProfileOption(tagName, option.getAttribute(u'label'), |
|---|
| 215 | None, None, option_list) |
|---|
| 216 | |
|---|
| 217 | result.append(tmp_po) |
|---|
| 218 | return result |
|---|
| 219 | |
|---|
| 220 | |
|---|
| 221 | def add_section(self): |
|---|
| 222 | pass |
|---|
| 223 | def remove_opt(self, section, name): |
|---|
| 224 | |
|---|
| 225 | |
|---|
| 226 | elem = self.search_option(section, name) |
|---|
| 227 | root = self.xml_parse.getElementsByTagName(self.root_tag)[0] |
|---|
| 228 | sec = root.getElementsByTagName(section) |
|---|
| 229 | |
|---|
| 230 | sec[0].removeChild(elem) |
|---|
| 231 | def remove_section(self, section_name): |
|---|
| 232 | ''' |
|---|
| 233 | Removes section of the DOM |
|---|
| 234 | @param section_name: name of the section that will be removed |
|---|
| 235 | @type section_name: str |
|---|
| 236 | ''' |
|---|
| 237 | |
|---|
| 238 | |
|---|
| 239 | root = self.xml_parse.getElementsByTagName(self.root_tag)[0] |
|---|
| 240 | |
|---|
| 241 | elem = self.search_in_groups(name) |
|---|
| 242 | root.removeChild(elem) |
|---|
| 243 | |
|---|
| 244 | |
|---|
| 245 | |
|---|
| 246 | def search_in_groups(self, name): |
|---|
| 247 | ''' |
|---|
| 248 | Search a element of group |
|---|
| 249 | @param name: name of group to search |
|---|
| 250 | @type name: str |
|---|
| 251 | |
|---|
| 252 | @return : a Child None of DOM if found or None if not found |
|---|
| 253 | @rtype: ChildNode or None |
|---|
| 254 | ''' |
|---|
| 255 | |
|---|
| 256 | element = self.xml.getElementsByTagName('groups')[0] |
|---|
| 257 | element_group = element.getElementsByTagName(u'group') |
|---|
| 258 | result = None |
|---|
| 259 | for i in element_group: |
|---|
| 260 | if i.getAttribute('name') == name: |
|---|
| 261 | result = i |
|---|
| 262 | return result |
|---|
| 263 | def add_section_after(self, section, section_after): |
|---|
| 264 | pass |
|---|
| 265 | |
|---|
| 266 | def add_section_before(self, section, section_before): |
|---|
| 267 | ''' |
|---|
| 268 | This function is to insert a new section at groups |
|---|
| 269 | with a new interface it is need insert and move sections |
|---|
| 270 | |
|---|
| 271 | |
|---|
| 272 | ''' |
|---|
| 273 | #Fill element |
|---|
| 274 | element = self.xml_parse.createElementNS(None, "group") |
|---|
| 275 | element.setAttributeNS(None, 'name',section) |
|---|
| 276 | #search Node to insert before it |
|---|
| 277 | beforeChild = self.search_in_groups(section_before) |
|---|
| 278 | #Add to xml doc |
|---|
| 279 | self.xml.getElementsByTagName('groups')[0].insertBefore(element, |
|---|
| 280 | beforeChild ) |
|---|
| 281 | |
|---|
| 282 | def search_option(self, section_name, option_name): |
|---|
| 283 | ''' |
|---|
| 284 | Search a option with a name and return this Node |
|---|
| 285 | @param section_name: A section name where is to looking for |
|---|
| 286 | @type section_name: str |
|---|
| 287 | @param option_name: A name of option for searching |
|---|
| 288 | @type option_name: str |
|---|
| 289 | |
|---|
| 290 | @return: A node with a element found or None if not found |
|---|
| 291 | @rtype: ChildNode element or None |
|---|
| 292 | ''' |
|---|
| 293 | |
|---|
| 294 | grp = self.xml.getElementsByTagName(section_name)[0] |
|---|
| 295 | result = None |
|---|
| 296 | for elem in grp.childNodes: |
|---|
| 297 | try: elem.getAttribute(u'label') |
|---|
| 298 | except: pass |
|---|
| 299 | else: |
|---|
| 300 | if elem.getAttribute(u'label') == option_name: |
|---|
| 301 | result = elem |
|---|
| 302 | break |
|---|
| 303 | |
|---|
| 304 | return result |
|---|
| 305 | |
|---|
| 306 | def add_option_before(self, section_name, option, before): |
|---|
| 307 | |
|---|
| 308 | result = self.xml.getElementsByTagName(section_name)[0].insertBefore(option, before) |
|---|
| 309 | def add_from_profileoption(self, profileoption): |
|---|
| 310 | ''' |
|---|
| 311 | use add_option |
|---|
| 312 | ''' |
|---|
| 313 | po = profileoption |
|---|
| 314 | section = po.get_section() |
|---|
| 315 | tagname = po.get_type() |
|---|
| 316 | label = po.get_label() |
|---|
| 317 | option = po.get_option() |
|---|
| 318 | arg_type = po.get_arg_type() |
|---|
| 319 | option_list = po.get_option_list() |
|---|
| 320 | option_name_next = po.get_next_opt() |
|---|
| 321 | |
|---|
| 322 | |
|---|
| 323 | self.add_option(section, tagname, label, option, arg_type, |
|---|
| 324 | option_list, option_name_next) |
|---|
| 325 | |
|---|
| 326 | |
|---|
| 327 | def add_option(self, section_name, tagname, label, option=None, |
|---|
| 328 | arg_type=None, options_list=None, option_name_before=None): |
|---|
| 329 | ''' |
|---|
| 330 | Add a option in a section |
|---|
| 331 | - If is a optionlist it have a option_list and if the option |
|---|
| 332 | should be not inserted at the end of section have a option_name_before |
|---|
| 333 | @param section_name: A section name where options should be added |
|---|
| 334 | @type section_name: str |
|---|
| 335 | @param tagname: option_check, option_list or others used at |
|---|
| 336 | Profile Editor or Wizard |
|---|
| 337 | @type tagname: str |
|---|
| 338 | @param label: Name of this option |
|---|
| 339 | @type label: str |
|---|
| 340 | @param option: The option is used to link with file options.xml |
|---|
| 341 | @type option: str |
|---|
| 342 | @param arg_type: type of arg (#XXX I think that it's obsulete right now) |
|---|
| 343 | @type arg_type:str |
|---|
| 344 | @param option_list: A list with a name options to option_list |
|---|
| 345 | @type option_list: list |
|---|
| 346 | @param option_name_before: name of option after where is inserted |
|---|
| 347 | @type option_name_before: str |
|---|
| 348 | ''' |
|---|
| 349 | element = self.xml_parse.createElementNS(None, tagname) |
|---|
| 350 | if arg_type != None: |
|---|
| 351 | element.setAttribute('arg_type', arg_type) |
|---|
| 352 | element.setAttribute('label',label) |
|---|
| 353 | if option != None: |
|---|
| 354 | element.setAttribute('option', option) |
|---|
| 355 | elements = [] |
|---|
| 356 | if options_list != None: |
|---|
| 357 | |
|---|
| 358 | for i in options_list: |
|---|
| 359 | element_in = self.xml_parse.createElementNS(None, 'option') |
|---|
| 360 | element_in.setAttributeNS(None, 'name', i) |
|---|
| 361 | elements.append(element_in) |
|---|
| 362 | after = None |
|---|
| 363 | if option_name_before != None: |
|---|
| 364 | after = self.search_option(section_name, option_name_before) |
|---|
| 365 | |
|---|
| 366 | result = self.xml.getElementsByTagName(section_name)[0].insertBefore(element, after) |
|---|
| 367 | if elements != [] : |
|---|
| 368 | for i in elements: |
|---|
| 369 | result.appendChild(i) |
|---|
| 370 | |
|---|
| 371 | def _determine_prev(self,section, list): |
|---|
| 372 | result = None |
|---|
| 373 | for i in list: |
|---|
| 374 | if i.getAttribute('name') == section: |
|---|
| 375 | break |
|---|
| 376 | |
|---|
| 377 | result = i |
|---|
| 378 | return result |
|---|
| 379 | |
|---|
| 380 | def get_prev(self, section): |
|---|
| 381 | ''' |
|---|
| 382 | get prev section |
|---|
| 383 | ''' |
|---|
| 384 | |
|---|
| 385 | element = self.get_group_element() |
|---|
| 386 | element_group = element.getElementsByTagName(u'group') |
|---|
| 387 | result = self._determine_prev(section, element_group) |
|---|
| 388 | return result |
|---|
| 389 | def get_next(self, section): |
|---|
| 390 | ''' |
|---|
| 391 | get next section |
|---|
| 392 | ''' |
|---|
| 393 | |
|---|
| 394 | element = self.get_group_element() |
|---|
| 395 | element_group = element.getElementsByTagName(u'group') |
|---|
| 396 | element_group.reverse() |
|---|
| 397 | result = self._determine_prev(section, element_group) |
|---|
| 398 | return result |
|---|
| 399 | |
|---|
| 400 | |
|---|
| 401 | def get_group_element(self): |
|---|
| 402 | element = self.xml.getElementsByTagName('groups')[0] |
|---|
| 403 | return element |
|---|
| 404 | def move_section_left(self, section): |
|---|
| 405 | node_prev = self.get_prev(section) |
|---|
| 406 | node = self.get_section_node(section) |
|---|
| 407 | element = self.get_group_element() |
|---|
| 408 | element.removeChild(node) |
|---|
| 409 | element.insertBefore(node, node_prev) |
|---|
| 410 | |
|---|
| 411 | |
|---|
| 412 | def move_section_right(self, section): |
|---|
| 413 | node_next = self.get_next(section) |
|---|
| 414 | node = self.get_section_node(section) |
|---|
| 415 | element = self.get_group_element() |
|---|
| 416 | element.removeChild(node_next) |
|---|
| 417 | element.insertBefore(node_next, node) |
|---|
| 418 | |
|---|
| 419 | |
|---|
| 420 | def get_list_opt(self, section, label): |
|---|
| 421 | ''' |
|---|
| 422 | Based on label of OptionList |
|---|
| 423 | return a List with a Options in. |
|---|
| 424 | ''' |
|---|
| 425 | elem = self.search_option(section, label) |
|---|
| 426 | list = elem.getElementsByTagName(u'option') |
|---|
| 427 | result = [] |
|---|
| 428 | for i in list: |
|---|
| 429 | name = i.getAttribute(u'name') |
|---|
| 430 | result.append(name) |
|---|
| 431 | return result |
|---|
| 432 | def get_prev_opt(section, option): |
|---|
| 433 | #XXX <- May be lack in other side |
|---|
| 434 | elem = self.search_option(section, option) |
|---|
| 435 | pass |
|---|
| 436 | |
|---|
| 437 | def move_option_up(self, section,option, option_up): |
|---|
| 438 | option_prev = self.search_option(section, option_up) |
|---|
| 439 | if option_up == None : |
|---|
| 440 | pass |
|---|
| 441 | else: |
|---|
| 442 | elem = self.search_option(section, option) |
|---|
| 443 | self.remove_opt(section, option) |
|---|
| 444 | self.add_option_before(section, elem, option_prev) |
|---|
| 445 | |
|---|
| 446 | |
|---|
| 447 | |
|---|
| 448 | def move_option_down(self, section, option, option_down): |
|---|
| 449 | option_next = self.search_option(section, option_down) |
|---|
| 450 | if option_down == None : |
|---|
| 451 | pass |
|---|
| 452 | else: |
|---|
| 453 | self.remove_opt(section, option_down) |
|---|
| 454 | elem = self.search_option(section, option) |
|---|
| 455 | self.add_option_before(section, option_next, elem) |
|---|
| 456 | |
|---|
| 457 | |
|---|
| 458 | |
|---|
| 459 | |
|---|
| 460 | def print_screen(self): |
|---|
| 461 | xml.dom.ext.PrettyPrint(self.xml) |
|---|
| 462 | def write_file(self,filename): |
|---|
| 463 | ''' |
|---|
| 464 | Write Option List to XML file |
|---|
| 465 | @param filename: File name of xml |
|---|
| 466 | @type filename: String |
|---|
| 467 | ''' |
|---|
| 468 | |
|---|
| 469 | file_object = open(filename, "w") |
|---|
| 470 | |
|---|
| 471 | #xml.dom.ext.PrettyPrint(self.xml, file_object) |
|---|
| 472 | self.xml.writexml(file_object) |
|---|
| 473 | file_object.close() |
|---|
| 474 | |
|---|
| 475 | |
|---|
| 476 | |
|---|
| 477 | # This is only for test a implementation of ProfileCore |
|---|
| 478 | |
|---|
| 479 | def main(): |
|---|
| 480 | s = ProfileCore("/home/kop/.umit/profile_editor.xml") |
|---|
| 481 | #for group in s.groups: |
|---|
| 482 | #print group |
|---|
| 483 | #for sections in s.section_names: |
|---|
| 484 | #print sections |
|---|
| 485 | #for tab in s.tabs: |
|---|
| 486 | #print tab |
|---|
| 487 | #s.get_group() |
|---|
| 488 | s.get_section('Scan') |
|---|
| 489 | #s.add_section_before('New label','Ping') |
|---|
| 490 | #s.add_option('Scan', 'option_list', 'dasdas', 'dasda', |
|---|
| 491 | # 'dasdas', ['sdas','dasda'], 'Timing: ') |
|---|
| 492 | s.remove_opt('Scan', 'TCP scan: ') |
|---|
| 493 | s.print_screen() |
|---|
| 494 | |
|---|
| 495 | |
|---|
| 496 | |
|---|
| 497 | if __name__ == "__main__": |
|---|
| 498 | main() |
|---|
| 499 | |
|---|