[evolution-mapi] Include and use fixed OpenChange's fxparser



commit dd28e4bde0551336e5d06e9b330990dc8cc84a6b
Author: Milan Crha <mcrha redhat com>
Date:   Mon Oct 31 13:11:06 2011 +0100

    Include and use fixed OpenChange's fxparser

 src/libexchangemapi/e-mapi-fast-transfer.c |   16 +-
 src/libexchangemapi/e-mapi-fast-transfer.h |    1 +
 src/libexchangemapi/e-mapi-openchange.c    |  665 ++++++++++++++++++++++++++++
 src/libexchangemapi/e-mapi-openchange.h    |   13 +
 4 files changed, 688 insertions(+), 7 deletions(-)
---
diff --git a/src/libexchangemapi/e-mapi-fast-transfer.c b/src/libexchangemapi/e-mapi-fast-transfer.c
index c5e942e..1ae3feb 100644
--- a/src/libexchangemapi/e-mapi-fast-transfer.c
+++ b/src/libexchangemapi/e-mapi-fast-transfer.c
@@ -422,7 +422,7 @@ e_mapi_fast_transfer_internal (EMapiConnection *conn,
 	enum MAPISTATUS ms;
 	enum TransferStatus transferStatus;
 	uint16_t stepCount = -1, totalCount = -1;
-	struct fx_parser_context *parser;
+	struct e_mapi_fx_parser_context *parser;
 	EMapiFXParserClosure data = { 0 };
 
 	data.conn = conn;
@@ -448,11 +448,11 @@ e_mapi_fast_transfer_internal (EMapiConnection *conn,
 		data.marker = PidTagStartMessage;
 	}
 		
-	parser = fxparser_init (data.mem_ctx, &data);
-	fxparser_set_marker_callback (parser, parse_marker_cb);
-	fxparser_set_delprop_callback (parser, parse_delprop_cb);
-	fxparser_set_namedprop_callback (parser, parse_namedprop_cb);
-	fxparser_set_property_callback (parser, parse_property_cb);
+	parser = e_mapi_fxparser_init (data.mem_ctx, &data);
+	e_mapi_fxparser_set_marker_callback (parser, parse_marker_cb);
+	e_mapi_fxparser_set_delprop_callback (parser, parse_delprop_cb);
+	e_mapi_fxparser_set_namedprop_callback (parser, parse_namedprop_cb);
+	e_mapi_fxparser_set_property_callback (parser, parse_property_cb);
 
 	do {
 		DATA_BLOB transferdata;
@@ -461,7 +461,9 @@ e_mapi_fast_transfer_internal (EMapiConnection *conn,
 		if (ms != MAPI_E_SUCCESS)
 			break;
 
-		fxparser_parse (parser, &transferdata);
+		ms = e_mapi_fxparser_parse (parser, &transferdata);
+		if (ms != MAPI_E_SUCCESS)
+			break;
 	} while ((transferStatus == TransferStatus_Partial) || (transferStatus == TransferStatus_NoRoom));
 
 	if (data.object) {
diff --git a/src/libexchangemapi/e-mapi-fast-transfer.h b/src/libexchangemapi/e-mapi-fast-transfer.h
index fba1822..f409f6f 100644
--- a/src/libexchangemapi/e-mapi-fast-transfer.h
+++ b/src/libexchangemapi/e-mapi-fast-transfer.h
@@ -40,6 +40,7 @@ typedef struct _EMapiObject EMapiObject;
 typedef struct _EMapiRecipient EMapiRecipient;
 typedef struct _EMapiAttachment EMapiAttachment;
 
+/* returns whether continue in transfer of the next object */
 typedef gboolean	(*EMapiFastTransferCB)		(EMapiConnection *conn,
 							 TALLOC_CTX *mem_ctx,
 							 /* const */ EMapiObject *object,
diff --git a/src/libexchangemapi/e-mapi-openchange.c b/src/libexchangemapi/e-mapi-openchange.c
index ae0abe2..de7049c 100644
--- a/src/libexchangemapi/e-mapi-openchange.c
+++ b/src/libexchangemapi/e-mapi-openchange.c
@@ -664,3 +664,668 @@ e_mapi_nameid_string_lookup_canonical(const char *Name, const char *OLEGUID, uin
 
 	OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, NULL);
 }
+
+enum e_mapi_fx_parser_state { ParserState_Entry, ParserState_HaveTag, ParserState_HavePropTag };
+
+struct e_mapi_fx_parser_context {
+	TALLOC_CTX		*mem_ctx;
+	DATA_BLOB		data;	/* the data we have (so far) to parse */
+	uint32_t		idx;	/* where we are up to in the data blob */
+	enum e_mapi_fx_parser_state	state;
+	struct SPropValue	lpProp;		/* the current property tag and value we are parsing */
+	struct MAPINAMEID	namedprop;	/* the current named property we are parsing */
+	bool 			enough_data;
+	uint32_t		tag;
+	void			*priv;
+	
+	/* callbacks for parser actions */
+	enum MAPISTATUS (*op_marker)(uint32_t, void *);
+	enum MAPISTATUS (*op_delprop)(uint32_t, void *);
+	enum MAPISTATUS (*op_namedprop)(uint32_t, struct MAPINAMEID, void *);
+	enum MAPISTATUS (*op_property)(struct SPropValue, void *);
+};
+
+static bool pull_uint8_t(struct e_mapi_fx_parser_context *parser, uint8_t *val)
+{
+	if ((parser->idx) + 1 > parser->data.length) {
+		*val = 0;
+		return false;
+	}
+	*val = parser->data.data[parser->idx];
+	(parser->idx)++;
+	return true;
+}
+
+static bool pull_uint16_t(struct e_mapi_fx_parser_context *parser, uint16_t *val)
+{
+	if ((parser->idx) + 2 > parser->data.length) {
+		*val = 0;
+		return false;
+	}
+	*val = parser->data.data[parser->idx];
+	(parser->idx)++;
+	*val += parser->data.data[parser->idx] << 8;
+	(parser->idx)++;
+	return true;
+}
+
+static bool pull_uint32_t(struct e_mapi_fx_parser_context *parser, uint32_t *val)
+{
+	if ((parser->idx) + 4 > parser->data.length) {
+		*val = 0;
+		return false;
+	}
+	*val = parser->data.data[parser->idx];
+	(parser->idx)++;
+	*val += parser->data.data[parser->idx] << 8;
+	(parser->idx)++;
+	*val += parser->data.data[parser->idx] << 16;
+	(parser->idx)++;
+	*val += parser->data.data[parser->idx] << 24;
+	(parser->idx)++;
+	return true;
+}
+
+static bool pull_tag(struct e_mapi_fx_parser_context *parser)
+{
+	return pull_uint32_t(parser, &(parser->tag));
+}
+
+static bool pull_uint8_data(struct e_mapi_fx_parser_context *parser, uint32_t read_len, uint8_t **data_read)
+{
+	uint32_t i;
+	for (i = 0; i < read_len; i++) {
+		if (!pull_uint8_t(parser, (uint8_t*)&((*data_read)[i]))) {
+			return false;
+		}
+	}
+	return true;
+}
+
+static bool pull_int64_t(struct e_mapi_fx_parser_context *parser, int64_t *val)
+{
+	int64_t tmp;
+	if ((parser->idx) + 8 > parser->data.length) {
+		*val = 0;
+		return false;
+	}
+	*val = parser->data.data[parser->idx];
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 8);
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 16);
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 24);
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 32);
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 40);
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 48);
+	(parser->idx)++;
+
+	tmp = parser->data.data[parser->idx];
+	*val += (tmp << 56);
+	(parser->idx)++;
+
+	return true;
+}
+
+static bool pull_double(struct e_mapi_fx_parser_context *parser, double *val)
+{
+	return pull_int64_t(parser, (int64_t *)val);
+}
+
+static bool pull_guid(struct e_mapi_fx_parser_context *parser, struct GUID *guid)
+{
+	int i;
+
+	if ((parser->idx) + 16 > parser->data.length) {
+		GUID_all_zero(guid);
+		return false;
+	}
+	if (!pull_uint32_t(parser, &(guid->time_low)))
+		return false;
+	if (!pull_uint16_t(parser, &(guid->time_mid)))
+		return false;
+	if (!pull_uint16_t(parser, &(guid->time_hi_and_version)))
+		return false;
+	if (!pull_uint8_t(parser, &(guid->clock_seq[0])))
+		return false;
+	if (!pull_uint8_t(parser, &(guid->clock_seq[1])))
+		return false;
+	for (i = 0; i < 6; ++i) {
+		if (!pull_uint8_t(parser, &(guid->node[i])))
+			return false;
+	}
+	return true;
+}
+
+static bool pull_systime(struct e_mapi_fx_parser_context *parser, struct FILETIME *ft)
+{
+	struct FILETIME filetime = {0,0};
+
+	if (parser->idx + 8 > parser->data.length ||
+	    !pull_uint32_t(parser, &(filetime.dwLowDateTime)) ||
+	    !pull_uint32_t(parser, &(filetime.dwHighDateTime)))
+		return false;
+
+	*ft = filetime;
+
+	return true;
+}
+
+static bool pull_clsid(struct e_mapi_fx_parser_context *parser, struct FlatUID_r **pclsid)
+{
+	struct FlatUID_r *clsid;
+	int i = 0;
+
+	if (parser->idx + 16 > parser->data.length)
+		return false;
+
+	clsid = talloc_zero(parser->mem_ctx, struct FlatUID_r);
+	for (i = 0; i < 16; ++i) {
+		if (!pull_uint8_t(parser, &(clsid->ab[i])))
+			return false;
+	}
+
+	*pclsid = clsid;
+
+	return true;
+}
+
+static bool pull_string8(struct e_mapi_fx_parser_context *parser, char **pstr)
+{
+	char *str;
+	uint32_t i, length;
+
+	if (!pull_uint32_t(parser, &length) ||
+	    parser->idx + length > parser->data.length)
+		return false;
+
+	str = talloc_array(parser->mem_ctx, char, length + 1);
+	for (i = 0; i < length; i++) {
+		if (!pull_uint8_t(parser, (uint8_t*)&(str[i]))) {
+			return false;
+		}
+	}
+	str[length] = '\0';
+
+	*pstr = str;
+
+	return true;
+}
+
+static bool fetch_ucs2_data(struct e_mapi_fx_parser_context *parser, uint32_t numbytes, smb_ucs2_t **data_read)
+{
+	if ((parser->idx) + numbytes > parser->data.length) {
+		// printf("insufficient data in fetch_ucs2_data (%i requested, %zi available)\n", numbytes, (parser->data.length - parser->idx));
+		return false;
+	}
+
+	*data_read = talloc_array(parser->mem_ctx, smb_ucs2_t, numbytes/2);
+	memcpy(*data_read, &(parser->data.data[parser->idx]), numbytes);
+	parser->idx += numbytes;
+	return true;
+}
+
+static bool fetch_ucs2_nullterminated(struct e_mapi_fx_parser_context *parser, smb_ucs2_t **data_read)
+{
+	uint32_t idx_local = parser->idx;
+	bool found = false;
+	while (idx_local < parser->data.length -1) {
+		smb_ucs2_t val = 0x0000;
+		val += parser->data.data[idx_local];
+		idx_local++;
+		val += parser->data.data[idx_local] << 8;
+		idx_local++;
+		if (val == 0x0000) {
+			found = true;
+			break;
+		}
+	}
+	if (!found)
+		return false;
+	return fetch_ucs2_data(parser, idx_local-(parser->idx), data_read); 
+}
+
+static bool pull_unicode(struct e_mapi_fx_parser_context *parser, char **pstr)
+{
+	smb_ucs2_t *ucs2_data = NULL;
+	char *utf8_data = NULL;
+	size_t utf8_len;
+	uint32_t length;
+
+	if (!pull_uint32_t(parser, &length) ||
+	    parser->idx + length > parser->data.length)
+		return false;
+
+	ucs2_data = talloc_array(parser->mem_ctx, smb_ucs2_t, length/2);
+
+	if (!fetch_ucs2_data(parser, length, &ucs2_data)) {
+		return false;
+	}
+	pull_ucs2_talloc(parser->mem_ctx, &utf8_data, ucs2_data, &utf8_len);
+
+	*pstr = utf8_data;
+
+	return true;
+}
+
+static bool pull_binary(struct e_mapi_fx_parser_context *parser, struct Binary_r *bin)
+{
+	if (!pull_uint32_t(parser, &(bin->cb)) ||
+	    parser->idx + bin->cb > parser->data.length)
+		return false;
+
+	bin->lpb = talloc_array(parser->mem_ctx, uint8_t, bin->cb + 1);
+
+	return pull_uint8_data(parser, bin->cb, &(bin->lpb));
+}
+
+/*
+ pull a property value from the blob, starting at position idx
+*/
+static bool fetch_property_value(struct e_mapi_fx_parser_context *parser, DATA_BLOB *buf, struct SPropValue *prop)
+{
+	switch(prop->ulPropTag & 0xFFFF) {
+	case PT_NULL:
+	{
+		if (!pull_uint32_t(parser, &(prop->value.null)))
+			return false;
+		break; 
+	}
+	case PT_SHORT:
+	{
+		if (!pull_uint16_t(parser, &(prop->value.i)))
+			return false;
+		break;
+	}
+	case PT_LONG:
+	{
+		if (!pull_uint32_t(parser, &(prop->value.l)))
+			return false;
+		break;
+	}
+	case PT_DOUBLE:
+	{
+		if (!pull_double(parser, (double *)&(prop->value.dbl)))
+			return false;
+		break;
+	}
+	case PT_BOOLEAN:
+	{
+		if (parser->idx + 2 > parser->data.length ||
+		    !pull_uint8_t(parser, &(prop->value.b)))
+			return false;
+
+		/* special case for fast transfer, 2 bytes instead of one */
+		(parser->idx)++;
+		break;
+	}
+	case PT_I8:
+	{
+		int64_t val;
+		if (!pull_int64_t(parser, &(val)))
+			return false;
+		prop->value.d = val;
+		break;
+	}
+	case PT_STRING8:
+	{
+		char *str = NULL;
+		if (!pull_string8(parser, &str))
+			return false;
+		prop->value.lpszA = str;
+		break;
+	}
+	case PT_UNICODE:
+	{
+		char *str = NULL;
+		if (!pull_unicode (parser, &str))
+			return false;
+		prop->value.lpszW = str;
+		break;
+	}
+	case PT_SYSTIME:
+	{
+		if (!pull_systime(parser, &prop->value.ft))
+			return false;
+		break;
+	}
+	case PT_CLSID:
+	{
+		if (!pull_clsid(parser, &prop->value.lpguid))
+			return false;
+		break;
+	}
+	case PT_SVREID:
+	case PT_BINARY:
+	{
+		if (!pull_binary(parser, &prop->value.bin))
+			return false;
+		break;
+	}
+	case PT_OBJECT:
+	{
+		if (!pull_uint32_t(parser, &(prop->value.object)))
+			return false;
+		break;
+	}
+	case PT_ERROR:
+	{
+		uint32_t num;
+		if (!pull_uint32_t(parser, &num))
+			return false;
+		prop->value.err = num;
+		break;
+	}
+	case PT_MV_BINARY:
+	{
+		uint32_t i;
+		if (!pull_uint32_t(parser, &(prop->value.MVbin.cValues)) ||
+		    parser->idx + prop->value.MVbin.cValues * 4 > parser->data.length)
+			return false;
+		prop->value.MVbin.lpbin = talloc_array(parser->mem_ctx, struct Binary_r, prop->value.MVbin.cValues);
+		for (i = 0; i < prop->value.MVbin.cValues; i++) {
+			if (!pull_binary(parser, &(prop->value.MVbin.lpbin[i])))
+				return false;
+		}
+		break;
+	}
+	case PT_MV_SHORT:
+	{
+		uint32_t i;
+		if (!pull_uint32_t(parser, &(prop->value.MVi.cValues)) ||
+		    parser->idx + prop->value.MVi.cValues * 2 > parser->data.length)
+			return false;
+		prop->value.MVi.lpi = talloc_array(parser->mem_ctx, uint16_t, prop->value.MVi.cValues);
+		for (i = 0; i < prop->value.MVi.cValues; i++) {
+			if (!pull_uint16_t(parser, &(prop->value.MVi.lpi[i])))
+				return false;
+		}
+		break;
+	}
+	case PT_MV_LONG:
+	{
+		uint32_t i;
+		if (!pull_uint32_t(parser, &(prop->value.MVl.cValues)) ||
+		    parser->idx + prop->value.MVl.cValues * 4 > parser->data.length)
+			return false;
+		prop->value.MVl.lpl = talloc_array(parser->mem_ctx, uint32_t, prop->value.MVl.cValues);
+		for (i = 0; i < prop->value.MVl.cValues; i++) {
+			if (!pull_uint32_t(parser, &(prop->value.MVl.lpl[i])))
+				return false;
+		}
+		break;
+	}
+	case PT_MV_STRING8:
+	{
+		uint32_t i;
+		char *str;
+		if (!pull_uint32_t(parser, &(prop->value.MVszA.cValues)) ||
+		    parser->idx + prop->value.MVszA.cValues * 4 > parser->data.length)
+			return false;
+		prop->value.MVszA.lppszA = (const char **) talloc_array(parser->mem_ctx, char *, prop->value.MVszA.cValues);
+		for (i = 0; i < prop->value.MVszA.cValues; i++) {
+			str = NULL;
+			if (!pull_string8(parser, &str))
+				return false;
+			prop->value.MVszA.lppszA[i] = str;
+		}
+		break;
+	}
+	case PT_MV_CLSID:
+	{
+		uint32_t i;
+		if (!pull_uint32_t(parser, &(prop->value.MVguid.cValues)) ||
+		    parser->idx + prop->value.MVguid.cValues * 16 > parser->data.length)
+			return false;
+		prop->value.MVguid.lpguid = talloc_array(parser->mem_ctx, struct FlatUID_r *, prop->value.MVguid.cValues);
+		for (i = 0; i < prop->value.MVguid.cValues; i++) {
+			if (!pull_clsid(parser, &(prop->value.MVguid.lpguid[i])))
+				return false;
+		}
+		break;
+	}
+	case PT_MV_UNICODE:
+	{
+		uint32_t i;
+		char *str;
+
+		if (!pull_uint32_t(parser, &(prop->value.MVszW.cValues)) ||
+		    parser->idx + prop->value.MVszW.cValues * 4 > parser->data.length)
+			return false;
+		prop->value.MVszW.lppszW = (const char **)  talloc_array(parser->mem_ctx, char *, prop->value.MVszW.cValues);
+		for (i = 0; i < prop->value.MVszW.cValues; i++) {
+			str = NULL;
+			if (!pull_unicode(parser, &str))
+				return false;
+			prop->value.MVszW.lppszW[i] = str;
+		}
+		break;
+	}
+	case PT_MV_SYSTIME:
+	{
+		uint32_t i;
+		if (!pull_uint32_t(parser, &(prop->value.MVft.cValues)) ||
+		    parser->idx + prop->value.MVft.cValues * 8 > parser->data.length)
+			return false;
+		prop->value.MVft.lpft = talloc_array(parser->mem_ctx, struct FILETIME, prop->value.MVft.cValues);
+		for (i = 0; i < prop->value.MVft.cValues; i++) {
+			if (!pull_systime(parser, &(prop->value.MVft.lpft[i])))
+				return false;
+		}
+		break;
+	}
+	default:
+		printf("unhandled conversion case in fetch_property_value(): 0x%x\n", (prop->ulPropTag & 0xFFFF));
+		g_return_val_if_reached(false);
+	}
+	return true;
+}
+
+static bool pull_named_property(struct e_mapi_fx_parser_context *parser, enum MAPISTATUS *ms)
+{
+	uint8_t type = 0;
+	if (!pull_guid(parser, &(parser->namedprop.lpguid)))
+		return false;
+	/* printf("guid       : %s\n", GUID_string(parser->mem_ctx, &(parser->namedprop.lpguid))); */
+	if (!pull_uint8_t(parser, &type))
+		return false;
+	if (type == 0) {
+		parser->namedprop.ulKind = MNID_ID;
+		if (!pull_uint32_t(parser, &(parser->namedprop.kind.lid)))
+			return false;
+		/* printf("LID dispid: 0x%08x\n", parser->namedprop.kind.lid); */
+	} else if (type == 1) {
+		smb_ucs2_t *ucs2_data = NULL;
+		size_t utf8_len;
+		parser->namedprop.ulKind = MNID_STRING;
+		if (!fetch_ucs2_nullterminated(parser, &ucs2_data))
+			return false;
+		pull_ucs2_talloc(parser->mem_ctx, (char**)&(parser->namedprop.kind.lpwstr.Name), ucs2_data, &(utf8_len));
+		parser->namedprop.kind.lpwstr.NameSize = utf8_len;
+		/* printf("named: %s\n", parser->namedprop.kind.lpwstr.Name); */
+	} else {
+		printf("unknown named property kind: 0x%02x\n", parser->namedprop.ulKind);
+		g_return_val_if_reached(false);
+	}
+	if (parser->op_namedprop) {
+		*ms = parser->op_namedprop(parser->lpProp.ulPropTag, parser->namedprop, parser->priv);
+	}
+
+	return true;
+}
+
+/**
+  \details set a callback function for marker output
+*/
+_PUBLIC_ void e_mapi_fxparser_set_marker_callback(struct e_mapi_fx_parser_context *parser, e_mapi_fxparser_marker_callback_t marker_callback)
+{
+	parser->op_marker = marker_callback;
+}
+
+/**
+  \details set a callback function for delete properties output
+*/
+_PUBLIC_ void e_mapi_fxparser_set_delprop_callback(struct e_mapi_fx_parser_context *parser, e_mapi_fxparser_delprop_callback_t delprop_callback)
+{
+	parser->op_delprop = delprop_callback;
+}
+
+/**
+  \details set a callback function for named properties output
+*/
+_PUBLIC_ void e_mapi_fxparser_set_namedprop_callback(struct e_mapi_fx_parser_context *parser, e_mapi_fxparser_namedprop_callback_t namedprop_callback)
+{
+	parser->op_namedprop = namedprop_callback;
+}
+
+/**
+  \details set a callback function for property output
+*/
+_PUBLIC_ void e_mapi_fxparser_set_property_callback(struct e_mapi_fx_parser_context *parser, e_mapi_fxparser_property_callback_t property_callback)
+{
+	parser->op_property = property_callback;
+}
+
+/**
+  \details initialise a fast transfer parser
+*/
+_PUBLIC_ struct e_mapi_fx_parser_context* e_mapi_fxparser_init(TALLOC_CTX *mem_ctx, void *priv)
+{
+	struct e_mapi_fx_parser_context *parser = talloc_zero(mem_ctx, struct e_mapi_fx_parser_context);
+
+	parser->mem_ctx = mem_ctx;
+	parser->data = data_blob_talloc_named(parser->mem_ctx, NULL, 0, "fast transfer parser");
+	parser->state = ParserState_Entry;
+	parser->idx = 0;
+	parser->lpProp.ulPropTag = (enum MAPITAGS) 0;
+	parser->lpProp.dwAlignPad = 0;
+	parser->lpProp.value.l = 0;
+	parser->priv = priv;
+
+	return parser;
+}
+
+/**
+  \details parse a fast transfer buffer
+*/
+_PUBLIC_ enum MAPISTATUS e_mapi_fxparser_parse(struct e_mapi_fx_parser_context *parser, DATA_BLOB *fxbuf)
+{
+	enum MAPISTATUS ms = MAPI_E_SUCCESS;
+
+	data_blob_append(parser->mem_ctx, &(parser->data), fxbuf->data, fxbuf->length);
+	parser->enough_data = true;
+	while(ms == MAPI_E_SUCCESS && (parser->idx < parser->data.length) && parser->enough_data) {
+		uint32_t idx = parser->idx;
+
+		switch(parser->state) {
+			case ParserState_Entry:
+			{
+				if (pull_tag(parser)) {
+					/* printf("tag: 0x%08x\n", parser->tag); */
+					parser->state = ParserState_HaveTag;
+				} else {
+					parser->enough_data = false;
+					parser->idx = idx;
+				}
+				break;
+			}
+			case ParserState_HaveTag:
+			{
+				switch (parser->tag) {
+					case PidTagStartTopFld:
+					case PidTagStartSubFld:
+					case PidTagEndFolder:
+					case PidTagStartMessage:
+					case PidTagStartFAIMsg:
+					case PidTagEndMessage:
+					case PidTagStartRecip:
+					case PidTagEndToRecip:
+					case PidTagNewAttach:
+					case PidTagEndAttach:
+					case PidTagStartEmbed:
+					case PidTagEndEmbed:
+						if (parser->op_marker) {
+							ms = parser->op_marker(parser->tag, parser->priv);
+						}
+						parser->state = ParserState_Entry;
+						break;
+					case PidTagFXDelProp:
+					{
+						uint32_t tag;
+						if (pull_uint32_t(parser, &tag)) {
+							if (parser->op_delprop) {
+								ms = parser->op_delprop(tag, parser->priv);
+							}
+							parser->state = ParserState_Entry;
+						} else {
+							parser->enough_data = false;
+							parser->idx = idx;
+						}
+						break;
+					}
+					default:
+					{
+						/* standard property thing */
+						parser->lpProp.ulPropTag = (enum MAPITAGS) parser->tag;
+						parser->lpProp.dwAlignPad = 0;
+						if ((parser->lpProp.ulPropTag >> 16) & 0x8000) {
+							/* this is a named property */
+							// printf("tag: 0x%08x\n", parser->tag);
+							// TODO: this should probably be a separate parser state
+							// TODO: this needs to return the named property
+							if (pull_named_property(parser, &ms)) {
+								parser->state = ParserState_HavePropTag;
+							} else {
+								parser->enough_data = false;
+								parser->idx = idx;
+							}
+						} else {
+							parser->state = ParserState_HavePropTag;
+						}
+					}
+				}
+				break;
+			}
+			case ParserState_HavePropTag:
+			{
+				if (fetch_property_value(parser, &(parser->data), &(parser->lpProp))) {
+					// printf("position %i of %zi\n", parser->idx, parser->data.length);
+					if (parser->op_property) {
+						ms = parser->op_property(parser->lpProp, parser->priv);
+					}
+					parser->state = ParserState_Entry;
+				} else {
+					parser->enough_data = false;
+					parser->idx = idx;
+				}
+				break;
+			}
+		}
+	}
+	{
+		// Remove the part of the buffer that we've used
+		uint32_t remainder_len = parser->data.length - parser->idx;
+		DATA_BLOB remainder = data_blob_talloc_named(parser->mem_ctx, &(parser->data.data[parser->idx]), remainder_len, "fast transfer parser");
+		data_blob_free(&(parser->data));
+		parser->data = remainder;
+		parser->idx = 0;
+	}
+
+	return ms;
+}
diff --git a/src/libexchangemapi/e-mapi-openchange.h b/src/libexchangemapi/e-mapi-openchange.h
index 0a1d6e5..36b0af4 100644
--- a/src/libexchangemapi/e-mapi-openchange.h
+++ b/src/libexchangemapi/e-mapi-openchange.h
@@ -35,6 +35,19 @@ G_BEGIN_DECLS
 enum MAPISTATUS e_mapi_nameid_lid_lookup_canonical (uint16_t lid, const char *OLEGUID, uint32_t *propTag);
 enum MAPISTATUS e_mapi_nameid_string_lookup_canonical(const char *Name, const char *OLEGUID, uint32_t *propTag);
 
+struct e_mapi_fx_parser_context;
+typedef enum MAPISTATUS (*e_mapi_fxparser_marker_callback_t)(uint32_t, void *);
+typedef enum MAPISTATUS (*e_mapi_fxparser_delprop_callback_t)(uint32_t, void *);
+typedef enum MAPISTATUS (*e_mapi_fxparser_namedprop_callback_t)(uint32_t, struct MAPINAMEID, void *);
+typedef enum MAPISTATUS (*e_mapi_fxparser_property_callback_t)(struct SPropValue, void *);
+
+struct e_mapi_fx_parser_context *e_mapi_fxparser_init(TALLOC_CTX *, void *);
+void e_mapi_fxparser_set_marker_callback(struct e_mapi_fx_parser_context *, e_mapi_fxparser_marker_callback_t);
+void e_mapi_fxparser_set_delprop_callback(struct e_mapi_fx_parser_context *, e_mapi_fxparser_delprop_callback_t);
+void e_mapi_fxparser_set_namedprop_callback(struct e_mapi_fx_parser_context *, e_mapi_fxparser_namedprop_callback_t);
+void e_mapi_fxparser_set_property_callback(struct e_mapi_fx_parser_context *, e_mapi_fxparser_property_callback_t);
+enum MAPISTATUS e_mapi_fxparser_parse(struct e_mapi_fx_parser_context *, DATA_BLOB *);
+
 G_END_DECLS
 
 #endif /* E_MAPI_OPENCHANGE_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]