static int fmm_ascmagic(unsigned char *buf, size_t nbytes, char **mime_type) { int has_escapes = 0; unsigned char *s; char nbuf[HOWMANY + 1]; /* one extra for terminating '\0' */ char *token; register struct names *p; int small_nbytes; char *strtok_state; unsigned char *tp; /* these are easy, do them first */ /* * for troff, look for . + letter + letter or .\"; this must be done to * disambiguate tar archives' ./file and other trash from real troff * input. */ if (*buf == '.') { tp = buf + 1; while (isSPACE(*tp)) ++tp; /* skip leading whitespace */ if ((isALNUM(*tp) || *tp == '\\') && (isALNUM(*(tp + 1)) || *tp == '"')) { strcpy(*mime_type, "application/x-troff"); return 0; } } if ((*buf == 'c' || *buf == 'C') && isSPACE(*(buf + 1))) { /* Fortran */ strcpy(*mime_type, "text/plain"); return 0; } /* look for tokens from names.h - this is expensive!, so we'll limit * ourselves to only SMALL_HOWMANY bytes */ small_nbytes = (nbytes > SMALL_HOWMANY) ? SMALL_HOWMANY : nbytes; /* make a copy of the buffer here because strtok() will destroy it */ s = (unsigned char *) memcpy(nbuf, buf, small_nbytes); s[small_nbytes] = '\0'; has_escapes = (memchr(s, '\033', small_nbytes) != NULL); while ((token = strtok_r((char *) s, " \t\n\r\f", &strtok_state)) != NULL) { s = NULL; /* make strtok() keep on tokin' */ for (p = names; p < names + NNAMES; p++) { if (strEQ(p->name, token)) { strcpy(*mime_type, types[p->type]); if (has_escapes) strcat(*mime_type, " (with escape sequences)"); return 0; } } } int is_tarball = is_tar(buf, nbytes); if ( is_tarball == 1 || is_tarball == 2 ) { /* 1: V7 tar archive */ /* 2: POSIX tar archive */ strcpy(*mime_type, "application/x-tar"); return 0; } /* all else fails, but it is ascii... */ strcpy(*mime_type, "text/plain"); return 0; }
cli_file_t cli_filetype2(int desc, const struct cl_engine *engine) { unsigned char smallbuff[MAGIC_BUFFER_SIZE + 1], *decoded, *bigbuff; int bread, sret; cli_file_t ret = CL_TYPE_UNKNOWN_DATA; struct cli_matcher *root; struct cli_ac_data mdata; memset(smallbuff, 0, sizeof(smallbuff)); if((bread = read(desc, smallbuff, MAGIC_BUFFER_SIZE)) > 0) ret = cli_filetype(smallbuff, bread); if(engine && ret == CL_TYPE_UNKNOWN_TEXT) { root = engine->root[0]; if(!root) return ret; if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) return ret; sret = cli_ac_scanbuff(smallbuff, bread, NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL); cli_ac_freedata(&mdata); if(sret >= CL_TYPENO) { ret = sret; } else { if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) return ret; decoded = (unsigned char *) cli_utf16toascii((char *) smallbuff, bread); if(decoded) { sret = cli_ac_scanbuff(decoded, strlen((char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL); free(decoded); if(sret == CL_TYPE_HTML) ret = CL_TYPE_HTML_UTF16; } cli_ac_freedata(&mdata); if((((struct cli_dconf*) engine->dconf)->phishing & PHISHING_CONF_ENTCONV) && ret != CL_TYPE_HTML_UTF16) { struct entity_conv conv; const size_t conv_size = 2*bread < 256 ? 256 : 2*bread; if(init_entity_converter(&conv,UNKNOWN,conv_size) == 0) { int end = 0; m_area_t area; area.buffer = (unsigned char *) smallbuff; area.length = bread; area.offset = 0; while(!end) { if(cli_ac_initdata(&mdata, root->ac_partsigs, AC_DEFAULT_TRACKLEN)) return ret; decoded = encoding_norm_readline(&conv, NULL, &area, bread); if(decoded) { sret = cli_ac_scanbuff(decoded, strlen((const char *) decoded), NULL, engine->root[0], &mdata, 1, 0, 0, -1, NULL); free(decoded); if(sret == CL_TYPE_HTML) { ret = CL_TYPE_HTML; end = 1; } } else end = 1; cli_ac_freedata(&mdata); } entity_norm_done(&conv); } else { cli_warnmsg("cli_filetype2: Error initializing entity converter\n"); } } } } if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) { if(!(bigbuff = (unsigned char *) cli_calloc(37638 + 1, sizeof(unsigned char)))) return ret; lseek(desc, 0, SEEK_SET); if((bread = read(desc, bigbuff, 37638)) > 0) { bigbuff[bread] = 0; switch(is_tar(bigbuff, bread)) { case 1: ret = CL_TYPE_OLD_TAR; cli_dbgmsg("Recognized old fashioned tar file\n"); break; case 2: ret = CL_TYPE_POSIX_TAR; cli_dbgmsg("Recognized POSIX tar file\n"); break; } } if(ret == CL_TYPE_UNKNOWN_DATA || ret == CL_TYPE_UNKNOWN_TEXT) { if(!memcmp(bigbuff + 32769, "CD001" , 5) || !memcmp(bigbuff + 37633, "CD001" , 5)) { cli_dbgmsg("Recognized ISO 9660 CD-ROM data\n"); ret = CL_TYPE_DATA; } else if(!memcmp(bigbuff + 32776, "CDROM" , 5)) { cli_dbgmsg("Recognized High Sierra CD-ROM data\n"); ret = CL_TYPE_DATA; } } free(bigbuff); } return ret; }
static gboolean extract_archive (GFile *destination, GFile *archive_file, guint strip_components, GError **error) { ArchiveType type; g_autofree char *archive_path = NULL; archive_path = g_file_get_path (archive_file); g_debug ("Uncompress %s\n", archive_path); type = get_type (archive_file); if (is_tar (type)) { g_autofree char *strip_components_str = g_strdup_printf ("--strip-components=%u", strip_components); /* tar_decompress_flag can return NULL, so put it last */ if (!tar (destination, error, "xf", archive_path, "--no-same-owner", strip_components_str, tar_decompress_flag (type), NULL)) return FALSE; } else if (type == ZIP) { g_autoptr(GFile) zip_dest = NULL; zip_dest = create_uncompress_directory (destination, strip_components, error); if (zip_dest == NULL) return FALSE; if (!unzip (zip_dest, error, archive_path, NULL)) return FALSE; if (strip_components > 0 && !strip_components_into (destination, zip_dest, strip_components, error)) return FALSE; } else if (type == RPM) { g_autoptr(GFile) rpm_dest = NULL; rpm_dest = create_uncompress_directory (destination, strip_components, error); if (rpm_dest == NULL) return FALSE; if (!unrpm (rpm_dest, archive_path, error)) return FALSE; if (strip_components > 0 && !strip_components_into (destination, rpm_dest, strip_components, error)) return FALSE; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown archive format of '%s'", archive_path); return FALSE; } return TRUE; }