skarim / vobject

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

vCard categories is not serialized properly unless value is in an array. #159

Open neilkatin opened 3 years ago

neilkatin commented 3 years ago

This problem seems to be very similar to #138, but since 138 was closed I'm submitting a new issue.

If I assign a string value to a vCard category value it gets serialized one letter at a time. If I assign a list with one string entry it works properly.

I replicated this on both the current released version (0.9.6.1) and on the master branch in from git.

Here's a short test program that demonstrates the issue:

import vobject

v = vobject.vCard()
v.add('fn')
v.fn.value="test-name"
v.add('categories')
v.categories.value = "test string"
print(f"test 1: string value\n{ v.serialize() }\n")

v = vobject.vCard()
v.add('fn')
v.fn.value="test-name"
v.add('categories')
v.categories.value = ["test string"]
print(f"test 2: string in array\n{ v.serialize() }\n")

Here's the output (on a python 3.8 system):

test 1: string value
BEGIN:VCARD
VERSION:3.0
CATEGORIES:t,e,s,t, ,s,t,r,i,n,g
FN:test-name
END:VCARD

test 2: string in array
BEGIN:VCARD
VERSION:3.0
CATEGORIES:test string
FN:test-name
END:VCARD
TMasz commented 3 years ago

I have a similar issue under Python 3.9.5. I found I had to convert the ORG and CATEGORIES values to a list but not the TITLE.

onmywaytoheaven commented 3 years ago

I have this issue on python 3.8.10, vobject 0.9.6.1 from pip

To fix this i tried to do same as Android Contacts working with my cyrrilic - encode it with quoted-printable

import vobject

vcard = vobject.vCard()
vcard.add('fn').value = 'John Doe'
vcard.add('org').value = 'Acme inc'
assert 'BEGIN:VCARD\r\nVERSION:3.0\r\nFN:John Doe\r\nORG:A;c;m;e; ;i;n;c\r\nEND:VCARD\r\n' == vcard.serialize()

And with quopri

import quopri
import vobject

vcard = vobject.vCard()
vcard.add('fn').value = 'John Doe'
org = quopri.encodestring('Acme inc'.encode()).decode()
vcard.add('org;charset=utf-8;encoding=quoted-printable').value = org
assert 'BEGIN:VCARD\r\nVERSION:3.0\r\nFN:John Doe\r\nORG;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:Acme inc\r\nEND:VCARD\r\n' == vcard.serialize()

Apparently, this works not because of specifying the encoding, but because of the adding parameters to ORG =\