• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
kmimemagic.cpp
1/* This file is part of the TDE libraries
2 Copyright (C) 2014 Timothy Pearson <kb9vqf@pearsoncomputing.net>
3
4 Small portions (the original KDE interface and utime code) are:
5 Copyright (C) 2000 Fritz Elfert <fritz@kde.org>
6 Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License version 2 as published by the Free Software Foundation.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23#include "config.h"
24#include "kmimemagic.h"
25#include <kdebug.h>
26#include <tdeapplication.h>
27#include <tqfile.h>
28#include <tdesimpleconfig.h>
29#include <tdestandarddirs.h>
30#include <kstaticdeleter.h>
31#include <klargefile.h>
32#include <assert.h>
33
34#include <magic.h>
35
36#ifndef MAGIC_MIME_TYPE
37#define MAGIC_MIME_TYPE MAGIC_MIME
38#endif
39
40// Taken from file/file.h
41// Keep in sync with that header!
42#define FILE_LOAD 0
43
44static void process(struct config_rec* conf, const TQString &);
45
46KMimeMagic* KMimeMagic::s_pSelf;
47static KStaticDeleter<KMimeMagic> kmimemagicsd;
48
49KMimeMagic* KMimeMagic::self() {
50 if( !s_pSelf ) {
51 initStatic();
52 }
53 return s_pSelf;
54}
55
56void KMimeMagic::initStatic() {
57 s_pSelf = kmimemagicsd.setObject( s_pSelf, new KMimeMagic() );
58 s_pSelf->setFollowLinks( true );
59}
60
61#include <stdio.h>
62#include <unistd.h>
63#include <stdlib.h>
64#include <sys/wait.h>
65#include <sys/types.h>
66#include <sys/stat.h>
67#include <fcntl.h>
68#include <errno.h>
69#include <ctype.h>
70#include <time.h>
71#include <utime.h>
72#include <stdarg.h>
73#include <tqregexp.h>
74#include <tqstring.h>
75
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"
84
95class KMimeMagicUtimeConf {
96 public:
97 KMimeMagicUtimeConf() {
98 tmpDirs << TQString::fromLatin1("/tmp"); // default value
99
100 // The trick is that we also don't want the user to override globally set
101 // directories. So we have to misuse TDEStandardDirs :}
102 TQStringList confDirs = TDEGlobal::dirs()->resourceDirs( "config" );
103 if ( !confDirs.isEmpty() ) {
104 TQString globalConf = confDirs.last() + "kmimemagicrc";
105 if ( TQFile::exists( globalConf ) ) {
106 TDESimpleConfig cfg( globalConf );
107 cfg.setGroup( "Settings" );
108 tmpDirs = cfg.readListEntry( "atimeDirs" );
109 }
110 if ( confDirs.count() > 1 ) {
111 TQString localConf = confDirs.first() + "kmimemagicrc";
112 if ( TQFile::exists( localConf ) ) {
113 TDESimpleConfig cfg( localConf );
114 cfg.setGroup( "Settings" );
115 tmpDirs += cfg.readListEntry( "atimeDirs" );
116 }
117 }
118 for ( TQStringList::Iterator it = tmpDirs.begin() ; it != tmpDirs.end() ; ++it ) {
119 TQString dir = *it;
120 if ( !dir.isEmpty() && dir[ dir.length()-1 ] != '/' ) {
121 (*it) += '/';
122 }
123 }
124 }
125 #if 0
126 // debug code
127 for ( TQStringList::Iterator it = tmpDirs.begin() ; it != tmpDirs.end() ; ++it ) {
128 kdDebug(7018) << " atimeDir: " << *it << endl;
129 }
130 #endif
131 }
132
133 bool restoreAccessTime( const TQString & file ) const {
134 TQString dir = file.left( file.findRev( '/' ) );
135 bool res = tmpDirs.contains( dir );
136 //kdDebug(7018) << "restoreAccessTime " << file << " dir=" << dir << " result=" << res << endl;
137 return res;
138 }
139 TQStringList tmpDirs;
140};
141
142TQString fixupMagicOutput(TQString &mime) {
143 if (mime == "inode/x-empty") {
144 return MIME_BINARY_ZEROSIZE;
145 }
146 else if (mime.contains("no read permission")) {
147 return MIME_BINARY_UNREADABLE;
148 }
149 else {
150 return mime;
151 }
152}
153
154/* current config */
155struct config_rec {
156 bool followLinks;
157 TQString resultBuf;
158 int accuracy;
159
160 magic_t magic;
161 TQStringList databases;
162
163 KMimeMagicUtimeConf * utimeConf;
164};
165
166/*
167 * apprentice - load configuration from the magic file.
168 */
169int KMimeMagic::apprentice( const TQString& magicfile ) {
170 TQString maindatabase = magicfile;
171 if (maindatabase == "") {
172#ifdef HAVE_LIBMAGIC_GETPATH
173 maindatabase = magic_getpath(0, FILE_LOAD);
174#else
175 maindatabase = TQString(LIBMAGIC_PATH);
176#endif
177 if (maindatabase == "") {
178 kdWarning() << k_funcinfo << "Unable to locate system mime magic database; mime type detection will not function correctly!" << endl;
179 }
180 }
181 conf->databases.clear();
182 conf->databases.append(maindatabase);
183 return magic_load(conf->magic, conf->databases[0].latin1());
184}
185
186/*
187 * magic_process - process input file fn. Opens the file and reads a
188 * fixed-size buffer to begin processing the contents.
189 */
190
191void process(struct config_rec* conf, const TQString & fn) {
192 KDE_struct_stat sb;
193 TQCString fileName = TQFile::encodeName( fn );
194
195 int magic_flags = MAGIC_ERROR|MAGIC_MIME_TYPE/*|MAGIC_DEBUG*/;
196 if (conf->followLinks) {
197 magic_flags |= MAGIC_SYMLINK;
198 }
199 magic_setflags(conf->magic, magic_flags);
200 conf->resultBuf = TQString(magic_file(conf->magic, fileName));
201 conf->resultBuf = fixupMagicOutput(conf->resultBuf);
202
203 if ( conf->utimeConf && conf->utimeConf->restoreAccessTime( fn ) ) {
204 /*
205 * Try to restore access, modification times if read it.
206 * This changes the "change" time (ctime), but we can't do anything
207 * about that.
208 */
209 struct utimbuf utbuf;
210 utbuf.actime = sb.st_atime;
211 utbuf.modtime = sb.st_mtime;
212 (void) utime(fileName, &utbuf);
213 }
214}
215
216KMimeMagic::KMimeMagic() {
217 // Magic file detection init
218 TQString mimefile = locate( "mime", "magic" );
219 init( mimefile );
220 // Add snippets from share/config/magic/*
221 TQStringList snippets = TDEGlobal::dirs()->findAllResources( "config", "magic/*.magic", true );
222 for ( TQStringList::Iterator it = snippets.begin() ; it != snippets.end() ; ++it ) {
223 if ( !mergeConfig( *it ) ) {
224 kdWarning() << k_funcinfo << "Failed to parse " << *it << endl;
225 }
226 }
227}
228
229KMimeMagic::KMimeMagic(const TQString & _configfile) {
230 init( _configfile );
231}
232
233void KMimeMagic::init( const TQString& _configfile ) {
234 int result;
235 conf = new config_rec;
236
237 /* initialize libmagic */
238 conf->magic = magic_open(MAGIC_MIME_TYPE);
239 magicResult = NULL;
240 conf->followLinks = false;
241
242 conf->utimeConf = 0L; // created on demand
243 /* on the first time through we read the magic file */
244 result = apprentice(_configfile);
245 if (result == -1) {
246 return;
247 }
248}
249
250/*
251 * The destructor.
252 * Free the magic-table and other resources.
253 */
254KMimeMagic::~KMimeMagic() {
255 if (conf) {
256 magic_close(conf->magic);
257 delete conf->utimeConf;
258 delete conf;
259 }
260 delete magicResult;
261}
262
263bool KMimeMagic::mergeConfig(const TQString & _configfile) {
264 conf->databases.append(_configfile);
265 TQString merged_databases = conf->databases.join(":");
266#ifdef MAGIC_VERSION
267 int magicvers = magic_version();
268#else // MAGIC_VERSION
269 int magicvers = 0;
270#endif // MAGIC_VERSION
271 if ((magicvers < 512) || (magicvers >= 518)) {
272 if (magic_load(conf->magic, merged_databases.latin1()) == 0) {
273 return true;
274 }
275 else {
276 return false;
277 }
278 }
279 else {
280 kdWarning(7018) << k_funcinfo << "KMimeMagic::mergeConfig disabled due to buggy libmagic version " << magicvers << endl;
281 return false;
282 }
283}
284
285void KMimeMagic::setFollowLinks( bool _enable ) {
286 conf->followLinks = _enable;
287}
288
289KMimeMagicResult *KMimeMagic::findBufferType(const TQByteArray &array) {
290 conf->resultBuf = TQString::null;
291 if ( !magicResult ) {
292 magicResult = new KMimeMagicResult();
293 }
294 magicResult->setInvalid();
295 conf->accuracy = 100;
296
297 int nbytes = array.size();
298 if (nbytes == 0) {
299 conf->resultBuf = MIME_BINARY_ZEROSIZE;
300 }
301 else {
302 int magic_flags = MAGIC_ERROR|MAGIC_MIME_TYPE/*|MAGIC_DEBUG*/;
303 if (conf->followLinks) {
304 magic_flags |= MAGIC_SYMLINK;
305 }
306 magic_setflags(conf->magic, magic_flags);
307 conf->resultBuf = TQString(magic_buffer(conf->magic, array.data(), nbytes));
308 conf->resultBuf = fixupMagicOutput(conf->resultBuf);
309 }
310 /* if we have any results, put them in the request structure */
311 magicResult->setMimeType(conf->resultBuf.stripWhiteSpace());
312 magicResult->setAccuracy(conf->accuracy);
313 return magicResult;
314}
315
316static void refineResult(KMimeMagicResult *r, const TQString & _filename) {
317 TQString tmp = r->mimeType();
318 if (tmp.isEmpty())
319 return;
320 if ( tmp == "text/x-c" || tmp == "text/x-objc" )
321 {
322 if ( _filename.right(2) == ".h" )
323 tmp += "hdr";
324 else
325 tmp += "src";
326 r->setMimeType(tmp);
327 }
328 else
329 if ( tmp == "text/x-c++" )
330 {
331 if ( _filename.endsWith(".h")
332 || _filename.endsWith(".hh")
333 || _filename.endsWith(".H")
334 || !_filename.right(4).contains('.'))
335 tmp += "hdr";
336 else
337 tmp += "src";
338 r->setMimeType(tmp);
339 }
340 else
341 if ( tmp == "application/x-sharedlib" )
342 {
343 if ( _filename.find( ".so" ) == -1 )
344 {
345 tmp = "application/x-executable";
346 r->setMimeType( tmp );
347 }
348 }
349}
350
351KMimeMagicResult *KMimeMagic::findBufferFileType( const TQByteArray &data, const TQString &fn) {
352 KMimeMagicResult * r = findBufferType( data );
353 refineResult(r, fn);
354 return r;
355}
356
357/*
358 * Find the content-type of the given file.
359 */
360KMimeMagicResult* KMimeMagic::findFileType(const TQString & fn) {
361#ifdef DEBUG_MIMEMAGIC
362 kdDebug(7018) << "KMimeMagic::findFileType " << fn << endl;
363#endif
364 conf->resultBuf = TQString::null;
365
366 if ( !magicResult ) {
367 magicResult = new KMimeMagicResult();
368 }
369 magicResult->setInvalid();
370 conf->accuracy = 100;
371
372 if ( !conf->utimeConf ) {
373 conf->utimeConf = new KMimeMagicUtimeConf();
374 }
375
376 /* process it based on the file contents */
377 process(conf, fn );
378
379 /* if we have any results, put them in the request structure */
380 magicResult->setMimeType(conf->resultBuf.stripWhiteSpace());
381 magicResult->setAccuracy(conf->accuracy);
382 refineResult(magicResult, fn);
383 return magicResult;
384}
KMimeMagicResult
Definition kmimemagic.h:47
KMimeMagicResult::mimeType
TQString mimeType() const
Retrieve the mimetype (e.g.
Definition kmimemagic.h:55
KMimeMagic
Definition kmimemagic.h:102
KMimeMagic::KMimeMagic
KMimeMagic()
Create a parser and initialize it with the KDE-global data: the "magic" config file as well as the sn...
Definition kmimemagic.cpp:216
KMimeMagic::setFollowLinks
void setFollowLinks(bool _enable)
Enable/Disable follow-links.
Definition kmimemagic.cpp:285
KMimeMagic::findBufferFileType
KMimeMagicResult * findBufferFileType(const TQByteArray &, const TQString &filename)
Same functionality as findBufferType() but with additional capability of distinguishing between C-hea...
Definition kmimemagic.cpp:351
KMimeMagic::magicResult
KMimeMagicResult * magicResult
The result type.
Definition kmimemagic.h:189
KMimeMagic::findFileType
KMimeMagicResult * findFileType(const TQString &_filename)
Try to find a MimeType for the given file.
Definition kmimemagic.cpp:360
KMimeMagic::~KMimeMagic
~KMimeMagic()
Destroy the parser.
Definition kmimemagic.cpp:254
KMimeMagic::mergeConfig
bool mergeConfig(const TQString &configFile)
Merge an existing parse table with the data from the given file.
Definition kmimemagic.cpp:263
KMimeMagic::self
static KMimeMagic * self()
Returns a pointer to the unique KMimeMagic instance in this process.
Definition kmimemagic.cpp:49
KMimeMagic::findBufferType
KMimeMagicResult * findBufferType(const TQByteArray &p)
Same functionality as above, except data is not read from a file.
Definition kmimemagic.cpp:289

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.9.8
This website is maintained by Timothy Pearson.