f53bed0b |
sctx->flags |= OLE2_CODEPAGE_ERROR_UNINITED;
}
else {
offset = 0;
for (try = 1; try <= 3; ++try) {
/* charset to UTF-8 should never exceed sz*6 */
sz2 = (try*2) * sz;
/* use cli_realloc, reuse the buffer that has already been translated */
outbuf = (char *)cli_realloc(outbuf, sz2+1);
if (!outbuf) {
free(buf);
return NULL;
}
outlen = sz2 - offset;
p2 = outbuf + offset;
/* conversion */
nonrev = iconv(cd, &p1, &inlen, &p2, &outlen);
if (errno == EILSEQ) {
cli_dbgmsg("ole2_convert_utf: input buffer contains invalid character for its encoding\n");
sctx->flags |= OLE2_CODEPAGE_ERROR_INVALID;
break;
}
else if (errno == EINVAL && nonrev == (size_t)-1) {
cli_dbgmsg("ole2_convert_utf: input buffer contains incomplete multibyte character\n");
sctx->flags |= OLE2_CODEPAGE_ERROR_INCOMPLETE;
break;
}
else if (inlen == 0) {
//cli_dbgmsg("ole2_convert_utf: input buffer is successfully translated\n");
break;
}
//outbuf[sz2 - outlen] = '\0';
//cli_dbgmsg("%u %s\n", inlen, outbuf);
offset = sz2 - outlen;
if (try < 3)
cli_dbgmsg("ole2_convert_utf: outbuf is too small, resizing %llu -> %llu\n",
(long long unsigned)((try*2) * sz), (long long unsigned)(((try+1)*2) * sz));
}
if (errno == E2BIG && nonrev == (size_t)-1) {
cli_dbgmsg("ole2_convert_utf: buffer could not be fully translated\n");
sctx->flags |= OLE2_CODEPAGE_ERROR_OUTBUFTOOSMALL;
}
outbuf[sz2 - outlen] = '\0';
}
iconv_close(cd);
free(buf);
#endif
/* this should force base64 encoding if NULL */
return outbuf;
}
static int
ole2_process_property(summary_ctx_t *sctx, unsigned char *databuf, uint32_t offset)
{
uint16_t proptype, padding;
int ret = CL_SUCCESS;
if (cli_json_timeout_cycle_check(sctx->ctx, &(sctx->toval)) != CL_SUCCESS) {
sctx->flags |= OLE2_SUMMARY_FLAG_TIMEOUT;
return CL_ETIMEOUT;
}
if (offset+sizeof(proptype)+sizeof(padding) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&proptype, databuf+offset, sizeof(proptype));
offset+=sizeof(proptype);
memcpy(&padding, databuf+offset, sizeof(padding));
offset+=sizeof(padding);
/* endian conversion */
proptype = sum16_endian_convert(proptype);
//cli_dbgmsg("proptype: 0x%04x\n", proptype);
if (padding != 0) {
cli_dbgmsg("ole2_process_property: invalid padding value, non-zero\n");
sctx->flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
return CL_EFORMAT;
}
switch (proptype) {
case PT_EMPTY:
case PT_NULL:
ret = cli_jsonnull(sctx->summary, sctx->propname);
break;
case PT_INT16:
{
int16_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum16_endian_convert(dout);
if (sctx->writecp) {
sctx->codepage = (uint16_t)dout;
ret = cli_jsonint(sctx->summary, sctx->propname, sctx->codepage);
}
else
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
break;
}
case PT_INT32:
case PT_INT32v1:
{
int32_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum32_endian_convert(dout);
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
break;
}
case PT_FLOAT32: /* review this please */
{
float dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum32_endian_convert(dout);
ret = cli_jsondouble(sctx->summary, sctx->propname, dout);
break;
}
case PT_DATE:
case PT_DOUBLE64: /* review this please */
{
double dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum64_endian_convert(dout);
ret = cli_jsondouble(sctx->summary, sctx->propname, dout);
break;
}
case PT_BOOL:
{
uint16_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* no need for endian conversion */
ret = cli_jsonbool(sctx->summary, sctx->propname, dout);
break;
}
case PT_INT8v1:
{
int8_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* no need for endian conversion */
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
break;
}
case PT_UINT8:
{
uint8_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* no need for endian conversion */
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
break;
}
case PT_UINT16:
{
uint16_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum16_endian_convert(dout);
if (sctx->writecp)
sctx->codepage = dout;
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
break;
}
case PT_UINT32:
case PT_UINT32v1:
{
uint32_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum32_endian_convert(dout);
ret = cli_jsonint(sctx->summary, sctx->propname, dout);
break;
}
case PT_INT64:
{
int64_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum64_endian_convert(dout);
ret = cli_jsonint64(sctx->summary, sctx->propname, dout);
break;
}
case PT_UINT64:
{
uint64_t dout;
if (offset+sizeof(dout) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&dout, databuf+offset, sizeof(dout));
offset+=sizeof(dout);
/* endian conversion */
dout = sum64_endian_convert(dout);
ret = cli_jsonint64(sctx->summary, sctx->propname, dout);
break;
}
case PT_BSTR:
case PT_LPSTR:
if (sctx->codepage == 0) {
cli_dbgmsg("ole2_propset_json: current codepage is unknown, cannot parse char stream\n");
sctx->flags |= OLE2_SUMMARY_FLAG_CODEPAGE;
}
else {
uint32_t strsize;
char *outstr, *outstr2;
if (offset+sizeof(strsize) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&strsize, databuf+offset, sizeof(strsize));
offset+=sizeof(strsize);
/* endian conversion? */
strsize = sum32_endian_convert(strsize);
if (offset+strsize > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
/* limitation on string length */
if (strsize > PROPSTRLIMIT) {
cli_dbgmsg("ole2_process_property: property string sized %lu truncated to size %lu\n",
(unsigned long)strsize, (unsigned long)PROPSTRLIMIT);
sctx->flags |= OLE2_SUMMARY_FLAG_TRUNC_STR;
strsize = PROPSTRLIMIT;
}
outstr = cli_calloc(strsize+1, 1); /* last char must be NULL */
if (!outstr) {
return CL_EMEM;
}
strncpy(outstr, (const char *)(databuf+offset), strsize);
/* conversion of various encodings to UTF-8 */
outstr2 = ole2_convert_utf(sctx, outstr, strsize, NULL);
if (!outstr2) {
/* use base64 encoding when all else fails! */
char b64jstr[PROPSTRLIMIT];
/* outstr2 should be 4/3 times the original (rounded up) */
outstr2 = cl_base64_encode(outstr, strsize);
if (!outstr2) {
cli_dbgmsg("ole2_process_property: failed to convert to base64 string\n");
return CL_EMEM;
}
snprintf(b64jstr, PROPSTRLIMIT, "%s_base64", sctx->propname);
ret = cli_jsonbool(sctx->summary, b64jstr, 1);
if (ret != CL_SUCCESS)
return ret;
}
ret = cli_jsonstr(sctx->summary, sctx->propname, outstr2);
free(outstr);
free(outstr2);
}
break;
case PT_LPWSTR:
{
uint32_t strsize;
char *outstr, *outstr2;
if (offset+sizeof(strsize) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(&strsize, databuf+offset, sizeof(strsize));
offset+=sizeof(strsize);
/* endian conversion; wide strings are by length, not size (x2) */
strsize = sum32_endian_convert(strsize)*2;
/* limitation on string length */
if (strsize > (2*PROPSTRLIMIT)) {
cli_dbgmsg("ole2_process_property: property string sized %lu truncated to size %lu\n",
(unsigned long)strsize, (unsigned long)(2*PROPSTRLIMIT));
sctx->flags |= OLE2_SUMMARY_FLAG_TRUNC_STR;
strsize = (2*PROPSTRLIMIT);
}
if (offset+strsize > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
outstr = cli_calloc(strsize+2, 1); /* last two chars must be NULL */
if (!outstr) {
return CL_EMEM;
}
memcpy(outstr, (const char *)(databuf+offset), strsize);
/* conversion of 16-width char strings (UTF-16 or UTF-16LE??) to UTF-8 */
outstr2 = ole2_convert_utf(sctx, outstr, strsize, UTF16_MS);
if (!outstr2) {
/* use base64 encoding when all else fails! */
char b64jstr[PROPSTRLIMIT];
outstr2 = cl_base64_encode(outstr, strsize);
if (!outstr2) {
free(outstr);
return CL_EMEM;
}
snprintf(b64jstr, PROPSTRLIMIT, "%s_base64", sctx->propname);
ret = cli_jsonbool(sctx->summary, b64jstr, 1);
if (ret != CL_SUCCESS)
return ret;
}
ret = cli_jsonstr(sctx->summary, sctx->propname, outstr2);
free(outstr);
free(outstr2);
break;
}
case PT_FILETIME:
{
uint32_t ltime, htime;
uint64_t wtime = 0, utime =0;
if (offset+sizeof(ltime)+sizeof(htime) > sctx->pssize) {
sctx->flags |= OLE2_SUMMARY_ERROR_OOB;
return CL_EFORMAT;
}
memcpy(<ime, databuf+offset, sizeof(ltime));
offset+=sizeof(ltime);
memcpy(&htime, databuf+offset, sizeof(htime));
offset+=sizeof(ltime);
ltime = sum32_endian_convert(ltime);
htime = sum32_endian_convert(htime);
/* UNIX timestamp formatting */
wtime = htime;
wtime <<= 32;
wtime |= ltime;
utime = wtime / 10000000;
utime -= 11644473600LL;
if ((uint32_t)((utime & 0xFFFFFFFF00000000) >> 32)) {
cli_dbgmsg("ole2_process_property: UNIX timestamp is larger than 32-bit number\n");
}
else {
ret = cli_jsonint(sctx->summary, sctx->propname, (uint32_t)(utime & 0xFFFFFFFF));
}
break;
}
default:
cli_dbgmsg("ole2_process_property: unhandled property type 0x%04x for %s property\n",
proptype, sctx->propname);
sctx->flags |= OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE;
}
return ret;
}
static void ole2_translate_docsummary_propid(summary_ctx_t *sctx, uint32_t propid)
{
switch(propid) {
case DSPID_CODEPAGE:
sctx->writecp = 1; /* must be set ONLY for codepage */
sctx->propname = "CodePage";
break;
case DSPID_CATEGORY:
sctx->propname = "Category";
break;
case DSPID_PRESFORMAT:
sctx->propname = "PresentationTarget";
break;
case DSPID_BYTECOUNT:
sctx->propname = "Bytes";
break;
case DSPID_LINECOUNT:
sctx->propname = "Lines";
break;
case DSPID_PARCOUNT:
sctx->propname = "Paragraphs";
break;
case DSPID_SLIDECOUNT:
sctx->propname = "Slides";
break;
case DSPID_NOTECOUNT:
sctx->propname = "Notes";
break;
case DSPID_HIDDENCOUNT:
sctx->propname = "HiddenSlides";
break;
case DSPID_MMCLIPCOUNT:
sctx->propname = "MMClips";
break;
case DSPID_SCALE:
sctx->propname = "Scale";
break;
case DSPID_HEADINGPAIR: /* VT_VARIANT | VT_VECTOR */
sctx->propname = "HeadingPairs";
break;
case DSPID_DOCPARTS: /* VT_VECTOR | VT_LPSTR */
sctx->propname = "DocPartTitles";
break;
case DSPID_MANAGER:
sctx->propname = "Manager";
break;
case DSPID_COMPANY:
sctx->propname = "Company";
break;
case DSPID_LINKSDIRTY:
sctx->propname = "LinksDirty";
break;
case DSPID_CCHWITHSPACES:
sctx->propname = "Char&WSCount";
break;
case DSPID_SHAREDDOC: /* SHOULD BE FALSE! */
sctx->propname = "SharedDoc";
break;
case DSPID_LINKBASE: /* moved to user-defined */
sctx->propname = "LinkBase";
break;
case DSPID_HLINKS: /* moved to user-defined */
sctx->propname = "HyperLinks";
break;
case DSPID_HYPERLINKSCHANGED:
sctx->propname = "HyperLinksChanged";
break;
case DSPID_VERSION:
sctx->propname = "Version";
break;
case DSPID_DIGSIG:
sctx->propname = "DigitalSig";
break;
case DSPID_CONTENTTYPE:
sctx->propname = "ContentType";
break;
case DSPID_CONTENTSTATUS:
sctx->propname = "ContentStatus";
break;
case DSPID_LANGUAGE:
sctx->propname = "Language";
break;
case DSPID_DOCVERSION:
sctx->propname = "DocVersion";
break;
default:
cli_dbgmsg("ole2_docsum_propset_json: unrecognized propid!\n");
sctx->flags |= OLE2_SUMMARY_FLAG_UNKNOWN_PROPID;
}
}
static void ole2_translate_summary_propid(summary_ctx_t *sctx, uint32_t propid)
{
switch(propid) {
case SPID_CODEPAGE:
sctx->writecp = 1; /* must be set ONLY for codepage */
sctx->propname = "CodePage";
break;
case SPID_TITLE:
sctx->propname = "Title";
break;
case SPID_SUBJECT:
sctx->propname = "Subject";
break;
case SPID_AUTHOR:
sctx->propname = "Author";
break;
case SPID_KEYWORDS:
sctx->propname = "Keywords";
break;
case SPID_COMMENTS:
sctx->propname = "Comments";
break;
case SPID_TEMPLATE:
sctx->propname = "Template";
break;
case SPID_LASTAUTHOR:
sctx->propname = "LastAuthor";
break;
case SPID_REVNUMBER:
sctx->propname = "RevNumber";
break;
case SPID_EDITTIME:
sctx->propname = "EditTime";
break;
case SPID_LASTPRINTED:
sctx->propname = "LastPrinted";
break;
case SPID_CREATEDTIME:
sctx->propname = "CreatedTime";
break;
case SPID_MODIFIEDTIME:
sctx->propname = "ModifiedTime";
break;
case SPID_PAGECOUNT:
sctx->propname = "PageCount";
break;
case SPID_WORDCOUNT:
sctx->propname = "WordCount";
break;
case SPID_CHARCOUNT:
sctx->propname = "CharCount";
break;
case SPID_THUMBNAIL:
sctx->propname = "Thumbnail";
break;
case SPID_APPNAME:
sctx->propname = "AppName";
break;
case SPID_SECURITY:
sctx->propname = "Security";
break;
default:
cli_dbgmsg("ole2_translate_summary_propid: unrecognized propid!\n");
sctx->flags |= OLE2_SUMMARY_FLAG_UNKNOWN_PROPID;
}
}
static int ole2_summary_propset_json(summary_ctx_t *sctx, off_t offset)
{
unsigned char *hdr, *ps;
uint32_t numprops, limitprops;
off_t foff = offset, psoff = 0;
uint32_t poffset;
int ret;
unsigned int i;
cli_dbgmsg("in ole2_summary_propset_json\n");
/* summary ctx propset-specific setup*/
sctx->codepage = 0;
sctx->writecp = 0;
sctx->propname = NULL;
/* examine property set metadata */
if ((foff+(2*sizeof(uint32_t))) > sctx->maplen) {
sctx->flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
return CL_EFORMAT;
}
hdr = (unsigned char*)fmap_need_off_once(sctx->sfmap, foff, (2*sizeof(uint32_t)));
if (!hdr) {
sctx->flags |= OLE2_SUMMARY_ERROR_DATABUF;
return CL_EREAD;
}
//foff+=(2*sizeof(uint32_t)); // keep foff pointing to start of propset segment
psoff+=(2*sizeof(uint32_t));
memcpy(&(sctx->pssize), hdr, sizeof(sctx->pssize));
memcpy(&numprops, hdr+sizeof(sctx->pssize), sizeof(numprops));
/* endian conversion */
sctx->pssize = sum32_endian_convert(sctx->pssize);
numprops = sum32_endian_convert(numprops);
cli_dbgmsg("ole2_summary_propset_json: pssize: %u, numprops: %u\n", sctx->pssize, numprops);
if (numprops > PROPCNTLIMIT) {
sctx->flags |= OLE2_SUMMARY_LIMIT_PROPS;
limitprops = PROPCNTLIMIT;
}
else {
limitprops = numprops;
} |
f53bed0b |
if (sctx->propname != NULL) {
ret = ole2_process_property(sctx, ps, propoff);
if (ret != CL_SUCCESS)
return ret;
}
else {
/* add unknown propid flag */
}
}
return CL_SUCCESS;
}
static int cli_ole2_summary_json_cleanup(summary_ctx_t *sctx, int retcode)
{
json_object *jarr;
cli_dbgmsg("in cli_ole2_summary_json_cleanup: %d[%x]\n", retcode, sctx->flags);
if (sctx->sfmap) {
funmap(sctx->sfmap);
}
if (sctx->flags) {
jarr = cli_jsonarray(sctx->summary, "ParseErrors");
/* summary errors */
if (sctx->flags & OLE2_SUMMARY_ERROR_TOOSMALL) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_TOOSMALL");
}
if (sctx->flags & OLE2_SUMMARY_ERROR_OOB) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_OOB");
}
if (sctx->flags & OLE2_SUMMARY_ERROR_DATABUF) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_DATABUF");
}
if (sctx->flags & OLE2_SUMMARY_ERROR_INVALID_ENTRY) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_ERROR_INVALID_ENTRY");
}
if (sctx->flags & OLE2_SUMMARY_LIMIT_PROPS) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_LIMIT_PROPS");
}
if (sctx->flags & OLE2_SUMMARY_FLAG_TIMEOUT) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_TIMEOUT");
}
if (sctx->flags & OLE2_SUMMARY_FLAG_CODEPAGE) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_CODEPAGE");
}
if (sctx->flags & OLE2_SUMMARY_FLAG_UNKNOWN_PROPID) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_UNKNOWN_PROPID");
}
if (sctx->flags & OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_UNHANDLED_PROPTYPE");
}
if (sctx->flags & OLE2_SUMMARY_FLAG_TRUNC_STR) {
cli_jsonstr(jarr, NULL, "OLE2_SUMMARY_FLAG_TRUNC_STR");
}
/* codepage translation errors */
if (sctx->flags & OLE2_CODEPAGE_ERROR_NOTFOUND) {
cli_jsonstr(jarr, NULL, "OLE2_CODEPAGE_ERROR_NOTFOUND");
}
if (sctx->flags & OLE2_CODEPAGE_ERROR_UNINITED) {
cli_jsonstr(jarr, NULL, "OLE2_CODEPAGE_ERROR_UNINITED");
}
if (sctx->flags & OLE2_CODEPAGE_ERROR_INVALID) {
cli_jsonstr(jarr, NULL, "OLE2_CODEPAGE_ERROR_INVALID");
}
if (sctx->flags & OLE2_CODEPAGE_ERROR_INCOMPLETE) {
cli_jsonstr(jarr, NULL, "OLE2_CODEPAGE_ERROR_INCOMPLETE");
}
if (sctx->flags & OLE2_CODEPAGE_ERROR_OUTBUFTOOSMALL) {
cli_jsonstr(jarr, NULL, "OLE2_CODEPAGE_ERROR_OUTBUFTOOSMALL");
}
}
return retcode;
}
int cli_ole2_summary_json(cli_ctx *ctx, int fd, int mode)
{
summary_ctx_t sctx;
STATBUF statbuf;
off_t foff = 0;
unsigned char *databuf;
summary_stub_t sumstub;
propset_entry_t pentry;
int ret = CL_SUCCESS;
cli_dbgmsg("in cli_ole2_summary_json\n");
/* preliminary sanity checks */
if (ctx == NULL) {
return CL_ENULLARG;
}
if (fd < 0) {
cli_dbgmsg("ole2_summary_json: invalid file descriptor\n");
return CL_ENULLARG; /* placeholder */
}
|
f53bed0b |
if (!sctx.summary) {
cli_errmsg("ole2_summary_json: no memory for json object.\n");
return cli_ole2_summary_json_cleanup(&sctx, CL_EMEM);
}
sctx.codepage = 0;
sctx.writecp = 0;
/* acquire property stream metadata */
if (sctx.maplen < sizeof(summary_stub_t)) {
sctx.flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);
}
databuf = (unsigned char*)fmap_need_off_once(sctx.sfmap, foff, sizeof(summary_stub_t));
if (!databuf) {
sctx.flags |= OLE2_SUMMARY_ERROR_DATABUF;
return cli_ole2_summary_json_cleanup(&sctx, CL_EREAD);
}
foff += sizeof(summary_stub_t);
memcpy(&sumstub, databuf, sizeof(summary_stub_t));
/* endian conversion and checks */
sumstub.byte_order = le16_to_host(sumstub.byte_order);
if (sumstub.byte_order != 0xfffe) {
cli_dbgmsg("ole2_summary_json: byteorder 0x%x is invalid\n", sumstub.byte_order);
sctx.flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);;
}
sumstub.version = sum16_endian_convert(sumstub.version); /*unused*/
sumstub.system = sum32_endian_convert(sumstub.system); /*unused*/
sumstub.num_propsets = sum32_endian_convert(sumstub.num_propsets);
if (sumstub.num_propsets != 1 && sumstub.num_propsets != 2) {
cli_dbgmsg("ole2_summary_json: invalid number of property sets\n");
sctx.flags |= OLE2_SUMMARY_ERROR_INVALID_ENTRY;
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);
}
cli_dbgmsg("ole2_summary_json: byteorder 0x%x\n", sumstub.byte_order);
cli_dbgmsg("ole2_summary_json: %u property set(s) detected\n", sumstub.num_propsets);
/* first property set (index=0) is always SummaryInfo or DocSummaryInfo */
if ((sctx.maplen-foff) < sizeof(propset_entry_t)) {
sctx.flags |= OLE2_SUMMARY_ERROR_TOOSMALL;
return cli_ole2_summary_json_cleanup(&sctx, CL_EFORMAT);
}
databuf = (unsigned char*)fmap_need_off_once(sctx.sfmap, foff, sizeof(propset_entry_t));
if (!databuf) {
sctx.flags |= OLE2_SUMMARY_ERROR_DATABUF;
return cli_ole2_summary_json_cleanup(&sctx, CL_EREAD);
}
foff += sizeof(propset_entry_t);
memcpy(&pentry, databuf, sizeof(propset_entry_t));
/* endian conversion */
pentry.offset = sum32_endian_convert(pentry.offset);
if ((ret = ole2_summary_propset_json(&sctx, pentry.offset)) != CL_SUCCESS) {
return cli_ole2_summary_json_cleanup(&sctx, ret);
}
/* second property set (index=1) is always a custom property set (if present) */
if (sumstub.num_propsets == 2) {
cli_jsonbool(ctx->wrkproperty, "HasUserDefinedProperties", 1);
}
return cli_ole2_summary_json_cleanup(&sctx, CL_SUCCESS);
}
#endif /* HAVE_JSON */ |