summaryrefslogtreecommitdiff
path: root/src/modules/typedetect/libmagic/LibMagicTypeDetect.cpp
blob: 458235316574b547cb7c9fd3896bf1cedf411c26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "LibMagicTypeDetect.hpp"
#include "Logger.hpp"

#include <stdexcept>

#include <cstdlib>

LibMagicTypeDetect::LibMagicTypeDetect( )
{
	m_magic = magic_open( MAGIC_MIME_TYPE | MAGIC_CONTINUE );
	if( m_magic == NULL ) {
		throw runtime_error( "Unable to open magic file" );
	}
	
	if( magic_load( m_magic, NULL ) != 0 ) {
		throw runtime_error( "Unable to load standard magic file database" );
	}
}

LibMagicTypeDetect::~LibMagicTypeDetect( )
{
	magic_close( m_magic );
}

MIMEType LibMagicTypeDetect::detect( RewindInputStream *s )
{
	enum { CHUNKSIZE = 65535 };
	enum { MAXBUFSIZE = 1024 * 1024 * 16 };
	size_t bufsize = 0;
	char *buf = (char *)malloc( CHUNKSIZE );
	size_t offset = 0;
	const char *res = 0;
	MIMEType type;
	
	while( s->good( ) && !s->eof( ) ) {
		s->read( buf + offset, CHUNKSIZE );
		std::streamsize n = s->gcount( );
		
		res = magic_buffer( m_magic, buf, bufsize + n );
		
		if( res != NULL ) {
			type = MIMEType( res );
			if( type != MIMEType::Null ) {
				break;
			}
		}
		
		bufsize += CHUNKSIZE;
		offset += CHUNKSIZE;

		if( bufsize > MAXBUFSIZE ) {
			break;
		}

		buf = (char *)realloc( buf, bufsize );
	}
	
	free( buf );
	
	if( res == NULL ) {
		return MIMEType::Null;
	}
	
	return MIMEType( res );
}

REGISTER_MODULE( "libmagic_typedetect", TypeDetect, LibMagicTypeDetect )