Improve OLE-related functions

This commit is contained in:
whydoubt
2005-03-16 12:43:01 +00:00
parent b4d9eb5225
commit e3df6e8fb7
3 changed files with 59 additions and 72 deletions

View File

@@ -1,3 +1,7 @@
Wed Mar 16 06:41:57 CST 2005 Jeff Smith <whydoubt@yahoo.com>
* include/mdbtools.h:
* src/libmdb/data.c: Improve OLE-related functions
Sun Mar 13 15:22:11 CST 2005 Jeff Smith <whydoubt@yahoo.com> Sun Mar 13 15:22:11 CST 2005 Jeff Smith <whydoubt@yahoo.com>
* src/util/mdb-export.c: * src/util/mdb-export.c:
* src/util/mdb-ver.c: Fix a couple of leaks * src/util/mdb-ver.c: Fix a couple of leaks

View File

@@ -277,8 +277,7 @@ typedef struct {
int cur_value_start; int cur_value_start;
int cur_value_len; int cur_value_len;
/* MEMO/OLE readers */ /* MEMO/OLE readers */
guint32 cur_blob_pg; guint32 cur_blob_pg_row;
int cur_blob_row;
int chunk_size; int chunk_size;
/* numerics only */ /* numerics only */
int col_prec; int col_prec;

View File

@@ -326,7 +326,7 @@ int mdb_read_next_dpg(MdbTableDef *table)
do { do {
if (!mdb_read_pg(mdb, table->cur_phys_pg++)) if (!mdb_read_pg(mdb, table->cur_phys_pg++))
return 0; return 0;
} while (mdb->pg_buf[0]!=0x01 || mdb_pg_get_int32(mdb, 4)!=entry->table_pg); } while (mdb->pg_buf[0]!=0x01 || mdb_get_int32(mdb->pg_buf, 4)!=entry->table_pg);
/* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */ /* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */
return table->cur_phys_pg; return table->cur_phys_pg;
} }
@@ -381,7 +381,7 @@ mdb_fetch_row(MdbTableDef *table)
} }
mdb_read_pg(mdb, pg); mdb_read_pg(mdb, pg);
} else { } else {
rows = mdb_pg_get_int16(mdb,fmt->row_count_offset); rows = mdb_get_int16(mdb->pg_buf,fmt->row_count_offset);
/* if at end of page, find a new page */ /* if at end of page, find a new page */
if (table->cur_row >= rows) { if (table->cur_row >= rows) {
@@ -440,32 +440,25 @@ int i;
int int
mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr)
{ {
guint16 ole_len; guint32 ole_len;
guint16 ole_flags;
char *buf; char *buf;
int pg_row, row_start; int pg_row, row_start;
int len; int len;
ole_len = mdb_get_int16(ole_ptr, 0); ole_len = mdb_get_int32(ole_ptr, 0);
ole_flags = mdb_get_int16(ole_ptr, 2);
if (ole_flags == 0x8000) { if ((ole_len & 0x80000000)
/* inline fields don't have a next */ || (ole_len & 0x40000000)) {
/* inline or single-page fields don't have a next */
return 0; return 0;
} else if (ole_flags == 0x4000) { } else {
/* 0x4000 flagged ole's are contained on one page and thus if (mdb_find_pg_row(mdb, col->cur_blob_pg_row,
* should be handled entirely with mdb_ole_read() */ &buf, &row_start, &len)) {
return 0;
} else if (ole_flags == 0x0000) {
pg_row = (col->cur_blob_pg << 8) & col->cur_blob_row;
if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) {
return 0; return 0;
} }
if (col->bind_ptr) if (col->bind_ptr)
memcpy(col->bind_ptr, buf + row_start, len); memcpy(col->bind_ptr, buf + row_start + 4, len - 4);
pg_row = mdb_get_int32(buf, row_start); col->cur_blob_pg_row = mdb_get_int32(buf, row_start);
col->cur_blob_pg = pg_row >> 8;
col->cur_blob_row = pg_row & 0xff;
return len; return len;
} }
@@ -474,20 +467,18 @@ mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr)
int int
mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size) mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size)
{ {
guint16 ole_len; guint32 ole_len;
guint16 ole_flags;
char *buf; char *buf;
int pg_row, row_start; int pg_row, row_start;
int len; int len;
ole_len = mdb_get_int16(ole_ptr, 0); ole_len = mdb_get_int32(ole_ptr, 0);
ole_flags = mdb_get_int16(ole_ptr, 2); mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %02x",
mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %08x", ole_len & 0x00ffffff, ole_len >> 24);
ole_len, ole_flags);
col->chunk_size = chunk_size; col->chunk_size = chunk_size;
if (ole_flags == 0x8000) { if (ole_len & 0x80000000) {
/* inline ole field, if we can satisfy it, then do it */ /* inline ole field, if we can satisfy it, then do it */
len = col->cur_value_len - MDB_MEMO_OVERHEAD; len = col->cur_value_len - MDB_MEMO_OVERHEAD;
if (chunk_size >= len) { if (chunk_size >= len) {
@@ -500,14 +491,14 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size)
} else { } else {
return 0; return 0;
} }
} else if (ole_flags == 0x4000) { } else if (ole_len & 0x40000000) {
pg_row = mdb_get_int32(ole_ptr, 4); col->cur_blob_pg_row = mdb_get_int32(ole_ptr, 4);
col->cur_blob_pg = pg_row >> 8;
col->cur_blob_row = pg_row & 0xff;
mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %ld", mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %ld",
col->cur_blob_row, col->cur_blob_pg); col->cur_blob_pg_row & 0xff,
col->cur_blob_pg_row >> 8);
if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { if (mdb_find_pg_row(mdb, col->cur_blob_pg_row,
&buf, &row_start, &len)) {
return 0; return 0;
} }
mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len);
@@ -518,35 +509,29 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size)
buffer_dump(col->bind_ptr, 0, 16); buffer_dump(col->bind_ptr, 0, 16);
} }
return len; return len;
} else if (ole_flags == 0x0000) { } else if (ole_len & 0xff000000 == 0) {
pg_row = mdb_get_int32(ole_ptr, 4); col->cur_blob_pg_row = mdb_get_int32(ole_ptr, 4);
col->cur_blob_pg = pg_row >> 8;
col->cur_blob_row = pg_row & 0xff;
if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { if (mdb_find_pg_row(mdb, col->cur_blob_pg_row,
&buf, &row_start, &len)) {
return 0; return 0;
} }
if (col->bind_ptr) if (col->bind_ptr)
memcpy(col->bind_ptr, buf + row_start, len); memcpy(col->bind_ptr, buf + row_start + 4, len - 4);
col->cur_blob_pg_row = mdb_get_int32(buf, row_start);
pg_row = mdb_get_int32(buf, row_start);
col->cur_blob_pg = pg_row >> 8;
col->cur_blob_row = pg_row & 0xff;
return len; return len;
} else { } else {
fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); fprintf(stderr,"Unhandled ole field flags = %02x\n", ole_len >> 24);
return 0; return 0;
} }
} }
int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size) int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
{ {
guint16 ole_len; guint32 ole_len;
guint16 ole_flags;
guint32 row_start, pg_row; guint32 row_start, pg_row;
guint32 len; guint32 len;
char *buf; char *buf, *pg_buf = mdb->pg_buf;
if (size<MDB_MEMO_OVERHEAD) { if (size<MDB_MEMO_OVERHEAD) {
return 0; return 0;
@@ -555,17 +540,16 @@ int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
/* The 16 bit integer at offset 0 is the length of the memo field. /* The 16 bit integer at offset 0 is the length of the memo field.
* The 32 bit integer at offset 4 contains page and row information. * The 32 bit integer at offset 4 contains page and row information.
*/ */
ole_len = mdb_pg_get_int16(mdb, start); ole_len = mdb_get_int32(pg_buf, start);
ole_flags = mdb_pg_get_int16(mdb, start+2);
if (ole_flags == 0x8000) { if (ole_len & 0x80000000) {
/* inline */
len = size - MDB_MEMO_OVERHEAD; len = size - MDB_MEMO_OVERHEAD;
/* inline ole field */ if (dest) memcpy(dest, pg_buf + start + MDB_MEMO_OVERHEAD, len);
if (dest) memcpy(dest, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
size - MDB_MEMO_OVERHEAD);
return len; return len;
} else if (ole_flags == 0x4000) { } else if (ole_len & 0x40000000) {
pg_row = mdb_get_int32(mdb->pg_buf, start+4); /* single page */
pg_row = mdb_get_int32(pg_buf, start+4);
mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8);
if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) {
@@ -577,11 +561,14 @@ int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
if (dest) if (dest)
memcpy(dest, buf + row_start, len); memcpy(dest, buf + row_start, len);
return len; return len;
} else if (ole_flags == 0x0000) { } else if (ole_len & 0xff000000 == 0) { // assume all flags in MSB
/* multi-page */
int cur = 0; int cur = 0;
pg_row = mdb_get_int32(mdb->pg_buf, start+4); pg_row = mdb_get_int32(pg_buf, start+4);
mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8);
do { do {
mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x",
pg_row >> 8);
if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) {
return 0; return 0;
} }
@@ -598,7 +585,7 @@ int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
} while ((pg_row >> 8)); } while ((pg_row >> 8));
return cur; return cur;
} else { } else {
fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); fprintf(stderr, "Unhandled ole field flags = %02x\n", ole_len >> 24);
return 0; return 0;
} }
} }
@@ -607,7 +594,7 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
guint32 memo_len; guint32 memo_len;
guint32 row_start, pg_row; guint32 row_start, pg_row;
guint32 len; guint32 len;
char *buf; char *buf, *pg_buf = mdb->pg_buf;
char *text = (char *) g_malloc(MDB_BIND_SIZE); char *text = (char *) g_malloc(MDB_BIND_SIZE);
if (size<MDB_MEMO_OVERHEAD) { if (size<MDB_MEMO_OVERHEAD) {
@@ -616,23 +603,23 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
} }
#if MDB_DEBUG #if MDB_DEBUG
buffer_dump(mdb->pg_buf, start, start + MDB_MEMO_OVERHEAD - 1); buffer_dump(pg_buf, start, start + MDB_MEMO_OVERHEAD - 1);
#endif #endif
/* The 32 bit integer at offset 0 is the length of the memo field /* The 32 bit integer at offset 0 is the length of the memo field
* with some flags in the high bits. * with some flags in the high bits.
* The 32 bit integer at offset 4 contains page and row information. * The 32 bit integer at offset 4 contains page and row information.
*/ */
memo_len = mdb_pg_get_int32(mdb, start); memo_len = mdb_get_int32(pg_buf, start);
if (memo_len & 0x80000000) { if (memo_len & 0x80000000) {
/* inline memo field */ /* inline memo field */
mdb_unicode2ascii(mdb, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], mdb_unicode2ascii(mdb, pg_buf + start + MDB_MEMO_OVERHEAD,
size - MDB_MEMO_OVERHEAD, text, MDB_BIND_SIZE); size - MDB_MEMO_OVERHEAD, text, MDB_BIND_SIZE);
return text; return text;
} else if (memo_len & 0x40000000) { } else if (memo_len & 0x40000000) {
/* single-page memo field */ /* single-page memo field */
pg_row = mdb_get_int32(mdb->pg_buf, start+4); pg_row = mdb_get_int32(pg_buf, start+4);
#if MDB_DEBUG #if MDB_DEBUG
printf("Reading LVAL page %06x\n", pg_row >> 8); printf("Reading LVAL page %06x\n", pg_row >> 8);
#endif #endif
@@ -647,14 +634,13 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
#endif #endif
mdb_unicode2ascii(mdb, buf + row_start, len, text, MDB_BIND_SIZE); mdb_unicode2ascii(mdb, buf + row_start, len, text, MDB_BIND_SIZE);
return text; return text;
} else { } else if (memo_len & 0xff000000 == 0) { // assume all flags in MSB
/* multi-page memo field */ /* multi-page memo field */
guint32 tmpoff = 0; guint32 tmpoff = 0;
char *tmp; char *tmp;
memo_len &= 0x3fffffff;
tmp = (char *) g_malloc(memo_len); tmp = (char *) g_malloc(memo_len);
pg_row = mdb_get_int32(mdb->pg_buf, start+4); pg_row = mdb_get_int32(pg_buf, start+4);
do { do {
#if MDB_DEBUG #if MDB_DEBUG
printf("Reading LVAL page %06x\n", pg_row >> 8); printf("Reading LVAL page %06x\n", pg_row >> 8);
@@ -680,11 +666,9 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
mdb_unicode2ascii(mdb, tmp, tmpoff, text, MDB_BIND_SIZE); mdb_unicode2ascii(mdb, tmp, tmpoff, text, MDB_BIND_SIZE);
g_free(tmp); g_free(tmp);
return text; return text;
/*
} else { } else {
fprintf(stderr,"Unhandled memo field flags = %04x\n", memo_flags); fprintf(stderr, "Unhandled memo field flags = %02x\n", memo_len >> 24);
return ""; return "";
*/
} }
} }
static char * static char *