Source code for cpe.cpe2_3_wfn

#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""
This file is part of cpe package.

This module is used to the treatment of identifiers
of IT platforms (hardware, operating systems or applications of system)
in accordance with Well-Formed Name (WFN) of version 2.3 of CPE
(Common Platform Enumeration) 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 cpe2_3 import CPE2_3
from comp.cpecomp import CPEComponent
from comp.cpecomp_logical import CPEComponentLogical
from comp.cpecomp2_3_wfn import CPEComponent2_3_WFN
from comp.cpecomp_undefined import CPEComponentUndefined
from comp.cpecomp_anyvalue import CPEComponentAnyValue
from comp.cpecomp_notapplicable import CPEComponentNotApplicable


[docs]class CPE2_3_WFN(CPE2_3): """ Implementation of WFN of version 2.3 of CPE specification. A CPE Name is a percent-encoded WFN with each name starting with the prefix 'wfn:'. Each platform can be broken down into many distinct parts. A CPE Name specifies a simple part and is used to identify any platform that matches the description of that part. The distinct parts are: - Hardware part: the physical platform supporting the IT system. - Operating system part: the operating system controls and manages the IT hardware. - Application part: software systems, services, servers, and packages installed on the system. CPE Name syntax: wfn:[a1=v1, a2=v2, …, an=vn] Only the following attributes SHALL be permitted in a WFN attribute-value pair: a. part b. vendor c. product d. version e. update f. edition g. language h. sw_edition i. target_sw j. target_hw k. other """ ############### # CONSTANTS # ############### #: Style of CPE Name STYLE = CPE2_3.STYLE_WFN #: Prefix of CPE Name with WFN style CPE_PREFIX = "wfn:[" #: Suffix of CPE Name with WFN style CPE_SUFFIX = "]" #################### # OBJECT METHODS # ####################
[docs] def __new__(cls, cpe_str, *args, **kwargs): """ Create a new CPE Name of version 2.3 with WFN style. :param string cpe_str: CPE Name string :returns: CPE object of version 2.3 of CPE specification with WFN style. :rtype: CPE2_3_WFN """ return dict.__new__(cls)
def _parse(self): """ Checks if the CPE Name is valid. :returns: None :exception: ValueError - bad-formed CPE Name """ # Check prefix and initial bracket of WFN if self._str[0:5] != CPE2_3_WFN.CPE_PREFIX: errmsg = "Bad-formed CPE Name: WFN prefix not found" raise ValueError(errmsg) # Check final backet if self._str[-1:] != "]": errmsg = "Bad-formed CPE Name: final bracket of WFN not found" raise ValueError(errmsg) content = self._str[5:-1] if content != "": # Dictionary with pairs attribute-value components = dict() # Split WFN in components list_component = content.split(CPEComponent2_3_WFN.SEPARATOR_COMP) # Adds the defined components for e in list_component: # Whitespace not valid in component names and values if e.find(" ") != -1: msg = "Bad-formed CPE Name: WFN with too many whitespaces" raise ValueError(msg) # Split pair attribute-value pair = e.split(CPEComponent2_3_WFN.SEPARATOR_PAIR) att_name = pair[0] att_value = pair[1] # Check valid attribute name if att_name not in CPEComponent.CPE_COMP_KEYS_EXTENDED: msg = "Bad-formed CPE Name: invalid attribute name '{0}'".format( att_name) raise ValueError(msg) if att_name in components: # Duplicate attribute msg = "Bad-formed CPE Name: attribute '{0}' repeated".format( att_name) raise ValueError(msg) if not (att_value.startswith('"') and att_value.endswith('"')): # Logical value strUpper = att_value.upper() if strUpper == CPEComponent2_3_WFN.VALUE_ANY: comp = CPEComponentAnyValue() elif strUpper == CPEComponent2_3_WFN.VALUE_NA: comp = CPEComponentNotApplicable() else: msg = "Invalid logical value '{0}'".format(att_value) raise ValueError(msg) elif att_value.startswith('"') and att_value.endswith('"'): # String value comp = CPEComponent2_3_WFN(att_value, att_name) else: # Bad value msg = "Bad-formed CPE Name: invalid value '{0}'".format( att_value) raise ValueError(msg) components[att_name] = comp # Adds the undefined components for ck in CPEComponent.CPE_COMP_KEYS_EXTENDED: if ck not in components: components[ck] = CPEComponentUndefined() # ####################### # Storage of CPE Name # # ####################### part_comp = components[CPEComponent.ATT_PART] if isinstance(part_comp, CPEComponentLogical): elements = [] elements.append(components) self[CPE.KEY_UNDEFINED] = elements else: # Create internal structure of CPE Name in parts: # one of them is filled with identified components, # the rest are empty part_value = part_comp.get_value() # Del double quotes of value system = part_value[1:-1] if system in CPEComponent.SYSTEM_VALUES: self._create_cpe_parts(system, components) else: self._create_cpe_parts(CPEComponent.VALUE_PART_UNDEFINED, components) # Fills the empty parts of internal structure of CPE Name for pk in CPE.CPE_PART_KEYS: if pk not in self.keys(): self[pk] = []
[docs] def get_attribute_values(self, att_name): """ Returns the values of attribute "att_name" of CPE Name. By default a only element in each part. :param string att_name: Attribute name to get :returns: List of attribute values :rtype: list :exception: ValueError - invalid attribute name """ lc = [] if not CPEComponent.is_valid_attribute(att_name): errmsg = "Invalid attribute name '{0}'".format(att_name) raise ValueError(errmsg) for pk in CPE.CPE_PART_KEYS: elements = self.get(pk) for elem in elements: comp = elem.get(att_name) if (isinstance(comp, CPEComponentAnyValue) or isinstance(comp, CPEComponentUndefined)): value = CPEComponent2_3_WFN.VALUE_ANY elif isinstance(comp, CPEComponentNotApplicable): value = CPEComponent2_3_WFN.VALUE_NA else: value = comp.get_value() lc.append(value) return lc
if __name__ == "__main__": import doctest doctest.testmod() doctest.testfile("tests/testfile_cpe2_3_wfn.txt")