summaryrefslogtreecommitdiffstats
path: root/kioslave/fish/fish.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-01-27 01:02:02 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-01-27 01:02:02 -0600
commitde7e5867a65e0a46f1388e3e50bc7eeddd1aecbf (patch)
treedbb3152c372f8620f9290137d461f3d9f9eba1cb /kioslave/fish/fish.cpp
parent936d3cec490c13f2c5f7dd14f5e364fddaa6da71 (diff)
downloadtdebase-de7e5867a65e0a46f1388e3e50bc7eeddd1aecbf.tar.gz
tdebase-de7e5867a65e0a46f1388e3e50bc7eeddd1aecbf.zip
Rename a number of libraries and executables to avoid conflicts with KDE4
Diffstat (limited to 'kioslave/fish/fish.cpp')
-rw-r--r--kioslave/fish/fish.cpp1661
1 files changed, 0 insertions, 1661 deletions
diff --git a/kioslave/fish/fish.cpp b/kioslave/fish/fish.cpp
deleted file mode 100644
index 3a527e39e..000000000
--- a/kioslave/fish/fish.cpp
+++ /dev/null
@@ -1,1661 +0,0 @@
-/***************************************************************************
- fish.cpp - a FISH kioslave
- -------------------
- begin : Thu Oct 4 17:09:14 CEST 2001
- copyright : (C) 2001-2003 by J�rg Walter
- email : jwalt-kde@garni.ch
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * 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 code contains fragments and ideas from the ftp kioslave
- done by David Faure <faure@kde.org>.
-
- Structure is a bit complicated, since I made the mistake to use
- TDEProcess... now there is a lightweight homebrew async IO system
- inside, but if signals/slots become available for ioslaves, switching
- back to TDEProcess should be easy.
-*/
-
-#include "config.h"
-
-#include <tqcstring.h>
-#include <tqfile.h>
-#include <tqsocket.h>
-#include <tqdatetime.h>
-#include <tqbitarray.h>
-#include <tqregexp.h>
-
-#include <stdlib.h>
-#ifdef HAVE_PTY_H
-#include <pty.h>
-#endif
-#ifdef HAVE_TERMIOS_H
-#include <termios.h>
-#endif
-#include <math.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/types.h>
-#ifdef HAVE_STROPTS
-#include <stropts.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LIBUTIL_H
-#include <libutil.h>
-#endif
-#ifdef HAVE_UTIL_H
-#include <util.h>
-#endif
-
-#include <kdebug.h>
-#include <kmessagebox.h>
-#include <kinstance.h>
-#include <kglobal.h>
-#include <kstandarddirs.h>
-#include <klocale.h>
-#include <kremoteencoding.h>
-#include <kurl.h>
-#include <ksock.h>
-#include <stdarg.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <kmimetype.h>
-#include <kmimemagic.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <sys/resource.h>
-
-#include "fish.h"
-#include "fishcode.h"
-
-#ifndef NDEBUG
-#define myDebug(x) kdDebug(7127) << __LINE__ << ": " x
-#define connected() do{myDebug( << "_______ emitting connected()" << endl); connected();}while(0)
-#define dataReq() do{myDebug( << "_______ emitting dataReq()" << endl); dataReq();}while(0)
-#define needSubURLData() do{myDebug( << "_______ emitting needSubURLData()" << endl); needSubURLData();}while(0)
-#define slaveStatus(x,y) do{myDebug( << "_______ emitting slaveStatus(" << x << ", " << y << ")" << endl); slaveStatus(x,y);}while(0)
-#define statEntry(x) do{myDebug( << "_______ emitting statEntry("<<x.size()<<")" << endl); statEntry(x);}while(0)
-#define listEntries(x) do{myDebug( << "_______ emitting listEntries(...)" << endl); listEntries(x);}while(0)
-#define canResume(x) do{myDebug( << "_______ emitting canResume("<<(int)x<<")" << endl); canResume(x);}while(0)
-#define totalSize(x) do{myDebug( << "_______ emitting totalSize("<<(int)x<<")" << endl); totalSize(x);}while(0)
-#define processedSize(x) do{myDebug( << "_______ emitting processedSize("<<x<<")" << endl); processedSize(x);}while(0)
-#define speed(x) do{myDebug( << "_______ emitting speed("<<(int)x<<")" << endl); speed(x);}while(0)
-#define redirection(x) do{myDebug( << "_______ emitting redirection("<<x<<")" << endl); redirection(x);}while(0)
-#define errorPage() do{myDebug( << "_______ emitting errorPage()" << endl); errorPage();}while(0)
-#define sendmimeType(x) do{myDebug( << "_______ emitting mimeType("<<x<<")" << endl); mimeType(x);}while(0)
-#define warning(x) do{myDebug( << "_______ emitting warning("<<x<<")" << endl); warning(x);}while(0)
-#define infoMessage(x) do{myDebug( << "_______ emitting infoMessage("<<x<<")" << endl); infoMessage(x);}while(0)
-#else
-#define myDebug(x)
-#define sendmimeType(x) mimeType(x)
-#endif
-
-static char *sshPath = NULL;
-static char *suPath = NULL;
-// disabled: currently not needed. Didn't work reliably.
-// static int isOpenSSH = 0;
-
-static int isNXFish = 0;
-
-#define E(x) ((const char*)remoteEncoding()->encode(x).data())
-
-using namespace TDEIO;
-extern "C" {
-
-static void ripper(int)
-{
- while (waitpid(-1,0,WNOHANG) > 0) {
- // do nothing, go on
- }
-}
-
-int KDE_EXPORT kdemain( int argc, char **argv )
-{
- KLocale::setMainCatalogue("kio_fish");
- TDEInstance instance("fish");
-
- myDebug( << "*** Starting fish " << endl);
- if (argc != 4) {
- myDebug( << "Usage: fish protocol domain-socket1 domain-socket2" << endl);
- exit(-1);
- }
-
- setenv("TZ", "UTC", true);
-
- struct sigaction act;
- memset(&act,0,sizeof(act));
- act.sa_handler = ripper;
- act.sa_flags = 0
-#ifdef SA_NOCLDSTOP
- | SA_NOCLDSTOP
-#endif
-#ifdef SA_RESTART
- | SA_RESTART
-#endif
- ;
- sigaction(SIGCHLD,&act,NULL);
-
- if (qstrcmp(argv[1],"nxfish")==0) {
- // Set NXFish - Mode
- isNXFish=1;
- }
-
- fishProtocol slave(argv[2], argv[3]);
- slave.dispatchLoop();
-
- myDebug( << "*** fish Done" << endl);
- return 0;
-}
-
-}
-
-const struct fishProtocol::fish_info fishProtocol::fishInfo[] = {
- { ("FISH"), 0,
- ("echo; /bin/sh -c start_fish_server > /dev/null 2>/dev/null; perl .fishsrv.pl " CHECKSUM " 2>/dev/null; perl -e '$|=1; print \"### 100 transfer fish server\\n\"; while(<STDIN>) { last if /^__END__/; $code.=$_; } exit(eval($code));' 2>/dev/null;"),
- 1 },
- { ("VER 0.0.3 copy append lscount lslinks lsmime exec stat"), 0,
- ("echo 'VER 0.0.3 copy append lscount lslinks lsmime exec stat'"),
- 1 },
- { ("PWD"), 0,
- ("pwd"),
- 1 },
- { ("LIST"), 1,
- ("echo `ls -Lla %1 2> /dev/null | grep '^[-dsplcb]' | wc -l`; ls -Lla %1 2>/dev/null | grep '^[-dspl]' | ( while read -r p x u g s m d y n; do file -b -i $n 2>/dev/null | sed -e '\\,^[^/]*$,d;s/^/M/;s,/.*[ \t],/,'; FILE=%1; if [ -e %1\"/$n\" ]; then FILE=%1\"/$n\"; fi; if [ -L \"$FILE\" ]; then echo \":$n\"; ls -lad \"$FILE\" | sed -e 's/.* -> /L/'; else echo \":$n\" | sed -e 's/ -> /\\\nL/'; fi; echo \"P$p $u.$g\nS$s\nd$m $d $y\n\"; done; );"
- "ls -Lla %1 2>/dev/null | grep '^[cb]' | ( while read -r p x u g a i m d y n; do echo \"P$p $u.$g\nE$a$i\nd$m $d $y\n:$n\n\"; done; )"),
- 0 },
- { ("STAT"), 1,
- ("echo `ls -dLla %1 2> /dev/null | grep '^[-dsplcb]' | wc -l`; ls -dLla %1 2>/dev/null | grep '^[-dspl]' | ( while read -r p x u g s m d y n; do file -b -i $n 2>/dev/null | sed -e '\\,^[^/]*$,d;s/^/M/;s,/.*[ \t],/,'; FILE=%1; if [ -e %1\"/$n\" ]; then FILE=%1\"/$n\"; fi; if [ -L \"$FILE\" ]; then echo \":$n\"; ls -lad \"$FILE\" | sed -e 's/.* -> /L/'; else echo \":$n\" | sed -e 's/ -> /\\\nL/'; fi; echo \"P$p $u.$g\nS$s\nd$m $d $y\n\"; done; );"
- "ls -dLla %1 2>/dev/null | grep '^[cb]' | ( while read -r p x u g a i m d y n; do echo \"P$p $u.$g\nE$a$i\nd$m $d $y\n:$n\n\"; done; )"),
- 0 },
- { ("RETR"), 1,
- ("ls -l %1 2>&1 | ( read -r a b c d x e; echo $x ) 2>&1; echo '### 001'; cat %1"),
- 1 },
- { ("STOR"), 2,
- ("> %2; echo '### 001'; ( [ \"`expr %1 / 4096`\" -gt 0 ] && dd bs=4096 count=`expr %1 / 4096` 2>/dev/null;"
- "[ \"`expr %1 % 4096`\" -gt 0 ] && dd bs=`expr %1 % 4096` count=1 2>/dev/null; ) | ( cat > %2 || echo Error $?; cat > /dev/null )"),
- 0 },
- { ("CWD"), 1,
- ("cd %1"),
- 0 },
- { ("CHMOD"), 2,
- ("chmod %1 %2"),
- 0 },
- { ("DELE"), 1,
- ("rm -f %1"),
- 0 },
- { ("MKD"), 1,
- ("mkdir %1"),
- 0 },
- { ("RMD"), 1,
- ("rmdir %1"),
- 0 },
- { ("RENAME"), 2,
- ("mv -f %1 %2"),
- 0 },
- { ("LINK"), 2,
- ("ln -f %1 %2"),
- 0 },
- { ("SYMLINK"), 2,
- ("ln -sf %1 %2"),
- 0 },
- { ("CHOWN"), 2,
- ("chown %1 %2"),
- 0 },
- { ("CHGRP"), 2,
- ("chgrp %1 %2"),
- 0 },
- { ("READ"), 3,
- ("echo '### 100';cat %3 /dev/zero | ( [ \"`expr %1 / 4096`\" -gt 0 ] && dd bs=4096 count=`expr %1 / 4096` >/dev/null;"
- "[ \"`expr %1 % 4096`\" -gt 0 ] && dd bs=`expr %1 % 4096` count=1 >/dev/null;"
- "dd bs=%2 count=1; ) 2>/dev/null;"),
- 0 },
- // Yes, this is "ibs=1", since dd "count" is input blocks.
- // On network connections, read() may not fill the buffer
- // completely (no more data immediately available), but dd
- // does ignore that fact by design. Sorry, writes are slow.
- // OTOH, WRITE is not used by the current ioslave methods,
- // we use APPEND.
- { ("WRITE"), 3,
- (">> %3; echo '### 001'; ( [ %2 -gt 0 ] && dd ibs=1 obs=%2 count=%2 2>/dev/null ) | "
- "( dd ibs=32768 obs=%1 seek=1 of=%3 2>/dev/null || echo Error $?; cat >/dev/null; )"),
- 0 },
- { ("COPY"), 2,
- ("if [ -L %1 ]; then if cp -pdf %1 %2 2>/dev/null; then :; else LINK=\"`readlink %1`\"; ln -sf $LINK %2; fi; else cp -pf %1 %2; fi"),
- 0 },
- { ("APPEND"), 2,
- (">> %2; echo '### 001'; ( [ %1 -gt 0 ] && dd ibs=1 obs=%1 count=%1 2> /dev/null; ) | ( cat >> %2 || echo Error $?; cat >/dev/null; )"),
- 0 },
- { ("EXEC"), 2,
- ("UMASK=`umask`; umask 077; touch %2; umask $UMASK; eval %1 < /dev/null > %2 2>&1; echo \"###RESULT: $?\" >> %2"),
- 0 }
-};
-
-fishProtocol::fishProtocol(const TQCString &pool_socket, const TQCString &app_socket)
- : SlaveBase("fish", pool_socket, app_socket), mimeBuffer(1024),
- mimeTypeSent(false)
-{
- myDebug( << "fishProtocol::fishProtocol()" << endl);
- if (sshPath == NULL) {
- // disabled: currently not needed. Didn't work reliably.
- // isOpenSSH = !system("ssh -V 2>&1 | grep OpenSSH > /dev/null");
- if (isNXFish)
- sshPath = strdup(TQFile::encodeName(KStandardDirs::findExe("nxfish")));
- else
- sshPath = strdup(TQFile::encodeName(KStandardDirs::findExe("ssh")));
- }
- if (suPath == NULL) {
- suPath = strdup(TQFile::encodeName(KStandardDirs::findExe("su")));
- }
- childPid = 0;
- connectionPort = 0;
- isLoggedIn = false;
- writeReady = true;
- isRunning = false;
- firstLogin = true;
- errorCount = 0;
- rawRead = 0;
- rawWrite = -1;
- recvLen = -1;
- sendLen = -1;
- setMultipleAuthCaching( true );
- connectionAuth.keepPassword = true;
- connectionAuth.url.setProtocol("fish");
- outBufPos = -1;
- outBuf = NULL;
- outBufLen = 0;
- typeAtom.m_uds = UDS_FILE_TYPE;
- typeAtom.m_long = 0;
- mimeAtom.m_uds = UDS_MIME_TYPE;
- mimeAtom.m_long = 0;
- mimeAtom.m_str = TQString::null;
-
- hasAppend = false;
-
- isStat = false; // FIXME: just a workaround for konq deficiencies
- redirectUser = ""; // FIXME: just a workaround for konq deficiencies
- redirectPass = ""; // FIXME: just a workaround for konq deficiencies
- fishCodeLen = strlen(fishCode);
-}
-/* ---------------------------------------------------------------------------------- */
-
-
-fishProtocol::~fishProtocol()
-{
- myDebug( << "fishProtocol::~fishProtocol()" << endl);
- shutdownConnection(true);
-}
-
-/* --------------------------------------------------------------------------- */
-
-/**
-Connects to a server and logs us in via SSH. Then starts FISH protocol.
-*/
-void fishProtocol::openConnection() {
- if (childPid) return;
-
- if (connectionHost.isEmpty() && !isNXFish)
- {
- error( TDEIO::ERR_UNKNOWN_HOST, TQString::null );
- return;
- }
-
- infoMessage(i18n("Connecting..."));
-
- myDebug( << "connecting to: " << connectionUser << "@" << connectionHost << ":" << connectionPort << endl);
- sendCommand(FISH_FISH);
- sendCommand(FISH_VER);
- if (connectionStart()) {
- error(ERR_COULD_NOT_CONNECT,connectionHost);
- shutdownConnection();
- return;
- };
- myDebug( << "subprocess is running" << endl);
-}
-
-static int open_pty_pair(int fd[2])
-{
-#if defined(HAVE_TERMIOS_H) && defined(HAVE_GRANTPT) && !defined(HAVE_OPENPTY)
-/** with kind regards to The GNU C Library
-Reference Manual for Version 2.2.x of the GNU C Library */
- int master, slave;
- char *name;
- struct ::termios ti;
- memset(&ti,0,sizeof(ti));
-
- ti.c_cflag = CLOCAL|CREAD|CS8;
- ti.c_cc[VMIN] = 1;
-
-#ifdef HAVE_GETPT
- master = getpt();
-#else
- master = open("/dev/ptmx", O_RDWR);
-#endif
- if (master < 0) return 0;
-
- if (grantpt(master) < 0 || unlockpt(master) < 0) goto close_master;
-
- name = ptsname(master);
- if (name == NULL) goto close_master;
-
- slave = open(name, O_RDWR);
- if (slave == -1) goto close_master;
-
-#if (defined(HAVE_ISASTREAM) || defined(isastream)) && defined(I_PUSH)
- if (isastream(slave) &&
- (ioctl(slave, I_PUSH, "ptem") < 0 ||
- ioctl(slave, I_PUSH, "ldterm") < 0))
- goto close_slave;
-#endif
-
- tcsetattr(slave, TCSANOW, &ti);
- fd[0] = master;
- fd[1] = slave;
- return 0;
-
-#if (defined(HAVE_ISASTREAM) || defined(isastream)) && defined(I_PUSH)
-close_slave:
-#endif
- close(slave);
-
-close_master:
- close(master);
- return -1;
-#else
-#ifdef HAVE_OPENPTY
- struct ::termios ti;
- memset(&ti,0,sizeof(ti));
-
- ti.c_cflag = CLOCAL|CREAD|CS8;
- ti.c_cc[VMIN] = 1;
-
- return openpty(fd,fd+1,NULL,&ti,NULL);
-#else
-#ifdef __GNUC__
-#warning "No tty support available. Password dialog won't work."
-#endif
- return socketpair(PF_UNIX,SOCK_STREAM,0,fd);
-#endif
-#endif
-}
-/**
-creates the subprocess
-*/
-bool fishProtocol::connectionStart() {
- int fd[2];
- int rc, flags;
- thisFn = TQString::null;
-
- rc = open_pty_pair(fd);
- if (rc == -1) {
- myDebug( << "socketpair failed, error: " << strerror(errno) << endl);
- return true;
- }
-
- if (!requestNetwork()) return true;
- myDebug( << "Exec: " << (local ? suPath : sshPath) << " Port: " << connectionPort << " User: " << connectionUser << endl);
- childPid = fork();
- if (childPid == -1) {
- myDebug( << "fork failed, error: " << strerror(errno) << endl);
- close(fd[0]);
- close(fd[1]);
- childPid = 0;
- dropNetwork();
- return true;
- }
- if (childPid == 0) {
- // taken from konsole, see TEPty.C for details
- // note: if we're running on socket pairs,
- // this will fail, but thats what we expect
-
- for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
-
- struct rlimit rlp;
- getrlimit(RLIMIT_NOFILE, &rlp);
- for (int i = 0; i < (int)rlp.rlim_cur; i++)
- if (i != fd[1]) close(i);
-
- dup2(fd[1],0);
- dup2(fd[1],1);
- dup2(fd[1],2);
- if (fd[1] > 2) close(fd[1]);
-
- setsid();
-
-#if defined(TIOCSCTTY)
- ioctl(0, TIOCSCTTY, 0);
-#endif
-
- int pgrp = getpid();
-#if defined( _AIX) || defined( __hpux)
- tcsetpgrp(0, pgrp);
-#else
- ioctl(0, TIOCSPGRP, (char *)&pgrp);
-#endif
-
- const char *dev = ttyname(0);
- setpgid(0,0);
- if (dev) close(open(dev, O_WRONLY, 0));
- setpgid(0,0);
-
- if (local) {
- execl(suPath, "su", "-", connectionUser.latin1(), "-c", "cd ~;echo FISH:;exec /bin/sh -c \"if env true 2>/dev/null; then env PS1= PS2= TZ=UTC LANG=C LC_ALL=C LOCALE=C /bin/sh; else PS1= PS2= TZ=UTC LANG=C LC_ALL=C LOCALE=C /bin/sh; fi\"", (void *)0);
- } else {
- #define common_args "-l", connectionUser.latin1(), "-x", "-e", "none", \
- "-q", connectionHost.latin1(), \
- "echo FISH:;exec /bin/sh -c \"if env true 2>/dev/null; then env PS1= PS2= TZ=UTC LANG=C LC_ALL=C LOCALE=C /bin/sh; else PS1= PS2= TZ=UTC LANG=C LC_ALL=C LOCALE=C /bin/sh; fi\"", (void *)0
- // disabled: leave compression up to the client.
- // (isOpenSSH?"-C":"+C"),
-
- if (connectionPort)
- execl(sshPath, "ssh", "-p", TQString::number(connectionPort).latin1(), common_args);
- else
- execl(sshPath, "ssh", common_args);
- #undef common_args
- }
- myDebug( << "could not exec! " << strerror(errno) << endl);
- ::exit(-1);
- }
- close(fd[1]);
- rc = fcntl(fd[0],F_GETFL,&flags);
- rc = fcntl(fd[0],F_SETFL,flags|O_NONBLOCK);
- childFd = fd[0];
-
- fd_set rfds, wfds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- char buf[32768];
- int offset = 0;
- while (!isLoggedIn) {
- FD_SET(childFd,&rfds);
- FD_ZERO(&wfds);
- if (outBufPos >= 0) FD_SET(childFd,&wfds);
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 1000;
- rc = select(childFd+1, &rfds, &wfds, NULL, &timeout);
- if (rc < 0) {
- if (errno == EINTR)
- continue;
- myDebug( << "select failed, rc: " << rc << ", error: " << strerror(errno) << endl);
- return true;
- }
- if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {
- if (outBuf) rc = write(childFd,outBuf+outBufPos,outBufLen-outBufPos);
- else rc = 0;
- if (rc >= 0) outBufPos += rc;
- else {
- if (errno == EINTR)
- continue;
- myDebug( << "write failed, rc: " << rc << ", error: " << strerror(errno) << endl);
- outBufPos = -1;
- //return true;
- }
- if (outBufPos >= outBufLen) {
- outBufPos = -1;
- outBuf = NULL;
- outBufLen = 0;
- }
- }
- if (FD_ISSET(childFd,&rfds)) {
- rc = read(childFd,buf+offset,32768-offset);
- if (rc > 0) {
- int noff = establishConnection(buf,rc+offset);
- if (noff < 0) return false;
- if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
- offset = noff;
- } else {
- if (errno == EINTR)
- continue;
- myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl);
- return true;
- }
- }
- }
- return false;
-}
-
-/**
-writes one chunk of data to stdin of child process
-*/
-void fishProtocol::writeChild(const char *buf, TDEIO::fileoffset_t len) {
- if (outBufPos >= 0 && outBuf) {
-#if 0
- TQString debug;
- debug.setLatin1(outBuf,outBufLen);
- if (len > 0) myDebug( << "write request while old one is pending, throwing away input (" << outBufLen << "," << outBufPos << "," << debug.left(10) << "...)" << endl);
-#endif
- return;
- }
- outBuf = buf;
- outBufPos = 0;
- outBufLen = len;
-}
-
-/**
-manages initial communication setup including password queries
-*/
-int fishProtocol::establishConnection(char *buffer, TDEIO::fileoffset_t len) {
- TQString buf;
- buf.setLatin1(buffer,len);
- int pos;
- // Strip trailing whitespace
- while (buf.length() && (buf[buf.length()-1] == ' '))
- buf.truncate(buf.length()-1);
-
- myDebug( << "establishing: got " << buf << endl);
- while (childPid && ((pos = buf.find('\n')) >= 0 ||
- buf.endsWith(":") || buf.endsWith("?"))) {
- pos++;
- TQString str = buf.left(pos);
- buf = buf.mid(pos);
- if (str == "\n")
- continue;
- if (str == "FISH:\n") {
- thisFn = TQString::null;
- infoMessage(i18n("Initiating protocol..."));
- if (!connectionAuth.password.isEmpty()) {
- connectionAuth.password = connectionAuth.password.left(connectionAuth.password.length()-1);
- cacheAuthentication(connectionAuth);
- }
- isLoggedIn = true;
- return 0;
- } else if (!str.isEmpty()) {
- thisFn += str;
- } else if (buf.endsWith(":")) {
- if (!redirectUser.isEmpty() && connectionUser != redirectUser) {
- KURL dest = url;
- dest.setUser(redirectUser);
- dest.setPass(redirectPass);
- redirection(dest);
- commandList.clear();
- commandCodes.clear();
- finished();
- redirectUser = "";
- redirectPass = "";
- return -1;
- } else if (!connectionPassword.isEmpty()) {
- myDebug( << "sending cpass" << endl);
- connectionAuth.password = connectionPassword+"\n";
- connectionPassword = TQString::null;
- // su does not like receiving a password directly after sending
- // the password prompt so we wait a while.
- if (local)
- sleep(1);
- writeChild(connectionAuth.password.latin1(),connectionAuth.password.length());
- } else {
- myDebug( << "sending mpass" << endl);
- connectionAuth.prompt = thisFn+buf;
- if (local)
- connectionAuth.caption = i18n("Local Login") + " - " + url.user() + "@" + url.host();
- else
- connectionAuth.caption = i18n("SSH Authorization") + " - " + url.user() + "@" + url.host();
- if ((!firstLogin || !checkCachedAuthentication(connectionAuth))) {
- connectionAuth.password = TQString::null; // don't prefill
- if ( !openPassDlg(connectionAuth)) {
- error(ERR_USER_CANCELED,connectionHost);
- shutdownConnection();
- return -1;
- }
- }
- firstLogin = false;
- connectionAuth.password += "\n";
- if (connectionAuth.username != connectionUser) {
- KURL dest = url;
- dest.setUser(connectionAuth.username);
- dest.setPass(connectionAuth.password);
- redirection(dest);
- if (isStat) { // FIXME: just a workaround for konq deficiencies
- redirectUser = connectionAuth.username;
- redirectPass = connectionAuth.password;
- }
- commandList.clear();
- commandCodes.clear();
- finished();
- return -1;
- }
- myDebug( << "sending pass" << endl);
- if (local)
- sleep(1);
- writeChild(connectionAuth.password.latin1(),connectionAuth.password.length());
- }
- thisFn = TQString::null;
- return 0;
- } else if (buf.endsWith("?")) {
- int rc = messageBox(QuestionYesNo,thisFn+buf);
- if (rc == KMessageBox::Yes) {
- writeChild("yes\n",4);
- } else {
- writeChild("no\n",3);
- }
- thisFn = TQString::null;
- return 0;
- } else {
- myDebug( << "unmatched case in initial handling! shouldn't happen!" << endl);
- }
- }
- return buf.length();
-}
-/**
-sets connection information for subsequent commands
-*/
-void fishProtocol::setHost(const TQString & host, int port, const TQString & u, const TQString & pass){
- TQString user(u);
-
- if (isNXFish)
- local = 0;
- else
- local = (host == "localhost" && port == 0);
-
- if (port <= 0) port = 0;
- if (user.isEmpty()) user = getenv("LOGNAME");
-
- if (host == connectionHost && port == connectionPort && user == connectionUser)
- return;
- myDebug( << "setHost " << u << "@" << host << endl);
-
- if (childPid) shutdownConnection();
-
- connectionHost = host;
- connectionAuth.url.setHost(host);
-
- connectionUser = user;
- connectionAuth.username = user;
- connectionAuth.url.setUser(user);
-
- connectionPort = port;
- connectionPassword = pass;
- firstLogin = true;
-}
-
-/**
-Forced close of the connection
-
-This function gets called from the application side of the universe,
-it shouldn't send any response.
- */
-void fishProtocol::closeConnection(){
- myDebug( << "closeConnection()" << endl);
- shutdownConnection(true);
-}
-
-/**
-Closes the connection
- */
-void fishProtocol::shutdownConnection(bool forced){
- if (childPid) {
- kill(childPid,SIGTERM); // We may not have permission...
- childPid = 0;
- close(childFd); // ...in which case this should do the trick
- childFd = -1;
- if (!forced)
- {
- dropNetwork();
- infoMessage(i18n("Disconnected."));
- }
- }
- outBufPos = -1;
- outBuf = NULL;
- outBufLen = 0;
- qlist.clear();
- commandList.clear();
- commandCodes.clear();
- isLoggedIn = false;
- writeReady = true;
- isRunning = false;
- rawRead = 0;
- rawWrite = -1;
- recvLen = -1;
- sendLen = -1;
-}
-/**
-builds each FISH request and sets the error counter
-*/
-bool fishProtocol::sendCommand(fish_command_type cmd, ...) {
- const fish_info &info = fishInfo[cmd];
- myDebug( << "queueing: cmd="<< cmd << "['" << info.command << "'](" << info.params <<"), alt=['" << info.alt << "'], lines=" << info.lines << endl);
-
- va_list list;
- va_start(list, cmd);
- TQString realCmd = info.command;
- TQString realAlt = info.alt;
- static TQRegExp rx("[][\\\\\n $`#!()*?{}~&<>;'\"%^@|\t]");
- for (int i = 0; i < info.params; i++) {
- TQString arg(va_arg(list, const char *));
- int pos = -2;
- while ((pos = rx.search(arg,pos+2)) >= 0) {
- arg.replace(pos,0,TQString("\\"));
- }
- //myDebug( << "arg " << i << ": " << arg << endl);
- realCmd.append(" ").append(arg);
- realAlt.replace(TQRegExp("%"+TQString::number(i+1)),arg);
- }
- TQString s("#");
- s.append(realCmd).append("\n ").append(realAlt).append(" 2>&1;echo '### 000'\n");
- if (realCmd == "FISH")
- s.prepend(" ");
- commandList.append(s);
- commandCodes.append(cmd);
- return true;
-}
-
-/**
-checks response string for result code, converting 000 and 001 appropriately
-*/
-int fishProtocol::handleResponse(const TQString &str){
- myDebug( << "handling: " << str << endl);
- if (str.startsWith("### ")) {
- bool isOk = false;
- int result = str.mid(4,3).toInt(&isOk);
- if (!isOk) result = 500;
- if (result == 0) result = (errorCount != 0?500:200);
- if (result == 1) result = (errorCount != 0?500:100);
- myDebug( << "result: " << result << ", errorCount: " << errorCount << endl);
- return result;
- } else {
- errorCount++;
- return 0;
- }
-}
-
-int fishProtocol::makeTimeFromLs(const TQString &monthStr, const TQString &dayStr, const TQString &timeyearStr)
-{
- TQDateTime dt(TQDate::currentDate(Qt::UTC));
- int year = dt.date().year();
- int month = dt.date().month();
- int currentMonth = month;
- int day = dayStr.toInt();
-
- static const char * const monthNames[12] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- for (int i=0; i < 12; i++) if (monthStr.startsWith(monthNames[i])) {
- month = i+1;
- break;
- }
-
- int pos = timeyearStr.find(':');
- if (timeyearStr.length() == 4 && pos == -1) {
- year = timeyearStr.toInt();
- } else if (pos == -1) {
- return 0;
- } else {
- if (month > currentMonth + 1) year--;
- dt.time().setHMS(timeyearStr.left(pos).toInt(),timeyearStr.mid(pos+1).toInt(),0);
- }
- dt.date().setYMD(year,month,day);
-
- return dt.toTime_t();
-}
-
-/**
-parses response from server and acts accordingly
-*/
-void fishProtocol::manageConnection(const TQString &l) {
- TQString line(l);
- int rc = handleResponse(line);
- UDSAtom atom;
- TQDateTime dt;
- TDEIO::filesize_t fsize;
- int pos, pos2, pos3;
- bool isOk = false;
- if (!rc) {
- switch (fishCommand) {
- case FISH_VER:
- if (line.startsWith("VER 0.0.3")) {
- line.append(" ");
- hasAppend = line.contains(" append ");
- } else {
- error(ERR_UNSUPPORTED_PROTOCOL,line);
- shutdownConnection();
- }
- break;
- case FISH_PWD:
- url.setPath(line);
- redirection(url);
- break;
- case FISH_LIST:
- myDebug( << "listReason: " << listReason << endl);
- /* Fall through */
- case FISH_STAT:
- if (line.length() > 0) {
- switch (line[0].cell()) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- fsize = line.toULongLong(&isOk);
- if (fsize > 0 && isOk) errorCount--;
- if ((fishCommand == FISH_LIST) && (listReason == LIST))
- totalSize(fsize);
- break;
-
- case 'P':
- errorCount--;
- if (line[1] == 'd') {
- mimeAtom.m_str = "inode/directory";
- typeAtom.m_long = S_IFDIR;
- } else {
- if (line[1] == '-') {
- typeAtom.m_long = S_IFREG;
- } else if (line[1] == 'l') {
- typeAtom.m_long = S_IFLNK;
- } else if (line[1] == 'c') {
- typeAtom.m_long = S_IFCHR;
- } else if (line[1] == 'b') {
- typeAtom.m_long = S_IFBLK;
- } else if (line[1] == 's') {
- typeAtom.m_long = S_IFSOCK;
- } else if (line[1] == 'p') {
- typeAtom.m_long = S_IFIFO;
- } else {
- myDebug( << "unknown file type: " << line[1].cell() << endl);
- errorCount++;
- break;
- }
- }
- //myDebug( << "file type: " << atom.m_long << endl);
- //udsEntry.append(atom);
-
- atom.m_uds = UDS_ACCESS;
- atom.m_long = 0;
- if (line[2] == 'r') atom.m_long |= S_IRUSR;
- if (line[3] == 'w') atom.m_long |= S_IWUSR;
- if (line[4] == 'x' || line[4] == 's') atom.m_long |= S_IXUSR;
- if (line[4] == 'S' || line[4] == 's') atom.m_long |= S_ISUID;
- if (line[5] == 'r') atom.m_long |= S_IRGRP;
- if (line[6] == 'w') atom.m_long |= S_IWGRP;
- if (line[7] == 'x' || line[7] == 's') atom.m_long |= S_IXGRP;
- if (line[7] == 'S' || line[7] == 's') atom.m_long |= S_ISGID;
- if (line[8] == 'r') atom.m_long |= S_IROTH;
- if (line[9] == 'w') atom.m_long |= S_IWOTH;
- if (line[10] == 'x' || line[10] == 't') atom.m_long |= S_IXOTH;
- if (line[10] == 'T' || line[10] == 't') atom.m_long |= S_ISVTX;
- udsEntry.append(atom);
-
- atom.m_uds = UDS_USER;
- atom.m_long = 0;
- pos = line.find('.',12);
- if (pos < 0) {
- errorCount++;
- break;
- }
- atom.m_str = line.mid(12,pos-12);
- udsEntry.append(atom);
-
- atom.m_uds = UDS_GROUP;
- atom.m_long = 0;
- atom.m_str = line.mid(pos+1);
- udsEntry.append(atom);
- break;
-
- case 'd':
- atom.m_uds = UDS_MODIFICATION_TIME;
- pos = line.find(' ');
- pos2 = line.find(' ',pos+1);
- if (pos < 0 || pos2 < 0) break;
- errorCount--;
- atom.m_long = makeTimeFromLs(line.mid(1,pos-1), line.mid(pos+1,pos2-pos), line.mid(pos2+1));
- udsEntry.append(atom);
- break;
-
- case 'D':
- atom.m_uds = UDS_MODIFICATION_TIME;
- pos = line.find(' ');
- pos2 = line.find(' ',pos+1);
- pos3 = line.find(' ',pos2+1);
- if (pos < 0 || pos2 < 0 || pos3 < 0) break;
- dt.setDate(TQDate(line.mid(1,pos-1).toInt(),line.mid(pos+1,pos2-pos-1).toInt(),line.mid(pos2+1,pos3-pos2-1).toInt()));
- pos = pos3;
- pos2 = line.find(' ',pos+1);
- pos3 = line.find(' ',pos2+1);
- if (pos < 0 || pos2 < 0 || pos3 < 0) break;
- dt.setTime(TQTime(line.mid(pos+1,pos2-pos-1).toInt(),line.mid(pos2+1,pos3-pos2-1).toInt(),line.mid(pos3+1).toInt()));
- errorCount--;
- atom.m_long = dt.toTime_t();
- udsEntry.append(atom);
- break;
-
- case 'S':
- atom.m_uds = UDS_SIZE;
- atom.m_long = line.mid(1).toULongLong(&isOk);
- if (!isOk) break;
- errorCount--;
- udsEntry.append(atom);
- break;
-
- case 'E':
- errorCount--;
- break;
-
- case ':':
- atom.m_uds = UDS_NAME;
- atom.m_long = 0;
- pos = line.findRev('/');
- atom.m_str = thisFn = line.mid(pos < 0?1:pos+1);
- if (fishCommand == FISH_LIST)
- udsEntry.append(atom);
- // By default, the mimetype comes from the extension
- // We'll use the file(1) result only as fallback [like the rest of KDE does]
- {
- KURL kurl("fish://host/");
- kurl.setFileName(thisFn); // properly encode special chars
- KMimeType::Ptr mime = KMimeType::findByURL(kurl);
- if ( mime->name() != KMimeType::defaultMimeType() )
- mimeAtom.m_str = mime->name();
- }
- errorCount--;
- break;
-
- case 'M': {
- TQString type = line.mid(1);
-
- // First thing's first. If remote says this is a directory, throw out any
- // name-based file type guesses.
- if (type == "inode/directory" && mimeAtom.m_str != type) {
- mimeAtom.m_str = type;
- typeAtom.m_long = S_IFDIR;
- }
- // This is getting ugly. file(1) makes some uneducated
- // guesses, so we must try to ignore them (#51274)
- else if (mimeAtom.m_str.isEmpty() && line.right(8) != "/unknown" &&
- (thisFn.find('.') < 0 || (line.left(8) != "Mtext/x-"
- && line != "Mtext/plain"))) {
- mimeAtom.m_str = type;
- }
- errorCount--;
- break;
- }
-
- case 'L':
- atom.m_uds = UDS_LINK_DEST;
- atom.m_long = 0;
- atom.m_str = line.mid(1);
- udsEntry.append(atom);
- if (!typeAtom.m_long) typeAtom.m_long = S_IFLNK;
- errorCount--;
- break;
- }
- } else {
- if (!mimeAtom.m_str.isNull())
- udsEntry.append(mimeAtom);
- mimeAtom.m_str = TQString::null;
-
- udsEntry.append(typeAtom);
- typeAtom.m_long = 0;
-
- if (fishCommand == FISH_STAT)
- udsStatEntry = udsEntry;
- else if (listReason == LIST) {
- listEntry(udsEntry, false); //1
- } else if (listReason == CHECK) checkExist = true; //0
- errorCount--;
- udsEntry.clear();
- }
- break;
-
- case FISH_RETR:
- if (line.length() == 0) {
- error(ERR_IS_DIRECTORY,url.prettyURL());
- recvLen = 0;
- break;
- }
- recvLen = line.toLongLong(&isOk);
- if (!isOk) {
- error(ERR_COULD_NOT_READ,url.prettyURL());
- shutdownConnection();
- break;
- }
- break;
- default : break;
- }
-
- } else if (rc == 100) {
- switch (fishCommand) {
- case FISH_FISH:
- writeChild(fishCode, fishCodeLen);
- break;
- case FISH_READ:
- recvLen = 1024;
- /* fall through */
- case FISH_RETR:
- myDebug( << "reading " << recvLen << endl);
- if (recvLen == -1) {
- error(ERR_COULD_NOT_READ,url.prettyURL());
- shutdownConnection();
- } else {
- rawRead = recvLen;
- dataRead = 0;
- mimeTypeSent = false;
- if (recvLen == 0)
- {
- mimeType("application/x-zerosize");
- mimeTypeSent = true;
- }
- }
- break;
- case FISH_STOR:
- case FISH_WRITE:
- case FISH_APPEND:
- rawWrite = sendLen;
- //myDebug( << "sending " << sendLen << endl);
- writeChild(NULL,0);
- break;
- default : break;
- }
- } else if (rc/100 != 2) {
- switch (fishCommand) {
- case FISH_STOR:
- case FISH_WRITE:
- case FISH_APPEND:
- error(ERR_COULD_NOT_WRITE,url.prettyURL());
- shutdownConnection();
- break;
- case FISH_RETR:
- error(ERR_COULD_NOT_READ,url.prettyURL());
- shutdownConnection();
- break;
- case FISH_READ:
- if ( rc == 501 )
- {
- mimeType("inode/directory");
- mimeTypeSent = true;
- recvLen = 0;
- finished();
- }
- else
- {
- error(ERR_COULD_NOT_READ,url.prettyURL());
- shutdownConnection();
- }
- break;
- case FISH_FISH:
- case FISH_VER:
- error(ERR_SLAVE_DEFINED,line);
- shutdownConnection();
- break;
- case FISH_PWD:
- case FISH_CWD:
- error(ERR_CANNOT_ENTER_DIRECTORY,url.prettyURL());
- break;
- case FISH_LIST:
- myDebug( << "list error. reason: " << listReason << endl);
- if (listReason == LIST) error(ERR_CANNOT_ENTER_DIRECTORY,url.prettyURL());
- else if (listReason == CHECK) {
- checkExist = false;
- finished();
- }
- break;
- case FISH_STAT:
- error(ERR_DOES_NOT_EXIST,url.prettyURL());
- udsStatEntry.clear();
- break;
- case FISH_CHMOD:
- error(ERR_CANNOT_CHMOD,url.prettyURL());
- break;
- case FISH_CHOWN:
- case FISH_CHGRP:
- error(ERR_ACCESS_DENIED,url.prettyURL());
- break;
- case FISH_MKD:
- if ( rc == 501 )
- error(ERR_DIR_ALREADY_EXIST,url.prettyURL());
- else
- error(ERR_COULD_NOT_MKDIR,url.prettyURL());
- break;
- case FISH_RMD:
- error(ERR_COULD_NOT_RMDIR,url.prettyURL());
- break;
- case FISH_DELE:
- error(ERR_CANNOT_DELETE,url.prettyURL());
- break;
- case FISH_RENAME:
- error(ERR_CANNOT_RENAME,url.prettyURL());
- break;
- case FISH_COPY:
- case FISH_LINK:
- case FISH_SYMLINK:
- error(ERR_COULD_NOT_WRITE,url.prettyURL());
- break;
- default : break;
- }
- } else {
- if (fishCommand == FISH_STOR) fishCommand = (hasAppend?FISH_APPEND:FISH_WRITE);
- if (fishCommand == FISH_FISH) {
- connected();
- } else if (fishCommand == FISH_LIST) {
- if (listReason == LIST) {
- listEntry(UDSEntry(),true);
- } else if (listReason == CHECK) {
- if (!checkOverwrite && checkExist)
- {
- error(ERR_FILE_ALREADY_EXIST,url.prettyURL());
- return; // Don't call finished!
- }
- }
- } else if (fishCommand == FISH_STAT) {
- UDSAtom atom;
-
- atom.m_uds = TDEIO::UDS_NAME;
- atom.m_str = url.fileName();
- udsStatEntry.append( atom );
- statEntry(udsStatEntry);
- } else if (fishCommand == FISH_APPEND) {
- dataReq();
- if (readData(rawData) > 0) sendCommand(FISH_APPEND,E(TQString::number(rawData.size())),E(url.path()));
- else if (!checkExist && putPerm > -1) sendCommand(FISH_CHMOD,E(TQString::number(putPerm,8)),E(url.path()));
- sendLen = rawData.size();
- } else if (fishCommand == FISH_WRITE) {
- dataReq();
- if (readData(rawData) > 0) sendCommand(FISH_WRITE,E(TQString::number(putPos)),E(TQString::number(rawData.size())),E(url.path()));
- else if (!checkExist && putPerm > -1) sendCommand(FISH_CHMOD,E(TQString::number(putPerm,8)),E(url.path()));
- putPos += rawData.size();
- sendLen = rawData.size();
- } else if (fishCommand == FISH_RETR) {
- data(TQByteArray());
- }
- finished();
- }
-}
-
-void fishProtocol::writeStdin(const TQString &line)
-{
- qlist.append(line);
-
- if (writeReady) {
- writeReady = false;
- //myDebug( << "Writing: " << qlist.first().mid(0,qlist.first().find('\n')) << endl);
- myDebug( << "Writing: " << qlist.first() << endl);
- myDebug( << "---------" << endl);
- writeChild((const char *)qlist.first().latin1(), qlist.first().length());
- }
-}
-
-void fishProtocol::sent()
-{
- if (rawWrite > 0) {
- myDebug( << "writing raw: " << rawData.size() << "/" << rawWrite << endl);
- writeChild(rawData.data(),(rawWrite > rawData.size()?rawData.size():rawWrite));
- rawWrite -= rawData.size();
- if (rawWrite > 0) {
- dataReq();
- if (readData(rawData) <= 0) {
- shutdownConnection();
- }
- }
- return;
- } else if (rawWrite == 0) {
- // workaround: some dd's insist in reading multiples of
- // 8 bytes, swallowing up to seven bytes. Sending
- // newlines is safe even when a sane dd is used
- writeChild("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",15);
- rawWrite = -1;
- return;
- }
- if (qlist.count() > 0) qlist.remove(qlist.begin());
- if (qlist.count() == 0) {
- writeReady = true;
- } else {
- //myDebug( << "Writing: " << qlist.first().mid(0,qlist.first().find('\n')) << endl);
- myDebug( << "Writing: " << qlist.first() << endl);
- myDebug( << "---------" << endl);
- writeChild((const char *)qlist.first().latin1(),qlist.first().length());
- }
-}
-
-int fishProtocol::received(const char *buffer, TDEIO::fileoffset_t buflen)
-{
- int pos = 0;
- do {
- if (buflen <= 0) break;
-
- if (rawRead > 0) {
- //myDebug( << "processedSize " << dataRead << ", len " << buflen << "/" << rawRead << endl);
- int dataSize = (rawRead > buflen?buflen:rawRead);
- if (!mimeTypeSent)
- {
- int mimeSize = TQMIN(dataSize, (int)mimeBuffer.size()-dataRead);
- memcpy(mimeBuffer.data()+dataRead,buffer,mimeSize);
- dataRead += mimeSize;
- rawRead -= mimeSize;
- buffer += mimeSize;
- buflen -= mimeSize;
- if (rawRead == 0) // End of data
- mimeBuffer.resize(dataRead);
- if (dataRead < (int)mimeBuffer.size())
- {
- myDebug( << "wait for more" << endl);
- break;
- }
-
- // We need a KMimeType::findByNameAndContent(filename,data)
- // For now we do: find by extension, and if not found (or extension not reliable)
- // then find by content.
- bool accurate = false;
- KMimeType::Ptr mime = KMimeType::findByURL( url, 0, false, true, &accurate );
- if ( !mime || mime->name() == KMimeType::defaultMimeType()
- || !accurate )
- {
- KMimeType::Ptr p_mimeType = KMimeType::findByContent(mimeBuffer);
- if ( p_mimeType && p_mimeType->name() != KMimeType::defaultMimeType() )
- mime = p_mimeType;
- }
-
- sendmimeType(mime->name());
-
-
- mimeTypeSent = true;
- if (fishCommand != FISH_READ) {
- totalSize(dataRead + rawRead);
- data(mimeBuffer);
- processedSize(dataRead);
- }
- mimeBuffer.resize(1024);
- pos = 0;
- continue; // Process rest of buffer/buflen
- }
-
- TQByteArray bdata;
- bdata.duplicate(buffer,dataSize);
- data(bdata);
-
- dataRead += dataSize;
- rawRead -= dataSize;
- processedSize(dataRead);
- if (rawRead <= 0) {
- buffer += dataSize;
- buflen -= dataSize;
- } else {
- return 0;
- }
- }
-
- if (buflen <= 0) break;
-
- pos = 0;
- // Find newline
- while((pos < buflen) && (buffer[pos] != '\n'))
- ++pos;
-
- if (pos < buflen)
- {
- TQString s = remoteEncoding()->decode(TQCString(buffer,pos+1));
-
- buffer += pos+1;
- buflen -= pos+1;
-
- manageConnection(s);
-
- pos = 0;
- // Find next newline
- while((pos < buflen) && (buffer[pos] != '\n'))
- ++pos;
- }
- } while (childPid && buflen && (rawRead > 0 || pos < buflen));
- return buflen;
-}
-/** get a file */
-void fishProtocol::get(const KURL& u){
- myDebug( << "@@@@@@@@@ get " << u << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- recvLen = -1;
- sendCommand(FISH_RETR,E(url.path()));
- }
- run();
-}
-
-/** put a file */
-void fishProtocol::put(const KURL& u, int permissions, bool overwrite, bool /*resume*/){
- myDebug( << "@@@@@@@@@ put " << u << " " << permissions << " " << overwrite << " " /* << resume */ << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- putPerm = permissions;
- checkOverwrite = overwrite;
- checkExist = false;
- putPos = 0;
- listReason = CHECK;
- sendCommand(FISH_LIST,E(url.path()));
- sendCommand(FISH_STOR,"0",E(url.path()));
- }
- run();
-}
-/** executes next command in sequence or calls finished() if all is done */
-void fishProtocol::finished() {
- if (commandList.count() > 0) {
- fishCommand = (fish_command_type)commandCodes.first();
- errorCount = -fishInfo[fishCommand].lines;
- rawRead = 0;
- rawWrite = -1;
- udsEntry.clear();
- udsStatEntry.clear();
- writeStdin(commandList.first());
- //if (fishCommand != FISH_APPEND && fishCommand != FISH_WRITE) infoMessage("Sending "+(commandList.first().mid(1,commandList.first().find("\n")-1))+"...");
- commandList.remove(commandList.begin());
- commandCodes.remove(commandCodes.begin());
- } else {
- myDebug( << "_______ emitting finished()" << endl);
- SlaveBase::finished();
- isRunning = false;
- }
-}
-/** aborts command sequence and calls error() */
-void fishProtocol::error(int type, const TQString &detail) {
- commandList.clear();
- commandCodes.clear();
- myDebug( << "ERROR: " << type << " - " << detail << endl);
- SlaveBase::error(type,detail);
- isRunning = false;
-}
-/** executes a chain of commands */
-void fishProtocol::run() {
- if (!isRunning) {
- int rc;
- isRunning = true;
- finished();
- fd_set rfds, wfds;
- FD_ZERO(&rfds);
- char buf[32768];
- int offset = 0;
- while (isRunning) {
- FD_SET(childFd,&rfds);
- FD_ZERO(&wfds);
- if (outBufPos >= 0) FD_SET(childFd,&wfds);
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 1000;
- rc = select(childFd+1, &rfds, &wfds, NULL, &timeout);
- if (rc < 0) {
- if (errno == EINTR)
- continue;
- myDebug( << "select failed, rc: " << rc << ", error: " << strerror(errno) << endl);
- error(ERR_CONNECTION_BROKEN,connectionHost);
- shutdownConnection();
- return;
- }
- if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {
-#if 0
- TQString debug;
- debug.setLatin1(outBuf+outBufPos,outBufLen-outBufPos);
- myDebug( << "now writing " << (outBufLen-outBufPos) << " " << debug.left(40) << "..." << endl);
-#endif
- if (outBufLen-outBufPos > 0) rc = write(childFd,outBuf+outBufPos,outBufLen-outBufPos);
- else rc = 0;
- if (rc >= 0) outBufPos += rc;
- else {
- if (errno == EINTR)
- continue;
- myDebug( << "write failed, rc: " << rc << ", error: " << strerror(errno) << endl);
- error(ERR_CONNECTION_BROKEN,connectionHost);
- shutdownConnection();
- return;
- }
- if (outBufPos >= outBufLen) {
- outBufPos = -1;
- outBuf = NULL;
- sent();
- }
- }
- else if (FD_ISSET(childFd,&rfds)) {
- rc = read(childFd,buf+offset,32768-offset);
- //myDebug( << "read " << rc << " bytes" << endl);
- if (rc > 0) {
- int noff = received(buf,rc+offset);
- if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
- //myDebug( << "left " << noff << " bytes: " << TQString::fromLatin1(buf,offset) << endl);
- offset = noff;
- } else {
- if (errno == EINTR)
- continue;
- myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl);
- error(ERR_CONNECTION_BROKEN,connectionHost);
- shutdownConnection();
- return;
- }
- }
- if (wasKilled())
- return;
- }
- }
-}
-/** stat a file */
-void fishProtocol::stat(const KURL& u){
- myDebug( << "@@@@@@@@@ stat " << u << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- isStat = true; // FIXME: just a workaround for konq deficiencies
- openConnection();
- isStat = false; // FIXME: just a workaround for konq deficiencies
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- sendCommand(FISH_STAT,E(url.path(-1)));
- }
- run();
-}
-/** find mimetype for a file */
-void fishProtocol::mimetype(const KURL& u){
- myDebug( << "@@@@@@@@@ mimetype " << u << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- recvLen = 1024;
- sendCommand(FISH_READ,"0","1024",E(url.path()));
- }
- run();
-}
-/** list a directory */
-void fishProtocol::listDir(const KURL& u){
- myDebug( << "@@@@@@@@@ listDir " << u << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- listReason = LIST;
- sendCommand(FISH_LIST,E(url.path()));
- }
- run();
-}
-/** create a directory */
-void fishProtocol::mkdir(const KURL& u, int permissions) {
- myDebug( << "@@@@@@@@@ mkdir " << u << " " << permissions << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- sendCommand(FISH_MKD,E(url.path()));
- if (permissions > -1) sendCommand(FISH_CHMOD,E(TQString::number(permissions,8)),E(url.path()));
- }
- run();
-}
-/** rename a file */
-void fishProtocol::rename(const KURL& s, const KURL& d, bool overwrite) {
- myDebug( << "@@@@@@@@@ rename " << s << " " << d << " " << overwrite << endl);
- if (s.host() != d.host() || s.port() != d.port() || s.user() != d.user()) {
- error(ERR_UNSUPPORTED_ACTION,s.prettyURL());
- return;
- }
- setHost(s.host(),s.port(),s.user(),s.pass());
- url = d;
- openConnection();
- if (!isLoggedIn) return;
- KURL src = s;
- url.cleanPath();
- src.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- if (!overwrite) {
- listReason = CHECK;
- checkOverwrite = false;
- sendCommand(FISH_LIST,E(url.path()));
- }
- sendCommand(FISH_RENAME,E(src.path()),E(url.path()));
- }
- run();
-}
-/** create a symlink */
-void fishProtocol::symlink(const TQString& target, const KURL& u, bool overwrite) {
- myDebug( << "@@@@@@@@@ symlink " << target << " " << u << " " << overwrite << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- if (!overwrite) {
- listReason = CHECK;
- checkOverwrite = false;
- sendCommand(FISH_LIST,E(url.path()));
- }
- sendCommand(FISH_SYMLINK,E(target),E(url.path()));
- }
- run();
-}
-/** change file permissions */
-void fishProtocol::chmod(const KURL& u, int permissions){
- myDebug( << "@@@@@@@@@ chmod " << u << " " << permissions << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- if (permissions > -1) sendCommand(FISH_CHMOD,E(TQString::number(permissions,8)),E(url.path()));
- }
- run();
-}
-/** copies a file */
-void fishProtocol::copy(const KURL &s, const KURL &d, int permissions, bool overwrite) {
- myDebug( << "@@@@@@@@@ copy " << s << " " << d << " " << permissions << " " << overwrite << endl);
- if (s.host() != d.host() || s.port() != d.port() || s.user() != d.user()) {
- error(ERR_UNSUPPORTED_ACTION,s.prettyURL());
- return;
- }
- //myDebug( << s << endl << d << endl);
- setHost(s.host(),s.port(),s.user(),s.pass());
- url = d;
- openConnection();
- if (!isLoggedIn) return;
- KURL src = s;
- url.cleanPath();
- src.cleanPath();
- if (!src.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- if (!overwrite) {
- listReason = CHECK;
- checkOverwrite = false;
- sendCommand(FISH_LIST,E(url.path()));
- }
- sendCommand(FISH_COPY,E(src.path()),E(url.path()));
- if (permissions > -1) sendCommand(FISH_CHMOD,E(TQString::number(permissions,8)),E(url.path()));
- }
- run();
-}
-/** removes a file or directory */
-void fishProtocol::del(const KURL &u, bool isFile){
- myDebug( << "@@@@@@@@@ del " << u << " " << isFile << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- url.cleanPath();
- if (!url.hasPath()) {
- sendCommand(FISH_PWD);
- } else {
- sendCommand((isFile?FISH_DELE:FISH_RMD),E(url.path()));
- }
- run();
-}
-/** special like background execute */
-void fishProtocol::special( const TQByteArray &data ){
- int tmp;
-
- TQDataStream stream(data, IO_ReadOnly);
-
- stream >> tmp;
- switch (tmp) {
- case FISH_EXEC_CMD: // SSH EXEC
- {
- KURL u;
- TQString command;
- TQString tempfile;
- stream >> u;
- stream >> command;
- myDebug( << "@@@@@@@@@ exec " << u << " " << command << endl);
- setHost(u.host(),u.port(),u.user(),u.pass());
- url = u;
- openConnection();
- if (!isLoggedIn) return;
- sendCommand(FISH_EXEC,E(command),E(url.path()));
- run();
- break;
- }
- default:
- // Some command we don't understand.
- error(ERR_UNSUPPORTED_ACTION,TQString().setNum(tmp));
- break;
- }
-}
-/** report status */
-void fishProtocol::slave_status() {
- myDebug( << "@@@@@@@@@ slave_status" << endl);
- if (childPid > 0)
- slaveStatus(connectionHost,isLoggedIn);
- else
- slaveStatus(TQString::null,false);
-}