Example #1
0
 def resources_listener(path, datetime, key, value, extra):
     if len(path) != 1:
         raise ValueError("Invalid path " + str(path))
     uid = path[0]
     href = extra.get_href(uid)
     if value is None:
         if extra._get(href) is not None:
             extra.delete(href, update_decsync=False)
     else:
         vobject_item = vobject.readOne(value)
         if sync_type == "contacts":
             tag = "VADDRESSBOOK"
         else:
             tag = "VCALENDAR"
         radicale_item.check_and_sanitize_items([vobject_item],
                                                tag=tag)
         item = radicale_item.Item(collection=extra,
                                   vobject_item=vobject_item,
                                   uid=uid)
         item.prepare()
         extra.upload(href, item, update_decsync=False)
Example #2
0
        def prepare(vobject_items, tag=None, write_whole_collection=None):
            if (write_whole_collection
                    or permissions and not parent_permissions):
                write_whole_collection = True
                content_type = environ.get("CONTENT_TYPE", "").split(";")[0]
                tags = {
                    value: key
                    for key, value in xmlutils.MIMETYPES.items()
                }
                tag = radicale_item.predict_tag_of_whole_collection(
                    vobject_items, tags.get(content_type))
                if not tag:
                    raise ValueError("Can't determine collection tag")
                collection_path = pathutils.strip_path(path)
            elif (write_whole_collection is not None
                  and not write_whole_collection
                  or not permissions and parent_permissions):
                write_whole_collection = False
                if tag is None:
                    tag = radicale_item.predict_tag_of_parent_collection(
                        vobject_items)
                collection_path = posixpath.dirname(pathutils.strip_path(path))
            props = None
            stored_exc_info = None
            items = []
            try:
                if tag:
                    radicale_item.check_and_sanitize_items(
                        vobject_items,
                        is_collection=write_whole_collection,
                        tag=tag)
                    if write_whole_collection and tag == "VCALENDAR":
                        vobject_components = []
                        vobject_item, = vobject_items
                        for content in ("vevent", "vtodo", "vjournal"):
                            vobject_components.extend(
                                getattr(vobject_item, "%s_list" % content, []))
                        vobject_components_by_uid = itertools.groupby(
                            sorted(vobject_components,
                                   key=radicale_item.get_uid),
                            radicale_item.get_uid)
                        for uid, components in vobject_components_by_uid:
                            vobject_collection = vobject.iCalendar()
                            for component in components:
                                vobject_collection.add(component)
                            item = radicale_item.Item(
                                collection_path=collection_path,
                                vobject_item=vobject_collection)
                            item.prepare()
                            items.append(item)
                    elif write_whole_collection and tag == "VADDRESSBOOK":
                        for vobject_item in vobject_items:
                            item = radicale_item.Item(
                                collection_path=collection_path,
                                vobject_item=vobject_item)
                            item.prepare()
                            items.append(item)
                    elif not write_whole_collection:
                        vobject_item, = vobject_items
                        item = radicale_item.Item(
                            collection_path=collection_path,
                            vobject_item=vobject_item)
                        item.prepare()
                        items.append(item)

                if write_whole_collection:
                    props = {}
                    if tag:
                        props["tag"] = tag
                    if tag == "VCALENDAR" and vobject_items:
                        if hasattr(vobject_items[0], "x_wr_calname"):
                            calname = vobject_items[0].x_wr_calname.value
                            if calname:
                                props["D:displayname"] = calname
                        if hasattr(vobject_items[0], "x_wr_caldesc"):
                            caldesc = vobject_items[0].x_wr_caldesc.value
                            if caldesc:
                                props["C:calendar-description"] = caldesc
                    radicale_item.check_and_sanitize_props(props)
            except Exception:
                stored_exc_info = sys.exc_info()

            # Use generator for items and delete references to free memory
            # early
            def items_generator():
                while items:
                    yield items.pop(0)

            return (items_generator(), tag, write_whole_collection, props,
                    stored_exc_info)
Example #3
0
 def _get(self, href, verify_href=True):
     if verify_href:
         try:
             if not pathutils.is_safe_filesystem_path_component(href):
                 raise pathutils.UnsafePathError(href)
             path = pathutils.path_to_filesystem(
                 self._filesystem_path, href)
         except ValueError as e:
             logger.debug(
                 "Can't translate name %r safely to filesystem in %r: %s",
                 href, self.path, e, exc_info=True)
             return None
     else:
         path = os.path.join(self._filesystem_path, href)
     try:
         with open(path, "rb") as f:
             raw_text = f.read()
     except (FileNotFoundError, IsADirectoryError):
         return None
     except PermissionError:
         # Windows raises ``PermissionError`` when ``path`` is a directory
         if (os.name == "nt" and
                 os.path.isdir(path) and os.access(path, os.R_OK)):
             return None
         raise
     # The hash of the component in the file system. This is used to check,
     # if the entry in the cache is still valid.
     input_hash = self._item_cache_hash(raw_text)
     cache_hash, uid, etag, text, name, tag, start, end = \
         self._load_item_cache(href, input_hash)
     if input_hash != cache_hash:
         with self._acquire_cache_lock("item"):
             # Lock the item cache to prevent multpile processes from
             # generating the same data in parallel.
             # This improves the performance for multiple requests.
             if self._lock.locked == "r":
                 # Check if another process created the file in the meantime
                 cache_hash, uid, etag, text, name, tag, start, end = \
                     self._load_item_cache(href, input_hash)
             if input_hash != cache_hash:
                 try:
                     vobject_items = tuple(vobject.readComponents(
                         raw_text.decode(self._encoding)))
                     radicale_item.check_and_sanitize_items(
                         vobject_items, tag=self.get_meta("tag"))
                     vobject_item, = vobject_items
                     temp_item = radicale_item.Item(
                         collection=self, vobject_item=vobject_item)
                     cache_hash, uid, etag, text, name, tag, start, end = \
                         self._store_item_cache(
                             href, temp_item, input_hash)
                 except Exception as e:
                     raise RuntimeError("Failed to load item %r in %r: %s" %
                                        (href, self.path, e)) from e
                 # Clean cache entries once after the data in the file
                 # system was edited externally.
                 if not self._item_cache_cleaned:
                     self._item_cache_cleaned = True
                     self._clean_item_cache()
     last_modified = time.strftime(
         "%a, %d %b %Y %H:%M:%S GMT",
         time.gmtime(os.path.getmtime(path)))
     # Don't keep reference to ``vobject_item``, because it requires a lot
     # of memory.
     return radicale_item.Item(
         collection=self, href=href, last_modified=last_modified, etag=etag,
         text=text, uid=uid, name=name, component_name=tag,
         time_range=(start, end))
Example #4
0
 def _get(self, href, verify_href=True):
     if verify_href:
         try:
             if not pathutils.is_safe_filesystem_path_component(href):
                 raise pathutils.UnsafePathError(href)
             path = pathutils.path_to_filesystem(self._filesystem_path,
                                                 href)
         except ValueError as e:
             logger.debug(
                 "Can't translate name %r safely to filesystem in %r: %s",
                 href,
                 self.path,
                 e,
                 exc_info=True)
             return None
     else:
         path = os.path.join(self._filesystem_path, href)
     try:
         with open(path, "rb") as f:
             raw_text = f.read()
     except (FileNotFoundError, IsADirectoryError):
         return None
     except PermissionError:
         # Windows raises ``PermissionError`` when ``path`` is a directory
         if (os.name == "nt" and os.path.isdir(path)
                 and os.access(path, os.R_OK)):
             return None
         raise
     # The hash of the component in the file system. This is used to check,
     # if the entry in the cache is still valid.
     input_hash = self._item_cache_hash(raw_text)
     cache_hash, uid, etag, text, name, tag, start, end = \
         self._load_item_cache(href, input_hash)
     if input_hash != cache_hash:
         with self._acquire_cache_lock("item"):
             # Lock the item cache to prevent multpile processes from
             # generating the same data in parallel.
             # This improves the performance for multiple requests.
             if self._lock.locked == "r":
                 # Check if another process created the file in the meantime
                 cache_hash, uid, etag, text, name, tag, start, end = \
                     self._load_item_cache(href, input_hash)
             if input_hash != cache_hash:
                 try:
                     vobject_items = tuple(
                         vobject.readComponents(
                             raw_text.decode(self._encoding)))
                     radicale_item.check_and_sanitize_items(
                         vobject_items, tag=self.get_meta("tag"))
                     vobject_item, = vobject_items
                     temp_item = radicale_item.Item(
                         collection=self, vobject_item=vobject_item)
                     cache_hash, uid, etag, text, name, tag, start, end = \
                         self._store_item_cache(
                             href, temp_item, input_hash)
                 except Exception as e:
                     raise RuntimeError("Failed to load item %r in %r: %s" %
                                        (href, self.path, e)) from e
                 # Clean cache entries once after the data in the file
                 # system was edited externally.
                 if not self._item_cache_cleaned:
                     self._item_cache_cleaned = True
                     self._clean_item_cache()
     last_modified = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
                                   time.gmtime(os.path.getmtime(path)))
     # Don't keep reference to ``vobject_item``, because it requires a lot
     # of memory.
     return radicale_item.Item(collection=self,
                               href=href,
                               last_modified=last_modified,
                               etag=etag,
                               text=text,
                               uid=uid,
                               name=name,
                               component_name=tag,
                               time_range=(start, end))
Example #5
0
        def prepare(vobject_items, tag=None, write_whole_collection=None):
            if (write_whole_collection or
                    permissions and not parent_permissions):
                write_whole_collection = True
                content_type = environ.get("CONTENT_TYPE",
                                           "").split(";")[0]
                tags = {value: key
                        for key, value in xmlutils.MIMETYPES.items()}
                tag = radicale_item.predict_tag_of_whole_collection(
                    vobject_items, tags.get(content_type))
                if not tag:
                    raise ValueError("Can't determine collection tag")
                collection_path = pathutils.strip_path(path)
            elif (write_whole_collection is not None and
                    not write_whole_collection or
                    not permissions and parent_permissions):
                write_whole_collection = False
                if tag is None:
                    tag = radicale_item.predict_tag_of_parent_collection(
                        vobject_items)
                collection_path = posixpath.dirname(
                    pathutils.strip_path(path))
            props = None
            stored_exc_info = None
            items = []
            try:
                if tag:
                    radicale_item.check_and_sanitize_items(
                        vobject_items, is_collection=write_whole_collection,
                        tag=tag)
                    if write_whole_collection and tag == "VCALENDAR":
                        vobject_components = []
                        vobject_item, = vobject_items
                        for content in ("vevent", "vtodo", "vjournal"):
                            vobject_components.extend(
                                getattr(vobject_item, "%s_list" % content, []))
                        vobject_components_by_uid = itertools.groupby(
                            sorted(vobject_components,
                                   key=radicale_item.get_uid),
                            radicale_item.get_uid)
                        for uid, components in vobject_components_by_uid:
                            vobject_collection = vobject.iCalendar()
                            for component in components:
                                vobject_collection.add(component)
                            item = radicale_item.Item(
                                collection_path=collection_path,
                                vobject_item=vobject_collection)
                            item.prepare()
                            items.append(item)
                    elif write_whole_collection and tag == "VADDRESSBOOK":
                        for vobject_item in vobject_items:
                            item = radicale_item.Item(
                                collection_path=collection_path,
                                vobject_item=vobject_item)
                            item.prepare()
                            items.append(item)
                    elif not write_whole_collection:
                        vobject_item, = vobject_items
                        item = radicale_item.Item(
                            collection_path=collection_path,
                            vobject_item=vobject_item)
                        item.prepare()
                        items.append(item)

                if write_whole_collection:
                    props = {}
                    if tag:
                        props["tag"] = tag
                    if tag == "VCALENDAR" and vobject_items:
                        if hasattr(vobject_items[0], "x_wr_calname"):
                            calname = vobject_items[0].x_wr_calname.value
                            if calname:
                                props["D:displayname"] = calname
                        if hasattr(vobject_items[0], "x_wr_caldesc"):
                            caldesc = vobject_items[0].x_wr_caldesc.value
                            if caldesc:
                                props["C:calendar-description"] = caldesc
                    radicale_item.check_and_sanitize_props(props)
            except Exception:
                stored_exc_info = sys.exc_info()

            # Use generator for items and delete references to free memory
            # early
            def items_generator():
                while items:
                    yield items.pop(0)

            return (items_generator(), tag, write_whole_collection, props,
                    stored_exc_info)