Hi all,

I've written a Cyrus->DBMail conversion tool and it takes care of everything 
and all messsages come up properly (except for some, with two consequtive @s 
in the sender address). In Outlook Express though, all dates show as being 
the time that the conversion was performed - not the actual date. KMail and 
Mozilla Mail are fine though.

Any suggestions are greatly apprecaited!

Chris
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include "dbmail.h"
#include "db.h"
#include "auth.h"
#include "list.h"

#define MAX_LINE_SIZE 1024
#define UID_SIZE 70

typedef struct stack_node * SNode;

struct stack_node {
	char * entry_name;
	SNode next;
};

static SNode stack_pointer = NULL;

char * config_file = DEFAULT_CONFIG_FILE;

extern field_t _db_host;
extern field_t _db_db;
extern field_t _db_user;
extern field_t _db_pass;

static u64_t userid;
static char message_buffer[READ_BLOCK_SIZE + MAX_LINE_SIZE + 1];
static char line_buffer[MAX_LINE_SIZE + 1];
static int num_folders = 0;
static int num_messages = 0;

int process_dir(char *, char *);

/* push() : Takes a string and copies it into a SNode. NOTE: Does not store reference to argument.
 * Caller may free argument string once push() returns */

void push(char *);
char * pop(void);
int stack_empty(void);
SNode new_SNode(void); 
void print_stack(void);
int insert_message(char *, char *);

/* get_curr_dir() : For portability reasons, this function may need modification. Makes use of 
 * getcwd(). */

char * get_curr_dir(void);

int stack_empty(void) {

	return stack_pointer == NULL;
}


SNode new_SNode(void) {

	SNode node = (SNode) malloc(sizeof(struct stack_node));

	if (node == NULL) {
		perror("malloc");
		exit(EXIT_FAILURE);
	}

	return node;
}

void push(char * entry_name) {

	SNode node = new_SNode();
	node->next = stack_pointer;
	stack_pointer = node;
	node->entry_name = (char *) malloc(sizeof(char) * (strlen(entry_name) + 1));
	(void) strcpy(node->entry_name, entry_name);

	return;
}

char * pop(void) {

	char * return_value;
	SNode temp;

	if (stack_pointer == NULL)
		return NULL;
	
	temp = stack_pointer->next;
	return_value = stack_pointer->entry_name;
	free(stack_pointer);
	stack_pointer = temp;

	return return_value;
}

void print_stack(void) {

	while (!stack_empty())
		printf("Stack entry: %s .\n", pop());

	return;
}
	
int process_dir(char * dir, char * base) {

	struct stat file;
	struct dirent ** filelisting;
	int i = 0, n = 0, return_value = 0;
	char * entry_name;
	char * creation_dir;
	u64_t mailbox_id;
	int msg_per_folder = 0;

	num_folders++;

	creation_dir = (1 + dir + strlen(base));

	mailbox_id = db_findmailbox(creation_dir, userid);

	if (mailbox_id == 0) {
		db_createmailbox(creation_dir, userid);
		printf("Creating mailbox %s\n", creation_dir);
	} else 
		printf("Mailbox %s already exists.\n", creation_dir);
	
	n = scandir(dir, &filelisting, 0, alphasort);

	for (i = 0; i < n; i++) {
		if (strcmp(".", filelisting[i]->d_name) == 0) {
			free(filelisting[i]);
			continue;
		}
		
		if (strcmp("..", filelisting[i]->d_name) == 0) {
			free(filelisting[i]);
			continue;
		}

		entry_name = (char *) malloc(sizeof(char) * (strlen(dir) + strlen(filelisting[i]->d_name) + 2));
		(void) strcpy(entry_name, dir);
		(void) strcat(entry_name, "/");
		(void) strcat(entry_name, filelisting[i]->d_name);
		free(filelisting[i]);

		return_value = stat(entry_name, &file);

		if (return_value != 0) {
			perror("stat");
			continue;
		}

		if (S_ISDIR(file.st_mode)) {
			push(entry_name); 
			continue;
		}

		if (S_ISREG(file.st_mode)) { 
			if (strstr(entry_name, "cyrus") != NULL) 
				continue;
			if (strcmp(dir, base) == 0)
				creation_dir = "INBOX";
			insert_message(creation_dir, entry_name);
			msg_per_folder++;
		}
	}

	free(filelisting);

	printf("%d messages converted for folder %s\n", msg_per_folder, creation_dir);

	num_messages += msg_per_folder;

	return 0;
}

char * get_curr_dir(void) {

	int size = 32;
	char * path = (char *) malloc(sizeof(char) * size);
	char * return_value;

	if (path == NULL) {
		perror("malloc");
		exit(EXIT_FAILURE);
	}

	return_value = getcwd(path, size);

	while (return_value == NULL) {
		free(path);
		size *= 2;
		path = malloc(sizeof(char) * size);
		return_value = getcwd(path, size);
	}

	return path;
}

int main(int argc, char **argv) {

	int i;
	struct list system_items;
	char * dir_name = get_curr_dir();

	if (argc != 2) {
		fprintf(stderr, "Usage: %s <dbmail username>\n", argv[0]);
		fprintf(stderr, "DBMail users must already exist!\n");
		exit(EXIT_FAILURE);
	}

	ReadConfig("DBMAIL", config_file, &system_items);
        SetTraceLevel(&system_items);
	GetDBParams(_db_host, _db_db, _db_user, _db_pass, &system_items);

        if (db_connect() != 0) {
                fprintf(stderr, "We're all doomed!");
                exit(EXIT_FAILURE);
	}
								        
	userid = auth_user_exists(argv[1]);

	if (userid == 0) {
	        fprintf(stderr, "Aiiieeee! Non-existant user specified!\n");
	        exit(EXIT_FAILURE);
	}
										
	printf("User id of user %s is %llu.\n", argv[1], userid);

	i = process_dir(dir_name, dir_name);

	while (!stack_empty()) 
		process_dir(pop(), dir_name);

	return 0;
}
	

	
int insert_message(char * folder, char * filename) {	
	
	FILE * message;
	u64_t message_id;
	u64_t message_size = 0, newlines = 0;
	char unique_id[UID_SIZE];
	int buffer_marker = 0;
	int line_length = 0;
	int single_char_line = 0;

	message = fopen(filename, "r");

	if (message == NULL) {
		perror("fopen");
		exit(EXIT_FAILURE);
	}

	message_id = db_insert_message(userid, folder, 0);

	/* First take care of the header */
	snprintf(unique_id, UID_SIZE, "%lluA%lu", userid, time(NULL));

	while (single_char_line != 1) {
		(void) fgets(line_buffer, MAX_LINE_SIZE, message);
		newlines += 1;
		line_length = strlen(line_buffer);

		line_buffer[line_length - 1] = '\0';
		line_buffer[line_length - 2] = '\n'; 

		line_length -= 1;

		if (line_length == 1) 
				single_char_line = 1;
			
		strcpy(&message_buffer[buffer_marker], line_buffer);
		buffer_marker += line_length;
		message_size += line_length; 
	}

	message_buffer[buffer_marker + 1] = '\0';

	db_insert_message_block(message_buffer, message_size, message_id);
	db_update_message(message_id, unique_id, message_size, message_size + newlines);

	buffer_marker = 0;
		
	while (!feof(message)) {
		(void) fgets(line_buffer, MAX_LINE_SIZE, message);
		newlines += 1;
		line_length = strlen(line_buffer);
		line_buffer[line_length - 1] = '\0';
		line_buffer[line_length - 2] = '\n';
		line_length -= 1;

		if (buffer_marker < (READ_BLOCK_SIZE - line_length)) {
			(void) strcpy(&message_buffer[buffer_marker], line_buffer);
			buffer_marker += line_length;
			message_size += line_length;
		} else {
			db_insert_message_block(message_buffer, buffer_marker, message_id);
			buffer_marker = 0;
			(void) strcpy(&message_buffer[buffer_marker], line_buffer);
			buffer_marker +=line_length;
		}
	}

	db_insert_message_block(message_buffer, buffer_marker, message_id);

	db_update_message(message_id, unique_id, message_size, message_size + newlines);

	fclose(message);
		
	return 0;
}


	
		
		
		
				
	
	

Reply via email to