Peter Bieringer 2 месяцев назад
Родитель
Сommit
fdcd3e2deb
2 измененных файлов с 34 добавлено и 2 удалено
  1. 16 1
      radicale/__main__.py
  2. 18 1
      radicale/item/__init__.py

+ 16 - 1
radicale/__main__.py

@@ -33,7 +33,7 @@ import sys
 from types import FrameType
 from typing import List, Optional, cast
 
-from radicale import VERSION, config, log, server, storage, types
+from radicale import VERSION, config, item, log, server, storage, types
 from radicale.log import logger
 
 
@@ -65,6 +65,8 @@ def run() -> None:
     parser.add_argument("--version", action="version", version=VERSION)
     parser.add_argument("--verify-storage", action="store_true",
                         help="check the storage for errors and exit")
+    parser.add_argument("--verify-item", action="store", nargs=1,
+                        help="check the provided item file for errors and exit")
     parser.add_argument("-C", "--config",
                         help="use specific configuration files", nargs="*")
     parser.add_argument("-D", "--debug", action="store_const", const="debug",
@@ -194,6 +196,19 @@ def run() -> None:
             sys.exit(1)
         return
 
+    if args_ns.verify_item:
+        encoding = configuration.get("encoding", "stock")
+        logger.info("Item verification start using 'stock' encoding: %s", encoding)
+        try:
+            if not item.verify(args_ns.verify_item[0], encoding):
+                logger.critical("Item verification failed")
+                sys.exit(1)
+        except Exception as e:
+            logger.critical("An exception occurred during item "
+                            "verification: %s", e, exc_info=False)
+            sys.exit(1)
+        return
+
     # Create a socket pair to notify the server of program shutdown
     shutdown_socket, shutdown_socket_out = socket.socketpair()
 

+ 18 - 1
radicale/item/__init__.py

@@ -37,7 +37,7 @@ from typing import (Any, Callable, List, MutableMapping, Optional, Sequence,
 import vobject
 
 from radicale import storage  # noqa:F401
-from radicale import pathutils
+from radicale import pathutils, utils
 from radicale.item import filter as radicale_filter
 from radicale.log import logger
 
@@ -335,6 +335,23 @@ def find_time_range(vobject_item: vobject.base.Component, tag: str
     return math.floor(start.timestamp()), math.ceil(end.timestamp())
 
 
+def verify(file: str, encoding: str):
+    logger.info("Verifying item: %s", file)
+    with open(file, "rb") as f:
+        content_raw = f.read()
+    content = content_raw.decode(encoding)
+    logger.info("Verifying item: %s has sha256sum %r", file, utils.sha256_str(content))
+    try:
+        vobject_items = read_components(content)  # noqa: F841
+    except Exception as e:
+        logger.error("Verifying item: %s problem: %s", file, e)
+        logger.info("Request content (hexdump/lines):\n%s", utils.hexdump_lines(content))
+        return False
+    else:
+        logger.info("Verifying item: %s successful", file)
+    return True
+
+
 class Item:
     """Class for address book and calendar entries."""