#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This file is part of cpe package.
This module allows to store the value of the components of a CPE name
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 cpecomp_simple import CPEComponentSimple
import re
[docs]class CPEComponent2_3(CPEComponentSimple):
"""
Represents a component of version 2.3 of CPE specification.
"""
####################
# OBJECT METHODS #
####################
[docs] def __repr__(self):
"""
Returns a unambiguous representation of CPE component.
:returns: Representation of CPE component as string
:rtype: string
"""
value = self.get_value()
return "{0}({1})".format(self.__class__.__name__, value)
def _is_valid_language(self):
"""
Return True if the value of component in attribute "language" is valid,
and otherwise False.
:returns: True if value is valid, False otherwise
:rtype: boolean
CASE 1: Language part with/without region part
CASE 2: Language part without region part
CASE 3: Region part with language part
CASE 4: Region part without language part
"""
def check_generic_language(self, value):
"""
Check possible values in language part
when region part exists or not in language value.
Possible values of language attribute: a=letter
| *a
| *aa
| aa
| aaa
| ?a
| ?aa
| ??
| ??a
| ???
"""
lang_pattern = []
lang_pattern.append("^(\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append("[a-z]{1,2}")
lang_pattern.append("|\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append("(([a-z][a-z]?)|(\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append("(\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append("|[a-z])?))")
lang_pattern.append("|([a-z]{2,3}))$")
lang_rxc = re.compile("".join(lang_pattern))
return lang_rxc.match(value)
def check_language_without_region(self, value):
"""
Check possible values in language part
when region part not exist in language value.
Possible values of language attribute: a=letter
| a?
| aa?
| a??
| a*
| aa*
| aaa*
| *a*
| *a?
| ?a*
| ?a?
"""
lang_pattern = []
lang_pattern.append("^([a-z]")
lang_pattern.append("([a-z](\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append("|\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append("|")
lang_pattern.append("([a-z]\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append("))")
lang_pattern.append("|")
lang_pattern.append("\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append("(\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append(")?")
lang_pattern.append("|\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append(")|\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append("[a-z](\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append("|\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append(")")
lang_pattern.append("|\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append("[a-z](\\")
lang_pattern.append(self.WILDCARD_MULTI)
lang_pattern.append("|\\")
lang_pattern.append(self.WILDCARD_ONE)
lang_pattern.append(")")
lang_pattern.append(")$")
lang_rxc = re.compile("".join(lang_pattern))
return lang_rxc.match(value)
def check_region_with_language(self, value):
"""
Check possible values in region part when language part exists.
Possible values of language attribute: a=letter, 1=digit
| *
| a*
| a?
| aa
| ??
| 1*
| 1??
| 11*
| 11?
| 111
| ???
"""
region_pattern = []
region_pattern.append("^(")
region_pattern.append("(\\")
region_pattern.append(self.WILDCARD_MULTI)
region_pattern.append(")|((\\")
region_pattern.append(self.WILDCARD_ONE)
region_pattern.append("){2,3})|([a-z]([a-z]|\\")
region_pattern.append(self.WILDCARD_MULTI)
region_pattern.append("|\\")
region_pattern.append(self.WILDCARD_ONE)
region_pattern.append("))|([0-9](\\")
region_pattern.append(self.WILDCARD_MULTI)
region_pattern.append("|\\")
region_pattern.append(self.WILDCARD_ONE)
region_pattern.append("(\\")
region_pattern.append(self.WILDCARD_ONE)
region_pattern.append(")?|[0-9][0-9\\")
region_pattern.append(self.WILDCARD_MULTI)
region_pattern.append("\\")
region_pattern.append(self.WILDCARD_ONE)
region_pattern.append("])))$")
region_rxc = re.compile("".join(region_pattern))
return region_rxc.match(region)
def check_region_without_language(self, value):
"""
Check possible values in region part when language part not exist.
Possible values of language attribute: 1=digit
| *111
| *11
| *1
"""
region_pattern = []
region_pattern.append("^(")
region_pattern.append("(\\")
region_pattern.append(self.WILDCARD_MULTI)
region_pattern.append("[0-9])")
region_pattern.append("([0-9]([0-9])?)?")
region_pattern.append(")$")
region_rxc = re.compile("".join(region_pattern))
return region_rxc.match(region)
comp_str = self._encoded_value.lower()
# Value with wildcards; separate language and region of value
parts = comp_str.split(self.SEPARATOR_LANG)
language = parts[0]
region_exists = len(parts) == 2
# Check the language part
if check_generic_language(self, language) is not None:
# Valid language, check region part
if region_exists:
# Region part exists; check it
region = parts[1]
return (check_region_with_language(self, region) is not None)
else:
# Not region part
return True
elif check_language_without_region(self, language) is not None:
# Language without region; region part should not exist
return not region_exists
else:
# Language part not exist; check region part
region = parts[0]
return check_region_without_language(self, region) is not None
def _is_valid_part(self):
"""
Return True if the value of component in attribute "part" is valid,
and otherwise False.
:returns: True if value of component is valid, False otherwise
:rtype: boolean
"""
comp_str = self._encoded_value
# Check if value of component do not have wildcard
if ((comp_str.find(self.WILDCARD_ONE) == -1) and
(comp_str.find(self.WILDCARD_MULTI) == -1)):
return super(CPEComponent2_3, self)._is_valid_part()
# Compilation of regular expression associated with value of part
part_pattern = "^(\{0}|\{1})$".format(self.WILDCARD_ONE,
self.WILDCARD_MULTI)
part_rxc = re.compile(part_pattern)
return part_rxc.match(comp_str) is not None