summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-08-30 08:44:22 +0200
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-08-30 08:44:22 +0200
commit1f66b85acf8e09f08b466b177ced0c0f20a7fc2b (patch)
tree1d9234fd382cc775ee4c6831d974574d7b900184 /src
parent4d1a67a018188e997e74f835fd849c70b207abe3 (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.vue50
-rw-r--r--src/components/ContactsList/ContactsListItem.vue8
-rw-r--r--src/models/contact.js49
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