/****************************************************************************
**
** Copyright (C) 1999-2006 Frank Hemer <frank@hemer.org>,
** Tilo Riemer <riemer@crossvc.com>,
** Wim Delvaux <wim.delvaux@chello.be>,
** Jose Hernandez <joseh@tesco.net>,
** Helmut Koll <HelmutKoll@web.de>,
** Tom Mishima <tmishima@mail.at-m.or.jp>,
** Joerg Preiss <auba@auba.de>
**
**
**----------------------------------------------------------------------------
**
**----------------------------------------------------------------------------
**
** CrossVC is available under two different licenses:
**
** If CrossVC is linked against the GPLed version of Qt
** CrossVC is released under the terms of GPL also.
**
** If CrossVC is linked against a nonGPLed version of Qt
** CrossVC is released under the terms of the
** CrossVC License for non-Unix platforms (CLNU)
**
**
** CrossVC License for non-Unix platforms (CLNU):
**
** Redistribution and use in binary form, without modification,
** are permitted provided that the following conditions are met:
**
** 1. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 2. It is not permitted to distribute the binary package under a name
** different than CrossVC.
** 3. The name of the authors may not be used to endorse or promote
** products derived from this software without specific prior written
** permission.
** 4. The source code is the creative property of the authors.
** Extensions and development under the terms of the Gnu Public License
** are limited to the Unix platform. Any distribution or compilation of
** the source code against libraries licensed other than gpl requires
** the written permission of the authors.
**
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**
**
** CrossVC License for Unix platforms:
**
** 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, version 2 of the License.
** 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 version 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#define DEFINE_GLOBALS
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time_ac.h>
#include <unistd.h>
//----------------------------------------------------------------------------
#include <qfile.h>
#include <qdir.h>
#include <qtextstream.h>
#include <qdialog.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qobject.h>
#include <qbutton.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <qapplication.h>
#include <qmessagebox.h>
#include <qregexp.h>
//----------------------------------------------------------------------------
#include "globals.h"
#include "wrapper.h"
#include "TextCodec.h"
#include "TextDecoder.h"
#include "TextEncoder.h"
#ifdef USE_FAM
#include "FamConnector.h"
#endif
#ifdef USE_WINNT_DIRMON
#include "WinNtConnector.h"
#endif
#ifdef USE_DNOTIFY
#include "DNotifyConnector.h"
#endif
//----------------------------------------------------------------------------
int sshPid = -1;
//----------------------------------------------------------------------------
void initGlobals() {
WINVERSION = 0;
determineTimeZoneDiff();
projectSettings = new ProjectSettings();
LookAndFeel::g_modalF = Qt::WType_Dialog|Qt::WStyle_DialogBorder|Qt::WStyle_SysMenu|Qt::WStyle_MinMax|Qt::WStyle_ContextHelp;
LookAndFeel::g_nonModalF = Qt::WType_TopLevel|Qt::WStyle_SysMenu|Qt::WStyle_MinMax|Qt::WStyle_ContextHelp;
Dialog::g_showWarning = true;
}
//----------------------------------------------------------------------------
const QString CvsOptions::cmprStr()
{
if (CvsOptions::g_compression > 0) {
QString compressionStr = "-z%1";
return compressionStr.arg(CvsOptions::g_compression);
} else return "";
}
//----------------------------------------------------------------------------
void determineTimeZoneDiff()
{
timeZoneDiffInSecs = 0;
struct tm *result = NULL;
time_t t_loc = time(0);
result = localtime(&t_loc);
if (result) {//the difference to UTC without daylight diff
#ifdef USE_TM_GMTOFF
timeZoneDiffInSecs = -(result->tm_gmtoff);
#else
timeZoneDiffInSecs = timezone;
#endif
}
TIMEZERO.setTime_t(0);//ATTENTION: this is different from QDateTime()
}
//----------------------------------------------------------------------------
bool isInCvsPass(QString cvsRoot)
{
QString method;
QString user;
QString passwd;
QString host;
int port;
QString rootDir;
extractCVSROOT( cvsRoot, method, user, passwd, host, port, rootDir);
QString cvsRootNoPort = cvsRoot;
if (port == 2401) {//only compare with portless root if default port
cvsRootNoPort.replace( QRegExp(":"+QString::number(port)),":");//remove port to compare with entries
} else {
port = -1;
}
if (CVSVERSION == "cvs") {
QFile f;
QString line;
//read .cvspass
f.setName(CVSPASSPATH);
if(f.open(IO_ReadOnly)) {//file is readable
QTextStream textStream(&f);
while(!textStream.atEnd()) {
line = textStream.readLine();
line = line.replace( QRegExp(":"+QString::number(port)),":");//remove port to compare with entries
if(line.find(cvsRootNoPort) != -1) {
f.close();
return true;
}
}
f.close();
}
} else if (CVSVERSION == "cvsnt") {
QFile f;
QString line;
//read ~/.cvs/cvspass
f.setName(QDir::homeDirPath()+"/.cvs/cvspass");
if(f.open(IO_ReadOnly)) {//file is readable
QTextStream textStream(&f);
while(!textStream.atEnd()) {
line = textStream.readLine();
line = line.replace( QRegExp(":"+QString::number(port)+":"),":");//remove port to compare with entries
if(line.find(cvsRootNoPort) != -1) {
f.close();
return true;
}
}
f.close();
}
} else if (WINVERSION) {
QString rootKey = "Software\\Cvsnt";
QString subKey = "cvspass";
}
return false;
}
//----------------------------------------------------------------------------
bool writeToCvsPassFile(const QString& cvsRoot, const QString& pwd) {
// restrictive umask
mode_t oldMask = umask(0077);
if (CVSVERSION == "cvs") {
QFile f;
QString line = cvsRoot+" "+pwd+"\n";
f.setName(CVSPASSPATH);
if(f.open(IO_WriteOnly | IO_Append)) {
QTextStream textStream(&f);
textStream << line;
f.flush();
f.close();
chmod(CVSPASSPATH.ascii(),0600); // little paranoia always makes sense
umask(oldMask);
return true;
}
} else if (CVSVERSION == "cvsnt") {
QFile f;
QString line = cvsRoot+"="+pwd+"\n";
f.setName(QDir::homeDirPath()+"/.cvs/cvspass");
if(f.open(IO_WriteOnly | IO_Append)) {
QTextStream textStream(&f);
textStream << line;
f.flush();
f.close();
chmod(CVSPASSPATH.ascii(),0600); // little paranoia always makes sense
umask(oldMask);
return true;
}
}
umask(oldMask);
return false;
}
//----------------------------------------------------------------------------
bool removeFromCvsPassFile( QString cvsRoot) {
QString method;
QString user;
QString passwd;
QString host;
int port;
QString rootDir;
extractCVSROOT( cvsRoot, method, user, passwd, host, port, rootDir);
QString cvsRootNoPort = cvsRoot;
cvsRootNoPort.replace( QRegExp(":"+QString::number(port)),":");//remove port to compare with entries
// restrictive umask
mode_t oldMask = umask(0077);
if (CVSVERSION == "cvs") {
QStringList list;
QString line;
QFile f;
bool found = false;
f.setName(CVSPASSPATH);
if(f.open(IO_ReadOnly)) {
QTextStream textStream(&f);
while(!textStream.atEnd()) {
line = textStream.readLine();
line = line.replace( QRegExp(":"+QString::number(port)),":");//remove port to compare with entries
if (line.startsWith(cvsRootNoPort)) {
found = true;
continue;
}
list.append(line);
}
f.close();
if (!found) {
umask(oldMask);
return false;
}
f.remove();
if (f.open(IO_WriteOnly)) {
QTextStream newTextStream(&f);
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
newTextStream << (*it);
newTextStream << "\n";
}
f.flush();
f.close();
chmod(CVSPASSPATH.ascii(),0600); // little paranoia always makes sense
}
}
umask(oldMask);
return true;
} else if (CVSVERSION == "cvsnt") {
QStringList list;
QString line;
QFile f;
bool found = false;
f.setName(QDir::homeDirPath()+"/.cvs/cvspass");
if(f.open(IO_ReadOnly)) {
QTextStream textStream(&f);
while(!textStream.atEnd()) {
line = textStream.readLine();
line = line.replace( QRegExp(":"+QString::number(port)+":"),":");//remove port to compare with entries
if (line.startsWith(cvsRootNoPort)) {
found = true;
continue;
}
list.append(line);
}
f.close();
if (!found) {
umask(oldMask);
return false;
}
f.remove();
if (f.open(IO_WriteOnly)) {
QTextStream newTextStream(&f);
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
newTextStream << (*it);
newTextStream << "\n";
}
f.flush();
f.close();
chmod(CVSPASSPATH.ascii(),0600); // little paranoia always makes sense
}
}
umask(oldMask);
return true;
}
umask(oldMask);
return false;
}
//----------------------------------------------------------------------------
bool extractCVSROOT( QString rootline,
QString& method,
QString& user,
QString& passwd,
QString& host,
int& port,
QString& path) {
/* Access method specified, as in
* "cvs -d :(gserver|kserver|pserver|sspi)[;params...]:[[[user][:password]@]host[:[port]]]/path",
* "cvs -d [:(ext|server)[;params...]:][[[user]@]host[:]]/path",
* "cvs -d :local[;params...]:e:\path",
* "cvs -d :fork[;params...]:/path".
*
* Note that path for connecting to a cvs-winnt server might be something like:
* "/d//somepath/cvs"
*/
method = QString::null;
user = QString::null;
passwd = QString::null;
host = QString::null;
port = -1;
path = QString::null;
int from, to;
int atpos;
QString tmpStr;
//method
if (rootline.at(0) == ':') {
from = 1;
to = rootline.find(':',from);
if (to == -1) return false;//syntax error
method = rootline.mid((unsigned int)from,(unsigned int)(to-from));
rootline = rootline.mid((unsigned int)(to+1));
//extract additional options, separated by ';'
QStringList optList = QStringList::split(";", method);
method = optList[0];
QStringList::Iterator it = optList.begin();
while (++it != optList.end()) {
int pos = (*it).find('=');
if (pos > -1) {
QString keyword = (*it).left(pos);
QString value = (*it).mid(pos+1);
if (keyword == "username" || keyword == "user") {
user = value;
} else if (keyword == "password" || keyword == "pass") {
passwd = value;
} else if (keyword == "hostname" || keyword == "host") {
host = value;
if (port == -1) port = 2401;
} else if (keyword == "port") {
port = value.toInt();
} else if (keyword == "directory" || keyword == "path") {
path = value;
} else {
qDebug("ignoring CVSROOT option: '"+keyword+"="+value+"'");
}
} else {
qDebug("Invalid option in CVSROOT: '"+(*it));
}
}
} else if ( (rootline.at((unsigned int)0) != '/') && (rootline.contains('/')) ) {
method = "ext";
} else {
method = "local";
}
if ( (method == "local") || (method == "fork")) {
if ( rootline.find(':') > 1) return false;
path = rootline;
return true;
}
//path
from = rootline.find('/');
if (from >= 0) {//cvs server running on UNIX
path = rootline.mid((unsigned int)from);
rootline.truncate((unsigned int)from);
} else {//cvsnt server running on winXX
from = rootline.find('\\');
if (from > 2) {//path found. it can contain a drive letter ... I love win ;-)
if (rootline[from-2].isLetter() &&
(rootline[from-1] == ':') &&
(rootline[from-3] == ':')) from -= 2;
path = rootline.mid((unsigned int)from);
rootline.truncate((unsigned int)from);
} else return false;
}
//user:password@
atpos = rootline.find('@');
if (atpos >= 0) {
to = rootline.findRev(':',atpos-1-rootline.length());
if (to >= 0) {
user = rootline.mid((unsigned int)0,(unsigned int)to);
passwd = rootline.mid((unsigned int)(to+1),(unsigned int)(atpos-to-1));
if (passwd.isEmpty()) return false;
if (user.isEmpty()) user = getenv("USER");
} else {
user = rootline.mid((unsigned int)0,(unsigned int)atpos);
}
if (user.isEmpty()) return false;//no user
}
rootline = rootline.mid((unsigned int)(atpos+1));
//host:port
if (host.isNull()) {
from = rootline.find(':');
to = rootline.find(':',from+1);
if (from == -1) {
host = rootline;
port = 2401;
} else if (to == -1) {
tmpStr = rootline.mid((unsigned int)(from+1));
if (tmpStr.isEmpty()) {
port = 2401;
} else {
port = tmpStr.toInt();
}
} else {
port = rootline.mid((unsigned int)(from+1),(unsigned int)(to-from-1)).toInt();
}
host = rootline.mid((unsigned int)0,(unsigned int)from);
}
if (host.isEmpty()) return false;//no host
if (port == 0) return false;//no number ie. syntax error
return true;
}
//----------------------------------------------------------------------------
int analyzeCVSROOT( QString& method,
QString& user,
QString& passwd,
QString& host,
int& port,
QString& path) {
QString line = getenv("CVSROOT");
if (!line.isEmpty()) {
bool retVal = extractCVSROOT(line, method, user, passwd, host, port, path);
if (user.isNull()) user = getenv("USER");
return retVal;
} else {
return false;
}
}
//----------------------------------------------------------------------------
int validateCVSROOT( QString rootline) {
QString method;
QString user;
QString passwd;
QString host;
int port;
QString path;
if (!extractCVSROOT(rootline,method,user,passwd,host,port,path)) return -1;
/*TODO: add real implementation*/
return 0;
}
//----------------------------------------------------------------------------
void removeDoubleSlashes(QString& s)
{
int pos;
while ( (pos = s.find("//")) > -1) s.replace(pos, 2, "/");
}
//----------------------------------------------------------------------------
void startSshAgent() {
bool useAgent = true;
if (bUseSshAgentVars) {
QString envValue;
if ( envValue=getenv("SSH_AUTH_SOCK")) {
envSSH_AUTH_SOCK = "SSH_AUTH_SOCK=" + envValue;
} else if ( envValue=getenv("SSH2_AUTH_SOCK")) {
envSSH_AUTH_SOCK = "SSH2_AUTH_SOCK=" + envValue;
} else {
useAgent = false;
}
if ( envValue=getenv("SSH_AGENT_PID")) {
envSSH_AGENT_PID = "SSH_AGENT_PID=" + envValue;
} else if ( envValue=getenv("SSH2_AGENT_PID")) {
envSSH_AGENT_PID = "SSH2_AGENT_PID=" + envValue;
} else {
useAgent = false;
}
if (useAgent) {
sshAgentIsRunning = true;
return;
} else if (sshPid > 0) {
return;
}
}
QString sh = ExtApps::g_sshAgent.path;
if (!sh.startsWith("/")) {
sh = APPDIR + "/" + LC_TOOLS_DIR + "/" + sh;
}
QString options = ExtApps::g_sshAgent.options;
masqedFilenamesForPlaceholders(options, ExtApps::g_sshKeyFiles);
QStringList args = QStringList::split("\" \"",umasqWs(options));
args.prepend(sh);
#ifdef Q_WS_MAC
QString askpass = APPDIR + "/" + LC_TOOLS_DIR + "/ssh-askpass.app/Contents/MacOS/ssh-askpass";
#else
QString askpass = APPDIR + "/" + LC_TOOLS_DIR + "/ssh-askpass.bin";
#endif
QStringList * env = NULL;
sshProc = new QProcess();
sshProc->setArguments(args);
if (QFileInfo(askpass).exists()) {
env = new QStringList();
QString tmpEnv;
QString tmpVar;
tmpVar = "DISPLAY";
tmpEnv = getenv(tmpVar);
if (tmpEnv.length() > 0) {
env->append(tmpVar+"="+tmpEnv);
#ifdef Q_WS_MAC
} else {
env->append(tmpVar+"=:0.0");
#endif
}
tmpVar = "PATH";
tmpEnv = getenv(tmpVar);
if (tmpEnv.length() != 0) {
env->append(tmpVar+"="+tmpEnv);
}
tmpVar = "HOME";
tmpEnv = getenv(tmpVar);
if (tmpEnv.length() != 0) {
env->append(tmpVar+"="+tmpEnv);
}
env->append("SSH_ASKPASS="+askpass);
}
if (sshProc->start(env)) {
while (sshProc->isRunning()) {
wait(100);
qApp->processEvents();
if (globalStopAction) sshProc->kill();
}
if ( (sshProc->normalExit()) && (sshProc->exitStatus() == 0) ) {
sshAgentStarted = true;
} else {
checkSshAgent();
killSshAgent();
}
} else {
qDebug("couldn't start proc: ->"+sh+"<-");
}
delete sshProc;
sshProc = 0;
}
//----------------------------------------------------------------------------
void checkSshAgent() {
QFile f;
QString line;
//now read the environment file and ascertain the PID of ssh-agent
f.setName(QDir::homeDirPath() + "/.ssh/lincvs-environment");
int tPid = -1;
sshAuthSock = "";
if(f.open(IO_ReadOnly)) {//file is readable
QTextStream textStream(&f);
while(!textStream.atEnd()) {
line = textStream.readLine();
if (line.find("setenv SSH_AUTH_SOCK ") == 0) {
QString tmp = line.mid(21);
envSSH_AUTH_SOCK = "SSH_AUTH_SOCK=" + tmp.left(tmp.find(";"));
} else if(line.contains("_AUTH_SOCK=") > 0) {//SSH or SSH2
envSSH_AUTH_SOCK = line.left(line.find(";"));
}
if (line.find("setenv SSH_AGENT_PID ") == 0) {
QString tmp = line.mid(21, 20);
QChar ch;
ch = tmp[0];
unsigned int ch_pos = 0;
while (ch.isDigit() && (tmp.length() > ch_pos)) {
ch_pos++;
ch = tmp.at(ch_pos);
}
QString pid = tmp.left(ch_pos);
envSSH_AGENT_PID = "SSH_AGENT_PID="+pid;
tPid = pid.toInt();
} else if(line.contains("_AGENT_PID=") > 0) {//SSH or SSH2
envSSH_AGENT_PID = line.left(line.find(";"));
QString pid = envSSH_AGENT_PID.mid(envSSH_AGENT_PID.find("=")+1);
tPid = pid.toInt();
}
}
}
if (tPid > 0 && (!envSSH_AUTH_SOCK.isEmpty())) {
if (sshPid == -1) sshPid = tPid;
sshAgentIsRunning = true;
} else {
killSshAgent();
sshAgentIsRunning = false;
}
}
//----------------------------------------------------------------------------
void killSshAgent() {
if (sshPid > 0) {
QString pid;
pid.setNum(sshPid);
if (system("kill " + pid)) qDebug("kill ssh agent pid: "+QString::number(sshPid)+" failed");
QString fileName = QDir::homeDirPath() + "/.ssh/lincvs-environment";
if (!QFile::remove(fileName)) {
qDebug("Kill ssh agent: couldn't remove environment:\n"+fileName);
}
sshAgentIsRunning = false;
sshAgentStarted = false;
sshPid = -1;
}
}
//----------------------------------------------------------------------------
QString writeTmpFile(QString text)
{
QString fname = createTempFile();
if (fname.length()) {
QFile file(fname);
if (file.open(IO_WriteOnly)) {
QTextStream s(&file); // serialize using f
s.setCodec(I18n::g_pTextEncoder->pTextCodecPool()->pCodecForName(I18n::g_nameOfEncoder));
s << text; // serialize string
}
file.close();
}
return fname;
}
//----------------------------------------------------------------------------
void writeUserHstFile(QString text)
{
QString fname = createHistoryFile();
if (fname.length()) {
QFile file(fname);
if (file.open(IO_WriteOnly)) { // open file for writing
QTextStream s(&file); // serialize using f
s.setCodec(I18n::g_pTextEncoder->pTextCodecPool()->pCodecForName(I18n::g_nameOfEncoder));
s << text; // serialize string
}
file.close();
}
}
//----------------------------------------------------------------------------
QString readTextFile(QString fn)
{
QFile f(fn);
QString str = "";
if (f.open(IO_ReadOnly)) {
QTextStream ts(&f);
ts.setCodec(I18n::g_pTextDecoder->pTextCodecPool()->pCodecForName(I18n::g_nameOfDecoder));
QString line;
while(!ts.eof()) {
line = ts.readLine();
str += line + "\n";
}
f.close();
}
return str;
}
//----------------------------------------------------------------------------
QString readDefaultTemplateFile()
{
return readTextFile(tmpDir + "/Template/rcsinfo");
}
//----------------------------------------------------------------------------
void writeDefaultTemplateFile(QString text)
{
QFile rcsFile(tmpDir + "/Template/rcsinfo");
if (text.isEmpty()) {//no text for template --> remove rcsinfo
if (rcsFile.exists()) rcsFile.remove();
} else {//we have some text --> write it into rcsinfo
createTemplateDir(); //create template dir if necessary
if (rcsFile.open(IO_WriteOnly)) {
QTextStream s(&rcsFile); // serialize using f
s.setCodec(I18n::g_pTextEncoder->pTextCodecPool()->pCodecForName(I18n::g_nameOfEncoder));
s << text; // serialize string
}
rcsFile.close();
}
}
//----------------------------------------------------------------------------
void createTmpDir()
{
// restrictive umask
mode_t oldMask = umask(0077);
QDir home = QDir::home();
QDir tempDir;
Misc::g_bVeryFirstStart = false;
QFileInfo tmp(home, ".crossvc");
if (tmp.exists()) {
if (!tmp.isDir()) {
QFile f(tmp.absFilePath());
f.remove(); //we must check the result of remove!!!
tempDir.mkdir(tmp.absFilePath());
Misc::g_bVeryFirstStart = true;
}
} else {
tempDir.mkdir(tmp.absFilePath());
Misc::g_bVeryFirstStart = true;
}
chmod(tmp.absFilePath(), 0700);
tmpDir = tmp.absFilePath();
umask(oldMask);
}
//----------------------------------------------------------------------------
QString createTempFile(QString appendix /*= QString::null*/)
{
if (!appendix.isNull()) appendix.replace(QRegExp("[\\/<>&\"]"),"_");
QString tmp = tmpDir + "/tmp.XXXXXX";
char* fname = new char[tmp.length() + 1];
strcpy(fname, tmp);
int res = mkstemp(fname);
if (res == -1) {
qDebug("Can't create tempfile: "+QString(fname));
delete [] fname;
return "";
} else if (remove(fname) == -1) {//remove the file because: 1. we only need its name 2. this should be handled as on the win platform
qDebug("Can't remove tempfile: "+QString(fname));
delete [] fname;
return "";
}
QString tmpFile = fname + appendix;
delete [] fname;
if (QFileInfo(tmpFile).exists()) {
qDebug("tempfile exists: "+tmpFile);
return "";
}
return tmpFile;
}
//----------------------------------------------------------------------------
void createTemplateDir()
{
// restrictive umask
mode_t oldMask = umask(0077);
QDir tempDir;
QFileInfo tmp(tmpDir, "Template");
if (tmp.exists()) {
if (!tmp.isDir()) {
QFile f(tmp.absFilePath());
f.remove(); //we must check the result of remove!!!
tempDir.mkdir(tmp.absFilePath());
}
} else tempDir.mkdir(tmp.absFilePath());
chmod(tmp.absFilePath(), 0700);
umask(oldMask);
}
//----------------------------------------------------------------------------
QString createHistoryFile()
{
createTemplateDir();
// restrictive umask
mode_t oldMask = umask(0077);
QString tmpl = tmpDir + "/Template/XXXXXX";
char* fname = new char[tmpl.length() + 1];
strcpy(fname, tmpl);
int file = mkstemp(fname);
QString tmpFile = fname;
delete [] fname;
if (file > -1) {
fchmod(file, 0600);
close(file);
umask(oldMask);
return tmpFile;
}
umask(oldMask);
return "";
}
//----------------------------------------------------------------------------
void runExternal( QString arg, QDir *dir) {
arg = LW::validateEchse(arg);
QString debugStr = "running: " + arg + " in";
if (dir) debugStr += ": " + dir->absPath();
else debugStr += " default dir: "+QDir::currentDirPath();
qDebug(debugStr);
arg += " ";
int S = 1;
int K = 2;
int blocked = 0;
unsigned int i;
unsigned int count = 0;
unsigned int lastPos = 0;
QStringList args;
for (i=0; i<arg.length(); i++) {
if ( arg.at(i) == '\"') {
if (blocked != S) {
count++;
blocked = S;
} else {
count--;
blocked = K;
}
}
if ( arg.mid(i,1) == "'" ) {
if (blocked != K) {
count++;
blocked = K;
} else {
count--;
blocked = S;
}
}
if ( (count == 0) && (arg.at(i) == ' ')) {
QString tmp = arg.mid(lastPos,i-lastPos);
if ( (tmp.startsWith("\"")) || (tmp.startsWith("'")) ) {
tmp = tmp.mid(1);
}
if ( (tmp.endsWith("\"")) || (tmp.endsWith("'")) ) {
tmp = tmp.left(tmp.length()-1);
}
if (!tmp.isEmpty()) {
tmp.replace(PLACEHOLDER_FOR_QUOTATION_MARKS, "\"");
args.append (tmp);
}
lastPos = i+1;
}
}
// for ( QStringList::Iterator it = args.begin(); it != args.end(); ++it ) {
// qDebug("cmd: ->"+(*it)+"<-");
// }
runExternal( args, dir);
}
//----------------------------------------------------------------------------
void runExternal( QStringList args, QDir *dir) {
QProcess proc;
if (dir) {
proc.setWorkingDirectory(*dir);
}
proc.setArguments(args);
if (!proc.start()) {
QString msg;
if (dir) msg += "in dir: ->"+dir->absPath()+"<-, ";
msg += "couldn't start proc: ->"+args.join(" ")+"<-";
qDebug(msg);
}
}
//----------------------------------------------------------------------------
void adaptQStringList(const QString &s, QStringList *list, int size) {
if (s.isEmpty()) {
return;
}
if (list->findIndex(s) == -1) {
//not in list
while ( (list->count() >= (unsigned int)size) && (list->count() > 0)) {
list->remove(--(list->end()));//remove the last element
}
list->prepend(s);
} else if (list->findIndex(s) > 0) {
// text isn't the first item in list
list->remove(s);
list->prepend(s);
}
}
//----------------------------------------------------------------------------
void simplifyStringList(QStringList* pList)
{
QStringList::Iterator it, head;
bool bAllDone = false;
head = pList->begin();
while(!bAllDone) {
it = head;
if (it == pList->end()) {
bAllDone = true;
// qDebug("DONE");
} else {
//qDebug(*head); //the lovely win doesn't like the star before head
QString cur = *it;
it++; //we need the second item
while(it != pList->end()) {
if (*it == cur) {
// qDebug("remove: " + *it);
//remove the multiple entry
it = pList->remove(it);
} else it++;
}
head++;
}
}
// remove empty entries
it = pList->begin();
while(it != pList->end()) {
if ((*it).isEmpty()) it = pList->remove(it);
else it++;
}
#ifdef ANY_DEBUG_STUFF
qDebug("StringList: Start");
for (it = pList->begin(); it != pList->end(); it++) {
qDebug(*it);
}
qDebug("simplify StringList: End");
#endif
}
//----------------------------------------------------------------------------
void cutList(QStringList* pList, int allowedSize)
{
int size = pList->count();
int diff = size - allowedSize;
if (diff < 1) {
return;
}
int i;
for (i = 0; i < diff; i++) {
pList->remove(pList->at(size - 1 - i));
}
}
//----------------------------------------------------------------------------
QString masqWs(const QString &str) {
return "\""+str+"\"";
}
//----------------------------------------------------------------------------
QString umasqWs(QString str) {
str = str.stripWhiteSpace();
if (str.startsWith("\"")) {
str.remove(0,1);
}
if (str.endsWith("\"")) {
str.truncate(str.length()-1);
}
return str;
}
//----------------------------------------------------------------------------
void masqQuoteMarks(QStringList *pList)
{
QStringList::Iterator it = pList->begin();
while (it != pList->end()) {
(*it).replace("\"", PLACEHOLDER_FOR_QUOTATION_MARKS);
it++;
}
}
//----------------------------------------------------------------------------
Mapping::FileAppItem getMatchForWildcard(const QStringList& nameList, const Mapping::FileAppList& appList) {
QRegExp rx;
Mapping::FileAppList::ConstIterator appIt;
for ( appIt = appList.begin(); appIt != appList.end(); ++appIt ) {
rx.setWildcard(!(*appIt).isRegExp);
rx.setPattern( (*appIt).wildcard);
QStringList::ConstIterator nameIt;
bool match = TRUE;
for ( nameIt = nameList.begin(); nameIt != nameList.end(); ++nameIt ) {
if (!rx.exactMatch( (*nameIt))) {
match = FALSE;
break;
}
}
if (match) {
return Mapping::FileAppItem((*appIt));
}
}
Mapping::FileAppItem item;
item.wildcard = "";
item.app = "";
item.params = "";
item.isRegExp = FALSE;
return item;
}
//----------------------------------------------------------------------------
QString validateOptions(const QString options)
{
QString newOps = options;
if (options.find(QRegExp("%([0-9]|n)")) < 0) newOps += " %n";
//printf("%d\n", options.find(QRegExp("%([0-9]|n)")));
return newOps;
}
//----------------------------------------------------------------------------
void openUrlWithRemoteBrowser(const QString url)
{
QStringList urlList;
urlList.append(url);
openUrlsWithRemoteBrowser(urlList);
}
//----------------------------------------------------------------------------
void openUrlsWithRemoteBrowser(const QStringList urlList)
{
QString cmd = "\"" + ExtApps::g_remoteBrowser.path +"\" ";
QString options = ExtApps::g_remoteBrowser.options;
options = validateOptions(options);
masqedFilenamesForPlaceholders(options, urlList);
cmd += options;
runExternal(cmd);
}
//----------------------------------------------------------------------------
bool masqedFilenamesForPlaceholders(QString& params, const QStringList& nameList) {
unsigned int oldSize = params.length();
int pos = 0;
while ( (pos = params.find("%",pos)) > -1) {
++pos;
unsigned int i = 0;
while ( (params.length() > ((unsigned)pos)+i) && (params.at(((unsigned)pos)+i).isDigit()) ) i++;
if (i>0) {
QString exp = params.mid(pos,i);
int namePos = exp.toInt()-1;
if ( (namePos > -1) && (nameList.count() > (unsigned)namePos) ) {
params.replace(QRegExp("%"+params.mid(pos,i)),"\""+nameList[namePos]+"\"");
}
}
}
QString allFiles = nameList.join("\" \"");
params.replace(QRegExp("%n"),"\""+allFiles+"\"");
if (oldSize<params.length()) return TRUE;
else return FALSE;
}
//----------------------------------------------------------------------------
bool setPermission(const QFile& file, int perm) {
if (perm <= 7) {
perm = perm << 6;
struct stat buf;
if (!stat(file.name().latin1(),&buf)) {//only change owner permissions
mode_t mode = buf.st_mode & (S_IRWXG | S_IRWXO);
perm += mode;
} else {
return false;
}
}
if (!chmod( file.name().latin1(),perm)) {
return true;
}
return false;
}
//----------------------------------------------------------------------------
bool rename(const QString& src, const QString& dst) {
QFile f(src);
bool readonly = false;
if (!QFileInfo(f).isWritable()) {
if (!setPermission(f,READABLE | WRITEABLE)) {
return false;
}
readonly = true;
}
if (rename(src.latin1(),dst.latin1())) {
return false;
}
if (readonly) {
f.setName(dst);
if (!setPermission(f,READABLE)) {
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
//return proxystring if available
//settings should be entered like:
//user@my.remote.server::otheruser@my.proxy.server
//where user and otheruser are optional
QString getProxy(const QString& userAtHost) {
QString host = userAtHost.mid(userAtHost.find("@")+1);
QString proxy;
for (QStringList::Iterator proxyit = proxyList.begin(); proxyit != proxyList.end(); proxyit++) {
if ( (*proxyit).startsWith(userAtHost)) {
proxy = (*proxyit);
break;
}
}
if (proxy.isEmpty()) {//no proxy found, try again without user spec
for (QStringList::Iterator proxyit = proxyList.begin(); proxyit != proxyList.end(); proxyit++) {
if ( (*proxyit).startsWith(host)) {
proxy = (*proxyit);
break;
}
}
}
if (!proxy.isEmpty()) {
int splitPos;
if ( (splitPos=proxy.find("::")) >= 0) {
proxy = proxy.mid(splitPos+2);
int etpos;
if ( (etpos=proxy.find("@"))>=0) {
proxy = proxy.mid(etpos+1);
}
return proxy.stripWhiteSpace();
}
}
return "";
}
//----------------------------------------------------------------------------
void wait(int usecs) {
#ifdef NANOSLEEP
struct timespec req;
req.tv_sec = usecs / 1000000;
req.tv_nsec = (usecs % 1000000) * 1000;
nanosleep(&req,NULL);
#else
usleep(usecs);
#endif
}
//----------------------------------------------------------------------------
QString getSystemLF() {
return "\n";
}
//----------------------------------------------------------------------------
void I18n::init()
{
CTextCodecPool* pTextCodecPool = new CTextCodecPool();
I18n::g_pTextDecoder = new CMetaTextDecoder(pTextCodecPool);
I18n::g_pTextDecoder->setGeneralDecoder(I18n::g_nameOfDecoder);
I18n::g_pTextEncoder = new CTextEncoder(pTextCodecPool);
I18n::g_pTextEncoder->setEncoder(I18n::g_nameOfEncoder);
}
//----------------------------------------------------------------------------
void I18n::destroy()
{
CTextCodecPool* pTextCodecPool = I18n::g_pTextDecoder->pTextCodecPool();
delete I18n::g_pTextDecoder;
I18n::g_pTextDecoder = 0;
delete I18n::g_pTextEncoder;
I18n::g_pTextEncoder = 0;
delete pTextCodecPool;
}
//----------------------------------------------------------------------------
bool initMonitoring() {
fc = NULL;
m_hasDirWatch = FALSE;
DirWatch::b_isActive = FALSE;
#ifdef USE_FAM
m_hasDirWatch = true;
if ( DirWatch::b_useDirWatch) {
if ((fc = new FamConnector()) && fc->isRunning()) {
DirWatch::b_isActive = true;
} else {
qDebug("init fam failed");
}
}
#endif
#ifdef USE_DNOTIFY
m_hasDirWatch = true;
if ( DirWatch::b_useDirWatch) {
if ((fc = new DNotifyConnector()) && fc->isRunning()) {
DirWatch::b_isActive = true;
} else {
qDebug("init dnotify failed");
}
}
#endif
return DirWatch::b_isActive;
}
DirConnector* getDirConnector() {
return fc;
}
bool hasDirWatch() {
return m_hasDirWatch;
}
void releaseMonitoring() {
if (fc) {
DirWatch::b_isActive = false;
delete fc;
fc = NULL;
}
}
//----------------------------------------------------------------------------
bool addMonitoredDir(DirBase * dir) {
if (!DirWatch::b_isActive) return FALSE;
bool added = fc->addMonitoredDir( dir);
if (!added) {
releaseMonitoring(); //hope it works here
}
return added;
}
//----------------------------------------------------------------------------
void releaseMonitoredDir(DirBase * dir) {
if (!DirWatch::b_isActive) return;
fc->releaseMonitoredDir( dir);
return;
}
//----------------------------------------------------------------------------
DirBase* checkMonitoredEvent(QString& fileName,bool& deleted) {
if (!DirWatch::b_isActive) return NULL;
return fc->checkEvent(fileName,deleted);
}
void suspendDirWatch() {
if (!DirWatch::b_isActive) return;
fc->suspend();
}
void resumeDirWatch() {
if (!DirWatch::b_isActive) return;
fc->resume();
}
void lockDirWatch() {
if (!DirWatch::b_isActive) return;
fc->lock();
}
void unlockDirWatch() {
if (!DirWatch::b_isActive) return;
fc->unlock();
}
syntax highlighted by Code2HTML, v. 0.9.1