Esempio n. 1
0
 def delete(self):
     """
     Deletes the Ip represented by this model in database.
     Also deletes the tools associated with this ip
     Also deletes the ports associated with this ip
     Also deletes the defects associated with this ip and its ports
     """
     mongoInstance = MongoCalendar.getInstance()
     tools = mongoInstance.find("tools", {"ip": self.ip}, True)
     for tool in tools:
         tool_model = Tool(tool)
         tool_model.delete()
     defects = mongoInstance.find(
         "defects", {
             "ip": self.ip,
             "$or": [{
                 "port": {
                     "$exists": False
                 }
             }, {
                 "port": None
             }]
         }, True)
     for defect in defects:
         defect_model = Defect(defect)
         defect_model.delete()
     ports = mongoInstance.find("ports", {"ip": self.ip}, True)
     for port in ports:
         port_model = Port(port)
         port_model.delete()
     mongoInstance.delete("ips", {"_id": self._id})
Esempio n. 2
0
 def removeItem(self, toDeleteIid):
     """
     Remove defect from given iid in defect treeview
     Args:
         toDeleteIid: database ID of defect to delete
     """
     item = self.treevw.item(toDeleteIid)
     dialog = ChildDialogQuestion(
         self.parent, "DELETE WARNING",
         "Are you sure you want to delete defect " + str(item["text"]) +
         " ?", ["Delete", "Cancel"])
     self.parent.wait_window(dialog.app)
     if dialog.rvalue != "Delete":
         return
     self.treevw.delete(toDeleteIid)
     defectToDelete = Defect.fetchObject({
         "title": item["text"],
         "ip": "",
         "port": "",
         "proto": ""
     })
     if defectToDelete is not None:
         if defectToDelete.index is not None:
             index = int(defectToDelete.index)
             children = self.treevw.get_children()
             for i in range(index + 1, len(children), 1):
                 d_o = Defect({"_id": children[i]})
                 d_o.update({"index": str(i)})
         defectToDelete.delete()
         self.resizeDefectTreeview()
Esempio n. 3
0
 def addDefect(self, defect_o):
     """
     Add the given defect object in the treeview
     Args:
         defect_o: a Models.Defect object to be inserted in treeview
     """
     if defect_o is None:
         return
     children = self.treevw.get_children()
     if defect_o.index is None or str(defect_o.index) == "":
         indToInsert = self.findInsertIndex(defect_o)
         if str(indToInsert) != "end":
             for i in range(int(indToInsert), len(children), 1):
                 d_o = Defect({"_id": children[i]})
                 d_o.update({"index": str(i + 1)})
     else:
         indToInsert = defect_o.index
     types = defect_o.mtype
     types = ", ".join(defect_o.mtype)
     new_values = (defect_o.ease, defect_o.impact, defect_o.risk, types,
                   defect_o.redactor
                   if defect_o.redactor != "N/A" else self.mainRedac)
     already_inserted = False
     already_inserted_iid = None
     for child in children:
         title = self.treevw.item(child)["text"]
         if title == defect_o.title:
             already_inserted = True
             already_inserted_iid = child
             break
     if not already_inserted:
         try:
             self.treevw.insert('',
                                indToInsert,
                                defect_o.getId(),
                                text=defect_o.title,
                                values=new_values,
                                tags=(defect_o.risk))
             defect_o.update({"index": str(indToInsert)})
         except tk.TclError:
             # The defect already exists
             already_inserted = True
             already_inserted_iid = defect_o.getId()
     if already_inserted:
         existing = self.treevw.item(already_inserted_iid)
         values = existing["values"]
         if values[4].strip() == "N/A":
             values[4] = defect_o.redactor
         elif defect_o.redactor not in values[4].split(", "):
             values[4] += ", " + defect_o.redactor
         self.treevw.item(already_inserted_iid, values=values)
     # mongoInstance.insert("defects_table",{""})
     self.resizeDefectTreeview()
Esempio n. 4
0
 def fillWithDefects(self):
     """
     Fetch defects that are global (not assigned to an ip) and fill the defect table with them.
     """
     defects = Defect.fetchObjects({"ip":""})
     d_list = {}
     end_defect = []
     for defect in defects:
         if defect.index is None:
             end_defect.append(defect)
         elif str(defect.index) == "end":
             end_defect.append(defect)
         else:
             ind = int(defect.index)
             if ind not in d_list:
                 d_list[ind] = defect
             else:
                 new_ind = ind + 1
                 while new_ind in d_list:
                     new_ind += 1
                 d_list[new_ind] = defect
                 defect.index = new_ind
                 defect.update({"index":str(new_ind)})
     # Fix dict order to index between 0 and *
     keys_ordered = sorted(list(d_list.keys()))
     for i in range(len(keys_ordered)):
         self.addDefect(d_list[keys_ordered[i]])
     for defect in end_defect:
         self.addDefect(defect)
Esempio n. 5
0
 def _insertChildrenDefects(self):
     """Insert every children defect in database as DefectView under this node"""
     defects = self.controller.getDefects()
     for defect in defects:
         defect_o = DefectController(Defect(defect))
         defect_vw = DefectView(self.appliTw, self.appliViewFrame,
                                self.mainApp, defect_o)
         defect_vw.addInTreeview(str(self.controller.getDbId()))
Esempio n. 6
0
 def delete(self):
     """
     Deletes the Port represented by this model in database.
     Also deletes the tools associated with this port
     Also deletes the defects associated with this port
     """
     mongoInstance = MongoCalendar.getInstance()
     tools = mongoInstance.find("tools", {"port": self.port, "proto": self.proto,
                                          "ip": self.ip}, True)
     for tool in tools:
         tool_model = Tool(tool)
         tool_model.delete()
     defects = mongoInstance.find("defects", {"port": self.port, "proto": self.proto,
                                              "ip": self.ip}, True)
     for defect in defects:
         defect_model = Defect(defect)
         defect_model.delete()
     mongoInstance.delete("ports", {"_id":  ObjectId(self._id)})
Esempio n. 7
0
 def setMainRedactor(self):
     """Sets a main redactor for a pentest. Each not assigned defect will be assigned to him/her"""
     self.settings.reloadSettings()
     dialog = ChildDialogCombo(self.parent, self.settings.getPentesters()+["N/A"], "Set main redactor", "N/A")
     newVal = self.parent.wait_window(dialog.app)
     if newVal is None:
         return
     if not newVal or newVal.strip() == "":
         return
     columnRedactor = self.treevw['columns'].index("redactor")
     for it in self.treevw.get_children():
         oldValues = self.treevw.item(it)["values"]
         if oldValues[columnRedactor] == "N/A":
             oldValues[columnRedactor] = newVal
             self.treevw.item(it, values=oldValues)
             d_o = Defect({"_id":it})
             d_o.update({"redactor":newVal})
     self.mainRedac = newVal
Esempio n. 8
0
 def updateRiskBox(self, _event=None):
     """Callback when ease or impact is modified.
     Calculate new resulting risk value
     Args
         _event: mandatory but not used
     """
     ease = self.easeForm.getValue()
     impact = self.impactForm.getValue()
     risk = Defect.getRisk(ease, impact)
     self.riskForm.setValue(risk)
Esempio n. 9
0
 def createDefectCallback(self, _event=None):
     """Callback for tool click #TODO move to ToolController
     Creates an empty defect view and open it's insert window with notes = tools notes.
     """
     modelData = self.controller.getData()
     toExport = modelData["notes"]
     for widget in self.appliViewFrame.winfo_children():
         widget.destroy()
     dv = DefectView(self.appliTw, self.appliViewFrame, self.mainApp,
                     DefectController(Defect(modelData)))
     dv.openInsertWindow(toExport)
Esempio n. 10
0
 def OnDoubleClick(self, event):
     """
     Callback for double click on treeview.
     Opens a window to update the double clicked defect view.
     Args:
         event: automatically created with the event catch. stores data about line in treeview that was double clicked.
     """
     item = self.treevw.identify("item", event.x, event.y)
     defect_m = Defect.fetchObject({"_id": ObjectId(item)})
     dialog = ChildDialogDefectView(self.parent, self.settings, defect_m)
     self.parent.wait_window(dialog.app)
     self.updateDefectInTreevw(defect_m)
Esempio n. 11
0
    def Parse(self, file_opened, **kwargs):
        """
        Parse a opened file to extract information
        Example file:
        10.0.0.1 - UNKNOWN - no connection - timeout
        10.0.0.2 - VULNERABLE - ?? - ????

        Args:
            file_opened: the open file
            kwargs: port("") and proto("") are valid
        Returns:
            a tuple with 4 values (All set to None if Parsing wrong file): 
                0. notes: notes to be inserted in tool giving direct info to pentester
                1. tags: a list of tags to be added to tool 
                2. lvl: the level of the command executed to assign to given targets
                3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
        """
        # 5. Parse the file has you want.
        # Here add a note to the tool's notes of each warnings issued by this testssl run.
        notes = ""
        tags = ["Neutral"]
        targets = {}
        for line in file_opened:
            # Auto Detect
            infos = line.split(" - ")
            if len(infos) < 3:
                return None, None, None, None
            if not Ip.isIp(infos[0]):
                return None, None, None, None
            if infos[1] not in ["UNKNOWN", "SAFE", "VULNERABLE"]:
                return None, None, None, None
            # Parse
            ip = line.split(" ")[0].strip()
            Ip().initialize(ip).addInDb()
            p_o = Port.fetchObject({"ip": ip, "port": kwargs.get(
                "port", None), "proto": kwargs.get("proto", None)})
            if p_o is not None:
                targets[str(p_o.getId())] = {"ip": ip, "port": kwargs.get(
                    "port", None), "proto": kwargs.get("proto", None)}
            if "VULNERABLE" in line:
                Defect().initialize(ip, kwargs.get("port", None), kwargs.get("proto", None), "Serveur vulnérable à BlueKeep",
                                    "Difficile", "Critique", "Critique", "N/A", ["Socle"], notes=notes, proofs=[]).addInDb()
                tags=["P0wned!"]
                if p_o is not None:
                    p_o.addTag("P0wned!")
                ip_o = Ip.fetchObject({"ip": ip})
                if ip_o is not None:
                    ip_o.addTag("P0wned!")
            elif "UNKNOWN" in line:
                tags = ["todo"]
            notes += line
        return notes, tags, "port", targets
Esempio n. 12
0
 def Parse(self, file_opened, **kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     targets = {}
     notes = file_opened.read()
     regex_ip = r"Nmap scan report for (\S+)"
     ip_group = re.search(regex_ip, notes)
     if ip_group is None:
         return None, None, None, None
     # Auto Detect:
     if "smb-vuln-ms17-010:" not in notes:
         return None, None, None, None
     # Parsing
     ip = ip_group.group(1).strip()
     Ip().initialize(ip).addInDb()
     port_re = r"(\d+)\/(\S+)\s+open\s+microsoft-ds"
     res_search = re.search(port_re, notes)
     res_insert = None
     if res_search is None:
         port = None
         proto = None
     else:
         port = res_search.group(1)
         proto = res_search.group(2)
         p_o = Port()
         p_o.initialize(ip, port, proto, "microsoft-ds")
         res_insert = p_o.addInDb()
         targets[str(p_o.getId())] = {
             "ip": ip,
             "port": port,
             "proto": proto
         }
     if "VULNERABLE" in notes:
         d_o = Defect()
         d_o.initialize(ip,
                        port,
                        proto,
                        "Serveur vulnérable à EternalBlue",
                        "Difficile",
                        "Critique",
                        "Critique",
                        "N/A", ["Socle"],
                        notes=notes,
                        proofs=[])
         d_o.addInDb()
         tags = ["P0wned!"]
         if res_insert is not None:
             p_o.addTag("P0wned!")
     return notes, tags, "port", targets
Esempio n. 13
0
    def addDefectCallback(self, _event):
        """
        Create an empty defect model and its attached view. Open this view insert window.

        Args:
            _event: Automatically generated with a button Callback, not used.
        """
        for widget in self.appliViewFrame.winfo_children():
            widget.destroy()
        modelData = self.controller.getData()
        dv = DefectView(self.appliTw, self.appliViewFrame, self.mainApp,
                        DefectController(Defect(modelData)))
        dv.openInsertWindow(modelData.get("notes", ""))
Esempio n. 14
0
    def addInTreeview(self, parentNode=None, addChildren=True):
        """Add this view in treeview. Also stores infos in application treeview.
        Args:
            parentNode: if None, will calculate the parent. If setted, forces the node to be inserted inside given parentNode.
            addChildren: If False, skip the tool and defects insert. Useful when displaying search results
        """
        if parentNode is None:
            parentNode = self.getParent()
            nodeText = str(self.controller.getModelRepr())
        elif parentNode == '':
            nodeText = self.controller.getDetailedString()
        else:
            nodeText = str(self.controller.getModelRepr())
        self.appliTw.views[str(self.controller.getDbId())] = {"view": self}
        try:
            self.appliTw.insert(parentNode,
                                "end",
                                str(self.controller.getDbId()),
                                text=nodeText,
                                tags=self.controller.getTags(),
                                image=self.getClassIcon())
        except TclError:
            pass
        if addChildren:
            defects = self.controller.getDefects()
            for defect in defects:
                defect_o = DefectController(Defect(defect))
                defect_vw = DefectView(self.appliTw, self.appliViewFrame,
                                       self.mainApp, defect_o)
                defect_vw.addInTreeview(str(self.controller.getDbId()))

            tools = self.controller.getTools()
            for tool in tools:
                tool_o = ToolController(Tool(tool))
                tool_vw = ToolView(self.appliTw, self.appliViewFrame,
                                   self.mainApp, tool_o)
                tool_vw.addInTreeview(str(self.controller.getDbId()))
        tools = self.controller.getTools()
        atleastone = False
        for tool in tools:  # SALE
            atleastone = True
            break
        if not atleastone:
            if len(self.controller.getTags()) == 0:
                self.controller.addTag("unscanned")
        self.appliTw.sort(parentNode)
        if "hidden" in self.controller.getTags():
            self.hide()
Esempio n. 15
0
    def Parse(self, file_opened, **_kwargs):
        """
        Parse a opened file to extract information
        Args:
            file_opened: the open file
            _kwargs: not used
        Returns:
            a tuple with 4 values (All set to None if Parsing wrong file): 
                0. notes: notes to be inserted in tool giving direct info to pentester
                1. tags: a list of tags to be added to tool 
                2. lvl: the level of the command executed to assign to given targets
                3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
        """
        notes = file_opened.read()
        targets = {}
        tags = []
        if "| http-methods:" not in notes:
            return None, None, None, None
        host, port, proto, service, risky_methods, supported_methods = parse(
            notes)
        if host == "":
            return None, None, None, None
        Ip().initialize(host).addInDb()
        p_o = Port().initialize(host, port, proto, service)
        res, iid = p_o.addInDb()
        if not res:
            p_o = Port.fetchObject({"_id": iid})

        p_o.updateInfos({"Methods": ", ".join(supported_methods)})
        targets[str(p_o.getId())] = {"ip": host, "port": port, "proto": proto}
        if "TRACE" in risky_methods:
            Defect().initialize(host, port, proto, "Méthode TRACE activée", "Difficile", "Important", "Important",
                                 "N/A", ["Socle"], notes="TRACE detected", proofs=[]).addInDb()
            risky_methods.remove("TRACE")
        if len(risky_methods) > 0:
            notes = "RISKY HTTP METHODS ALLOWED : " + " ".join(risky_methods)
            tags = []
            tags.append("Interesting")
        return notes, tags, "port", targets
Esempio n. 16
0
    def __init__(self, parent, settings, defectModel=None):
        """
        Open a child dialog of a tkinter application to choose autoscan settings.

        Args:
            parent: the tkinter parent view to use for this window construction.
            defectModel : A Defect Model object to load default values. None to have empty fields, default is None.
        """
        self.app = tk.Toplevel(parent)
        self.app.title("Add a security defect")
        self.app.resizable(False, False)
        self.rvalue = None
        appFrame = ttk.Frame(self.app)
        self.isInsert = defectModel is None
        if self.isInsert:
            defectModel = Defect()

        self.defect_vw = DefectView(None, appFrame, DummyMainApp(settings),
                                    DefectController(defectModel))
        if self.isInsert:
            self.defect_vw.openInsertWindow(addButtons=False)
        else:
            self.defect_vw.openModifyWindow(addButtons=False)

        ok_button = ttk.Button(appFrame, text="OK")
        ok_button.pack(side="right", padx=5, pady=10)
        ok_button.bind('<Button-1>', self.okCallback)
        cancel_button = ttk.Button(appFrame, text="Cancel")
        cancel_button.pack(side="right", padx=5, pady=10)
        cancel_button.bind('<Button-1>', self.cancel)
        appFrame.pack(fill=tk.BOTH, ipady=10, ipadx=10)
        self.app.transient(parent)
        try:
            self.app.wait_visibility()
            self.app.grab_set()
        except tk.TclError:
            pass
Esempio n. 17
0
 def getDefectsAsDict(self):
     """
     Returns a dictionnary with treeview defects stored inside
     Returns:
         The returned dict will be formed this way (shown as json):
         {
             "Risk level describer 1":{
                 "defect title 1": {
                     "description":{
                         "title": "defect title 1",
                         "risk": "Risk level 1",
                         "ease": "Ease of exploitation 1",
                         "impact": "Impact 1",
                         "redactor": "Redactor name",
                         "type": ['D', 'T', ...]
                     },
                     "defects_ids":[
                         id 1,
                         id 2...
                     ]
                 },
                 "defect title 2":{
                     ...
                 }
                 ...
             },
             "Risk level describer 2":{
                 ...
             }
             ...
         }
     """
     defects_dict = dict()
     defects_dict["Critique"] = dict()
     defects_dict["Majeur"] = dict()
     defects_dict["Important"] = dict()
     defects_dict["Mineur"] = dict()
     columnEase = self.treevw['columns'].index("ease")
     columnImpact = self.treevw['columns'].index("impact")
     columnType = self.treevw['columns'].index("type")
     columnRisk = self.treevw['columns'].index("risk")
     columnRedactor = self.treevw['columns'].index("redactor")
     for children_id in self.treevw.get_children():
         children = self.treevw.item(children_id)
         title = children["text"]
         defect_recap = dict()
         defect_recap["title"] = title
         defect_recap["risk"] = children["values"][columnRisk]
         defect_recap["ease"] = children["values"][columnEase]
         defect_recap["impact"] = children["values"][columnImpact]
         defect_recap["redactor"] = children["values"][columnRedactor]
         types = children["values"][columnType].split(",")
         d_types = []
         for d_type in types:
             d_types.append(d_type.strip())
         defect_recap["type"] = d_types
         defects_dict[defect_recap["risk"]][title] = dict()
         defects_dict[defect_recap["risk"]
                      ][title]["description"] = defect_recap
         defects_dict[defect_recap["risk"]][title]["defects_ids"] = []
         defects = Defect.fetchObjects({"title": title})
         for defect in defects:
             defects_dict[defect_recap["risk"]
                          ][title]["defects_ids"].append(defect.getId())
     return defects_dict
Esempio n. 18
0
def parseWarnings(file_opened):
    """
    Parse the result of a testssl json output file
        Args:
            file_opened:  the opened file reference

        Returns:
            Returns a tuple with (None values if not matching a testssl output):
                - a list of string for each testssl NOT ok, WARN, or MEDIUM warnings
                - a dict of targeted objects with database id as key and a unique key as a mongo search pipeline ({})
    """
    targets = {}
    missconfiguredHosts = {}
    firstLine = True
    for line in file_opened:
        if firstLine:
            if line.strip() != '"id", "fqdn/ip", "port", "severity", "finding", "cve", "cwe"' and \
                    line.strip() != '"id","fqdn/ip","port","severity","finding","cve","cwe"':
                return None, None
            firstLine = False
            continue
        # Search ip in file
        warn = re.search(
            r"^\"[^\"]*\", ?\"([^\"]*)\", ?\"([^\"]*)\", ?\"(OK|INFO|NOT ok|WARN|LOW|MEDIUM|HIGH|CRITICAL)\", ?\"[^\"]*\", ?\"[^\"]*\", ?\"[^\"]*\"$",
            line)
        if warn is not None:
            ip = warn.group(1)
            domain = None
            port = warn.group(2)
            notes = warn.group(3)
            if "/" in ip:
                domain = ip.split("/")[0]
                ip = "/".join(ip.split("/")[1:])
                Ip().initialize(domain).addInDb()
                Port().initialize(domain, port, "tcp", "ssl").addInDb()
            Ip().initialize(ip).addInDb()
            Port().initialize(ip, port, "tcp", "ssl").addInDb()
            if notes not in ["OK", "INFO"]:
                missconfiguredHosts[ip] = missconfiguredHosts.get(ip, {})
                missconfiguredHosts[ip][port] = missconfiguredHosts[ip].get(
                    port, [])
                missconfiguredHosts[ip][port].append(notes + " : " + line)
                if domain is not None:
                    missconfiguredHosts[domain] = missconfiguredHosts.get(
                        domain, {})
                    missconfiguredHosts[domain][port] = missconfiguredHosts[
                        domain].get(port, [])
                    missconfiguredHosts[domain][port].append(notes + " : " +
                                                             line)
    for ip in missconfiguredHosts.keys():
        for port in missconfiguredHosts[ip].keys():
            p_o = Port.fetchObject({"ip": ip, "port": port, "proto": "tcp"})
            targets[str(p_o.getId())] = {
                "ip": ip,
                "port": port,
                "proto": "tcp"
            }
            missconfiguredHosts[ip][port].sort()
            notes = "\n".join(missconfiguredHosts[ip][port])
            res, _ = Defect().initialize(ip,
                                         port,
                                         "tcp",
                                         "Défauts d'implémentation du SSL/TLS",
                                         "Très difficile",
                                         "Majeur",
                                         "Important",
                                         "N/A", ["Socle"],
                                         notes=notes,
                                         proofs=[]).addInDb()
            if not res:
                p_o.updateInfos({"compliant": "False"})
                defect_o = Defect.fetchObject({
                    "ip": ip,
                    "title": "Défauts d'implémentation du SSL/TLS",
                    "port": port,
                    "proto": "tcp"
                })
                defect_o.notes += notes
                defect_o.update()
    if firstLine:
        return None, None
    return str(len(missconfiguredHosts.keys())
               ) + " misconfigured hosts found. Defects created.", targets
Esempio n. 19
0
 def Parse(self, file_opened, **_kwargs):
     """
     Parse a opened file to extract information
     Args:
         file_opened: the open file
         _kwargs: not used
     Returns:
         a tuple with 4 values (All set to None if Parsing wrong file): 
             0. notes: notes to be inserted in tool giving direct info to pentester
             1. tags: a list of tags to be added to tool 
             2. lvl: the level of the command executed to assign to given targets
             3. targets: a list of composed keys allowing retrieve/insert from/into database targerted objects.
     """
     notes = ""
     tags = []
     content = file_opened.read()
     targets = {}
     try:
         notes_json = json.loads(content)
     except json.decoder.JSONDecodeError:
         return None, None, None, None
     oneScanIsValid = False
     for scan in notes_json:
         try:
             if scan.get('ssh_scan_version', None) is None:
                 continue
             ips = [scan["hostname"], scan["ip"]]
             port = str(scan["port"])
             for ip in ips:
                 if ip.strip() == "":
                     continue
                 Ip().initialize(ip).addInDb()
                 port_o = Port().initialize(ip, port, "tcp", "ssh")
                 res, iid = port_o.addInDb()
                 if not res:
                     port_o = Port.fetchObject({"_id": iid})
                 notes = "\n".join(scan["compliance"].get(
                     "recommendations", []))
                 targets[str(port_o.getId())] = {
                     "ip": ip,
                     "port": port,
                     "proto": "tcp"
                 }
                 oneScanIsValid = True
                 if "nopassword" in scan["auth_methods"]:
                     tags = ["P0wned!"]
                 # Will not exit if port was not ssh
                 is_ok = scan["compliance"]["compliant"]
                 if str(is_ok) == "False":
                     port_o.updateInfos({"compliant": "False"})
                     port_o.updateInfos(
                         {"auth_methods": scan["auth_methods"]})
                     Defect().initialize(
                         ip,
                         port,
                         "tcp",
                         "Défauts d’implémentation de la configuration SSH",
                         "Très difficile",
                         "Majeur",
                         "Important",
                         "N/A", ["Socle"],
                         notes=notes,
                         proofs=[]).addInDb()
         except KeyError:
             continue
     if not oneScanIsValid:
         return None, None, None, None
     return notes, tags, "port", targets
    def notify(self, db, collection, iid, action, _parent):
        """
        Callback for the observer implemented in mongo.py.
        Each time an object is inserted, updated or deleted the standard way, this function will be called.

        Args:
            collection: the collection that has been modified
            iid: the mongo ObjectId _id that was modified/inserted/deleted
            action: string "update" or "insert" or "delete". It was the action performed on the iid
            _parent: Not used. the mongo ObjectId of the parent. Only if action in an insert. Not used anymore
        """
        mongoInstance = MongoCalendar.getInstance()
        if not mongoInstance.hasACalendarOpen():
            return
        if mongoInstance.calendarName != db:
            return
        # Delete
        if action == "delete":
            if collection == "defects":
                view = self.getViewFromId(str(iid))
                if view is not None:
                    view.beforeDelete()
                    self.appli.statusbar.notify([],view.controller.getTags())
            try:
                self.delete(ObjectId(iid))
            except tk.TclError:
                pass  # item was not inserted in the treeview

        # Insert
        if action == "insert":
            view = None
            res = mongoInstance.find(collection, {"_id": ObjectId(iid)}, False)
            if collection == "tools":
                view = ToolView(self, self.appli.viewframe,
                                self.appli, ToolController(Tool(res)))
            elif collection == "waves":
                view = WaveView(self, self.appli.viewframe,
                                self.appli, WaveController(Wave(res)))
            elif collection == "scopes":
                view = ScopeView(self, self.appli.viewframe,
                                 self.appli, ScopeController(Scope(res)))
            elif collection == "ports":
                view = PortView(self, self.appli.viewframe,
                                self.appli, PortController(Port(res)))
            elif collection == "ips":
                view = IpView(self, self.appli.viewframe,
                              self.appli, IpController(Ip(res)))
            elif collection == "intervals":
                view = IntervalView(self, self.appli.viewframe,
                                    self.appli, IntervalController(Interval(res)))
            elif collection == "defects":
                view = DefectView(self, self.appli.viewframe,
                                self.appli, DefectController(Defect(res)))
            try:
                if view is not None:
                    view.addInTreeview()
                    view.insertReceived()
                    self.appli.statusbar.notify(view.controller.getTags())
            except tk.TclError:
                pass

        if action == "update":
            try:
                view = self.getViewFromId(str(iid))
                if view is not None:
                    oldTags = self.item(str(iid))["tags"]
                    view.controller.actualize()
                    self.appli.statusbar.notify(view.controller.getTags(), oldTags)
                    self.item(str(iid), text=str(
                        view.controller.getModelRepr()), image=view.getIcon())
            except tk.TclError:
                if view is not None:
                    view.addInTreeview()
            if str(self.appli.openedViewFrameId) == str(iid):
                for widget in self.appli.viewframe.winfo_children():
                    widget.destroy()
                view.openModifyWindow()
            if view is not None:
                view.updateReceived()
        self.appli.statusbar.update()
 def _load(self):
     """
     Load the treeview with database information
     """
     mongoInstance = MongoCalendar.getInstance()
     dialog = ChildDialogProgress(self.appli, "Loading "+str(
         mongoInstance.calendarName), "Opening "+str(mongoInstance.calendarName) + ". Please wait for a few seconds.", 200, "determinate")
     step = 0
     dialog.show(100)
     nbObjects = mongoInstance.find("waves").count()
     nbObjects += mongoInstance.find("scopes").count()
     nbObjects += mongoInstance.find("intervals").count()
     nbObjects += mongoInstance.find("scopes").count()
     nbObjects += mongoInstance.find("ips").count()
     nbObjects += mongoInstance.find("ports").count()
     nbObjects += mongoInstance.find("tools").count()
     onePercentNbObject = nbObjects//100 if nbObjects > 100 else 1
     nbObjectTreated = 0
     for child in self.get_children():
         self.delete(child)
     self._hidden = []
     self._detached = []
     self.waves_node = self.insert("", "end", str(
         "waves"), text="Waves", image=WaveView.getClassIcon())
     # Loading every category separatly is faster than recursivly.
     # This is due to cursor.next function calls in pymongo
     # Adding wave objects
     waves = Wave.fetchObjects({})
     for wave in waves:
         wave_o = WaveController(wave)
         wave_vw = WaveView(self, self.appli.viewframe, self.appli, wave_o)
         wave_vw.addInTreeview(self.waves_node, False)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     scopes = Scope.fetchObjects({})
     for scope in scopes:
         scope_o = ScopeController(scope)
         scope_vw = ScopeView(self, self.appli.viewframe, self.appli, scope_o)
         scope_vw.addInTreeview(None, False)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     intervals = Interval.fetchObjects({})
     for interval in intervals:
         interval_o = IntervalController(interval)
         interval_vw = IntervalView(self, self.appli.viewframe, self.appli, interval_o)
         interval_vw.addInTreeview(None, False)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding ip objects
     self.ips_node = self.insert("", "end", str(
         "ips"), text="IPs", image=IpView.getClassIcon())
     ips = Ip.fetchObjects({})
     for ip in ips:
         ip_o = IpController(ip)
         ip_vw = IpView(self, self.appli.viewframe, self.appli, ip_o)
         ip_vw.addInTreeview(None, False)
         self.appli.statusbar.notify(ip_vw.controller.getTags())
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding port objects
     ports = Port.fetchObjects({})
     for port in ports:
         port_o = PortController(port)
         port_vw = PortView(self, self.appli.viewframe, self.appli, port_o)
         port_vw.addInTreeview(None, False)
         self.appli.statusbar.notify(port_vw.controller.getTags())
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding defect objects
     defects = Defect.fetchObjects({"ip":{"$ne":""}})
     for defect in defects:
         defect_o = DefectController(defect)
         defect_vw = DefectView(
             self, self.appli.viewframe, self.appli, defect_o)
         defect_vw.addInTreeview(None)
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     # Adding tool objects
     tools = Tool.fetchObjects({})
     for tool in tools:
         tool_o = ToolController(tool)
         tool_vw = ToolView(self, self.appli.viewframe, self.appli, tool_o)
         tool_vw.addInTreeview(None, False)
         self.appli.statusbar.notify(tool_vw.controller.getTags())
         nbObjectTreated += 1
         if nbObjectTreated % onePercentNbObject == 0:
             step += 1
             dialog.update(step)
     self.sort(self.ips_node)
     self.appli.statusbar.update()
     dialog.destroy()