/* fileentry.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2001-2023 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "fileentry.hh"
#include "aguix/lowlevelfunc.h"
#include "aguix/fieldlistviewdnd.h"
#include "wconfig.h"
#include "grouphash.h"
#include "pdatei.h"
#include "nmrowdata.h"
#include "condparser.h"
#include "stringbuf.h"
#include "wcfiletype.hh"
#include "magic_db.hh"
#include "worker.h"
#include "nwc_os.hh"
#include "error_count.hh"

class FEBookmarkInfo {
public:
    FEBookmarkInfo() : m_bookmark_match( FileEntry::NOT_IN_BOOKMARKS ),
                       m_matching_labels( NULL )
    {
    }
    FEBookmarkInfo( const FEBookmarkInfo &other ) : m_bookmark_match( other.m_bookmark_match ),
                                                    m_matching_labels( NULL )
    {
        if ( other.m_matching_labels != NULL ) {
            m_matching_labels = new std::list<std::string>( *other.m_matching_labels );
        }
    }

    ~FEBookmarkInfo()
    {
        if ( m_matching_labels != NULL ) {
            delete m_matching_labels;
        }
    }

    FEBookmarkInfo &operator=( const FEBookmarkInfo &rhs )
    {
        if ( this != &rhs ) {
            m_bookmark_match = rhs.m_bookmark_match;

            if ( m_matching_labels != NULL ) delete m_matching_labels;
            if ( rhs.m_matching_labels != NULL ) {
                m_matching_labels = new std::list<std::string>( *rhs.m_matching_labels );
            } else {
                m_matching_labels = NULL;
            }
        }
        return *this;
    }


    FileEntry::bookmark_match_t m_bookmark_match;
    std::list<std::string> *m_matching_labels;
};

FileEntry::FileEntry()
{
  name=NULL;
  fullname=NULL;
  filetype=NULL;
  use=true;
  isHidden=false;
  isCorrupt = false;
  exists = false;
  
  reclistQueued = false;
  
  memset( &statbuf, 0, sizeof( statbuf ) );
  memset( &dstatbuf, 0, sizeof( dstatbuf ) );
  
  contentBuf.content = NULL;
  contentBuf.size = 0;
  
  outputBuf = NULL;

  _ID = -1;

  m_bookmark_info = NULL;
}

FileEntry::~FileEntry()
{
  if(name!=NULL) _freesafe(name);
  if(fullname!=NULL) _freesafe(fullname);
  freeContentBuf();
  freeOutputBuf();

  if ( m_bookmark_info != NULL ) delete m_bookmark_info;
}

bool FileEntry::isDir() const
{
  bool dir=false;
  if ( isLink == true ) {
    if ( isCorrupt == false ) {
      if ( S_ISDIR( dstatbuf.mode ) ) dir = true;
    }
  } else if ( S_ISDIR( statbuf.mode ) ) dir = true;
  return dir;
}

FileEntry *FileEntry::duplicate()
{
#if 0
  FileEntry *tfe=new FileEntry();
  tfe->fullname=dupstring(fullname);
  tfe->name=dupstring(name);
  tfe->dirsize=dirsize;
  tfe->select=select;
  tfe->isLink=isLink;
  tfe->isCorrupt=isCorrupt;
  tfe->inFilter=inFilter;
  tfe->filetype=filetype;

  memcpy( &( tfe->statbuf ), &statbuf, sizeof( statbuf ) );
  memcpy( &( tfe->dstatbuf ), &dstatbuf, sizeof( dstatbuf ) );

  tfe->setCustomColors( customcolors );
  tfe->setColor( 0, fg );
  tfe->setColor( 1, bg );

  return tfe;
#endif
  return new FileEntry( *this );
}

int FileEntry::readInfos()
{
  return readInfos(false);
}

int FileEntry::readInfos( bool update )
{
    //TODO: auf update achten
    worker_struct_stat stbuf;

    select = false;
    dirsize = -1;
    filetype = NULL;
    isCorrupt = false;
    isLink = false;
    exists = false;

    if ( fullname == NULL ) return 1;

    memset( &statbuf, 0, sizeof( statbuf ) );
    memset( &dstatbuf, 0, sizeof( dstatbuf ) );

    if ( worker_lstat( fullname, &stbuf ) == 0 ) {
        statbuf.size = stbuf.st_size;
        statbuf.lastaccess = stbuf.st_atime;
        statbuf.lastmod = stbuf.st_mtime;
        statbuf.lastchange = stbuf.st_ctime;
        statbuf.mode = stbuf.st_mode;
        statbuf.userid = stbuf.st_uid;
        statbuf.groupid = stbuf.st_gid;
        statbuf.inode = stbuf.st_ino;
        statbuf.nlink = stbuf.st_nlink;
        statbuf.blocks = stbuf.st_blocks;
        statbuf.rdev = stbuf.st_rdev;
        statbuf.dev = stbuf.st_dev;

        exists = true;
    } else {
        ErrorCount::account_errno( errno );
        isCorrupt = true;
        return 2;
    }

    if ( S_ISLNK( statbuf.mode ) ) {
        isLink = true;
        if ( worker_stat( fullname, &stbuf ) == 0 ) {
            dstatbuf.size = stbuf.st_size;
            dstatbuf.lastaccess = stbuf.st_atime;
            dstatbuf.lastmod = stbuf.st_mtime;
            dstatbuf.lastchange = stbuf.st_ctime;
            dstatbuf.mode = stbuf.st_mode;
            dstatbuf.userid = stbuf.st_uid;
            dstatbuf.groupid = stbuf.st_gid;
            dstatbuf.inode = stbuf.st_ino;
            dstatbuf.nlink = stbuf.st_nlink;
            dstatbuf.blocks = stbuf.st_blocks;
            dstatbuf.rdev = stbuf.st_rdev;
            dstatbuf.dev = stbuf.st_dev;
        } else {
            /* corrupt link */
            ErrorCount::account_errno( errno );
            isCorrupt = true;
            dstatbuf.mode = 0;  // to prevent corrupt links treated as dirs
            if ( errno == ENOENT ) {
                // Eventl. fuer spaetere Betrachtungen
            }
        }
    }
    return 0;
}

char *FileEntry::getDestination() const
{
    char *str = NULL;
    if ( isLink == true && fullname != NULL ) {
        str = NWC::OS::getLinkTarget( fullname );
    }
    return str;
}

const char *FileEntry::getPermissionString()
{
  static char str[WORKER_PERMCHARS + 1];

  if ( isLink == true ) str[0] = 'l';
  else {
      if ( isCorrupt ) str[0] = '?';
      else if ( S_ISDIR( statbuf.mode ) ) str[0] = 'd';
      else if ( S_ISFIFO( statbuf.mode ) ) str[0] = 'p';
      else if ( S_ISSOCK( statbuf.mode ) ) str[0] = 's';
      else if ( S_ISCHR( statbuf.mode ) ) str[0] = 'c';
      else if ( S_ISBLK( statbuf.mode ) ) str[0] = 'b';
      else str[0] = '-';
  }
  if ( ( statbuf.mode & S_IRUSR ) == S_IRUSR ) str[1] = 'r'; else str[1] = '-';
  if ( ( statbuf.mode & S_IWUSR ) == S_IWUSR ) str[2] = 'w'; else str[2] = '-';
  if ( ( statbuf.mode & S_ISUID ) == S_ISUID ) {
    if ( ( statbuf.mode & S_IXUSR ) == S_IXUSR ) str[3] = 's'; else str[3] = 'S';
  } else {
    if ( ( statbuf.mode & S_IXUSR ) == S_IXUSR ) str[3] = 'x'; else str[3] = '-';
  }
  if ( ( statbuf.mode & S_IRGRP ) == S_IRGRP ) str[4] = 'r'; else str[4] = '-';
  if ( ( statbuf.mode & S_IWGRP ) == S_IWGRP ) str[5] = 'w'; else str[5] = '-';
  if ( ( statbuf.mode & S_ISGID ) == S_ISGID ) {
    if ( ( statbuf.mode & S_IXGRP ) == S_IXGRP ) str[6] = 's'; else str[6] = 'S';
  } else {
    if ( ( statbuf.mode & S_IXGRP ) == S_IXGRP ) str[6] = 'x'; else str[6] = '-';
  }
  if ( ( statbuf.mode & S_IROTH ) == S_IROTH ) str[7] = 'r'; else str[7] = '-';
  if ( ( statbuf.mode & S_IWOTH ) == S_IWOTH ) str[8] = 'w'; else str[8] = '-';
  if ( ( statbuf.mode & S_ISVTX ) == S_ISVTX ) {
    if ( ( statbuf.mode & S_IXOTH ) == S_IXOTH ) str[9] = 't'; else str[9] = 'T';
  } else {
    if ( ( statbuf.mode & S_IXOTH ) == S_IXOTH ) str[9] = 'x'; else str[9] = '-';
  }
  str[10]=0;
  return str;
}

bool FileEntry::isExe( bool fastTest ) const
{
  if ( fastTest == true ) {
    if ( ( statbuf.mode & S_IXUSR ) == S_IXUSR ) return true;
    if ( ( statbuf.mode & S_IXGRP ) == S_IXGRP ) return true;
    if ( ( statbuf.mode & S_IXOTH ) == S_IXOTH ) return true;
  } else {
    uid_t uid;
    gid_t gid;
    mode_t m;
    bool e = false;

    if ( isLink == false ) {
      uid = userid();
      gid = groupid();
      m = mode();
    } else if ( isCorrupt == false ) {
      uid = duserid();
      gid = dgroupid();
      m = dmode();
    } else {
      // corrupt symlink is not executable
      return false;
    }
    
    if ( uid == geteuid() ) {
      e = ( ( m & S_IXUSR ) != 0 ) ? true : false;
    } else if ( ugdb->isInGroup( gid ) == true ) {
      e = ( ( m & S_IXGRP ) != 0 ) ? true : false;
    } else {
      e = ( ( m & S_IXOTH ) != 0 ) ? true : false;
    }
    return e;
  }
  return false;
}

bool FileEntry::match( const char* pattern )
{
  if(fnmatch(pattern,name,0)==0) return true;
  return false;
}

loff_t FileEntry::size() const
{
  return statbuf.size;
}

time_t FileEntry::lastaccess() const
{
  return statbuf.lastaccess;
}

time_t FileEntry::lastmod() const
{
  return statbuf.lastmod;
}

time_t FileEntry::lastchange() const
{
  return statbuf.lastchange;
}

mode_t FileEntry::mode() const
{
  return statbuf.mode;
}

uid_t FileEntry::userid() const
{
  return statbuf.userid;
}

gid_t FileEntry::groupid() const
{
  return statbuf.groupid;
}

ino_t FileEntry::inode() const
{
  return statbuf.inode;
}

nlink_t FileEntry::nlink() const
{
  return statbuf.nlink;
}

loff_t FileEntry::blocks() const
{
  return statbuf.blocks;
}

loff_t FileEntry::dsize() const
{
  return dstatbuf.size;
}

time_t FileEntry::dlastaccess() const
{
  return dstatbuf.lastaccess;
}

time_t FileEntry::dlastmod() const
{
  return dstatbuf.lastmod;
}

time_t FileEntry::dlastchange() const
{
  return dstatbuf.lastchange;
}

mode_t FileEntry::dmode() const
{
  return dstatbuf.mode;
}

uid_t FileEntry::duserid() const
{
  return dstatbuf.userid;
}

gid_t FileEntry::dgroupid() const
{
  return dstatbuf.groupid;
}

ino_t FileEntry::dinode() const
{
  return dstatbuf.inode;
}

nlink_t FileEntry::dnlink() const
{
  return dstatbuf.nlink;
}

loff_t FileEntry::dblocks() const
{
  return dstatbuf.blocks;
}

dev_t FileEntry::rdev() const
{
  return statbuf.rdev;
}

dev_t FileEntry::drdev() const
{
  return dstatbuf.rdev;
}

dev_t FileEntry::dev() const
{
  return statbuf.dev;
}

dev_t FileEntry::ddev() const
{
  return dstatbuf.dev;
}

bool FileEntry::checkAccess( int m ) const
{
  if ( fullname == NULL ) return false;
  return ( worker_access( fullname, m ) == 0 ) ? true : false;
}

char *FileEntry::getContentStr( int pos, int len )
{
  char *resstr = NULL;
  int mylen, i;

  if ( pos < 0 ) return dupstring( "" );
  if ( len < 1 ) return dupstring( "" );

  if ( contentBuf.content == NULL ) readContentBuf();
  if ( contentBuf.content != NULL ) {
    mylen = a_min( len, contentBuf.size - pos );
    if ( mylen > 0 ) {
      resstr = (char*)_allocsafe( mylen + 1 );
      for ( i = 0; i < mylen; i++ ) {
        resstr[i] = contentBuf.content[i+pos];
      }
      resstr[i] = '\0';
    }
  }
  
  return ( resstr != NULL ) ? resstr : dupstring( "" );
}

int FileEntry::getContentNum( int pos, int len )
{
  int mylen, i;
  int res = -1;

  if ( pos < 0 ) return -1;
  if ( len < 1 ) return -1;
  
  if ( contentBuf.content == NULL ) readContentBuf();
  if ( contentBuf.content != NULL ) {
    mylen = a_min( len, contentBuf.size - pos );
    if ( mylen > 0 ) {
      res = 0;
      for ( i = 0; i < mylen; i++ ) {
        res <<= 8;
        res += (unsigned char)contentBuf.content[i+pos];
      }
    }
  }
  
  return res;
}

void FileEntry::freeContentBuf()
{
  if ( contentBuf.content != NULL ) {
    _freesafe( contentBuf.content );
    contentBuf.content = NULL;
    contentBuf.size = 0;
  }
}

void FileEntry::readContentBuf( int len )
{
  int reads, i;
  unsigned char fbuffer[64];
  PDatei *pfp;
  
  if ( isReg() == false ) return;
  if ( ( len < 1 ) || ( len > 64 ) ) return;
  if ( contentBuf.content == NULL ) {
    reads = -1;
    pfp = new PDatei();
    if ( pfp->open( fullname ) == 0 ) {
      reads = pfp->read( fbuffer, len );
    }
    delete pfp;
    if ( ( reads > 0 ) && ( reads <= len ) ) {
      contentBuf.content = (char*)_allocsafe( len + 1 );
      contentBuf.size = reads;
      for ( i = 0; i < reads; i++ ) {
        contentBuf.content[i] = (char)fbuffer[i];
      }
      for ( i = reads; i < ( len + 1 ); i++ ) {
        contentBuf.content[i] = '\0';
      }
    }
  }
}

void FileEntry::freeOutputBuf()
{
  if ( outputBuf != NULL ) {
    delete outputBuf;
    outputBuf = NULL;
  }
}

const char *FileEntry::findOutput( const char *tcommand )
{
  if ( outputBuf == NULL ) {
    outputBuf = new StringBuf();
  } else {
    return outputBuf->find( tcommand );
  }
  return NULL;
}

void FileEntry::addOutput( const char *tcommand, const char *toutput, int value )
{
  if ( outputBuf == NULL ) outputBuf = new StringBuf();
  
  outputBuf->add( tcommand, toutput, value );
}

int FileEntry::findReturnvalue( const char *tcommand, int *return_value )
{
  if ( outputBuf == NULL ) {
    outputBuf = new StringBuf();
  } else {
    return outputBuf->findValue( tcommand, return_value );
  }
  return -1;
}

int FileEntry::findOutputAndRV( const char *tcommand,
                                const char **return_output,
                                int *return_value )
{
  if ( outputBuf == NULL ) {
    outputBuf = new StringBuf();
  } else {
    return outputBuf->find( tcommand, return_output, return_value );
  }
  return -1;
}

bool FileEntry::isReg() const
{
  if ( isLink == false ) {
    if ( isCorrupt == true ) return false;
    if ( S_ISREG( statbuf.mode ) ) return true;
    else return false;
  }
  if ( isCorrupt == true ) return false;
  if ( S_ISREG( dstatbuf.mode ) ) return true;
  return false;
}

void FileEntry::setCustomColor( const FileEntryCustomColor &c )
{
    m_colors.setCustomColor( c );
}

void FileEntry::setCustomColors( const int fg[4], const int bg[4] )
{
    m_colors.setCustomColors( fg, bg );
}

const FileEntryCustomColor &FileEntry::getCustomColor() const
{
    return m_colors.getCustomColor();
}

int FileEntry::getCustomColorSet() const
{
    return m_colors.getCustomColorSet();
}

void FileEntry::clearCustomColor()
{
    m_colors.setCustomColorSet( 0 );
}

void FileEntry::clearOverrideColor()
{
    m_colors.setOverrideColorSet( 0 );
}

void FileEntry::setColor( const FileEntryColor &c )
{
    m_colors = c;
}

const FileEntryColor &FileEntry::getColor() const
{
    return m_colors;
}

void FileEntry::setOverrideColor( int type, int fg, int bg )
{
    m_colors.setOverrideColor( type, fg, bg );
}

/*
 * Method to check for same destination file
 * it currently only check the destination itself, not the possible
 * destination of a symlink
 */
bool FileEntry::isSameFile( const char *othername, bool follow_symlinks ) const
{
  worker_struct_stat buf;

  if ( othername == NULL ) return false;
  if ( worker_stat( othername, &buf ) != 0 ) return false;

  if ( ( isLink == true ) && ( follow_symlinks == true ) && ( isCorrupt == false ) ) {
    if ( ( dinode() == buf.st_ino ) && ( ddev() == buf.st_dev ) ) return true;
  } else {
    if ( ( inode() == buf.st_ino ) && ( dev() == buf.st_dev ) ) return true;
  }
  return false;
}

bool FileEntry::isSamePath( const FileEntry *fe ) const
{
    if ( ! fe ) return false;

    if ( fullname == NULL || fe->fullname == NULL ) return false;
  
    if ( strcmp( fullname, fe->fullname ) == 0 ) return true;

    return false;
}

FileEntry::FileEntry( const FileEntry &other )
{
  fullname = ( other.fullname != NULL ) ? dupstring( other.fullname ) : NULL;
  name = (other.name != NULL ) ? dupstring( other.name ) : NULL;
  filetype = other.filetype;
  use = other.use;
  isHidden = other.isHidden;
  reclistQueued = other.reclistQueued;

  memcpy( &statbuf, &( other.statbuf ), sizeof( statbuf ) );
  memcpy( &dstatbuf, &( other.dstatbuf ), sizeof( dstatbuf ) );

  setColor( other.getColor() );

  dirsize = other.dirsize;
  select = other.select;
  isLink = other.isLink;
  isCorrupt = other.isCorrupt;
  exists = other.exists;

  // not copied
  contentBuf.content = NULL;
  contentBuf.size = 0;
  
  outputBuf = NULL;

  _ID = other._ID;

  if ( other.m_bookmark_info != NULL ) {
      m_bookmark_info = new FEBookmarkInfo( *other.m_bookmark_info );
  } else {
      m_bookmark_info = NULL;
  }

  m_filetype_file_output = other.m_filetype_file_output;
  m_mime_type = other.m_mime_type;
}

FileEntry::FileEntry( const NWC::FSEntry &other )
{
    fullname = dupstring( other.getFullname().c_str() );
    name = dupstring( other.getBasename().c_str() );
    filetype = nullptr;
    use = true;
    isHidden = other.isHiddenEntry();
    isCorrupt = other.isBrokenLink();
    exists = other.entryExists();

    reclistQueued = false;

    memset( &statbuf, 0, sizeof( statbuf ) );
    memset( &dstatbuf, 0, sizeof( dstatbuf ) );
    
    statbuf.size = other.stat_size();
    statbuf.lastaccess = other.stat_lastaccess();
    statbuf.lastmod = other.stat_lastmod();
    statbuf.lastchange = other.stat_lastchange();
    statbuf.mode = other.stat_mode();
    statbuf.userid = other.stat_userid();
    statbuf.groupid = other.stat_groupid();
    statbuf.inode = other.stat_inode();
    statbuf.nlink = other.stat_nlink();
    statbuf.blocks = other.stat_blocks();
    statbuf.rdev = other.stat_rdev();
    statbuf.dev = other.stat_dev();

    dstatbuf.size = other.stat_dest_size();
    dstatbuf.lastaccess = other.stat_dest_lastaccess();
    dstatbuf.lastmod = other.stat_dest_lastmod();
    dstatbuf.lastchange = other.stat_dest_lastchange();
    dstatbuf.mode = other.stat_dest_mode();
    dstatbuf.userid = other.stat_dest_userid();
    dstatbuf.groupid = other.stat_dest_groupid();
    dstatbuf.inode = other.stat_dest_inode();
    dstatbuf.nlink = other.stat_dest_nlink();
    dstatbuf.blocks = other.stat_dest_blocks();
    dstatbuf.rdev = other.stat_dest_rdev();
    dstatbuf.dev = other.stat_dest_dev();

    dirsize = 0;
    select = false;
    isLink = other.isLink();

    contentBuf.content = NULL;
    contentBuf.size = 0;
  
    outputBuf = NULL;

    _ID = -1;

    m_bookmark_info = NULL;
}

/*
 * Method to test for equal fileentry
 *
 * Does same extented test to ensure that the fileentry
 * is a duplicated version
 */
bool FileEntry::equals( const FileEntry *fe ) const
{
  if ( fe == NULL ) return false;
  if ( fe == this ) return true;
  return equals( *fe );
}

bool FileEntry::equals( const FileEntry &fe ) const
{
  // require name
  if ( ( fullname == NULL ) || ( fe.fullname == NULL ) ) return false;
  
  // require same inode/device

  //Currently disabled because AVFS can set 0
  //  if ( statbuf.inode == 0 ) return false;
  if ( ( statbuf.inode != fe.statbuf.inode ) || ( statbuf.dev != fe.statbuf.dev ) ) return false;

  // require same size
  if ( statbuf.size != fe.statbuf.size ) return false;

  // require same name
  if ( strcmp( fullname, fe.fullname ) != 0 ) return false;

  // finally require same times

  // skip access time check since it might be changed by background file type check
  // if ( statbuf.lastaccess != fe.statbuf.lastaccess ) return false;

  if ( statbuf.lastmod != fe.statbuf.lastmod ) return false;
  if ( statbuf.lastchange != fe.statbuf.lastchange ) return false;

  return true;
}

int FileEntry::getID() const
{
    return _ID;
}

void FileEntry::setID( int ID )
{
    _ID = ID;
}

void FileEntry::setMatchingLabels( const std::list<std::string> &labels )
{
    if ( labels.empty() == true ) {
        if ( m_bookmark_info != NULL ) {
            delete m_bookmark_info;
            m_bookmark_info = NULL;
        }
    } else {
        if ( m_bookmark_info == NULL ) {
            m_bookmark_info = new FEBookmarkInfo;
        }
        if ( m_bookmark_info->m_matching_labels != NULL ) delete m_bookmark_info->m_matching_labels;
        m_bookmark_info->m_matching_labels = new std::list<std::string>( labels );
    }
}

const std::list<std::string> &FileEntry::getMatchingLabels() const
{
    if ( m_bookmark_info == NULL ) throw( 1 );
    if ( m_bookmark_info->m_matching_labels == NULL ) throw( 1 );
    
    return *m_bookmark_info->m_matching_labels;
}

void FileEntry::clearMatchingLabels()
{
    if ( m_bookmark_info != NULL ) {
        delete m_bookmark_info;
        m_bookmark_info = NULL;
    }
}

bool FileEntry::hasMatchingLabels() const
{
    if ( m_bookmark_info == NULL ) return false;
    if ( m_bookmark_info->m_matching_labels == NULL ) return false;
    if ( m_bookmark_info->m_matching_labels->empty() == true ) return false;

    return true;
}

FileEntry::bookmark_match_t FileEntry::getBookmarkMatch() const
{
    if ( m_bookmark_info == NULL ) return FileEntry::NOT_IN_BOOKMARKS;
    return m_bookmark_info->m_bookmark_match;
}

void FileEntry::setBookmarkMatch( bookmark_match_t m )
{
    if ( m == NOT_IN_BOOKMARKS ) {
        if ( m_bookmark_info != NULL ) {
            m_bookmark_info->m_bookmark_match = m;
        }
    } else {
        if ( m_bookmark_info == NULL ) {
            m_bookmark_info = new FEBookmarkInfo;
        }
        m_bookmark_info->m_bookmark_match = m;
    }
}

void FileEntry::setFiletypeFileOutput( const std::string &output )
{
    m_filetype_file_output = output;
}

std::string FileEntry::getFiletypeFileOutput() const
{
    return m_filetype_file_output;
}

void FileEntry::setMimeType( const std::string &mimetype )
{
    m_mime_type = mimetype;
}

std::string FileEntry::getMimeType() const
{
    return m_mime_type;
}
