parent
4a0bcde7a3
commit
75df1093be
@ -141,7 +141,7 @@ class ApplicationPartPut(ApplicationBase):
|
|||||||
content_type = environ.get("CONTENT_TYPE", "").split(";",
|
content_type = environ.get("CONTENT_TYPE", "").split(";",
|
||||||
maxsplit=1)[0]
|
maxsplit=1)[0]
|
||||||
try:
|
try:
|
||||||
vobject_items = list(vobject.readComponents(content or ""))
|
vobject_items = radicale_item.read_components(content or "")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Bad PUT request on %r: %s", path, e, exc_info=True)
|
"Bad PUT request on %r: %s", path, e, exc_info=True)
|
||||||
|
@ -27,6 +27,7 @@ import binascii
|
|||||||
import contextlib
|
import contextlib
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
@ -42,6 +43,16 @@ from radicale.item import filter as radicale_filter
|
|||||||
from radicale.log import logger
|
from radicale.log import logger
|
||||||
|
|
||||||
|
|
||||||
|
def read_components(s: str) -> List[vobject.base.Component]:
|
||||||
|
"""Wrapper for vobject.readComponents"""
|
||||||
|
# Workaround for bug in InfCloud
|
||||||
|
# PHOTO is a data URI
|
||||||
|
s = re.sub(r"^(PHOTO(?:;[^:\r\n]*)?;ENCODING=b(?:;[^:\r\n]*)?:)"
|
||||||
|
r"data:[^;,\r\n]*;base64,", r"\1", s,
|
||||||
|
flags=re.MULTILINE | re.IGNORECASE)
|
||||||
|
return list(vobject.readComponents(s))
|
||||||
|
|
||||||
|
|
||||||
def predict_tag_of_parent_collection(
|
def predict_tag_of_parent_collection(
|
||||||
vobject_items: Sequence[vobject.base.Component]) -> Optional[str]:
|
vobject_items: Sequence[vobject.base.Component]) -> Optional[str]:
|
||||||
"""Returns the predicted tag or `None`"""
|
"""Returns the predicted tag or `None`"""
|
||||||
|
@ -21,8 +21,6 @@ import sys
|
|||||||
import time
|
import time
|
||||||
from typing import Iterable, Iterator, Optional, Tuple
|
from typing import Iterable, Iterator, Optional, Tuple
|
||||||
|
|
||||||
import vobject
|
|
||||||
|
|
||||||
import radicale.item as radicale_item
|
import radicale.item as radicale_item
|
||||||
from radicale import pathutils
|
from radicale import pathutils
|
||||||
from radicale.log import logger
|
from radicale.log import logger
|
||||||
@ -93,8 +91,8 @@ class CollectionPartGet(CollectionPartCache, CollectionPartLock,
|
|||||||
cache_content = self._load_item_cache(href, cache_hash)
|
cache_content = self._load_item_cache(href, cache_hash)
|
||||||
if cache_content is None:
|
if cache_content is None:
|
||||||
try:
|
try:
|
||||||
vobject_items = list(vobject.readComponents(
|
vobject_items = radicale_item.read_components(
|
||||||
raw_text.decode(self._encoding)))
|
raw_text.decode(self._encoding))
|
||||||
radicale_item.check_and_sanitize_items(
|
radicale_item.check_and_sanitize_items(
|
||||||
vobject_items, tag=self.tag)
|
vobject_items, tag=self.tag)
|
||||||
vobject_item, = vobject_items
|
vobject_item, = vobject_items
|
||||||
|
8
radicale/tests/static/contact_photo_with_data_uri.vcf
Normal file
8
radicale/tests/static/contact_photo_with_data_uri.vcf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
BEGIN:VCARD
|
||||||
|
VERSION:3.0
|
||||||
|
UID:contact
|
||||||
|
N:Contact;;;;
|
||||||
|
FN:Contact
|
||||||
|
NICKNAME:test
|
||||||
|
PHOTO;ENCODING=b;TYPE=png:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAD0lEQVQIHQEEAPv/AP///wX+Av4DfRnGAAAAAElFTkSuQmCC
|
||||||
|
END:VCARD
|
@ -139,6 +139,12 @@ permissions: RrWw""")
|
|||||||
_, answer = self.get(path)
|
_, answer = self.get(path)
|
||||||
assert "UID:contact1" in answer
|
assert "UID:contact1" in answer
|
||||||
|
|
||||||
|
def test_add_contact_photo_with_data_uri(self) -> None:
|
||||||
|
"""Test workaround for broken PHOTO data from InfCloud"""
|
||||||
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
contact = get_file_content("contact_photo_with_data_uri.vcf")
|
||||||
|
self.put("/contacts.vcf/contact.vcf", contact)
|
||||||
|
|
||||||
def test_add_contact_without_uid(self) -> None:
|
def test_add_contact_without_uid(self) -> None:
|
||||||
"""Add a contact without UID."""
|
"""Add a contact without UID."""
|
||||||
self.create_addressbook("/contacts.vcf/")
|
self.create_addressbook("/contacts.vcf/")
|
||||||
|
Loading…
Reference in New Issue
Block a user