diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 12:23:03 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 12:23:03 +0900 |
commit | 11a3f117dca9ddd520fc76650858c60f69d2bdb5 (patch) | |
tree | 1c3b126230f27c8e1451b5669a2e7f760be29fe1 /src/cts-vcard-file.c | |
parent | 914aa1e2236ac93b14e1f19a1c1931385a58d572 (diff) | |
download | contacts-service-11a3f117dca9ddd520fc76650858c60f69d2bdb5.tar.gz contacts-service-11a3f117dca9ddd520fc76650858c60f69d2bdb5.tar.bz2 contacts-service-11a3f117dca9ddd520fc76650858c60f69d2bdb5.zip |
sync
Diffstat (limited to 'src/cts-vcard-file.c')
-rwxr-xr-x | src/cts-vcard-file.c | 1765 |
1 files changed, 0 insertions, 1765 deletions
diff --git a/src/cts-vcard-file.c b/src/cts-vcard-file.c deleted file mode 100755 index cf8e6ce..0000000 --- a/src/cts-vcard-file.c +++ /dev/null @@ -1,1765 +0,0 @@ -/* - * Contacts Service - * - * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Youngjae Shin <yj99.shin@samsung.com> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include <ctype.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <time.h> -#include <iconv.h> - -#include "cts-internal.h" -#include "cts-types.h" -#include "cts-utils.h" -#include "cts-normalize.h" -#include "cts-vcard.h" -#include "cts-vcard-file.h" - -static int cts_tmp_photo_id; - -enum { - CTS_VCARD_VER_NONE, - CTS_VCARD_VER_2_1, - CTS_VCARD_VER_3_0, - CTS_VCARD_VER_4_0, -}; - -enum { - CTS_VCARD_VALUE_NONE, - CTS_VCARD_VALUE_FN, - CTS_VCARD_VALUE_N, - CTS_VCARD_VALUE_NICKNAME, - CTS_VCARD_VALUE_PHOTO, - CTS_VCARD_VALUE_BDAY, - CTS_VCARD_VALUE_ADR, - CTS_VCARD_VALUE_LABEL, - CTS_VCARD_VALUE_TEL, - CTS_VCARD_VALUE_EMAIL, - CTS_VCARD_VALUE_TITLE, - CTS_VCARD_VALUE_ROLE, - CTS_VCARD_VALUE_ORG, - CTS_VCARD_VALUE_NOTE, - CTS_VCARD_VALUE_REV, - CTS_VCARD_VALUE_UID, - CTS_VCARD_VALUE_URL, - CTS_VCARD_VALUE_X_ANNIVERSARY, - CTS_VCARD_VALUE_X_IRMC_LUID, - CTS_VCARD_VALUE_X_SLP_GROUP, - CTS_VCARD_VALUE_END, - CTS_VCARD_VALUE_MAX -}; - -static const char *content_name[CTS_VCARD_VALUE_MAX]; - -static inline char* cts_vcard_remove_empty_line(char *src) -{ - while (*src) { - if ('\n' != *src && '\r' != *src) - break; - src++; - } - return src; -} - -static char* cts_vcard_check_word(char *src, const char *word) -{ - bool start = false; - - retvm_if(NULL == src, NULL, "The src is NULL."); - - src = cts_vcard_remove_empty_line(src); - - while (*src) { - switch (*src) { - case ' ': - case ':': - case ';': - src++; - break; - default: - start = true; - break; - } - if (start) break; - } - - while (*src == *word) { - src++; - word++; - - if ('\0' == *src || '\0' == *word) - break; - } - - if ('\0' == *word) - return src; - else - return NULL; -} - -static int cts_vcard_check_content_type(char **vcard) -{ - int i; - char *new_start; - - for (i=CTS_VCARD_VALUE_NONE+1;i<CTS_VCARD_VALUE_MAX;i++) { - new_start = cts_vcard_check_word(*vcard, content_name[i]); - if (new_start && (':' == *new_start || ';' == *new_start)) - break; - } - - if (CTS_VCARD_VALUE_MAX == i) - return CTS_VCARD_VALUE_NONE; - else { - *vcard = new_start; - return i; - } -} - -static inline int cts_vcard_check_quoted(char *src) -{ - int ret; - - while (*src) { - if ('Q' == *src) { - ret = strncmp(src, "QUOTED-PRINTABLE", sizeof("QUOTED-PRINTABLE") - 1); - if (!ret) - return CTS_TRUE; - }else if (':' == *src) { - break; - } - src++; - } - return CTS_FALSE; -} - -static inline int cts_vcard_hex_to_dec(char hex) -{ - switch (hex) { - case '0' ... '9': - return hex - '0'; - case 'a' ... 'f': - return hex - 'a' + 10; - case 'A' ... 'F': - return hex - 'A' + 10; - default: - return 0; - } -} -static inline int cts_vcard_decode_quoted_val(char *val) -{ - char *src, *dest; - - src = strchr(val, ':'); - if (NULL == src) - src = val; - - dest = src; - while (*src) { - if ('=' == *src) { - *dest = (char)((cts_vcard_hex_to_dec(*(src+1)) << 4) + cts_vcard_hex_to_dec(*(src+2))); - if (*(src+1) && *(src+2)) - src += 2; - }else - *dest = *src; - dest++; - src++; - } - - *dest = '\0'; - return dest - val; -} - -static inline char* cts_vcard_translate_charset(char *src, int len) -{ - int ret; - char *val = src; - - while (*val) { - if ('C' == *val) { - ret = strncmp(val, "CHARSET", sizeof("CHARSET") - 1); - if (!ret) { - val += sizeof("CHARSET"); - break; - } - }else if (':' == *val) { - return NULL; - } - val++; - } - - if (*val) { - int src_len, dest_len, i = 0; - iconv_t ic; - char enc[32], *dest; - - while (';' != *val && ':' != *val) { - enc[i++] = *val++; - } - enc[i] = '\0'; - if (0 == strcasecmp("UTF-8", enc)) - return NULL; - - while (':' != *val) - val++; - - ic = iconv_open("UTF-8", enc); - retvm_if(ic == (iconv_t)-1, NULL, "iconv_open(%s) Failed", enc); - - src_len = len - (val - src); - dest_len = 2048; - dest = malloc(dest_len); - - while (true) { - char *in = val; - char *out = dest; - size_t in_byte = src_len; - size_t out_byte = dest_len; - - ret = iconv(ic, &in, &in_byte, &out, &out_byte); - - if (-1 == ret) { - if (E2BIG == errno) { - dest_len *= 2; - dest = realloc(dest, dest_len); - continue; - } else { - if (dest) { - free(dest); - dest = NULL; - } - ERR("iconv is Failed(errno = %d)", errno); - break; - } - } - dest[dest_len-out_byte] = '\0'; - break; - } - iconv_close(ic); - return dest; - } - - return NULL; -} - -static char* cts_vcard_get_val(int ver, char *src, char **dest) -{ - int len; - bool start = false; - char *cursor; - - retvm_if(NULL == src, NULL, "The src is NULL."); - retvm_if(NULL == dest, NULL, "The dest is NULL."); - - while (*src) { - switch (*src) { - case '\n': - return NULL; - case '\r': - case ' ': - case ':': - src++; - break; - default: - start = true; - break; - } - if (start) break; - } - - cursor = src; - len = 0; - while (*cursor) - { - if ('\r' == *cursor) cursor++; - if ('\n' == *cursor) { - if (' ' != *(cursor+1)) - break; - } - - cursor++; - } - - if (src == cursor) { - *dest = NULL; - return NULL; - } - else { - int len = 0; - char temp = *cursor; - char *new_dest; - - *cursor = '\0'; - *dest = strdup(src); - //if(CTS_VCARD_VER_2_1 == ver) - if (cts_vcard_check_quoted(*dest)) - len = cts_vcard_decode_quoted_val(*dest); - if (0 == len) - len = strlen(*dest); - new_dest = cts_vcard_translate_charset(*dest, len); - if (new_dest) { - free(*dest); - *dest = new_dest; - } - *cursor = temp; - return (cursor + 1); - } -} - -static inline int cts_vcard_check_version(const char *src) -{ - bool start = false; - const char *ver3 = "3.0"; - - while (*src) { - switch (*src) { - case '\n': - case '\r': - return CTS_VCARD_VER_2_1; - case ' ': - src++; - break; - default: - start = true; - break; - } - if (start) break; - } - - if (0 == strcmp(src, ver3)) - return CTS_VCARD_VER_3_0; - else - return CTS_VCARD_VER_2_1; -} - -static inline int cts_vcard_remove_folding(char *folded_src) -{ - char *result = folded_src; - - retv_if(NULL == folded_src, CTS_ERR_ARG_NULL); - - while (*folded_src) { - if ('\r' == *folded_src) - folded_src++; - if ('\n' == *folded_src && ' ' == *(folded_src+1)) - folded_src += 2; - - if ('\0' == *folded_src) - break; - - *result = *folded_src; - result++; - folded_src++; - } - *result = '\0'; - return CTS_SUCCESS; -} - - -static inline char* cts_get_content_value(char *val) -{ - char *temp; - - temp = strchr(val, ':'); - if (temp) - temp++; - else - temp = val; - - retvm_if('\0' == *(temp) || '\r' == *(temp) || '\n' == *(temp), - NULL, "Invalid vcard content(%s)", val); - - return temp; -} - - -static char* cts_strtok(char *val, char c) -{ - while(*val) { - if(*val == c) { - *val = '\0'; - return (val+1); - } - val++; - } - return val; -} - - -static inline int cts_vcard_get_display_name(cts_name *name, char *val) -{ - char *temp; - - temp = cts_get_content_value(val); - name->display = SAFE_STRDUP(temp); - - return CTS_SUCCESS; -} - - -static inline int cts_vcard_get_name(cts_name *name, char *val) -{ - char *temp, *start; - const char separator = ';'; - - start = cts_get_content_value(val); - retv_if(NULL == start, CTS_ERR_NO_DATA); - - temp = cts_strtok(start, separator); - name->last = SMART_STRDUP(start); - start = temp; - temp = cts_strtok(start, separator); - name->first = SMART_STRDUP(start); - start = temp; - temp = cts_strtok(start, separator); - name->addition = SMART_STRDUP(start); - start = temp; - temp = cts_strtok(start, separator); - name->prefix = SMART_STRDUP(start); - start = temp; - temp = cts_strtok(start, separator); - name->suffix = SMART_STRDUP(start); - - return CTS_SUCCESS; -} - -static inline GSList* cts_vcard_get_nickname(GSList *nicks, char *val) -{ - char *temp; - cts_nickname *result; - const char *separator = ","; - - temp = strtok(val, separator); - while (temp) { - if ('\0' == *temp) continue; - - result = (cts_nickname *)contacts_svc_value_new(CTS_VALUE_NICKNAME); - if (result) { - result->embedded = true; - result->nick = strdup(temp); - nicks = g_slist_append(nicks, result); - } - - temp = strtok(NULL, separator); - } - - return nicks; -} - -static inline GSList* cts_vcard_get_event(GSList *events, int type, char *val) -{ - cts_event *event; - - event = (cts_event *)contacts_svc_value_new(CTS_VALUE_EVENT); - if (event) { - char *dest, *src; - - event->embedded = true; - event->type = type; - - dest = src = val; - while (*src) { - if ('0' <= *src && *src <= '9') { - *dest = *src; - dest++; - } - src++; - if (8 <= dest - val) - break; - } - *dest = '\0'; - - event->date = atoi(val); - - events = g_slist_append(events, event); - } - - return events; -} - -static inline int cts_vcard_get_company(cts_company *org, char *val) -{ - char *temp, *start; - - start = cts_get_content_value(val); - retv_if(NULL == start, CTS_ERR_NO_DATA); - - temp = strchr(start, ';'); - if (temp) { - *temp = '\0'; - org->name = SMART_STRDUP(start); - org->department = SMART_STRDUP(temp+1); - } - else - org->name = strdup(start); - - return CTS_SUCCESS; -} - - -static inline char* cts_vcard_get_note(char *val) -{ - char *temp; - - temp = cts_get_content_value(val); - - if (temp) - return g_strcompress(temp); - else - return NULL; -} - - -static inline int cts_vcard_get_time(char *val) -{ - int i; - char tmp[10]; - struct tm ts = {0}; - - i = 0; - while (*val && (*val < '0' || '9' < *val)) val++; - while (*val) { - tmp[i++] = *val; - val++; - if (4<=i || *val < '0' || '9' < *val) break; - } - tmp[i] = 0; - ts.tm_year = atoi(tmp)-1900; - - i = 0; - while (*val && (*val < '0' || '9' < *val)) val++; - while (*val) { - tmp[i++] = *val; - val++; - if (2<=i || *val < '0' || '9' < *val) break; - } - tmp[i] = 0; - ts.tm_mon = atoi(tmp)-1; - - i = 0; - while (*val && (*val < '0' || '9' < *val)) val++; - while (*val) { - tmp[i++] = *val; - val++; - if (2<=i || *val < '0' || '9' < *val) break; - } - tmp[i] = 0; - ts.tm_mday = atoi(tmp); - - i = 0; - while (*val && (*val < '0' || '9' < *val)) val++; - while (*val) { - tmp[i++] = *val; - val++; - if (2<=i || *val < '0' || '9' < *val) break; - } - tmp[i] = 0; - ts.tm_hour = atoi(tmp); - - i = 0; - while (*val && (*val < '0' || '9' < *val)) val++; - while (*val) { - tmp[i++] = *val; - val++; - if (2<=i || *val < '0' || '9' < *val) break; - } - tmp[i] = 0; - ts.tm_min = atoi(tmp); - - i = 0; - while (*val && (*val < '0' || '9' < *val)) val++; - while (*val) { - tmp[i++] = *val; - val++; - if (2<=i || *val < '0' || '9' < *val) break; - } - tmp[i] = 0; - ts.tm_sec = atoi(tmp); - - return (int)mktime(&ts); -} - - -static inline GSList* cts_vcard_get_web(GSList *webs, char *val) -{ - cts_web *web; - char *temp; - - temp = cts_get_content_value(val); - retvm_if(NULL == temp, webs, "Invalid vcard(%s)", val); - - web = (cts_web *)contacts_svc_value_new(CTS_VALUE_WEB); - if (web) { - web->embedded = true; - web->url = strdup(temp);; - if (val != temp) { - *(temp-1) = '\0'; - temp = val; - while (*temp) - { - *temp = tolower(*temp); - temp++; - } - - temp = strchr(val, ';'); - if (temp) { - if (strstr(val, "home")) - web->type = CTS_WEB_TYPE_HOME; - else if (strstr(val, "work")) - web->type = CTS_WEB_TYPE_WORK; - } - } - webs = g_slist_append(webs, web); - } else { - ERR("contacts_svc_value_new() Failed"); - } - - return webs; -} - - -static inline bool cts_vcard_get_number_type(cts_number *number, char *val) -{ - char *temp, *result; - int type = CTS_NUM_TYPE_NONE; - bool pref = false; - - temp = val; - while (*temp) - { - *temp = tolower(*temp); - temp++; - } - - temp = strchr(val , ';'); - if (temp) { - result = strstr(val, "home"); - if (result) type |= CTS_NUM_TYPE_HOME; - result = strstr(val, "msg"); - if (result) type |= CTS_NUM_TYPE_MSG; - result = strstr(val, "work"); - if (result) type |= CTS_NUM_TYPE_WORK; - result = strstr(val, "pref"); - if (result) pref = true; - result = strstr(val, "voice"); - if (result) type |= CTS_NUM_TYPE_VOICE; - result = strstr(val, "fax"); - if (result) type |= CTS_NUM_TYPE_FAX; - result = strstr(val, "cell"); - if (result) type |= CTS_NUM_TYPE_CELL; - result = strstr(val, "video"); - if (result) type |= CTS_NUM_TYPE_VIDEO; - result = strstr(val, "pager"); - if (result) type |= CTS_NUM_TYPE_PAGER; - result = strstr(val, "bbs"); - if (result) type |= CTS_NUM_TYPE_BBS; - result = strstr(val, "modem"); - if (result) type |= CTS_NUM_TYPE_MODEM; - result = strstr(val, "car"); - if (result) type |= CTS_NUM_TYPE_CAR; - result = strstr(val, "isdn"); - if (result) type |= CTS_NUM_TYPE_ISDN; - result = strstr(val, "pcs"); - if (result) type |= CTS_NUM_TYPE_PCS; - } - number->type = type; - - return pref; -} - - -static inline GSList* cts_vcard_get_number(GSList *numbers, char *val) -{ - cts_number *number; - char *temp; - - temp = cts_get_content_value(val); - retvm_if(NULL == temp, numbers, "Invalid vcard(%s)", val); - - number = (cts_number *)contacts_svc_value_new(CTS_VALUE_NUMBER); - if (number) { - number->embedded = true; - number->number = strdup(temp); - if (val != temp) { - *(temp-1) = '\0'; - number->is_default = cts_vcard_get_number_type(number, val); - } - numbers = g_slist_append(numbers, number); - } else { - ERR("contacts_svc_value_new() Failed"); - } - - return numbers; -} - -static inline bool cts_vcard_get_email_type(cts_email *email, char *val) -{ - char *temp; - int type = CTS_EMAIL_TYPE_NONE; - bool pref = false; - - temp = val; - while (*temp) - { - *temp = tolower(*temp); - temp++; - } - - temp = strchr(val , ';'); - if (temp) { - if (strstr(val, "home")) - type = CTS_EMAIL_TYPE_HOME; - else if (strstr(val, "work")) - type = CTS_EMAIL_TYPE_WORK; - if (strstr(val, "pref")) - pref = true; - } - email->type = type; - - return pref; -} - -static inline GSList* cts_vcard_get_email(GSList *emails, char *val) -{ - cts_email *email; - char *temp; - - temp = cts_get_content_value(val); - retvm_if(NULL == temp, emails, "Invalid vcard(%s)", val); - - email = (cts_email *)contacts_svc_value_new(CTS_VALUE_EMAIL); - if (email) { - email->embedded = true; - email->email_addr = strdup(temp); - if (val != temp) { - *(temp-1) = '\0'; - email->is_default = cts_vcard_get_email_type(email, val); - } - emails = g_slist_append(emails, email); - } else { - ERR("contacts_svc_value_new() Failed"); - } - - return emails; -} - -static inline bool cts_vcard_get_postal_type(cts_postal *postal, char *val) -{ - char *temp, *result; - int type = CTS_ADDR_TYPE_NONE; - bool pref = false; - - temp = val; - while (*temp) - { - *temp = tolower(*temp); - temp++; - } - - temp = strchr(val , ';'); - if (temp) { - result = strstr(val, "dom"); - if (result) type |= CTS_ADDR_TYPE_DOM; - result = strstr(val, "intl"); - if (result) type |= CTS_ADDR_TYPE_INTL; - result = strstr(val, "postal"); - if (result) type |= CTS_ADDR_TYPE_POSTAL; - result = strstr(val, "parcel"); - if (result) type |= CTS_ADDR_TYPE_PARCEL; - result = strstr(val, "home"); - if (result) type |= CTS_ADDR_TYPE_HOME; - result = strstr(val, "work"); - if (result) type |= CTS_ADDR_TYPE_WORK; - result = strstr(val, "pref"); - if (result) pref = true; - } - postal->type = type; - - return pref; -} - -#define CTS_GET_ADDR_COMPONENT(dest, src, tmp_char) \ - tmp_char = strchr(src , ';'); \ -if (tmp_char) { \ - *tmp_char = '\0'; \ - dest = SMART_STRDUP(src); \ - src = tmp_char+1; \ -} \ -else { \ - dest = SMART_STRDUP(src); \ - break; \ -} \ - -static inline GSList* cts_vcard_get_postal(GSList *postals, char *val) -{ - char *text; - cts_postal *postal; - - postal = (cts_postal *)contacts_svc_value_new(CTS_VALUE_POSTAL); - if (postal) { - postal->embedded = true; - - text = strrchr(val , ':'); - if (text) - text++; - else - text = val; - - while (true) { - char *temp; - - CTS_GET_ADDR_COMPONENT(postal->pobox, text, temp); - CTS_GET_ADDR_COMPONENT(postal->extended, text, temp); - CTS_GET_ADDR_COMPONENT(postal->street, text, temp); - CTS_GET_ADDR_COMPONENT(postal->locality, text, temp); - CTS_GET_ADDR_COMPONENT(postal->region, text, temp); - CTS_GET_ADDR_COMPONENT(postal->postalcode, text, temp); - CTS_GET_ADDR_COMPONENT(postal->country, text, temp); - - ERR("invalid ADR type(%s)", temp); - break; - } - if (postal->pobox || postal->extended || postal->street || postal->locality - || postal->region || postal->postalcode || postal->country) { - postal->is_default = cts_vcard_get_postal_type(postal, val); - } else { - ERR("Invalid vcard(%s)", val); - contacts_svc_value_free((CTSvalue *)postal); - return postals; - } - - postals = g_slist_append(postals, postal); - } - - return postals; -} - -static inline int cts_vcard_get_photo_type(char *val) -{ - char *temp, *result; - - temp = val; - while (*temp) - { - *temp = tolower(*temp); - temp++; - } - - result = strstr(val, "jpeg"); - if (result) return CTS_VCARD_IMG_JPEG; - result = strstr(val, "jpg"); - if (result) return CTS_VCARD_IMG_JPEG; - - result = strstr(val, "png"); - if (result) return CTS_VCARD_IMG_PNG; - - result = strstr(val, "gif"); - if (result) return CTS_VCARD_IMG_GIF; - - result = strstr(val, "tiff"); - if (result) return CTS_VCARD_IMG_TIFF; - - return CTS_VCARD_IMG_NONE; -} - -static inline const char* cts_get_img_suffix(int type) -{ - switch (type) - { - case CTS_VCARD_IMG_TIFF: - return "tiff"; - case CTS_VCARD_IMG_GIF: - return "gif"; - case CTS_VCARD_IMG_PNG: - return "png"; - case CTS_VCARD_IMG_JPEG: - case CTS_VCARD_IMG_NONE: - default: - return "jpeg"; - } -} - -static inline int cts_vcard_get_photo(cts_ct_base *base, char *val) -{ - int ret, type, fd; - gsize size; - guchar *buf; - char *temp; - char dest[CTS_IMG_PATH_SIZE_MAX]; - - temp = strchr(val , ':'); - retvm_if(NULL == temp, CTS_ERR_ARG_INVALID, "val is invalid(%s)", val); - - *temp = '\0'; - type = cts_vcard_get_photo_type(val); - - ret = snprintf(dest, sizeof(dest), "%s/%d-%d.%s", CTS_VCARD_IMAGE_LOCATION, - getpid(), cts_tmp_photo_id++, cts_get_img_suffix(type)); - retvm_if(ret<=0, CTS_ERR_FAIL, "Destination file name was not created"); - - fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660); - retvm_if(fd < 0, CTS_ERR_FAIL, "open(%s) Failed(%d)", dest, errno); - - buf = g_base64_decode(temp+1, &size); - - while (0 < size) { - ret = write(fd, buf, size); - if (ret <= 0) { - if (EINTR == errno) - continue; - else { - ERR("write() Failed(%d)", errno); - close(fd); - if (ENOSPC == errno) - return CTS_ERR_NO_SPACE; - else - return CTS_ERR_IO_ERR; - } - } - size -= ret; - } - - close(fd); - g_free(buf); - - base->vcard_img_path = strdup(dest); - - return CTS_SUCCESS; -} - -static inline GSList* cts_vcard_get_group(GSList *groups, char *val) -{ - char *temp; - cts_group *result; - const char *separator = ","; - - temp = strtok(val, separator); - while (temp) { - if ('\0' == *temp) continue; - - result = (cts_group *)contacts_svc_value_new(CTS_VALUE_GROUP_RELATION); - if (result) { - result->embedded = true; - result->vcard_group = strdup(temp); - groups = g_slist_append(groups, result); - } - - temp = strtok(NULL, separator); - } - - return groups; -} - -static inline char* cts_vcard_pass_unsupported(char *vcard) -{ - while (*vcard) { - if ('\n' == *vcard) - return (vcard + 1); - vcard++; - } - - return NULL; -} - -static inline int cts_vcard_get_contact(int ver, int flags, - char *vcard, contact_t *contact) -{ - int type; - char *cursor, *new_start, *val; - - cursor = vcard; - while (cursor) - { - type = cts_vcard_check_content_type(&cursor); - if (CTS_VCARD_VALUE_NONE == type) { - new_start = cts_vcard_pass_unsupported(cursor); - if (new_start) { - cursor = new_start; - continue; - } - else - break; - } - - new_start = cts_vcard_get_val(ver, cursor, &val); - if (NULL == new_start) - continue; - - if (NULL == val) { - cursor = new_start; - continue; - } - cts_vcard_remove_folding(val); - - switch (type) { - case CTS_VCARD_VALUE_FN: - cts_vcard_get_display_name(contact->name, val); - free(val); - break; - case CTS_VCARD_VALUE_N: - cts_vcard_get_name(contact->name, val); - free(val); - break; - case CTS_VCARD_VALUE_NICKNAME: - contact->nicknames = cts_vcard_get_nickname(contact->nicknames, val); - free(val); - break; - case CTS_VCARD_VALUE_PHOTO: - cts_vcard_get_photo(contact->base, val); - free(val); - break; - case CTS_VCARD_VALUE_BDAY: - contact->events = cts_vcard_get_event(contact->events, - CTS_EVENT_TYPE_BIRTH, val); - free(val); - break; - case CTS_VCARD_VALUE_ADR: - case CTS_VCARD_VALUE_LABEL: - contact->postal_addrs = cts_vcard_get_postal(contact->postal_addrs, val); - free(val); - break; - case CTS_VCARD_VALUE_TEL: - contact->numbers = cts_vcard_get_number(contact->numbers, val); - free(val); - break; - case CTS_VCARD_VALUE_EMAIL: - contact->emails = cts_vcard_get_email(contact->emails, val); - free(val); - break; - case CTS_VCARD_VALUE_TITLE: - if (NULL == contact->company) { - contact->company = (cts_company*)contacts_svc_value_new(CTS_VALUE_COMPANY); - if (NULL == contact->company) { - free(val); - ERR("contacts_svc_value_new(CTS_VALUE_COMPANY) Failed"); - return CTS_ERR_OUT_OF_MEMORY; - } - contact->company->embedded = true; - } - contact->company->jot_title = val; - break; - case CTS_VCARD_VALUE_ROLE: - if (NULL == contact->company) { - contact->company = (cts_company*)contacts_svc_value_new(CTS_VALUE_COMPANY); - if (NULL == contact->company) { - free(val); - ERR("contacts_svc_value_new(CTS_VALUE_COMPANY) Failed"); - return CTS_ERR_OUT_OF_MEMORY; - } - contact->company->embedded = true; - } - contact->company->role = val; - break; - case CTS_VCARD_VALUE_ORG: - if (NULL == contact->company) { - contact->company = (cts_company*)contacts_svc_value_new(CTS_VALUE_COMPANY); - if (NULL == contact->company) { - free(val); - ERR("contacts_svc_value_new(CTS_VALUE_COMPANY) Failed"); - return CTS_ERR_OUT_OF_MEMORY; - } - contact->company->embedded = true; - } - cts_vcard_get_company(contact->company, val); - free(val); - break; - case CTS_VCARD_VALUE_NOTE: - contact->base->note = cts_vcard_get_note(val); - free(val); - break; - case CTS_VCARD_VALUE_REV: - if (*val) - contact->base->changed_time = cts_vcard_get_time(val);; - free(val); - break; - case CTS_VCARD_VALUE_UID: - contact->base->uid = val; - break; - case CTS_VCARD_VALUE_URL: - contact->web_addrs = cts_vcard_get_web(contact->web_addrs, val); - free(val); - break; - case CTS_VCARD_VALUE_X_ANNIVERSARY: - contact->events = cts_vcard_get_event(contact->events, - CTS_EVENT_TYPE_ANNIVERSARY, val); - free(val); - break; - case CTS_VCARD_VALUE_X_IRMC_LUID: - contact->base->id = atoi(val); - free(val); - break; - case CTS_VCARD_VALUE_X_SLP_GROUP: - if (flags & CTS_VCARD_CONTENT_X_SLP_GROUP) - contact->grouprelations = cts_vcard_get_group(contact->grouprelations, val); - free(val); - break; - case CTS_VCARD_VALUE_END: - free(val); - return CTS_SUCCESS; - default: - ERR("cts_vcard_check_content_type() Failed(%d)", type); - return CTS_ERR_VOBJECT_FAILED; - } - cursor = new_start; - } - - ERR("Invalid vcard(%s)", vcard); - return CTS_ERR_ARG_INVALID; -} - -static void cts_vcard_initial(void) -{ - if (NULL == *content_name) { - //content_name[CTS_VCARD_VALUE_NAME] = "NAME"; /* not supported */ - //content_name[CTS_VCARD_VALUE_PROFILE] = "PROFILE"; /* not supported */ - //content_name[CTS_VCARD_VALUE_SOURCE] = "SOURCE"; /* not supported */ - content_name[CTS_VCARD_VALUE_FN] = "FN"; - content_name[CTS_VCARD_VALUE_N] = "N"; - content_name[CTS_VCARD_VALUE_NICKNAME] = "NICKNAME"; - content_name[CTS_VCARD_VALUE_PHOTO] = "PHOTO"; - content_name[CTS_VCARD_VALUE_BDAY] = "BDAY"; - content_name[CTS_VCARD_VALUE_ADR] = "ADR"; - content_name[CTS_VCARD_VALUE_LABEL] = "LABEL"; /* not supported */ - content_name[CTS_VCARD_VALUE_TEL] = "TEL"; - content_name[CTS_VCARD_VALUE_EMAIL] = "EMAIL"; - //content_name[CTS_VCARD_VALUE_MAILER] = "MAILER"; /* not supported */ - //content_name[CTS_VCARD_VALUE_TZ] = "TZ"; /* not supported */ - //content_name[CTS_VCARD_VALUE_GEO] = "GEO"; /* not supported */ - content_name[CTS_VCARD_VALUE_TITLE] = "TITLE"; - content_name[CTS_VCARD_VALUE_ROLE] = "ROLE"; - //content_name[CTS_VCARD_VALUE_LOGO] = "LOGO"; /* not supported */ - //content_name[CTS_VCARD_VALUE_AGENT] = "AGENT"; /* not supported */ - content_name[CTS_VCARD_VALUE_ORG] = "ORG"; - //content_name[CTS_VCARD_VALUE_CATEGORIES] = "CATEGORIES"; /* not supported */ - content_name[CTS_VCARD_VALUE_NOTE] = "NOTE"; - //content_name[CTS_VCARD_VALUE_PRODID] = "PRODID"; /* not supported */ - content_name[CTS_VCARD_VALUE_REV] = "REV"; - //content_name[CTS_VCARD_VALUE_SORT-STRING] = "SORT-STRING"; /* not supported */ - //content_name[CTS_VCARD_VALUE_SOUND] = "SOUND"; /* not supported */ - content_name[CTS_VCARD_VALUE_UID] = "UID"; - content_name[CTS_VCARD_VALUE_URL] = "URL"; - //content_name[CTS_VCARD_VALUE_VERSION] = "VERSION"; /* not supported */ - //content_name[CTS_VCARD_VALUE_CLASS] = "CLASS"; /* not supported */ - //content_name[CTS_VCARD_VALUE_KEY] = "KEY"; /* not supported */ - content_name[CTS_VCARD_VALUE_X_ANNIVERSARY] = "X-ANNIVERSARY"; - //content_name[CTS_VCARD_VALUE_X_CHILDREN] = "X-CHILDREN"; - content_name[CTS_VCARD_VALUE_X_IRMC_LUID] = "X-IRMC-LUID"; - content_name[CTS_VCARD_VALUE_X_SLP_GROUP] = "X-SLP-GROUP"; - content_name[CTS_VCARD_VALUE_END] = "END"; - } -}; - -int cts_vcard_parse(const void *vcard_stream, CTSstruct **contact, int flags) -{ - int ret, ver; - contact_t *result; - char *val_begin, *new_start, *val; - char *vcard = (char *)vcard_stream; - - retv_if(NULL == vcard_stream, CTS_ERR_ARG_NULL); - - cts_vcard_initial(); - - vcard = cts_vcard_check_word(vcard, "BEGIN:VCARD"); - retvm_if(NULL == vcard, CTS_ERR_ARG_INVALID, "The vcard is invalid."); - - val_begin = cts_vcard_check_word(vcard, "VERSION:"); - new_start = cts_vcard_get_val(CTS_VCARD_VER_NONE, val_begin, &val); - if (NULL == new_start || NULL == val) - ver = CTS_VCARD_VER_2_1; - else { - ver = cts_vcard_check_version(val); - free(val); - vcard = new_start; - } - - result = (contact_t *)contacts_svc_struct_new(CTS_STRUCT_CONTACT); - retvm_if(NULL == result, CTS_ERR_OUT_OF_MEMORY, "contacts_svc_struct_new() Failed"); - - result->name = (cts_name*)contacts_svc_value_new(CTS_VALUE_NAME); - if (NULL == result->name) { - ERR("contacts_svc_value_new(CTS_VALUE_NAME) Failed"); - contacts_svc_struct_free((CTSstruct *)result); - return CTS_ERR_OUT_OF_MEMORY; - } - result->name->embedded = true; - - result->base = (cts_ct_base*)contacts_svc_value_new(CTS_VALUE_CONTACT_BASE_INFO); - if (NULL == result->base) { - ERR("contacts_svc_value_new(CTS_VALUE_CONTACT_BASE_INFO) Failed"); - contacts_svc_struct_free((CTSstruct *)result); - return CTS_ERR_OUT_OF_MEMORY; - } - result->base->embedded = true; - - ret = cts_vcard_get_contact(ver, flags, vcard, result); - - if (CTS_SUCCESS != ret) { - contacts_svc_struct_free((CTSstruct *)result); - if (CTS_ERR_ARG_INVALID == ret) - ERR("cts_vcard_get_contact() Failed(%d)\n %s \n", ret, vcard); - else - ERR("cts_vcard_get_contact() Failed(%d)", ret); - - return ret; - } - - *contact = (CTSstruct *)result; - return CTS_SUCCESS; -} - -/************************** - * - * Contact To VCard - * - **************************/ - -const char *CTS_CRLF = "\r\n"; - -static inline int cts_vcard_append_name(cts_name *name, - char *dest, int dest_size) -{ - int ret_len; - ret_len = snprintf(dest, dest_size, "%s", content_name[CTS_VCARD_VALUE_N]); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ":%s", - SAFE_STR(name->last)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(name->first)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(name->addition)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(name->prefix)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s%s", - SAFE_STR(name->suffix), CTS_CRLF); - - if (name->display) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_FN], - name->display, CTS_CRLF); - else { - char display[1024]; - - if (name->first && name->last) { - if (CTS_ORDER_NAME_FIRSTLAST == contacts_svc_get_order(CTS_ORDER_OF_SORTING)) { - snprintf(display, sizeof(display), "%s %s", name->first, name->last); - } else { - int lang; - if (CTS_LANG_DEFAULT == name->lang_type) - lang = cts_get_default_language(); - else - lang = name->lang_type; - - if (CTS_LANG_ENGLISH == lang) - snprintf(display, sizeof(display), "%s, %s", name->last, name->first); - else - snprintf(display, sizeof(display), "%s %s", name->last, name->first); - } - } - else - snprintf(display, sizeof(display), "%s%s", SAFE_STR(name->first), SAFE_STR(name->last)); - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_FN], - display, CTS_CRLF); - } - - return ret_len; -} - -static inline int cts_vcard_put_number_type(int type, char *dest, int dest_size) -{ - int ret_len = 0; - if (type & CTS_NUM_TYPE_HOME) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME"); - if (type & CTS_NUM_TYPE_MSG) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MSG"); - if (type & CTS_NUM_TYPE_WORK) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK"); - if (type & CTS_NUM_TYPE_VOICE) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE"); - if (type & CTS_NUM_TYPE_FAX) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "FAX"); - if (type & CTS_NUM_TYPE_VOICE) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE"); - if (type & CTS_NUM_TYPE_CELL) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CELL"); - if (type & CTS_NUM_TYPE_VIDEO) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VIDEO"); - if (type & CTS_NUM_TYPE_PAGER) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PAGER"); - if (type & CTS_NUM_TYPE_BBS) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "BBS"); - if (type & CTS_NUM_TYPE_MODEM) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MODEM"); - if (type & CTS_NUM_TYPE_CAR) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CAR"); - if (type & CTS_NUM_TYPE_ISDN) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "ISDN"); - if (type & CTS_NUM_TYPE_PCS) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PCS"); - - return ret_len; -} - -static inline int cts_vcard_append_numbers(GSList *numbers, - char *dest, int dest_size) -{ - int ret_len = 0; - GSList *cursor; - cts_number *data; - - for (cursor=numbers;cursor;cursor=cursor->next) { - data = cursor->data; - if (data->number) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", - content_name[CTS_VCARD_VALUE_TEL]); - ret_len += cts_vcard_put_number_type(data->type, dest+ret_len, - dest_size-ret_len); - if (data->is_default) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PREF"); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ":%s%s", - data->number, CTS_CRLF); - } - } - - return ret_len; -} - -static inline int cts_vcard_append_emails(GSList *emails, - char *dest, int dest_size) -{ - int ret_len = 0; - GSList *cursor; - cts_email *data; - - for (cursor=emails;cursor;cursor=cursor->next) { - data = cursor->data; - if (data->email_addr) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", - content_name[CTS_VCARD_VALUE_EMAIL]); - if (CTS_EMAIL_TYPE_HOME & data->type) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME"); - if (CTS_EMAIL_TYPE_WORK & data->type) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK"); - - if (data->is_default) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PREF"); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ":%s%s", - data->email_addr, CTS_CRLF); - } - } - - return ret_len; -} - -static inline int cts_vcard_put_postal_type(int type, char *dest, int dest_size) -{ - int ret_len = 0; - if (type & CTS_ADDR_TYPE_DOM) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "DOM"); - if (type & CTS_ADDR_TYPE_INTL) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "INTL"); - if (type & CTS_ADDR_TYPE_HOME) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME"); - if (type & CTS_ADDR_TYPE_WORK) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK"); - if (type & CTS_ADDR_TYPE_POSTAL) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "POSTAL"); - if (type & CTS_ADDR_TYPE_PARCEL) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PARCEL"); - - return ret_len; -} - -static inline int cts_vcard_append_postals(GSList *numbers, - char *dest, int dest_size) -{ - int ret_len = 0; - GSList *cursor; - cts_postal *data; - - for (cursor=numbers;cursor;cursor=cursor->next) { - data = cursor->data; - if (data) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", - content_name[CTS_VCARD_VALUE_ADR]); - ret_len += cts_vcard_put_postal_type(data->type, dest+ret_len, - dest_size-ret_len); - if (data->is_default) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PREF"); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ":%s", - SAFE_STR(data->pobox)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(data->extended)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(data->street)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(data->locality)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(data->region)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - SAFE_STR(data->postalcode)); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s%s", - SAFE_STR(data->country), CTS_CRLF); - } - } - - return ret_len; -} - -static inline int cts_vcard_append_company(cts_company *org, - char *dest, int dest_size) -{ - int ret_len = 0; - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s", - content_name[CTS_VCARD_VALUE_ORG], - SAFE_STR(org->name)); - if (org->department) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", - org->department); - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", CTS_CRLF); - - if (org->jot_title) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_TITLE], - org->jot_title, CTS_CRLF); - if (org->role) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_ROLE], - org->role, CTS_CRLF); - - return ret_len; -} - -static inline int cts_vcard_append_nicks(GSList *nicks, - char *dest, int dest_size) -{ - bool first; - int ret_len = 0; - GSList *cursor; - cts_nickname *data; - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:", - content_name[CTS_VCARD_VALUE_NICKNAME]); - - first = true; - for (cursor=nicks;cursor;cursor=cursor->next) { - data = cursor->data; - if (data->nick && *data->nick) { - if (first) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", data->nick); - first = false; - } - else { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ",%s", data->nick); - } - } - } - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", CTS_CRLF); - - return ret_len; -} - -static inline int cts_vcard_append_webs(GSList *webs, - char *dest, int dest_size) -{ - int ret_len = 0; - GSList *cursor; - cts_web *data; - - for (cursor=webs;cursor;cursor=cursor->next) { - data = cursor->data; - if (data->url && *data->url) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_URL], - data->url, CTS_CRLF); - } - } - - return ret_len; -} - -static inline int cts_vcard_append_events(GSList *webs, - char *dest, int dest_size) -{ - int ret_len = 0; - GSList *cursor; - cts_event *data; - - for (cursor=webs;cursor;cursor=cursor->next) { - data = cursor->data; - if (!data->date) continue; - - if (CTS_EVENT_TYPE_BIRTH == data->type) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%d-%02d-%d%s", - content_name[CTS_VCARD_VALUE_BDAY], - data->date/10000, (data->date%10000)/100, data->date%100, - CTS_CRLF); - } - else if (CTS_EVENT_TYPE_ANNIVERSARY == data->type) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%d-%02d-%d%s", - content_name[CTS_VCARD_VALUE_X_ANNIVERSARY], - data->date/10000, (data->date%10000)/100, data->date%100, - CTS_CRLF); - } - } - - return ret_len; -} - -static inline const char* cts_get_photo_type_str(int type) -{ - switch (type) - { - case CTS_VCARD_IMG_TIFF: - return "TIFF"; - case CTS_VCARD_IMG_GIF: - return "GIF"; - case CTS_VCARD_IMG_PNG: - return "PNG"; - case CTS_VCARD_IMG_JPEG: - default: - return "JPEG"; - } -} - -static inline int cts_vcard_put_photo(const char *path, char *dest, int dest_size) -{ - int ret, fd, type; - gsize read_len; - char *suffix; - gchar *buf; - guchar image[CTS_VCARD_PHOTO_MAX_SIZE]; - - suffix = strrchr(path, '.'); - retvm_if(NULL == suffix, 0, "Image Type(%s) is invalid", path); - - type = cts_vcard_get_photo_type(suffix); - retvm_if(CTS_VCARD_IMG_NONE == type, 0, "Image Type(%s) is invalid", path); - - fd = open(path, O_RDONLY); - retvm_if(fd < 0, 0, "Open(%s) Failed(%d)", path, errno); - - read_len = 0; - while ((ret=read(fd, image+read_len, sizeof(image)-read_len))) { - if (-1 == ret) { - if (EINTR == errno) - continue; - else - break; - } - read_len += ret; - } - close(fd); - retvm_if(ret < 0, 0, "read() Failed(%d)", errno); - - ret = 0; - buf = g_base64_encode(image, read_len); - if (buf) { - ret = snprintf(dest, dest_size, "%s;ENCODING=BASE64;TYPE=%s:%s%s%s", - content_name[CTS_VCARD_VALUE_PHOTO], - cts_get_photo_type_str(type), buf, CTS_CRLF, CTS_CRLF); - g_free(buf); - } - - return ret; -} -static inline int cts_vcard_append_base(cts_ct_base *base, - char *dest, int dest_size) -{ - int ret_len = 0; - - if (base->img_path) - ret_len += cts_vcard_put_photo(base->img_path, - dest+ret_len, dest_size-ret_len); - if (base->uid) - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_UID], - base->uid, CTS_CRLF); - if (base->note) { - gchar *escaped_note; - escaped_note = g_strescape(base->note, NULL); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%s%s", - content_name[CTS_VCARD_VALUE_NOTE], - escaped_note, CTS_CRLF); - g_free(escaped_note); - } - - if (base->changed_time) { - struct tm ts; - gmtime_r((time_t *)&base->changed_time, &ts); - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s", - content_name[CTS_VCARD_VALUE_REV], - 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday, - ts.tm_hour, ts.tm_min, ts.tm_sec, - CTS_CRLF); - } - - return ret_len; -} - -static inline int cts_vcard_append_grouprelations(GSList *grouprelations, - char *dest, int dest_size) -{ - bool first; - int ret_len = 0; - GSList *cursor; - cts_group *data; - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s:", - content_name[CTS_VCARD_VALUE_X_SLP_GROUP]); - - first = true; - for (cursor=grouprelations;cursor;cursor=cursor->next) { - data = cursor->data; - if (data->name && *data->name) { - if (first) { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", data->name); - first = false; - } - else { - ret_len += snprintf(dest+ret_len, dest_size-ret_len, ",%s", data->name); - } - } - } - - ret_len += snprintf(dest+ret_len, dest_size-ret_len, "%s", CTS_CRLF); - - return ret_len; -} - -static inline int cts_vcard_append_contact(int flags, contact_t *contact, - char *dest, int dest_size) -{ - int ret_len = 0; - - if (contact->name) - ret_len += cts_vcard_append_name(contact->name, - dest+ret_len, dest_size-ret_len); - if (contact->company) - ret_len += cts_vcard_append_company(contact->company, - dest+ret_len, dest_size-ret_len); - if (contact->postal_addrs) - ret_len += cts_vcard_append_postals(contact->postal_addrs, - dest+ret_len, dest_size-ret_len); - if (contact->numbers) - ret_len += cts_vcard_append_numbers(contact->numbers, - dest+ret_len, dest_size-ret_len); - if (contact->emails) - ret_len += cts_vcard_append_emails(contact->emails, - dest+ret_len, dest_size-ret_len); - if (contact->nicknames) - ret_len += cts_vcard_append_nicks(contact->nicknames, - dest+ret_len, dest_size-ret_len); - if (contact->web_addrs) - ret_len += cts_vcard_append_webs(contact->web_addrs, - dest+ret_len, dest_size-ret_len); - if (contact->events) - ret_len += cts_vcard_append_events(contact->events, - dest+ret_len, dest_size-ret_len); - if (contact->base) - ret_len += cts_vcard_append_base(contact->base, - dest+ret_len, dest_size-ret_len); - if (contact->grouprelations && (flags & CTS_VCARD_CONTENT_X_SLP_GROUP)) - ret_len += cts_vcard_append_grouprelations(contact->grouprelations, - dest+ret_len, dest_size-ret_len); - - return ret_len; -} - -#define CTS_VCARD_FOLDING_LIMIT 75 - -static inline int cts_vcard_add_folding(char *src) -{ - int len, result_len; - char result[CTS_VCARD_FILE_MAX_SIZE]; - char *r; - const char *s; - - s = src; - r = result; - len = result_len = 0; - while (*s) { - if ('\r' == *s) - len--; - else if ('\n' == *s) - len = -1; - - if (CTS_VCARD_FOLDING_LIMIT == len) { - *r = '\r'; - r++; - *r = '\n'; - r++; - *r = ' '; - r++; - len = 1; - result_len += 3; - } - - *r = *s; - r++; - s++; - len++; - result_len++; - retvm_if(sizeof(result) - 5 < result_len, CTS_ERR_ARG_INVALID, - "src is too long\n(%s)", src); - } - *r = '\0'; - - memcpy(src, result, result_len+1); - return CTS_SUCCESS; -} - -int cts_vcard_make(const CTSstruct *contact, char **vcard_stream, int flags) -{ - int ret_len, ret; - char result[CTS_VCARD_FILE_MAX_SIZE]; - - retv_if(NULL == contact, CTS_ERR_ARG_NULL); - retv_if(NULL == vcard_stream, CTS_ERR_ARG_NULL); - retvm_if(CTS_STRUCT_CONTACT != contact->s_type, CTS_ERR_ARG_INVALID, - "The record(%d) must be type of CTS_STRUCT_CONTACT.", contact->s_type); - - cts_vcard_initial(); - - ret_len = snprintf(result, sizeof(result), "%s%s", "BEGIN:VCARD", CTS_CRLF); - ret_len += snprintf(result+ret_len, sizeof(result)-ret_len, - "%s%s%s", "VERSION:", "3.0", CTS_CRLF); - - ret_len += cts_vcard_append_contact(flags, (contact_t *)contact, - result+ret_len, sizeof(result)-ret_len); - - retvm_if(sizeof(result)-ret_len <= 0, CTS_ERR_EXCEEDED_LIMIT, - "This contact has too many information"); - - ret_len += snprintf(result+ret_len, sizeof(result)-ret_len, - "%s%s", "END:VCARD", CTS_CRLF); - - ret = cts_vcard_add_folding(result); - if (CTS_SUCCESS != ret) - return ret; - *vcard_stream = strdup(result); - - return CTS_SUCCESS; -} - |