skarim / vobject

A full-featured Python package for parsing and creating iCalendar and vCard files
https://vobject.sameenkarim.com
258 stars 93 forks source link

vcard 2.1 support: add #168

Open icegood opened 3 years ago

icegood commented 3 years ago

Some (older) phones are export images in vcards in 2.1 format with line ENCODING=BASE64

instead of

ENCODING=B (for v 3.0: https://datatracker.ietf.org/doc/html/rfc2426#section-3.1.4) in PHOTO field.

This leads to serialization error in VCardTextBehavior.encode : instead of being encoded back to base64 it tries to run line.value = backslashEscape(line.value)

slyduda commented 1 year ago

The following quick fix helped me:

https://github.com/Kozea/Radicale/issues/1238#issuecomment-1352530048

pbiering commented 1 year ago

The following quick fix helped me:

Kozea/Radicale#1238 (comment)

The encoding gets all wonky when BASE64 is used for the encoding param. I am not sure why and I am sure this quick fix breaks other cases, but it allows me to use base64 encoding on photos now so that's all that matters for me.

=> one has to investigate proper solution for "vobject" - unconditional overtake of the "quick fix" can turn dangerous.

slyduda commented 1 year ago

agreed, and thank you for the clarification. i should have added a bit more words of caution on my comment!

to add, i will clarify that what i mean by The encoding gets all wonky when BASE64 is used for the encoding param. is that this is already the default behavior. If BASE64 if used for the encoding param on a valid uploaded vcard, vobject (seems to at least by my understanding) think that the value is going to be something other than a string or bytes object in memory so it tries to encode and decode a value that doesn't necessarily need it.

if there are cases in which the vobject value with an encoding param can be something other than a string then that line should stay. what is more likely to be a safer solution that I haven't tested yet is:

    def decode(cls, line):
        """
        Remove backslash escaping from line.valueDecode line, either to remove
        backslash espacing, or to decode base64 encoding. The content line should
        contain a ENCODING=b for base64 encoding, but Apple Addressbook seems to
        export a singleton parameter of 'BASE64', which does not match the 3.0
        vCard spec. If we encouter that, then we transform the parameter to
        ENCODING=b
        """
        if line.encoded:
            if 'BASE64' in line.singletonparams:
                line.singletonparams.remove('BASE64')
                line.encoding_param = cls.base64string
            encoding = getattr(line, 'encoding_param', None)
            if encoding:
                if isinstance(line.value, bytes):
                    line.value = codecs.decode(line.value, "base64")
                elif not isinstance(line.value, string):
                    line.value = codecs.decode(line.value.encode("utf-8"), "base64")
            else:
                line.value = stringToTextValues(line.value)[0]
            line.encoded = False

but again, word of caution, this needs testing before applying it to anything production facing