Browse code

Merge branch 'master' into fmapify

* master:
testcase for cl_scan APIs
c4w: add Scan_GetFileType - untested
upgrade sigui api
make the sigload callback be aware of custom sigs

Conflicts:
unit_tests/Makefile.am
unit_tests/Makefile.in
unit_tests/check_clamav.c

Török Edvin authored on 2011/06/15 18:26:05
Showing 10 changed files
... ...
@@ -222,7 +222,7 @@ CL_CLEAN = File is scanned
222 222
 CL_BREAK = Whitelisted by callback - file is skipped and marked as clean
223 223
 CL_VIRUS = Blacklisted by callback - file is skipped and marked as infected
224 224
 */
225
-extern void cl_engine_set_clcb_file_type(struct cl_engine *engine, clcb_pre_cache callback);
225
+extern void cl_engine_set_clcb_pre_cache(struct cl_engine *engine, clcb_pre_cache callback);
226 226
 
227 227
 typedef cl_error_t (*clcb_pre_scan)(int fd, const char *type, void *context);
228 228
 /* PRE-SCAN
... ...
@@ -261,11 +261,12 @@ CL_VIRUS = Blacklisted by callback - scan result is set to CL_VIRUS
261 261
 extern void cl_engine_set_clcb_post_scan(struct cl_engine *engine, clcb_post_scan callback);
262 262
 
263 263
 
264
-typedef int (*clcb_sigload)(const char *type, const char *name, void *context);
264
+typedef int (*clcb_sigload)(const char *type, const char *name, unsigned int custom, void *context);
265 265
 /* SIGNATURE LOAD
266 266
 Input:
267 267
 type = The signature type (e.g. "db", "ndb", "mdb", etc.)
268 268
 name = The virus name
269
+custom = The signature is official (custom == 0) or custom (custom != 0)
269 270
 context = Opaque application provided data
270 271
 
271 272
 Output:
... ...
@@ -573,7 +573,7 @@ static int cli_loaddb(FILE *fs, struct cl_engine *engine, unsigned int *signo, u
573 573
 	if(engine->ignored && cli_chkign(engine->ignored, start, buffer_cpy))
574 574
 	    continue;
575 575
 
576
-	if(engine->cb_sigload && engine->cb_sigload("db", start, engine->cb_sigload_ctx)) {
576
+	if(engine->cb_sigload && engine->cb_sigload("db", start, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
577 577
 	    cli_dbgmsg("cli_loaddb: skipping %s due to callback\n", start);
578 578
 	    continue;
579 579
 	}
... ...
@@ -652,7 +652,7 @@ static int cli_loadidb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
652 652
 	if(engine->ignored && cli_chkign(engine->ignored, tokens[0], buffer_cpy))
653 653
 	    continue;
654 654
 
655
-	if(engine->cb_sigload && engine->cb_sigload("idb", tokens[0], engine->cb_sigload_ctx)) {
655
+	if(engine->cb_sigload && engine->cb_sigload("idb", tokens[0], options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
656 656
 	    cli_dbgmsg("cli_loadidb: skipping %s due to callback\n", tokens[0]);
657 657
 	    continue;
658 658
 	}
... ...
@@ -926,7 +926,7 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
926 926
 	if(engine->ignored && cli_chkign(engine->ignored, virname, buffer_cpy))
927 927
 	    continue;
928 928
 
929
-	if(!sdb && engine->cb_sigload && engine->cb_sigload("ndb", virname, engine->cb_sigload_ctx)) {
929
+	if(!sdb && engine->cb_sigload && engine->cb_sigload("ndb", virname, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
930 930
 	    cli_dbgmsg("cli_loadndb: skipping %s due to callback\n", virname);
931 931
 	    continue;
932 932
 	}
... ...
@@ -1235,7 +1235,7 @@ static int load_oneldb(char *buffer, int chkpua, int chkign, struct cl_engine *e
1235 1235
     if (chkign && cli_chkign(engine->ignored, virname, buffer_cpy))
1236 1236
 	return CL_SUCCESS;
1237 1237
 
1238
-    if(engine->cb_sigload && engine->cb_sigload("ldb", virname, engine->cb_sigload_ctx)) {
1238
+    if(engine->cb_sigload && engine->cb_sigload("ldb", virname, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
1239 1239
 	cli_dbgmsg("cli_loadldb: skipping %s due to callback\n", virname);
1240 1240
 	(*sigs)--;
1241 1241
 	return CL_SUCCESS;
... ...
@@ -1443,7 +1443,7 @@ static int cli_loadcbc(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1443 1443
 	return CL_SUCCESS;
1444 1444
     }
1445 1445
 
1446
-    if(engine->cb_sigload && engine->cb_sigload("cbc", dbname, engine->cb_sigload_ctx)) {
1446
+    if(engine->cb_sigload && engine->cb_sigload("cbc", dbname, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
1447 1447
 	cli_dbgmsg("cli_loadcbc: skipping %s due to callback\n", dbname);
1448 1448
 	return CL_SUCCESS;
1449 1449
     }
... ...
@@ -1948,7 +1948,7 @@ static int cli_loadhash(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1948 1948
 		dot = dbname;
1949 1949
 	    else
1950 1950
 		dot++;
1951
-	    if(engine->cb_sigload(dot, pt, engine->cb_sigload_ctx)) {
1951
+	    if(engine->cb_sigload(dot, pt, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
1952 1952
 		cli_dbgmsg("cli_loadhash: skipping %s (%s) due to callback\n", pt, dot);
1953 1953
 	        continue;
1954 1954
 	    }
... ...
@@ -2090,7 +2090,7 @@ static int cli_loadmd(FILE *fs, struct cl_engine *engine, unsigned int *signo, i
2090 2090
 	    continue;
2091 2091
 	}
2092 2092
 
2093
-	if(engine->cb_sigload && engine->cb_sigload("md", new->virname, engine->cb_sigload_ctx)) {
2093
+	if(engine->cb_sigload && engine->cb_sigload("md", new->virname, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
2094 2094
 	    cli_dbgmsg("cli_loadmd: skipping %s due to callback\n", new->virname);
2095 2095
 	    mpool_free(engine->mempool, new->virname);
2096 2096
 	    mpool_free(engine->mempool, new);
... ...
@@ -2230,7 +2230,7 @@ static int cli_loadcdb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
2230 2230
 	    continue;
2231 2231
 	}
2232 2232
 
2233
-	if(engine->cb_sigload && engine->cb_sigload("cdb", new->virname, engine->cb_sigload_ctx)) {
2233
+	if(engine->cb_sigload && engine->cb_sigload("cdb", new->virname, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
2234 2234
 	    cli_dbgmsg("cli_loadcdb: skipping %s due to callback\n", new->virname);
2235 2235
 	    mpool_free(engine->mempool, new->virname);
2236 2236
 	    mpool_free(engine->mempool, new);
... ...
@@ -441,7 +441,7 @@ int load_regex_matcher(struct cl_engine *engine,struct regex_matcher* matcher,FI
441 441
 		if(functionality_level_check(buffer))
442 442
 			continue;
443 443
 
444
-		if(engine->cb_sigload && engine->cb_sigload("phishing", buffer, engine->cb_sigload_ctx)) {
444
+		if(engine->cb_sigload && engine->cb_sigload("phishing", buffer, options & CL_DB_OFFICIAL, engine->cb_sigload_ctx)) {
445 445
 			cli_dbgmsg("load_regex_matcher: skipping %s due to callback\n", buffer);
446 446
 			continue;
447 447
 		}
... ...
@@ -48,9 +48,13 @@ check_clamav.c: $(top_builddir)/test/clam.exe clamav.hdb
48 48
 clamav.hdb: input/clamav.hdb
49 49
 	cp $< $@
50 50
 
51
+check_clamav.c: $(top_builddir)/test/clam.exe clamav.hdb
51 52
 check_clamd.sh: $(top_builddir)/test/clam.exe check_clamd
52 53
 check_clamscan.sh: $(top_builddir)/test/clam.exe
53 54
 
55
+clamav.hdb: input/clamav.hdb
56
+	cp $< $@
57
+
54 58
 $(top_builddir)/test/clam.exe:
55 59
 	(cd $(top_builddir)/test && $(MAKE))
56 60
 
... ...
@@ -1102,9 +1102,13 @@ check_clamav.c: $(top_builddir)/test/clam.exe clamav.hdb
1102 1102
 clamav.hdb: input/clamav.hdb
1103 1103
 	cp $< $@
1104 1104
 
1105
+check_clamav.c: $(top_builddir)/test/clam.exe clamav.hdb
1105 1106
 check_clamd.sh: $(top_builddir)/test/clam.exe check_clamd
1106 1107
 check_clamscan.sh: $(top_builddir)/test/clam.exe
1107 1108
 
1109
+clamav.hdb: input/clamav.hdb
1110
+	cp $< $@
1111
+
1108 1112
 $(top_builddir)/test/clam.exe:
1109 1113
 	(cd $(top_builddir)/test && $(MAKE))
1110 1114
 
... ...
@@ -146,12 +146,90 @@ END_TEST
146 146
 START_TEST (test_cl_cvdparse)
147 147
 END_TEST
148 148
 
149
+static int get_test_file(int i, char *file, unsigned fsize, unsigned long *size);
150
+static struct cl_engine *g_engine;
151
+
149 152
 /* int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */
150 153
 START_TEST (test_cl_scandesc)
154
+{
155
+    const char *virname = NULL;
156
+    char file[256];
157
+    unsigned long size;
158
+    unsigned long int scanned = 0;
159
+    int ret;
160
+
161
+    int fd = get_test_file(_i, file, sizeof(file), &size);
162
+    cli_dbgmsg("scanning (scandesc) %s\n", file);
163
+    ret = cl_scandesc(fd, &virname, &scanned, g_engine, CL_SCAN_STDOPT);
164
+    cli_dbgmsg("scan end (scandesc) %s\n", file);
165
+
166
+    fail_unless_fmt(ret == CL_VIRUS, "cl_scandesc failed for %s: %s", file, cl_strerror(ret));
167
+    fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
168
+    close(fd);
169
+}
151 170
 END_TEST
152 171
 
153 172
 /* int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */
154 173
 START_TEST (test_cl_scanfile)
174
+{
175
+    const char *virname = NULL;
176
+    char file[256];
177
+    unsigned long size;
178
+    unsigned long int scanned = 0;
179
+    int ret;
180
+
181
+    int fd = get_test_file(_i, file, sizeof(file), &size);
182
+    close(fd);
183
+
184
+    cli_dbgmsg("scanning (scanfile) %s\n", file);
185
+    ret = cl_scanfile(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT);
186
+    cli_dbgmsg("scan end (scanfile) %s\n", file);
187
+
188
+    fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile failed for %s: %s", file, cl_strerror(ret));
189
+    fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
190
+}
191
+END_TEST
192
+
193
+START_TEST (test_cl_scanfile_callback)
194
+{
195
+    const char *virname = NULL;
196
+    char file[256];
197
+    unsigned long size;
198
+    unsigned long int scanned = 0;
199
+    int ret;
200
+
201
+    int fd = get_test_file(_i, file, sizeof(file), &size);
202
+    close(fd);
203
+
204
+    cli_dbgmsg("scanning (scanfile_cb) %s\n", file);
205
+    /* TODO: test callbacks */
206
+    ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
207
+    cli_dbgmsg("scan end (scanfile_cb) %s\n", file);
208
+
209
+    fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile failed for %s: %s", file, cl_strerror(ret));
210
+    fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
211
+}
212
+END_TEST
213
+
214
+START_TEST (test_cl_scandesc_callback)
215
+{
216
+    const char *virname = NULL;
217
+    char file[256];
218
+    unsigned long size;
219
+    unsigned long int scanned = 0;
220
+    int ret;
221
+
222
+    int fd = get_test_file(_i, file, sizeof(file), &size);
223
+
224
+    cli_dbgmsg("scanning (scandesc_cb) %s\n", file);
225
+    /* TODO: test callbacks */
226
+    ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
227
+    cli_dbgmsg("scan end (scandesc_cb) %s\n", file);
228
+
229
+    fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile failed for %s: %s", file, cl_strerror(ret));
230
+    fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
231
+    close(fd);
232
+}
155 233
 END_TEST
156 234
 
157 235
 /* int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, unsigned int options) */
... ...
@@ -180,6 +258,7 @@ END_TEST
180 180
 
181 181
 static char **testfiles = NULL;
182 182
 static unsigned testfiles_n = 0;
183
+static const expected_testfiles = 46;
183 184
 
184 185
 static void init_testfiles(void)
185 186
 {
... ...
@@ -201,6 +280,7 @@ static void init_testfiles(void)
201 201
 	testfiles[i-1] = strdup(dirent->d_name);
202 202
     }
203 203
     testfiles_n = i;
204
+    fail_unless_fmt(testfiles_n == expected_testfiles, "testfiles: %d != %d", testfiles_n, expected_testfiles);
204 205
 
205 206
     closedir(d);
206 207
 }
... ...
@@ -216,7 +296,6 @@ static void free_testfiles(void)
216 216
     testfiles_n = 0;
217 217
 }
218 218
 
219
-static struct cl_engine *g_engine;
220 219
 static int inited = 0;
221 220
 
222 221
 static void engine_setup(void)
... ...
@@ -334,8 +413,6 @@ static Suite *test_cl_suite(void)
334 334
     tcase_add_test(tc_cl, test_cl_retflevel);
335 335
     tcase_add_test(tc_cl, test_cl_cvdhead);
336 336
     tcase_add_test(tc_cl, test_cl_cvdparse);
337
-    tcase_add_test(tc_cl, test_cl_scandesc);
338
-    tcase_add_test(tc_cl, test_cl_scanfile);
339 337
     tcase_add_test(tc_cl, test_cl_load);
340 338
     tcase_add_test(tc_cl, test_cl_cvdverify);
341 339
     tcase_add_test(tc_cl, test_cl_statinidir);
... ...
@@ -345,9 +422,13 @@ static Suite *test_cl_suite(void)
345 345
 
346 346
     suite_add_tcase(s, tc_cl_scan);
347 347
     tcase_add_checked_fixture (tc_cl_scan, engine_setup, engine_teardown);
348
-    tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle, 0, 16);
349
-    tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, 16);
350
-
348
+    tcase_add_loop_test(tc_cl_scan, test_cl_scandesc, 0, expected_testfiles);
349
+    tcase_add_loop_test(tc_cl_scan, test_cl_scanfile, 0, expected_testfiles);
350
+    tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_callback, 0, expected_testfiles);
351
+    tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_callback, 0, expected_testfiles);
352
+    tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle, 0, expected_testfiles);
353
+    tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, expected_testfiles);
354
+    
351 355
     return s;
352 356
 }
353 357
 
... ...
@@ -691,6 +772,7 @@ int main(void)
691 691
     srunner_add_suite(sr, test_htmlnorm_suite());
692 692
     srunner_add_suite(sr, test_bytecode_suite());
693 693
 
694
+
694 695
     srunner_set_log(sr, "test.log");
695 696
     if(freopen("test-stderr.log","w+",stderr) == NULL) {
696 697
 	    fputs("Unable to redirect stderr!\n",stderr);
... ...
@@ -255,6 +255,12 @@ int CLAMAPI Scan_ScanObject(CClamAVScanner *pScanner, const wchar_t *pObjectPath
255 255
 int CLAMAPI Scan_ScanObjectByHandle(CClamAVScanner *pScanner, HANDLE object, int *pScanStatus, PCLAM_SCAN_INFO_LIST *pInfoList);
256 256
 
257 257
 /*
258
+ * Returns the outer file type as an _int64[2] for the give HANDLE
259
+ * Scan is not performed and no callback is invoked
260
+ */
261
+ int CLAMAPI Scan_GetFileType(HANDLE hFile, _int64 *filetype);
262
+
263
+/*
258 264
  * MANDATORY SUPPORT
259 265
  * Destroy memory allocated when malicious objects are found during scan
260 266
  * INPUT @param pScanner : opaque object
... ...
@@ -28,6 +28,58 @@
28 28
 #include "clscanapi.h"
29 29
 #include "interface.h"
30 30
 
31
+const char *types[] = {
32
+"HTML",
33
+"HTML_UTF16",
34
+"MSEXE",
35
+"GRAPHICS",
36
+"TEXT_ASCII",
37
+"TEXT_UTF8",
38
+"TEXT_UTF16LE",
39
+"TEXT_UTF16BE",
40
+"PDF",
41
+"SCRIPT",
42
+"RTF",
43
+"RIFF",
44
+"MSCHM",
45
+"MSCAB",
46
+"MSOLE2",
47
+"MSSZDD",
48
+"ZIP",
49
+"RAR",
50
+"7Z",
51
+"BZ",
52
+"GZ",
53
+"ARJ",
54
+"ZIPSFX",
55
+"RARSFX",
56
+"CABSFX",
57
+"ARJSFX",
58
+"NULSFT",
59
+"AUTOIT",
60
+"ISHIELD_MSI",
61
+"SFX",
62
+"BINHEX",
63
+"MAIL",
64
+"TNEF",
65
+"BINARY_DATA",
66
+"CRYPTFF",
67
+"UUENCODED",
68
+"SCRENC",
69
+"POSIX_TAR",
70
+"OLD_TAR",
71
+"ELF",
72
+"MACHO",
73
+"MACHO_UNIBIN",
74
+"SIS",
75
+"SWF",
76
+"CPIO_OLD",
77
+"CPIO_ODC",
78
+"CPIO_NEWC",
79
+"CPIO_CRC",
80
+NULL
81
+};
82
+
31 83
 int WINAPI SHCreateDirectoryExA(HWND, LPCTSTR, SECURITY_ATTRIBUTES *); /* cannot include Shlobj.h due to DATADIR collision */
32 84
 
33 85
 #define FMT(s) "!"__FUNCTION__": "s"\n"
... ...
@@ -55,6 +107,7 @@ typedef struct {
55 55
     CLAM_SCAN_CALLBACK scancb;
56 56
     void *scancb_ctx;
57 57
     unsigned int scanopts;
58
+    _int64 *filetype;
58 59
 } instance;
59 60
 
60 61
 struct {
... ...
@@ -73,6 +126,7 @@ BOOL minimal_definitions = FALSE;
73 73
 #define lock_instances()(WaitForSingleObject(instance_mutex, INFINITE) == WAIT_FAILED)
74 74
 #define unlock_instances() do {ReleaseMutex(instance_mutex);} while(0)
75 75
 
76
+cl_error_t filetype_cb(int fd, const char *detected_file_type, void *context);
76 77
 cl_error_t prescan_cb(int fd, const char *detected_file_type, void *context);
77 78
 cl_error_t postscan_cb(int fd, int result, const char *virname, void *context);
78 79
 
... ...
@@ -250,8 +304,8 @@ BOOL interface_setup(void) {
250 250
     return TRUE;
251 251
 }
252 252
 
253
-static int sigload_callback(const char *type, const char *name, void *context) {
254
-    if(minimal_definitions && strcmp(type, "fp"))
253
+static int sigload_callback(const char *type, const char *name, unsigned int custom, void *context) {
254
+    if(minimal_definitions && (custom || strcmp(type, "fp")))
255 255
 	return 1;
256 256
     return 0;
257 257
 }
... ...
@@ -355,7 +409,8 @@ int CLAMAPI Scan_Initialize(const wchar_t *pEnginesFolder, const wchar_t *pTempR
355 355
 	unlock_engine();
356 356
 	FAIL(CL_EMEM, "Not enough memory for a new engine");
357 357
     }
358
-    cl_engine_set_clcb_pre_cache(engine, prescan_cb);
358
+    cl_engine_set_clcb_pre_cache(engine, filetype_cb);
359
+    cl_engine_set_clcb_pre_scan(engine, prescan_cb);
359 360
     cl_engine_set_clcb_post_scan(engine, postscan_cb);
360 361
     
361 362
     minimal_definitions = bLoadMinDefs;
... ...
@@ -449,7 +504,7 @@ int CLAMAPI Scan_CreateInstance(CClamAVScanner **ppScanner) {
449 449
     INFN();
450 450
     if(!ppScanner)
451 451
 	FAIL(CL_ENULLARG, "NULL pScanner");
452
-    inst = calloc(1, sizeof(*inst));
452
+    inst = (instance *)calloc(1, sizeof(*inst));
453 453
     if(!inst)
454 454
 	FAIL(CL_EMEM, "CreateInstance: OOM");
455 455
     if(lock_engine()) {
... ...
@@ -887,7 +942,7 @@ int CLAMAPI Scan_ScanObjectByHandle(CClamAVScanner *pScanner, HANDLE object, int
887 887
     perf = GetTickCount();
888 888
     res = cl_scandesc_callback(fd, &virname, NULL, engine, inst->scanopts, &sctx);
889 889
 
890
-    do {
890
+    if(!inst->filetype) do {
891 891
 	CLAM_SCAN_INFO si;
892 892
 	CLAM_ACTION act;
893 893
 	DWORD cbperf;
... ...
@@ -935,7 +990,7 @@ int CLAMAPI Scan_ScanObjectByHandle(CClamAVScanner *pScanner, HANDLE object, int
935 935
     if(res == CL_VIRUS) {
936 936
 	logg("Scan_ScanObjectByHandle (instance %p): file is INFECTED with %s\n", inst, virname);
937 937
 	if(pInfoList) {
938
-	    CLAM_SCAN_INFO_LIST *infolist = calloc(1, sizeof(CLAM_SCAN_INFO_LIST) + sizeof(CLAM_SCAN_INFO) + MAX_VIRNAME_LEN * 2);
938
+	    CLAM_SCAN_INFO_LIST *infolist = (CLAM_SCAN_INFO_LIST *)calloc(1, sizeof(CLAM_SCAN_INFO_LIST) + sizeof(CLAM_SCAN_INFO) + MAX_VIRNAME_LEN * 2);
939 939
 	    PCLAM_SCAN_INFO scaninfo;
940 940
 	    wchar_t *wvirname;
941 941
 	    if(!infolist)
... ...
@@ -967,6 +1022,16 @@ int CLAMAPI Scan_ScanObjectByHandle(CClamAVScanner *pScanner, HANDLE object, int
967 967
     WIN();
968 968
 }
969 969
 
970
+int CLAMAPI Scan_GetFileType(HANDLE hFile, _int64 *filetype) {
971
+    instance *inst;
972
+    int status, ret = Scan_CreateInstance((CClamAVScanner **)&inst);
973
+    if(ret != CLAMAPI_SUCCESS)
974
+	return ret;
975
+    inst->filetype = filetype;
976
+    ret = Scan_ScanObjectByHandle((CClamAVScanner *)inst, hFile, &status, NULL);
977
+    Scan_DestroyInstance((CClamAVScanner *)inst);
978
+    return ret;
979
+}
970 980
 
971 981
 int CLAMAPI Scan_DeleteScanInfo(CClamAVScanner *pScanner, PCLAM_SCAN_INFO_LIST pInfoList) {
972 982
     logg("*in Scan_DeleteScanInfo(pScanner = %p, pInfoList = %p)\n", pScanner, pInfoList);
... ...
@@ -989,6 +1054,33 @@ int CLAMAPI Scan_DeleteScanInfo(CClamAVScanner *pScanner, PCLAM_SCAN_INFO_LIST p
989 989
     WIN();
990 990
 }
991 991
 
992
+cl_error_t filetype_cb(int fd, const char *type, void *context) {
993
+    struct scan_ctx *sctx = (struct scan_ctx *)context;
994
+    if(sctx && sctx->inst && sctx->inst->filetype) {
995
+	int i=0;
996
+	if(strncmp(type, "CL_TYPE_", 8)) {
997
+	    for(i=0; types[i]; i++) {
998
+		if(!strcmp(&type[8], types[i]))
999
+		    break;
1000
+	    }
1001
+	    if(!types[i]) i = -1;
1002
+	} else
1003
+	    i = -1;
1004
+	if(i<0) {
1005
+	    sctx->inst->filetype[0] = -1;
1006
+	    sctx->inst->filetype[1] = -1;
1007
+	} else if(i<64) {
1008
+	    sctx->inst->filetype[0] = 1LL << i;
1009
+	    sctx->inst->filetype[1] = 0;
1010
+	} else {
1011
+	    sctx->inst->filetype[0] = 0;
1012
+	    sctx->inst->filetype[1] = 1LL << (i-64);
1013
+	}
1014
+	return CL_BREAK;
1015
+    }
1016
+    return CL_CLEAN;
1017
+}
1018
+
992 1019
 cl_error_t prescan_cb(int fd, const char *type, void *context) {
993 1020
     struct scan_ctx *sctx = (struct scan_ctx *)context;
994 1021
     char tmpf[4096];
... ...
@@ -1003,6 +1095,9 @@ cl_error_t prescan_cb(int fd, const char *type, void *context) {
1003 1003
 	return CL_CLEAN;
1004 1004
     }
1005 1005
     inst = sctx->inst;
1006
+    if(inst && inst->filetype)
1007
+	return CL_CLEAN; /* Just in case, this shouldn't happen */
1008
+
1006 1009
     logg("*in prescan_cb with clamav context %p, instance %p, fd %d, type %s)\n", context, inst, fd, type);
1007 1010
     if(strncmp(type, "CL_TYPE_", 8) ||
1008 1011
        (strcmp(&type[8], "BINARY_DATA") &&
... ...
@@ -1105,10 +1200,13 @@ cl_error_t postscan_cb(int fd, int result, const char *virname, void *context) {
1105 1105
 	logg("!postscan_cb called with NULL clamav context\n");
1106 1106
 	return CL_CLEAN;
1107 1107
     }
1108
+    inst = sctx->inst;
1109
+    if(inst && inst->filetype)
1110
+	return CL_CLEAN; /* No callback, we are just filetyping */
1111
+
1108 1112
     if(fd == sctx->entryfd)
1109 1113
 	return CL_CLEAN; /* Moved to after cl_scandesc returns due to heuristic results not being yet set in magicscan */
1110 1114
 
1111
-    inst = sctx->inst;
1112 1115
     si.cbSize = sizeof(si);
1113 1116
     si.flags = 0;
1114 1117
     si.scanPhase = SCAN_PHASE_POSTSCAN;
... ...
@@ -256,7 +256,7 @@ bool SigUICopy::copySignatures(const wxString &staging)
256 256
     return OK;
257 257
 }
258 258
 
259
-int SigUICopy::sigprogress(const char* WXUNUSED(type), const char* WXUNUSED(name), void *context)
259
+int SigUICopy::sigprogress(const char* WXUNUSED(type), const char* WXUNUSED(name), unsigned int WXUNUSED(custom), void *context)
260 260
 {
261 261
     SigUICopy *p = (SigUICopy*)context;
262 262
     if (++p->cnt % 1000)
... ...
@@ -40,7 +40,7 @@ class SigUICopy
40 40
 		bool copySignatures(const wxString &staging);
41 41
 		bool loadDB(const wxString& dir);
42 42
 		bool canceled(void);
43
-		static int sigprogress(const char *type, const char *name, void *context);
43
+		static int sigprogress(const char *type, const char *name, unsigned int custom, void *context);
44 44
 };
45 45
 
46 46
 #endif