summaryrefslogtreecommitdiff
path: root/src/libical/icalvalue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libical/icalvalue.c')
-rw-r--r--src/libical/icalvalue.c238
1 files changed, 150 insertions, 88 deletions
diff --git a/src/libical/icalvalue.c b/src/libical/icalvalue.c
index bad30e2..63a0121 100644
--- a/src/libical/icalvalue.c
+++ b/src/libical/icalvalue.c
@@ -50,9 +50,9 @@
#include <locale.h>
#include <ctype.h> /* for isspace and isdigit */
-#ifdef WIN32
-#define snprintf _snprintf
-#define strcasecmp stricmp
+#if defined(_MSC_VER)
+#define snprintf _snprintf
+#define strcasecmp stricmp
#endif
#if _MAC_OS_
@@ -136,18 +136,37 @@ icalvalue* icalvalue_new_clone(const icalvalue* old) {
new->data.v_string=icalmemory_strdup(old->data.v_string);
if ( new->data.v_string == 0 ) {
+ icalvalue_free(new);
return 0;
}
}
break;
}
+ case ICAL_ACTION_VALUE:
+ {
+ new->data = old->data;
+
+ if (old->data.v_enum == ICAL_ACTION_X) {
+ //preserve the custom action string
+ if (old->x_value != 0) {
+ new->x_value = icalmemory_strdup(old->x_value);
+
+ if (new->x_value == 0) {
+ icalvalue_free(new);
+ return 0;
+ }
+ }
+ }
+ break;
+ }
case ICAL_RECUR_VALUE:
{
if(old->data.v_recur != 0){
new->data.v_recur = malloc(sizeof(struct icalrecurrencetype));
if(new->data.v_recur == 0){
+ icalvalue_free(new);
return 0;
}
@@ -163,6 +182,7 @@ icalvalue* icalvalue_new_clone(const icalvalue* old) {
new->x_value=icalmemory_strdup(old->x_value);
if (new->x_value == 0) {
+ icalvalue_free(new);
return 0;
}
}
@@ -187,6 +207,7 @@ static char* icalmemory_strdup_and_dequote(const char* str)
const char* p;
char* out = (char*)malloc(sizeof(char) * strlen(str) +1);
char* pout;
+ int wroteNull = 0;
if (out == 0){
return 0;
@@ -194,7 +215,11 @@ static char* icalmemory_strdup_and_dequote(const char* str)
pout = out;
- for (p = str; *p!=0; p++){
+ /* Stop the loop when encountering a terminator in the source string
+ or if a null has been written to the destination. This prevents
+ reading past the end of the source string if the last character
+ is a backslash. */
+ for (p = str; !wroteNull && *p!=0; p++){
if( *p == '\\')
{
@@ -202,6 +227,7 @@ static char* icalmemory_strdup_and_dequote(const char* str)
switch(*p){
case 0:
{
+ wroteNull = 1; //stops iteration so p isn't incremented past the end of str
*pout = '\0';
break;
@@ -263,6 +289,84 @@ static char* icalmemory_strdup_and_dequote(const char* str)
}
/*
+ * Returns a quoted copy of a string
+ * @todo This is not RFC2445 compliant.
+ * The RFC only allows:
+ * TSAFE-CHAR = %x20-21 / %x23-2B / %x2D-39 / %x3C-5B / %x5D-7E / NON-US-ASCII
+ * As such, \t\r\b\f are not allowed, not even escaped
+ */
+static char* icalmemory_strdup_and_quote(const icalvalue* value,
+ const char* unquoted_str)
+{
+ char *str;
+ char *str_p;
+ const char *p;
+ size_t buf_sz;
+
+ buf_sz = strlen(unquoted_str)+1;
+
+ str_p = str = (char*)icalmemory_new_buffer(buf_sz);
+
+ if (str_p == 0){
+ return 0;
+ }
+
+ for(p=unquoted_str; *p!=0; p++){
+
+ switch(*p){
+ case '\n': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\n");
+ break;
+ }
+
+ case '\t': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\t");
+ break;
+ }
+ case '\r': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\r");
+ break;
+ }
+ case '\b': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\b");
+ break;
+ }
+ case '\f': {
+ icalmemory_append_string(&str,&str_p,&buf_sz,"\\f");
+ break;
+ }
+
+ case ';':
+ case ',':
+ /* unescaped COMMA is allowed in CATEGORIES property as its
+ considered a list delimiter here, see:
+ http://tools.ietf.org/html/rfc2445#section-4.3.11 */
+ if (icalproperty_isa(value->parent) == ICAL_CATEGORIES_PROPERTY) {
+ icalmemory_append_char(&str,&str_p,&buf_sz,*p);
+ break;
+ }
+ case '"':
+ case '\\': {
+ icalmemory_append_char(&str,&str_p,&buf_sz,'\\');
+ icalmemory_append_char(&str,&str_p,&buf_sz,*p);
+ break;
+ }
+
+ default: {
+ icalmemory_append_char(&str,&str_p,&buf_sz,*p);
+ }
+ }
+ }
+
+ /* Assume the last character is not a '\0' and add one. We could
+ check *str_p != 0, but that would be an uninitialized memory
+ read. */
+
+ icalmemory_append_char(&str,&str_p,&buf_sz,'\0');
+ return str;
+}
+
+/*
* FIXME
*
* This is a bad API, as it forces callers to specify their own X type.
@@ -297,14 +401,16 @@ icalvalue* icalvalue_new_enum(icalvalue_kind kind, int x_type, const char* str)
* If you want a code that that does the same job with a decimal separator
* dependant on the current locale, then use strtof() from libc.
*/
-int simple_str_to_float(const char* from,
- float *result,
- char** to)
+int simple_str_to_double(const char* from,
+ double *result,
+ char** to)
{
#define TMP_NUM_SIZE 100
char *start=NULL, *end=NULL, *cur=(char*)from ;
char tmp_buf[TMP_NUM_SIZE+1] ; /*hack*/
+#ifndef _WIN32_WCE
struct lconv *loc_data = localeconv () ;
+#endif
int i=0 ;
/*sanity checks*/
@@ -335,12 +441,13 @@ int simple_str_to_float(const char* from,
return 1 ;
}
memset(tmp_buf, 0, TMP_NUM_SIZE+1) ;
- i=0 ;
+
/*
* copy the float number string into tmp_buf, and take
* care to have the (optional) decimal separator be the one
* of the current locale.
*/
+#ifndef _WIN32_WCE
for (i=0 ; i < end - from ;++i) {
if (start[i] == '.'
&& loc_data
@@ -353,6 +460,9 @@ int simple_str_to_float(const char* from,
tmp_buf[i] = start[i] ;
}
}
+#else
+ GetNumberFormat(LOCALE_SYSTEM_DEFAULT,0,start, NULL, tmp_buf,TMP_NUM_SIZE);
+#endif
if (to)
*to = end ;
*result = atof(tmp_buf) ;
@@ -388,7 +498,7 @@ icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char*
case ICAL_BINARY_VALUE:
{
icalattach *attach;
- attach = icalattach_new_from_data ((unsigned char*)str, 0, 0);
+ attach = icalattach_new_from_data (str, 0, 0);
if ( !attach )
break;
value = icalvalue_new_attach (attach);
@@ -495,7 +605,7 @@ icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char*
char *cur=NULL ;
struct icalgeotype geo = {0.0, 0.0};
- if (simple_str_to_float (str, &geo.lat, &cur)) {
+ if (simple_str_to_double (str, &geo.lat, &cur)) {
goto geo_parsing_error ;
}
@@ -518,7 +628,7 @@ icalvalue* icalvalue_new_from_string_with_error(icalvalue_kind kind,const char*
++cur ;
}
- if (simple_str_to_float (cur, &geo.lon, &cur)) {
+ if (simple_str_to_double (cur, &geo.lon, &cur)) {
goto geo_parsing_error ;
}
value = icalvalue_new_geo (geo) ;
@@ -706,6 +816,7 @@ icalvalue_free (icalvalue* v)
case ICAL_TEXT_VALUE:
case ICAL_CALADDRESS_VALUE:
case ICAL_URI_VALUE:
+ case ICAL_STRING_VALUE:
case ICAL_QUERY_VALUE:
{
if (v->data.v_string != 0) {
@@ -766,9 +877,10 @@ static char* icalvalue_binary_as_ical_string_r(const icalvalue* value) {
static char* icalvalue_int_as_ical_string_r(const icalvalue* value) {
int data;
- char* str = (char*)icalmemory_new_buffer(MAX_INT_DIGITS);
+ char* str;
icalerror_check_arg_rz( (value!=0),"value");
+ str = (char*)icalmemory_new_buffer(MAX_INT_DIGITS);
data = icalvalue_get_integer(value);
@@ -782,10 +894,11 @@ static char* icalvalue_utcoffset_as_ical_string_r(const icalvalue* value)
{
int data,h,m,s;
char sign;
- char* str = (char*)icalmemory_new_buffer(9);
+ char* str;
icalerror_check_arg_rz( (value!=0),"value");
+ str = (char*)icalmemory_new_buffer(9);
data = icalvalue_get_utcoffset(value);
if (abs(data) == data){
@@ -827,81 +940,8 @@ static char* icalvalue_recur_as_ical_string_r(const icalvalue* value)
return icalrecurrencetype_as_string_r(recur);
}
- /* @todo This is not RFC2445 compliant.
- * The RFC only allows:
- * TSAFE-CHAR = %x20-21 / %x23-2B / %x2D-39 / %x3C-5B / %x5D-7E / NON-US-ASCII
- * As such, \t\r\b\f are not allowed, not even escaped
- */
-
static char* icalvalue_text_as_ical_string_r(const icalvalue* value) {
- char *str;
- char *str_p;
- const char *p;
- size_t buf_sz;
-
- buf_sz = strlen(value->data.v_string)+1;
-
- str_p = str = (char*)icalmemory_new_buffer(buf_sz);
-
- if (str_p == 0){
- return 0;
- }
-
- for(p=value->data.v_string; *p!=0; p++){
-
- switch(*p){
- case '\n': {
- icalmemory_append_string(&str,&str_p,&buf_sz,"\\n");
- break;
- }
-
- case '\t': {
- icalmemory_append_string(&str,&str_p,&buf_sz,"\\t");
- break;
- }
- case '\r': {
- icalmemory_append_string(&str,&str_p,&buf_sz,"\\r");
- break;
- }
- case '\b': {
- icalmemory_append_string(&str,&str_p,&buf_sz,"\\b");
- break;
- }
- case '\f': {
- icalmemory_append_string(&str,&str_p,&buf_sz,"\\f");
- break;
- }
-
- case ';':
- case ',':
- case '"':
- case '\\':{
- icalmemory_append_char(&str,&str_p,&buf_sz,'\\');
- icalmemory_append_char(&str,&str_p,&buf_sz,*p);
- break;
- }
-
- default: {
- icalmemory_append_char(&str,&str_p,&buf_sz,*p);
- }
- }
- }
-
- /* Assume the last character is not a '\0' and add one. We could
- check *str_p != 0, but that would be an uninitialized memory
- read. */
-
-
- icalmemory_append_char(&str,&str_p,&buf_sz,'\0');
- return str;
-}
-
-
-static char* icalvalue_text_as_ical_string(const icalvalue* value) {
- char *buf;
- buf = icalvalue_text_as_ical_string_r(value);
- icalmemory_add_tmp_buffer(buf);
- return buf;
+ return icalmemory_strdup_and_quote(value, value->data.v_string);
}
@@ -1035,13 +1075,24 @@ static char* icalvalue_float_as_ical_string_r(const icalvalue* value) {
float data;
char* str;
+ char* old_locale;
icalerror_check_arg_rz( (value!=0),"value");
data = icalvalue_get_float(value);
+ /* bypass current locale in order to make
+ sure snprintf uses a '.' as a separator
+ set locate to 'C' and keep old locale */
+ old_locale = strdup (setlocale (LC_NUMERIC,NULL));
+ setlocale (LC_NUMERIC,"C");
+
str = (char*)icalmemory_new_buffer(40);
snprintf(str,40,"%f",data);
+ /* restore saved locale */
+ setlocale (LC_NUMERIC,old_locale);
+ free (old_locale);
+
return str;
}
@@ -1050,14 +1101,25 @@ static char* icalvalue_geo_as_ical_string_r(const icalvalue* value) {
struct icalgeotype data;
char* str;
+ char* old_locale;
icalerror_check_arg_rz( (value!=0),"value");
data = icalvalue_get_geo(value);
+ /* bypass current locale in order to make
+ * sure snprintf uses a '.' as a separator
+ * set locate to 'C' and keep old locale */
+ old_locale = strdup (setlocale (LC_NUMERIC,NULL));
+ setlocale (LC_NUMERIC,"C");
+
str = (char*)icalmemory_new_buffer(80);
snprintf(str,80,"%f;%f",data.lat,data.lon);
+ /* restore saved locale */
+ setlocale (LC_NUMERIC,old_locale);
+ free (old_locale);
+
return str;
}
@@ -1186,7 +1248,7 @@ icalvalue_as_ical_string_r(const icalvalue* value)
case ICAL_X_VALUE:
if (value->x_value != 0)
- return icalmemory_strdup(value->x_value);
+ return icalmemory_strdup_and_quote(value,value->x_value);
/* FALLTHRU */