// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.xmule-project.net )
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifdef PRECOMP
#	include "xmule-headers.h"
#else
#	include "otherfunctions.h"
#	include "PartFile.h"
#	include "Preferences.h"                 // CPreferences::GetAllinCat
#	include "resource.h"
#	include "wintypes.h"                    // BYTE DWORD UINT WORD
#	include "xmule.h"
#endif

#include <map>                              // Needed for std::map
#include <stdint.h>                         // uint32_t
#include <wx/utils.h>
#include <wx/file.h>                        // Needed for wxFile

#include "strings.en"

#define itemsof(x) (sizeof(x)/sizeof(x[0]))

wxString GetResString(unsigned int uStringID)
{
    static std::map<unsigned int, wxString> msgs;

    if (msgs.empty())
    {
#include "resource.h"                       // Needed for strings' IDs
#include "strings.en"                       // Needed for strings
        for (unsigned int a = 0; a < itemsof(_resStrings); ++a)
        {
            msgs[_resStrings[a].id] = wxString(_resStrings[a].resstr, *wxConvCurrent);
        }        
    }
    return msgs[uStringID];
}

// Base chars for encode an decode functions
static BYTE base16Chars[17] = "0123456789ABCDEF";

static BYTE base32Chars[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

#define BASE16_LOOKUP_MAX 23
static BYTE base16Lookup[BASE16_LOOKUP_MAX][2] =
{
    {
        '0', 0x0
    }
    ,
    {
        '1', 0x1
    }
    ,
    {
        '2', 0x2
    }
    ,
    {
        '3', 0x3
    }
    ,
    {
        '4', 0x4
    }
    ,
    {
        '5', 0x5
    }
    ,
    {
        '6', 0x6
    }
    ,
    {
        '7', 0x7
    }
    ,
    {
        '8', 0x8
    }
    ,
    {
        '9', 0x9
    }
    ,
    {
        ':', 0x9
    }
    ,
    {
        ';', 0x9
    }
    ,
    {
        '<', 0x9
    }
    ,
    {
        '=', 0x9
    }
    ,
    {
        '>', 0x9
    }
    ,
    {
        '?', 0x9
    }
    ,
    {
        '@', 0x9
    }
    ,
    {
        'A', 0xA
    }
    ,
    {
        'B', 0xB
    }
    ,
    {
        'C', 0xC
    }
    ,
    {
        'D', 0xD
    }
    ,
    {
        'E', 0xE
    }
    ,
    {
        'F', 0xF
    }
}

;

wxString CastItoXBytes(uint64_t count)
{
    wxString buffer;

    if (count < 1024)
    {
        buffer.Printf("%.0f %s", (float) count, GetResString(IDS_BYTES) .GetData());
    }
    else if(count < 1048576)
    {
        buffer.Printf("%.0f %s", (float) count/1024, GetResString(IDS_KBYTES) .GetData());
    }
    else if(count < 1073741824)
    {
        buffer.Printf("%.2f %s", (float) count/1048576, GetResString(IDS_MBYTES) .GetData());
    }
    else if(count < 1099511627776LL)
    {
        buffer.Printf("%.2f %s", (float) count/1073741824, GetResString(IDS_GBYTES) .GetData());
    }
    else
    {
        buffer.Printf("%.3f %s", (float) count/1099511627776LL, GetResString(IDS_TBYTES) .GetData());
    }

    return buffer;
}

wxString CastItoIShort(uint64_t count)
{
    wxString output;

    if (count < 1000)
    {
        output.Printf("%i", count);
    }
    else if(count < 1000000)
    {
        output.Printf("%.0f" + GetResString(IDS_KILO), static_cast<float>(count / 1000));
    }
    else if(count < 1000000000)
    {
        output.Printf("%.2f" + GetResString(IDS_MEGA), static_cast<float>(count / 1000000));
    }
    else if(count < 1000000000000LL)
    {
        output.Printf("%.2f" + GetResString(IDS_GIGA), static_cast<float>(count / 1000000000LL));
    }
    else if(count < 1000000000000000LL)
    {
        output.Printf("%.2f" + GetResString(IDS_TERRA), static_cast<float>(count / 1000000000000LL));
    }

    return output;
}

wxString CastSecondsToHM(int32_t count)
{
    wxString buffer;

    if (count < 0)
    {
        buffer = "?";
    }
    else if(count < 60)
    {
        buffer.Printf("%i %s", count, GetResString(IDS_SECS) .GetData());
    }
    else if(count < 3600)
    {
        buffer.Printf("%i:%s %s", count / 60, LeadingZero(count - (count/60) *60) .GetData(), GetResString(IDS_MINS) .GetData());
    }
    else if(count < 86400)
    {
        buffer.Printf("%i:%s %s", count  /3600, LeadingZero((count - (count/3600) *3600) /60) .GetData(), GetResString(IDS_HOURS) .GetData());
    }
    else
    {
        buffer.Printf("%i %s %i %s", count / 86400, GetResString(IDS_DAYS) .GetData(), (count - (count/86400) *86400) /3600, GetResString(IDS_HOURS) .GetData());
    }

    return buffer;
}

wxString LeadingZero(uint32_t units)
{
    wxString temp;
    if (units < 10)
    {
        temp.Printf("0%i", units);
    }
    else
    {
        temp.Printf("%i", units);
    }

    return temp;
}

//<<--9/21/02
void ShellOpenFile(wxString name)
{
    //ShellExecute(NULL, "open", name, NULL, NULL, SW_SHOW);
    printf("todo. shellopen\n");
}

namespace
{
    bool IsHexDigit(int c)
    {
        switch (c)
        {
        case '0': return true;
        case '1': return true;
        case '2': return true;
        case '3': return true;
        case '4': return true;
        case '5': return true;
        case '6': return true;
        case '7': return true;
        case '8': return true;
        case '9': return true;
        case 'A': return true;
        case 'B': return true;
        case 'C': return true;
        case 'D': return true;
        case 'E': return true;
        case 'F': return true;
        case 'a': return true;
        case 'b': return true;
        case 'c': return true;
        case 'd': return true;
        case 'e': return true;
        case 'f': return true;
        default: return false;
        }
    }
}

void URLDecode(wxString &result, const char *buff)
{
    int buflen = (int) strlen(buff);
    int x;
    int y;
    // length of buff2 will be less or equal to length of buff:
    char *buff2 = nstrdup(buff);
    for (x = 0, y = 0 ; x < buflen ;++x)
    {
        if (buff[x] == '%' &&x + 2 < buflen &&IsHexDigit(buff[x + 1]) &&IsHexDigit(buff[x + 2]))
        {
            char hexstr[3];
            // Copy the two BYTEs following the %
            strncpy(hexstr, &buff[x + 1], 2);
            // Skip over the hex
            x = x + 2;
            // Convert the hex to ASCII
            buff2[y++] = (unsigned char) strtoul(hexstr, NULL, 16);
        }
        else
        {
            buff2[y++] = buff[x];
            break;
        }
    }
    result = buff2;
    delete[] buff2;
}

wxString URLEncode(wxString sIn)
{
    wxString sOut;
    const int nLen = sIn.Length() + 1;
    register LPBYTE pOutTmp = NULL;
    LPBYTE pOutBuf = NULL;
    register LPBYTE pInTmp = NULL;
    //GetData(); //GetBuffer(nLen);:
    LPBYTE pInBuf = (LPBYTE) sIn.GetWriteBuf(nLen);
    //alloc out buffer
    //GetData(); //GetBuffer(nLen  * 3 - 2);//new BYTE [nLen  * 3];:
    pOutBuf = (LPBYTE) sOut.GetWriteBuf(nLen *3 - 2);
    if (pOutBuf)
    {
        pInTmp = pInBuf;
        pOutTmp = pOutBuf;
        // do encoding
        while ( *pInTmp)
        {
            if (isalnum( *pInTmp))
            *pOutTmp++= *pInTmp;
            else
            if (isspace( *pInTmp))
            *pOutTmp++= '+';
            else
            {
                *pOutTmp++= '%';
                *pOutTmp++= toHex( *pInTmp >> 4);
                *pOutTmp++= toHex( *pInTmp%16);
            }
            pInTmp++;
        }
        *pOutTmp = '\0';
        sOut = pOutBuf;
        //delete [] pOutBuf;
        //Out.ReleaseBuffer();
        sOut.UngetWriteBuf();
    }
    //sIn.ReleaseBuffer();
    sIn.UngetWriteBuf();
    return sOut;
}

inline unsigned char toHex(const unsigned char& x)
{
    return x > 9 ? x + 55: x + 48;
}

int GetFTIDbyName(wxString infile)
{
    int i;
    wxString ext;
    ext = infile.Trim();
    i = ext.Len();
    while (i > 0)
    {
        i--;
        if (((const char *) ext) [i] == '.')
        {
            i = - i;
        }
    }
    if (i >= 0)
    {
        // Any:
        return 0;
    }
    else
    {
        i = - i;
        ext = ext.Mid(i + 1, ext.Len() - i - 1) .MakeLower();
        //printf("infile=%s ",(const char *)infile);printf("ext=%s\n",(const char *)ext);
        // Type Archive
        if (ext == "gz" ||ext == "zip" ||ext == "ace" ||ext == "rar" ||ext == "arj" || ext == "tar")
        {
            return 1;
        }
        // Type Audio
        else if(ext == "mpc" ||ext == "mp4" ||ext == "aac" ||ext == "ape" ||ext == "mp3" || ext == "mp2" ||ext == "wav" ||ext == "au" ||ext == "ogg" || ext == "wma" || ext == "mid")
        {
            return 2;
        }
        // Type Picture
        else if(ext == "jpg" ||ext == "jpeg" ||ext == "bmp" ||ext == "gif" ||ext == "tif" || ext == "png")
        {
            return 3;
        }
        // Type CD/DVD Image
        else if(ext == "ccd" || ext == "sub" || ext == "cue" || ext == "bin" || ext == "iso" || ext == "nrg" || ext == "img" || ext == "bwa" || ext == "bwi" || ext == "bws" || ext == "bwt" || ext == "mds" || ext == "mdf")
        {
            return 4;
        }
        // Type Program
        else if(ext == "exe" || ext == "com")
        {
            return 5;
        }
        // Type Video
        else if(ext == "avi" || ext == "mpg" || ext == "mpeg" || ext == "ram" || ext == "rm" || ext == "asf" || ext == "vob" || ext == "divx" || ext == "vivo" || ext == "ogm" || ext == "mov" || ext == "wmv")
        {
            return 6;
        }
    }
    // Type Any
    return 0;
}

// Returns the Typename, examining the extention of the given filename
wxString GetFiletypeByName(wxString infile)
{
    wxString ext;
    // For what was this ???  PLK
#if 0
    if (infile.ReverseFind('.') == - 1) return GetResString(IDS_SEARCH_ANY);
#endif
    // For what is this ??? PLK
    if (infile.Find('.', TRUE) == - 1) return GetResString(IDS_SEARCH_ANY);
    // ext == extension of the filename (Search Result) PLK
    ext = infile.Right(infile.Length() - infile.Find('.', TRUE)) .MakeLower();
    // Type Audio
    if (ext == ".mpc" || ext == ".mp4" || ext == ".aac" || ext == ".ape" || ext == ".mp3" || ext == ".mp2" || ext == ".wav" || ext == ".au" || ext == ".ogg" || ext == ".wma" || ext == ".mid")
    {
        return GetResString(IDS_SEARCH_AUDIO);
    }
    // Type Picture
    if (ext == ".jpg" || ext == ".jpeg" || ext == ".bmp" || ext == ".gif" || ext == ".tif" || ext == ".png")
    {
        return GetResString(IDS_SEARCH_PICS);
    }
    // Type Video
    if (ext == ".avi" || ext == ".mpg" || ext == ".mpeg" || ext == ".ram" || ext == ".rm" || ext == ".asf" || ext == ".vob" || ext == ".divx" || ext == ".vivo" || ext == ".ogm" || ext == ".mov" || ext == ".wmv")
    {
        return GetResString(IDS_SEARCH_VIDEO);
    }
    // Type Archive
    if (ext == ".gz" || ext == ".zip" || ext == ".ace" || ext == ".rar" || ext == ".tar")
    {
        return GetResString(IDS_SEARCH_ARC);
    }
    // Type Program
    if (ext == ".exe" || ext == ".com")
    {
        return GetResString(IDS_SEARCH_PRG);
    }
    // Type CD/DVD Image
    if (ext == ".ccd" || ext == ".sub" || ext == ".cue" || ext == ".bin" || ext == ".iso" || ext == ".nrg" || ext == ".img" || ext == ".bwa" || ext == ".bwi" || ext == ".bws" || ext == ".bwt" || ext == ".mds" || ext == ".mdf")
    {
        return GetResString(IDS_SEARCH_CDIMG);
    }
    // Type Any
    return GetResString(IDS_SEARCH_ANY);
}

wxString MakeStringEscaped(wxString in)
{
    in.Replace(wxT("&"), wxT("&&"));
    return in;
}

bool Ask4RegFix(bool checkOnly)
{
#if 0
    // check registry if ed2k links is assigned to xmule
    CRegKey regkey;
    regkey.Create(HKEY_CLASSES_ROOT, "ed2k\\shell\\open\\command");
    ULONG maxsize = 500;
    TCHAR rbuffer[500];
    char modbuffer[490];
    char regbuffer[520];
    regkey.QueryStringValue(0, rbuffer, &maxsize);
    ::GetModuleFileName(0, modbuffer, 490);
    sprintf(regbuffer, "\"%s\" \"%%1\"", modbuffer);
    if (strcmp(rbuffer, regbuffer))
    {
        if (checkOnly) return true;
        if (MessageBox(0, GetResString(IDS_ASSIGNED2K), GetResString(IDS_ED2KLINKFIX), MB_ICONQUESTION |MB_YESNO) == IDYES)
        {
            regkey.SetStringValue(0, regbuffer);
            // Added Shrink:
            regkey.Create(HKEY_CLASSES_ROOT, "ed2k\\DefaultIcon");
            regkey.SetStringValue(0, modbuffer);
            regkey.Create(HKEY_CLASSES_ROOT, "ed2k");
            regkey.SetStringValue(0, "URL: ed2k Protocol");
            regkey.SetStringValue("URL Protocol", "");
        }
    }
    regkey.Close();
    return false;
#endif
}

int GetMaxConnections()
{
#if 0
    OSVERSIONINFOEX osvi;
    ZeroMemory( &osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    if (!GetVersionEx((OSVERSIONINFO *) &osvi))
    {
        //if OSVERSIONINFOEX doesn't work, try OSVERSIONINFO
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        if (!GetVersionEx((OSVERSIONINFO *) &osvi))
        //shouldn't ever happen:
        return - 1;
    }
    // Windows NT product family:
    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
    //no limits:
    return - 1;
    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
    {
        // Windows 95 product family
        if (osvi.dwMajorVersion == 4 &&osvi.dwMinorVersion == 0)
        {
            //old school 95
            HKEY hKey;
            DWORD dwValue;
            DWORD dwLength = sizeof(dwValue);
            LONG lResult;
            RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
            0, KEY_QUERY_VALUE, &hKey);
            lResult = RegQueryValueEx(hKey, TEXT("MaxConnections"), NULL, NULL,
            (LPBYTE) &dwValue, &dwLength);
            RegCloseKey(hKey);
            if (lResult != ERROR_SUCCESS || lResult < 1)
            //the default for 95 is 100:
            return 100;
            return dwValue;
        }
        else
        {
            //98 or ME
            HKEY hKey;
            TCHAR szValue[32];
            DWORD dwLength = sizeof(szValue);
            LONG lResult;
            RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
            0, KEY_QUERY_VALUE, &hKey);
            lResult = RegQueryValueEx(hKey, TEXT("MaxConnections"), NULL, NULL,
            (LPBYTE) szValue, &dwLength);
            RegCloseKey(hKey);
            LONG lMaxConnections;
            if (lResult != ERROR_SUCCESS || (lMaxConnections = atoi(szValue)) < 1)
            //the default for 98/ME is 100:
            return 100;
            return lMaxConnections;
        }
    }
    //give the user the benefit of the doubt, most use NT+ anyway:
    return - 1;
#endif
    return - 1;
}

wxString GetRateString(uint16_t rate)
{
    switch (rate)
    {
    case 0:
        return GetResString(IDS_CMT_NOTRATED);
        break;
    case 1:
        return GetResString(IDS_CMT_FAKE);
        break;
    case 2:
        return GetResString(IDS_CMT_POOR);
        break;
    case 3:
        return GetResString(IDS_CMT_GOOD);
        break;
    case 4:
        return GetResString(IDS_CMT_FAIR);
        break;
    case 5:
        return GetResString(IDS_CMT_EXCELLENT);
        break;
    }
    return GetResString(IDS_CMT_NOTRATED);
}

// Returns a BASE32 encoded BYTE array
//
// [In]
//   buffer: Pointer to BYTE array
//   bufLen: Lenght of buffer array
//
// [Return]
//   wxString object with BASE32 encoded BYTE array
wxString EncodeBase32(const unsigned char *buffer, unsigned int bufLen)
{
    wxString Base32Buff;
    unsigned int i, index;
    unsigned char word;

    for (i = 0, index = 0 ; i < bufLen ;)
    {
        // Is the current word going to span a BYTE boundary?
        if (index > 3)
        {
            word = (buffer[i] & (0xFF >> index));
            index = (index + 5) % 8;
            word <<= index;

            if (i < bufLen - 1)
            {
                word |= buffer[i + 1] >> (8 - index);
            }

            i++;
        }
        else
        {
            word = (buffer[i] >> (8 - (index + 5))) &0x1F;
            index = (index + 5) % 8;
            if (index == 0)
            {
                i++;
            }
        }

        Base32Buff += (char)base32Chars[word];
    }

    return Base32Buff;
}

// Returns a BASE16 encoded BYTE array
//
// [In]
//   buffer: Pointer to BYTE array
//   bufLen: Lenght of buffer array
//
// [Return]
//   wxString object with BASE16 encoded BYTE array
wxString EncodeBase16(const unsigned char *buffer, unsigned int bufLen)
{
    wxString Base16Buff;

    for (unsigned int i = 0; i < bufLen; ++i)
    {
        Base16Buff += base16Chars[buffer[i] >> 4];
        Base16Buff += base16Chars[buffer[i] &0xf];
    }

    return Base16Buff;
}

// Decodes a BASE16 string into a BYTE array
//
// [In]
//   base16Buffer: String containing BASE16
//   base16BufLen: Lenght BASE16 coded string's length
//
// [Out]
//   buffer: BYTE array containing decoded string
void DecodeBase16(const char *base16Buffer, unsigned int base16BufLen, BYTE *buffer)
{
    memset(buffer, 0, DecodeLengthBase16(base16BufLen));
    for (unsigned int i = 0 ; i < base16BufLen ; i++)
    {
        int lookup = toupper(base16Buffer[i]) - '0';
        // Check to make sure that the given word falls inside a valid range
        BYTE word = 0;
        if (lookup < 0 || lookup >= BASE16_LOOKUP_MAX)
        word = 0xFF;
        else
        word = base16Lookup[lookup][1];
        if (i % 2 == 0)
        {
            buffer[i/2] = word << 4;
        }
        else
        {
            buffer[ (i - 1) /2] |= word;
        }
    }
}

// Calculates length to decode from BASE16
//
// [In]
//   base16Length: Actual length of BASE16 string
//
// [Return]
//   New length of BYTE array decoded
int DecodeLengthBase16(int base16Length)
{
    return base16Length / 2;
}

#if 0
void UpdateURLMenu(CMenu &menu, int &counter)
{
    counter = 0;
    theApp.webservices.RemoveAll();
    wxString name, url, sbuffer;
    char buffer[1024];
    int lenBuf = 1024;
    FILE *readFile = fopen(wxString(theApp.glob_prefs->GetAppDir()) + "webservices.dat", "r");
    if (readFile != NULL)
    {
        while (!feof(readFile))
        {
            if (fgets(buffer, lenBuf, readFile) == 0) break;
            sbuffer = buffer;
            // ignore comments & too short lines
            if (sbuffer.GetAt(0) == '#' || sbuffer.GetAt(0) == '/' || sbuffer.GetLength() < 5)
            continue;
            int pos = sbuffer.Find(',');
            if (pos > 0)
            {
                counter++;
                menu.AppendMenu(MF_STRING, MP_WEBURL + (counter - 1), sbuffer.Left(pos) .Trim());
                theApp.webservices.Add(sbuffer.Right(sbuffer.GetLength() - pos - 1) .Trim());
            }
        }
        fclose(readFile);
    }
}

#endif

void RunURL(CAbstractFile *file, wxString urlpattern)
{
}

wxString GetCatTitle(int catid)
{
    switch (catid)
    {
        case 0: return GetResString(IDS_ALL);
        case 1: return GetResString(IDS_ALLOTHERS);
        case 2: return GetResString(IDS_STATUS_NOTCOMPLETED);
        case 3: return GetResString(IDS_DL_TRANSFCOMPL);
        case 4: return GetResString(IDS_WAITING);
        case 5: return GetResString(IDS_DOWNLOADING);
        case 6: return GetResString(IDS_ERRORLIKE);
        case 7: return GetResString(IDS_PAUSED);
        case 8: return GetResString(IDS_STOPPED);
        case 9: return GetResString(IDS_VIDEO);
        case 10: return GetResString(IDS_AUDIO);
        case 11: return GetResString(IDS_SEARCH_ARC);
        case 12: return GetResString(IDS_SEARCH_CDIMG);
        case 13: return GetResString(IDS_SEARCH_PICS);
        case 14: return GetResString(IDS_TEXT);
    }
    return "?";
}

bool CheckShowItemInGivenCat(CPartFile *file, int inCategory)
{
    // easy normal cases
    bool IsInCat;
    bool IsNotFiltered = true;
    IsInCat = ((inCategory == 0) || (inCategory > 0 &&inCategory == file->GetCategory()));
    if (theApp.glob_prefs->GetAllcatType() > 0)
    switch (theApp.glob_prefs->GetAllcatType())
    {
    case 1:
        {
            IsNotFiltered = ((file->GetCategory() == 0) || (inCategory > 0));
            break;
        }
    case 2:
        {
            IsNotFiltered = (file->IsPartFile());
            break;
        }
    case 3:
        {
            IsNotFiltered = (!file->IsPartFile());
            break;
        }
    case 4:
        {
            IsNotFiltered = ((file->GetStatus() == PS_READY || file->GetStatus() == PS_EMPTY) &&file->GetTransferingSrcCount() == 0);
            break;
        }
    case 5:
        {
            IsNotFiltered = ((file->GetStatus() == PS_READY || file->GetStatus() == PS_EMPTY) &&file->GetTransferingSrcCount() > 0);
            break;
        }
    case 6:
        {
            IsNotFiltered = (file->GetStatus() == PS_ERROR);
            break;
        }
    case 7:
        {
            IsNotFiltered = ((file->GetStatus() == PS_PAUSED) && (!file->IsStopped()));
            break;
        }
    case 8:
        {
            IsNotFiltered = file->IsStopped();
            break;
        }
    case 9:
        {
            IsNotFiltered = file->IsMovie();
            break;
        }
    case 10:
        {
            IsNotFiltered = file->IsSound();
            break;
        }
    case 11:
        {
            IsNotFiltered = file->IsArchive();
            break;
        }
    case 12:
        {
            IsNotFiltered = file->IsCDImage();
            break;
        }
    case 13:
        {
            IsNotFiltered = file->IsImage();
            break;
        }
    case 14:
        {
            IsNotFiltered = file->IsText();
            break;
        }
    }
    return(IsNotFiltered &&IsInCat);
}

#ifdef __FreeBSD__
long long atoll(char *s)
{
    return strtoll(s, (char **) NULL, 10);
}

#endif /* __FreeBSD__ */

void MakeFoldername(wxString& path)
{
    int length = path.length();
    if (length <= 0)
    {
        return;
    }
    
    if (path.Right(1) == '/')
    {
        path = path.Left(length - 1);
    }
}

void HexDump(const void *buffer, unsigned long buflen)
{
#if defined(__DEBUG__)
    const uint8_t *cbuf = (const uint8_t *) buffer;
    for (unsigned long ofs = 0 ; ofs < buflen ; /* no increment here */
    )
    {
        printf("%08lx", ofs);
        for (unsigned long i = 0 ; (i < 8) && (ofs < buflen) ; i++, ofs++)
        {
            printf(" %02x", (int) cbuf[ofs]);
        }
        printf("\n");
    }
#endif
}

bool BackupFile(const wxString &filename, const wxString &appendix)
{
    wxRemoveFile(filename + appendix);
    if (!wxRenameFile(filename, filename + appendix))
    {
        if (!SafeCopyFile(filename, filename + appendix))
        {
            printf("info: Could not create backup of '%s'\n",
            filename.c_str());
            return false;
        }
        else if(!wxRemoveFile(filename))
        {
            printf("info: Could not delete original '%s' after creating backup\n", filename.c_str());
        }
    }
    return true;
}

// This function is a modified form of wxWindows-2.4.2's wxCopyFile()
// It's primary purpose is to ignore chmod()s on FAT32 partitions
bool SafeCopyFile(const wxString &file1, const wxString &file2)
{
    wxFile fileIn(file1, wxFile::read);
    if (!fileIn.IsOpened())
    {
        //		return FALSE;// for copying it the file could be open too!!
    }
    wxFile fileOut(file2, wxFile::write);
    char buf[4096];
    size_t count;
    while (true)
    {
        count = fileIn.Read(buf, WXSIZEOF(buf));
        if (fileIn.Error())
        {
            return FALSE;
        }
        if (!count)
        {
            break;
        }
        if (fileOut.Write(buf, count) < count)
        {
            return FALSE;
        }
    }
    if (!fileIn.Close() || !fileOut.Close())
    {
        return FALSE;
    }
    return TRUE;
}

