+
+ printf("\033[32m\033[1mFloor: %s\033[0m\n", floor64->f_name);
+}
+
+
+// convert function for a msglist or a fulltext index record
+// (both are indexed by a long and the data is arrays of longs)
+void convert_msglists(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+ int i;
+
+ char *table = (which_cdb == CDB_FULLTEXT) ? "FullText" : "Msglist";
+
+ // records are indexed by a single "long" and contains an array of zero or more "long"s
+ // and remember ... "long" is int32_t on the source system
+ int32_t in_roomnum;
+ long out_roomnum;
+ memcpy(&in_roomnum, in_key->data, sizeof(in_roomnum));
+ out_roomnum = (long) in_roomnum;
+
+ if (in_key->size != 4) {
+ printf("\033[31m\033[1m *** SOURCE DATABASE IS NOT 32-BIT *** ABORTING *** \033[0m\n");
+ abort();
+ }
+
+ int num_msgs = in_data->size / sizeof(int32_t);
+ printf("\033[32m\033[1m%s: key %ld (%d messages)\033[0m\n", table, out_roomnum, num_msgs);
+
+ // the key is a "long"
+ out_key->size = sizeof(out_roomnum);
+ out_key->data = realloc(out_key->data, out_key->size);
+ memcpy(out_key->data, &out_roomnum, sizeof(out_roomnum));
+
+ // the data is another array, but a wider type
+ out_data->size = sizeof(long) * num_msgs;
+ out_data->data = realloc(out_data->data, out_data->size);
+
+ int32_t in_msg = 0;
+ long out_msg = 0;
+ for (i=0; i<num_msgs; ++i) {
+ memcpy(&in_msg, (in_data->data + (i * sizeof(int32_t))), sizeof(int32_t));
+ out_msg = (long) in_msg;
+ memcpy((out_data->data + (i * sizeof(long))), &out_msg, sizeof(long));
+ printf("msg#%ld\n", out_msg);
+ }
+}
+
+
+// convert function for a visit record
+void convert_visits(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // data
+ struct visit_32 *visit32 = (struct visit_32 *)in_data->data;
+ out_data->size = sizeof(struct visit);
+ out_data->data = realloc(out_data->data, out_data->size);
+ struct visit *visit64 = (struct visit *)out_data->data;
+
+ // the data (zero it out so it will compress well)
+ memset(visit64, 0, sizeof(struct visit));
+ visit64->v_roomnum = (long) visit32->v_roomnum;
+ visit64->v_roomgen = (long) visit32->v_roomgen;
+ visit64->v_usernum = (long) visit32->v_usernum;
+ visit64->v_lastseen = (long) visit32->v_lastseen;
+ visit64->v_flags = (unsigned) visit32->v_flags;
+ strcpy(visit64->v_seen, visit32->v_seen);
+ strcpy(visit64->v_answered, visit32->v_answered);
+ visit64->v_view = (int) visit32->v_view;
+
+ printf("\033[32m\033[1mVisit: room %ld, gen %ld, user %ld\033[0m\n", visit64->v_roomnum, visit64->v_roomgen, visit64->v_usernum);
+
+ // create the key (which is based on the data, so there is no need to the old key)
+ out_key->size = sizeof(struct visit_index);
+ out_key->data = realloc(out_key->data, out_key->size);
+ struct visit_index *newvisitindex = (struct visit_index *) out_key->data;
+ newvisitindex->iRoomID = visit64->v_roomnum;
+ newvisitindex->iRoomGen = visit64->v_roomgen;
+ newvisitindex->iUserID = visit64->v_usernum;
+}
+
+
+// convert function for a directory record
+void convert_dir(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // the key is a string
+ out_key->size = in_key->size;
+ out_key->data = realloc(out_key->data, out_key->size + 1);
+ memcpy(out_key->data, in_key->data, in_key->size);
+ char *k = (char *)out_key->data;
+ k[out_key->size] = 0;
+
+ // the data is also a string
+ out_data->size = in_data->size;
+ out_data->data = realloc(out_data->data, out_data->size + 1);
+ memcpy(out_data->data, in_data->data, in_data->size);
+ char *d = (char *)out_data->data;
+ d[out_data->size] = 0;
+
+ // please excuse my friend, he isn't null terminated
+ printf("\033[32m\033[1mDirectory entry: %s -> %s\033[0m\n", (char *)out_key->data, (char *)out_data->data);
+}
+
+
+// convert function for a use table record
+void convert_usetable(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // the key is a string
+ out_key->size = in_key->size;
+ out_key->data = realloc(out_key->data, out_key->size);
+ memcpy(out_key->data, in_key->data, in_key->size);
+
+ // the data is a "struct UseTable"
+ struct UseTable_32 *use32 = (struct UseTable_32 *)in_data->data;
+ out_data->size = sizeof(struct UseTable);
+ out_data->data = realloc(out_data->data, out_data->size);
+ memset(out_data->data, 0, out_data->size);
+ struct UseTable *use64 = (struct UseTable *)out_data->data;
+
+ // the data
+ strcpy(use64->ut_msgid, use32->ut_msgid);
+ use64->ut_timestamp = (time_t) use32->ut_timestamp;
+}
+
+
+// convert function for large message texts
+void convert_bigmsgs(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // The key is a packed long
+ int32_t in_msgnum;
+ long out_msgnum;
+ memcpy(&in_msgnum, in_key->data, sizeof(in_msgnum));
+ out_msgnum = (long)in_msgnum;
+
+ if (in_key->size != 4) {
+ printf("\033[31m\033[1m *** SOURCE DATABASE IS NOT 32-BIT *** ABORTING *** \033[0m\n");
+ abort();
+ }
+
+ // the data is binary-ish but has no packed integers
+ out_data->size = in_data->size;
+ out_data->data = realloc(out_data->data, out_data->size);
+ memcpy(out_data->data, in_data->data, in_data->size);
+
+ printf("\033[32m\033[1mBigmsg %ld , length %d\033[0m\n", out_msgnum, out_data->size);
+}
+
+
+// convert function for EUID Index records
+void convert_euidindex(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // The structure of an euidindex record *key* is:
+ // |----room_number----|----------EUID-------------|
+ // (sizeof long) (actual length of euid)
+
+ // The structure of an euidindex record *value* is:
+ // |-----msg_number----|----room_number----|----------EUID-------------|
+ // (sizeof long) (sizeof long) (actual length of euid)
+
+ int32_t in_msgnum = 0;
+ int32_t in_roomnum = 0;
+ char euid[SIZ];
+ long out_msgnum = 0;
+ long out_roomnum = 0;
+
+ memcpy(&in_msgnum, in_data->data, sizeof(in_msgnum));
+ memcpy(&in_roomnum, in_data->data+sizeof(int32_t), sizeof(in_msgnum));
+ strcpy(euid, in_data->data+(sizeof(int32_t)*2));
+
+ out_msgnum = (long) in_msgnum;
+ out_roomnum = (long) in_roomnum;
+ printf("euidindex: msgnum=%ld, roomnum=%ld, euid=\"%s\"\n", out_msgnum, out_roomnum, euid);
+
+ out_key->size = sizeof(long) + strlen(euid) + 1;
+ out_key->data = realloc(out_key->data, out_key->size);
+ memcpy(out_key->data, &out_roomnum, sizeof(out_roomnum));
+ strcpy(out_key->data+sizeof(out_roomnum), euid);
+
+ out_data->size = sizeof(long) + sizeof(long) + strlen(euid) + 1;
+ out_data->data = realloc(out_data->data, out_data->size);
+ memcpy(out_data->data, &out_msgnum, sizeof(out_msgnum));
+ memcpy(out_data->data+sizeof(out_msgnum), &out_roomnum, sizeof(out_roomnum));
+ strcpy(out_data->data+sizeof(out_msgnum)+sizeof(out_roomnum), euid);
+
+
+ int i;
+ char ch;
+
+ printf(" in_key: ");
+ for (i=0; i<in_key->size; ++i) {
+ ch = 0;
+ memcpy(&ch, in_key->data+i, 1);
+ printf("%02X ", (int) ch);
+ }
+ printf("\n");
+
+ printf(" out_key: ");
+ for (i=0; i<out_key->size; ++i) {
+ ch = 0;
+ memcpy(&ch, out_key->data+i, 1);
+ printf("%02X ", (int) ch);
+ }
+ printf("\n");
+
+ printf(" in_data: ");
+ for (i=0; i<in_data->size; ++i) {
+ ch = 0;
+ memcpy(&ch, in_data->data+i, 1);
+ printf("%02X ", (int) ch);
+ }
+ printf("\n");
+
+ printf("out_data: ");
+ for (i=0; i<out_data->size; ++i) {
+ ch = 0;
+ memcpy(&ch, out_data->data+i, 1);
+ printf("%02X ", (int) ch);
+ }
+ printf("\n");
+
+
+}
+
+
+// convert users-by-number records
+void convert_usersbynumber(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // key is a long
+ // and remember ... "long" is int32_t on the source system
+ int32_t in_usernum;
+ long out_usernum;
+ memcpy(&in_usernum, in_key->data, sizeof(in_usernum));
+ out_usernum = (long) in_usernum;
+
+ if (in_key->size != 4) {
+ printf("\033[31m\033[1m *** SOURCE DATABASE IS NOT 32-BIT *** ABORTING *** \033[0m\n");
+ abort();
+ }
+
+ out_key->size = sizeof(out_usernum);
+ out_key->data = realloc(out_key->data, out_key->size);
+ memcpy(out_key->data, &out_usernum, sizeof(out_usernum));
+
+ // value is a string
+ out_data->size = in_data->size;
+ out_data->data = realloc(out_data->data, out_data->size);
+ memcpy(out_data->data, in_data->data, in_data->size);
+
+ printf("usersbynumber: %ld --> %s\n", out_usernum, (char *)out_data->data);
+}
+
+
+// convert function for a config record
+void convert_config(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+
+ // the key is a string
+ out_key->size = in_key->size;
+ out_key->data = realloc(out_key->data, out_key->size + 1);
+ memcpy(out_key->data, in_key->data, in_key->size);
+ char *k = (char *)out_key->data;
+ k[out_key->size] = 0;
+
+ // the data is a pair of strings
+ out_data->size = in_data->size;
+ out_data->data = realloc(out_data->data, out_data->size + 1);
+ memcpy(out_data->data, in_data->data, in_data->size);
+ char *d = (char *)out_data->data;
+ d[out_data->size] = 0;
+
+ // please excuse my friend, he isn't null terminated
+ printf("\033[32m\033[1mConfig entry: %s -> %s\033[0m\n", (char *)out_key->data, (char *)out_data->data+strlen(out_data->data)+1);
+}
+
+
+// For obsolete databases, zero all the output
+void zero_function(int which_cdb, DBT *in_key, DBT *in_data, DBT *out_key, DBT *out_data) {
+ out_key->size = 0;
+ out_data->size = 0;