/* $Id: gzip.c,v 1.1.1.1 2009/02/21 21:25:20 khorben Exp $ */ /* Copyright (c) 2007 khorben of Uberwall */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "plugin.h" /* gzip */ /* public */ /* types */ #pragma pack(1) struct gzip { uint16_t magic; uint8_t method; uint8_t flags; uint32_t mtime; uint8_t deflate; uint8_t os; }; #pragma pack() /* variables */ /* magic */ static unsigned char sig[] = "\x1f\x8b"; static PluginMagic gzip_magic[] = { { sizeof(struct gzip), 0, sig, sizeof(sig)-1 }, { 0, 0, NULL, 0 } }; /* functions */ static int gzip_callback(PluginHelper * ph, int signature, FILE * fp); /* plugin */ Plugin plugin = { PT_ARCHIVE | PT_COMPRESSION, "GZIP", gzip_magic, gzip_callback }; /* private */ /* functions */ /* gzip_callback */ static int _callback_method(PluginHelper * ph, uint8_t method); static int _callback_flags(PluginHelper * ph, uint8_t flags); static int _callback_mtime(PluginHelper * ph, time_t mtime); static int _callback_deflate(uint8_t method, uint8_t deflate); static int _callback_os(PluginHelper * ph, uint8_t os); static int gzip_callback(PluginHelper * ph, int signature, FILE * fp) { int score = 0; struct gzip buf; if(fread(&buf, sizeof(buf), 1, fp) != 1) return -1; score+=_callback_method(ph, buf.method); score+=_callback_flags(ph, buf.flags); score+=_callback_mtime(ph, buf.mtime); score+=_callback_deflate(buf.method, buf.deflate); score+=_callback_os(ph, buf.os); ph->printf(ph, "\n"); return score / 5; } static int _callback_method(PluginHelper * ph, uint8_t method) { struct { int method; char * string; int score; } name[] = { { 0x08, "deflate", 100 }, { -1, "unknown", 30 } }; unsigned int i; for(i = 0; name[i].method != -1 && method != name[i].method; i++); ph->printf(ph, "%s%s", "compression ", name[i].string); return name[i].score; } static int _callback_flags(PluginHelper * ph, uint8_t flags) { struct { uint8_t flag; char * string; } name[] = { { 0x01, "FTEXT" }, { 0x02, "FHCRC" }, { 0x04, "FEXTRA" }, { 0x08, "FNAME" }, { 0x10, "FCOMMENT" }, { 0x00, NULL } }; unsigned int i; char * prefix = ", flags"; for(i = 0; name[i].string != NULL; i++) { if((flags & name[i].flag) != name[i].flag) continue; ph->printf(ph, "%s %s", prefix, name[i].string); prefix = ""; } if(prefix[0] != '\0') ph->printf(ph, "%s", ", no flags"); return flags & 0xe0 ? 30 : 100; } static int _callback_mtime(PluginHelper * ph, time_t mtime) /* FIXME implement endian interpretation */ { struct tm tm; char tmp[22] = ""; if(mtime == 0) return 100; if(gmtime_r(&mtime, &tm) == NULL || strftime(tmp, sizeof(tmp), ", %d/%m/%Y %H:%M:%S", &tm) == 0) { ph->printf(ph, "%s", ", unknown date"); return 0; } ph->printf(ph, "%s", tmp); /* between Wed May 1 00:00:00 CEST 1996 and now */ return mtime > 830901600 && mtime < time(NULL) ? 100 : 0; } static int _callback_deflate(uint8_t method, uint8_t deflate) { if(method == 0) return 0; if(deflate != 0x02 && deflate != 0x04) return 0; return 100; } static int _callback_os(PluginHelper * ph, uint8_t os) { struct { int os; char * string; int score; } name[] = { { 0, "MS-DOS or OS/2 or NT/Win32 on FAT", 100 }, { 1, "Amiga", 30 }, { 2, "VMS or OpenVMS", 30 }, { 3, "Unix", 100 }, { 4, "VM/CMS", 30 }, { 5, "Atari TOS", 30 }, { 6, "OS/2 or NT on HPFS", 100 }, { 7, "Macintosh", 100 }, { 8, "Z-System", 30 }, { 9, "CP/M", 30 }, { 10, "TOPS-20", 30 }, { 11, "NT on NTFS", 100 }, { 12, "QDOS", 30 }, { 13, "Acorn RISCOS", 100 }, { -1, "unknown", 20 } }; unsigned int i; for(i = 0; name[i].os != -1 && os != name[i].os; i++); ph->printf(ph, "%s%s", ", OS ", name[i].string); return name[i].score; }