#include <ctype.h>
#include <sys/types.h>
#include "ghasher.h"
struct faileditem{
	gchar *filename;
	gchar *reason;
};

static void faileditem_free_cb(gpointer data,gpointer userdata)
{
	struct faileditem *item = data;

	g_free(item->filename);
	g_free(item->reason);
	g_free(item);
}

static void read_digest_file(GHashTable * files, const char *filename, GError ** error)
{
	char *line;
	gsize len;
	GIOChannel *f;

	f = g_io_channel_new_file(filename, "r", error);
	if (f == NULL) {
		return;
	}
	/*We have the hex for the md5sum , space , then the filename*/
	while (g_io_channel_read_line(f, &line, &len, NULL, error) == G_IO_STATUS_NORMAL) {
		gchar *tmp, *name, *hash;
		if (len == 0) {
			continue;
		}
		tmp = line;

		while (*tmp && isspace(*tmp))
			++tmp;
		hash = tmp;

		while (*tmp && isalnum(*tmp))
			++tmp;
		while (*tmp && isspace(*tmp)) {
			*tmp = '\0';
			++tmp;
		}

		name = tmp;

		while (*tmp) {
			if (*tmp == '\n' || *tmp == '\r')
				*tmp = '\0';
			++tmp;
		}
		g_hash_table_replace(files, g_strdup(name), g_strdup(hash));
		g_free(line);
	}

	g_io_channel_unref(f);
}

static GList *do_verify(GtkListStore *store,int hashcol,int filenamecol,GHashTable *files)
{
	GtkTreeIter iter;
	GList *result = NULL;

	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
		return NULL;

	do {
		gchar *h = NULL,*f = NULL,*base,*ch;
		
		gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, filenamecol, &f, -1);
		if (f == NULL) {
			g_print("Getting iterator failed!!\n");
			continue;
		}

		base = g_path_get_basename(f);

		gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, hashcol, &h, -1);
		if (h == NULL) {
			struct faileditem *item;
			g_print("Getting hash for %s failed!!\n",f);

			item = g_new(struct faileditem,1);
			item->filename = base;
			item->reason = g_strdup_printf("Hash seems unavailable. This might be a bug in ghasher :-/");			
			result = g_list_append(result,item);

			g_free(f);
			continue;
		}
		ch = g_hash_table_lookup(files,base);	
		if(ch == NULL)
			ch = g_hash_table_lookup(files,f);	
		
		if(ch == NULL){	
			struct faileditem *item;
			g_print("Hash for %s does not exist!!\n",base);

			item = g_new(struct faileditem,1);
			item->filename = base;
			item->reason = g_strdup_printf("File was not found in sum file");			
			result = g_list_append(result,item);
			g_free(h);

			continue;
		}	
		g_free(f);
		g_print("Checking '%s'  '%s' == '%s' !!\n",base,h,ch);
		if(g_ascii_strcasecmp(h,ch) != 0){
			struct faileditem *item;
			g_print("Failed '%s'  '%s' != '%s' !!\n",base,h,ch);

			item = g_new(struct faileditem,1);
			item->filename = base;
			item->reason = g_strdup_printf("Digest sum(%s) does not match sumfile(%s)",h,ch);			
			result = g_list_append(result,item);
			g_free(h);

			continue;
	
		}
		g_free(base);
		g_free(h);

	} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
	
	return result;
}

void verify_sumfile(GtkWidget  *mainwindow,GtkListStore *filestore,int hashcol,int filecol,const char *filename)
{
	GHashTable *files;
	GList *failed;
	GError *error = NULL;
	
	files = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free);
	read_digest_file(files,filename,&error);
	if(error != NULL){
		show_error_dialog(mainwindow,"Opening '%s' failed\n%s",filename,error->message);
		g_error_free(error);
		g_hash_table_destroy(files);
		return;
	} 
	failed = do_verify(filestore,hashcol,filecol,files);
	if(failed != NULL)
		show_error_dialog(mainwindow,"Digest does not match");
	else
		show_error_dialog(mainwindow,"All digest matches");

	g_list_foreach(failed,faileditem_free_cb,NULL);
	g_list_free(failed);

}


syntax highlighted by Code2HTML, v. 0.9.1