def parseTextParameters(self, txt, data): """ Parse parameters, return string point at value. """ try: stripValueSpaces = False # Fix for AB.app base PHOTO properties that use two spaces at start of line while txt: if txt[0] == ';': # Parse parameter # Move past delimiter txt = txt[1:] # Get quoted string or token - in iCalendar we only look for "=" here # but for "broken" vCard BASE64 property we need to also terminate on # ":;" parameter_name, txt = stringutils.strduptokenstr(txt, "=:;") if parameter_name is None: raise InvalidProperty("Invalid property", data) if txt[0] != "=": # Deal with parameters without values if ParserContext.VCARD_2_NO_PARAMETER_VALUES == ParserContext.PARSER_RAISE: raise InvalidProperty("Invalid property parameter", data) elif ParserContext.VCARD_2_NO_PARAMETER_VALUES == ParserContext.PARSER_ALLOW: parameter_value = None else: # PARSER_IGNORE and PARSER_FIX parameter_name = None if parameter_name.upper() == "BASE64" and ParserContext.VCARD_2_BASE64 == ParserContext.PARSER_FIX: parameter_name = definitions.Parameter_ENCODING parameter_value = definitions.Parameter_Value_ENCODING_B stripValueSpaces = True else: txt = txt[1:] parameter_value, txt = stringutils.strduptokenstr(txt, ":;,") if parameter_value is None: raise InvalidProperty("Invalid property", data) # Now add parameter value (decode ^-escaping) if parameter_name is not None: attrvalue = Parameter(name=parameter_name, value=decodeParameterValue(parameter_value)) self.mParameters.setdefault(parameter_name.upper(), []).append(attrvalue) # Look for additional values while txt[0] == ',': txt = txt[1:] parameter_value2, txt = stringutils.strduptokenstr(txt, ":;,") if parameter_value2 is None: raise InvalidProperty("Invalid property", data) attrvalue.addValue(decodeParameterValue(parameter_value2)) elif txt[0] == ':': txt = txt[1:] if stripValueSpaces: txt = txt.replace(" ", "") return txt except IndexError: raise InvalidProperty("Invalid property", data)
def test_strduptokenstr(self): """ Make sure L{strduptokenstr} copes with all possibilities. """ data = ( # Leading space (" abc:def", ":;", ("abc", ":def")), (" \"abc\":def", ":;", ("abc", ":def")), (" ", ":;", (None, "")), # Quoted ("\"abc\":def", ":;", ("abc", ":def")), ("\"ab\\c\":def", ":;", ("ab\\c", ":def")), ("\"ab\\c:def", ":;", (None, "\"ab\\c:def")), ("\"abc\":", ":;", ("abc", ":")), ("\"abc\"", ":;", ("abc", "")), # Unuoted ("abc:def", ":;", ("abc", ":def")), ("abc:", ":;", ("abc", ":")), ("abc", ":;", ("abc", "")), ) for txt, tokens, result in data: self.assertEqual(strduptokenstr(txt, tokens), result)
def parseText(cls, data): """ Parse the text format data and return a L{Property} @param data: text data @type data: C{str} """ try: prop = cls() # Look for parameter or value delimiter prop_name, txt = stringutils.strduptokenstr(data, ";:") if not prop_name: raise InvalidProperty("Invalid property: empty name", data) # Get the name if prop.sUsesGroup: # Check for group prefix splits = prop_name.split(".", 1) if len(splits) == 2: # We have both group and name prop.mGroup = splits[0] prop.mName = splits[1] else: # We have the name prop.mName = prop_name else: prop.mName = prop_name # Get the parameters txt = prop.parseTextParameters(txt, data) # Tidy first prop.mValue = None # Get value type from property name value_type = prop.determineValueType() # Check for multivalued if prop.mName.upper() in prop.sMultiValues: prop.mValue = MultiValue(value_type) else: # Create the type prop.mValue = Value.createFromType(value_type) # Now parse the data prop.mValue.parse(txt, prop.sVariant) prop._postCreateValue(value_type) return prop except Exception as e: raise InvalidProperty("Invalid property: '{}'".format(e), data)
def parseText(cls, data): """ Parse the text format data and return a L{Property} @param data: text data @type data: C{str} """ try: prop = cls() # Look for parameter or value delimiter prop_name, txt = stringutils.strduptokenstr(data, ";:") if not prop_name: raise InvalidProperty("Invalid property", data) # Get the name if prop.sUsesGroup: # Check for group prefix splits = prop_name.split(".", 1) if len(splits) == 2: # We have both group and name prop.mGroup = splits[0] prop.mName = splits[1] else: # We have the name prop.mName = prop_name else: prop.mName = prop_name # Get the parameters txt = prop.parseTextParameters(txt, data) # Tidy first prop.mValue = None # Get value type from property name value_type = prop.determineValueType() # Check for multivalued if prop.mName.upper() in prop.sMultiValues: prop.mValue = MultiValue(value_type) else: # Create the type prop.mValue = Value.createFromType(value_type) # Now parse the data prop.mValue.parse(txt, prop.sVariant) prop._postCreateValue(value_type) return prop except Exception: raise InvalidProperty("Invalid property", data)
def parseTextParameters(self, txt, data): """ Parse parameters, return string point at value. """ try: while txt: if txt[0] == ';': # Parse parameter # Move past delimiter txt = txt[1:] # Get quoted string or token parameter_name, txt = stringutils.strduptokenstr(txt, "=") if parameter_name is None: raise InvalidProperty("Invalid property: empty parameter name", data) txt = txt[1:] parameter_value, txt = stringutils.strduptokenstr(txt, ":;,") if parameter_value is None: raise InvalidProperty("Invalid property: empty parameter value", data) # Now add parameter value (decode ^-escaping) attrvalue = Parameter(name=parameter_name, value=decodeParameterValue(parameter_value)) self.mParameters.setdefault(parameter_name.upper(), []).append(attrvalue) # Look for additional values while txt[0] == ',': txt = txt[1:] parameter_value2, txt = stringutils.strduptokenstr(txt, ":;,") if parameter_value2 is None: raise InvalidProperty("Invalid property: empty parameter multi-value", data) attrvalue.addValue(decodeParameterValue(parameter_value2)) elif txt[0] == ':': return txt[1:] else: # We should never get here but if we do we need to terminate the loop raise InvalidProperty("Invalid property: missing value separator", data) except IndexError: raise InvalidProperty("Invalid property: 'parameter index error'", data)
def parseTextParameters(self, txt, data): """ Parse parameters, return string point at value. """ try: while txt: if txt[0] == ';': # Parse parameter # Move past delimiter txt = txt[1:] # Get quoted string or token parameter_name, txt = stringutils.strduptokenstr(txt, "=") if parameter_name is None: raise InvalidProperty("Invalid property", data) txt = txt[1:] parameter_value, txt = stringutils.strduptokenstr(txt, ":;,") if parameter_value is None: raise InvalidProperty("Invalid property", data) # Now add parameter value (decode ^-escaping) attrvalue = Parameter(name=parameter_name, value=decodeParameterValue(parameter_value)) self.mParameters.setdefault(parameter_name.upper(), []).append(attrvalue) # Look for additional values while txt[0] == ',': txt = txt[1:] parameter_value2, txt = stringutils.strduptokenstr(txt, ":;,") if parameter_value2 is None: raise InvalidProperty("Invalid property", data) attrvalue.addValue(decodeParameterValue(parameter_value2)) elif txt[0] == ':': return txt[1:] else: # We should never get here but if we do we need to terminate the loop raise InvalidProperty("Invalid property", data) except IndexError: raise InvalidProperty("Invalid property", data)
def parseTextParameters(self, txt, data): """ Parse parameters, return string point at value. """ try: stripValueSpaces = False # Fix for AB.app base PHOTO properties that use two spaces at start of line while txt: if txt[0] == ';': # Parse parameter # Move past delimiter txt = txt[1:] # Get quoted string or token - in iCalendar we only look for "=" here # but for "broken" vCard BASE64 property we need to also terminate on # ":;" parameter_name, txt = stringutils.strduptokenstr( txt, "=:;") if parameter_name is None: raise InvalidProperty( "Invalid property: empty parameter name", data) if txt[0] != "=": # Deal with parameters without values if ParserContext.VCARD_2_NO_PARAMETER_VALUES == ParserContext.PARSER_RAISE: raise InvalidProperty("Invalid property parameter", data) elif ParserContext.VCARD_2_NO_PARAMETER_VALUES == ParserContext.PARSER_ALLOW: parameter_value = None else: # PARSER_IGNORE and PARSER_FIX parameter_name = None if parameter_name.upper( ) == "BASE64" and ParserContext.VCARD_2_BASE64 == ParserContext.PARSER_FIX: parameter_name = definitions.Parameter_ENCODING parameter_value = definitions.Parameter_Value_ENCODING_B stripValueSpaces = True else: txt = txt[1:] parameter_value, txt = stringutils.strduptokenstr( txt, ":;,") if parameter_value is None: raise InvalidProperty( "Invalid property: empty parameter name", data) # Now add parameter value (decode ^-escaping) if parameter_name is not None: attrvalue = Parameter( name=parameter_name, value=decodeParameterValue(parameter_value)) self.mParameters.setdefault(parameter_name.upper(), []).append(attrvalue) # Look for additional values while txt[0] == ',': txt = txt[1:] parameter_value2, txt = stringutils.strduptokenstr( txt, ":;,") if parameter_value2 is None: raise InvalidProperty( "Invalid property: empty parameter multi-value", data) attrvalue.addValue( decodeParameterValue(parameter_value2)) elif txt[0] == ':': txt = txt[1:] if stripValueSpaces: txt = txt.replace(" ", "") return txt except IndexError: raise InvalidProperty("Invalid property: index error", data)