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(); #if MDB_DEBUG mdb_buffer_dump(kkd, 0, len); #endif pos = 0; while (pos < len) { record_len = mdb_get_int16(kkd, pos); pos += 2; if (mdb_get_option(MDB_DEBUG_PROPS)) { fprintf(stderr, "%02d ",i++); mdb_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 printf("new len = %d\n", names->len); #endif } return names; }
static MdbProperties * mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len) { guint32 record_len, name_len; int pos = 0; int elem, dtype, dsize; gchar *name, *value; MdbProperties *props; int i=0; #if MDB_DEBUG mdb_buffer_dump(kkd, 0, len); #endif pos = 0; 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(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; props->hash = g_hash_table_new(g_str_hash, g_str_equal); while (pos < len) { record_len = mdb_get_int16(kkd, pos); 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_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); mdb_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), g_strdup(kkd[pos + 8] ? "yes" : "no")); } else { g_hash_table_insert(props->hash, g_strdup(name), mdb_col_to_string(mdb, kkd, pos + 8, dtype, dsize)); } g_free(value); pos += record_len; } return props; }
/* * That function takes a raw KKD/MR2 binary buffer, * typically read from LvProp in table MSysbjects * and returns a GPtrArray of MdbProps* */ GArray* mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) { guint32 record_len; guint16 record_type; size_t pos; GPtrArray *names = NULL; MdbProperties *props; GArray *result; #if MDB_DEBUG mdb_buffer_dump(buffer, 0, len); #endif mdb_debug(MDB_DEBUG_PROPS,"starting prop parsing of type %s", buffer); if (strcmp("KKD", buffer) && strcmp("MR2", buffer)) { fprintf(stderr, "Unrecognized format.\n"); mdb_buffer_dump(buffer, 0, len); return NULL; } result = g_array_new(0, 0, sizeof(MdbProperties*)); pos = 4; while (pos < len) { record_len = mdb_get_int32(buffer, pos); record_type = mdb_get_int16(buffer, pos + 4); mdb_debug(MDB_DEBUG_PROPS,"prop chunk type:0x%04x len:%d", record_type, record_len); //mdb_buffer_dump(buffer, pos+4, record_len); switch (record_type) { case 0x80: if (names) free_names(names); names = mdb_read_props_list(mdb, buffer+pos+6, record_len - 6); break; case 0x00: case 0x01: if (!names) { fprintf(stderr,"sequence error!\n"); break; } props = mdb_read_props(mdb, names, buffer+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; }
void dump_ole(MdbTableDef *table, char *colname, char *sargname) { char ole_data[200000]; int len; MdbSarg sarg; char *sargcol, *sargop, *sargval; mdb_bind_column_by_name(table, colname, ole_data, &len); if (sargname) { sargcol = strtok(sargname," "); sargop = strtok(NULL," "); sargval = strtok(NULL," "); printf("col %s op %s val %s\n",sargcol,sargop,sargval); sarg.op = MDB_EQUAL; /* only support = for now, sorry */ strcpy(sarg.value.s, sargval); mdb_add_sarg_by_name(table, sargcol, &sarg); } mdb_rewind_table(table); while (mdb_fetch_row(table)) { mdb_buffer_dump(ole_data, 0, len); printf("---\n"); } }
int mdb_read_row(MdbTableDef *table, unsigned int row) { MdbHandle *mdb = table->entry->mdb; MdbColumn *col; unsigned int i; int row_start; size_t row_size; int delflag, lookupflag; MdbField fields[256]; int num_fields; if (table->num_rows == 0) return 0; if (mdb_find_row(mdb, row, &row_start, &row_size)) { fprintf(stderr, "warning: mdb_find_row failed."); return 0; } delflag = lookupflag = 0; if (row_start & 0x8000) lookupflag++; if (row_start & 0x4000) delflag++; row_start &= OFFSET_MASK; /* remove flags */ #if MDB_DEBUG fprintf(stdout,"Row %d bytes %d to %d %s %s\n", row, row_start, row_start + row_size - 1, lookupflag ? "[lookup]" : "", delflag ? "[delflag]" : ""); #endif if (!table->noskip_del && delflag) { return 0; } num_fields = mdb_crack_row(table, row_start, row_start + row_size - 1, fields); if (!mdb_test_sargs(table, fields, num_fields)) return 0; #if MDB_DEBUG fprintf(stdout,"sarg test passed row %d \n", row); #endif #if MDB_DEBUG mdb_buffer_dump(mdb->pg_buf, row_start, row_size); #endif /* take advantage of mdb_crack_row() to clean up binding */ /* use num_cols instead of num_fields -- bsb 03/04/02 */ for (i = 0; i < table->num_cols; i++) { col = g_ptr_array_index(table->columns,fields[i].colnum); _mdb_attempt_bind(mdb, col, fields[i].is_null, fields[i].start, fields[i].siz); } return 1; }
MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) { MdbTableDef *table; MdbHandle *mdb = entry->mdb; MdbFormatConstants *fmt = mdb->fmt; int 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 */ return NULL; table = mdb_alloc_tabledef(entry); mdb_get_int16(pg_buf, 8); /* len */ table->num_rows = mdb_get_int32(pg_buf, fmt->tab_num_rows_offset); table->num_var_cols = mdb_get_int16(pg_buf, fmt->tab_num_cols_offset-2); table->num_cols = mdb_get_int16(pg_buf, fmt->tab_num_cols_offset); table->num_idxs = mdb_get_int32(pg_buf, fmt->tab_num_idxs_offset); table->num_real_idxs = mdb_get_int32(pg_buf, fmt->tab_num_ridxs_offset); /* grab a copy of the usage map */ pg_row = mdb_get_int32(pg_buf, fmt->tab_usage_map_offset); mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz)); table->usage_map = g_memdup(buf + row_start, table->map_sz); if (mdb_get_option(MDB_DEBUG_USAGE)) mdb_buffer_dump(buf, row_start, table->map_sz); mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d len %d", pg_row >> 8, pg_row & 0xff, row_start, table->map_sz); /* grab a copy of the free space page map */ pg_row = mdb_get_int32(pg_buf, fmt->tab_free_map_offset); mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->freemap_sz)); table->free_usage_map = g_memdup(buf + row_start, table->freemap_sz); mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n", pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz); 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; }
size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size) { guint32 ole_len; void *buf; int row_start; size_t len; ole_len = mdb_get_int32(ole_ptr, 0); mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %02x", ole_len & 0x00ffffff, ole_len >> 24); col->chunk_size = chunk_size; if (ole_len & 0x80000000) { /* inline ole field, if we can satisfy it, then do it */ len = col->cur_value_len - MDB_MEMO_OVERHEAD; if (chunk_size >= len) { if (col->bind_ptr) memcpy(col->bind_ptr, &mdb->pg_buf[col->cur_value_start + MDB_MEMO_OVERHEAD], len); return len; } else { return 0; } } else if (ole_len & 0x40000000) { col->cur_blob_pg_row = mdb_get_int32(ole_ptr, 4); mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %ld", col->cur_blob_pg_row & 0xff, col->cur_blob_pg_row >> 8); if (mdb_find_pg_row(mdb, col->cur_blob_pg_row, &buf, &row_start, &len)) { return 0; } mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); if (col->bind_ptr) { memcpy(col->bind_ptr, buf + row_start, len); if (mdb_get_option(MDB_DEBUG_OLE)) mdb_buffer_dump(col->bind_ptr, 0, 16); } return len; } else if ((ole_len & 0xff000000) == 0) {