示例#1
0
/**
   \details creates a DATA_BLOB in uncompressed Rich Text Format (RTF)
   from the compressed format used in the PR_RTF_COMPRESSED property
   opened in the stream.

   \param obj_stream stream object with RTF stream content
   \param rtf the output blob with uncompressed content

   \return MAPI_E_SUCCESS on success, otherwise MAPI error. Possible
   MAPI error codes are:
   - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
   - MAPI_E_INVALID_PARAMETER: obj_stream is not a valid pointer
   - MAPI_E_CORRUPT_DATA: a problem was encountered while
     decompressing the RTF compressed data
   - MAPI_E_CALL_FAILED: A network problem was encountered during the
   transaction

   \note Developers may also call GetLastError() to retrieve the last
   MAPI error code.
 
   \note rtf->data needs to be freed with MAPIFreeBuffer

   \sa OpenStream
*/
_PUBLIC_ enum MAPISTATUS WrapCompressedRTFStream(mapi_object_t *obj_stream, 
						 DATA_BLOB *rtf)
{
	enum MAPISTATUS		retval;
	struct mapi_context	*mapi_ctx;
	struct mapi_session	*session;
	TALLOC_CTX		*mem_ctx;
	uint32_t		in_size;
	uint8_t			*rtfcomp;
	uint16_t		read_size;
	unsigned char		buf[0x1000];

	/* sanity check and init */
	OPENCHANGE_RETVAL_IF(!obj_stream, MAPI_E_INVALID_PARAMETER, NULL);

	session = mapi_object_get_session(obj_stream);
	OPENCHANGE_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);

	mapi_ctx = session->mapi_ctx;
	OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);

	mem_ctx = mapi_ctx->mem_ctx;

	/* Read the stream pointed by obj_stream */
	read_size = 0;
	in_size = 0;
	rtfcomp = talloc_zero(mem_ctx, uint8_t);
	do {
		retval = ReadStream(obj_stream, buf, 0x1000, &read_size);
		OPENCHANGE_RETVAL_IF(retval, GetLastError(), rtf->data);
		if (read_size) {
			rtfcomp = talloc_realloc(mem_ctx, rtfcomp, uint8_t, 
						   in_size + read_size);
			memcpy(&(rtfcomp[in_size]), buf, read_size);
			in_size += read_size;
		}
	} while (read_size);

	return uncompress_rtf(mem_ctx, rtfcomp, in_size, rtf);
}
/**
     \details Test the Compressed RTF decompression routine.

   This function:
   -# Loads some test data and checks it
   -# Decompresses the test data
   -# Checks that the decompressed data matches the expected result

   \param mt pointer on the top-level mapitest structure

   \return true on success, otherwise false
*/ 
_PUBLIC_ bool mapitest_noserver_lzfu(struct mapitest *mt)
{
	enum MAPISTATUS		retval;
	DATA_BLOB		uncompressed1;
	DATA_BLOB		uncompressed2;
	uint8_t			compressed_hex[1024];
	uint8_t			*compressed;
	uint32_t		compressed_length;

	compressed = talloc_array(mt->mem_ctx, uint8_t, 1024);

	memcpy(compressed_hex, RTF_COMPRESSED1_HEX, 98);
	compressed_length = strhex_to_str((char*)compressed, 1024, (char*)compressed_hex, 98);
	if (compressed_length != 49) {
		mapitest_print(mt, "* %-40s: uncompress RTF - Bad length\n", "LZFU");
		return false;
	}

	uint32_t crc = calculateCRC(compressed, 0x10, (49-0x10));
	if (crc == 0xA7C7C5F1) {
		  mapitest_print(mt, "* CRC pass\n");
	} else {
		  mapitest_print(mt, "* CRC failure, expected 0xA7C7C5F1, but got 0x%08X\n", crc);
	}

	retval = uncompress_rtf(mt->mem_ctx, compressed, compressed_length, &uncompressed1);
	if (retval != MAPI_E_SUCCESS) {
		mapitest_print_retval(mt, "uncompress_rtf - step 1 (bad retval)");
		return false;
	}	   

	if (sizeof(RTF_UNCOMPRESSED1) != uncompressed1.length) {
		mapitest_print(mt, "* %-40s: FAILED (bad length: %i vs %i)\n", "uncompress_rtf - step 1",
			       sizeof(RTF_UNCOMPRESSED1), uncompressed1.length);
		return false;
	}
	if (!strncmp((char*)uncompressed1.data, RTF_UNCOMPRESSED1, uncompressed1.length)) {
		mapitest_print(mt, "* %-40s: PASSED\n", "uncompress_rtf - step 1");
	} else {
		mapitest_print(mt, "* %-40s: FAILED - %s\n", "uncompress_rtf - step 1", (char*)uncompressed1.data);
		return false;
	}

	memcpy(compressed_hex, RTF_COMPRESSED2_HEX, 60);
	compressed_length = strhex_to_str((char*)compressed, 1024, (char*)compressed_hex, 60);
	if (compressed_length != 30) {
		mapitest_print(mt, "* %-40s: uncompress RTF - Bad length\n", "LZFU");
		return false;
	}
	retval = uncompress_rtf(mt->mem_ctx, compressed, compressed_length, &uncompressed2);
	if (retval != MAPI_E_SUCCESS) {
		mapitest_print_retval(mt, "uncompress_rtf - step 2 (bad retval)");
		return false;
	}	   

	if (!strncmp((char*)uncompressed2.data, RTF_UNCOMPRESSED2, uncompressed2.length)) {
		mapitest_print(mt, "* %-40s: PASSED\n", "uncompress_rtf - step 2");
	} else {
		mapitest_print(mt, "* %-40s: FAILED - %s\n", "uncompress_rtf - step 2", (char*)uncompressed2.data);
		return false;
	}
	
	/* TODO: add an uncompressed test here */

	return true;
}
/**
     \details Test the Compressed RTF compression / decompression routines on a larger file

   \param mt pointer to the top-level mapitest structure

   \return true on success, otherwise false
*/ 
_PUBLIC_ bool mapitest_noserver_rtfcp_large(struct mapitest *mt)
{
	enum MAPISTATUS		retval;

	char			*filename = NULL;
	char			*original_uncompressed_data;
	size_t			original_uncompressed_length;
	char			*original_uncompressed_hex;

	uint8_t			*compressed;
	size_t			compressed_length;

	DATA_BLOB		decompressed;
	char 			*decompressed_hex;

	/* load the test file */
	filename = talloc_asprintf(mt->mem_ctx, "%s/testcase.rtf", LZFU_DATADIR);
	original_uncompressed_data = file_load(filename, &original_uncompressed_length, 0, mt->mem_ctx);
	if (!original_uncompressed_data) {
		perror(filename);
		mapitest_print(mt, "%s: Error while loading %s\n", __FUNCTION__, filename);
		talloc_free(filename);
		return false;
	}
	talloc_free(filename);
	original_uncompressed_hex = hex_encode_talloc(mt->mem_ctx, (const unsigned char*)original_uncompressed_data, original_uncompressed_length);

	/* compress it */
	retval = compress_rtf(mt->mem_ctx, original_uncompressed_data, original_uncompressed_length, &compressed, &compressed_length);
	if (retval != MAPI_E_SUCCESS) {
		mapitest_print_retval_clean(mt, "mapitest_noserver_rtfcp_large - step 1 (bad retval)", retval);
		return false;
	}

	/* decompress it */
	retval = uncompress_rtf(mt->mem_ctx, compressed, compressed_length, &decompressed);
	if (retval != MAPI_E_SUCCESS) {
		mapitest_print_retval_clean(mt, "mapitest_noserver_rtfcp_large - step 2 (bad retval)", retval);
		return false;
	}

	mapitest_print(mt, "Original data size = 0x%zx\n", original_uncompressed_length);
	mapitest_print(mt, "Decompressed size  = 0x%zx\n", decompressed.length);
	{
		int i;
		int min;

		min = (original_uncompressed_length >= decompressed.length) ? decompressed.length : original_uncompressed_length;
		mapitest_print(mt, "Comparing data over 0x%x bytes\n", min);
		for (i = 0; i < min; i++) {
			if (decompressed.data[i] != original_uncompressed_data[i]) {
				mapitest_print(mt, "Bytes differ at offset 0x%x: original (0x%.2x) decompressed (0x%.2x)\n", 
						i, original_uncompressed_data[i], decompressed.data[i]);
			}
		}
		
	}

	/* check the uncompressed version (less trailing null) matches the original test file contents */
	decompressed_hex = hex_encode_talloc(mt->mem_ctx, decompressed.data, decompressed.length -1);
	if (strncasecmp(original_uncompressed_hex, decompressed_hex, original_uncompressed_length) != 0) {
		mapitest_print(mt, "* %-40s: compare results - mismatch\n", "RTFCP_LARGE");
		return false;
	} else {
		mapitest_print(mt, "* %-40s: compare results - match\n", "RTFCP_LARGE");
		// mapitest_print(mt, "- %s\n", original_uncompressed_hex);
		// mapitest_print(mt, "- %s\n", decompressed_hex);
	}
	
	/* clean up */
	talloc_free(decompressed_hex);
	talloc_free(compressed);
	talloc_free(original_uncompressed_hex);

	return true;
}