vcard.cc 9.49 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
vcard.cc
Copyright (C) 2015  Belledonne Communications SARL

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 2
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

20 21
#include "vcard.h"
#include "belcard/belcard.hpp"
22
#include "belcard/belcard_parser.hpp"
23
#include "sal/sal.h"
24
#include <bctoolbox/crypto.h>
25

26
struct _LinphoneVcard {
27
	shared_ptr<belcard::BelCard> belCard;
28 29
	char *etag;
	char *url;
30
	unsigned char *md5;
31 32
};

33 34 35 36
#ifdef __cplusplus
extern "C" {
#endif

37 38
LinphoneVcard* linphone_vcard_new(void) {
	LinphoneVcard* vCard = (LinphoneVcard*) ms_new0(LinphoneVcard, 1);
39 40
	vCard->belCard = belcard::BelCardGeneric::create<belcard::BelCard>();
	return vCard;
41 42
}

43 44 45 46 47 48
static LinphoneVcard* linphone_vcard_new_from_belcard(shared_ptr<belcard::BelCard> belcard) {
	LinphoneVcard* vCard = (LinphoneVcard*) ms_new0(LinphoneVcard, 1);
	vCard->belCard = belcard;
	return vCard;
}

49
void linphone_vcard_free(LinphoneVcard *vCard) {
50 51
	if (!vCard) return;
	
52 53
	vCard->belCard.reset();
	ms_free(vCard);
54 55
}

56 57
bctbx_list_t* linphone_vcard_list_from_vcard4_file(const char *filename) {
	bctbx_list_t *result = NULL;
58
	if (filename) {
59 60
		belcard::BelCardParser parser = belcard::BelCardParser::getInstance();
		shared_ptr<belcard::BelCardList> belCards = parser.parseFile(filename);
61
		if (belCards) {
62
			for (auto it = belCards->getCards().begin(); it != belCards->getCards().end(); ++it) {
63 64
				shared_ptr<belcard::BelCard> belCard = (*it);
				LinphoneVcard *vCard = linphone_vcard_new_from_belcard(belCard);
65
				result = bctbx_list_append(result, vCard);
66 67 68 69 70 71
			}
		}
	}
	return result;
}

72 73
bctbx_list_t* linphone_vcard_list_from_vcard4_buffer(const char *buffer) {
	bctbx_list_t *result = NULL;
74
	if (buffer) {
75 76
		belcard::BelCardParser parser = belcard::BelCardParser::getInstance();
		shared_ptr<belcard::BelCardList> belCards = parser.parse(buffer);
77 78 79
		if (belCards) {
			for (auto it = belCards->getCards().begin(); it != belCards->getCards().end(); ++it) {
				shared_ptr<belcard::BelCard> belCard = (*it);
80
				LinphoneVcard *vCard = linphone_vcard_new_from_belcard(belCard);
81
				result = bctbx_list_append(result, vCard);
82 83 84 85 86 87
			}
		}
	}
	return result;
}

88 89
LinphoneVcard* linphone_vcard_new_from_vcard4_buffer(const char *buffer) {
	LinphoneVcard *vCard = NULL;
90
	if (buffer) {
91 92
		belcard::BelCardParser parser = belcard::BelCardParser::getInstance();
		shared_ptr<belcard::BelCard> belCard = parser.parseOne(buffer);
93
		if (belCard) {
94
			vCard = linphone_vcard_new_from_belcard(belCard);
Sylvain Berfini's avatar
Sylvain Berfini committed
95 96
		} else {
			ms_error("Couldn't parse buffer %s", buffer);
97 98 99 100 101
		}
	}
	return vCard;
}

102
const char * linphone_vcard_as_vcard4_string(LinphoneVcard *vCard) {
103 104
	if (!vCard) return NULL;
	
105
	return vCard->belCard->toFoldedString().c_str();
106 107
}

108
void linphone_vcard_set_full_name(LinphoneVcard *vCard, const char *name) {
109 110
	if (!vCard || !name) return;
	
111 112
	shared_ptr<belcard::BelCardFullName> fn = belcard::BelCardGeneric::create<belcard::BelCardFullName>();
	fn->setValue(name);
113
	vCard->belCard->setFullName(fn);
114 115
}

116
const char* linphone_vcard_get_full_name(const LinphoneVcard *vCard) {
117 118
	if (!vCard) return NULL;
	
119
	const char *result = vCard->belCard->getFullName() ? vCard->belCard->getFullName()->getValue().c_str() : NULL;
120
	return result;
121 122
}

123
void linphone_vcard_add_sip_address(LinphoneVcard *vCard, const char *sip_address) {
124 125
	if (!vCard || !sip_address) return;
	
126 127 128 129 130
	shared_ptr<belcard::BelCardImpp> impp = belcard::BelCardGeneric::create<belcard::BelCardImpp>();
	impp->setValue(sip_address);
	vCard->belCard->addImpp(impp);
}

131
void linphone_vcard_remove_sip_address(LinphoneVcard *vCard, const char *sip_address) {
132 133 134 135 136 137 138 139 140 141 142
	if (!vCard) return;
	
	for (auto it = vCard->belCard->getImpp().begin(); it != vCard->belCard->getImpp().end(); ++it) {
		const char *value = (*it)->getValue().c_str();
		if (strcmp(value, sip_address) == 0) {
			vCard->belCard->removeImpp(*it);
			break;
		}
	}
}

143
void linphone_vcard_edit_main_sip_address(LinphoneVcard *vCard, const char *sip_address) {
144 145 146 147 148 149 150 151 152 153 154 155
	if (!vCard || !sip_address) return;
	
	if (vCard->belCard->getImpp().size() > 0) {
		const shared_ptr<belcard::BelCardImpp> impp = vCard->belCard->getImpp().front();
		impp->setValue(sip_address);
	} else {
		shared_ptr<belcard::BelCardImpp> impp = belcard::BelCardGeneric::create<belcard::BelCardImpp>();
		impp->setValue(sip_address);
		vCard->belCard->addImpp(impp);
	}
}

156 157
bctbx_list_t* linphone_vcard_get_sip_addresses(const LinphoneVcard *vCard) {
	bctbx_list_t *result = NULL;
158 159
	if (!vCard) return NULL;
	
160
	for (auto it = vCard->belCard->getImpp().begin(); it != vCard->belCard->getImpp().end(); ++it) {
161 162
		const char *value = (*it)->getValue().c_str();
		if (strncmp(value, "sip:", 4) == 0) {
163
			result = bctbx_list_append(result, (char *)value);
164 165 166
		}
	}
	return result;
167 168
}

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
void linphone_vcard_add_phone_number(LinphoneVcard *vCard, const char *phone) {
	if (!vCard || !phone) return;
	
	shared_ptr<belcard::BelCardPhoneNumber> phone_number = belcard::BelCardGeneric::create<belcard::BelCardPhoneNumber>();
	phone_number->setValue(phone);
	vCard->belCard->addPhoneNumber(phone_number);
}

void linphone_vcard_remove_phone_number(LinphoneVcard *vCard, const char *phone) {
	if (!vCard) return;
	
	for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) {
		const char *value = (*it)->getValue().c_str();
		if (strcmp(value, phone) == 0) {
			vCard->belCard->removePhoneNumber(*it);
			break;
		}
	}
}

189 190
bctbx_list_t* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard) {
	bctbx_list_t *result = NULL;
191 192 193 194
	if (!vCard) return NULL;
	
	for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) {
		const char *value = (*it)->getValue().c_str();
195
		result = bctbx_list_append(result, (char *)value);
196 197 198 199
	}
	return result;
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
void linphone_vcard_set_organization(LinphoneVcard *vCard, const char *organization) {
	if (!vCard) return;
	
	if (vCard->belCard->getOrganizations().size() > 0) {
		const shared_ptr<belcard::BelCardOrganization> org = vCard->belCard->getOrganizations().front();
		org->setValue(organization);
	} else {
		shared_ptr<belcard::BelCardOrganization> org = belcard::BelCardGeneric::create<belcard::BelCardOrganization>();
		org->setValue(organization);
		vCard->belCard->addOrganization(org);
	}
}

const char* linphone_vcard_get_organization(const LinphoneVcard *vCard) {
	if (vCard && vCard->belCard->getOrganizations().size() > 0) {
		const shared_ptr<belcard::BelCardOrganization> org = vCard->belCard->getOrganizations().front();
		return org->getValue().c_str();
	}
	
	return NULL;
}

222
bool_t linphone_vcard_generate_unique_id(LinphoneVcard *vCard) {
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
	char uuid[64];
	
	if (vCard) {
		if (linphone_vcard_get_uid(vCard)) {
			return FALSE;
		}
		if (sal_generate_uuid(uuid, sizeof(uuid)) == 0) {
			char vcard_uuid[sizeof(uuid)+4];
			snprintf(vcard_uuid, sizeof(vcard_uuid), "urn:%s", uuid);
			linphone_vcard_set_uid(vCard, ms_strdup(vcard_uuid));
			return TRUE;
		}
	}
	return FALSE;
}

239
void linphone_vcard_set_uid(LinphoneVcard *vCard, const char *uid) {
240 241 242 243 244 245 246
	if (!vCard || !uid) return;
	
	shared_ptr<belcard::BelCardUniqueId> uniqueId = belcard::BelCardGeneric::create<belcard::BelCardUniqueId>();
	uniqueId->setValue(uid);
	vCard->belCard->setUniqueId(uniqueId);
}

247
const char* linphone_vcard_get_uid(const LinphoneVcard *vCard) {
Sylvain Berfini's avatar
Sylvain Berfini committed
248
	if (vCard && vCard->belCard->getUniqueId()) {
249 250 251 252 253
		return vCard->belCard->getUniqueId()->getValue().c_str();
	}
	return NULL;
}

254
void linphone_vcard_set_etag(LinphoneVcard *vCard, const char * etag) {
255 256 257 258 259 260
	if (!vCard) {
		return;
	}
	if (vCard->etag) {
		ms_free(vCard->etag);
	}
261 262 263
	vCard->etag = ms_strdup(etag);
}

264
const char* linphone_vcard_get_etag(const LinphoneVcard *vCard) {
Sylvain Berfini's avatar
Sylvain Berfini committed
265
	if (!vCard) return NULL;
266 267 268
	return vCard->etag;
}

269
void linphone_vcard_set_url(LinphoneVcard *vCard, const char * url) {
270 271 272 273 274 275
	if (!vCard) {
		return;
	}
	if (vCard->url) {
		ms_free(vCard->url);
	}
276 277 278
	vCard->url = ms_strdup(url);
}

279
const char* linphone_vcard_get_url(const LinphoneVcard *vCard) {
Sylvain Berfini's avatar
Sylvain Berfini committed
280
	if (!vCard) return NULL;
281
	return vCard->url;
282 283
}

284 285
#define VCARD_MD5_HASH_SIZE 16

286
void linphone_vcard_compute_md5_hash(LinphoneVcard *vCard) {
287
	unsigned char digest[VCARD_MD5_HASH_SIZE];
288
	const char *text = NULL;
289 290 291
	if (!vCard) {
		return;
	}
292
	text = linphone_vcard_as_vcard4_string(vCard);
jehan's avatar
jehan committed
293
	bctbx_md5((unsigned char *)text, strlen(text), digest);
294 295
	vCard->md5 = (unsigned char *)ms_malloc(sizeof(digest));
	memcpy(vCard->md5, digest, sizeof(digest));
296 297
}

298
bool_t linphone_vcard_compare_md5_hash(LinphoneVcard *vCard) {
299 300 301 302 303 304
	unsigned char *previous_md5 = vCard->md5;
	unsigned char *new_md5 = NULL;
	int result = -1;
	
	if (!previous_md5) {
		return result;
305
	}
306 307 308
	
	linphone_vcard_compute_md5_hash(vCard);
	new_md5 = vCard->md5;
309
	result = memcmp(new_md5, previous_md5, VCARD_MD5_HASH_SIZE);
310 311 312 313
	
	ms_free(previous_md5);
	ms_free(new_md5);
	return result;
314 315
}

316 317 318
#ifdef __cplusplus
}
#endif