Logo Search packages:      
Sourcecode: zinf version File versions  Download package

utility.cpp

/*____________________________________________________________________________
    
    Zinf - Zinf Is Not FreeA*p (The Free MP3 Player)

    Portions Copyright (C) 1999 EMusic.com

    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.
    
    $Id: utility.cpp,v 1.21 2004/02/09 23:18:33 enxrah Exp $
____________________________________________________________________________*/

// The debugger can't handle symbols more than 255 characters long.
// STL often creates symbols longer than that.
// When symbols are longer than 255 characters, the warning is disabled.
#include "config.h"
#ifdef WIN32
#pragma warning(disable:4786) 
#endif

#include <assert.h>
#include <time.h>
#include <ctype.h>
#include <stdio.h>

#include <string>
#include <vector>
#include <iostream>

using namespace std;

#include <sys/types.h>
#include <sys/stat.h>

#ifdef HAVE_GLIB
#include <glib.h>
#endif

#ifdef WIN32
#include <windows.h>
#include <direct.h>
#include <shlobj.h>
#define MKDIR(z) mkdir(z)
#else
#include "win32impl.h"
#include "browser.h"
#include <unistd.h>
#include <wordexp.h>
#define MKDIR(z) mkdir(z, 0755)
#define _stat stat
#ifndef _S_IFDIR
#define _S_IFDIR S_IFDIR 
#endif
#endif

#ifdef __QNX__
#include <strings.h>
#endif

#include "path_max.h"

#include "facontext.h"
#include "utility.h"
#include "errors.h"
#include "properties.h"

void CreateDirectoryPath(const char* path)
{
    char* temp = new char[strlen(path) + 1];

    // make a copy we can destroy
    strcpy(temp, path);

    char* cp = temp;
    char* end;

    do
    {
        end = strchr(cp, DIR_MARKER);

        if(end)
            *end = 0x00;

        MKDIR(temp);

        if(end)
        {
            *end = DIR_MARKER;
            cp = end + 1;
        }

    }while(end);

    delete [] temp;
}

bool IsRelative(const char* path)
{
    bool result = false;

    assert(path);

    if(path)
    {
        result = (  path[0] != DIR_MARKER );

#ifdef WIN32
       if(result && strlen(path) > 2)
       {
            result = !(path[1] == ':' && path[2] == '\\');
       }
#endif
    }

    return result;
}

void ResolvePath(string  &path)
{
    string path2 = "";
    int rep;
    string dotslash = ".";
    string dotdotslash = "..";
    string slashslash = "";
    slashslash += DIR_MARKER;
    slashslash += DIR_MARKER;
    dotslash += DIR_MARKER;
    dotdotslash += DIR_MARKER;

    if(IsRelative(path.c_str())) {
        // need to get cwd and resolve this path in
        // relation to it.
        char* cwd = NULL;
      // only make cwd as big as necessary. but only does max 4096 in gnu
        // KGK I don't think this is portable and should be 
        // KGK set back to the old method! see man getcwd

        cwd = getcwd(NULL, 0);
      
        string fullPath;
      fullPath = cwd;
      fullPath += DIR_MARKER_STR;
      fullPath += path.c_str();
      path = fullPath;
      
      // getcwd allocates space via malloc.
        if(cwd) free(cwd);
    }

    // remove multiple separators between elements
    // and make sure end does not contain separator
    // unless it is the root directory and remove
    // relative indicators in the *path    

#ifdef WIN32
    // network path, skip initial double slash
    if(path.c_str()[0] == '\\' && path.c_str()[1] == '\\'){
      path2 = "\\\\";
      path = (path.c_str()+2);
    }
#endif 
    while((rep = path.find(dotdotslash.c_str(),0,dotdotslash.length())) >= 0){
      for(int rep2=rep-2;rep2>=0;rep2--){
            if(path.c_str()[rep2] == DIR_MARKER){
            path.erase(rep2+1,(rep+2)-(rep2));
                break;
            }
      }
    }
    while((rep = path.find(dotslash.c_str(),0,dotslash.length())) >= 0){
          path.erase(rep,2);
    }
    while((rep = path.find(slashslash.c_str(),0,slashslash.length())) >= 0){
      path.erase(rep,1);
      
    }
    path2 += path;
    path = "";
    path = path2;
}

void RFC822GMTTimeString(struct tm* time, char buf[32])
{
    const char* day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    const char* month[] = {"Jan", "Feb",  "Mar", "Apr", "May", "Jun",  
                           "Jul", "Aug", "Sep", "Oct",  "Nov", "Dec"};

    // Example: Sun, 06 Nov 1994 08:49:37 GMT
    const char* k822Format = "%s, %02d %s %4d %02d:%02d:%02d GMT";

    sprintf(buf, k822Format, day[time->tm_wday],
                             time->tm_mday,
                             month[time->tm_mon],
                             time->tm_year + 1900,
                             time->tm_hour,
                             time->tm_min,
                             time->tm_sec);
}

char *strdup_new(const char *str)
{
    char *n;

    n = new char[strlen(str) + 1];
    strcpy(n, str);
 
    return n;
}

#ifdef WIN32

char *ZinfDir(Preferences *pref)
{
    string path;
    char *s;

    pref->GetPrefString(kInstallDirPref, &path);

    s = new char[path.length() + 1];
    strcpy(s, path.c_str());

    return s;
}

#elif defined(__BEOS__)

#include <be/storage/FindDirectory.h>
#include <be/storage/Path.h>

char *ZinfDir(Preferences *pref)
{
    BPath prefPath;
    assert(find_directory(B_USER_SETTINGS_DIRECTORY, &prefPath) == B_NO_ERROR);
    prefPath.Append( "zinf" );

    const char *path = prefPath.Path();
    char *s = new char[strlen(path) + 1];
    strcpy(s, path);

    return s;
}

#else

#include <stdlib.h>

char *ZinfDir(Preferences *prefs)
{
    char *homeDir = getenv("HOME");
    const char *fadir = "/."BRANDING_APP_NAME;
    char *s;

    if (!homeDir) {
        s = new char[2];
        strcpy(s, "/");
        return s;
    }

    s = new char[strlen(homeDir) + strlen(fadir) + 1];
    strcpy(s, homeDir);
    strcat(s, fadir);

    return s;
}
#endif

Error FilePathToURL(const char* path, string &url)
{
    Error result = kError_InvalidParam;
    string path2 ="";
    assert(path);
    url = "";
#ifdef HAVE_GLIB
    GError *error = NULL;
    gchar* tmp=g_filename_to_uri(path,NULL,&error);
    if(!error){
      result=kError_NoErr;
      url=tmp;
    }
    g_clear_error (&error);
    g_free(tmp); 
#else
    if(path)
    {
        path2 = path;
        ResolvePath(path2);
#ifdef WIN32
        int indx;
        while((indx = path2.rfind('\\'))>=0){   
            path2.replace(indx,1,1,'/');
        }
        if(path2.c_str()[1] == ':')
            path2.replace(1,1,1,'|');
#endif
        url = "file://";
        url += path2;
        result = kError_NoErr;
    }
#endif
    return result;
}

Error URLToFilePath(const char* url, string &path)
{
    Error result = kError_InvalidParam;
    assert(url);
    path = "";
#ifdef HAVE_GLIB
    GError *error = NULL;
    gchar* tmp=g_filename_from_uri(url,NULL,&error);
    if(!error){
      result=kError_NoErr;
      path=tmp;
      ResolvePath(path);
    }
    g_clear_error (&error);
    g_free(tmp);
#else
    if(url && !strncasecmp(url, "file:", 5))
    {
        result = kError_BufferTooSmall;
        string url2 = url;
        uint indx;
#ifdef WIN32
        if(url2.c_str()[1] == '|')
            url2.replace(1,1,1,':');
        while((indx = url2.rfind('/'))>=7){     
            url2.replace(indx,1,1,'\\');
        }

#endif //WIN32
      while((indx = url2.rfind('%'))!=string::npos){
        cout<<"escaped string\n";
        char p0, p1;
        p0=url2.at(indx+1);
        p1=url2.at(indx+2);
        if(isdigit(p0))
          p0-='0';
        else
          p0=tolower(p0)-'a';
        if(isdigit(p1))
          p1-='0';
        else
          p1=tolower(p0)-'a';
        url2.at(indx)=(16*p0+p1);
        url2.erase(indx+1,2);
      }
        url2.erase(0,5);
      while (url && !strncasecmp(url2.c_str(), "//", 2))
        url2.erase(0,1);
        path = url2;
        ResolvePath(path);
        result = kError_NoErr; 
    }
#endif //HAVE_GLIB
    return result;
}


Error FilePathToURL(const string& path, string& url)
{
    Error result = FilePathToURL (path.c_str(), url);
    return result;
}


Error URLToFilePath (const string&url, string&path)
{
    Error result = URLToFilePath (url.c_str(), path);
    return result;
}



void ToUpper(char *s)
{
    char *p;
    
    for(p = s; *p != '\0'; p++)
       *p = toupper(*p);
}       

void ToLower(char *s)
{
    char *p;
    
    for(p = s; *p != '\0'; p++)
       *p = tolower(*p);
}      

void ReplaceSpaces(string &in, string &encoded)
{
    encoded = "";
    
    for (unsigned int i = 0; i < in.size(); i++)
    {
        if (in[i] == ' ')
            encoded += "%20";
        else if ((unsigned char)in[i] > 127)
        {
            char enc[10];
            sprintf(enc, "%%%02X", in[i] & 0xFF);
            enc[3] = 0;
            encoded += enc;
        }
        else
            encoded += in[i];
    }
}

#ifdef WIN32
#elif __BEOS__

#include <be/app/Roster.h>
#include <be/be_apps/NetPositive/NetPositive.h>

void LaunchBrowser(const char* url)
{
    status_t err;

    BMessenger netpositive(B_NETPOSITIVE_APP_SIGNATURE, -1, &err);
    if (err == B_OK)
    {
        BMessage msg(B_NETPOSITIVE_OPEN_URL);
        msg.AddString("be:url", url);
        err = netpositive.SendMessage(&msg);
        if (err < B_OK)
        {
            printf(_("error sending msg to netpositive: %s\n"), strerror(err));
        }
    }
    else
    {
        const char *browser = "NetPositive";
        char *command = new char[strlen(browser) + strlen(url) + 10];
        sprintf(command, "%s \"%s\" &", browser, url);
        system(command);
        delete[] command;
    }
}

#else
void LaunchBrowser(const char* url)
{
    if (fork() > 0) 
    {
       return;
    }
    launch_browser(url, eBrowserNetscape);
}

void LaunchBrowser(Preferences*prefs, const string& url)
{
  string browser; 
  prefs->GetPrefString (kBrowserPref, browser);
  
    if (fork() > 0) 
    {
       return;
    }
    launch_browser(url, browser);
}
#endif


void FindMusicFiles(const char* rootPath, 
                    vector<string>& urls, 
                    vector<string>& queries)
{
    HANDLE findFileHandle = NULL;
    WIN32_FIND_DATA findData;
    string findPath;
    string::size_type pos = string::npos;

    vector<string>::iterator query = queries.begin();

    // first run each query on this directory
    for(;query != queries.end(); query++)
    {
        findPath = rootPath;
        findPath += DIR_MARKER_STR;
        pos = findPath.size();
        findPath += *query;

        findFileHandle = FindFirstFile((char *)findPath.c_str(), &findData);

        if(findFileHandle != INVALID_HANDLE_VALUE)
        {
            do
            {
                findPath.replace(pos, 
                                 findPath.size() - pos, 
                                 findData.cFileName);
                
            string url = "";
                FilePathToURL(findPath.c_str(), url);

                urls.push_back(url.c_str());

            }while(FindNextFile(findFileHandle, &findData));

            FindClose(findFileHandle);
        }
    }

    // next find all the directories in this directory and
    // and run the queries on them
#ifdef WIN32
    findPath.replace(pos, 
                     findPath.size() - pos, 
                     "*.*");
#else
    findPath.replace(pos,
                     findPath.size() - pos,
                     "*");
#endif

    findFileHandle = FindFirstFile((char *)findPath.c_str(), &findData);

    if(findFileHandle != INVALID_HANDLE_VALUE)
    {
        do
        {
            if(strcmp(findData.cFileName, ".") && 
               strcmp(findData.cFileName, ".."))
            {
                findPath.replace(pos, 
                                 findPath.size() - pos, 
                                 findData.cFileName);
                struct stat st;

                stat(findPath.c_str(), &st);

                if(st.st_mode & _S_IFDIR)
                {
                    FindMusicFiles(findPath.c_str(),
                                   urls,
                                   queries);
                }
            }

        }while(FindNextFile(findFileHandle, &findData));

        FindClose(findFileHandle);
    }
}

#ifdef WIN32
bool ResolveLink(string& path)
{
    bool result = false;
    HRESULT hres = NULL;

    hres = CoInitialize(NULL);

    if(SUCCEEDED(hres))
    {
        IShellLink* psl = NULL;

        // Get a pointer to the IShellLink interface
        hres = CoCreateInstance(CLSID_ShellLink, 
                                NULL, 
                                CLSCTX_INPROC_SERVER, 
                                IID_IShellLink, 
                                (void**)&psl);

        if(SUCCEEDED(hres))
        {
            IPersistFile* ppf;

            // Get a pointer to the IPersistFile interface
            hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);

            if(SUCCEEDED(hres))
            {
                WORD wsz[MAX_PATH];

                // Ensure string is UNICODE
                MultiByteToWideChar(CP_ACP, 
                                    0, 
                                    path.c_str(), 
                                    -1, 
                                    wsz, 
                                    MAX_PATH);

                // Load Shortcut
                hres = ppf->Load(wsz, STGM_READ);

                if(SUCCEEDED(hres))
                {
                    // Resolve the link
                    hres = psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI);
            
                    if(SUCCEEDED(hres))
                    {
                        WIN32_FIND_DATA wfd;
                        char buf[MAX_PATH];

                        // Resolve the link
                        hres = psl->GetPath(buf,sizeof(buf),&wfd, 0);

                        if(SUCCEEDED(hres))
                        {
                            path = buf;
                            result = true;
                        }
                    }
                }

                // Release the IPersist Interface
                ppf->Release();
            }
    
            // Release the IShellLink Interface
            psl->Release();
        }

        CoUninitialize(); 
    }

    return result;
}

#endif

#ifndef WIN32

const unsigned iCopyBufferSize = 8192;

bool CopyFile(const char *pExistingFileName, 
              const char *pNewFileName,      // name of new file
              bool bFailIfExists)      // operation if file exists
{
    FILE  *fpDest, *fpSrc;
    char   szBuffer[iCopyBufferSize];
    unsigned iRet;

    if (bFailIfExists && !access(pNewFileName, 0))
        return false;

    fpDest = fopen(pNewFileName, "wb");
    if (fpDest == NULL)
        return false;

    fpSrc = fopen(pExistingFileName, "rb");
    if (fpSrc == NULL)
        return false;

    for(;;)
    {
        iRet = fread(szBuffer, 1, iCopyBufferSize, fpSrc);
        if ((int)iRet < 0)
        {
            fclose(fpDest);
            fclose(fpSrc);
            return false;
        }

        if (fwrite(szBuffer, 1, iRet, fpDest) != iRet)
        {
            fclose(fpDest);
            fclose(fpSrc);
            return false;
        }
        if (iRet != iCopyBufferSize)
           break; 
    }

    fclose(fpDest);
    fclose(fpSrc);

    return true;
}

#endif

string FindFile(string oPath)
{
    char *findpath, *path, *filename, *slash;
    string retvalue = oPath;

    path = new char[_MAX_PATH];
    strcpy(path, oPath.c_str());

    slash = strrchr(path, DIR_MARKER);

    if (!slash)
        return retvalue;

    slash++;
    filename = new char[strlen(slash) + 1];
    strcpy(filename, slash);
    *slash = '\0';

    findpath = new char[strlen(path) + 1];
    strcpy(findpath, path);

    strcat(findpath, "*");
#ifdef WIN32
    strcat(findpath, ".*");
#endif

    WIN32_FIND_DATA find;
    HANDLE handle;

    handle = FindFirstFile(findpath, &find);
    if (handle != INVALID_HANDLE_VALUE) {
        do {
            if (!strcasecmp(find.cFileName, filename)) {
                retvalue = string(path) + string(find.cFileName);
                break;
            }
        }
        while (FindNextFile(handle, &find));
        FindClose(handle);
    }

    delete [] findpath;
    delete [] path;
    delete [] filename;

    return retvalue;
}

bool ShowHelp(FAContext *m_context, const char *helpurl)
{
    string  oHelpFile;
    string dir;

    m_context->prefs->GetPrefString(kInstallDirPref, dir);
    oHelpFile = dir;

    oHelpFile += DIR_MARKER_STR;
#ifdef WIN32
    oHelpFile += "help";
    oHelpFile += DIR_MARKER_STR;
#endif
#ifdef unix
    oHelpFile += "../share/"BRANDING_APP_NAME"/help/";
#endif
    oHelpFile += helpurl;

    struct _stat   st;
    if (_stat(oHelpFile.c_str(), &st) != 0 || st.st_mode & S_IFREG == 0)
    {
         return false;
    }

    FilePathToURL(oHelpFile.c_str(), dir);

#ifdef HAVE_GTK 
    LaunchBrowser(dir.c_str());
#endif
#ifdef WIN32

    Int32PropValue *pProp;
    HWND            hWnd;
    if (IsError(m_context->props->GetProperty("MainWindow", 
                (PropValue **)&pProp)))
       hWnd = NULL;
    else
       hWnd = (HWND)pProp->GetInt32();

    ShellExecute(hWnd, "open", dir.c_str(), NULL, NULL, SW_SHOWNORMAL);
#endif
    return true;
} 

bool GetProxySettings(FAContext *context, string &server, unsigned short &port)
{
    bool   useProxy;
    int32_t  numFields;
    string proxyname;
    char hostname[512];

    context->prefs->GetPrefBoolean(kUseProxyPref, &useProxy);
    context->prefs->GetPrefString(kProxyHostPref, &proxyname);

    if(useProxy)
    {
        numFields = sscanf(proxyname.c_str(),
                           "http://%[^:/]:%hu", hostname, &port);
        if (numFields > 0)
        {
            server = (string)hostname;
            if (numFields == 1)
               port = 80;

            return true;
        }
    }

    return false;
}


vector<string> 
SplitPath(const string& path)
{
    vector<string> dirs;

    //cerr << "LibraryPath is " << path << endl;
    string::size_type start = 0;
    string::size_type sep = 0;
    string subpath;

    for (;sep != string::npos;){
        sep = path.find(':', start);

        if (sep == string::npos)
            subpath = path.substr (start);
        else 
            subpath = path.substr(start, sep-start);

        if (subpath.size()) {
#ifndef WIN32
            wordexp_t result;
            if (wordexp(subpath.c_str(), &result, 0) ==0){
                //cerr << "Expanded " << dir << " in ";
                subpath = result.we_wordv[0];
                //cerr << dir << endl;
            }
            wordfree(&result);
#endif

            dirs.push_back(subpath);
        }
        start = sep+1;
    }
    return dirs;
}



/* arch-tag: d001c99d-4382-4b87-92f5-88e445c789fe
   (do not change this comment) */

Generated by  Doxygen 1.6.0   Back to index