Пример #1
0
void mdb_iconv_init(MdbHandle *mdb)
{
	const char *iconv_code;

	/* check environment variable */
	if (!(iconv_code=getenv("MDBICONV"))) {
		iconv_code="UTF-8";
	}

#ifdef HAVE_ICONV
        if (IS_JET4(mdb)) {
                mdb->iconv_out = iconv_open("UCS-2LE", iconv_code);
                mdb->iconv_in = iconv_open(iconv_code, "UCS-2LE");
        } else {
                /* According to Microsoft Knowledge Base pages 289525 and */
		/* 202427, code page info is not contained in the database */
		const char *jet3_iconv_code;

		/* check environment variable */
		if (!(jet3_iconv_code=getenv("MDB_JET3_CHARSET"))) {
			jet3_iconv_code="CP1252";
		}

                mdb->iconv_out = iconv_open(jet3_iconv_code, iconv_code);
                mdb->iconv_in = iconv_open(iconv_code, jet3_iconv_code);
        }
#endif
}
Пример #2
0
int
main(int argc, char **argv)
{
	MdbHandle *mdb;
	int print_mdbver = 0;
	int opt;

  	/* setlocale (LC_ALL, ""); */
    	bindtextdomain (PACKAGE, LOCALEDIR);
      	textdomain (PACKAGE);
	while ((opt=getopt(argc, argv, "M"))!=-1) {
		switch (opt) {
			case 'M':
				print_mdbver = 1;
				break;
			default:
				break;
		}
	}

	if (print_mdbver) {
		fprintf(stdout,"%s\n", MDB_FULL_VERSION);
		if (argc-optind < 1) exit(0);
	}

	/* 
	** optind is now the position of the first non-option arg, 
	** see getopt(3) 
	*/
	if (argc-optind < 1) {
		fprintf(stderr,_("Usage: %s [-M] <file>\n"),argv[0]);
		exit(1);
	}

	mdb_init();

	if (!(mdb = mdb_open(argv[optind], MDB_NOFLAGS))) {
		fprintf(stderr,_("Error: unable to open file %s\n"),argv[optind]);
		mdb_exit();
		exit(1);
	}
	if (IS_JET3(mdb)) {
		printf("JET3\n");
	} else if (IS_JET4(mdb)) {
		printf("JET4\n");
	} else {
		printf(_("unknown database version\n"));
	}
	
	mdb_close(mdb);
	mdb_exit();

	exit(0);
}
Пример #3
0
/**
 * mdb_open:
 * @filename: path to MDB (database) file
 * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write
 *
 * Opens an MDB file and returns an MdbHandle to it.  MDB File may be relative
 * to the current directory, a full path to the file, or relative to a 
 * component of $MDBPATH.
 *
 * Return value: pointer to MdbHandle structure.
 **/
MdbHandle *mdb_open(char *filename, MdbFileFlags flags)
{
	MdbHandle *mdb;

	mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
	mdb_set_default_backend(mdb, "access");
	/* need something to bootstrap with, reassign after page 0 is read */
	mdb->fmt = &MdbJet3Constants;
	mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile));
	mdb->f->refs = 1;
	mdb->f->fd = -1;
	mdb->f->filename = (char *) mdb_find_file(filename);
	if (!mdb->f->filename) { 
		fprintf(stderr, "Can't alloc filename\n");
		mdb_close(mdb);
		return NULL; 
	}
	if (flags & MDB_WRITABLE) {
		mdb->f->writable = TRUE;
		mdb->f->fd = open(mdb->f->filename,O_RDWR);
	} else {
		mdb->f->fd = open(mdb->f->filename,O_RDONLY);
	}

	if (mdb->f->fd==-1) {
		fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); 
		mdb_close(mdb);
		return NULL;
	}
	if (!mdb_read_pg(mdb, 0)) {
		fprintf(stderr,"Couldn't read first page.\n");
		mdb_close(mdb);
		return NULL;
	}
	if (mdb->pg_buf[0] != 0) {
		mdb_close(mdb);
		return NULL; 
	}
	mdb->f->jet_version = mdb_pg_get_int32(mdb, 0x14);
	if (IS_JET4(mdb)) {
		mdb->fmt = &MdbJet4Constants;
	} else if (IS_JET3(mdb)) {
		mdb->fmt = &MdbJet3Constants;
	} else {
		fprintf(stderr,"Unknown Jet version.\n");
		mdb_close(mdb);
		return NULL; 
	}

	return mdb;
}
Пример #4
0
/*
 * This function is used in reading text data from an MDB table.
 */
int
mdb_unicode2ascii(MdbHandle *mdb, char *src, size_t slen, char *dest, size_t dlen)
{
	char *tmp = NULL;
	size_t tlen = 0;
	size_t len_in, len_out;
	char *in_ptr, *out_ptr;

	if ((!src) || (!dest) || (!dlen))
		return 0;

	/* Uncompress 'Unicode Compressed' string into tmp */
	if (IS_JET4(mdb) && (slen>=2)
	 && ((src[0]&0xff)==0xff) && ((src[1]&0xff)==0xfe)) {
		unsigned int compress=1;
		src += 2;
		slen -= 2;
		tmp = (char *)g_malloc(slen*2);
		while (slen) {
			if (*src == 0) {
				compress = (compress) ? 0 : 1;
				src++;
				slen--;
			} else if (compress) {
				tmp[tlen++] = *src++;
				tmp[tlen++] = 0;
				slen--;
			} else if (slen >= 2){
				tmp[tlen++] = *src++;
				tmp[tlen++] = *src++;
				slen-=2;
			}
		}
	}

	in_ptr = (tmp) ? tmp : src;
	out_ptr = dest;
	len_in = (tmp) ? tlen : slen;
	len_out = dlen;

#if HAVE_ICONV
	//printf("1 len_in %d len_out %d\n",len_in, len_out);
	while (1) {
		iconv(mdb->iconv_in, &in_ptr, &len_in, &out_ptr, &len_out);
		if ((!len_in) || (errno == E2BIG)) break;
		/* Don't bail if impossible conversion is encountered */
		in_ptr += (IS_JET4(mdb)) ? 2 : 1;
		len_in -= (IS_JET4(mdb)) ? 2 : 1;
		*out_ptr++ = '?';
		len_out--;
	}
	//printf("2 len_in %d len_out %d\n",len_in, len_out);
	dlen -= len_out;
#else
	if (IS_JET3(mdb)) {
		strncpy(out_ptr, in_ptr, len_in);
		dlen = len_in;
	} else {
		/* rough UCS-2LE to ISO-8859-1 conversion */
		unsigned int i;
		for (i=0; i<len_in; i+=2)
			dest[i/2] = (in_ptr[i+1] == 0) ? in_ptr[i] : '?';
		dlen = len_in/2;
	}
#endif

	if (tmp) g_free(tmp);
	dest[dlen]='\0';
	//printf("dest %s\n",dest);
	return dlen;
}
Пример #5
0
/*
 * This function is used in writing text data to an MDB table.
 * If slen is 0, strlen will be used to calculate src's length.
 */
int
mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t slen, char *dest, size_t dlen)
{
        size_t len_in, len_out;
        char *in_ptr, *out_ptr;

	if ((!src) || (!dest) || (!dlen))
		return 0;

        in_ptr = src;
        out_ptr = dest;
        len_in = (slen) ? slen : strlen(in_ptr);
        len_out = dlen;

#ifdef HAVE_ICONV
	iconv(mdb->iconv_out, &in_ptr, &len_in, &out_ptr, &len_out);
	//printf("len_in %d len_out %d\n", len_in, len_out);
	dlen -= len_out;
#else
	if (IS_JET3(mdb)) {
		dlen = MIN(len_in, len_out);
		strncpy(out_ptr, in_ptr, dlen);
	} else {
		unsigned int i;
		slen = MIN(len_in, len_out/2);
		dlen = slen*2;
		for (i=0; i<slen; i++) {
			out_ptr[i*2] = in_ptr[i];
			out_ptr[i*2+1] = 0;
		}
	}
#endif

	/* Unicode Compression */
	if(IS_JET4(mdb) && (dlen>4)) {
		unsigned char *tmp = g_malloc(dlen);
		unsigned int tptr = 0, dptr = 0;
		int comp = 1;

		tmp[tptr++] = 0xff;
		tmp[tptr++] = 0xfe;
		while((dptr < dlen) && (tptr < dlen)) {
			if (((dest[dptr+1]==0) && (comp==0))
			 || ((dest[dptr+1]!=0) && (comp==1))) {
				/* switch encoding mode */
				tmp[tptr++] = 0;
				comp = (comp) ? 0 : 1;
			} else if (dest[dptr]==0) {
				/* this string cannot be compressed */
				tptr = dlen;
			} else if (comp==1) {
				/* encode compressed character */
				tmp[tptr++] = dest[dptr];
				dptr += 2;
			} else if (tptr+1 < dlen) {
				/* encode uncompressed character */
				tmp[tptr++] = dest[dptr];
				tmp[tptr++] = dest[dptr+1];
				dptr += 2;
			} else {
				/* could not encode uncompressed character
				 * into single byte */
				tptr = dlen;
			}
		}
		if (tptr < dlen) {
			memcpy(dest, tmp, tptr);
			dlen = tptr;
		}
		g_free(tmp);
	}

	return dlen;
}
Пример #6
0
/**
 * mdb_open:
 * @filename: path to MDB (database) file
 * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write
 *
 * Opens an MDB file and returns an MdbHandle to it.  MDB File may be relative
 * to the current directory, a full path to the file, or relative to a 
 * component of $MDBPATH.
 *
 * Return value: pointer to MdbHandle structure.
 **/
MdbHandle *mdb_open(const char *filename, MdbFileFlags flags)
{
	MdbHandle *mdb;
	int open_flags;

	mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
	mdb_set_default_backend(mdb, "access");
#ifdef HAVE_ICONV
	mdb->iconv_in = (iconv_t)-1;
	mdb->iconv_out = (iconv_t)-1;
#endif
	/* need something to bootstrap with, reassign after page 0 is read */
	mdb->fmt = &MdbJet3Constants;
	mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile));
	mdb->f->refs = 1;
	mdb->f->fd = -1;
	mdb->f->filename = mdb_find_file(filename);
	if (!mdb->f->filename) { 
		fprintf(stderr, "Can't alloc filename\n");
		mdb_close(mdb);
		return NULL; 
	}
	if (flags & MDB_WRITABLE) {
		mdb->f->writable = TRUE;
		open_flags = O_RDWR;
	} else {
		open_flags = O_RDONLY;
	}

#ifdef _WIN32
	open_flags |= O_BINARY;
#endif

	mdb->f->fd = open(mdb->f->filename, open_flags);

	if (mdb->f->fd==-1) {
		fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); 
		mdb_close(mdb);
		return NULL;
	}
	if (!mdb_read_pg(mdb, 0)) {
		fprintf(stderr,"Couldn't read first page.\n");
		mdb_close(mdb);
		return NULL;
	}
	if (mdb->pg_buf[0] != 0) {
		mdb_close(mdb);
		return NULL; 
	}
	mdb->f->jet_version = mdb_get_int32(mdb->pg_buf, 0x14);
	if (IS_JET4(mdb)) {
		mdb->fmt = &MdbJet4Constants;
	} else if (IS_JET3(mdb)) {
		mdb->fmt = &MdbJet3Constants;
	} else {
		fprintf(stderr,"Unknown Jet version.\n");
		mdb_close(mdb);
		return NULL; 
	}
	mdb_iconv_init(mdb);

	return mdb;
}
Пример #7
0
GPtrArray *mdb_read_columns(MdbTableDef *table)
{
	MdbHandle *mdb = table->entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	MdbColumn *pcol;
	unsigned char *col;
	unsigned int i;
	int cur_pos;
	size_t name_sz;
	
	table->columns = g_ptr_array_new();

	col = (unsigned char *) g_malloc(fmt->tab_col_entry_size);

	cur_pos = fmt->tab_cols_start_offset + 
		(table->num_real_idxs * fmt->tab_ridx_entry_size);

	/* new code based on patch submitted by Tim Nelson 2000.09.27 */

	/* 
	** column attributes 
	*/
	for (i=0;i<table->num_cols;i++) {
#ifdef MDB_DEBUG
	/* printf("column %d\n", i);
	buffer_dump(mdb->pg_buf, cur_pos, fmt->tab_col_entry_size); */
#endif
		read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size);
		pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn));

		pcol->col_type = col[0];

		
		pcol->col_num = col[fmt->col_num_offset];

		
		
		pcol->var_col_num = mdb_get_int16(col, fmt->tab_col_offset_var);
		

		
		pcol->row_col_num = mdb_get_int16(col, fmt->tab_row_col_num_offset);
		

		/* FIXME: can this be right in Jet3 and Jet4? */
		if (pcol->col_type == MDB_NUMERIC) {
			pcol->col_prec = col[11];
			pcol->col_scale = col[12];
		}

		
		pcol->is_fixed = col[fmt->col_fixed_offset] & 0x01 ? 1 : 0;

		
		pcol->fixed_offset = mdb_get_int16(col, fmt->tab_col_offset_fixed);
		
		

		if (pcol->col_type != MDB_BOOL) {
			
			pcol->col_size = mdb_get_int16(col, fmt->col_size_offset);
		} else {
			pcol->col_size=0;
		}
		
		g_ptr_array_add(table->columns, pcol);
	}

	g_free (col);

	/* 
	** column names - ordered the same as the column attributes table
	*/
	for (i=0;i<table->num_cols;i++) {
		char *tmp_buf;
		pcol = g_ptr_array_index(table->columns, i);

		if (IS_JET4(mdb)) {
			name_sz = read_pg_if_16(mdb, &cur_pos);
		} else if (IS_JET3(mdb)) {
			name_sz = read_pg_if_8(mdb, &cur_pos);
		} else {
			fprintf(stderr,"Unknown MDB version\n");
			continue;
		}
		tmp_buf = (char *) g_malloc(name_sz);
		read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz);
		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);

	table->index_start = cur_pos;
	return table->columns;
}
Пример #8
0
GPtrArray *
mdb_read_indices(MdbTableDef *table)
{
	MdbCatalogEntry *entry = table->entry;
	MdbHandle *mdb = entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	MdbIndex *pidx;
	unsigned int i, j;
	int idx_num, key_num, col_num;
	int cur_pos, name_sz, idx2_sz, type_offset;
	int index_start_pg = mdb->cur_pg;
	guchar *tmpbuf;

        table->indices = g_ptr_array_new();

        if (IS_JET4(mdb)) {
		cur_pos = table->index_start + 52 * table->num_real_idxs;
		idx2_sz = 28;
		type_offset = 23;
	} else {
		cur_pos = table->index_start + 39 * table->num_real_idxs;
		idx2_sz = 20;
		type_offset = 19;
	}

	tmpbuf = (guchar *) g_malloc(idx2_sz);
	for (i=0;i<table->num_idxs;i++) {
		read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz);
		cur_pos += idx2_sz;
		pidx = (MdbIndex *) g_malloc0(sizeof(MdbIndex));
		pidx->table = table;
		pidx->index_num = mdb_get_int16(tmpbuf, 4);
		pidx->index_type = tmpbuf[type_offset]; 
		g_ptr_array_add(table->indices, pidx);
	}
	g_free(tmpbuf);

	for (i=0;i<table->num_idxs;i++) {
		pidx = g_ptr_array_index (table->indices, i);
		if (IS_JET4(mdb)) {
			name_sz=read_pg_if_16(mdb, &cur_pos);
			cur_pos += 2;
			tmpbuf = g_malloc(name_sz);
			read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz);
			cur_pos += name_sz;
			mdb_unicode2ascii(mdb, tmpbuf, 0, name_sz, pidx->name); 
			g_free(tmpbuf);
		} else {
			read_pg_if(mdb, &cur_pos, 0);
			name_sz=mdb->pg_buf[cur_pos++];
			read_pg_if_n(mdb, (unsigned char *) pidx->name, &cur_pos, name_sz);
			cur_pos += name_sz;
			pidx->name[name_sz]='\0';		
		}
		//fprintf(stderr, "index name %s\n", pidx->name);
	}

	mdb_read_alt_pg(mdb, entry->table_pg);
	mdb_read_pg(mdb, index_start_pg);
	cur_pos = table->index_start;
	idx_num=0;
	for (i=0;i<table->num_real_idxs;i++) {
		if (IS_JET4(mdb)) cur_pos += 4;
		do {
			pidx = g_ptr_array_index (table->indices, idx_num++);
		} while (pidx && pidx->index_type==2);

		/* if there are more real indexes than index entries left after
		   removing type 2's decrement real indexes and continue.  Happens
		   on Northwind Orders table.
		*/
		if (!pidx) {
			table->num_real_idxs--;
			continue;
		}

		pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, 
				fmt->tab_cols_start_offset +
				(i*fmt->tab_ridx_entry_size));

		key_num=0;
		for (j=0;j<MDB_MAX_IDX_COLS;j++) {
			col_num=read_pg_if_16(mdb,&cur_pos);
			cur_pos += 2;
			read_pg_if(mdb, &cur_pos, 0);
			cur_pos++;
			if (col_num == 0xFFFF)
				continue;
			/* set column number to a 1 based column number and store */
			pidx->key_col_num[key_num] = col_num + 1;
			pidx->key_col_order[key_num] =
				(mdb->pg_buf[cur_pos-1]) ? MDB_ASC : MDB_DESC;
			key_num++;
		}
		pidx->num_keys = key_num;

		cur_pos += 4;
		pidx->first_pg = read_pg_if_32(mdb, &cur_pos);
		cur_pos += 4;
		read_pg_if(mdb, &cur_pos, 0);
		pidx->flags = mdb->pg_buf[cur_pos++];
		if (IS_JET4(mdb)) cur_pos += 9;
	}
	return NULL;
}