blob: e56f83e6f8490e464a55d4ab91e83989178f5b55 [file] [log] [blame]
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import Foundation
import Contacts
/*
*This extension adds fields UID and PHOTO to vCard provided by default
*It also provides image compression that mostly could be useful when sending contact request
*/
enum VCardFields: String {
case begin = "BEGIN:VCARD"
case uid = "UID:"
case photoJPEG = "PHOTO;ENCODING=BASE64;TYPE=JPEG:"
case photoPNG = "PHOTO;ENCODING=BASE64;TYPE=PNG:"
case end = "END:VCARD"
case name = "N:"
case fullName = "FN:"
}
extension CNContactVCardSerialization {
class func dataWithImageAndUUID(from contact: CNContact, andImageCompression compressedSize: Int?) throws -> Data {
// recreate vCard string
let beginString = VCardFields.begin.rawValue + "\n"
let entryUIDString = VCardFields.uid.rawValue + contact.identifier + "\n"
let name = contact.familyName.trimmingCharacters(in: .whitespacesAndNewlines)
let firstnameString = VCardFields.name.rawValue + name + "\n"
let fullNameString = VCardFields.fullName.rawValue + name + "\n"
let endString = VCardFields.end.rawValue
var vCardString = beginString + entryUIDString + firstnameString + fullNameString + endString
// if contact have an image add it to vCard data
guard var image = contact.imageData else {
return vCardString.data(using: .utf8)!
}
var photofieldName = VCardFields.photoPNG
// if we need smallest image first scale it and than compress
var scaledImage: UIImage?
if compressedSize != nil {
scaledImage = UIImage(data: image)?
.convert(toSize: CGSize(width: 50.0, height: 50.0), scale: 1)
}
if let scaledImage = scaledImage {
if UIImagePNGRepresentation(scaledImage) != nil {
image = UIImagePNGRepresentation(scaledImage)!
}
}
if let compressionSize = compressedSize, image.count > compressionSize {
// compress image before sending vCard
guard let compressedImage = UIImage(data: image)?
.convertToData(ofMaxSize: compressionSize) else {
return vCardString.data(using: .utf8)!
}
image = compressedImage
photofieldName = VCardFields.photoJPEG
}
let base64Image = image.base64EncodedString(options: Data.Base64EncodingOptions.init(rawValue: 0))
let vcardImageString = photofieldName.rawValue + base64Image + "\n"
vCardString = vCardString.replacingOccurrences(of: VCardFields.end.rawValue, with: (vcardImageString + VCardFields.end.rawValue))
return vCardString.data(using: .utf8)!
}
class func parseToVCard(data: Data) -> CNContact? {
do {
let vCards = try CNContactVCardSerialization.contacts(with: data)
guard let vCard = vCards.first else { return nil }
if let returnData = String(data: data, encoding: .utf8) {
let contentArr = returnData.components(separatedBy: "\n")
if let nameRow = contentArr.filter({String($0.prefix(3)) == VCardFields.fullName.rawValue}).first {
let vcard = CNMutableContact()
let name = String(nameRow.suffix(nameRow.count - 3))
vcard.familyName = name
vcard.imageData = vCard.imageData
return vcard
}
}
return vCard
} catch {
return nil
}
}
}