/* * ole_ptr should point to the original blob value of the field. * If omited, there will be no multi-page check to that the caller is * responsible for not calling this function. Then, it doesn't have to * preserve the original value. */ size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) { guint32 ole_len; void *buf; int row_start; size_t len; if (ole_ptr) { 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); if ((ole_len & 0x80000000) || (ole_len & 0x40000000)) /* inline or single-page fields don't have a next */ return 0; } mdb_debug(MDB_DEBUG_OLE, "pg_row %d", col->cur_blob_pg_row); if (!col->cur_blob_pg_row) return 0; /* we are done */ 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 + 4, len - 4); col->cur_blob_pg_row = mdb_get_int32(buf, row_start); return len - 4; }
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; }
/** * mdb_like_cmp * @s: String to search within. * @r: Search pattern. * * Tests the string @s to see if it matches the search pattern @r. In the * search pattern, a percent sign indicates matching on any number of * characters, and an underscore indicates matching any single character. * * Returns: 1 if the string matches, 0 if the string does not match. */ int mdb_like_cmp(char *s, char *r) { unsigned int i; int ret; mdb_debug(MDB_DEBUG_LIKE, "comparing %s and %s", s, r); switch (r[0]) { case '\0': if (s[0]=='\0') { return 1; } else { return 0; } case '_': /* skip one character */ return mdb_like_cmp(&s[1],&r[1]); case '%': /* skip any number of characters */ /* the strlen(s)+1 is important so the next call can */ /* if there are trailing characters */ for(i=0;i<strlen(s)+1;i++) { if (mdb_like_cmp(&s[i],&r[1])) { return 1; } } return 0; default: for(i=0;i<strlen(r);i++) { if (r[i]=='_' || r[i]=='%') break; } if (strncmp(s,r,i)) { return 0; } else { mdb_debug(MDB_DEBUG_LIKE, "at pos %d comparing %s and %s", i, &s[i], &r[i]); ret = mdb_like_cmp(&s[i],&r[i]); mdb_debug(MDB_DEBUG_LIKE, "returning %d (%s and %s)", ret, &s[i], &r[i]); return ret; } } }
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 ((size_t)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, (char*)buf + row_start, len); if (mdb_get_option(MDB_DEBUG_OLE)) buffer_dump(col->bind_ptr, 0, 16); } return len; } else if ((ole_len & 0xff000000) == 0) {