libopc
opc_zipextract.c

Demonstrates low level ZIP read functionality as needed by the high level opcContainer API.

/*
Tests the low-level ZIP functionality. Will extract all streams and verify the CRC checksum.
Ussage:
opc_zipextract FILENAME
Sample:
opc_zipextract OOXMLI1.docx
*/
#include <opc/opc.h>
#include <stdio.h>
#include <libxml/xmlstring.h>
#include <time.h>
#include <zlib.h> // for crc32 function
#ifdef WIN32
#include <crtdbg.h>
#endif
static opc_error_t loadSegment(void *iocontext,
void *userctx,
opcZip *zip=(opcZip*)userctx;
// OPC_ENSURE(0==skip(iocontext));
OPC_ENSURE(0==open(iocontext));
opc_uint32_t crc=0;
char buf[100];
int ret=0;
while((ret=read(iocontext, buf, sizeof(buf)))>0) {
crc=crc32(crc, (const Bytef*)buf, ret);
}
OPC_ASSERT(info->data_crc==crc);
OPC_ASSERT(ret>=0);
OPC_ENSURE(0==close(iocontext));
opcZipLoadSegment(zip, xmlStrdup(info->name), info->rels_segment, info);
return OPC_ERROR_NONE;
}
static opc_error_t releaseSegment(opcZip *zip, opc_uint32_t segment_id) {
const xmlChar *name=NULL;
OPC_ENSURE(OPC_ERROR_NONE==opcZipGetSegmentInfo(zip, segment_id, &name, NULL, NULL));
OPC_ASSERT(NULL!=name);
xmlFree((void*)name);
return OPC_ERROR_NONE;
}
int main( int argc, const char* argv[] )
{
#ifdef WIN32
_CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
time_t start_time=time(NULL);
opc_error_t err=OPC_ERROR_NONE;
if (OPC_ERROR_NONE==(err=opcInitLibrary())) {
if (argc>2) {
opcIO_t io;
if (OPC_ERROR_NONE==opcFileInitIOFile(&io, _X(argv[1]), OPC_FILE_READ)) {
opcZip *zip=opcZipCreate(&io);
if (NULL!=zip) {
err=opcZipLoader(&io, zip, loadSegment);
if (OPC_ERROR_NONE==err) {
// successfully loaded; dump all segments
-1!=segment_id;
segment_id=opcZipGetNextSegmentId(zip, segment_id)) {
const xmlChar *name=NULL;
opc_bool_t rels_segment=OPC_FALSE;
opc_uint32_t data_crc=0;
OPC_ENSURE(OPC_ERROR_NONE==opcZipGetSegmentInfo(zip, segment_id, &name, &rels_segment, &data_crc));
OPC_ASSERT(NULL!=name);
if (!rels_segment && 0==xmlStrcmp(name, _X(argv[2]))) {
printf("extracting \"%s\"\n", name);
opcZipInputStream *stream=opcZipOpenInputStream(zip, segment_id);
if (NULL!=stream) {
opc_uint32_t crc=0;
opc_uint8_t buf[100];
opc_uint32_t ret=0;
while((ret=opcZipReadInputStream(zip, stream , buf, sizeof(buf)))>0) {
// printf("%.*s", ret, buf);
crc=crc32(crc, (const Bytef*)buf, ret);
}
OPC_ASSERT(crc==data_crc);
opcZipCloseInputStream(zip, stream);
}
} else {
printf("skip \"%s\" %s\n", name, (rels_segment?"(.rels)":""));
}
}
}
opcZipClose(zip, releaseSegment);
} else {
OPC_ENSURE(OPC_ERROR_NONE==opcFileCleanupIO(&io));
}
}
}
if (OPC_ERROR_NONE==err) err=opcFreeLibrary();
}
time_t end_time=time(NULL);
fprintf(stderr, "time %.2lfsec\n", difftime(end_time, start_time));
#ifdef WIN32
OPC_ASSERT(!_CrtDumpMemoryLeaks());
#endif
return (OPC_ERROR_NONE==err?0:3);
}