Example #1
0
    def parse(self, ins):

        result = False

        self.setProperties({})

        LOOK_FOR_CONTAINER = 0
        GET_PROPERTY_OR_COMPONENT = 1

        state = LOOK_FOR_CONTAINER

        # Get lines looking for start of calendar
        lines = [None, None]
        comp = self
        compend = None
        componentstack = []

        while readFoldedLine(ins, lines):

            line = lines[0]

            if state == LOOK_FOR_CONTAINER:

                # Look for start
                if line == self.getBeginDelimiter():
                    # Next state
                    state = GET_PROPERTY_OR_COMPONENT

                    # Indicate success at this point
                    result = True

                # Handle blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("%s data has blank lines" % (self.sContainerDescriptor,))

                # Unrecognized data
                else:
                    raise InvalidData("%s data not recognized" % (self.sContainerDescriptor,), line)

            elif state == GET_PROPERTY_OR_COMPONENT:

                # Parse property or look for start of component
                if line.startswith("BEGIN:") and self.sComponentType is not None:

                    # Push previous details to stack
                    componentstack.append((comp, compend,))

                    # Start a new component
                    comp = self.sComponentType.makeComponent(line[6:], comp)
                    compend = comp.getEndDelimiter()

                # Look for end of object
                elif line == self.getEndDelimiter():

                    # Finalise the current calendar
                    self.finalise()

                    # Change state
                    state = LOOK_FOR_CONTAINER

                # Look for end of current component
                elif line == compend:

                    # Finalise the component (this caches data from the properties)
                    comp.finalise()

                    # Embed component in parent and reset to use parent
                    componentstack[-1][0].addComponent(comp)
                    comp, compend = componentstack.pop()

                # Blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("%s data has blank lines" % (self.sContainerDescriptor,))

                # Must be a property
                else:

                    # Parse parameter/value for top-level calendar item
                    prop = self.sPropertyType.parseText(line)

                    # Check for valid property
                    if comp is self:
                        if not comp.validProperty(prop):
                            raise InvalidData("Invalid property", str(prop))
                        else:
                            comp.addProperty(prop)
                    else:
                        comp.addProperty(prop)

        # Check for truncated data
        if state != LOOK_FOR_CONTAINER:
            raise InvalidData("%s data not complete" % (self.sContainerDescriptor,))

        # Validate some things
        if result and not self.hasProperty("VERSION"):
            raise InvalidData("%s missing VERSION" % (self.sContainerDescriptor,))

        return result
Example #2
0
    def parseMultipleTextData(cls, ins):

        if isinstance(ins, str):
            ins = StringIO(ins)

        results = []

        card = cls(add_defaults=False)

        LOOK_FOR_VCARD = 0
        GET_PROPERTY = 1

        state = LOOK_FOR_VCARD

        # Get lines looking for start of calendar
        lines = [None, None]

        while readFoldedLine(ins, lines):

            line = lines[0]
            if state == LOOK_FOR_VCARD:

                # Look for start
                if line == card.getBeginDelimiter():
                    # Next state
                    state = GET_PROPERTY

                # Handle blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("vCard data has blank lines")

                # Unrecognized data
                else:
                    raise InvalidData("vCard data not recognized", line)

            elif state == GET_PROPERTY:

                # Look for end of object
                if line == card.getEndDelimiter():

                    # Finalise the current calendar
                    card.finalise()

                    # Validate some things
                    if not card.hasProperty("VERSION"):
                        raise InvalidData("vCard missing VERSION", "")

                    results.append(card)

                    # Change state
                    card = Card(add_defaults=False)
                    state = LOOK_FOR_VCARD

                # Blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("vCard data has blank lines")

                # Must be a property
                else:

                    # Parse parameter/value for top-level calendar item
                    prop = Property.parseText(line)

                    # Check for valid property
                    if not card.validProperty(prop):
                        raise InvalidData("Invalid property", str(prop))
                    else:
                        card.addProperty(prop)

        # Check for truncated data
        if state != LOOK_FOR_VCARD:
            raise InvalidData("vCard data not complete")

        return results
Example #3
0
    def parseComponent(self, ins):

        result = None

        LOOK_FOR_VCALENDAR = 0
        GET_PROPERTY_OR_COMPONENT = 1
        GOT_VCALENDAR = 4

        state = LOOK_FOR_VCALENDAR

        # Get lines looking for start of calendar
        lines = [None, None]
        comp = self
        compend = None
        componentstack = []
        got_timezone = False

        while readFoldedLine(ins, lines):

            line = lines[0]

            if state == LOOK_FOR_VCALENDAR:

                # Look for start
                if line == self.getBeginDelimiter():
                    # Next state
                    state = GET_PROPERTY_OR_COMPONENT

                # Handle blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("iCalendar data has blank lines")

                # Unrecognized data
                else:
                    raise InvalidData("iCalendar data not recognized", line)

            elif state == GET_PROPERTY_OR_COMPONENT:

                # Parse property or look for start of component
                if line.startswith("BEGIN:"):

                    # Push previous details to stack
                    componentstack.append((comp, compend,))

                    # Start a new component
                    comp = self.sComponentType.makeComponent(line[6:], comp)
                    compend = comp.getEndDelimiter()

                    # Cache as result - but only the first one, we ignore the rest
                    if result is None:
                        result = comp

                    # Look for timezone component to trigger timezone merge only if one is present
                    if comp.getType() == definitions.cICalComponent_VTIMEZONE:
                        got_timezone = True

                elif line == self.getEndDelimiter():

                    # Change state
                    state = GOT_VCALENDAR

                # Look for end of current component
                elif line == compend:

                    # Finalise the component (this caches data from the properties)
                    comp.finalise()

                    # Embed component in parent and reset to use parent
                    componentstack[-1][0].addComponent(comp)
                    comp, compend = componentstack.pop()

                # Blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("iCalendar data has blank lines")

                # Ignore top-level items
                elif comp is self:
                    pass

                # Must be a property
                else:

                    # Parse parameter/value for top-level calendar item
                    prop = self.sPropertyType.parseText(line)

                    # Check for valid property
                    if comp is not self:
                        comp.addProperty(prop)

            # Exit if we have one - ignore all the rest
            if state == GOT_VCALENDAR:
                break

        # We need to store all timezones in the static object so they can be accessed by any date object
        # Only do this if we read in a timezone
        if got_timezone:
            from pycalendar.timezonedb import TimezoneDatabase
            TimezoneDatabase.mergeTimezones(self, self.getComponents(definitions.cICalComponent_VTIMEZONE))

        return result
Example #4
0
    def parseComponent(self, ins):

        result = None

        LOOK_FOR_VCALENDAR = 0
        GET_PROPERTY_OR_COMPONENT = 1
        GOT_VCALENDAR = 4

        state = LOOK_FOR_VCALENDAR

        # Get lines looking for start of calendar
        lines = [None, None]
        comp = self
        compend = None
        componentstack = []
        got_timezone = False

        while readFoldedLine(ins, lines):

            line = lines[0]

            if state == LOOK_FOR_VCALENDAR:

                # Look for start
                if line == self.getBeginDelimiter():
                    # Next state
                    state = GET_PROPERTY_OR_COMPONENT

                # Handle blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("iCalendar data has blank lines")

                # Unrecognized data
                else:
                    raise InvalidData("iCalendar data not recognized", line)

            elif state == GET_PROPERTY_OR_COMPONENT:

                # Parse property or look for start of component
                if line.startswith("BEGIN:"):

                    # Push previous details to stack
                    componentstack.append((comp, compend,))

                    # Start a new component
                    comp = self.sComponentType.makeComponent(line[6:], comp)
                    compend = comp.getEndDelimiter()

                    # Cache as result - but only the first one, we ignore the rest
                    if result is None:
                        result = comp

                    # Look for timezone component to trigger timezone merge only if one is present
                    if comp.getType() == definitions.cICalComponent_VTIMEZONE:
                        got_timezone = True

                elif line == self.getEndDelimiter():

                    # Change state
                    state = GOT_VCALENDAR

                # Look for end of current component
                elif line == compend:

                    # Finalise the component (this caches data from the properties)
                    comp.finalise()

                    # Embed component in parent and reset to use parent
                    componentstack[-1][0].addComponent(comp)
                    comp, compend = componentstack.pop()

                # Blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("iCalendar data has blank lines")

                # Ignore top-level items
                elif comp is self:
                    pass

                # Must be a property
                else:

                    # Parse parameter/value for top-level calendar item
                    prop = self.sPropertyType.parseText(line)

                    # Check for valid property
                    if comp is not self:
                        comp.addProperty(prop)

            # Exit if we have one - ignore all the rest
            if state == GOT_VCALENDAR:
                break

        # We need to store all timezones in the static object so they can be accessed by any date object
        # Only do this if we read in a timezone
        if got_timezone:
            from pycalendar.timezonedb import TimezoneDatabase
            TimezoneDatabase.mergeTimezones(self, self.getComponents(definitions.cICalComponent_VTIMEZONE))

        return result
Example #5
0
    def parseMultipleTextData(cls, ins):

        if isinstance(ins, str):
            ins = StringIO(ins)

        results = []

        card = cls(add_defaults=False)

        LOOK_FOR_VCARD = 0
        GET_PROPERTY = 1

        state = LOOK_FOR_VCARD

        # Get lines looking for start of calendar
        lines = [None, None]

        while readFoldedLine(ins, lines):

            line = lines[0]
            if state == LOOK_FOR_VCARD:

                # Look for start
                if line == card.getBeginDelimiter():
                    # Next state
                    state = GET_PROPERTY

                # Handle blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("vCard data has blank lines")

                # Unrecognized data
                else:
                    raise InvalidData("vCard data not recognized", line)

            elif state == GET_PROPERTY:

                # Look for end of object
                if line == card.getEndDelimiter():

                    # Finalise the current calendar
                    card.finalise()

                    # Validate some things
                    if not card.hasProperty("VERSION"):
                        raise InvalidData("vCard missing VERSION", "")

                    results.append(card)

                    # Change state
                    card = Card(add_defaults=False)
                    state = LOOK_FOR_VCARD

                # Blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("vCard data has blank lines")

                # Must be a property
                else:

                    # Parse parameter/value for top-level calendar item
                    prop = Property.parseText(line)

                    # Check for valid property
                    if not card.validProperty(prop):
                        raise InvalidData("Invalid property", str(prop))
                    else:
                        card.addProperty(prop)

        # Check for truncated data
        if state != LOOK_FOR_VCARD:
            raise InvalidData("vCard data not complete")

        return results
Example #6
0
    def parse(self, ins):

        result = False

        self.setProperties({})

        LOOK_FOR_CONTAINER = 0
        GET_PROPERTY_OR_COMPONENT = 1

        state = LOOK_FOR_CONTAINER

        # Get lines looking for start of calendar
        lines = [None, None]
        comp = self
        compend = None
        componentstack = []

        while readFoldedLine(ins, lines):

            line = lines[0]

            if state == LOOK_FOR_CONTAINER:

                # Look for start
                if line == self.getBeginDelimiter():
                    # Next state
                    state = GET_PROPERTY_OR_COMPONENT

                    # Indicate success at this point
                    result = True

                # Handle blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("%s data has blank lines" %
                                          (self.sContainerDescriptor, ))

                # Unrecognized data
                else:
                    raise InvalidData(
                        "%s data not recognized" %
                        (self.sContainerDescriptor, ), line)

            elif state == GET_PROPERTY_OR_COMPONENT:

                # Parse property or look for start of component
                if line.startswith(
                        "BEGIN:") and self.sComponentType is not None:

                    # Push previous details to stack
                    componentstack.append((
                        comp,
                        compend,
                    ))

                    # Start a new component
                    comp = self.sComponentType.makeComponent(line[6:], comp)
                    compend = comp.getEndDelimiter()

                # Look for end of object
                elif line == self.getEndDelimiter():

                    # Finalise the current calendar
                    self.finalise()

                    # Change state
                    state = LOOK_FOR_CONTAINER

                # Look for end of current component
                elif line == compend:

                    # Finalise the component (this caches data from the properties)
                    comp.finalise()

                    # Embed component in parent and reset to use parent
                    componentstack[-1][0].addComponent(comp)
                    comp, compend = componentstack.pop()

                # Blank line
                elif len(line) == 0:
                    # Raise if requested, otherwise just ignore
                    if ParserContext.BLANK_LINES_IN_DATA == ParserContext.PARSER_RAISE:
                        raise InvalidData("%s data has blank lines" %
                                          (self.sContainerDescriptor, ))

                # Must be a property
                else:

                    # Parse parameter/value for top-level calendar item
                    prop = self.sPropertyType.parseText(line)

                    # Check for valid property
                    if comp is self:
                        if not comp.validProperty(prop):
                            raise InvalidData("Invalid property", str(prop))
                        else:
                            comp.addProperty(prop)
                    else:
                        comp.addProperty(prop)

        # Check for truncated data
        if state != LOOK_FOR_CONTAINER:
            raise InvalidData("%s data not complete" %
                              (self.sContainerDescriptor, ))

        # Validate some things
        if result and not self.hasProperty("VERSION"):
            raise InvalidData("%s missing VERSION" %
                              (self.sContainerDescriptor, ))

        return result