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.
--
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));
@@ -160,7 +179,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 +195,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 +206,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 +226,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 +316,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 +511,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 +529,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,105 @@
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_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:
@@ -279,16 +367,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 +399,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);
}
;
signature.asc
Description: This is a digitally signed message part
_______________________________________________ devel mailing list [email protected] http://mailman.openchange.org/listinfo/devel
