Browse code

Big update

git-svn: trunk@88

Tomasz Kojm authored on 2003/10/26 15:01:03
Showing 27 changed files
... ...
@@ -1,4 +1,11 @@
1
-Fri Oct 24 02:19:54 CEST 2003
1
+Sun Oct 26 06:26:14 CET 2003 (tk)
2
+----------------------------------
3
+  * clamd: report file errors with CONTSCAN (suggested by Daniel Fraga)
4
+  * libclamav: cvd and general cleanups
5
+  * freshclam: rewritten to use cvd, cleanups; --debug added
6
+  * mirrors.txt: only use database.clamav.net
7
+
8
+Fri Oct 24 02:19:54 CEST 2003 (tk)
2 9
 ----------------------------------
3 10
   * clamd: initialize the virus-number variable (Igor Brezac)
4 11
   * sigtool: fixed compilation issue on Solaris (bug reported by
... ...
@@ -58,14 +65,14 @@ Wed Oct  8 14:49:40 CEST 2003 (tk)
58 58
 
59 59
 Wed Oct  8 12:39:26 CEST 2003 (tk)
60 60
 ----------------------------------
61
-  * clamd: (!!!) fixed race condition in database reloading code
61
+  * clamd: (!!!) fixed a race condition in database reloading code
62 62
   * libclamav: finished support for cvd files
63 63
 
64 64
 Sun Oct  5 18:30:40 BST 2003 (njh)
65 65
 ----------------------------------
66 66
   * clamav-milter: Used to always remove old UNIX domain sockets, now
67 67
   		only does that if FixStaleSocket is set
68
-		
68
+
69 69
 Sun Oct  5 14:58:05 BST 2003 (njh)
70 70
 ----------------------------------
71 71
   * clamav-milter: s/atoi(cpt->strarg)/cpt->numarg for MaxThreads
... ...
@@ -272,7 +279,7 @@ Wed Aug 13 16:07:39 CEST 2003
272 272
 
273 273
 Wed Aug  6 03:01:51 CEST 2003
274 274
 -----------------------------
275
-  * clamd: new directives: VirusAction, Debug
275
+  * clamd: new directives: VirusEvent, Debug
276 276
   * libclamav: zziplib downgraded to the old version due to Zip handling
277 277
 	       problems
278 278
 
... ...
@@ -313,11 +320,12 @@ Wed Jul 17 23:33:17 CEST 2003
313 313
 	       newline character (Nigel)
314 314
 
315 315
 Mon Jul 14 03:43:35 CEST 2003
316
+-----------------------------
316 317
   * clamav-milter: Some TODOs done by Nigel Kukard <nkukard@lbsd.net>
317 318
                    Should stop a couple of remote chances of crashes (Nigel)
318 319
 
319 320
 Thu Jul 10 17:16:32 CEST 2003
321
+-----------------------------
320 322
   * clamd: fixed PidFile permissions (applied patch from Magnus Ekdahl, the
321 323
 	   bug was reported by Tomasz Papszun)
322 324
 
... ...
@@ -2,6 +2,53 @@ Note: This README/NEWS file refers to the source tarball. Some things described
2 2
 here may not be available in the binary packages.
3 3
 --
4 4
 
5
+
6
+
7
+0.65
8
+----
9
+
10
+-) clamd:
11
+    + fixed a race condition in the database reloading code (random hangs
12
+      under high load)
13
+    + fixed PidFile permissions (Magnus Ekdahl, bug reported by Tomasz Papszun)
14
+    + fixed LogFile permissions (Magnus Ekdahl)
15
+    + new directive ScanRAR (bacause RAR support is now disabled by default)
16
+    + new directive VirusEvent
17
+    + new directive FixStaleSocket (Thomas Lamy and Mark Mielke)
18
+    + new directive TCPAddr (Bernard Quatermass, fixed by Damien Curtain)
19
+    + new directive Debug
20
+
21
+-) clamav-milter:
22
+    + 
23
+    + new --force-scan flag
24
+    + new -P and -q flags by Nicholas M. Kirsch
25
+
26
+-) libclamav:
27
+    + multiple mbox fixes (thanks to Rene Bellora, Bernd Kuhls, Thomas Lamy, 
28
+      Tomasz Papszun,
29
+
30
+    + memory leak fixes (Thomas Lamy)
31
+    + support for a new database container format (CVD) with support for
32
+      digital signatures, 
33
+    + new scan option CL_DISABLERAR (disables built-in RAR unpacker)
34
+
35
+-) freshclam:
36
+    + fixed --on-error-execute behaviour (David Woakes)
37
+    + new option --user (-u) USER - run as USER instead of the default user.
38
+      Patch by Damien Curtain.
39
+
40
+-) documentation:
41
+    + new Spanish documentation on ClamAV + Sendmail integration by
42
+      Erick Ivaan Lopez Carreon
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
5 52
 0.60
6 53
 ----
7 54
 
... ...
@@ -81,7 +81,7 @@ dnl there is now a CREATE_PREFIX_TARGET_H in this file as a shorthand for
81 81
 dnl PREFIX_CONFIG_H from a target.h file, however w/o the target.h ever created
82 82
 dnl (the prefix is a bit different, since we add an extra -target- and -host-)
83 83
 dnl 
84
-dnl @version: $Id: aclocal.m4,v 1.8 2003/10/20 00:55:10 kojm Exp $
84
+dnl @version: $Id: aclocal.m4,v 1.9 2003/10/26 06:00:55 kojm Exp $
85 85
 dnl @author Guido Draheim <guidod@gmx.de>                 STATUS: used often
86 86
 
87 87
 AC_DEFUN([AC_CREATE_TARGET_H],
... ...
@@ -4041,7 +4041,7 @@ dnl      AC_COMPILE_CHECK_SIZEOF(ptrdiff_t, $headers)
4041 4041
 dnl      AC_COMPILE_CHECK_SIZEOF(off_t, $headers)
4042 4042
 dnl
4043 4043
 dnl @author Kaveh Ghazi <ghazi@caip.rutgers.edu>
4044
-dnl @version $Id: aclocal.m4,v 1.8 2003/10/20 00:55:10 kojm Exp $
4044
+dnl @version $Id: aclocal.m4,v 1.9 2003/10/26 06:00:55 kojm Exp $
4045 4045
 dnl
4046 4046
 AC_DEFUN([AC_COMPILE_CHECK_SIZEOF],
4047 4047
 [changequote(<<, >>)dnl
... ...
@@ -58,7 +58,7 @@ int dirscan(const char *dirname, char **virname, unsigned long int *scanned, con
58 58
 	struct stat statbuf;
59 59
 	struct cfgstruct *cpt;
60 60
 	char *fname;
61
-	int ret = 0;
61
+	int ret = 0, scanret = 0;
62 62
 
63 63
     if((cpt = cfgopt(copt, "MaxDirectoryRecursion"))) {
64 64
 	if(cpt->numarg) {
... ...
@@ -88,7 +88,7 @@ int dirscan(const char *dirname, char **virname, unsigned long int *scanned, con
88 88
 			    }
89 89
 			} else
90 90
 			    if(S_ISREG(statbuf.st_mode) || (S_ISLNK(statbuf.st_mode) && (checksymlink(fname) == 2) && cfgopt(copt, "FollowFileSymlinks")))
91
-				if(cl_scanfile(fname, virname, scanned, root, limits, options) == CL_VIRUS) {
91
+				if((scanret = cl_scanfile(fname, virname, scanned, root, limits, options)) == CL_VIRUS) {
92 92
 				    mdprintf(odesc, "%s: %s FOUND\n", fname, *virname);
93 93
 				    logg("%s: %s FOUND\n", fname, *virname);
94 94
 				    virusaction(fname, *virname, copt);
... ...
@@ -98,6 +98,9 @@ int dirscan(const char *dirname, char **virname, unsigned long int *scanned, con
98 98
 					return 1;
99 99
 				    } else
100 100
 					ret = 2;
101
+				} else if(scanret != CL_CLEAN) {
102
+				    mdprintf(odesc, "%s: %s\n", fname, cl_strerror(scanret));
103
+				    logg("*%s: %s\n", fname, cl_strerror(scanret));
101 104
 				}
102 105
 		    }
103 106
 
... ...
@@ -1017,8 +1017,8 @@ Optional Packages:
1017 1017
   --with-user=uid	  name of the clamav user (default=clamav).
1018 1018
   --with-group=gid	  name of the clamav group (default=clamav).
1019 1019
   --with-dbdir=path	  Path to virus database directory.
1020
-  --with-db1=name	  Name of the main database (viruses.db).
1021
-  --with-db2=name	  Name of the new format database (viruses.db2).
1020
+  --with-db1=name	  Name of the main database (main.cvd).
1021
+  --with-db2=name	  Name of the daily database (daily.cvd).
1022 1022
 
1023 1023
 Some influential environment variables:
1024 1024
   CC          C compiler command
... ...
@@ -9025,7 +9025,7 @@ _ACEOF
9025 9025
 
9026 9026
 else
9027 9027
   cat >>confdefs.h <<\_ACEOF
9028
-#define DB1NAME "viruses.db"
9028
+#define DB1NAME "main.cvd"
9029 9029
 _ACEOF
9030 9030
 
9031 9031
 fi;
... ...
@@ -9040,7 +9040,7 @@ _ACEOF
9040 9040
 
9041 9041
 else
9042 9042
   cat >>confdefs.h <<\_ACEOF
9043
-#define DB2NAME "viruses.db2"
9043
+#define DB2NAME "daily.cvd"
9044 9044
 _ACEOF
9045 9045
 
9046 9046
 fi;
... ...
@@ -149,15 +149,15 @@ AC_ARG_WITH(dbdir,
149 149
 [  --with-dbdir=path	  Path to virus database directory.],
150 150
 db_dir="$withval", db_dir="_default_")
151 151
 
152
-dnl viruses.db
152
+dnl main.cvd
153 153
 AC_ARG_WITH(db1, 
154
-[  --with-db1=name	  Name of the main database (viruses.db).],
155
-AC_DEFINE_UNQUOTED(DB1NAME,"$withval",), AC_DEFINE(DB1NAME, "viruses.db"))
154
+[  --with-db1=name	  Name of the main database (main.cvd).],
155
+AC_DEFINE_UNQUOTED(DB1NAME,"$withval",), AC_DEFINE(DB1NAME, "main.cvd"))
156 156
 
157
-dnl viruses.db2
157
+dnl daily.cvd
158 158
 AC_ARG_WITH(db2, 
159
-[  --with-db2=name	  Name of the new format database (viruses.db2).],
160
-AC_DEFINE_UNQUOTED(DB2NAME,"$withval",), AC_DEFINE(DB2NAME, "viruses.db2"))
159
+[  --with-db2=name	  Name of the daily database (daily.cvd).],
160
+AC_DEFINE_UNQUOTED(DB2NAME,"$withval",), AC_DEFINE(DB2NAME, "daily.cvd"))
161 161
 
162 162
 dnl I had problems with $pkgdatadir, that's why I'm using these funny checks
163 163
 if test "$db_dir" = "_default_"
... ...
@@ -1,5 +1,5 @@
1 1
 #
2
-#  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+#  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
3 3
 #  Fixes by Arkadiusz Miskiewicz <misiek@pld.org.pl>
4 4
 #	    Masaki Ogawa <proc@mac.com>
5 5
 #
... ...
@@ -17,26 +17,26 @@
17 17
 #  along with this program; if not, write to the Free Software
18 18
 #  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 19
 
20
-EXTRA_DIST = viruses.db viruses.db2 mirrors.txt
20
+EXTRA_DIST = main.cvd daily.cvd mirrors.txt
21 21
 DBINST = @DBDIR@
22 22
 CLAMAVUSER = @CLAMAVUSER@
23 23
 CLAMAVGROUP = @CLAMAVGROUP@
24 24
  
25 25
 install:
26 26
 	$(mkinstalldirs) $(DESTDIR)$(DBINST)
27
-#	@$(INSTALL_DATA) viruses.db $(DESTDIR)$(DBINST)
28
-#	@$(INSTALL_DATA) viruses.db2 $(DESTDIR)$(DBINST)
27
+#	@$(INSTALL_DATA) main.cvd $(DESTDIR)$(DBINST)
28
+#	@$(INSTALL_DATA) daily.cvd $(DESTDIR)$(DBINST)
29 29
 	@$(INSTALL_DATA) mirrors.txt $(DESTDIR)$(DBINST)
30 30
 	@if test -n "${CLAMAVUSER}" && test -n "${CLAMAVGROUP}"; then \
31 31
 	    chmod 775 $(DESTDIR)$(DBINST); \
32 32
 	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST); \
33 33
 	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST); \
34
-	    chmod 664 $(DESTDIR)$(DBINST)/viruses.db; \
35
-	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/viruses.db; \
36
-	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/viruses.db; \
37
-	    chmod 664 $(DESTDIR)$(DBINST)/viruses.db2; \
38
-	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/viruses.db2; \
39
-	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/viruses.db2; \
34
+	    chmod 664 $(DESTDIR)$(DBINST)/main.cvd; \
35
+	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/main.cvd; \
36
+	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/main.cvd; \
37
+	    chmod 664 $(DESTDIR)$(DBINST)/daily.cvd; \
38
+	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/daily.cvd; \
39
+	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/daily.cvd; \
40 40
 	    chmod 664 $(DESTDIR)$(DBINST)/mirrors.txt; \
41 41
 	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/mirrors.txt; \
42 42
 	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/mirrors.txt; \
... ...
@@ -15,7 +15,7 @@
15 15
 @SET_MAKE@
16 16
 
17 17
 #
18
-#  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
18
+#  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
19 19
 #  Fixes by Arkadiusz Miskiewicz <misiek@pld.org.pl>
20 20
 #	    Masaki Ogawa <proc@mac.com>
21 21
 #
... ...
@@ -116,7 +116,7 @@ am__include = @am__include@
116 116
 am__quote = @am__quote@
117 117
 install_sh = @install_sh@
118 118
 
119
-EXTRA_DIST = viruses.db viruses.db2 mirrors.txt
119
+EXTRA_DIST = main.cvd daily.cvd mirrors.txt
120 120
 DBINST = @DBDIR@
121 121
 subdir = database
122 122
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
... ...
@@ -246,19 +246,19 @@ uninstall-am: uninstall-info-am
246 246
 
247 247
 install:
248 248
 	$(mkinstalldirs) $(DESTDIR)$(DBINST)
249
-#	@$(INSTALL_DATA) viruses.db $(DESTDIR)$(DBINST)
250
-#	@$(INSTALL_DATA) viruses.db2 $(DESTDIR)$(DBINST)
249
+#	@$(INSTALL_DATA) main.cvd $(DESTDIR)$(DBINST)
250
+#	@$(INSTALL_DATA) daily.cvd $(DESTDIR)$(DBINST)
251 251
 	@$(INSTALL_DATA) mirrors.txt $(DESTDIR)$(DBINST)
252 252
 	@if test -n "${CLAMAVUSER}" && test -n "${CLAMAVGROUP}"; then \
253 253
 	    chmod 775 $(DESTDIR)$(DBINST); \
254 254
 	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST); \
255 255
 	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST); \
256
-	    chmod 664 $(DESTDIR)$(DBINST)/viruses.db; \
257
-	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/viruses.db; \
258
-	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/viruses.db; \
259
-	    chmod 664 $(DESTDIR)$(DBINST)/viruses.db2; \
260
-	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/viruses.db2; \
261
-	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/viruses.db2; \
256
+	    chmod 664 $(DESTDIR)$(DBINST)/main.cvd; \
257
+	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/main.cvd; \
258
+	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/main.cvd; \
259
+	    chmod 664 $(DESTDIR)$(DBINST)/daily.cvd; \
260
+	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/daily.cvd; \
261
+	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/daily.cvd; \
262 262
 	    chmod 664 $(DESTDIR)$(DBINST)/mirrors.txt; \
263 263
 	    chown ${CLAMAVUSER} $(DESTDIR)$(DBINST)/mirrors.txt; \
264 264
 	    chgrp ${CLAMAVGROUP} $(DESTDIR)$(DBINST)/mirrors.txt; \
265 265
new file mode 100644
266 266
new file mode 100644
... ...
@@ -1,4 +1,3 @@
1
-clamav.elektrapro.com
2
-clamav.ozforces.com
3
-clamav.essentkabel.com
4
-clamav.org
1
+database.clamav.net
2
+database.clamav.net
3
+database.clamav.net
5 4
deleted file mode 100644
6 5
deleted file mode 100644
... ...
@@ -1,8 +1,8 @@
1 1
 .\" Manual page created by Tomasz Kojm, 14/15 IV 2002
2
-.TH "FreshClam" "1" "June 6, 2003" "Tomasz Kojm" "Clam AntiVirus"
2
+.TH "freshclam" "1" "October 25, 2003" "Tomasz Kojm" "Clam AntiVirus"
3 3
 .SH "NAME"
4 4
 .LP 
5
-freshclam \- update virus databases
5
+freshclam \- update ClamAV virus databases
6 6
 .SH "SYNOPSIS"
7 7
 .LP 
8 8
 freshclam [options]
... ...
@@ -22,6 +22,9 @@ Print the version number and exit.
22 22
 \fB\-v, \-\-verbose\fR
23 23
 Be verbose. This option causes freshclam to print many additional informations.
24 24
 .TP 
25
+\fB\-\-debug\fR
26
+Enable debug messages.
27
+.TP 
25 28
 \fB\-\-quiet\fR
26 29
 Be quiet \- output only error messages.
27 30
 .TP 
... ...
@@ -71,7 +74,7 @@ Execute COMMAND after succesful update.
71 71
 
72 72
 \fBfreshclam \-\-datadir .\fR
73 73
 .TP 
74
-(2) Run as daemon and check 2 times on day for new database:
74
+(2) Run as a daemon and check 2 times per day for a new database:
75 75
 
76 76
 \fBfreshclam \-d \-c 2\fR
77 77
 .SH "RETURN CODES"
... ...
@@ -89,7 +92,7 @@ Execute COMMAND after succesful update.
89 89
 .TP 
90 90
 53: Can't unlink file.
91 91
 .TP 
92
-54: MD5 checksum of downloaded database isn't ok.
92
+54: Verification (md5, digital signature) error.
93 93
 .TP 
94 94
 55: Error reading file.
95 95
 .TP 
... ...
@@ -63,6 +63,9 @@ void freshclam(struct optstruct *opt)
63 63
 
64 64
     /* initialize some important variables */
65 65
 
66
+    if(optl(opt, "debug"))
67
+	cl_debug();
68
+
66 69
     mprintf_disabled = 0;
67 70
 
68 71
     if(optc(opt, 'v')) mprintf_verbose = 1;
... ...
@@ -108,7 +111,7 @@ void freshclam(struct optstruct *opt)
108 108
 	mprintf("Can't change dir to %s\n", newdir);
109 109
 	exit(50);
110 110
     } else
111
-	mprintf("Current working dir is %s\n", newdir);
111
+	mprintf("*Current working dir is %s\n", newdir);
112 112
 
113 113
 
114 114
     if(optc(opt, 'd')) {
... ...
@@ -151,82 +154,14 @@ void freshclam(struct optstruct *opt)
151 151
 
152 152
 }
153 153
 
154
-/*void free_mirror(mirrors* m)
155
-{
156
-    mirrors *n;
157
-    
158
-    while(m)
159
-    {
160
-        n = m->next;
161
-        if(m->mirror != NULL)
162
-            free(m->mirror);
163
-        free(m);
164
-        m = n;
165
-    }
166
-
167
-}*/
168
-
169 154
 int download(struct optstruct *opt)
170 155
 {
171 156
 	int ret = 0;
172 157
 	mirrors *m = NULL, *h = NULL;
173
-	char *last = NULL;
174 158
 	char *datadir, *mirror_last;
175 159
 	int mirror_used = 0;
176 160
 
177 161
     /*
178
-     * If the previous database update was not from the first host
179
-     * listed in mirrors.txt it will have been saved to DBDIR/mirror.
180
-     * In this case use this host one more time (if it is up) for
181
-     * database updates then revert to the order in DBDIR/mirrors.txt
182
-     */    
183
-    last = parse_mirror(opt);
184
-
185
-    if(last != NULL)
186
-    {
187
-        if((ret = downloadmanager(opt, last)) == 0)
188
-        {
189
-            mprintf("Database updated from last used mirror %s.\n", last);
190
-
191
-	    if(optl(opt, "datadir"))
192
-	    {
193
-		datadir = getargl(opt, "datadir");
194
-	    }
195
-	    else
196
-	    {	
197
-		datadir = DATADIR;
198
-	    }
199
-
200
-	    if((mirror_last = malloc(sizeof(char) * (strlen(datadir) + strlen(MIRROR) + 1))) == NULL)
201
-	    {
202
-		fprintf(stderr, "ERROR: Can't allocate sufficient memory\n");
203
-		mexit(1);
204
-	    }
205
-
206
-	    strcpy(mirror_last, datadir);
207
-	    strcat(mirror_last, MIRROR);
208
-
209
-	    if(unlink(mirror_last) == -1)
210
-	    {
211
-		fprintf(stderr, "ERROR: Can't unlink file %s !\n", mirror_last);
212
-	    }
213
-
214
-            free(last);
215
-	    free(mirror_last);
216
-            return ret;
217
-        }
218
-
219
-        /* Only continue if there is an error connecting to the host */
220
-        if((ret != 52) && (ret != 54))
221
-        {
222
-            free(last);
223
-            return ret;
224
-        }
225
-
226
-    	free(last);
227
-    }
228
-        
229
-    /*
230 162
      * There's an error in __nss_hostname_digits_dots () from /lib/libc.so.6
231 163
      * which gets triggered here for some reason.....
232 164
      * Calling fflush is a temp workaround
... ...
@@ -243,36 +178,21 @@ int download(struct optstruct *opt)
243 243
             {
244 244
                 logg("Database updated from mirror %s.\n", m->mirror);
245 245
                 mprintf("Database updated from mirror %s.\n", m->mirror);
246
-                write_mirror(opt, m->mirror);
247
-            }
248
-            else
249
-            {
250
-                logg("Database updated from %s.\n", m->mirror);
251
-                mprintf("Database updated from %s.\n", m->mirror);
252 246
             }
253 247
 
254 248
             FREE_MIRROR(h);
255 249
             return ret;
256 250
         }
257 251
 
258
-        /* If we contacted a mirror then record the fact even if we
259
-         * don't update any databases this run
260
-         */
261
-        if(ret == 1)
262
-        {
263
-            if(mirror_used > 0)
264
-                write_mirror(opt, m->mirror);
265
-        
266
-            FREE_MIRROR(h);
267
-            return ret;
268
-        }
269
-           
270 252
         /* Only continue if there is an error connecting to the host */
271 253
         if((ret != 52) && (ret != 54))
272 254
         {
273 255
             FREE_MIRROR(h);
274 256
             return ret;
275 257
         }
258
+
259
+	mprintf("Waiting 10 seconds...\n");
260
+	sleep(10);
276 261
         mirror_used++;
277 262
         m = m->next;
278 263
     }
... ...
@@ -281,117 +201,6 @@ int download(struct optstruct *opt)
281 281
     return ret;
282 282
 }
283 283
 
284
-void write_mirror(struct optstruct *opt, char * mirror)
285
-{
286
-    char *datadir, *mirror_last;
287
-    FILE *fd;
288
-    
289
-    if(optl(opt, "datadir"))
290
-    {
291
-        datadir = getargl(opt, "datadir");
292
-    }
293
-    else
294
-    {
295
-        datadir = DATADIR;
296
-    }
297
-
298
-    if((mirror_last = malloc(sizeof(char) * (strlen(datadir) + strlen(MIRROR) + 1))) == NULL)
299
-    {
300
-        fprintf(stderr, "ERROR: Can't allocate sufficient memory\n");
301
-        mexit(1);
302
-    }
303
-
304
-    strcpy(mirror_last, datadir);
305
-
306
-    strcat(mirror_last, MIRROR);
307
-
308
-    if((fd = fopen(mirror_last, "w")) == NULL)
309
-    {
310
-        /* No mirror was used last time - this is normal */
311
-        fprintf(stderr, "ERROR: Can't create file %s !\n", mirror_last);
312
-        free(mirror_last);
313
-        return;
314
-    }
315
-    
316
-    if(!fputs(mirror, fd))
317
-    {
318
-        fprintf(stderr, "ERROR: Can't write to file %s !\n", mirror_last);
319
-    }
320
-
321
-    fclose(fd);
322
-    free(mirror_last);
323
-    
324
-    return;
325
-}
326
-
327
-/*
328
- * If the previous database update was not from the first host
329
- * listed in mirrors.txt it will have been saved to DBDIR/mirror.
330
- * In this case use this host one more time (if it is up) for
331
- * database updates then revert to the order in DBDIR/mirrors.txt
332
- */
333
-char * parse_mirror(struct optstruct *opt)
334
-{
335
-    char *datadir = NULL, *mirror_last  = NULL, *last = NULL;
336
-    FILE *fd;
337
-    char buf[BUFSIZ];
338
-    
339
-    if(optl(opt, "datadir"))
340
-    {
341
-        datadir = getargl(opt, "datadir");
342
-    }
343
-    else
344
-    {
345
-        datadir = DATADIR;
346
-    }
347
-
348
-    if((mirror_last = malloc(sizeof(char) * (strlen(datadir) + strlen(MIRROR) + 1))) == NULL)
349
-    {
350
-        fprintf(stderr, "ERROR: Can't allocate sufficient memory\n");
351
-        mexit(1);
352
-    }
353
-
354
-    strcpy(mirror_last, datadir);
355
-
356
-    strcat(mirror_last, MIRROR);
357
-
358
-    if((fd = fopen(mirror_last, "r")) == NULL)
359
-    {
360
-        /* No mirror was used last time - this is normal */
361
-        free(mirror_last);
362
-        return NULL;
363
-    }
364
-
365
-    while(fgets(buf, BUFSIZ, fd))
366
-    {
367
-        if(buf[0] == '#')
368
-            continue;
369
-
370
-        if(strlen(buf) > 0)
371
-        {
372
-            if((last = malloc(sizeof(char) * (strlen(buf) +1))) == NULL)
373
-            {
374
-                fprintf(stderr, "ERROR: Can't allocate sufficient memory\n");
375
-                free(mirror_last);
376
-                return NULL;
377
-            }
378
-
379
-            chomp(buf);
380
-            strcpy(last, buf);
381
-            break;
382
-        }    
383
-    }
384
-
385
-    if(fclose(fd) != 0)
386
-    {
387
-        fprintf(stderr, "ERROR: Can't close fd !\n");
388
-    }
389
-
390
-    free(mirror_last);
391
-
392
-    return last;
393
-}
394
-
395 284
 mirrors* parse_mirrorcfg(struct optstruct *opt)
396 285
 {
397 286
     mirrors *head = NULL, *curr = NULL, *prev = NULL;
... ...
@@ -504,12 +313,13 @@ void help(void)
504 504
     mprintf_stdout = 1;
505 505
 
506 506
     mprintf("\n");
507
-    mprintf("		   Clam AntiVirus: FreshClam  "VERSION"\n");
508
-    mprintf("		   (c) 2002 Tomasz Kojm <zolw@konarski.edu.pl>\n");
507
+    mprintf("		   Clam AntiVirus: freshclam  "VERSION"\n");
508
+    mprintf("		   (c) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>\n");
509 509
     mprintf("	  \n");
510 510
     mprintf("    --help		    -h		show help\n");
511 511
     mprintf("    --version		    -V		print version number and exit\n");
512 512
     mprintf("    --verbose		    -v		be verbose\n");
513
+    mprintf("    --debug		    		enable debug messages\n");
513 514
     mprintf("    --quiet				be quiet, output only error messages\n");
514 515
     mprintf("    --stdout				write to stdout instead of stderr\n");
515 516
     mprintf("					(this help is always written to stdout)\n");
... ...
@@ -44,47 +44,67 @@
44 44
 
45 45
 int downloadmanager(const struct optstruct *opt, const char *hostname)
46 46
 {
47
-	char *oldmd5 = NULL, *old2md5 = NULL, *newmd5 = NULL, 
48
-	     *new2md5 = NULL, *downmd5, *tempname;
49
-	int hostfd, vir;
50
-	short int updatedb = 0, updatedb2 = 0, nodb = 0, nodb2 = 0;
51 47
 	time_t currtime;
52
-	const char *proxy;	/* proxy support njh@bandsman.co.uk */
53
-	const char *user;
48
+	int ret, updated = 0, signo = 0;
49
+
54 50
 
55 51
     time(&currtime);
56
-    logg("Checking for a new database - started at %s", ctime(&currtime));
57
-    mprintf("Checking for a new database - started at %s", ctime(&currtime));
52
+    mprintf("ClamAV update process started at %s", ctime(&currtime));
53
+    logg("ClamAV update process started at %s", ctime(&currtime));
58 54
 
55
+#ifndef HAVE_GMP
56
+    mprintf("SECURITY WARNING: NO SUPPORT FOR DIGITAL SIGNATURES\n");
57
+    logg("SECURITY WARNING: NO SUPPORT FOR DIGITAL SIGNATURES\n");
58
+#endif
59 59
 
60
-    /* first thing we want is a local file md5 checksum */
61
-    if(fileinfo(DB1NAME, 1) == -1) {
62
-	/* there is no database, so we just download a new one */
63
-	nodb = 1; 
64
-	mprintf(DB1NAME" not found in the data directory.\n");
65
-    } else {
66
-	if((oldmd5 = cl_md5file(DB1NAME)) == NULL) {
67
-	    mprintf("@Can't create md5 checksum of the "DB1NAME" database.\n");
68
-	    return 51;
69
-	}
70
-    }
60
+    if((ret = downloaddb(DB1NAME, "main.cvd", hostname, &signo, opt)) > 50)
61
+	return ret;
62
+    else if(ret == 0)
63
+	updated = 1;
71 64
 
72
-    if(fileinfo(DB2NAME, 1) == -1) {
73
-	nodb2 = 1; 
74
-	mprintf(DB2NAME" not found in the data directory.\n");
75
-    } else {
76
-	if((old2md5 = cl_md5file(DB2NAME)) == NULL) {
77
-	    mprintf("@Can't create md5 checksum of the "DB2NAME" database.\n");
78
-	    return 51;
65
+    if((ret = downloaddb(DB2NAME, "daily.cvd", hostname, &signo, opt)) > 50)
66
+	return ret;
67
+    else if(ret == 0)
68
+	updated = 1;
69
+
70
+    if(updated) {
71
+	mprintf("Database updated (%d signatures) from %s.\n", signo, hostname);
72
+	logg("Database updated (%d signatures) from %s.\n", signo, hostname);
73
+
74
+#ifdef BUILD_CLAMD
75
+	if(optl(opt, "daemon-notify")) {
76
+		const char *clamav_conf = getargl(opt, "daemon-notify");
77
+	    if(!clamav_conf)
78
+		clamav_conf = DEFAULT_CFG;
79
+
80
+	    notify(clamav_conf);
79 81
 	}
80
-    }
82
+#endif
83
+
84
+	if(optl(opt, "on-update-execute"))
85
+	    system(getargl(opt, "on-update-execute"));
86
+
87
+	return 0;
88
+
89
+    } else
90
+	return 1;
91
+}
92
+
93
+int downloaddb(const char *localname, const char *remotename, const char *hostname, int *signo, const struct optstruct *opt)
94
+{
95
+	struct cl_cvd *current, *remote;
96
+	int hostfd, nodb = 0, ret;
97
+	char  *tempname;
98
+	const char *proxy, *user;
99
+
81 100
 
101
+    if((current = cl_cvdhead(localname)) == NULL)
102
+	nodb = 1;
82 103
 
83
-    if(optl(opt, "proxy-user")) {
104
+    if(optl(opt, "proxy-user"))
84 105
 	user = getargl(opt, "proxy-user");
85
-    } else {
106
+    else
86 107
 	user = NULL;
87
-    }
88 108
 
89 109
     /*
90 110
      * njh@bandsman.co.uk: added proxy support. Tested using squid 2.4
... ...
@@ -111,7 +131,7 @@ int downloadmanager(const struct optstruct *opt, const char *hostname)
111 111
 		proxy = NULL;
112 112
     }
113 113
     if(proxy)
114
-	mprintf("*Connecting via %s\n", proxy);
114
+	mprintf("Connecting via %s\n", proxy);
115 115
 
116 116
     hostfd = wwwconnect(hostname, proxy);
117 117
 
... ...
@@ -119,22 +139,30 @@ int downloadmanager(const struct optstruct *opt, const char *hostname)
119 119
 	mprintf("@Connection with %s failed.\n", hostname);
120 120
 	return 52;
121 121
     } else
122
-	mprintf("Connected to %s.\n", hostname);
122
+	mprintf("*Connected to %s.\n", hostname);
123 123
 
124 124
 
125
-    if((newmd5 = get_md5_checksum("viruses.md5", hostfd, hostname, proxy, user)) == NULL) {
126
-	mprintf("@Can't get viruses.md5 sum from %s\n", hostname);
125
+    if(!(remote = remote_cvdhead(remotename, hostfd, hostname, proxy, user))) {
126
+	mprintf("@Can't read %s header from %s\n", remotename, hostname);
127 127
 	close(hostfd);
128 128
 	return 52;
129 129
     }
130 130
 
131
-    /* ok, we have md5 sum from Internet */
131
+    *signo += current->sigs; /* we need to do it just here */
132 132
 
133
-    if(oldmd5 && !strncmp(oldmd5, newmd5, 32)) {
134
-	mprintf(DB1NAME" is up to date.\n");
135
-	logg(DB1NAME" is up to date.\n");
136
-    } else
137
-	updatedb = 1;
133
+    if(current && (current->version >= remote->version)) {
134
+	mprintf("%s is up to date (version: %d, sigs: %d, f-level: %d, builder: %s)\n", localname, current->version, current->sigs, current->fl, current->builder);
135
+	logg("%s is up to date (version: %d, sigs: %d, f-level: %d, builder: %s)\n", localname, current->version, current->sigs, current->fl, current->builder);
136
+	close(hostfd);
137
+	cl_cvdfree(current);
138
+	cl_cvdfree(remote);
139
+	return 1;
140
+    }
141
+
142
+    if(current)
143
+	cl_cvdfree(current);
144
+
145
+    cl_cvdfree(remote);
138 146
 
139 147
     /* FIXME: We need to reconnect, because we won't be able to donwload
140 148
      * the database. The problem doesn't exist with my local apache.
... ...
@@ -150,160 +178,46 @@ int downloadmanager(const struct optstruct *opt, const char *hostname)
150 150
     };
151 151
     /* end */
152 152
 
153
-    if((new2md5 = get_md5_checksum("viruses2.md5", hostfd, hostname, proxy, user)) == NULL) {
154
-	mprintf("@Can't get viruses2.md5 sum from %s\n", hostname);
155
-	close(hostfd);
156
-	return 52;
157
-    }
158
-
159
-    /* ok, we have md5 sum from Internet */
160
-
161
-    if(old2md5 && !strncmp(old2md5, new2md5, 32)) {
162
-	mprintf(DB2NAME" is up to date.\n");
163
-	logg(DB2NAME" is up to date.\n");
164
-    } else
165
-	updatedb2 = 1;
166
-
167
-    if(!updatedb && !updatedb2) {
168
-	close(hostfd);
169
-	return 1;
153
+    /* temporary file is created in clamav's directory thus we don't need
154
+     * to create it immediately because race condition is not possible here
155
+     */
156
+    tempname = cl_gentemp(".");
157
+
158
+    if(get_database(remotename, hostfd, tempname, hostname, proxy, user)) {
159
+        mprintf("@Can't download %s from %s\n", remotename, hostname);
160
+        unlink(tempname);
161
+        free(tempname);
162
+        close(hostfd);
163
+        return 52;
170 164
     }
171 165
 
172
-    if(updatedb) {
173
-
174
-	/* temporary file is created in clamav's directory thus we don't need
175
-	 * to create it immediately, because race conditions are impossible
176
-	 */
177
-	tempname = cl_gentemp(".");
178
-
179
-	/* download the database */
180
-	/* FIXME: We need to reconnect, because we won't be able to donwload
181
-	 * the database. The problem doesn't exist with my local apache.
182
-	 * Some code change is needed in get_md5_checksum().
183
-	 */
184
-
185
-	/* begin bug work-around */
186
-	close(hostfd);
187
-	hostfd = wwwconnect(hostname, proxy);
188
-
189
-	if(hostfd < 0) {
190
-	    mprintf("@Connection with %s failed.\n", hostname);
191
-	    free(tempname);
192
-	    return 52;
193
-	};
194
-	/* end */
195
-
196
-	if(get_database(DB1NAME, hostfd, tempname, hostname, proxy, user)) {
197
-	    mprintf("@Can't download "DB1NAME" from %s\n", hostname);
198
-	    unlink(tempname);
199
-	    free(tempname);
200
-	    close(hostfd);
201
-	    return 52;
202
-	}
203
-
204
-	close(hostfd);
205
-
206
-	/* ok, we have new database */
207
-	if((downmd5 = cl_md5file(tempname)) == NULL) {
208
-	    unlink(tempname);
209
-	    free(tempname);
210
-	    mprintf("@Can't create md5 checksum of the virus database.\n");
211
-	    return 51;
212
-	}
213
-
214
-	if(!strcmp(newmd5, downmd5)) {
215
-	    if(!nodb && unlink(DB1NAME)) {
216
-		mprintf("@Can't unlink "DB1NAME" file. Fix the problem and try again.\n");
217
-		unlink(tempname);
218
-		free(tempname);
219
-		return 53;
220
-	    } else
221
-		rename(tempname, DB1NAME);
222
-	} else {
223
-	    mprintf("@The checksum of "DB1NAME" database isn't ok. Please check it yourself or try again.\n");
224
-	    unlink(tempname);
225
-	    free(tempname);
226
-	    return 54;
227
-	}
166
+    close(hostfd);
228 167
 
229
-	unlink(tempname);
230
-	free(tempname);
231
-	free(downmd5);
168
+    if((ret = cl_cvdverify(tempname))) {
169
+        mprintf("@Verification: %s\n", cl_strerror(ret));
170
+        unlink(tempname);
171
+        free(tempname);
172
+        return 54;
232 173
     }
233 174
 
234
-    if(updatedb2) {
235
-	tempname = cl_gentemp(".");
236
-
237
-	/* download viruses.db2 */
238
-
239
-	/* begin bug work-around */
240
-	close(hostfd);
241
-	hostfd = wwwconnect(hostname, proxy);
242
-
243
-	if(hostfd < 0) {
244
-	    mprintf("@Connection with %s failed.\n", hostname);
245
-	    free(tempname);
246
-	    return 52;
247
-	};
248
-	/* end */
249
-
250
-	if(get_database(DB2NAME, hostfd, tempname, hostname, proxy, user)) {
251
-	    mprintf("@Can't download "DB2NAME" from %s\n", hostname);
252
-	    unlink(tempname);
253
-	    free(tempname);
254
-	    close(hostfd);
255
-	    return 52;
256
-	}
257
-
258
-	close(hostfd);
259
-
260
-	/* ok, we have new database */
261
-	if((downmd5 = cl_md5file(tempname)) == NULL) {
262
-	    unlink(tempname);
263
-	    free(tempname);
264
-	    mprintf("@Can't create md5 checksum of the virus database.\n");
265
-	    return 51;
266
-	}
267
-
268
-	if(!strcmp(new2md5, downmd5)) {
269
-	    if(!nodb2 && unlink(DB2NAME)) {
270
-		mprintf("@Can't unlink "DB2NAME" file. Fix the problem and try again.\n");
271
-		unlink(tempname);
272
-		free(tempname);
273
-		return 53;
274
-	    } else
275
-		rename(tempname, DB2NAME);
276
-	} else {
277
-	    mprintf("@The checksum of "DB2NAME" database isn't ok. Please check it yourself or try again.\n");
278
-	    unlink(tempname);
279
-	    free(tempname);
280
-	    return 54;
281
-	}
282
-
175
+    if(!nodb && unlink(localname)) {
176
+	mprintf("@Can't unlink %s. Please fix it and try again.\n", localname);
283 177
 	unlink(tempname);
284 178
 	free(tempname);
285
-	free(downmd5);
286
-    }
287
-
288
-    vir = countlines(DB1NAME);
289
-    vir += countlines(DB2NAME);
290
-
291
-    mprintf("Database updated (containing in total %d signatures).\n", vir);
292
-    logg("Database updated (containing in total %d signatures).\n", vir);
293
-
294
-#ifdef BUILD_CLAMD
295
-    if(optl(opt, "daemon-notify")) {
296
-	    const char *clamav_conf = getargl(opt, "daemon-notify");
297
-	if(!clamav_conf)
298
-	    clamav_conf = DEFAULT_CFG;
179
+	return 53;
180
+    } else
181
+	rename(tempname, localname);
299 182
 
300
-	notify(clamav_conf);
183
+    if((current = cl_cvdhead(localname)) == NULL) {
184
+	mprintf("@Can't read CVD header of new %s database.\n", localname);
185
+	return 54;
301 186
     }
302
-#endif
303 187
 
304
-    if(optl(opt, "on-update-execute"))
305
-	system(getargl(opt, "on-update-execute"));
188
+    mprintf("%s updated (version: %d, sigs: %d, f-level: %d, builder: %s)\n", localname, current->version, current->sigs, current->fl, current->builder);
189
+    logg("%s updated (version: %d, sigs: %d, f-level: %d, builder: %s)\n", localname, current->version, current->sigs, current->fl, current->builder);
306 190
 
191
+    cl_cvdfree(current);
192
+    free(tempname);
307 193
     return 0;
308 194
 }
309 195
 
... ...
@@ -379,13 +293,12 @@ wwwconnect(const char *server, const char *proxy)
379 379
 
380 380
 /* njh@bandsman.co.uk: added proxy support */
381 381
 /* TODO: use a HEAD instruction to see if the file has been changed */
382
-char *
383
-get_md5_checksum(const char *file, int socketfd, const char *hostname, const char *proxy, const char *user)
382
+struct cl_cvd *remote_cvdhead(const char *file, int socketfd, const char *hostname, const char *proxy, const char *user)
384 383
 {
385
-	char cmd[512], buffer[FBUFFSIZE];
386
-	char *md5sum, *ch, *tmp;
384
+	char cmd[512], head[513], buffer[FBUFFSIZE], *ch, *tmp;
387 385
 	int i, j, bread, cnt;
388 386
 	char *remotename = NULL, *authorization = NULL;
387
+	struct cl_cvd *cvd;
389 388
 
390 389
     if(proxy) {
391 390
         remotename = mmalloc(strlen(hostname) + 8);
... ...
@@ -402,17 +315,17 @@ get_md5_checksum(const char *file, int socketfd, const char *hostname, const cha
402 402
 	}
403 403
     }
404 404
 
405
-    mprintf("Reading md5 sum (%s): ", file);
405
+    mprintf("Reading CVD header (%s): ", file);
406 406
 
407 407
 #ifdef	NO_SNPRINTF
408
-    sprintf(cmd, "GET %s/database/%s HTTP/1.1\r\n"
408
+    sprintf(cmd, "GET %s/%s HTTP/1.1\r\n"
409 409
 	"Host: %s\r\n%s"
410 410
 	"User-Agent: "PACKAGE"/"VERSION"\r\n"
411 411
 	"Cache-Control: no-cache\r\n"
412 412
 	"Connection: close\r\n"
413 413
 	"\r\n", (remotename != NULL)?remotename:"", file, hostname, (authorization != NULL)?authorization:"");
414 414
 #else
415
-    snprintf(cmd, sizeof(cmd), "GET %s/database/%s HTTP/1.1\r\n"
415
+    snprintf(cmd, sizeof(cmd), "GET %s/%s HTTP/1.1\r\n"
416 416
 	     "Host: %s\r\n%s"
417 417
 	     "User-Agent: "PACKAGE"/"VERSION"\r\n"
418 418
 	     "Cache-Control: no-cache\r\n"
... ...
@@ -433,12 +346,12 @@ get_md5_checksum(const char *file, int socketfd, const char *hostname, const cha
433 433
     }
434 434
 
435 435
     if(bread == -1) {
436
-	mprintf("@Error while reading md5 sum of database from %s\n", hostname);
436
+	mprintf("@Error while reading CVD header of database from %s\n", hostname);
437 437
 	return NULL;
438 438
     }
439 439
 
440 440
     if ((strstr(buffer, "HTTP/1.1 404")) != NULL) { 
441
-      mprintf("@md5 sum not found on remote server\n");
441
+      mprintf("@CVD file not found on remote server\n");
442 442
       return NULL;
443 443
     }
444 444
 
... ...
@@ -454,19 +367,22 @@ get_md5_checksum(const char *file, int socketfd, const char *hostname, const cha
454 454
       i++;
455 455
     }  
456 456
 
457
-    md5sum = (char *) mcalloc(33, sizeof(char));
458
-    
459
-    for (j=0; j<32; j++) {
460
-      if (!ch || (ch && !*ch) || (ch && !isalnum(ch[j]))) {
461
-	mprintf("@Malformed md5 checksum detected.\n");
462
-	free(md5sum);
457
+    memset(head, 0, sizeof(head));
458
+
459
+    for (j=0; j<512; j++) {
460
+      if (!ch || (ch && !*ch) || (ch && !isprint(ch[j]))) {
461
+	mprintf("@Malformed CVD header detected.\n");
463 462
 	return NULL;
464 463
       }
465
-      md5sum[j] = ch[j];
464
+      head[j] = ch[j];
466 465
     }
467 466
 
468
-    mprintf("OK\n");
469
-    return md5sum;
467
+    if((cvd = cl_cvdparse(head)) == NULL)
468
+	mprintf("@Broken CVD header.\n");
469
+    else
470
+	mprintf("OK\n");
471
+
472
+    return cvd;
470 473
 }
471 474
 
472 475
 /* njh@bandsman.co.uk: added proxy support */
... ...
@@ -476,8 +392,9 @@ get_database(const char *dbfile, int socketfd, const char *file, const char *hos
476 476
 {
477 477
 	char cmd[512], buffer[FBUFFSIZE];
478 478
 	char *ch;
479
-	int bread, fd, i;
479
+	int bread, fd, i, rot = 0;
480 480
 	char *remotename = NULL, *authorization = NULL;
481
+	const char *rotation = "|/-\\";
481 482
 
482 483
 
483 484
     if(proxy) {
... ...
@@ -502,14 +419,14 @@ get_database(const char *dbfile, int socketfd, const char *file, const char *hos
502 502
     }
503 503
 
504 504
 #ifdef NO_SNPRINTF
505
-    sprintf(cmd, "GET %s/database/%s HTTP/1.1\r\n"
505
+    sprintf(cmd, "GET %s/%s HTTP/1.1\r\n"
506 506
 	     "Host: %s\r\n%s"
507 507
 	     "User-Agent: "PACKAGE"/"VERSION"\r\n"
508 508
 	     "Cache-Control: no-cache\r\n"
509 509
 	     "Connection: close\r\n"
510 510
 	     "\r\n", (remotename != NULL)?remotename:"", dbfile, hostname, (authorization != NULL)?authorization:"");
511 511
 #else
512
-    snprintf(cmd, sizeof(cmd), "GET %s/database/%s HTTP/1.1\r\n"
512
+    snprintf(cmd, sizeof(cmd), "GET %s/%s HTTP/1.1\r\n"
513 513
 	     "Host: %s\r\n%s"
514 514
 	     "User-Agent: "PACKAGE"/"VERSION"\r\n"
515 515
 	     "Cache-Control: no-cache\r\n"
... ...
@@ -531,8 +448,6 @@ get_database(const char *dbfile, int socketfd, const char *file, const char *hos
531 531
       return -1;
532 532
     }
533 533
 
534
-    mprintf("Downloading %s ", dbfile);
535
-
536 534
     ch = buffer;
537 535
     i = 0;
538 536
     while (1) {
... ...
@@ -548,30 +463,16 @@ get_database(const char *dbfile, int socketfd, const char *file, const char *hos
548 548
     write(fd, ch, bread - i);
549 549
     while((bread = read(socketfd, buffer, FBUFFSIZE))) {
550 550
 	write(fd, buffer, bread);
551
-	mprintf(".");
551
+	mprintf("Downloading %s [%c]\r", dbfile, rotation[rot]);
552
+	fflush(stdout);
553
+	rot = ++rot % 4;
552 554
     }
553 555
 
554
-    mprintf(" done\n");
556
+    mprintf("Downloading %s [*]\n", dbfile);
555 557
     close(fd);
556 558
     return 0;
557 559
 }
558 560
 
559
-int countlines(const char *filename)
560
-{
561
-	FILE *fd;
562
-	char buff[65536];
563
-	int lines = 0;
564
-
565
-    if((fd = fopen(filename, "r")) == NULL)
566
-	return 0;
567
-
568
-    while(fgets(buff, sizeof(buff), fd))
569
-	lines++;
570
-
571
-    fclose(fd);
572
-    return lines;
573
-}
574
-
575 561
 const char base64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
576 562
 
577 563
 unsigned int fmt_base64(char* dest,const char* src,unsigned int len) {
... ...
@@ -20,12 +20,18 @@
20 20
 #define __MANAGER_H
21 21
 
22 22
 #include "options.h"
23
+#include "clamav.h"
23 24
 
24 25
 int downloadmanager(const struct optstruct *opt, const char *hostname);
26
+
27
+int downloaddb(const char *localname, const char *remotename, const char *hostname, int *signo, const struct optstruct *opt);
28
+
25 29
 int wwwconnect(const char *server, const char *proxy);
26
-char *get_md5_checksum(const char *dbfile, int socketfd, const char *hostname, const char *proxy, const char *user);
30
+
31
+struct cl_cvd *remote_cvdhead(const char *file, int socketfd, const char *hostname, const char *proxy, const char *user);
32
+
27 33
 int get_database(const char *dbfile, int socketfd, const char *file, const char *hostname, const char *proxy, const char *user);
28
-int countlines(const char *filename);
34
+
29 35
 unsigned int fmt_base64(char* dest,const char* src,unsigned int len);
30 36
 
31 37
 #endif
... ...
@@ -40,6 +40,7 @@ int main(int argc, char **argv)
40 40
 	    {"help", 0, 0, 'h'},
41 41
 	    {"quiet", 0, 0, 0},
42 42
 	    {"verbose", 0, 0, 'v'},
43
+	    {"debug", 0, 0, 0},
43 44
 	    {"version", 0, 0, 'V'},
44 45
 	    {"datadir", 1, 0, 0},
45 46
 	    {"log", 1, 0, 'l'},
... ...
@@ -67,17 +67,17 @@ extern "C"
67 67
 #define CL_MAIL		0100
68 68
 #define CL_DISABLERAR  01000
69 69
 
70
-struct patt {
70
+struct cli_patt {
71 71
     short int *pattern;
72 72
     unsigned int length;
73 73
     char *virname;
74 74
     unsigned short int sigid, parts, partno;
75
-    struct patt *next;
75
+    struct cli_patt *next;
76 76
 };
77 77
 
78 78
 struct cl_node {
79 79
     char islast;
80
-    struct patt *list;
80
+    struct cli_patt *list;
81 81
     struct cl_node *trans[CL_NUM_CHILDS], *fail;
82 82
 
83 83
     /* FIXME: these variables are only used in a root node */
... ...
@@ -122,6 +122,8 @@ extern int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum)
122 122
 extern char *cl_retdbdir(void);
123 123
 
124 124
 extern struct cl_cvd *cl_cvdhead(const char *file);
125
+extern struct cl_cvd *cl_cvdparse(const char *head);
126
+extern int cl_cvdverify(const char *file);
125 127
 extern void cl_cvdfree(struct cl_cvd *cvd);
126 128
 
127 129
 /* data dir stat functions */
... ...
@@ -29,6 +29,7 @@
29 29
 #include "clamav.h"
30 30
 #include "others.h"
31 31
 #include "dsig.h"
32
+#include "str.h"
32 33
 
33 34
 #define TAR_BLOCKSIZE 512
34 35
 
... ...
@@ -140,69 +141,34 @@ int cli_untgz(int fd, const char *destdir)
140 140
     return 0;
141 141
 }
142 142
 
143
-char *cli_cut(const char *line, int field)
143
+struct cl_cvd *cl_cvdparse(const char *head)
144 144
 {
145
-        int length, counter = 0, i, j = 0;
146
-        char *buffer;
147
-
148
-    length = strlen(line);
149
-    buffer = (char *) cli_calloc(length, sizeof(char));
150
-
151
-    for(i = 0; i < length; i++) {
152
-        if(line[i] == ':') {
153
-            counter++;
154
-            if(counter == field) {
155
-		break;
156
-	    } else {
157
-		memset(buffer, 0, length);
158
-		j = 0;
159
-	    }
160
-        } else {
161
-            buffer[j++] = line[i];
162
-        }
163
-    }
164
-
165
-    return (char *) cli_realloc(buffer, strlen(buffer) + 1);
166
-}
167
-
168
-struct cl_cvd *cli_cvdhead(FILE *fd)
169
-{
170
-	char *pt, head[513];
145
+	char *pt;
171 146
 	struct cl_cvd *cvd;
172
-	int i;
173
-
174
-
175
-    if(fread(head, 1, 512, fd) != 512) {
176
-	cli_errmsg("Can't read CVD head from stream\n");
177
-	return NULL;
178
-    }
179
-
180
-    head[512] = 0;
181
-    for(i = 511; i > 0 && (head[i] == ' ' || head[i] == 10); head[i] = 0, i--);
182 147
 
183 148
     if(strncmp(head, "ClamAV-VDB:", 11)) {
184
-	cli_errmsg("Not a CVD file.\n");
149
+	cli_dbgmsg("Not a CVD head.\n");
185 150
 	return NULL;
186 151
     }
187 152
 
188 153
     cvd = (struct cl_cvd *) cli_calloc(1, sizeof(struct cl_cvd));
189
-    cvd->time = cli_cut(head, 2);
154
+    cvd->time = cli_tok(head, 2, ':');
190 155
 
191
-    pt = cli_cut(head, 3);
156
+    pt = cli_tok(head, 3, ':');
192 157
     cvd->version = atoi(pt);
193 158
     free(pt);
194 159
 
195
-    pt = cli_cut(head, 4);
160
+    pt = cli_tok(head, 4, ':');
196 161
     cvd->sigs = atoi(pt);
197 162
     free(pt);
198 163
 
199
-    pt = cli_cut(head, 5);
164
+    pt = cli_tok(head, 5, ':');
200 165
     cvd->fl = (short int) atoi(pt);
201 166
     free(pt);
202 167
 
203
-    cvd->md5 = cli_cut(head, 6);
204
-    cvd->dsig = cli_cut(head, 7);
205
-    cvd->builder = cli_cut(head, 8);
168
+    cvd->md5 = cli_tok(head, 6, ':');
169
+    cvd->dsig = cli_tok(head, 7, ':');
170
+    cvd->builder = cli_tok(head, 8, ':');
206 171
 
207 172
     return cvd;
208 173
 }
... ...
@@ -210,13 +176,25 @@ struct cl_cvd *cli_cvdhead(FILE *fd)
210 210
 struct cl_cvd *cl_cvdhead(const char *file)
211 211
 {
212 212
 	FILE *fd;
213
+	char head[513];
214
+	int i;
213 215
 
214 216
     if((fd = fopen(file, "rb")) == NULL) {
215
-	cli_errmsg("Can't open CVD file %s\n", file);
217
+	cli_dbgmsg("Can't open CVD file %s\n", file);
216 218
 	return NULL;
217 219
     }
218 220
 
219
-    return cli_cvdhead(fd);
221
+    if(fread(head, 1, 512, fd) != 512) {
222
+	cli_dbgmsg("Can't read CVD head from stream\n");
223
+	return NULL;
224
+    }
225
+
226
+    fclose(fd);
227
+
228
+    head[512] = 0;
229
+    for(i = 511; i > 0 && (head[i] == ' ' || head[i] == 10); head[i] = 0, i--);
230
+
231
+    return cl_cvdparse(head);
220 232
 }
221 233
 
222 234
 void cl_cvdfree(struct cl_cvd *cvd)
... ...
@@ -230,43 +208,57 @@ void cl_cvdfree(struct cl_cvd *cvd)
230 230
 
231 231
 int cli_cvdverify(FILE *fd)
232 232
 {
233
-	struct cl_cvd *head;
234
-	char *md5;
233
+	struct cl_cvd *cvd;
234
+	char *md5, head[513];
235
+	int i;
236
+
237
+    fseek(fd, 0, SEEK_SET);
238
+    if(fread(head, 1, 512, fd) != 512) {
239
+	cli_dbgmsg("Can't read CVD head from stream\n");
240
+	return CL_ECVD;
241
+    }
242
+
243
+    head[512] = 0;
244
+    for(i = 511; i > 0 && (head[i] == ' ' || head[i] == 10); head[i] = 0, i--);
235 245
 
236
-    if((head = cli_cvdhead(fd)) == NULL)
246
+    if((cvd = cl_cvdparse(head)) == NULL)
237 247
 	return CL_ECVD;
238 248
 
239
-    //fseek(fd, 512, SEEK_SET);
240 249
 
241 250
     md5 = cli_md5stream(fd);
242
-
243 251
     cli_dbgmsg("MD5(.tar.gz) = %s\n", md5);
244 252
 
245
-    if(strncmp(md5, head->md5, 32)) {
253
+    if(strncmp(md5, cvd->md5, 32)) {
246 254
 	cli_dbgmsg("MD5 verification error.\n");
247 255
 	return CL_EMD5;
248 256
     }
249 257
 
250 258
 #ifdef HAVE_GMP
251
-    if(cli_versig(md5, head->dsig)) {
259
+    if(cli_versig(md5, cvd->dsig)) {
252 260
 	cli_dbgmsg("Digital signature verification error.\n");
253 261
 	return CL_EDSIG;
254 262
     }
255 263
 #endif
256 264
 
265
+    free(md5);
266
+    free(cvd);
257 267
     return 0;
258 268
 }
259 269
 
260
-struct cl_cvd *cl_cvdverify(const char *file)
270
+int cl_cvdverify(const char *file)
261 271
 {
262 272
 	FILE *fd;
273
+	int ret;
263 274
 
264 275
     if((fd = fopen(file, "rb")) == NULL) {
265 276
 	cli_errmsg("Can't open CVD file %s\n", file);
266
-	return NULL;
277
+	return CL_EOPEN;
267 278
     }
268 279
 
269
-    return cli_cvdverify(fd);
280
+    ret = cli_cvdverify(fd);
281
+    fclose(fd);
282
+
283
+    return ret;
270 284
 }
271 285
 
272 286
 int cli_cvdload(FILE *fd, struct cl_node **root, int *virnum)
... ...
@@ -32,7 +32,7 @@
32 32
 #include "unrarlib.h"
33 33
 #include "defaults.h"
34 34
 
35
-int cli_addpatt(struct cl_node *root, struct patt *pattern)
35
+int cli_addpatt(struct cl_node *root, struct cli_patt *pattern)
36 36
 {
37 37
 	struct cl_node *pos, *next;
38 38
 	int i;
... ...
@@ -144,9 +144,9 @@ void cl_buildtrie(struct cl_node *root)
144 144
     cli_maketrans(root);
145 145
 }
146 146
 
147
-void cli_freepatt(struct patt *list)
147
+void cli_freepatt(struct cli_patt *list)
148 148
 {
149
-	struct patt *handler, *prev;
149
+	struct cli_patt *handler, *prev;
150 150
 
151 151
 
152 152
     handler = list;
... ...
@@ -176,7 +176,7 @@ void cl_freetrie(struct cl_node *root)
176 176
 int cl_scanbuff(const char *buffer, unsigned int length, char **virname, const struct cl_node *root)
177 177
 {
178 178
 	struct cl_node *current;
179
-	struct patt *pt;
179
+	struct cli_patt *pt;
180 180
 	int i, position, *partcnt;
181 181
 
182 182
     current = (struct cl_node *) root;
... ...
@@ -220,7 +220,7 @@ int cl_scanbuff(const char *buffer, unsigned int length, char **virname, const s
220 220
     return CL_CLEAN;
221 221
 }
222 222
 
223
-int cli_findpos(const char *buffer, int offset, int length, const struct patt *pattern)
223
+int cli_findpos(const char *buffer, int offset, int length, const struct cli_patt *pattern)
224 224
 {
225 225
 	int bufferpos = offset + CL_MIN_LENGTH;
226 226
 	int postfixend = offset + length;
... ...
@@ -26,10 +26,10 @@ struct nodelist {
26 26
     struct nodelist *next;
27 27
 };
28 28
 
29
-int cli_addpatt(struct cl_node *root, struct patt *pattern);
29
+int cli_addpatt(struct cl_node *root, struct cli_patt *pattern);
30 30
 struct nodelist *cli_bfsadd(struct nodelist *bfs, struct cl_node *n);
31 31
 void cli_failtrans(struct cl_node *root);
32 32
 void cli_fasttrie(struct cl_node *n, struct cl_node *root);
33
-int cli_findpos(const char *buffer, int offset, int length, const struct patt *pattern);
33
+int cli_findpos(const char *buffer, int offset, int length, const struct cli_patt *pattern);
34 34
 
35 35
 #endif
... ...
@@ -27,6 +27,7 @@
27 27
 #include <fcntl.h>
28 28
 
29 29
 #include "clamav.h"
30
+#include "cvd.h"
30 31
 #include "strings.h"
31 32
 #include "matcher.h"
32 33
 #include "others.h"
... ...
@@ -35,13 +36,13 @@
35 35
 
36 36
 int cli_parse_add(struct cl_node *root, const char *virname, const char *hexstr, int sigid, int parts, int partno)
37 37
 {
38
-	struct patt *new;
38
+	struct cli_patt *new;
39 39
 	const char *pt;
40 40
 	int ret, virlen;
41 41
 
42 42
     /* decode a hexstring and prepare a new entry */
43 43
 
44
-    if((new = (struct patt *) cli_calloc(1, sizeof(struct patt))) == NULL)
44
+    if((new = (struct cli_patt *) cli_calloc(1, sizeof(struct cli_patt))) == NULL)
45 45
 	return CL_EMEM;
46 46
 
47 47
     new->sigid = sigid;
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -124,7 +124,7 @@ void cli_chomp(char *string)
124 124
 
125 125
 char *cli_tok(const char *line, int field, char delimiter)
126 126
 {
127
-        int length, counter = 0, i, j = 0, k;
127
+        int length, counter = 0, i, j = 0;
128 128
         char *buffer;
129 129
 
130 130
 
... ...
@@ -132,28 +132,20 @@ char *cli_tok(const char *line, int field, char delimiter)
132 132
     buffer = (char *) cli_calloc(length, sizeof(char));
133 133
 
134 134
     for(i = 0; i < length; i++) {
135
-        if(line[i] == delimiter || line[i] == '\n') {
135
+        if(line[i] == delimiter) {
136 136
             counter++;
137
-            if(counter == field)
137
+            if(counter == field) {
138 138
 		break;
139
-
140
-            for(k = 0; k < length; k++)
141
-		buffer[k] = 0;
142
-
143
-            j = 0;
144
-        } else {
145
-	    if(line[i] != delimiter) {
146
-		buffer[j]=line[i];
147
-		j++;
139
+	    } else {
140
+		memset(buffer, 0, length);
141
+		j = 0;
148 142
 	    }
149
-	}
143
+        } else {
144
+            buffer[j++] = line[i];
145
+        }
150 146
     }
151 147
 
152 148
     cli_chomp(buffer); /* preventive */
153 149
 
154
-    if(strlen(buffer) == 0) {
155
-	free(buffer);
156
-	return NULL;
157
-    } else
158
-	return realloc(buffer, strlen(buffer) + 1);
150
+    return (char *) cli_realloc(buffer, strlen(buffer) + 1);
159 151
 }
... ...
@@ -64,6 +64,7 @@
64 64
 
65 65
 /* -- include files ------------------------------------------------------- */
66 66
 #include "unrarlib.h"                       /* include global configuration */
67
+#include "others.h"
67 68
 /* ------------------------------------------------------------------------ */
68 69
 
69 70
 
... ...
@@ -126,7 +126,7 @@ sigtool_SOURCES = \
126 126
 sigtool_LDADD = ../clamscan/getopt.o ../clamscan/others.o
127 127
 
128 128
 DEFS = @DEFS@
129
-LIBS = -L../libclamav -lclamav
129
+LIBS = -L../libclamav -lclamav @FRESHCLAM_LIBS@
130 130
 subdir = sigtool
131 131
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
132 132
 CONFIG_CLEAN_FILES =
... ...
@@ -152,7 +152,7 @@ LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
152 152
 	$(AM_LDFLAGS) $(LDFLAGS) -o $@
153 153
 CFLAGS = @CFLAGS@
154 154
 DIST_SOURCES = $(sigtool_SOURCES)
155
-DIST_COMMON = Makefile.am Makefile.in
155
+DIST_COMMON = COPYING Makefile.am Makefile.in
156 156
 SOURCES = $(sigtool_SOURCES)
157 157
 
158 158
 all: all-am
... ...
@@ -433,6 +433,22 @@ void sigtool(struct optstruct *opt)
433 433
     /* free_opt(opt); */
434 434
 }
435 435
 
436
+int countlines(const char *filename)
437
+{
438
+	FILE *fd;
439
+	char buff[65536];
440
+	int lines = 0;
441
+
442
+    if((fd = fopen(filename, "r")) == NULL)
443
+	return 0;
444
+
445
+    while(fgets(buff, sizeof(buff), fd))
446
+	lines++;
447
+
448
+    fclose(fd);
449
+    return lines;
450
+}
451
+
436 452
 int build(struct optstruct *opt)
437 453
 {
438 454
 	int ret, no = 0, bytes, itmp;
... ...
@@ -444,6 +460,7 @@ int build(struct optstruct *opt)
444 444
 	gzFile *gz;
445 445
 	time_t timet;
446 446
 	struct tm *brokent;
447
+	struct cl_cvd *old;
447 448
 
448 449
     /* build a tar.gz archive
449 450
      * we need: COPYING and {viruses.db, viruses.db2}+
... ...
@@ -462,7 +479,7 @@ int build(struct optstruct *opt)
462 462
 
463 463
     cl_debug(); /* enable debug messages */
464 464
 
465
-    if((ret = cl_loaddbdir(cl_retdbdir(), &root, &no))) {
465
+    if((ret = cl_loaddbdir(".", &root, &no))) {
466 466
 	mprintf("!Can't load database: %s\n", cl_strerror(ret));
467 467
         exit(1);
468 468
     }
... ...
@@ -530,7 +547,7 @@ int build(struct optstruct *opt)
530 530
     time(&timet);
531 531
     brokent = localtime(&timet);
532 532
     setlocale(LC_TIME, "C");
533
-    strftime(smbuff, 24, "%b-%d %H-%M %Z:", brokent);
533
+    strftime(smbuff, 24, "%b-%d %H-%M %Z %Y:", brokent);
534 534
     strcat(header, smbuff);
535 535
 
536 536
     /* version number */
... ...
@@ -545,7 +562,6 @@ int build(struct optstruct *opt)
545 545
     strcat(header, smbuff);
546 546
 
547 547
     /* number of signatures */
548
-    //FIXME: THIS IS WRONG
549 548
     sprintf(smbuff, "%d:", no);
550 549
     strcat(header, smbuff);
551 550