//============================================================================= // // File : kvi_app_fs.cpp // Creation date : Thu Dec 24 1998 04:05:26 by Szymon Stefanek // // This file is part of the Kvirc irc client distribution // Copyright (C) 1998-2006 Szymon Stefanek (pragma at kvirc dot 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 opinion) 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #define __KVIRC__ #include "kvi_debug.h" #include "kvi_app.h" #include "kvi_locale.h" #include "kvi_fileutils.h" #include "kvi_mediatype.h" #include "kvi_env.h" #include "kvi_time.h" #include "kvi_options.h" #include "kvi_defaults.h" #include "kvi_iconmanager.h" #include #include #include #include "config.h" extern KviMediaManager * g_pMediaManager; //============ getGlobalKvircDirectory ================// void KviApp::getGlobalKvircDirectory(TQString &szData,KvircSubdir dir,const TQString &appendFile) { szData=m_szGlobalKvircDir; KviTQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR); switch(dir) { case None : break; case Pics : szData.append("pics"); break; // Local hack for Debian case Modules : case Plugins : szData = TDE_LIBDIR "/kvirc/" KVI_VERSION_BRANCH "/modules"; break; case EasyPlugins : szData.append("easyplugins"); break; case ConfigPlugins : KviTQString::appendFormatted(szData,"config%smodules",KVI_PATH_SEPARATOR); break; case ConfigScripts : KviTQString::appendFormatted(szData,"config%sscripts",KVI_PATH_SEPARATOR); break; case Help : szData.append("help"); { // Localized help TQString tmp(KviLocale::localeName().ptr()); tmp.prepend(KVI_PATH_SEPARATOR_CHAR); tmp.prepend(szData); if(KviFileUtils::directoryExists(tmp))szData = tmp; else { tmp = szData; KviTQString::appendFormatted(tmp,"%sen",KVI_PATH_SEPARATOR); if(KviFileUtils::directoryExists(tmp))szData = tmp; } } break; case HelpEN : KviTQString::appendFormatted(szData,"help%sen",KVI_PATH_SEPARATOR); break; case HelpNoIntl : szData.append("help"); break; case Log : debug("WARNING Global log directory requested!"); break; case Incoming : debug("WARNING Global incoming directory requested!"); break; case Trash : debug("WARNING Global trash directory requested!"); break; case Config : szData.append("config"); break; case Audio : szData.append("audio"); break; case Scripts : szData.append("scripts"); break; case MsgColors : szData.append("msgcolors"); break; case Charmaps : szData.append("charmaps"); break; case Avatars : szData.append("avatars"); break; case DefScript : szData.append("defscript"); break; case License : szData.append("license"); break; case Filters : szData.append("filters"); break; case Locale : szData.append("locale"); break; case Tmp : debug("WARNING Global tmp directory requested!"); break; case Themes : szData.append("themes"); break; case Classes : szData.append("classes"); break; case SmallIcons : szData.append("pics"KVI_PATH_SEPARATOR KVI_SMALLICONS_SUBDIRECTORY); break; } if(!appendFile.isEmpty()) { KviTQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR); szData.append(appendFile); } KviFileUtils::adjustFilePath(szData); } void KviApp::getLocalKvircDirectory(TQString &szData,KvircSubdir dir,const TQString & appendFile,bool bCreateIfNeeded) { szData=m_szLocalKvircDir; KviTQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR); switch(dir) { case None : break; case Pics : szData.append("pics"); break; case EasyPlugins : szData.append("easyplugins"); break; case Config : szData.append("config"); break; case ConfigPlugins : szData.append("config"KVI_PATH_SEPARATOR"modules"); break; case ConfigScripts : szData.append("config"KVI_PATH_SEPARATOR"scripts"); break; case Log : szData.append("log"); break; case Incoming : szData = KVI_OPTION_STRING(KviOption_stringIncomingPath); // we should take special care here // the user is likely to mess the path behind our back // try to recover from most common problems while(KviTQString::lastCharIs(szData,KVI_PATH_SEPARATOR_CHAR)) szData = szData.remove(szData.length()-1,1); if(szData.isEmpty()) { // unset ? KVI_OPTION_STRING(KviOption_stringIncomingPath) = TQDir::homeDirPath(); if(!KVI_OPTION_STRING(KviOption_stringIncomingPath).endsWith(TQString(TQChar(KVI_PATH_SEPARATOR_CHAR)))) KVI_OPTION_STRING(KviOption_stringIncomingPath).append(KVI_PATH_SEPARATOR_CHAR); KVI_OPTION_STRING(KviOption_stringIncomingPath).append(KVI_DEFAULT_INCOMING_SUBDIRECTORY_NAME); } break; case Help : szData.append("help"); { // Localized help TQString tmp = KviLocale::localeName().ptr(); tmp.prepend(KVI_PATH_SEPARATOR_CHAR); tmp.prepend(szData); if(KviFileUtils::directoryExists(tmp))szData = tmp; else { tmp = szData; tmp.append(KVI_PATH_SEPARATOR"en"); if(KviFileUtils::directoryExists(tmp))szData = tmp; } } break; case HelpEN : szData.append("help"KVI_PATH_SEPARATOR"en"); break; case HelpNoIntl : szData.append("help"); break; case Audio : szData.append("audio"); break; case Scripts : szData.append("scripts"); break; case Modules : case Plugins : szData.append("modules"); break; case Trash : szData.append("trash"); break; case MsgColors : szData.append("msgcolors"); break; case Charmaps : szData.append("charmaps"); break; case Avatars : szData.append("avatars"); break; case License : szData.append("license"); break; case Filters : szData.append("filters"); break; case Tmp : szData.append("tmp"); break; case Locale : szData.append("locale"); break; case Themes : szData.append("themes"); break; case DefScript : szData.append("defscript"); /* should never happen! */ break; case Classes : szData.append("classes"); break; case SmallIcons : szData.append("pics"KVI_PATH_SEPARATOR KVI_SMALLICONS_SUBDIRECTORY); break; } if(bCreateIfNeeded)KviFileUtils::makeDir(szData); if(!appendFile.isEmpty()) { KviTQString::ensureLastCharIs(szData,KVI_PATH_SEPARATOR_CHAR); szData.append(appendFile); } KviFileUtils::adjustFilePath(szData); } void KviApp::getGlobalKvircDirectory(KviStr &szData,KvircSubdir dir,const TQString &appendFile) { TQString szBuffer = szData.ptr(); getGlobalKvircDirectory(szBuffer,dir,appendFile); szData=szBuffer; } //=============== getLocalKvircDirectory ================// void KviApp::getLocalKvircDirectory(KviStr &szData,KvircSubdir dir,const TQString &appendFile,bool bCreateIfNeeded) { TQString szBuffer = szData.ptr(); getLocalKvircDirectory(szBuffer,dir,appendFile,bCreateIfNeeded); szData=szBuffer; } void KviApp::getTmpFileName(TQString &szBuffer,const TQString &szEndingFileName) { TQString tmp; getLocalKvircDirectory(tmp,Tmp); KviTQString::ensureLastCharIs(tmp,KVI_PATH_SEPARATOR_CHAR); struct timeval tmv; kvi_gettimeofday(&tmv,0); TQString szFileName = szEndingFileName.isNull() ? TQString("file.tmp") : szEndingFileName; do { szBuffer = tmp; KviTQString::appendFormatted(szBuffer,"kvirc_%d_%Q",tmv.tv_usec,&szFileName); tmv.tv_usec++; } while(KviFileUtils::fileExists(szBuffer)); } //====================== trashFile ====================// // // Moves a file to the local trash directory // bool KviApp::trashFile(const char *filename) { // Exists ? TQFileInfo fi = TQFileInfo(TQString::fromUtf8(filename)); if( !fi.exists() ) return false; // nothing to trash // Build the filename KviStr lastPart = filename; lastPart.cutToLast(KVI_PATH_SEPARATOR_CHAR); // need only the filename lastPart.append(".bak_"); TQDateTime tm(TQDateTime::currentDateTime()); lastPart.append(tm.toString()); lastPart.replaceAll(' ',"_"); // Ok...have lastPart.bak_Dec_11_31_1999 // Find the thrash directory (make it if necessary) KviStr trashFile; getLocalKvircDirectory(trashFile,Trash,lastPart.ptr(),true); // Check if a such file already exists fi.setFile(trashFile.ptr()); while(fi.exists()) { trashFile.append(".rnm"); fi.setFile(trashFile.ptr()); } // rename the file return KviFileUtils::renameFile(filename,trashFile.ptr()); } void KviApp::completeDirectory(const TQString &word,KviPointerList * matches) { TQString szDir = word; TQString szFile = word; KviTQString::cutToLast(szFile,KVI_PATH_SEPARATOR_CHAR); KviTQString::cutFromLast(szDir,KVI_PATH_SEPARATOR_CHAR); KviFileUtils::adjustFilePath(szDir); KviTQString::ensureLastCharIs(szDir,KVI_PATH_SEPARATOR_CHAR); TQDir d(szDir); // FIXME: maybe check timestamps ? (old modules) TQStringList sl = d.entryList(TQDir::Dirs); TQStringList::Iterator it; for(it = sl.begin();it != sl.end();++it) { TQString * t = new TQString(*it); if(KviTQString::equalCS(*t,".") || KviTQString::equalCS(*t,"..")) { delete t; } else { #ifdef COMPILE_ON_WINDOWS if(KviTQString::equalCIN(szFile,*t,szFile.length())) #else //!COMPILE_ON_WINDOWS if(KviTQString::equalCSN(szFile,*t,szFile.length())) #endif //COMPILE_ON_WINDOWS { t->prepend(szDir); t->append(KVI_PATH_SEPARATOR_CHAR); matches->append(t); } else { delete t; } } } sl = d.entryList(TQDir::Files); for(it = sl.begin();it != sl.end();++it) { TQString * t = new TQString(*it); #ifdef COMPILE_ON_WINDOWS if(KviTQString::equalCIN(szFile,*t,szFile.length())) #else //!COMPILE_ON_WINDOWS if(KviTQString::equalCSN(szFile,*t,szFile.length())) #endif //COMPILE_ON_WINDOWS { t->prepend(szDir); matches->append(t); } else { delete t; } } } //============= getChannelDumpLogFileName ==============// // // Returns a valid filename for the channel dump log // void KviApp::getChannelDumpLogFileName(TQString &str) { unsigned int logN = 0; TQString fPrefix="kick_"; do{ TQString fName; KviTQString::sprintf(fName,"%Q%u.log",&fPrefix,logN); getLocalKvircDirectory(str,Log,fName); logN++; if(logN > 9999) { // Time to clear logs! :) fPrefix+="x"; logN = 0; } } while(KviFileUtils::fileExists(str)); KviFileUtils::adjustFilePath(str); } bool KviApp::findFileByMediaType(KviStr &szRetPath,const char * filename) { g_pMediaManager->lock(); KviMediaType * m = g_pMediaManager->findMediaType(filename,false); if(m) { if(m->szSavePath.hasData()) { szRetPath = m->szSavePath; szRetPath.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR); szRetPath.append(filename); if(KviFileUtils::fileExists(szRetPath.ptr())) { // check again the media type... check the magic too KviMediaType * mt = g_pMediaManager->findMediaType(szRetPath.ptr()); if(mt == m) { g_pMediaManager->unlock(); //if(retMediaType)*retMediaType = mt; TQString szTmp = szRetPath.ptr(); // FIXME KviFileUtils::adjustFilePath(szTmp); szRetPath = szTmp; return true; } // else mime type not matched...we should not be looking there! } } } g_pMediaManager->unlock(); return false; } //===================== findUserFile =====================// // // Looks for an user file in the standard directories // bool KviApp::findUserFile(KviStr &szRetPath,const char *filename) { static KviApp::KvircSubdir localsubdirs[5]={ Avatars , Incoming , Pics , Audio , Log }; static KviApp::KvircSubdir globalsubdirs[3]={ Avatars , Pics , Audio }; // Absolute paths can not be "found"... they are obvious if(kvi_isAbsolutePath(filename)) { szRetPath=filename; TQString szTmp = szRetPath.ptr(); // FIXME KviFileUtils::adjustFilePath(szTmp); szRetPath = szTmp; return KviFileUtils::fileExists(filename); } // FIXME: #warning "Use the user defined path ?" // lookup the magic by name match only... if(findFileByMediaType(szRetPath,filename))return true; int i; for(i= 0;i<5; i++) { getLocalKvircDirectory(szRetPath,localsubdirs[i],filename); if(KviFileUtils::fileExists(szRetPath.ptr()))return true; } for(i= 0;i<3; i++) { getGlobalKvircDirectory(szRetPath,globalsubdirs[i],filename); if(KviFileUtils::fileExists(szRetPath.ptr()))return true; } if(findImageInImageSearchPath(szRetPath,filename))return true; // Last resort ... szRetPath = TQDir::homeDirPath(); szRetPath.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR); szRetPath.append(filename); if(KviFileUtils::fileExists(szRetPath.ptr()))return true;; szRetPath = filename; //if(retMediaType)*retMediaType = m; return false; //gotit: //if(retMediaType)*retMediaType = g_pMediaManager->findMediaType(szRetPath.ptr()); // return true; } //========================= findImage ===========================// // // Find a file inside the default "Image" directories // This should be thread safe (and in fact IS used by other threads) // This function should be used only for finding the INTERNAL // pixmaps... (so we expect them to be in the pics directory or // Eventually in user's $HOME // // FIXME: #warning "Check WHEN findImage is used and when findUserFile is used...we have a mess here" bool KviApp::findImageInImageSearchPath(KviStr &szRetPath,const char * filename) { // first lookup the user defined paths for(TQStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).begin(); it != KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end();++it) { szRetPath = *it; szRetPath.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR); szRetPath.append(filename); //debug("LOOK FOR %s",szRetPath.ptr()); if(KviFileUtils::fileExists(szRetPath.ptr()))return true; } return false; } bool KviApp::findImageInImageSearchPath(TQString &szRetPath,const char * filename) { // first lookup the user defined paths for(TQStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).begin(); it != KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end();++it) { szRetPath = *it; KviTQString::ensureLastCharIs(szRetPath,KVI_PATH_SEPARATOR_CHAR); szRetPath.append(filename); //debug("LOOK FOR %s",szRetPath.ptr()); if(KviFileUtils::fileExists(szRetPath))return true; } return false; } static KviApp::KvircSubdir pics_localsubdirs[2]={ KviApp::Pics , KviApp::Avatars }; static KviApp::KvircSubdir pics_globalsubdirs[2]={ KviApp::Pics , KviApp::Avatars }; bool KviApp::mapImageFile(KviStr &szRetPath,const char * filename) { TQString buff; bool ret=mapImageFile(buff,filename); szRetPath=buff; return ret; } bool KviApp::mapImageFile(TQString &szRetPath,const char * filename) { szRetPath = filename; // can't map non absolute paths if(!kvi_isAbsolutePath(filename))return false; // can't map non existing paths if(!KviFileUtils::fileExists(filename))return false; TQFileInfo fi = TQFileInfo(TQString::fromUtf8(filename)); unsigned int size = fi.size(); KviStr szBestMatch; while(szRetPath.find(KVI_PATH_SEPARATOR) != -1) { KviTQString::cutToFirst(szRetPath,KVI_PATH_SEPARATOR); if(szRetPath.isEmpty())break; KviStr szBuffer; int i; for(i=0;i<2;i++) { getLocalKvircDirectory(szBuffer,pics_localsubdirs[i],szRetPath); if(KviFileUtils::fileExists(szBuffer.ptr())) { TQFileInfo fi2(TQString::fromUtf8(szBuffer.ptr())); if(size == fi2.size()) { // probably the same file szBestMatch = szRetPath; } } } for(i=0;i<2;i++) { getGlobalKvircDirectory(szBuffer,pics_globalsubdirs[i],szRetPath); //debug("CHECK %s",szBuffer.ptr()); if(KviFileUtils::fileExists(szBuffer.ptr())) { TQFileInfo fi2(TQString::fromUtf8(szBuffer.ptr())); if(size == fi2.size()) { // probably the same file szBestMatch = szRetPath; } } } // Last resort szBuffer = TQDir::homeDirPath(); szBuffer.ensureLastCharIs(KVI_PATH_SEPARATOR_CHAR); szBuffer.append(szRetPath); if(KviFileUtils::fileExists(szBuffer.ptr())) { TQFileInfo fi2(TQString::fromUtf8(szBuffer.ptr())); if(size == fi2.size()) { // prolly the same file szBestMatch = szRetPath; } } } if(szBestMatch.hasData()) { szRetPath = szBestMatch; return true; } // no way to map it :/ szRetPath = filename; return false; } bool KviApp::findImage(KviStr &szRetPath,const char *filename) { TQString buff; bool ret=findImage(buff,filename); szRetPath=buff; return ret; } bool KviApp::findImage(TQString &szRetPath,const char *filename) { // Find an user file... if(kvi_isAbsolutePath(filename)) { szRetPath=filename; return KviFileUtils::fileExists(filename); } // if we have a theme, look it up as first if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty()) { TQString szTmp = KVI_OPTION_STRING(KviOption_stringIconThemeSubdir); szTmp.append(KVI_PATH_SEPARATOR_CHAR); szTmp.append(filename); getLocalKvircDirectory(szRetPath,KviApp::Themes,szTmp); if(KviFileUtils::fileExists(szRetPath))return true; getGlobalKvircDirectory(szRetPath,KviApp::Themes,szTmp); if(KviFileUtils::fileExists(szRetPath))return true; } int i; for(i=0;i<2;i++) { getLocalKvircDirectory(szRetPath,pics_localsubdirs[i],filename); if(KviFileUtils::fileExists(szRetPath))return true; } for(i=0;i<2;i++) { getGlobalKvircDirectory(szRetPath,pics_globalsubdirs[i],filename); if(KviFileUtils::fileExists(szRetPath))return true; } if(findImageInImageSearchPath(szRetPath,filename))return true; // Last resort szRetPath = TQDir::homeDirPath(); KviTQString::ensureLastCharIs(szRetPath,KVI_PATH_SEPARATOR_CHAR); szRetPath.append(filename); if(KviFileUtils::fileExists(szRetPath))return true; szRetPath = filename; return false; } bool KviApp::findImageThemeOnlyCompat(TQString &szRetPath,const char *filename) { // if we have a theme, look it up as first if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty()) { TQString szTmp = KVI_OPTION_STRING(KviOption_stringIconThemeSubdir); szTmp.append(KVI_PATH_SEPARATOR_CHAR); szTmp.append(filename); getLocalKvircDirectory(szRetPath,KviApp::Themes,szTmp); if(KviFileUtils::fileExists(szRetPath))return true; getGlobalKvircDirectory(szRetPath,KviApp::Themes,szTmp); if(KviFileUtils::fileExists(szRetPath))return true; } getLocalKvircDirectory(szRetPath,KviApp::Pics,filename); if(KviFileUtils::fileExists(szRetPath))return true; if(findImageInImageSearchPath(szRetPath,filename))return true; szRetPath = filename; return false; } bool KviApp::findSmallIcon(TQString &szRetPath,const char *filename) { // this is a bit optimized for the small builtin icons // looks up less places. //if(kvi_isAbsolutePath(filename)) //{ // BUG!.. we should never //szRetPath=filename; //return KviFileUtils::fileExists(filename); //} // if we have a theme, look it up as first if(!KVI_OPTION_STRING(KviOption_stringIconThemeSubdir).isEmpty()) { TQString szTmp = KVI_OPTION_STRING(KviOption_stringIconThemeSubdir); szTmp.append(KVI_PATH_SEPARATOR_CHAR); szTmp.append(KVI_SMALLICONS_SUBDIRECTORY); szTmp.append(KVI_PATH_SEPARATOR_CHAR); szTmp.append(filename); getLocalKvircDirectory(szRetPath,KviApp::Themes,szTmp); if(KviFileUtils::fileExists(szRetPath))return true; getGlobalKvircDirectory(szRetPath,KviApp::Themes,szTmp); if(KviFileUtils::fileExists(szRetPath))return true; } int i; // unlikely getLocalKvircDirectory(szRetPath,KviApp::SmallIcons,filename); if(KviFileUtils::fileExists(szRetPath))return true; getLocalKvircDirectory(szRetPath,KviApp::Pics,filename); if(KviFileUtils::fileExists(szRetPath))return true; // likely getGlobalKvircDirectory(szRetPath,KviApp::SmallIcons,filename); if(KviFileUtils::fileExists(szRetPath))return true; if(findImageInImageSearchPath(szRetPath,filename))return true; // Last resort... bleah :/ szRetPath = TQDir::homeDirPath(); KviTQString::ensureLastCharIs(szRetPath,KVI_PATH_SEPARATOR_CHAR); szRetPath.append(filename); if(KviFileUtils::fileExists(szRetPath))return true; szRetPath = filename; return false; } //================== getReadOnlyConfigPath ====================// // // We want to READ a config file...find it // bool KviApp::getReadOnlyConfigPath(KviStr &buffer,const char *config_name,KvircSubdir sbd,bool bNoFail) { // DEPRECATED TQString tmp; bool bRet = getReadOnlyConfigPath(tmp,config_name,sbd,bNoFail); buffer = tmp; return bRet; } bool KviApp::getReadOnlyConfigPath(TQString &buffer,const char *config_name,KvircSubdir sbd,bool bNoFail) { // Take a look in the local directory.... getLocalKvircDirectory(buffer,sbd,config_name); //debug("%s %s %i |%s| %i",__FILE__,__FUNCTION__,__LINE__,buffer.ptr(),KviFileUtils::fileExists(buffer.ptr())); if(!KviFileUtils::fileExists(buffer)) { // No saved config yet... check for defaults TQString tmp; getGlobalKvircDirectory(tmp,sbd,config_name); if(!KviFileUtils::fileExists(tmp)) { // No defaults...no such config file at all. if(bNoFail)getLocalKvircDirectory(buffer,sbd,config_name); return false; } else buffer = tmp; // get the defaults this time } // else file exists... return true; }