Attached, the previous patch but with PT_MV_STRING8 support in the write
API (including escape/unescape).

Btw, I forgot to mention in my previous email that I had increased
buf[1024] to buf[0x4000]. This is a nasty hack which assumes a MAPI
property can't handle more than a 0x4000 buffer unless it opens a
stream. (assumption made on past experiences/tests).

Cheers,
Julien.

On Mon, 2008-03-31 at 17:47 +0200, Julien Kerihuel wrote:
> On Sat, 2008-03-29 at 15:39 +0100, Julien Kerihuel wrote:
> 
> > I'll be polishing the API this afternoon + write the doxygen
> > documentation + add a preview backup option for a single message in
> > openchangeclient for further tests.
> > 
> > Commit expected tonight.
> 
> The initial libocpf write API has been pushed on the repository during
> the week-end. It sounds to work properly with most of messages (for the
> few properties we support) but libocpf fails to be generated valid ocpf
> files if double quotes are included within strings (example:
> PR_TRANSPORT_MESSAGE_HEADERS)
> 
> The attached patch adds escape/unescape strings support for '\' and '"'
> characters:
>         - escapes them in the ocpf_write API: when it dumps MAPI message
>         to OCPF file
>         - (un)escapes them when it sends the message on the server
> 
> For example, the following subject:
>         \"test\"       "test2"       \\"test3\\"        \\\test4\\\
> 
> Will be written in OCPF:
>         "\\\"test\\\"       \"test2\"       \\\\\"test3\\\\\"        \\\
>         \\\test4\\\\\\"
> 
> Brad, can you let me know if the given patch fixes ocpf file generation
> for you? (ocpf-dump, ocpf-syntax and ocpf-send)
> 
> The escape\unescape routines and lex way to handle this is IMO a bit
> lame, but it sounds to do the job properly so far. I'll be working on
> adding PT_MV_STRING8 support to libocpf write API while waiting for an
> update status.
> 
> Cheers,
> Julien.
> 
> _______________________________________________
> devel mailing list
> [email protected]
> http://mailman.openchange.org/listinfo/devel
-- 
Julien Kerihuel
[EMAIL PROTECTED]
OpenChange Project Manager

GPG Fingerprint: 0B55 783D A781 6329 108A  B609 7EF6 FE11 A35F 1F79

Property changes on: libocpf
___________________________________________________________________
Name: svn:ignore
   - *.po
ocpf.tab.[ch]
lex.yy.c
proto_private.h
proto.h

   + *.po
ocpf.tab.[ch]
lex.yy.c
proto_private.h
proto.h
Doxyfile


Index: libocpf/ocpf_api.c
===================================================================
--- libocpf/ocpf_api.c	(revision 380)
+++ libocpf/ocpf_api.c	(working copy)
@@ -52,7 +52,7 @@
 }
 
 
-int ocpf_propvalue_var(const char *propname, uint32_t proptag, const char *variable)
+int ocpf_propvalue_var(const char *propname, uint32_t proptag, const char *variable, bool unescape)
 {
 	struct ocpf_var		*vel;
 	struct ocpf_property	*element;
@@ -79,7 +79,12 @@
 			element = NULL;
 			element = talloc_zero(ocpf->mem_ctx, struct ocpf_property);
 			element->aulPropTag = aulPropTag;
-			element->value = vel->value;
+			if (unescape && (((aulPropTag & 0xFFFF) == PT_STRING8) || 
+					 ((aulPropTag & 0xFFFF) == PT_UNICODE))) {
+				element->value = ocpf_write_unescape_string(vel->value);
+			} else {
+				element->value = vel->value;
+			}
 			DLIST_ADD(ocpf->props, element);
 			return OCPF_SUCCESS;
 		}
@@ -90,16 +95,30 @@
 
 
 int ocpf_set_propvalue(TALLOC_CTX *mem_ctx, const void **value, uint16_t proptype, uint16_t sproptype, 
-		       union SPropValue_CTR lpProp)
+		       union SPropValue_CTR lpProp, bool unescape)
 {
+	char	*str = NULL;
+
 	OCPF_RETVAL_IF(proptype != sproptype, OCPF_WARN_PROPVALUE_MISMATCH, NULL);
 
 	switch (proptype) {
 	case PT_STRING8:
-		*value = talloc_memdup(mem_ctx, (const void *)lpProp.lpszA, strlen(lpProp.lpszA) + 1);
+		if (unescape) {
+			str = ocpf_write_unescape_string(lpProp.lpszA);
+		} else {
+			str = talloc_strdup(ocpf->mem_ctx, lpProp.lpszA);
+		}
+		*value = talloc_memdup(mem_ctx, str, strlen(str) + 1);
+		talloc_free(str);
 		return OCPF_SUCCESS;
 	case PT_UNICODE:
-		*value = talloc_memdup(mem_ctx, (const void *)lpProp.lpszW, strlen(lpProp.lpszW) + 1);
+		if (unescape) {
+			str = ocpf_write_unescape_string(lpProp.lpszW);
+		} else {
+			str = talloc_strdup(ocpf->mem_ctx, lpProp.lpszW);
+		}
+		*value = talloc_memdup(mem_ctx, str, strlen(str) + 1);
+		talloc_free(str);
 		return OCPF_SUCCESS;
 	case PT_SHORT:
 		*value = talloc_memdup(mem_ctx, (const void *)&lpProp.i, sizeof (uint16_t));
@@ -133,7 +152,13 @@
 
 			for (i = 0; i < lpProp.MVszA.cValues; i++) {
 				((struct SLPSTRArray *)*value)->strings[i] = talloc_zero(mem_ctx, struct LPSTR);
-				((struct SLPSTRArray *)*value)->strings[i]->lppszA = talloc_strdup(mem_ctx, lpProp.MVszA.strings[i]->lppszA);
+				if (unescape) {
+					str = ocpf_write_unescape_string(lpProp.MVszA.strings[i]->lppszA);
+				} else {
+					str = (char *)lpProp.MVszA.strings[i]->lppszA;
+				}
+				((struct SLPSTRArray *)*value)->strings[i]->lppszA = talloc_strdup(mem_ctx, str);
+				talloc_free(str);
 			}
 		}
 		return OCPF_SUCCESS;
@@ -160,7 +185,8 @@
 	return OCPF_SUCCESS;
 }
 
-int ocpf_propvalue(uint32_t aulPropTag, const char *propname, union SPropValue_CTR lpProp, uint16_t proptype)
+int ocpf_propvalue(uint32_t aulPropTag, const char *propname, union SPropValue_CTR lpProp, 
+		   uint16_t proptype, bool unescape)
 {
 	struct ocpf_property	*element;
 	int			ret;
@@ -175,7 +201,7 @@
 	element = NULL;
 	element = talloc_zero(ocpf->mem_ctx, struct ocpf_property);
 	element->aulPropTag = aulPropTag;
-	ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, (uint16_t)aulPropTag & 0xFFFF, proptype, lpProp);
+	ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, (uint16_t)aulPropTag & 0xFFFF, proptype, lpProp, unescape);
 	if (ret == -1) {
 		talloc_free(element);
 		return OCPF_ERROR;
@@ -186,12 +212,12 @@
 }
 
 
-void ocpf_propvalue_s(const char *propname, union SPropValue_CTR lpProp, uint16_t proptype)
+void ocpf_propvalue_s(const char *propname, union SPropValue_CTR lpProp, uint16_t proptype, bool unescape)
 {
 	uint32_t	aulPropTag;
 
 	aulPropTag = get_proptag_value(propname);
-	ocpf_propvalue(aulPropTag, propname, lpProp, proptype);
+	ocpf_propvalue(aulPropTag, propname, lpProp, proptype, unescape);
 }
 
 
@@ -206,11 +232,12 @@
    \param lpProp named property value
    \param var_name variable name
    \param proptype variable property type
+   \param unescape whether the property value should be escaped
 
    \return OCPF_SUCCESS on success, otherwise OCPF_ERROR.
  */
 int ocpf_nproperty_add(struct ocpf_nprop *nprop, union SPropValue_CTR lpProp,
-		       const char *var_name, uint16_t proptype)
+		       const char *var_name, uint16_t proptype, bool unescape)
 {
 	enum MAPISTATUS		retval;
 	int			ret = 0;
@@ -295,7 +322,7 @@
 		}
 		OCPF_RETVAL_IF(!element->value, OCPF_WARN_VAR_NOT_REGISTERED, element);
 	} else {
-		ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, element->propType, proptype, lpProp);
+		ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, element->propType, proptype, lpProp, unescape);
 		if (ret == -1) {
 			talloc_free(element);
 			return OCPF_ERROR;
@@ -490,7 +517,7 @@
 }
 
 
-int ocpf_variable_add(const char *name, union SPropValue_CTR lpProp, uint16_t propType)
+int ocpf_variable_add(const char *name, union SPropValue_CTR lpProp, uint16_t propType, bool unescape)
 {
 	struct ocpf_var		*element;
 	int			ret;
@@ -508,7 +535,7 @@
 	element->name = talloc_strdup((TALLOC_CTX *)element, name);
 	element->propType = propType;
 
-	ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, propType, propType, lpProp);
+	ret = ocpf_set_propvalue((TALLOC_CTX *)element, &element->value, propType, propType, lpProp, unescape);
 	OCPF_RETVAL_IF(ret == -1, OCPF_WARN_VAR_TYPE, element);
 
 	DLIST_ADD(ocpf->vars, element);
Index: libocpf/lex.l
===================================================================
--- libocpf/lex.l	(revision 380)
+++ libocpf/lex.l	(working copy)
@@ -114,8 +114,8 @@
 			}
 "\""			{ 
 			    int start_lineno = lineno;
-			    int c;
-			    char buf[1024];
+			    int c, c2;
+			    char buf[0x4000];
 			    char *p = buf;
 			    int f = 0;
 			    int skip_ws = 0;
@@ -127,18 +127,30 @@
 				    continue;
 				}
 				skip_ws = 0;
-				
+
+				if (c == '\\') {
+					c2 = c;
+					c = input();
+					if (c == '"') { 
+						*p++ = c;
+						c = input();
+					} else {
+						*p++ = c2;
+					}
+				}
+
 				if(c == '"') {
-				    if(f) {
-					*p++ = '"';
-					f = 0;
-				    } else
-					f = 1;
-				    continue;
+					if(f) {
+						*p++ = '"';
+						f = 0;
+					} else {
+						f = 1;
+					}
+					continue;
 				}
 				if(f == 1) {
-				    unput(c);
-				    break;
+					unput(c);
+					break;
 				}
 				if(c == '\n') {
 				    lineno++;
Index: libocpf/ocpf_write.c
===================================================================
--- libocpf/ocpf_write.c	(revision 380)
+++ libocpf/ocpf_write.c	(working copy)
@@ -168,17 +168,124 @@
 	return line;
 }
 
+static char *ocpf_write_escape_string(const char *value)
+{
+	char	*str = NULL;
+	char	*stmp = NULL;
+	int	value_len;
+	int	len = 0;
+	int	tmp = 0;
+
+	value_len = strlen(value);
+	tmp = strcspn(value, "\\\"");
+
+	if (tmp == value_len) {
+		str = talloc_strdup(ocpf->mem_ctx, value);
+		return str;
+	} else {
+		str = talloc_strndup(ocpf->mem_ctx, value, tmp);
+		str = talloc_asprintf_append_buffer(str, "\\\%c", value[tmp]);
+	}
+	len += tmp + 1;
+
+	while (len < value_len) {
+		tmp = strcspn(value + len, "\\\"");
+		
+		if ((tmp + len) == value_len) {
+			str = talloc_asprintf_append_buffer(str, "%s", value + len);
+			break;
+		} else {
+			stmp = talloc_strndup(ocpf->mem_ctx, value + len, tmp);
+			str = talloc_asprintf_append_buffer(str, "%s\\\%c", stmp, value[len + tmp]);
+			talloc_free(stmp);
+			len += tmp + 1;
+		}
+	}
+
+	return str;
+}
+
+char *ocpf_write_unescape_string(const char *value)
+{
+	char	*str = NULL;
+	char	*stmp = NULL;
+	int	value_len;
+	int	len = 0;
+	int	tmp = 0;
+
+	value_len = strlen(value);
+	tmp = strcspn(value, "\\");
+
+	if (tmp == value_len) {
+		str = talloc_strdup(ocpf->mem_ctx, value);
+		return str;
+	}
+	
+	str = talloc_strndup(ocpf->mem_ctx, value, tmp + 1);
+	if (value[tmp + 1] && value[tmp + 1] == '\\') {
+		len += tmp + 2;
+	} else {
+		len += tmp + 1;
+	}
+
+	while (len < value_len) {
+		tmp = strcspn(value + len, "\\");
+		
+		if ((tmp + len) == value_len) {
+			str = talloc_asprintf_append(str, "%s", value + len);
+			break;
+		}
+			
+		stmp = talloc_strndup(ocpf->mem_ctx, value + len, tmp + 1);
+		str = talloc_asprintf_append(str, stmp);
+		if (value[len + tmp + 1] && 
+		    (value[len + tmp + 1] == '\\' || value[len + tmp + 1] == '"')) {
+			len += tmp + 2;
+		} else {
+			len += tmp + 1;
+		}
+		talloc_free(stmp);
+	}
+
+	return str;
+}
+
+static char *ocpf_write_mv_string8(const struct SLPSTRArray *value)
+{
+	char		*str = NULL;
+	char		*tmp = NULL;
+	uint32_t	i;
+
+	str = talloc_asprintf(ocpf->mem_ctx, "{ ");
+	for (i = 0; i < value->cValues; i++) {
+		tmp = ocpf_write_escape_string((const char *)value->strings[i]->lppszA);
+		if (i != value->cValues - 1) {
+			str = talloc_asprintf_append_buffer(str, "\"%s\", ", tmp);
+		} else {
+			str = talloc_asprintf_append_buffer(str, "\"%s\" }", tmp);
+		}
+		talloc_free(tmp);
+	}
+
+	return str;
+}
+
 static char *ocpf_write_property(bool *found, uint32_t ulPropTag, const void *value)
 {
 	char	*line = NULL;
+	char	*str = NULL;
 
 	switch (ulPropTag & 0xFFFF) {
 	case PT_STRING8:
-		line = talloc_asprintf(ocpf->mem_ctx, "\"%s\"\n", (const char *)value);
+		str = ocpf_write_escape_string((const char *)value);
+		line = talloc_asprintf(ocpf->mem_ctx, "\"%s\"\n", str);
+		talloc_free(str);
 		*found = true;
 		break;
 	case PT_UNICODE:
-		line = talloc_asprintf(ocpf->mem_ctx, "U\"%s\"\n", (const char *)value);
+		str = ocpf_write_escape_string((const char *)value);
+		line = talloc_asprintf(ocpf->mem_ctx, "U\"%s\"\n", str);
+		talloc_free(str);
 		*found = true;
 		break;
 	case PT_SHORT:
@@ -205,6 +312,10 @@
 		line = ocpf_write_binary((const struct SBinary *)value);
 		*found = true;
 		break;
+	case PT_MV_STRING8:
+		line = ocpf_write_mv_string8((const struct SLPSTRArray *)value);
+		*found = true;
+		break;
 	}
 
 	return line;
@@ -279,16 +390,16 @@
 	for (i = 0; i < mapi_lpProps->cValues; i++) {
 		propID = mapi_lpProps->lpProps[i].ulPropTag >> 16;
 		cast_SPropValue(&mapi_lpProps->lpProps[i], &lpProps);
-
+		
 		if (propID < 0x8000) {
 			/* HACK: replace PR_CONVERSATION_TOPIC with PR_SUBJECT */
 			if (lpProps.ulPropTag == PR_CONVERSATION_TOPIC) {
 				lpProps.ulPropTag = PR_SUBJECT;
-				ocpf_propvalue(lpProps.ulPropTag, NULL, lpProps.value, lpProps.ulPropTag & 0xFFFF);
+				ocpf_propvalue(lpProps.ulPropTag, NULL, lpProps.value, lpProps.ulPropTag & 0xFFFF, false);
 				cast_SPropValue(&mapi_lpProps->lpProps[i], &lpProps);
 			}
 			ocpf_propvalue(mapi_lpProps->lpProps[i].ulPropTag, NULL, 
-				       lpProps.value, mapi_lpProps->lpProps[i].ulPropTag & 0xFFFF);
+				       lpProps.value, mapi_lpProps->lpProps[i].ulPropTag & 0xFFFF, false);
 		} else {
 			nameid = talloc_zero(ocpf->mem_ctx, struct MAPINAMEID);
 			retval = GetNamesFromIDs(obj_message, ((lpProps.ulPropTag & 0xFFFF0000) | PT_NULL),
@@ -311,7 +422,7 @@
 				ocpf_oleguid_add(nprop.guid, tmp_guid);
 			
 			nprop.registered = false;
-			ocpf_nproperty_add(&nprop, lpProps.value, NULL, nprop.propType);
+			ocpf_nproperty_add(&nprop, lpProps.value, NULL, nprop.propType, false);
 
 			talloc_free(nameid);
 		}
Index: libocpf/ocpf.y
===================================================================
--- libocpf/ocpf.y	(revision 380)
+++ libocpf/ocpf.y	(working copy)
@@ -163,7 +163,7 @@
 Set		:
 		kw_SET VAR EQUAL propvalue
 		{
-			ocpf_variable_add($2, lpProp, type);
+			ocpf_variable_add($2, lpProp, type, true);
 			memset(&lpProp, 0, sizeof (union SPropValue_CTR));
 		}
 		;
@@ -182,21 +182,21 @@
 content		:
 		IDENTIFIER EQUAL propvalue
 		{
-			ocpf_propvalue_s($1, lpProp, type);
+		  ocpf_propvalue_s($1, lpProp, type, true);
 			ocpf_propvalue_free(lpProp, type);
 		}
 		| INTEGER EQUAL propvalue
 		{
-			ocpf_propvalue($1, "UNNAMED", lpProp, type);
+			ocpf_propvalue($1, "UNNAMED", lpProp, type, true);
 			ocpf_propvalue_free(lpProp, type);
 		}
 		| IDENTIFIER EQUAL VAR
 		{
-			ocpf_propvalue_var($1, 0x0, $3);
+			ocpf_propvalue_var($1, 0x0, $3, true);
 		}
 		| INTEGER EQUAL VAR
 		{
-			ocpf_propvalue_var(NULL, $1, $3);
+			ocpf_propvalue_var(NULL, $1, $3, true);
 		}
 		;
 
@@ -309,19 +309,19 @@
 
 ncontent	: kind EQUAL propvalue
 		{
-			ocpf_nproperty_add(&nprop, lpProp, NULL, type);
+			ocpf_nproperty_add(&nprop, lpProp, NULL, type, true);
 		}
 		| known_kind EQUAL propvalue
 		{
-			ocpf_nproperty_add(&nprop, lpProp, NULL, type);
+			ocpf_nproperty_add(&nprop, lpProp, NULL, type, true);
 		}
 		| kind EQUAL VAR
 		{
-			ocpf_nproperty_add(&nprop, lpProp, $3, type);
+			ocpf_nproperty_add(&nprop, lpProp, $3, type, true);
 		}
 		| known_kind EQUAL VAR
 		{
-			ocpf_nproperty_add(&nprop, lpProp, $3, type);
+			ocpf_nproperty_add(&nprop, lpProp, $3, type, true);
 		}
 		;
 

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
devel mailing list
[email protected]
http://mailman.openchange.org/listinfo/devel

Reply via email to