1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * GImageView
5  * Copyright (C) 2001-2003 Takuro Ashie
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: compare_md5.c,v 1.4 2004/04/08 10:38:50 makeinu Exp $
22  */
23 
24 /*
25  * 2003-05-17 Takuro Ashie <ashie@homa.ne.jp>
26  *
27  *     Fetched from textutils-2.1 and adapt to GImageView.
28  *
29  *     Copyright (C) 1995-2002 Free Software Foundation, Inc.
30  *     Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>.
31  */
32 
33 #include <string.h>
34 #include <stdio.h>
35 #include <sys/types.h>
36 
37 #include "gimv_dupl_finder.h"
38 #include "gimv_image_info.h"
39 #include "gimv_thumb.h"
40 #include "md5.h"
41 
42 
43 /* Most systems do not distinguish between external and internal
44    text representations.  */
45 /* FIXME: This begs for an autoconf test.  */
46 #if O_BINARY
47 # define OPENOPTS(BINARY) ((BINARY) != 0 ? TEXT1TO1 : TEXTCNVT)
48 # define TEXT1TO1 "rb"
49 # define TEXTCNVT "r"
50 #else
51 # if defined VMS
52 #  define OPENOPTS(BINARY) ((BINARY) != 0 ? TEXT1TO1 : TEXTCNVT)
53 #  define TEXT1TO1 "rb", "ctx=stm"
54 #  define TEXTCNVT "r", "ctx=stm"
55 # else
56 #  if UNIX || __UNIX__ || unix || __unix__ || _POSIX_VERSION
57 #   define OPENOPTS(BINARY) "r"
58 #  else
59     /* The following line is intended to evoke an error.
60        Using #error is not portable enough.  */
61     "Cannot determine system type."
62 #  endif
63 # endif
64 #endif
65 
66 #define DIGEST_BIN_BYTES (128 / 8)
67 
68 static gboolean
69 digest_file (const gchar *filename, gint binary, guchar *bin_result)
70 {
71    FILE *fp;
72    gint err;
73 
74    fp = fopen (filename, OPENOPTS (binary));
75    if (fp == NULL)
76       return FALSE;
77 
78    err = md5_stream (fp, bin_result);
79    if (err) {
80       fclose (fp);
81       return FALSE;
82    }
83 
84    if (fclose (fp) == EOF)
85       return FALSE;
86 
87    return TRUE;
88 }
89 
90 
91 static gpointer
duplicates_md5_get_data(GimvThumb * thumb)92 duplicates_md5_get_data (GimvThumb *thumb)
93 {
94    const gchar *filename;
95    gchar *temp_file = NULL;
96    guchar bin_buffer[DIGEST_BIN_BYTES + 1];
97    gboolean success;
98 
99    g_return_val_if_fail (GIMV_IS_THUMB(thumb), NULL);
100    g_return_val_if_fail (thumb->info, NULL);
101 
102    if (gimv_image_info_need_temp_file (thumb->info)) {
103       temp_file = gimv_image_info_get_temp_file (thumb->info);
104       filename = temp_file;
105    } else {
106       filename = gimv_image_info_get_path (thumb->info);
107    }
108 
109    g_return_val_if_fail (filename && *filename, NULL);
110 
111    success = digest_file (filename, TRUE, bin_buffer);
112    if (!success)
113       return NULL;
114 
115    bin_buffer[DIGEST_BIN_BYTES] = '\0';
116 
117    return g_strdup (bin_buffer);
118 }
119 
120 
121 static gint
duplicates_md5_compare(gpointer data1,gpointer data2,gfloat * similarity)122 duplicates_md5_compare (gpointer data1, gpointer data2, gfloat *similarity)
123 {
124    const gchar *str1 = data1, *str2 = data2;
125    gint retval;
126 
127    if (!str1)
128       return str2 ? 1 : 0;
129    else if (!str2)
130       return 1;
131 
132    retval = strcmp (str1, str2);
133 
134    if (!retval)
135       *similarity = 1.0;
136    else
137       *similarity = 0.0;
138 
139    return retval;
140 }
141 
142 
143 static void
duplicates_md5_data_delete(gpointer data)144 duplicates_md5_data_delete (gpointer data)
145 {
146    g_free (data);
147 }
148 
149 
150 GimvDuplCompFuncTable gimv_dupl_md5_funcs =
151 {
152    label:       N_("md5sum"),
153    get_data:    duplicates_md5_get_data,
154    compare:     duplicates_md5_compare,
155    data_delete: duplicates_md5_data_delete,
156 };
157