summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Murchison <murch@andrew.cmu.edu>2016-12-23 08:19:37 -0500
committerKen Murchison <murch@andrew.cmu.edu>2016-12-23 08:19:37 -0500
commitc63af68b33accf16a5bd8ffc8464d80fe4338c60 (patch)
tree163b91088a36d85c3ceb69880e2ad20731a2258f
parent4433081ef4e946c4ff5cf58cde13adc3f40d1afb (diff)
downloadlibical-git-c63af68b33accf16a5bd8ffc8464d80fe4338c60.tar.gz
RFC6868 parameter value en/decoding
-rw-r--r--src/libical/icalparameter.c100
-rw-r--r--src/libical/icalparser.c32
2 files changed, 118 insertions, 14 deletions
diff --git a/src/libical/icalparameter.c b/src/libical/icalparameter.c
index 5dab4951..d1227bd2 100644
--- a/src/libical/icalparameter.c
+++ b/src/libical/icalparameter.c
@@ -174,13 +174,95 @@ char *icalparameter_as_ical_string(icalparameter *param)
}
/**
- * Return a string representation of the parameter according to RFC5445.
+ * checks whether this character is allowed in a (Q)SAFE-CHAR
+ *
+ * QSAFE-CHAR = WSP / %x21 / %x23-7E / NON-US-ASCII
+ * ; any character except CTLs and DQUOTE
+ * SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E / NON-US-ASCII
+ * ; any character except CTLs, DQUOTE. ";", ":", ","
+ * WSP = SPACE / HTAB
+ * NON-US-ASCII = %x80-F8
+ * ; Use restricted by charset parameter
+ * ; on outer MIME object (UTF-8 preferred)
+ */
+static int icalparameter_is_safe_char(unsigned char character, int quoted)
+{
+ if (character == ' ' || character == '\t' || character == '!' ||
+ (character >= 0x80 && character <= 0xF8)) {
+ return 1;
+ }
+
+ if (quoted && character >= 0x23 && character <= 0x7e) {
+ return 1;
+ }
+ else if (!quoted &&
+ ((character >= 0x23 && character <= 0x2b) ||
+ (character >= 0x2d && character <= 0x39) ||
+ (character >= 0x3c && character <= 0x7e))) {
+ return 1;
+ }
+
+ return 0;
+}
+
+ /**
+ * Appends the parameter value to the buffer, encoding per RFC 6868
+ * and filtering out those characters not permitted by the specifications
+ *
+ * paramtext = *SAFE-CHAR
+ * quoted-string= DQUOTE *QSAFE-CHAR DQUOTE
+ */
+static void icalparameter_append_encoded_value(char **buf, char **buf_ptr,
+ size_t *buf_size, const char *value)
+{
+ int qm = 0;
+ const char *p;
+
+ /* Encapsulate the property in quotes if necessary */
+ if (strpbrk(value, ";:,") != 0) {
+ icalmemory_append_char(buf, buf_ptr, buf_size, '"');
+ qm = 1;
+ }
+
+ /* Copy the parameter value */
+ for (p = value; *p; p++) {
+ if (icalparameter_is_safe_char(*p, qm)) {
+ icalmemory_append_char(buf, buf_ptr, buf_size, *p);
+ } else {
+ /* Encode unsafe characters per RFC6868, otherwise replace with SP */
+ switch (*p) {
+ case '\n':
+ icalmemory_append_string(buf, buf_ptr, buf_size, "^n");
+ break;
+
+ case '^':
+ icalmemory_append_string(buf, buf_ptr, buf_size, "^^");
+ break;
+
+ case '"':
+ icalmemory_append_string(buf, buf_ptr, buf_size, "^'");
+ break;
+
+ default:
+ icalmemory_append_char(buf, buf_ptr, buf_size, ' ');
+ break;
+ }
+ }
+ }
+
+ if (qm == 1) {
+ icalmemory_append_char(buf, buf_ptr, buf_size, '"');
+ }
+}
+
+/**
+ * Return a string representation of the parameter according to RFC5445/RFC6868.
*
* param = param-name "=" param-value
* param-name = iana-token / x-token
* param-value = paramtext /quoted-string
- * paramtext = *SAFE-SHARE
- * quoted-string= DQUOTE *QSAFE-CHARE DQUOTE
+ * paramtext = *SAFE-CHAR
+ * quoted-string= DQUOTE *QSAFE-CHAR DQUOTE
* QSAFE-CHAR = any character except CTLs and DQUOTE
* SAFE-CHAR = any character except CTLs, DQUOTE. ";", ":", ","
*/
@@ -222,17 +304,7 @@ char *icalparameter_as_ical_string_r(icalparameter *param)
icalmemory_append_string(&buf, &buf_ptr, &buf_size, "=");
if (param->string != 0) {
- int qm = 0;
-
- /* Encapsulate the property in quotes if necessary */
- if (strpbrk(param->string, ";:,") != 0) {
- icalmemory_append_char(&buf, &buf_ptr, &buf_size, '"');
- qm = 1;
- }
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, param->string);
- if (qm == 1) {
- icalmemory_append_char(&buf, &buf_ptr, &buf_size, '"');
- }
+ icalparameter_append_encoded_value(&buf, &buf_ptr, &buf_size, param->string);
} else if (param->data != 0) {
const char *str = icalparameter_enum_to_string(param->data);
diff --git a/src/libical/icalparser.c b/src/libical/icalparser.c
index f9593489..4c337df9 100644
--- a/src/libical/icalparser.c
+++ b/src/libical/icalparser.c
@@ -210,6 +210,34 @@ static char *parser_get_prop_name(char *line, char **end)
return str;
}
+/* Decode parameter value per RFC6868 */
+static void parser_decode_param_value(char *value)
+{
+ char *in, *out;
+
+ for (in = out = value; *in; in++, out++) {
+ if (*in == '^' && strspn(in+1, "n^'")) {
+ switch (*++in) {
+ case 'n':
+ *out = '\n';
+ break;
+
+ case '^':
+ *out = '^';
+ break;
+
+ case '\'':
+ *out = '"';
+ break;
+ }
+ } else {
+ *out = *in;
+ }
+ }
+
+ while (*out) *out++ = '\0';
+}
+
static int parser_get_param_name_stack(char *line, char *name, size_t name_length,
char *value, size_t value_length)
{
@@ -255,6 +283,8 @@ static int parser_get_param_name_stack(char *line, char *name, size_t name_lengt
strncpy(value, next, requested_value_length);
value[requested_value_length] = 0;
+ parser_decode_param_value(value);
+
return 1;
}
@@ -289,6 +319,8 @@ static char *parser_get_param_name_heap(char *line, char **end)
*end = make_segment(*end, *end + strlen(*end));
}
+ parser_decode_param_value(*end);
+
return str;
}