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);
}
;
signature.asc
Description: This is a digitally signed message part
_______________________________________________ devel mailing list [email protected] http://mailman.openchange.org/listinfo/devel
