diff options
author | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2019-08-30 08:44:22 +0200 |
---|---|---|
committer | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2019-08-30 08:44:22 +0200 |
commit | 1f66b85acf8e09f08b466b177ced0c0f20a7fc2b (patch) | |
tree | 1d9234fd382cc775ee4c6831d974574d7b900184 /src | |
parent | 4d1a67a018188e997e74f835fd849c70b207abe3 (diff) |
Support vcard 3 photo syntax
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/components/ContactDetails/ContactDetailsAvatar.vue | 50 | ||||
-rw-r--r-- | src/components/ContactsList/ContactsListItem.vue | 8 | ||||
-rw-r--r-- | src/models/contact.js | 49 |
3 files changed, 80 insertions, 27 deletions
diff --git a/src/components/ContactDetails/ContactDetailsAvatar.vue b/src/components/ContactDetails/ContactDetailsAvatar.vue index a2a24b5b..2f0f587a 100644 --- a/src/components/ContactDetails/ContactDetailsAvatar.vue +++ b/src/components/ContactDetails/ContactDetailsAvatar.vue @@ -25,7 +25,7 @@ <div class="contact-header-avatar"> <div class="contact-header-avatar__wrapper"> <div class="contact-header-avatar__background" @click="toggleModal" /> - <div v-if="contact.photo" :style="{ 'backgroundImage': `url(${photo})` }" + <div v-if="contact.photo" :style="{ 'backgroundImage': `url(${contact.photoUrl})` }" class="contact-header-avatar__photo" @click="toggleModal" /> @@ -55,7 +55,7 @@ {{ t('contacts', 'Download picture') }} </ActionLink> </template> - <img ref="img" :src="photo" class="contact-header-modal__photo" + <img ref="img" :src="contact.photoUrl" class="contact-header-modal__photo" :style="{ width, height }" @load="updateImgSize"> </Modal> @@ -107,15 +107,6 @@ export default { } }, computed: { - photo() { - const photo = this.contact.vCard.getFirstProperty('photo') - if (photo && !this.contact.photo.startsWith('data') && photo.type === 'binary') { - // split on coma in case of any leftover base64 data and retrieve last part - // usually we come to this part when the base64 image type is unknown - return `data:image;base64,${this.contact.photo.split(',').pop()}` - } - return this.contact.photo - }, isReadOnly() { if (this.contact.addressbook) { return this.contact.addressbook.readOnly @@ -145,7 +136,8 @@ export default { let self = this reader.onload = function(e) { - self.setPhoto(reader.result) + // only getting the raw binary base64 + self.setPhoto(reader.result.split(',').pop(), file.type) } reader.readAsDataURL(file) @@ -161,13 +153,30 @@ export default { /** * Update the contact photo * - * @param {String} value the photo as base64 + * @param {String} data the photo as base64 binary string + * @param {String} type mimetype */ - setPhoto(value) { - // check if photo property exists to decide whether to add/update it - this.contact.photo - ? this.contact.photo = value - : this.contact.vCard.addPropertyWithValue('photo', value) + setPhoto(data, type) { + // Vcard 3 and 4 have different syntax + // https://tools.ietf.org/html/rfc2426#page-11 + if (this.contact.version === '3.0') { + // check if photo property exists to decide whether to add/update it + this.contact.photo + ? this.contact.photo = data + : this.contact.vCard.addPropertyWithValue('photo', data) + + const photo = this.contact.vCard.getFirstProperty('photo') + photo.setParameter('encoding', 'b') + if (type) { + photo.setParameter('type', type.split('/').pop()) + } + } else { + // https://tools.ietf.org/html/rfc6350#section-6.2.4 + // check if photo property exists to decide whether to add/update it + this.contact.photo + ? this.contact.photo = `data:${type};base64,${data}` + : this.contact.vCard.addPropertyWithValue('photo', `data:${type};base64,${data}`) + } this.$store.dispatch('updateContact', this.contact) this.loading = false @@ -219,8 +228,9 @@ export default { const response = await get(`${this.root}${file}`, { responseType: 'arraybuffer' }) - const data = `data:${response.headers['content-type']};base64,${Buffer.from(response.data, 'binary').toString('base64')}` - this.setPhoto(data) + const type = response.headers['content-type'] + const data = Buffer.from(response.data, 'binary').toString('base64') + this.setPhoto(data, type) } catch (error) { OC.Notification.showTemporary(t('contacts', 'Error while processing the picture.')) console.error(error) diff --git a/src/components/ContactsList/ContactsListItem.vue b/src/components/ContactsList/ContactsListItem.vue index 22f8b6b4..d71a2a69 100644 --- a/src/components/ContactsList/ContactsListItem.vue +++ b/src/components/ContactsList/ContactsListItem.vue @@ -104,13 +104,7 @@ export default { }, avatarUrl() { if (this.contact.photo) { - const type = this.contact.vCard.getFirstProperty('photo').type - if (!this.contact.photo.startsWith('data') && type === 'binary') { - // split on coma in case of any leftover base64 data and retrieve last part - // usually we come to this part when the base64 image type is unknown - return `url(data:image;base64,${this.contact.photo.split(',').pop()})` - } - return `url(${this.contact.photo})` + return `url(${this.contact.photoUrl})` } return `url(${this.contact.url}?photo)` } diff --git a/src/models/contact.js b/src/models/contact.js index c4eebecc..15f0d7e2 100644 --- a/src/models/contact.js +++ b/src/models/contact.js @@ -165,6 +165,27 @@ export default class Contact { } /** + * Return the version + * + * @readonly + * @memberof Contact + */ + get version() { + return this.vCard.getFirstPropertyValue('version') + } + + /** + * Set the version + * + * @param {string} version the version to set + * @memberof Contact + */ + set version(version) { + this.vCard.updatePropertyWithValue('version', version) + return true + } + + /** * Return the uid * * @readonly @@ -238,6 +259,34 @@ export default class Contact { } /** + * Return the photo usable url + * + * @readonly + * @memberof Contact + */ + get photoUrl() { + const photo = this.vCard.getFirstProperty('photo') + const encoding = photo.getFirstParameter('encoding') + + const isBinary = photo.type === 'binary' || encoding === 'b' + + if (photo && !this.photo.startsWith('data') && isBinary) { + // split on coma in case of any leftover base64 data and retrieve last part + // usually we come to this part when the base64 image type is unknown + return `data:image;base64,${this.photo.split(',').pop()}` + } + // could be just an url of the already encoded `data:image...` + try { + // eslint-disable-next-line no-new + new URL(this.photo) + return this.photo + } catch { + console.error('Invalid photo for the following contact. Ignoring...', this.contact) + return false + } + } + + /** * Return the groups * * @readonly |