Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround for bug that prevented editing vCards with commas in the address #1394

Merged
merged 4 commits into from
Jan 6, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions src/mixins/PropertyMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
import debounce from 'debounce'
import Contact from '../models/contact'
import ICAL from 'ical.js'
import { setPropertyAlias } from '../services/updateDesignSet'

export default {
props: {
Expand Down Expand Up @@ -142,14 +142,7 @@ export default {
this.localContact.vCard.addPropertyWithValue(`${group}.x-ablabel`, label)

// force update the main design sets
if (ICAL.design.vcard.property[name]) {
ICAL.design.vcard.property[propGroup]
= ICAL.design.vcard.property[name]
}
if (ICAL.design.vcard3.property[name]) {
ICAL.design.vcard3.property[propGroup]
= ICAL.design.vcard3.property[name]
}
setPropertyAlias(name, propGroup)

this.$emit('update')
},
Expand Down
37 changes: 1 addition & 36 deletions src/models/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import uuid from 'uuid'
import ICAL from 'ical.js'

import store from '../store'
import updateDesignSet from '../services/updateDesignSet'

/**
* Check if the given value is an empty array or an empty string
Expand All @@ -35,40 +36,6 @@ const isEmpty = value => {
return (Array.isArray(value) && value.join('') === '') || (!Array.isArray(value) && value === '')
}

/**
* Parse a jCal and update the global designset
* if any grouped property is found
*
* @param {Array} jCal the contact ICAL.js jCal
* @returns {Boolean}
*/
const updateDesignSet = jCal => {
let result = false
jCal[1].forEach(prop => {
const propGroup = prop[0].split('.')

// if this is a grouped property, update the designSet
if (propGroup.length === 2 && (
ICAL.design.vcard.property[propGroup[1]]
|| ICAL.design.vcard3.property[propGroup[1]]
)) {
// force update the main design sets
if (ICAL.design.vcard.property[propGroup[1]]) {
ICAL.design.vcard.property[prop[0]]
= ICAL.design.vcard.property[propGroup[1]]
result = true
}
if (ICAL.design.vcard3.property[propGroup[1]]) {
ICAL.design.vcard3.property[prop[0]]
= ICAL.design.vcard3.property[propGroup[1]]

result = true
}
}
})
return result
}

export default class Contact {

/**
Expand All @@ -88,8 +55,6 @@ export default class Contact {
throw new Error('Only one contact is allowed in the vcard data')
}

// add grouped properties to the design set
// if any found, refresh the contact jCal
if (updateDesignSet(jCal)) {
jCal = ICAL.parse(vcard)
}
Expand Down
111 changes: 111 additions & 0 deletions src/services/updateDesignSet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* @copyright Copyright (c) 2019 John Molakvoæ <[email protected]>
*
* @author John Molakvoæ <[email protected]>
* @author Christian Kraus <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import ICAL from 'ical.js'

/**
* Fixes nextcloud/contacts#1009 that prevented editing of contacts if
* their address contained a comma. This is actually a bug in ical.js
* but it has not been fixed for some time now.
*
* This can be removed once https://github.com/mozilla-comm/ical.js/issues/386
* has been resolved.
*
* @returns {Boolean} Whether or not the design set has been altered.
*/
const setLabelAsSingleValue = () => {
if (
!ICAL.design.vcard.param.label
|| ICAL.design.vcard.param.label.multiValue !== false
|| !ICAL.design.vcard3.param.label
|| ICAL.design.vcard3.param.label.multiValue !== false
) {
ICAL.design.vcard.param.label = { multiValue: false }
ICAL.design.vcard3.param.label = { multiValue: false }

return true
}

return false
}

/**
* Some clients group properties by naming them something like 'ITEM1.URL'.
* These should be treated the same as their original (i.e. 'URL' in this
* example), so we iterate through the vCard to find these properties and
* add them to the ical.js design set.
*
* @link https://github.com/nextcloud/contacts/issues/42
*
* @param {Array} vCard The ical.js vCard
* @returns {Boolean} Whether or not the design set has been altered.
*/
const addGroupedProperties = vCard => {
let madeChanges = false
vCard[1].forEach(prop => {
const propGroup = prop[0].split('.')

// if this is a grouped property, update the designSet
if (propGroup.length === 2) {
madeChanges = setPropertyAlias(propGroup[1], prop[0])
}
})
return madeChanges
}

/**
* Check whether the ical.js design sets need updating (and if so, do it)
*
* @param {Array} vCard The ical.js vCard
* @returns {boolean} Whether or not the design set has been altered.
*/
export default function(vCard) {
let madeChanges = false

madeChanges |= setLabelAsSingleValue()
madeChanges |= addGroupedProperties(vCard)

return madeChanges
}

/**
* @param {String} original Name of the property whose settings should be copied
* @param {String} alias Name of the new property
* @returns {boolean} Whether or not the design set has been altered.
*/
export function setPropertyAlias(original, alias) {
let madeChanges = false
original = original.toLowerCase()
alias = alias.toLowerCase()

if (ICAL.design.vcard.property[original]) {
ICAL.design.vcard.property[alias] = ICAL.design.vcard.property[original]
madeChanges = true
}

if (ICAL.design.vcard3.property[original]) {
ICAL.design.vcard3.property[alias] = ICAL.design.vcard3.property[original]
madeChanges = true
}

return madeChanges
}