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 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 parseJSON(cls, jobject): """ Parse a JSON property of the form: [name, attrs, type, value1, value2, ...] @param jobject: a JSON array @type jobject: C{list} """ try: prop = cls() # Get the name prop.mName = jobject[0].encode("utf-8").upper() # Get the parameters if jobject[1]: for name, value in jobject[1].items(): # Now add parameter value name = name.upper() attrvalue = Parameter(name=name.encode("utf-8"), value=value.encode("utf-8")) prop.mParameters.setdefault(name, []).append(attrvalue) # Get default value type from property name and insert a VALUE parameter if current value type is not default value_type = cls.sValueTypeMap.get(jobject[2].upper(), Value.VALUETYPE_UNKNOWN) default_type = cls.sDefaultValueTypeMap.get(prop.mName.upper(), Value.VALUETYPE_UNKNOWN) if default_type != value_type: attrvalue = Parameter(name=cls.sValue, value=jobject[2].encode("utf-8").upper()) prop.mParameters.setdefault(cls.sValue, []).append(attrvalue) # Get value type from property name value_type = prop.determineValueType() # Check for multivalued values = jobject[3:] if prop.mName.upper() in cls.sMultiValues: prop.mValue = MultiValue(value_type) prop.mValue.parseJSONValue(values) else: # Create the type prop.mValue = Value.createFromType(value_type) prop.mValue.parseJSONValue(values[0]) # Special post-create for some types prop._postCreateValue(value_type) return prop except Exception as e: raise InvalidProperty("Invalid property: '{}'".format(e), jobject)
def createValue(self, data): # Tidy first self.mValue = None # Get value type from property name value_type = self.determineValueType() # Check for multivalued if self.mName.upper() in self.sMultiValues: self.mValue = MultiValue(value_type) else: # Create the type self.mValue = Value.createFromType(value_type) # Now parse the data try: self.mValue.parse(data, self.sVariant) except ValueError as e: raise InvalidProperty("Invalid property value: '{}'".format(e), data) self._postCreateValue(value_type)
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)