ÜberWall

UWfirmforce

/* $Id: gzip.c,v 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 <stdint.h>
#include <string.h>
#include <time.h>
#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;
}