patch 'props' from Nirgal Vourgère

This commit is contained in:
Brian Bruns
2011-02-16 18:58:02 -05:00
parent fa83ed0af0
commit 6696edf1f8
10 changed files with 198 additions and 278 deletions

View File

@@ -1,5 +1,5 @@
lib_LTLIBRARIES = libmdb.la
libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c
libmdb_la_SOURCES= catalog.c mem.c file.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c
libmdb_la_LDFLAGS = -version-info 1:0:0
AM_CPPFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS)
LIBS = $(GLIB_LIBS) @LIBS@

View File

@@ -63,10 +63,14 @@ GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtype)
MdbCatalogEntry *entry, msysobj;
MdbTableDef *table;
char obj_id[256];
char obj_name[256];
char obj_name[MDB_MAX_OBJ_NAME];
char obj_type[256];
char obj_flags[256];
char obj_props[MDB_BIND_SIZE];
int type;
unsigned int i;
MdbColumn *col_props;
int kkd_size_ole;
if (!mdb) return NULL;
if (mdb->catalog) mdb_free_catalog(mdb);
@@ -91,14 +95,16 @@ GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtype)
mdb_bind_column_by_name(table, "Name", obj_name, NULL);
mdb_bind_column_by_name(table, "Type", obj_type, NULL);
mdb_bind_column_by_name(table, "Flags", obj_flags, NULL);
i = mdb_bind_column_by_name(table, "LvProp", obj_props, &kkd_size_ole);
col_props = g_ptr_array_index(table->columns, i-1);
mdb_rewind_table(table);
while (mdb_fetch_row(table)) {
type = atoi(obj_type);
if (objtype==MDB_ANY || type == objtype) {
// fprintf(stdout, "obj_id: %10ld objtype: %-3d obj_name: %s\n",
// (atol(obj_id) & 0x00FFFFFF), type, obj_name);
//fprintf(stderr, "obj_id: %10ld objtype: %-3d (0x%04x) obj_name: %s\n",
// (atol(obj_id) & 0x00FFFFFF), type, type, obj_name);
entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry));
entry->mdb = mdb;
strcpy(entry->object_name, obj_name);
@@ -106,7 +112,14 @@ GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtype)
entry->table_pg = atol(obj_id) & 0x00FFFFFF;
entry->flags = atol(obj_flags);
mdb->num_catalog++;
g_ptr_array_add(mdb->catalog, entry);
g_ptr_array_add(mdb->catalog, entry);
if (kkd_size_ole) {
size_t kkd_len;
void *kkd = mdb_ole_read_full(mdb, col_props, &kkd_len);
//buffer_dump(kkd, 0, kkd_len);
entry->props = kkd_to_props(mdb, kkd, kkd_len);
free(kkd);
}
}
}
//mdb_dump_catalog(mdb, MDB_TABLE);
@@ -126,14 +139,12 @@ mdb_dump_catalog(MdbHandle *mdb, int obj_type)
for (i=0;i<mdb->num_catalog;i++) {
entry = g_ptr_array_index(mdb->catalog,i);
if (obj_type==MDB_ANY || entry->object_type==obj_type) {
fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x KKD pg: %04x row: %2d\n",
fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x",
mdb_get_objtype_string(entry->object_type),
entry->object_name,
(unsigned int) entry->table_pg,
(unsigned int) entry->kkd_pg,
entry->kkd_rowid);
(unsigned int) entry->table_pg);
}
}
}
return;
}

View File

@@ -1,151 +0,0 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "mdbtools.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
/*
** Note: This code is mostly garbage right now...just a test to parse out the
** KKD structures.
*/
static GArray *mdb_get_column_props(MdbCatalogEntry *entry, int start)
{
int pos, cnt=0;
int len, tmp, cplen;
MdbColumnProp prop;
MdbHandle *mdb = entry->mdb;
entry->props = g_array_new(FALSE,FALSE,sizeof(MdbColumnProp));
len = mdb_pg_get_int16(mdb,start);
pos = start + 6;
while (pos < start+len) {
tmp = mdb_pg_get_int16(mdb,pos); /* length of string */
pos += 2;
cplen = tmp > MDB_MAX_OBJ_NAME ? MDB_MAX_OBJ_NAME : tmp;
g_memmove(prop.name,&mdb->pg_buf[pos],cplen);
prop.name[cplen]='\0';
pos += tmp;
g_array_append_val(entry->props, prop.name);
cnt++;
}
entry->num_props = cnt;
return entry->props;
}
static GHashTable *mdb_get_column_def(MdbCatalogEntry *entry, int start)
{
GHashTable *hash = NULL;
MdbHandle *mdb = entry->mdb;
MdbColumnProp prop;
int tmp, pos, col_num, val_len, i;
int len, col_type;
unsigned char c;
int end;
fprintf(stdout,"\n data\n");
fprintf(stdout,"-------\n");
len = mdb_pg_get_int16(mdb,start);
fprintf(stdout,"length = %3d\n",len);
pos = start + 6;
end = start + len;
while (pos < end) {
fprintf(stdout,"pos = %3d\n",pos);
start = pos;
tmp = mdb_pg_get_int16(mdb,pos); /* length of field */
pos += 2;
col_type = mdb_pg_get_int16(mdb,pos); /* ??? */
pos += 2;
col_num = 0;
if (col_type) {
col_num = mdb_pg_get_int16(mdb,pos);
pos += 2;
}
val_len = mdb_pg_get_int16(mdb,pos);
pos += 2;
fprintf(stdout,"length = %3d %04x %2d %2d ",tmp, col_type, col_num, val_len);
for (i=0;i<val_len;i++) {
c = mdb->pg_buf[pos+i];
if (isprint(c))
fprintf(stdout," %c",c);
else
fprintf(stdout," %02x",c);
}
pos = start + tmp;
prop = g_array_index(entry->props,MdbColumnProp,col_num);
fprintf(stdout," Property %s",prop.name);
fprintf(stdout,"\n");
}
return hash;
}
void mdb_kkd_dump(MdbCatalogEntry *entry)
{
int rows;
int kkd_start, kkd_end;
int i, tmp, pos, row_type, datapos=0;
MdbColumnProp prop;
MdbHandle *mdb = entry->mdb;
int rowid = entry->kkd_rowid;
fprintf(stdout, "kkd_pg=%d kkd_rowid=%d\n", entry->kkd_pg, rowid);
mdb_read_pg(mdb, entry->kkd_pg);
rows = mdb_get_int16(mdb->pg_buf, 8);
fprintf(stdout,"number of rows = %d\n",rows);
kkd_start = mdb_get_int16(mdb->pg_buf, 10+rowid*2);
fprintf(stdout,"kkd start = %d 0x%04x\n",kkd_start,kkd_start);
kkd_end = mdb->fmt->pg_size;
for (i=0;i<rows;i++) {
tmp = mdb_get_int16(mdb->pg_buf, 10+i*2);
if (tmp < mdb->fmt->pg_size &&
tmp > kkd_start &&
tmp < kkd_end) {
kkd_end = tmp;
}
}
fprintf(stdout,"kkd end = %d 0x%04x\n",kkd_end,kkd_end);
pos = kkd_start + 4; /* 4 = K K D \0 */
while (pos < kkd_end) {
tmp = mdb_pg_get_int16(mdb,pos);
row_type = mdb_pg_get_int16(mdb,pos+4);
fprintf(stdout,"row size = %3d type = 0x%02x\n",tmp,row_type);
if (row_type==0x80) {
fprintf(stdout,"\nColumn Properties\n");
fprintf(stdout,"-----------------\n");
mdb_get_column_props(entry,pos);
for (i=0;i<entry->num_props;i++) {
prop = g_array_index(entry->props,MdbColumnProp,i);
fprintf(stdout,"%3d %s\n",i,prop.name);
}
}
if (row_type==0x01) datapos = pos;
pos += tmp;
}
if (datapos) {
mdb_get_column_def(entry, datapos);
}
}

View File

@@ -44,9 +44,9 @@ mdb_debug(int klass, char *fmt, ...)
if (!optset) load_options();
if (klass & opts) {
va_start(ap, fmt);
vfprintf (stdout,fmt, ap);
vfprintf (stderr,fmt, ap);
va_end(ap);
fprintf(stdout,"\n");
fprintf(stderr,"\n");
}
#endif
}
@@ -59,7 +59,7 @@ load_options()
if (!optset && (s=getenv("MDBOPTS"))) {
opt = strtok(s, ":");
do {
while (opt) {
if (!strcmp(opt, "use_index")) opts |= MDB_USE_INDEX;
if (!strcmp(opt, "no_memo")) opts |= MDB_NO_MEMO;
if (!strcmp(opt, "debug_like")) opts |= MDB_DEBUG_LIKE;
@@ -67,15 +67,17 @@ load_options()
if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE;
if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE;
if (!strcmp(opt, "debug_row")) opts |= MDB_DEBUG_ROW;
if (!strcmp(opt, "debug_props")) opts |= MDB_DEBUG_PROPS;
if (!strcmp(opt, "debug_all")) {
opts |= MDB_DEBUG_LIKE;
opts |= MDB_DEBUG_WRITE;
opts |= MDB_DEBUG_USAGE;
opts |= MDB_DEBUG_OLE;
opts |= MDB_DEBUG_ROW;
opts |= MDB_DEBUG_PROPS;
}
opt = strtok(NULL,":");
} while (opt);
}
}
optset = 1;
}

View File

@@ -1,5 +1,5 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
* Copyright (C) 2000-2011 Brian Bruns and others
*
*
* This library is free software; you can redistribute it and/or
@@ -20,16 +20,16 @@
#include "mdbtools.h"
GPtrArray *
mdb_read_props_list(gchar *kkd, int len)
static GPtrArray *
mdb_read_props_list(MdbHandle *mdb, gchar *kkd, int len)
{
guint32 record_len;
int pos = 0;
gchar *name;
GPtrArray *names = NULL;
int i = 0;
names = g_ptr_array_new();
int i=0;
#if MDB_DEBUG
buffer_dump(kkd, 0, len);
#endif
@@ -37,13 +37,13 @@ mdb_read_props_list(gchar *kkd, int len)
while (pos < len) {
record_len = mdb_get_int16(kkd, pos);
pos += 2;
#if MDB_DEBUG
printf("%02d ",i++);
buffer_dump(kkd, pos - 2, record_len + 2);
#endif
name = g_malloc(record_len + 1);
strncpy(name, &kkd[pos], record_len);
name[record_len] = '\0';
if (mdb_get_option(MDB_DEBUG_PROPS)) {
fprintf(stderr, "%02d ",i++);
buffer_dump(kkd, pos - 2, record_len + 2);
}
name = g_malloc(3*record_len + 1); /* worst case scenario is 3 bytes out per byte in */
mdb_unicode2ascii(mdb, &kkd[pos], record_len, name, 3*record_len);
pos += record_len;
g_ptr_array_add(names, name);
#if MDB_DEBUG
@@ -60,6 +60,12 @@ mdb_free_props(MdbProperties *props)
if (props->name) g_free(props->name);
g_free(props);
}
static void
free_names(GPtrArray *names) {
g_ptr_array_foreach(names, (GFunc)g_free, NULL);
g_ptr_array_free(names, TRUE);
}
MdbProperties *
mdb_alloc_props()
{
@@ -69,7 +75,7 @@ mdb_alloc_props()
return props;
}
MdbProperties *
static MdbProperties *
mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len)
{
guint32 record_len, name_len;
@@ -77,23 +83,22 @@ mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len)
int elem, dtype, dsize;
gchar *name, *value;
MdbProperties *props;
int i = 0;
int i=0;
#if MDB_DEBUG
buffer_dump(kkd, 0, len);
#endif
pos = 0;
/* skip the name record */
record_len = mdb_get_int16(kkd, pos);
pos += 4;
name_len = mdb_get_int16(kkd, pos);
pos += 2;
props = mdb_alloc_props();
if (name_len) {
props->name = g_malloc(name_len + 1);
strncpy(props->name, &kkd[pos], name_len);
props->name[name_len]='\0';
props->name = g_malloc(3*name_len + 1);
mdb_unicode2ascii(mdb, kkd+pos, name_len, props->name, 3*name_len);
mdb_debug(MDB_DEBUG_PROPS,"prop block named: %s", props->name);
}
pos += name_len;
@@ -101,18 +106,18 @@ mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len)
while (pos < len) {
record_len = mdb_get_int16(kkd, pos);
elem = mdb_get_int16(kkd, pos + 4);
dtype = kkd[pos + 3];
elem = mdb_get_int16(kkd, pos + 4);
dsize = mdb_get_int16(kkd, pos + 6);
value = g_malloc(dsize + 1);
strncpy(value, &kkd[pos + 8], dsize);
value[dsize] = '\0';
name = g_ptr_array_index(names,elem);
#if MDB_DEBUG
printf("%02d ",i++);
buffer_dump(kkd, pos, record_len);
printf("elem %d dsize %d dtype %d\n", elem, dsize, dtype);
#endif
if (mdb_get_option(MDB_DEBUG_PROPS)) {
fprintf(stderr, "%02d ",i++);
mdb_debug(MDB_DEBUG_PROPS,"elem %d (%s) dsize %d dtype %d", elem, name, dsize, dtype);
buffer_dump(value, 0, dsize);
}
if (dtype == MDB_MEMO) dtype = MDB_TEXT;
if (dtype == MDB_BOOL) {
g_hash_table_insert(props->hash, g_strdup(name),
@@ -127,3 +132,68 @@ mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len)
return props;
}
static void
print_keyvalue(gpointer key, gpointer value, gpointer outfile)
{
fprintf((FILE*)outfile,"\t%s: %s\n", (gchar *)key, (gchar *)value);
}
void
mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name) {
if (show_name)
fprintf(outfile,"name: %s\n", props->name ? props->name : "(none)");
g_hash_table_foreach(props->hash, print_keyvalue, outfile);
if (show_name)
fputc('\n', outfile);
}
GArray*
kkd_to_props(MdbHandle *mdb, void *kkd, size_t len) {
guint32 record_len;
guint16 record_type;
size_t pos;
GPtrArray *names = NULL;
MdbProperties *props;
#if MDB_DEBUG
buffer_dump(kkd, 0, len);
#endif
mdb_debug(MDB_DEBUG_PROPS,"starting prop parsing of type %s", kkd);
if (strcmp("KKD", kkd) && strcmp("MR2", kkd)) {
fprintf(stderr, "Unrecognized format.\n");
buffer_dump(kkd, 0, len);
return NULL;
}
GArray *result = g_array_new(0, 0, sizeof(MdbProperties*));
pos = 4;
while (pos < len) {
record_len = mdb_get_int32(kkd, pos);
record_type = mdb_get_int16(kkd, pos + 4);
mdb_debug(MDB_DEBUG_PROPS,"prop chunk type:0x%04x len:%d", record_type, record_len);
//buffer_dump(kkd, pos+4, record_len);
switch (record_type) {
case 0x80:
if (names) free_names(names);
names = mdb_read_props_list(mdb, kkd+pos+6, record_len - 6);
break;
case 0x00:
case 0x01:
if (!names) {
fprintf(stderr,"sequence error!\n");
break;
}
props = mdb_read_props(mdb, names, kkd+pos+6, record_len - 6);
g_array_append_val(result, props);
//mdb_dump_props(props, stderr, 1);
break;
default:
fprintf(stderr,"Unknown record type %d\n", record_type);
break;
}
pos += record_len;
}
if (names) free_names(names);
return result;
}

View File

@@ -78,6 +78,7 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
MdbFormatConstants *fmt = mdb->fmt;
int len, row_start, pg_row;
void *buf, *pg_buf = mdb->pg_buf;
guint i;
mdb_read_pg(mdb, entry->table_pg);
if (mdb_get_byte(pg_buf, 0) != 0x02) /* not a valid table def page */
@@ -110,6 +111,13 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
table->first_data_pg = mdb_get_int16(pg_buf, fmt->tab_first_dpg_offset);
if (entry->props)
for (i=0; i<entry->props->len; ++i) {
MdbProperties *props = g_array_index(entry->props, MdbProperties*, i);
if (!props->name)
table->props = props;
}
return table;
}
MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type)
@@ -205,7 +213,7 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
MdbFormatConstants *fmt = mdb->fmt;
MdbColumn *pcol;
unsigned char *col;
unsigned int i;
unsigned int i, j;
int cur_pos;
size_t name_sz;
@@ -291,11 +299,25 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
mdb_unicode2ascii(mdb, tmp_buf, name_sz, pcol->name, MDB_MAX_OBJ_NAME);
g_free(tmp_buf);
}
/* Sort the columns by col_num */
g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer);
GArray *allprops = table->entry->props;
if (allprops)
for (i=0;i<table->num_cols;i++) {
pcol = g_ptr_array_index(table->columns, i);
for (j=0; j<allprops->len; ++j) {
MdbProperties *props = g_array_index(allprops, MdbProperties*, j);
if (props->name && pcol->name && !strcmp(props->name, pcol->name)) {
pcol->props = props;
break;
}
}
}
table->index_start = cur_pos;
return table->columns;
}
@@ -316,6 +338,8 @@ guint32 pgnum;
fprintf(stdout,"number of columns = %d\n",table->num_cols);
fprintf(stdout,"number of indices = %d\n",table->num_real_idxs);
if (table->props)
mdb_dump_props(table->props, stdout, 0);
mdb_read_columns(table);
mdb_read_indices(table);
@@ -326,6 +350,8 @@ guint32 pgnum;
i, col->name,
mdb_get_coltype_string(mdb->default_backend, col->col_type),
col->col_size);
if (col->props)
mdb_dump_props(col->props, stdout, 0);
}
for (i=0;i<table->num_idxs;i++) {
@@ -370,3 +396,17 @@ int mdb_is_system_table(MdbCatalogEntry *entry)
return ((entry->object_type == MDB_TABLE)
&& (entry->flags & 0x80000002)) ? 1 : 0;
}
const char *
mdb_table_get_prop(const MdbTableDef *table, const gchar *key) {
if (!table->props)
return NULL;
return g_hash_table_lookup(table->props->hash, key);
}
const char *
mdb_col_get_prop(const MdbColumn *col, const gchar *key) {
if (!col->props)
return NULL;
return g_hash_table_lookup(col->props->hash, key);
}

View File

@@ -2,7 +2,7 @@ include_HEADERS = connectparams.h
SQLDIR = ../sql
SQLSOURCES = mdbsql.c parser.c lexer.c
MDBDIR = ../libmdb
MDBSOURCES = backend.c index.c money.c catalog.c kkd.c sargs.c \
MDBSOURCES = backend.c index.c money.c catalog.c sargs.c \
data.c like.c table.c dump.c file.c mem.c \
map.c props.c worktable.c options.c \
write.c stats.c iconv.c

View File

@@ -1,5 +1,5 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
* Copyright (C) 2000-2011 Brian Bruns and others
*
*
* This library is free software; you can redistribute it and/or
@@ -80,7 +80,7 @@ main(int argc, char **argv)
}
if (found) {
MdbColumn *col = g_ptr_array_index(table->columns, col_num - 1);
MdbColumn *col = g_ptr_array_index(table->columns, col_num-1);
size_t size;
void *kkd = mdb_ole_read_full(mdb, col, &size);
dump_kkd(mdb, kkd, size);
@@ -94,64 +94,12 @@ main(int argc, char **argv)
return 0;
}
void print_keyvalue(gpointer key, gpointer value, gpointer user_data)
{
printf("%s = %s\n", (gchar *)key, (gchar *)value);
}
void dump_kkd(MdbHandle *mdb, void *kkd, size_t len)
{
guint32 record_len;
guint16 record_type;
size_t pos;
GPtrArray *names = NULL;
MdbProperties *props;
#if MDB_DEBUG
buffer_dump(kkd, 0, len);
#endif
if (strcmp("KKD", kkd)) {
fprintf(stderr, "Unrecognized format.\n");
buffer_dump(kkd, 0, len);
return;
}
pos = 4;
while (pos < len) {
record_len = mdb_get_int32(kkd, pos);
record_type = mdb_get_int16(kkd, pos + 4);
//printf("len = %d type = %d\n", record_len, record_type);
switch (record_type) {
case 0x80:
names = mdb_read_props_list(kkd+pos+6, record_len - 6);
break;
case 0x00:
if (!names) {
printf("sequence error!\n");
break;
}
props = mdb_read_props(mdb, names, kkd+pos+6, record_len - 6);
printf("type 0x00 name %s\n", props->name ? props->name : "(none)");
g_hash_table_foreach(props->hash, print_keyvalue, NULL);
putchar('\n');
mdb_free_props(props);
break;
case 0x01:
if (!names) {
printf("sequence error!\n");
break;
}
props = mdb_read_props(mdb, names, kkd+pos+6, record_len - 6);
printf("type 0x01 name %s\n", props->name ? props->name : "(none)");
g_hash_table_foreach(props->hash, print_keyvalue, NULL);
putchar('\n');
mdb_free_props(props);
break;
default:
fprintf(stderr,"Unknown record type %d\n", record_type);
return;
}
pos += record_len;
GArray *aprops = kkd_to_props(mdb, kkd, len);
int i;
for (i=0; i<aprops->len; ++i) {
MdbProperties *props = g_array_index(aprops, MdbProperties*, i);
mdb_dump_props(props, stdout, 1);
}
}