diff options
Diffstat (limited to 'src/modules/file/libkvifile.cpp')
-rw-r--r-- | src/modules/file/libkvifile.cpp | 1260 |
1 files changed, 1260 insertions, 0 deletions
diff --git a/src/modules/file/libkvifile.cpp b/src/modules/file/libkvifile.cpp new file mode 100644 index 00000000..8b8dd9ec --- /dev/null +++ b/src/modules/file/libkvifile.cpp @@ -0,0 +1,1260 @@ +//============================================================================= +// +// File : libkvifile.cpp +// Creation date : Fri Nov 9 03:27:59 2001 GMT by Szymon Stefanek +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 2001-2005 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. +// +//============================================================================= + +#include "kvi_module.h" +#include "kvi_fileutils.h" +#include "kvi_locale.h" +#include "kvi_malloc.h" +#include "kvi_app.h" +#include "kvi_options.h" +#include "kvi_qcstring.h" + +#include "kvi_kvs_arraycast.h" + +#include <qfileinfo.h> +#include "kvi_file.h" +#include <qdir.h> +#include <qtextstream.h> + +/* + @doc: file.copy + @type: + command + @title: + file.copy + @keyterms: + copying files + @short: + Makes a copy of a file + @syntax: + file.copy [-o] <source:string> <destination:string> + @switches: + !sw: -o | --overwrite + Overwrites the file even if it already exists. + @description: + Makes a copy of the <source> file as <destination>.[br] + If the [-o] switch is used , the <destination> file is overwritten , if already exists.[br] + With no [-o] switch , this command does not overwrite files.[br] + The destination path must be already existing: if you want to ensure this, use [fnc]$file.mkdir[/fnc] first.[br] + The paths (<source> and <destination>) are adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed. Just use UNIX style paths for them.[br] + @seealso: + [cmd]file.rename[/cmd], [fnc]$file.exists[/fnc] +*/ + +static bool file_kvs_cmd_copy(KviKvsModuleCommandCall * c) +{ + QString szSrc,szDst; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("source",KVS_PT_NONEMPTYSTRING,0,szSrc) + KVSM_PARAMETER("destination",KVS_PT_NONEMPTYSTRING,0,szDst) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szSrc); + KviFileUtils::adjustFilePath(szDst); + if(KviFileUtils::fileExists(szDst) && !c->switches()->find('o',"overwrite")) + { + c->warning(__tr2qs("Destinaion file exists: no copy made")); + return true; + } + if(!KviFileUtils::copyFile(szSrc,szDst)) + { + c->warning(__tr2qs("Failed to copy from %Q to %Q"),&szSrc,&szDst); + c->warning(__tr2qs("Either the source doesn't exist or the destination can not be created")); + } + return true; +} + + +/* + @doc: file.addimagepath + @type: + command + @title: + file.addimagepath + @short: + Adds an image search path + @syntax: + file.addimagepath <path:string> + @description: + Adds <path> to the image search path list.[br] + KVIrc will look for images files (also) in that path (when a relative image file name is used).[br] + Yes, this function is a bit misplaced... + @seealso: + [cmd]file.delimagepath[/cmd] +*/ + +static bool file_kvs_cmd_addimagepath(KviKvsModuleCommandCall * c) +{ + QString szDst; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("path",KVS_PT_NONEMPTYSTRING,0,szDst) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szDst); + + QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).find(szDst); + if(it == KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end()) + KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).append(szDst); + return true; +} + + + +/* + @doc: file.delimagepath + @type: + command + @title: + file.delimagepath + @short: + Removes an image search path + @syntax: + file.delimagepath <path:string> + @description: + Removes <path> from the image search path list.[br] + Yes, this function is a bit misplaced... + @seealso: + [cmd]file.addimagepath[/cmd] +*/ + +static bool file_kvs_cmd_delimagepath(KviKvsModuleCommandCall * c) +{ + QString szDst; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("path",KVS_PT_NONEMPTYSTRING,0,szDst) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szDst); + + QStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).find(szDst); + if(it == KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).end()) + KVI_OPTION_STRINGLIST(KviOption_stringlistImageSearchPaths).remove(szDst); + return true; +} + + +/* + @doc: file.write + @type: + command + @title: + file.write + @keyterms: + writing data to files + @short: + Writes an ascii data string to a file + @syntax: + file.write [-a] [-l] <filename:string> <data:string> + @switches: + !sw: -a | --append + If the file already exists, append the data instead of overwriting the original contents. + !sw: -l | --local-8-bit + Causes the file to be written in the local 8 bit character set instead of the + default utf8. + @description: + Writes <data> (which is an ASCII string) to the file <filename>.[br] + It does NOT append a traling LF character: if you want it you must explicitly specify it in the <data> parameter.[br] + -a causes the command to append the <data> to the file instead of overwriting the entire file.[br] + The path is adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed. Just use UNIX style paths for them.[br] + The file is saved in utf8 unless the -l switch is specified (in that case the local 8 bit encoding is used). + Please note that uf8 is the only character set that preserves ALL the possible characters. + @seealso: + [cmd]file.rename[/cmd], [fnc]$file.exists[/fnc] +*/ + +static bool file_kvs_cmd_write(KviKvsModuleCommandCall * c) +{ + QString szFileName,szData; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName) + KVSM_PARAMETER("data",KVS_PT_NONEMPTYSTRING,0,szData) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szFileName); + + bool bRet; + if(c->switches()->find('l',"local-8-bit")) + bRet = KviFileUtils::writeFileLocal8Bit(szFileName,szData,c->switches()->find('a',"append")); + else + bRet = KviFileUtils::writeFile(szFileName,szData,c->switches()->find('a',"append")); + + if(!bRet) + c->warning(__tr2qs("Failed to write to file %Q: the destination couldn't be opened"),&szFileName); + + return true; +} + + +/* + @doc: file.rename + @type: + command + @title: + file.rename + @keyterms: + copying files + @short: + Makes a copy of a file + @syntax: + file.rename <oldname:string> <newname:string> + @description: + Renames a file from <oldname> to <newname>.[br] + This command can also rename directories.[br] + If the <newname> file already exists , this command fails.[br] + The paths (<oldname> and <newname>) are adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed.Just use UNIX style paths for them.[br] + @seealso: + [cmd]file.copy[/cmd], [fnc]$file.exists[/fnc] +*/ + +static bool file_kvs_cmd_rename(KviKvsModuleCommandCall * c) +{ + QString szOld,szNew; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("oldname",KVS_PT_NONEMPTYSTRING,0,szOld) + KVSM_PARAMETER("newname",KVS_PT_NONEMPTYSTRING,0,szNew) + KVSM_PARAMETERS_END(c) + + KviFileUtils::adjustFilePath(szOld); + KviFileUtils::adjustFilePath(szNew); + + if(KviFileUtils::fileExists(szNew)) + c->warning(__tr2qs("Destination file exists: file not renamed")); + + if(!KviFileUtils::renameFile(szOld,szNew)) + c->warning(__tr2qs("Failed to rename %Q to %Q"),&szOld,&szNew); + return true; +} + + +/* + @doc: file.mkdir + @type: + command + @title: + file.mkdir + @keyterms: + creating directories + @short: + Creates a directory + @syntax: + file.mkdir <directory:string> + @description: + Creates the <directory>.[br] + The path is adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed. Just use an UNIX style path.[br] + @seealso: + [fnc]$file.exists[/fnc] +*/ + +static bool file_kvs_cmd_mkdir(KviKvsModuleCommandCall * c) +{ + QString szDir; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("directory",KVS_PT_NONEMPTYSTRING,0,szDir) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szDir); + if(!KviFileUtils::makeDir(szDir)) + c->warning(__tr2qs("Failed to make the directory %Q"),&szDir); + return true; +} + + + +/* + @doc: file.remove + @type: + command + @title: + file.remove + @keyterms: + removing files + @short: + Removes a file + @syntax: + file.remove [-q] <name:string> + @switches: + !sw: -q | --quiet + Suppresses any warning message + @description: + Removes the file <name>.[br] + -q suppresses any warning message (about non existing file , for example).[br] + The path is adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed. Just use an UNIX style path.[br] + @seealso: + [fnc]$file.exists[/fnc] +*/ + +static bool file_kvs_cmd_remove(KviKvsModuleCommandCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + if(!KviFileUtils::removeFile(szName)) + { + if(!c->switches()->find('q',"quiet")) + c->warning(__tr2qs("Failed to remove the file %Q"),&szName); + } + return true; +} + + +/* + @doc: file.rmdir + @type: + command + @title: + file.rmdir + @keyterms: + removing directories + @short: + Removes a directory + @syntax: + file.rmdir [-q] <name:string> + @switches: + !sw: -q | --quiet + Suppresses any warning message + @description: + Removes the directory <name>.[br] + The directory must be empty for this command to success.[br] + -q suppresses any warning message (about non existing directory , for example).[br] + The path is adjusted according to the system that KVIrc + is running on so you don't have to bother about portability: it *should* be automatically + guaranteed. Just use an UNIX style path.[br] + @seealso: + [fnc]$file.exists[/fnc] + [cmd]file.remove[/cmd] +*/ + +static bool file_kvs_cmd_rmdir(KviKvsModuleCommandCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("name",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + if(!KviFileUtils::removeDir(szName)) + { + if(!c->switches()->find('q',"quiet")) + c->warning(__tr2qs("Failed to remove the directory %Q"),&szName); + } + return true; +} + + +/* + @doc: file.exists + @type: + function + @title: + $file.exists + @short: + Check if a file exists + @syntax: + <boolean> $file.exists(<filename:string>) + @description: + Returns true if the file <filename> exists (this is also valid for directories!).[br] + The <filename> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br] +*/ + +static bool file_kvs_fnc_exists(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_STRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + QFileInfo f(szName); + c->returnValue()->setBoolean(f.exists()); + return true; +} + + +/* + @doc: file.type + @type: + function + @title: + $file.type + @short: + Checks the type of a path + @syntax: + <string> $file.type(<filename:string>) + @description: + Returns "f" if the <filename> points to a real file , "d" if <filename> + is the name of a directory or "l" if it is a symbolic link.[br] + The <filename> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br] +*/ + +static bool file_kvs_fnc_type(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + QFileInfo f(szName); + if(f.isFile())c->returnValue()->setString("f"); + else if(f.isDir())c->returnValue()->setString("d"); + else if(f.isSymLink())c->returnValue()->setString("l"); + return true; +} + + +/* + @doc: file.size + @type: + function + @title: + $file.size + @short: + Returns the size of a file + @syntax: + <integer> $file.size(<filename:string>) + @description: + Returns the size of the file pointed by <filename>.[br] + If the file does not exist , this function returns 0.[br] + The <filename> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br] +*/ + +static bool file_kvs_fnc_size(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + QFileInfo f(szName); + c->returnValue()->setInteger(f.size()); + return true; +} +/* + @doc: file.allSizese + @type: + function + @title: + $file.allSizes + @short: + Returns all sizes of a specified directory. + @syntax: + <array> $file.allSize(<dirname:string>) + @description: + Returns the size of every files of the specified directory as an array.[br] +*/ + +static bool file_kvs_fnc_allSizes(KviKvsModuleFunctionCall * c) +{ + QString szDir; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("directory",KVS_PT_NONEMPTYSTRING,0,szDir) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szDir); + + QDir d(szDir); + if(!d.exists()) + { + c->warning(__tr2qs("The specified directory does not exist '%Q'"),&szDir); + return true; + } + + QStringList sl; + sl = d.entryList(QDir::Files); + + KviKvsArray * a = new KviKvsArray(); + QString szFile; + if(!sl.isEmpty()) + { + int idx = 0; + for(QStringList::Iterator it = sl.begin();it != sl.end();++it) + { + szFile=szDir+(*it); + QFileInfo f(szFile); + a->set(idx,new KviKvsVariant((kvs_int_t)f.size())); + idx++; + } + } + c->returnValue()->setArray(a); + + + + + return true; +} + +/* + @doc: file.fixpath + @type: + function + @title: + $file.fixpath + @short: + Converts file paths + @syntax: + <string> $file.fixpath(<filename:string>) + @description: + Returns the <filename> adjusted to match the current operating + system file path conventions.[br] This means that on UNIX , a path like "C:\folder\file.mp3" + will be returned as "/folder/file.mp3" and vice-versa.[br] + There is a minor problem with unix paths converted to the windows system: unix + has no "drive" concept thus the unix paths do not contain a drive. KVIrc will + always map the paths to the "default" C: drive.[br] + This is a good reason to avoid using absolute hard-coded paths :).[br] + Please note that you DON'T NEED to call this function on paths that you + pass to the other file.* functions: they are adjusted automatically.[br] + @seealso: + [fnc]$file.ps[/fnc] +*/ + + +static bool file_kvs_fnc_fixpath(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_STRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + c->returnValue()->setString(szName); + return true; +} + + +/* + @doc: file.ps + @type: + function + @title: + $file.ps + @short: + Returns the file path separator + @syntax: + <string> $file.ps() + @description: + Returns the file path separator for the current operating system.[br] + On windows , '\' is returned , on UNIX , '/'.[br] + @seealso: + [fnc]$file.fixpath[/fnc] +*/ + +static bool file_kvs_fnc_ps(KviKvsModuleFunctionCall * c) +{ + c->returnValue()->setString(QString(QChar(KVI_PATH_SEPARATOR_CHAR))); + return true; +} + + +/* + @doc: file.ls + @type: + function + @title: + $file.ls + @short: + Returns a directory listing + @syntax: + <array> $file.ls(<directory:string>,[<flags:string>[,<namefilter:string>]]) + @description: + Returns the listing of the specified directory as an array.[br] + The <directory> should be an unix-style file path and is adjusted according to the system that KVIrc is running on.[br] + <flags> may be a combination of the following characters:[br] + d: list directories[br] + f: list files[br] + l: list symbolic links[br] + r: list readable files[br] + w: list writeable files[br] + x: list executable files[br] + h: list hidden files[br] + s: list system files[br] + n: sort files by name[br] + t: sort files by file time[br] + b: sort files by file size[br] + z: put the directories first, then the files[br] + k: invert sort order[br] + i: case insensitive sort[br] + If <flags> is empty then a default of 'dfrwxhs'.[br] + If none of r,w,x is set then KVIrc sets all of them by default.[br] + If <namefilter> is passed then it is interpreted as a wildcard string + that must match the entries to be returned.[br] + @example: + [example] + %dir[]=$file.ls(/,"d") + [cmd]foreach[/cmd](%f,%dir[])echo %f + %dir[]=$file.ls(/usr/include,"f","t*.h"); + [cmd]foreach[/cmd](%f,%dir[])echo %f + %dir[]=$file.ls($file.homedir,"dfr"); + [cmd]foreach[/cmd](%f,%dir[])echo %f + [/example] +*/ + +static bool file_kvs_fnc_ls(KviKvsModuleFunctionCall * c) +{ + QString szDir,szFlags,szFilter; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("directory",KVS_PT_NONEMPTYSTRING,0,szDir) + KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags) + KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFilter) + KVSM_PARAMETERS_END(c) + + KviFileUtils::adjustFilePath(szDir); + + QDir d(szDir); + if(!d.exists()) + { + c->warning(__tr2qs("The specified directory does not exist '%Q'"),&szDir); + return true; + } + +#ifdef COMPILE_USE_QT4 + QFlags<QDir::Filter> iFlags = 0; +#else + int iFlags = 0; +#endif + if(szFlags.isEmpty())iFlags = QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Writable | QDir::Executable | QDir::Hidden | QDir::System; + else { + if(szFlags.find('d',false) != -1)iFlags |= QDir::Dirs; + if(szFlags.find('f',false) != -1)iFlags |= QDir::Files; + if(szFlags.find('l',false) == -1)iFlags |= QDir::NoSymLinks; + if(szFlags.find('r',false) != -1)iFlags |= QDir::Readable; + if(szFlags.find('w',false) != -1)iFlags |= QDir::Writable; + if(szFlags.find('x',false) != -1)iFlags |= QDir::Executable; + if(szFlags.find('h',false) != -1)iFlags |= QDir::Hidden; + if(szFlags.find('s',false) != -1)iFlags |= QDir::System; + } +#ifdef COMPILE_USE_QT4 + QFlags<QDir::SortFlag> iSort = 0; +#else + int iSort = 0; +#endif + if(szFlags.isEmpty())iSort = QDir::Unsorted; + else { + if(szFlags.find('n',false) != -1)iSort |= QDir::Name; + if(szFlags.find('t',false) != -1)iSort |= QDir::Time; + if(szFlags.find('b',false) != -1)iSort |= QDir::Size; + if(szFlags.find('z',false) != -1)iSort |= QDir::DirsFirst; + if(szFlags.find('k',false) != -1)iSort |= QDir::Reversed; + if(szFlags.find('i',false) != -1)iSort |= QDir::IgnoreCase; + } + + QStringList sl; + if(!szFilter.isEmpty())sl = d.entryList(szFilter,iFlags,iSort); + else sl = d.entryList(iFlags,iSort); + + KviKvsArray * a = new KviKvsArray(); + if(!sl.isEmpty()) + { + int idx = 0; + for(QStringList::Iterator it = sl.begin();it != sl.end();++it) + { + a->set(idx,new KviKvsVariant(*it)); + idx++; + } + } + c->returnValue()->setArray(a); + + return true; +} + +/* + @doc: file.read + @type: + function + @title: + $file.read + @short: + Reads a text file + @syntax: + <string> $file.read(<filename:string>[,<size:integer>[,<flags:string>]]) + @description: + Reads at most <size> bytes of the file pointed by <filename>.[br] + <size> is an upper limit but may be not reached if the real file is smaller.[br] + The data read is returned as a string , so if the file contains binary data, + expect strange results.[br] If <size> is not specified, then KVIrc tries to read + the whole file up to the 1 MB limit (so if you want to read a file that is + bigger thatn 1 MB then you MUST specify the <size>).[br] + WARNING: always check the file size before attemting to read a whole file... + reading a CDROM iso image may sit down your system :) (and will prolly crash while + allocating memory , before attempting to read anything)[br] + An empty string is returned if a serious error occures.[br] + The <filename> is adjusted according to the system that KVIrc is running on.[br] + Flags are actually limited to the single letter 'l'. By default the file + is decoded from the ut8 characters set. If 'l' is present the the file + is decoded by using the local 8 bit character set instead. + @examples: + [example] + echo $file.read(/proc/cpuinfo) + [/example] + @seealso: + [fnc]$file.readbinary[/fnc] +*/ + +static bool file_kvs_fnc_read(KviKvsModuleFunctionCall * c) +{ + QString szNameZ; + kvs_uint_t uSize; + QString szFlags; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szNameZ) + KVSM_PARAMETER("size",KVS_PT_UINT,KVS_PF_OPTIONAL,uSize) + KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szNameZ); + + QFile f(szNameZ); + if(!f.open(IO_ReadOnly)) + { + c->warning(__tr2qs("Can't open the file \"%Q\" for reading"),&szNameZ); + return true; + } + + if(c->params()->count() < 2)uSize = 1024 * 1024; // 1 meg file default + + char * buf = (char *)kvi_malloc(sizeof(char) * (uSize + 1)); + unsigned int uReaded = 0; + unsigned int uRetries = 0; + + while((uReaded < uSize) && (!f.atEnd())) + { + int readedNow = f.readBlock(buf + uReaded,uSize - uReaded); + if(readedNow < 0) + { + kvi_free(buf); + c->warning(__tr2qs("Read error for file %Q"),&szNameZ); + return true; + } else readedNow += uReaded; + uRetries ++; + if(uRetries > 1000) + { + // ops + kvi_free(buf); + c->warning(__tr2qs("Read error for file %Q (have been unable to read the requested size in 1000 retries)"),&szNameZ); + return true; + } + uReaded += readedNow; + } + + buf[uReaded] = '\0'; + + if(szFlags.find('l',false) == -1) + c->returnValue()->setString(QString::fromUtf8(buf)); + else + c->returnValue()->setString(QString::fromLocal8Bit(buf)); + + kvi_free(buf); + + return true; +} + + +/* + @doc: file.readLines + @type: + function + @title: + $file.readLines + @short: + Reads lines of a text file + @syntax: + <array> $file.readLines(<filename:string>[,<startline:integer>,[<count:integer>[,<flags:string>]]]) + @description: + Reads lines from the specified file and returns them as an array of strings. + The lines are assumed to be separated by linefeed characters (which are NOT returned). + Eventual terminating carriage return characters at the end of the line are stripped. + If <startline> is specified, then all the lines with indexes lower that <startline> are + discarded. If <count> is specified then a maximum of <count> lines is returned. + If <count> is not specified then all the lines until the end are read. + The <filename> is adjusted according to the system that KVIrc is running on.[br] + Flags are actually limited to the single letter 'l'. By default the file + is decoded from the ut8 characters set. If 'l' is present the the file + is decoded by using the local 8 bit character set instead. + WARNING: Always check the size of the file you're going to read: it is not + a good idea attempting to read a 700 MB binary file with this function since + it will probably sit down your system and exhaust your virtual memory. + @examples: + [example] + echo $file.readLines(/proc/cpuinfo) + [/example] + @seealso: + [fnc]$file.read[/fnc], [cmd]file.writeLines[/cmd], [fnc]$lf[/fnc] +*/ + + + +static bool file_kvs_fnc_readLines(KviKvsModuleFunctionCall * c) +{ + QString szName; + QString szFlags; + kvs_int_t iStartLine; + kvs_int_t iCount; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETER("startline",KVS_PT_INT,KVS_PF_OPTIONAL,iStartLine) + KVSM_PARAMETER("count",KVS_PT_INT,KVS_PF_OPTIONAL,iCount) + KVSM_PARAMETER("flags",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags) + KVSM_PARAMETERS_END(c) + KviFileUtils::adjustFilePath(szName); + + QFile f(szName); + if(!f.open(IO_ReadOnly)) + { + c->warning(__tr2qs("Can't open the file \"%Q\" for reading"),&szName); + return true; + } + + if(c->params()->count() < 2)iStartLine = 0; + if(c->params()->count() < 3)iCount = -1; + + bool bLocal8Bit = szFlags.find('l',0,false) != -1; + + KviKvsArray * a = new KviKvsArray(); + + int iIndex=0; + + QTextStream stream( &f ); + + stream.setEncoding(bLocal8Bit ? QTextStream::Locale : QTextStream::UnicodeUTF8); + for(int i=0;i<iStartLine;i++) + stream.readLine(); + + if(iCount>0) + { + for(; (iCount>0 && !stream.atEnd()) ; iCount-- ) + a->set(iIndex,new KviKvsVariant(stream.readLine())); + iIndex++; + } else { + while(!stream.atEnd()) { + a->set(iIndex,new KviKvsVariant(stream.readLine())); + iIndex++; + } + } + + f.close(); + + c->returnValue()->setArray(a); + + return true; +} + + +/* + @doc: file.writelines + @type: + command + @title: + file.writeLines + @short: + Writes an array of lines to a file + @syntax: + file.writeLines [-l] [-a] [-c] <filename:string> <lines:array> + @switches: + !sw: -l | --local-8-bit + Causes the lines to be saved in local 8 bit character set instead + of the default unicode encoding. + !sw: -a | --append + If the file already exists, then the lines are appended to the end + instead of overwriting the file. + !sw: -c | --crlf + The lines are separated by a carriage-return+line-feed character + combination, compatible with windows text mode files. + This is the only way to make the file readable in windows notepad, for example. + Please note that this is broken design: do NOT use it :) + !sw: -n | --no-separator + Do not separate the lines at all (either the separators are already + inside the lines array or no line separation is desired at all). + -n takes precedence over -c. + !sw: -q | --quiet + Don't complain if the file can't be opened: just fail silently + @description: + Writes the array of <lines> to the specified file. + The lines are separated by a single linefeed character (see also [fnc]$lf[/fnc]) + unless the -c or -n switches are used. If the file already exists then it is + overwritten with the new data unless the -a switch is used. + The lines array is encoded in the ut8 character set unless the -l switch is used. + @seealso: + [fnc]$file.readLines[/fnc] +*/ + + + +static bool file_kvs_cmd_writeLines(KviKvsModuleCommandCall * c) +{ + QString szFile,szFlags; + KviKvsArrayCast a; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFile) + KVSM_PARAMETER("lines",KVS_PT_ARRAYCAST,0,a) + KVSM_PARAMETERS_END(c) + + KviFileUtils::adjustFilePath(szFile); + + KviFile f(szFile); + int iFlags = IO_WriteOnly; + + if(!f.openForWriting(c->switches()->find('a',"append"))) + { + if(!c->switches()->find('q',"quiet")) + c->warning(__tr2qs("Can't open the file \"%Q\" for writing"),&szFile); + return true; + } + + bool bLocal8Bit = c->switches()->find('l',"local-8-bit"); + bool bNoSeparator = c->switches()->find('n',"no-separator"); + bool bAddCR = c->switches()->find('c',"crlf"); + + unsigned int u = 0; + while(u < a.array()->size()) + { + KviKvsVariant * v = a.array()->at(u); + KviQCString dat; + if(v) + { + QString szDat; + v->asString(szDat); + KviQCString dat = bLocal8Bit ? szDat.local8Bit() : szDat.utf8(); + } + if(!bNoSeparator) + { + if(bAddCR)dat += "\r\n"; + else dat += '\n'; + } + f.writeBlock(dat.data(),dat.length()); + u++; + } + + f.close(); + + return true; +} + + +/* + @doc: file.localdir + @type: + function + @title: + $file.localdir + @short: + Get the KVIrc local directory + @syntax: + <string> $file.localdir([relative_path:string]) + @description: + Returns the path to the KVIrc local data directory.[br] + The KVIrc local data directory is always writeable and contains + the various subdirectories that KVIrc uses internally: audio , avatars , + config , help , incoming , log , modules , msgcolors and pics.[br] + If <relative_path> is passed , then it is appended at the end of the directory + to form a complete filepath.[br] + The path is adjusted to contain single separators suitable for the platform + that KVIrc is atually running on (thus you not need to care about path + separators in the <relative_path> , KVIrc will adjust them).[br] + @examples: + [example] + echo KVIrc looks for pictures in $file.localdir(pics) + echo panic.png would be translated to $file.localdir(pics/panic.png) + [/example] +*/ + +static bool file_kvs_fnc_localdir(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName) + KVSM_PARAMETERS_END(c) + if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR); + QString szPath; + g_pApp->getLocalKvircDirectory(szPath,KviApp::None,szName); + KviFileUtils::adjustFilePath(szPath); + c->returnValue()->setString(szPath); + return true; +} + + + +/* + @doc: file.homedir + @type: + function + @title: + $file.homedir + @short: + Get the user's HOME directory + @syntax: + <string> $file.homedir([relative_path:string]) + @description: + Returns the user's HOME directory path.[br] + If <relative_path> is passed , then it is appended at the end of the directory + to form a complete filepath.[br] + The path is adjusted to contain single separators suitable for the platform + that KVIrc is atually running on (thus you not need to care about path + separators in the <relative_path> , KVIrc will adjust them).[br] +*/ + +static bool file_kvs_fnc_homedir(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName) + KVSM_PARAMETERS_END(c) + if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR); + QString szPath = QDir::homeDirPath(); + KviQString::ensureLastCharIs(szPath,KVI_PATH_SEPARATOR_CHAR); + szPath.append(szName); + KviFileUtils::adjustFilePath(szPath); + c->returnValue()->setString(szPath); + return true; +} + + + +/* + @doc: file.rootdir + @type: + function + @title: + $file.rootdir + @short: + Get the system root directory + @syntax: + $file.rootdir(<relative_path>) + $file.rootdir + @description: + Returns the system's root directory (/ on UNIX and C:/ on Windows).[br] + If <relative_path> is passed , then it is appended at the end of the directory + to form a complete filepath.[br] + The path is adjusted to contain single separators suitable for the platform + that KVIrc is atually running on (thus you not need to care about path + separators in the <relative_path> , KVIrc will adjust them).[br] +*/ + +static bool file_kvs_fnc_rootdir(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName) + KVSM_PARAMETERS_END(c) + if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR); + QString szPath = QDir::rootDirPath(); + KviQString::ensureLastCharIs(szPath,KVI_PATH_SEPARATOR_CHAR); + szPath.append(szName); + KviFileUtils::adjustFilePath(szPath); + c->returnValue()->setString(szPath); + return true; +} + + +/* + @doc: file.cwd + @type: + function + @title: + $file.currentdir + @short: + Get the current directory + @syntax: + <string> $file.cwd([relative_path:string]) + @description: + Returns the current working directory.[br] + If <relative_path> is passed , then it is appended at the end of the directory + to form a complete filepath.[br] + The path is adjusted to contain single separators suitable for the platform + that KVIrc is atually running on (thus you not need to care about path + separators in the <relative_path> , KVIrc will adjust them).[br] +*/ + +static bool file_kvs_fnc_cwd(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName) + KVSM_PARAMETERS_END(c) + if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR); + QString szPath = QDir::currentDirPath(); + KviQString::ensureLastCharIs(szPath,KVI_PATH_SEPARATOR_CHAR); + szPath.append(szName); + KviFileUtils::adjustFilePath(szPath); + c->returnValue()->setString(szPath); + return true; +} + + +/* + @doc: file.globaldir + @type: + function + @title: + $file.globaldir + @short: + Get the KVIrc global directory + @syntax: + $file.globaldir(<relative_path>) + $file.globaldir + @description: + Returns the path to the KVIrc global data directory.[br] + The KVIrc local data directory is always readable but usually not writeable and contains + the various subdirectories that KVIrc uses internally: audio , avatars , + config , help , incoming , log , modules , msgcolors and pics.[br] + If <relative_path> is passed , then it is appended at the end of the directory + to form a complete filepath.[br] + The path is adjusted to contain single separators suitable for the platform + that KVIrc is atually running on (thus you not need to care about path + separators in the <relative_path> , KVIrc will adjust them).[br] + @examples: + [example] + echo KVIrc looks for pictures in $file.globaldir(pics) + echo panic.png would be translated to $file.globaldir(pics/panic.png) + [/example] +*/ + +static bool file_kvs_fnc_globaldir(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("relative_path",KVS_PT_STRING,KVS_PF_OPTIONAL,szName) + KVSM_PARAMETERS_END(c) + if(szName.isEmpty())szName.append(KVI_PATH_SEPARATOR_CHAR); + QString szPath; + g_pApp->getGlobalKvircDirectory(szPath,KviApp::None,szName); + KviFileUtils::adjustFilePath(szPath); + c->returnValue()->setString(szPath); + return true; +} + +/* + @doc: file.extractpath + @type: + function + @title: + $file.extractpath + @short: + Extract the path from a filename + @syntax: + <string> $file.extractpath(<filepath:string>) + @description: + Returns the path part of the <filepath> translated to match the current + platform filesystem conventions.[br] + The path will NOT contain a trailing path separator.[br] + For example, if <filepath> is /usr/arch/mp3/Carisma_SuonoDelSilenzio.mp3 then + this function will return /usr/arch/mp3 on UNIX and C:\usr\arch\mp3 on Windows. + @seealso: + [fnc]$file.extractFileName[/fnc] +*/ + +static bool file_kvs_fnc_extractpath(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filepath",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETERS_END(c) + c->returnValue()->setString(QFileInfo(szName).dirPath(TRUE)); + return true; +} + + +/* + @doc: file.extractfilename + @type: + function + @title: + $file.extractfilename + @short: + Extract the filename from a file path + @syntax: + <string> $file.extractpath(<filepath:string>) + @description: + Returns the filename part of the filepath translated to match the current + platform filesystem conventions.[br] + For example, if <filepath> is /usr/arch/mp3/Carisma_SuonoDelSilenzio.mp3 then + this function will return Carisma_SuonoDelSilenzio.mp3 + @seealso: + [fnc]$file.extractPath[/fnc] +*/ + +static bool file_kvs_fnc_extractfilename(KviKvsModuleFunctionCall * c) +{ + QString szName; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("filepath",KVS_PT_NONEMPTYSTRING,0,szName) + KVSM_PARAMETERS_END(c) + KviFileUtils::extractFileName(szName); + KviQString::cutToLast(szName,KVI_PATH_SEPARATOR_CHAR); + c->returnValue()->setString(szName); + return true; +} + + + +static bool file_module_init(KviModule * m) +{ + + KVSM_REGISTER_SIMPLE_COMMAND(m,"copy",file_kvs_cmd_copy); + KVSM_REGISTER_SIMPLE_COMMAND(m,"rename",file_kvs_cmd_rename); + KVSM_REGISTER_SIMPLE_COMMAND(m,"mkdir",file_kvs_cmd_mkdir); + KVSM_REGISTER_SIMPLE_COMMAND(m,"write",file_kvs_cmd_write); + KVSM_REGISTER_SIMPLE_COMMAND(m,"remove",file_kvs_cmd_remove); + KVSM_REGISTER_SIMPLE_COMMAND(m,"rmdir",file_kvs_cmd_rmdir); + KVSM_REGISTER_SIMPLE_COMMAND(m,"addimagepath",file_kvs_cmd_addimagepath); + KVSM_REGISTER_SIMPLE_COMMAND(m,"delimagepath",file_kvs_cmd_delimagepath); + KVSM_REGISTER_SIMPLE_COMMAND(m,"writeLines",file_kvs_cmd_writeLines); + + KVSM_REGISTER_FUNCTION(m,"exists",file_kvs_fnc_exists); + KVSM_REGISTER_FUNCTION(m,"type",file_kvs_fnc_type); + KVSM_REGISTER_FUNCTION(m,"size",file_kvs_fnc_size); + + KVSM_REGISTER_FUNCTION(m,"allsizes",file_kvs_fnc_allSizes); + + KVSM_REGISTER_FUNCTION(m,"fixpath",file_kvs_fnc_fixpath); + KVSM_REGISTER_FUNCTION(m,"ps",file_kvs_fnc_ps); + KVSM_REGISTER_FUNCTION(m,"read",file_kvs_fnc_read); + KVSM_REGISTER_FUNCTION(m,"localdir",file_kvs_fnc_localdir); + KVSM_REGISTER_FUNCTION(m,"homedir",file_kvs_fnc_homedir); + KVSM_REGISTER_FUNCTION(m,"rootdir",file_kvs_fnc_rootdir); + KVSM_REGISTER_FUNCTION(m,"cwd",file_kvs_fnc_cwd); + KVSM_REGISTER_FUNCTION(m,"globaldir",file_kvs_fnc_globaldir); + KVSM_REGISTER_FUNCTION(m,"extractpath",file_kvs_fnc_extractpath); + KVSM_REGISTER_FUNCTION(m,"extractfilename",file_kvs_fnc_extractfilename); + KVSM_REGISTER_FUNCTION(m,"ls",file_kvs_fnc_ls); + KVSM_REGISTER_FUNCTION(m,"readLines",file_kvs_fnc_readLines); + + + return true; +} + +static bool file_module_cleanup(KviModule *m) +{ + return true; +} + +KVIRC_MODULE( + "File", // module name + "1.0.0", // module version + "Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net)", // author & (C) + "Interface to the file system", + file_module_init, + 0, + 0, + file_module_cleanup +) |