Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    def testParameterEncodingDecoding(self):

        prop = Property("X-FOO", "Test")
        prop.addParameter(Parameter("X-BAR", "\"Check\""))
        self.assertEqual(str(prop), "X-FOO;X-BAR=^'Check^':Test\r\n")

        prop.addParameter(Parameter("X-BAR2", "Check\nThis\tOut\n"))
        self.assertEqual(str(prop), "X-FOO;X-BAR=^'Check^';X-BAR2=Check^nThis\tOut^n:Test\r\n")

        data = "X-FOO;X-BAR=^'Check^':Test"
        prop = Property.parseText(data)
        self.assertEqual(prop.getParameterValue("X-BAR"), "\"Check\"")

        data = "X-FOO;X-BAR=^'Check^';X-BAR2=Check^nThis\tOut^n:Test"
        prop = Property.parseText(data)
        self.assertEqual(prop.getParameterValue("X-BAR"), "\"Check\"")
        self.assertEqual(prop.getParameterValue("X-BAR2"), "Check\nThis\tOut\n")
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    def _init_attr_value_datetime(self, dt):
        # Value
        self.mValue = DateTimeValue(value=dt)

        # Parameters
        self.setupValueParameter()

        # Look for timezone
        if not dt.isDateOnly() and dt.local():
            if definitions.cICalParameter_TZID in self.mParameters:
                del self.mParameters[definitions.cICalParameter_TZID]
            self.mParameters.setdefault(
                definitions.cICalParameter_TZID, []).append(
                    Parameter(name=definitions.cICalParameter_TZID,
                              value=dt.getTimezoneID()))
Example #7
0
    def testAddCN(self):

        data = (
            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
ORGANIZER:[email protected]
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
            "まだ",
            """BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//mulberrymail.com//Mulberry v4.0//EN
BEGIN:VEVENT
UID:C3184A66-1ED0-11D9-A5E0-000A958A3252
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
DTSTAMP:20020101T000000Z
RRULE:FREQ=YEARLY;UNTIL=20031231;BYMONTH=1
ORGANIZER;CN=まだ:[email protected]
SUMMARY:New Year's Day
END:VEVENT
END:VCALENDAR
""".replace("\n", "\r\n"),
        )

        cal1 = Calendar()
        cal1.parse(StringIO.StringIO(data[0]))

        vevent = cal1.getComponents("VEVENT")[0]
        organizer = vevent.getProperties("ORGANIZER")[0]
        organizer.addParameter(Parameter("CN", data[1]))

        cal2 = Calendar()
        cal2.parse(StringIO.StringIO(data[2]))

        self.assertEqual(str(cal1), str(cal2))
Example #8
0
    def editTriggerBy(self, duration, trigger_start):
        # Remove existing
        self.removeProperties(definitions.cICalProperty_TRIGGER)

        # Updated cached values
        self.mTriggerAbsolute = False
        self.mTriggerBy = duration
        self.mTriggerOnStart = trigger_start

        # Add new (with parameter)
        prop = Property(definitions.cICalProperty_TRIGGER, duration)
        attr = Parameter(
            definitions.cICalParameter_RELATED,
            (definitions.cICalParameter_RELATED_START,
             definitions.cICalParameter_RELATED_END)[not trigger_start])
        prop.addParameter(attr)
        self.addProperty(prop)
        def removePropertiesParameters(component):

            if not doTimezones:
                for subcomponent in tuple(component.getComponents()):
                    if subcomponent.getType() == "VTIMEZONE":
                        component.removeComponent(subcomponent)

            for subcomponent in component.getComponents():
                removePropertiesParameters(subcomponent)

            if component.getType() == "VEVENT":
                if component.hasEnd():
                    component.editTimingStartDuration(
                        component.getStart(),
                        component.getEnd() - component.getStart())

            allProps = []
            for properties in component.getProperties().itervalues():
                allProps.extend(properties)
            for property in allProps:
                # Always reset DTSTAMP on these properties
                if property.getName() in ("ATTENDEE",
                                          "X-CALENDARSERVER-ATTENDEE-COMMENT"):
                    if property.hasParameter("X-CALENDARSERVER-DTSTAMP"):
                        property.replaceParameter(
                            Parameter("X-CALENDARSERVER-DTSTAMP",
                                      "20080101T000000Z"))

                for filter in filters:
                    if ":" in filter:
                        propname, parameter = filter.split(":")
                        if property.getName() == propname:
                            if property.hasParameter(parameter):
                                property.removeParameters(parameter)
                    else:
                        if "=" in filter:
                            filter_name, filter_value = filter.split("=")
                            if property.getName(
                            ) == filter_name and property.getValue().getValue(
                            ) == filter_value:
                                component.removeProperty(property)
                        else:
                            if property.getName() == filter:
                                component.removeProperty(property)
Example #10
0
    def setupValueParameter(self):
        if self.sValue in self.mParameters:
            del self.mParameters[self.sValue]

        # Only if we have a value right now
        if self.mValue is None:
            return

        # See if current type is default for this property. If there is no mapping available,
        # then always add VALUE if it is not TEXT. Always add the value if listed in the
        # C{sAlwaysValueTypes} attribute.
        default_type = self.sDefaultValueTypeMap.get(self.mName.upper())
        if self.mName.upper() in self.sSpecialVariants:
            actual_type = default_type
        else:
            actual_type = self.mValue.getType()
        if default_type is None or default_type != actual_type or self.mName.upper() in self.sAlwaysValueTypes:
            actual_value = self.sTypeValueMap.get(actual_type)
            if actual_value is not None and (default_type is not None or actual_type != Value.VALUETYPE_TEXT):
                self.mParameters.setdefault(self.sValue, []).append(Parameter(name=self.sValue, value=actual_value))
Example #11
0
    def _init_attr_value_datetimelist(self, dtl):
        # Value
        date_only = (len(dtl) > 0) and dtl[0].isDateOnly()
        if date_only:
            self.mValue = MultiValue(Value.VALUETYPE_DATE)
        else:
            self.mValue = MultiValue(Value.VALUETYPE_DATETIME)

        for dt in dtl:
            self.mValue.addValue(DateTimeValue(dt))

        # Parameters
        self.setupValueParameter()

        # Look for timezone
        if ((len(dtl) > 0) and not dtl[0].isDateOnly() and dtl[0].local()):
            if definitions.cICalParameter_TZID in self.mParameters:
                del self.mParameters[definitions.cICalParameter_TZID]
            self.mParameters.setdefault(
                definitions.cICalParameter_TZID, []).append(
                    Parameter(name=definitions.cICalParameter_TZID,
                              value=dtl[0].getTimezoneID()))
Example #12
0
    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)
Example #13
0
        # Replace with anonymized CUAs:
        for propName in ('organizer', 'attendee'):
            try:
                for prop in tuple(comp.getProperties(propName)):
                    cua = prop.getValue().getValue()
                    record = directoryMap.lookupCUA(cua)
                    if record is None:
                        # print("Can't find record for", cua)
                        record = directoryMap.addRecord(cua=cua)
                        if record is None:
                            comp.removeProperty(prop)
                            continue
                    prop.setValue("urn:uuid:%s" % (record['guid'], ))
                    if prop.hasParameter('X-CALENDARSERVER-EMAIL'):
                        prop.replaceParameter(
                            Parameter('X-CALENDARSERVER-EMAIL',
                                      record['email']))
                    else:
                        prop.removeParameters('EMAIL')
                        prop.addParameter(Parameter('EMAIL', record['email']))
                    prop.removeParameters('CN')
                    prop.addParameter(Parameter('CN', record['name']))
            except KeyError:
                pass

        # Replace with anonymized text:
        for propName in ('summary', 'location', 'description'):
            try:
                for prop in comp.getProperties(propName):
                    prop.setValue(anonymize(prop.getValue().getValue()))
            except KeyError:
                pass