24 #include "kmimemagic.h"
26 #include <tdeapplication.h>
28 #include <ksimpleconfig.h>
29 #include <kstandarddirs.h>
30 #include <kstaticdeleter.h>
31 #include <klargefile.h>
36 #ifndef MAGIC_MIME_TYPE
37 #define MAGIC_MIME_TYPE MAGIC_MIME
44 static void process(
struct config_rec* conf,
const TQString &);
47 static KStaticDeleter<KMimeMagic> kmimemagicsd;
56 void KMimeMagic::initStatic() {
57 s_pSelf = kmimemagicsd.setObject( s_pSelf,
new KMimeMagic() );
65 #include <sys/types.h>
76 #define MIME_INODE_DIR "inode/directory"
77 #define MIME_INODE_CDEV "inode/chardevice"
78 #define MIME_INODE_BDEV "inode/blockdevice"
79 #define MIME_INODE_FIFO "inode/fifo"
80 #define MIME_INODE_LINK "inode/link"
81 #define MIME_INODE_SOCK "inode/socket"
82 #define MIME_BINARY_UNREADABLE "application/x-unreadable"
83 #define MIME_BINARY_ZEROSIZE "application/x-zerosize"
95 class KMimeMagicUtimeConf {
97 KMimeMagicUtimeConf() {
98 tmpDirs << TQString::fromLatin1(
"/tmp");
102 TQStringList confDirs = TDEGlobal::dirs()->resourceDirs(
"config" );
103 if ( !confDirs.isEmpty() ) {
104 TQString globalConf = confDirs.last() +
"kmimemagicrc";
105 if ( TQFile::exists( globalConf ) ) {
106 KSimpleConfig cfg( globalConf );
107 cfg.setGroup(
"Settings" );
108 tmpDirs = cfg.readListEntry(
"atimeDirs" );
110 if ( confDirs.count() > 1 ) {
111 TQString localConf = confDirs.first() +
"kmimemagicrc";
112 if ( TQFile::exists( localConf ) ) {
113 KSimpleConfig cfg( localConf );
114 cfg.setGroup(
"Settings" );
115 tmpDirs += cfg.readListEntry(
"atimeDirs" );
118 for ( TQStringList::Iterator it = tmpDirs.begin() ; it != tmpDirs.end() ; ++it ) {
120 if ( !dir.isEmpty() && dir[ dir.length()-1 ] !=
'/' ) {
127 for ( TQStringList::Iterator it = tmpDirs.begin() ; it != tmpDirs.end() ; ++it ) {
128 kdDebug(7018) <<
" atimeDir: " << *it << endl;
133 bool restoreAccessTime(
const TQString & file )
const {
134 TQString dir = file.left( file.findRev(
'/' ) );
135 bool res = tmpDirs.contains( dir );
139 TQStringList tmpDirs;
142 TQString fixupMagicOutput(TQString &mime) {
143 if (mime ==
"inode/x-empty") {
144 return MIME_BINARY_ZEROSIZE;
146 else if (mime.contains(
"no read permission")) {
147 return MIME_BINARY_UNREADABLE;
161 TQStringList databases;
163 KMimeMagicUtimeConf * utimeConf;
169 int KMimeMagic::apprentice(
const TQString& magicfile ) {
170 TQString maindatabase = magicfile;
171 if (maindatabase ==
"") {
172 #ifdef HAVE_LIBMAGIC_GETPATH
173 maindatabase = magic_getpath(0, FILE_LOAD);
175 maindatabase = TQString(LIBMAGIC_PATH);
177 if (maindatabase ==
"") {
178 kdWarning() << k_funcinfo <<
"Unable to locate system mime magic database; mime type detection will not function correctly!" << endl;
181 conf->databases.clear();
182 conf->databases.append(maindatabase);
183 return magic_load(conf->magic, conf->databases[0].latin1());
191 void process(
struct config_rec* conf,
const TQString & fn) {
193 TQCString fileName = TQFile::encodeName( fn );
195 int magic_flags = MAGIC_ERROR|MAGIC_MIME_TYPE;
196 if (conf->followLinks) {
197 magic_flags |= MAGIC_SYMLINK;
199 magic_setflags(conf->magic, magic_flags);
200 conf->resultBuf = TQString(magic_file(conf->magic, fileName));
201 conf->resultBuf = fixupMagicOutput(conf->resultBuf);
203 if ( conf->utimeConf && conf->utimeConf->restoreAccessTime( fn ) ) {
209 struct utimbuf utbuf;
210 utbuf.actime = sb.st_atime;
211 utbuf.modtime = sb.st_mtime;
212 (void) utime(fileName, &utbuf);
218 TQString mimefile = locate(
"mime",
"magic" );
221 TQStringList snippets = TDEGlobal::dirs()->findAllResources(
"config",
"magic/*.magic",
true );
222 for ( TQStringList::Iterator it = snippets.begin() ; it != snippets.end() ; ++it ) {
224 kdWarning() << k_funcinfo <<
"Failed to parse " << *it << endl;
233 void KMimeMagic::init(
const TQString& _configfile ) {
235 conf =
new config_rec;
238 conf->magic = magic_open(MAGIC_MIME_TYPE);
240 conf->followLinks =
false;
242 conf->utimeConf = 0L;
244 result = apprentice(_configfile);
256 magic_close(conf->magic);
257 delete conf->utimeConf;
264 conf->databases.append(_configfile);
265 TQString merged_databases = conf->databases.join(
":");
267 int magicvers = magic_version();
271 if ((magicvers < 512) || (magicvers >= 518)) {
272 if (magic_load(conf->magic, merged_databases.latin1()) == 0) {
280 kdWarning(7018) << k_funcinfo <<
"KMimeMagic::mergeConfig disabled due to buggy libmagic version " << magicvers << endl;
286 conf->followLinks = _enable;
290 conf->resultBuf = TQString::null;
295 conf->accuracy = 100;
297 int nbytes = array.size();
299 conf->resultBuf = MIME_BINARY_ZEROSIZE;
302 int magic_flags = MAGIC_ERROR|MAGIC_MIME_TYPE;
303 if (conf->followLinks) {
304 magic_flags |= MAGIC_SYMLINK;
306 magic_setflags(conf->magic, magic_flags);
307 conf->resultBuf = TQString(magic_buffer(conf->magic, array.data(), nbytes));
308 conf->resultBuf = fixupMagicOutput(conf->resultBuf);
311 magicResult->setMimeType(conf->resultBuf.stripWhiteSpace());
320 if ( tmp ==
"text/x-c" || tmp ==
"text/x-objc" )
322 if ( _filename.right(2) ==
".h" )
329 if ( tmp ==
"text/x-c++" )
331 if ( _filename.endsWith(
".h")
332 || _filename.endsWith(
".hh")
333 || _filename.endsWith(
".H")
334 || !_filename.right(4).contains(
'.'))
341 if ( tmp ==
"application/x-sharedlib" )
343 if ( _filename.find(
".so" ) == -1 )
345 tmp =
"application/x-executable";
346 r->setMimeType( tmp );
361 #ifdef DEBUG_MIMEMAGIC
362 kdDebug(7018) <<
"KMimeMagic::findFileType " << fn << endl;
364 conf->resultBuf = TQString::null;
370 conf->accuracy = 100;
372 if ( !conf->utimeConf ) {
373 conf->utimeConf =
new KMimeMagicUtimeConf();
380 magicResult->setMimeType(conf->resultBuf.stripWhiteSpace());
TQString mimeType() const
Retrieve the mimetype (e.g.
KMimeMagic()
Create a parser and initialize it with the KDE-global data: the "magic" config file as well as the sn...
void setFollowLinks(bool _enable)
Enable/Disable follow-links.
KMimeMagicResult * findBufferFileType(const TQByteArray &, const TQString &filename)
Same functionality as findBufferType() but with additional capability of distinguishing between C-hea...
KMimeMagicResult * magicResult
The result type.
KMimeMagicResult * findFileType(const TQString &_filename)
Try to find a MimeType for the given file.
~KMimeMagic()
Destroy the parser.
bool mergeConfig(const TQString &configFile)
Merge an existing parse table with the data from the given file.
static KMimeMagic * self()
Returns a pointer to the unique KMimeMagic instance in this process.
KMimeMagicResult * findBufferType(const TQByteArray &p)
Same functionality as above, except data is not read from a file.