#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""
This file is part of cpe package.
This module contains the common characteristics of
any name matching algorithm, associated with a version of Common Platform
Enumeration (CPE) specification.
Copyright (C) 2013 Alejandro Galindo García, Roberto Abdelkader Martínez Pérez
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
For any problems using the cpe package, or general questions and
feedback about it, please contact:
- Alejandro Galindo García: galindo.garcia.alejandro@gmail.com
- Roberto Abdelkader Martínez Pérez: robertomartinezp@gmail.com
"""
from cpe import CPE
from comp.cpecomp import CPEComponent
[docs]class CPESet(object):
"""
Represents a set of CPE Names.
This class allows:
- create a set of CPE Names.
- match a CPE Name against a set of CPE Names.
"""
####################
# OBJECT METHODS #
####################
[docs] def __getitem__(self, i):
"""
Returns the i'th CPE Name of set.
:param int i: CPE Name index to find
:returns: CPE Name found
:rtype: CPE
:exception: IndexError - list index out of range
"""
return self.K[i]
[docs] def __init__(self):
"""
Creates an empty set of CPE Names.
:returns: None
"""
self.K = []
[docs] def __len__(self):
"""
Returns the count of CPE Names of set.
:returns: count of components of CPE Name
:rtype: int
TEST: empty set
>>> from cpeset1_1 import CPESet1_1
>>> s = CPESet1_1()
>>> len(s)
0
"""
return len(self.K)
[docs] def __str__(self):
"""
Returns a human-readable representation of CPE set.
:returns: Representation of CPE set as string
:rtype: string
"""
setlen = self.__len__()
str = []
str.append("CPE Set version {0} contains {1} elements".format(
self.VERSION, setlen))
if setlen > 0:
str.append(":")
for i in range(0, setlen):
str.append(" {0}".format(self.K[i].__str__()))
return "\n".join(str)
[docs] def append(self, cpe):
"""
Adds a CPE Name to the set if not already.
:param CPE cpe: CPE Name to store in set
:returns: None
:exception: NotImplementedError - Method not implemented
"""
errmsg = "Method not implemented. Use the method of some child class"
raise NotImplementedError(errmsg)
[docs] def name_match(self, cpe):
"""
Accepts a set of known instances of CPE Names and a candidate CPE Name,
and returns 'True' if the candidate can be shown to be
an instance based on the content of the known instances.
Otherwise, it returns 'False'.
:param CPESet self: A set of m known CPE Names K = {K1, K2, …, Km}.
:param CPE cpe: A candidate CPE Name X.
:returns: True if X matches K, otherwise False.
:rtype: boolean
"""
# An empty set not matching with any CPE
if len(self) == 0:
return False
# If input CPE Name string is in set of CPE Name strings
# not do searching more because there is a matching
for k in self.K:
if (k.cpe_str == cpe.cpe_str):
return True
# If "cpe" is an empty CPE Name any system matches
if len(cpe) == 0:
return True
# There are not a CPE Name string in set equal to
# input CPE Name string
match = False
for p in CPE.CPE_PART_KEYS:
elems_cpe = cpe.get(p)
for ec in elems_cpe:
# Search of element of part of input CPE
# Each element ec of input cpe[p] is compared with
# each element ek of k[p] in set K
for k in self.K:
if (len(k) >= len(cpe)):
elems_k = k.get(p)
for ek in elems_k:
# Matching
# Each component in element ec is compared with
# each component in element ek
for c in range(0, len(cpe)):
key = CPEComponent.ordered_comp_parts[c]
comp_cpe = ec.get(key)
comp_k = ek.get(key)
match = comp_k in comp_cpe
if not match:
# Search compoment in another element ek[p]
break
# Component analyzed
if match:
# Element matched
break
if match:
break
# Next element in part in "cpe"
if not match:
# cpe part not match with parts in set
return False
# Next part in input CPE Name
# All parts in input CPE Name matched
return True