vcard.cc 9.68 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 = new belcard::BelCardParser();
		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
		delete(parser);
69 70 71 72
	}
	return result;
}

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

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

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

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

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

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

134
void linphone_vcard_remove_sip_address(LinphoneVcard *vCard, const char *sip_address) {
135 136
	if (!vCard) return;
	
137
	shared_ptr<belcard::BelCardImpp> impp;
138 139 140
	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) {
141
			impp = *it;
142 143 144
			break;
		}
	}
145 146 147
	if (impp) {
		vCard->belCard->removeImpp(impp);
	}
148 149
}

150
void linphone_vcard_edit_main_sip_address(LinphoneVcard *vCard, const char *sip_address) {
151 152 153 154 155 156 157 158 159 160 161 162
	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);
	}
}

163 164
bctbx_list_t* linphone_vcard_get_sip_addresses(const LinphoneVcard *vCard) {
	bctbx_list_t *result = NULL;
165 166
	if (!vCard) return NULL;
	
167
	for (auto it = vCard->belCard->getImpp().begin(); it != vCard->belCard->getImpp().end(); ++it) {
168 169
		const char *value = (*it)->getValue().c_str();
		if (strncmp(value, "sip:", 4) == 0) {
170
			result = bctbx_list_append(result, (char *)value);
171 172 173
		}
	}
	return result;
174 175
}

176 177 178 179 180 181 182 183 184 185 186
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;
	
187
	shared_ptr<belcard::BelCardPhoneNumber> tel;
188 189 190
	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) {
191
			tel = *it;
192 193 194
			break;
		}
	}
195 196 197
	if (tel) {
		vCard->belCard->removePhoneNumber(tel);
	}
198 199
}

200 201
bctbx_list_t* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard) {
	bctbx_list_t *result = NULL;
202 203 204 205
	if (!vCard) return NULL;
	
	for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) {
		const char *value = (*it)->getValue().c_str();
206
		result = bctbx_list_append(result, (char *)value);
207 208 209 210
	}
	return result;
}

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
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;
}

233
bool_t linphone_vcard_generate_unique_id(LinphoneVcard *vCard) {
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
	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;
}

250
void linphone_vcard_set_uid(LinphoneVcard *vCard, const char *uid) {
251 252 253 254 255 256 257
	if (!vCard || !uid) return;
	
	shared_ptr<belcard::BelCardUniqueId> uniqueId = belcard::BelCardGeneric::create<belcard::BelCardUniqueId>();
	uniqueId->setValue(uid);
	vCard->belCard->setUniqueId(uniqueId);
}

258
const char* linphone_vcard_get_uid(const LinphoneVcard *vCard) {
Sylvain Berfini's avatar
Sylvain Berfini committed
259
	if (vCard && vCard->belCard->getUniqueId()) {
260 261 262 263 264
		return vCard->belCard->getUniqueId()->getValue().c_str();
	}
	return NULL;
}

265
void linphone_vcard_set_etag(LinphoneVcard *vCard, const char * etag) {
266 267 268 269 270 271
	if (!vCard) {
		return;
	}
	if (vCard->etag) {
		ms_free(vCard->etag);
	}
272 273 274
	vCard->etag = ms_strdup(etag);
}

275
const char* linphone_vcard_get_etag(const LinphoneVcard *vCard) {
Sylvain Berfini's avatar
Sylvain Berfini committed
276
	if (!vCard) return NULL;
277 278 279
	return vCard->etag;
}

280
void linphone_vcard_set_url(LinphoneVcard *vCard, const char * url) {
281 282 283 284 285 286
	if (!vCard) {
		return;
	}
	if (vCard->url) {
		ms_free(vCard->url);
	}
287 288 289
	vCard->url = ms_strdup(url);
}

290
const char* linphone_vcard_get_url(const LinphoneVcard *vCard) {
Sylvain Berfini's avatar
Sylvain Berfini committed
291
	if (!vCard) return NULL;
292
	return vCard->url;
293 294
}

295 296
#define VCARD_MD5_HASH_SIZE 16

297
void linphone_vcard_compute_md5_hash(LinphoneVcard *vCard) {
298
	unsigned char digest[VCARD_MD5_HASH_SIZE];
299
	const char *text = NULL;
300 301 302
	if (!vCard) {
		return;
	}
303
	text = linphone_vcard_as_vcard4_string(vCard);
jehan's avatar
jehan committed
304
	bctbx_md5((unsigned char *)text, strlen(text), digest);
305 306
	vCard->md5 = (unsigned char *)ms_malloc(sizeof(digest));
	memcpy(vCard->md5, digest, sizeof(digest));
307 308
}

309
bool_t linphone_vcard_compare_md5_hash(LinphoneVcard *vCard) {
310 311 312 313 314 315
	unsigned char *previous_md5 = vCard->md5;
	unsigned char *new_md5 = NULL;
	int result = -1;
	
	if (!previous_md5) {
		return result;
316
	}
317 318 319
	
	linphone_vcard_compute_md5_hash(vCard);
	new_md5 = vCard->md5;
320
	result = memcmp(new_md5, previous_md5, VCARD_MD5_HASH_SIZE);
321 322 323 324
	
	ms_free(previous_md5);
	ms_free(new_md5);
	return result;
325 326
}

327 328 329
#ifdef __cplusplus
}
#endif