summaryrefslogtreecommitdiffstats
path: root/kioslave/sftp
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/sftp
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/sftp')
-rw-r--r--kioslave/sftp/AUTHORS3
-rw-r--r--kioslave/sftp/CHANGELOG59
-rw-r--r--kioslave/sftp/CMakeLists.txt37
-rw-r--r--kioslave/sftp/DEBUGGING12
-rw-r--r--kioslave/sftp/Makefile.am25
-rw-r--r--kioslave/sftp/TODO5
-rw-r--r--kioslave/sftp/atomicio.cpp67
-rw-r--r--kioslave/sftp/atomicio.h39
-rw-r--r--kioslave/sftp/kio_sftp.cpp2282
-rw-r--r--kioslave/sftp/kio_sftp.h149
-rw-r--r--kioslave/sftp/ksshprocess.cpp1114
-rw-r--r--kioslave/sftp/ksshprocess.h623
-rw-r--r--kioslave/sftp/ksshprocesstest.cpp98
-rw-r--r--kioslave/sftp/process.cpp493
-rw-r--r--kioslave/sftp/process.h148
-rw-r--r--kioslave/sftp/sftp.h91
-rw-r--r--kioslave/sftp/sftp.protocol84
-rw-r--r--kioslave/sftp/sftpfileattr.cpp346
-rw-r--r--kioslave/sftp/sftpfileattr.h261
19 files changed, 0 insertions, 5936 deletions
diff --git a/kioslave/sftp/AUTHORS b/kioslave/sftp/AUTHORS
deleted file mode 100644
index c763d00bc..000000000
--- a/kioslave/sftp/AUTHORS
+++ /dev/null
@@ -1,3 +0,0 @@
-Dawit Alemayehu <adawit@kde.org>
-Lucas Fisher <ljfisher@iastate.edu>
-
diff --git a/kioslave/sftp/CHANGELOG b/kioslave/sftp/CHANGELOG
deleted file mode 100644
index b60e7f44b..000000000
--- a/kioslave/sftp/CHANGELOG
+++ /dev/null
@@ -1,59 +0,0 @@
-- add dialog to ask for username
-- rename() causes SSH to die
-- How to handle overwrite?
-- After the user cancels with the stop button, we get ERR_CANNOT_LAUNCH_PROCESS
- errors, until we kill the ioslave. Same thing after trying the wrong passwd
- too many times.
- This is happening because TDEProcess thinks that the ssh process is still running
- even though it exited.
-- How to handle password and caching?
- - Write our own askpass program using kde
- - set env SSH_ASKPASS_PROGRAM before launching
- -how to do this? TDEProcess doesn't give us access to env variables.
- - Our askpass program can probably talk to the tdesu daemon to implement caching.
-- chmod() succeeds, but konqueror always puts permissions to 0 afterwards. The properties
- dialog is right though.
- Nevermind - ftp ioslave does this too! Maybe a bug with konqueror.
-- stat does not give us group and owner names, only numbers. We could cache the uid/name and
- gid/name so we can give names when doing a stat also.
-
-7-13-2001 - ReadLink stopped working. sftp server always retuns a file not found error
- - Need to implement 64 bit file lengths-->write DataStream << for u_int64
- Still need to offer 32 bit size since this is what kde wants. ljf
- - rename() isn't exactly causing ioslave to die. The stat of the file we are
- going to rename is killing the slave. The slave dies in the statEntry() call.
- I don't know what I am putting in the UDS entry that is causing this. ljf
-7-14-2001 - got put, mimetype working ljf
- - fixed readlink problem - I was sending the wrong path. doh! ljf
-7-17-2001 - If the user changes the host, the slave doesn't change host! setHost() is not
- called, nor is another ioslave spawned. I have not investigated the problem
- yet. ljf
-7-21-2001 - got slave working with kde 2.2 cvs
-7-22-2001 - probable solution to getting password prompt -- open with controlling
- but don't connect stdin/out to terminal. duh!
-8-9-2001 - Doh! I haven't kept very good logs. Look at the cvs logs for better info.
- - At this point kio_sftp is using KSshProcess which I wrote in order to make
- a standard interface to the various version of ssh out there. So far it is
- working fairly well. We also now report host key changes to the user and
- allow them to choose whether or not to continue. This is a big improvement.
- - Todo: support use of keys and ssh agent
- put()'s resume functionality needs some work
-1-26-2002 - Rewrote put() following the ftp::put() so it should behave the same way
- - increase the size of the data packet we ask for in ::get up to 60k.
- Through-put increases nicely.
- - Call closeConnection() from construction. Keeps from having unused ssh
- processes laying around after failed operations.
-2-19-2002 - get() now emits mimetype, fixes problem with konqi not downloading file for
- viewing in kpart.
- - get port number using getservbyname instead of hard coding it.
-2-27-2002 - testing before committing back to cvs, test with openssh 3, ssh 3
-6-?-2002 - rewrote openConnection() to using new KSshProcess connect proceedures
-7-20-2002 - Don't put up a message box when auth fails because of now or changed key,
- the call to error() will put up the dialog.
- - Connect fails and no more password are prompted for when we get
- ERR_AUTH_FAILED from KSshProcess.
-9-15-2002 - stuff
-9-29-2002 - the last i18n string updates, fixed problem with uploading files to
- openssh server.
-5-8-2003 - check whether operation types are supported by the negotiated sftp
- protocol version
diff --git a/kioslave/sftp/CMakeLists.txt b/kioslave/sftp/CMakeLists.txt
deleted file mode 100644
index c068166b0..000000000
--- a/kioslave/sftp/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-#################################################
-#
-# (C) 2010-2011 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_BINARY_DIR}
- ${TDE_INCLUDE_DIR}
- ${TQT_INCLUDE_DIRS}
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES sftp.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kio_sftp (module) #########################
-
-set( target kio_sftp )
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES process.cpp atomicio.cpp kio_sftp.cpp sftpfileattr.cpp ksshprocess.cpp
- LINK kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/sftp/DEBUGGING b/kioslave/sftp/DEBUGGING
deleted file mode 100644
index 89ae8fe18..000000000
--- a/kioslave/sftp/DEBUGGING
+++ /dev/null
@@ -1,12 +0,0 @@
-DEBUGGING
-
-The best way to debug this slave is to send debug info to a
-file using 'kdebugDialog --fullmode'. Then you can 'tail -f' the file to
-see debug messages in real-time.
-
-I also suggest getting the openssh source and recompiling sftp-server to
-send messages to the auth log. This can be done in sftp-server.c be defining
-DEBUG_SFTP_SERVER.
-
-You can do the same with the ssh client by finding the two calls to log_init()
-in ssh.c and changing the last argument from 1 to 0 and recompiling.
diff --git a/kioslave/sftp/Makefile.am b/kioslave/sftp/Makefile.am
deleted file mode 100644
index abbb91323..000000000
--- a/kioslave/sftp/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-## Makefile.am of tdebase/kioslave/sftp
-
-INCLUDES = $(all_includes)
-AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -ltdetexteditor
-METASOURCES = AUTO
-
-####### Files
-
-check_PROGRAMS = ksshprocesstest
-
-ksshprocesstest_SOURCES = ksshprocesstest.cpp
-ksshprocesstest_LDADD = $(LIB_KSYCOCA) ksshprocess.lo process.lo atomicio.lo
-
-kde_module_LTLIBRARIES = kio_sftp.la
-
-kio_sftp_la_SOURCES = process.cpp atomicio.cpp kio_sftp.cpp sftpfileattr.cpp ksshprocess.cpp
-kio_sftp_la_LIBADD = $(LIB_KIO)
-kio_sftp_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-noinst_HEADERS = atomicio.h kio_sftp.h ksshprocess.h process.h sftpfileattr.h sftp.h
-
-kdelnk_DATA = sftp.protocol
-kdelnkdir = $(kde_servicesdir)
-
-messages:
- $(XGETTEXT) *.cpp -o $(podir)/kio_sftp.pot
diff --git a/kioslave/sftp/TODO b/kioslave/sftp/TODO
deleted file mode 100644
index 0f1411317..000000000
--- a/kioslave/sftp/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
-=====
-
-- Support for use of public keys, maybe ssh-agent, a key management app, etc.
-
diff --git a/kioslave/sftp/atomicio.cpp b/kioslave/sftp/atomicio.cpp
deleted file mode 100644
index 057f20fe9..000000000
--- a/kioslave/sftp/atomicio.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * 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.
- */
-
-//#include "includes.h"
-//RCSID("$OpenBSD: atomicio.c,v 1.9 2001/03/02 18:54:30 deraadt Exp $");
-
-//#include "xmalloc.h"
-#include "atomicio.h"
-#include <unistd.h>
-#include <errno.h>
-#include <kdebug.h>
-
-/*
- * ensure all of data on socket comes through. f==read || f==write
- */
-
-ssize_t atomicio(int fd, char *_s, size_t n, bool read)
-{
- char *s = _s;
- ssize_t res;
- ssize_t pos = 0;
-
- while (n > pos) {
- if( read)
- res = ::read(fd, s + pos, n - pos);
- else
- res = ::write(fd, s + pos, n - pos);
-
- switch (res) {
- case -1:
- kdDebug() << "atomicio(): errno=" << errno << endl;
-#ifdef EWOULDBLOCK
- if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
-#else
- if (errno == EINTR || errno == EAGAIN)
-#endif
- continue;
- case 0:
- return (res);
- default:
- pos += res;
- }
- }
- return (pos);
-}
diff --git a/kioslave/sftp/atomicio.h b/kioslave/sftp/atomicio.h
deleted file mode 100644
index 4468757d5..000000000
--- a/kioslave/sftp/atomicio.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef atomicio_h
-#define atomicio_h
-
-/* $OpenBSD: atomicio.h,v 1.3 2001/03/02 18:54:30 deraadt Exp $ */
-
-/*
- * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * 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.
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-
-/*
- * Ensure all of data on socket comes through. f==read || f==write
- */
-ssize_t atomicio(int fd, char *_s, size_t n, bool read = true);
-
-#endif
diff --git a/kioslave/sftp/kio_sftp.cpp b/kioslave/sftp/kio_sftp.cpp
deleted file mode 100644
index 73f5bfc6d..000000000
--- a/kioslave/sftp/kio_sftp.cpp
+++ /dev/null
@@ -1,2282 +0,0 @@
-/***************************************************************************
- sftp.cpp - description
- -------------------
- begin : Fri Jun 29 23:45:40 CDT 2001
- copyright : (C) 2001 by Lucas Fisher
- email : ljfisher@purdue.edu
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-/*
-DEBUGGING
-We are pretty much left with kdDebug messages for debugging. We can't use a gdb
-as described in the ioslave DEBUG.howto because tdeinit has to run in a terminal.
-Ssh will detect this terminal and ask for a password there, but will just get garbage.
-So we can't connect.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <fcntl.h>
-
-#include <tqcstring.h>
-#include <tqstring.h>
-#include <tqobject.h>
-#include <tqstrlist.h>
-#include <tqfile.h>
-#include <tqbuffer.h>
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <netdb.h>
-#include <string.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <kapplication.h>
-#include <kuser.h>
-#include <kdebug.h>
-#include <kmessagebox.h>
-#include <kinstance.h>
-#include <kglobal.h>
-#include <kstandarddirs.h>
-#include <klocale.h>
-#include <kurl.h>
-#include <kio/ioslave_defaults.h>
-#include <kmimetype.h>
-#include <kmimemagic.h>
-#include <klargefile.h>
-#include <kremoteencoding.h>
-
-#include "sftp.h"
-#include "kio_sftp.h"
-#include "atomicio.h"
-#include "sftpfileattr.h"
-#include "ksshprocess.h"
-
-
-using namespace TDEIO;
-extern "C"
-{
- int KDE_EXPORT kdemain( int argc, char **argv )
- {
- TDEInstance instance( "kio_sftp" );
-
- kdDebug(KIO_SFTP_DB) << "*** Starting kio_sftp " << endl;
-
- if (argc != 4) {
- kdDebug(KIO_SFTP_DB) << "Usage: kio_sftp protocol domain-socket1 domain-socket2" << endl;
- exit(-1);
- }
-
- sftpProtocol slave(argv[2], argv[3]);
- slave.dispatchLoop();
-
- kdDebug(KIO_SFTP_DB) << "*** kio_sftp Done" << endl;
- return 0;
- }
-}
-
-
-/*
- * This helper handles some special issues (blocking and interrupted
- * system call) when writing to a file handle.
- *
- * @return 0 on success or an error code on failure (ERR_COULD_NOT_WRITE,
- * ERR_DISK_FULL, ERR_CONNECTION_BROKEN).
- */
-static int writeToFile (int fd, const char *buf, size_t len)
-{
- while (len > 0)
- {
- ssize_t written = ::write(fd, buf, len);
- if (written >= 0)
- {
- buf += written;
- len -= written;
- continue;
- }
-
- switch(errno)
- {
- case EINTR:
- continue;
- case EPIPE:
- return ERR_CONNECTION_BROKEN;
- case ENOSPC:
- return ERR_DISK_FULL;
- default:
- return ERR_COULD_NOT_WRITE;
- }
- }
- return 0;
-}
-
-sftpProtocol::sftpProtocol(const TQCString &pool_socket, const TQCString &app_socket)
- : SlaveBase("kio_sftp", pool_socket, app_socket),
- mConnected(false), mPort(-1), mMsgId(0) {
- kdDebug(KIO_SFTP_DB) << "sftpProtocol(): pid = " << getpid() << endl;
-}
-
-
-sftpProtocol::~sftpProtocol() {
- kdDebug(KIO_SFTP_DB) << "~sftpProtocol(): pid = " << getpid() << endl;
- closeConnection();
-}
-
-/**
- * Type is a sftp packet type found in .sftp.h'.
- * Example: SSH2_FXP_READLINK, SSH2_FXP_RENAME, etc.
- *
- * Returns true if the type is supported by the sftp protocol
- * version negotiated by the client and server (sftpVersion).
- */
-bool sftpProtocol::isSupportedOperation(int type) {
- switch (type) {
- case SSH2_FXP_VERSION:
- case SSH2_FXP_STATUS:
- case SSH2_FXP_HANDLE:
- case SSH2_FXP_DATA:
- case SSH2_FXP_NAME:
- case SSH2_FXP_ATTRS:
- case SSH2_FXP_INIT:
- case SSH2_FXP_OPEN:
- case SSH2_FXP_CLOSE:
- case SSH2_FXP_READ:
- case SSH2_FXP_WRITE:
- case SSH2_FXP_LSTAT:
- case SSH2_FXP_FSTAT:
- case SSH2_FXP_SETSTAT:
- case SSH2_FXP_FSETSTAT:
- case SSH2_FXP_OPENDIR:
- case SSH2_FXP_READDIR:
- case SSH2_FXP_REMOVE:
- case SSH2_FXP_MKDIR:
- case SSH2_FXP_RMDIR:
- case SSH2_FXP_REALPATH:
- case SSH2_FXP_STAT:
- return true;
- case SSH2_FXP_RENAME:
- return sftpVersion >= 2 ? true : false;
- case SSH2_FXP_EXTENDED:
- case SSH2_FXP_EXTENDED_REPLY:
- case SSH2_FXP_READLINK:
- case SSH2_FXP_SYMLINK:
- return sftpVersion >= 3 ? true : false;
- default:
- kdDebug(KIO_SFTP_DB) << "isSupportedOperation(type:"
- << type << "): unrecognized operation type" << endl;
- break;
- }
-
- return false;
-}
-
-void sftpProtocol::copy(const KURL &src, const KURL &dest, int permissions, bool overwrite)
-{
- kdDebug(KIO_SFTP_DB) << "copy(): " << src << " -> " << dest << endl;
-
- bool srcLocal = src.isLocalFile();
- bool destLocal = dest.isLocalFile();
-
- if ( srcLocal && !destLocal ) // Copy file -> sftp
- sftpCopyPut(src, dest, permissions, overwrite);
- else if ( destLocal && !srcLocal ) // Copy sftp -> file
- sftpCopyGet(dest, src, permissions, overwrite);
- else
- error(ERR_UNSUPPORTED_ACTION, TQString::null);
-}
-
-void sftpProtocol::sftpCopyGet(const KURL& dest, const KURL& src, int mode, bool overwrite)
-{
- kdDebug(KIO_SFTP_DB) << "sftpCopyGet(): " << src << " -> " << dest << endl;
-
- // Attempt to establish a connection...
- openConnection();
- if( !mConnected )
- return;
-
- KDE_struct_stat buff_orig;
- TQCString dest_orig ( TQFile::encodeName(dest.path()) );
- bool origExists = (KDE_lstat( dest_orig.data(), &buff_orig ) != -1);
-
- if (origExists)
- {
- if (S_ISDIR(buff_orig.st_mode))
- {
- error(ERR_IS_DIRECTORY, dest.prettyURL());
- return;
- }
-
- if (!overwrite)
- {
- error(ERR_FILE_ALREADY_EXIST, dest.prettyURL());
- return;
- }
- }
-
- TDEIO::filesize_t offset = 0;
- TQCString dest_part ( dest_orig + ".part" );
-
- int fd = -1;
- bool partExists = false;
- bool markPartial = config()->readBoolEntry("MarkPartial", true);
-
- if (markPartial)
- {
- KDE_struct_stat buff_part;
- partExists = (KDE_stat( dest_part.data(), &buff_part ) != -1);
-
- if (partExists && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode))
- {
- if (canResume( buff_part.st_size ))
- {
- offset = buff_part.st_size;
- kdDebug(KIO_SFTP_DB) << "sftpCopyGet: Resuming @ " << offset << endl;
- }
- }
-
- if (offset > 0)
- {
- fd = KDE_open(dest_part.data(), O_RDWR);
- offset = KDE_lseek(fd, 0, SEEK_END);
- if (offset == 0)
- {
- error(ERR_CANNOT_RESUME, dest.prettyURL());
- return;
- }
- }
- else
- {
- // Set up permissions properly, based on what is done in file io-slave
- int openFlags = (O_CREAT | O_TRUNC | O_WRONLY);
- int initialMode = (mode == -1) ? 0666 : (mode | S_IWUSR);
- fd = KDE_open(dest_part.data(), openFlags, initialMode);
- }
- }
- else
- {
- // Set up permissions properly, based on what is done in file io-slave
- int openFlags = (O_CREAT | O_TRUNC | O_WRONLY);
- int initialMode = (mode == -1) ? 0666 : (mode | S_IWUSR);
- fd = KDE_open(dest_orig.data(), openFlags, initialMode);
- }
-
- if(fd == -1)
- {
- kdDebug(KIO_SFTP_DB) << "sftpCopyGet: Unable to open (" << fd << ") for writting." << endl;
- if (errno == EACCES)
- error (ERR_WRITE_ACCESS_DENIED, dest.prettyURL());
- else
- error (ERR_CANNOT_OPEN_FOR_WRITING, dest.prettyURL());
- return;
- }
-
- Status info = sftpGet(src, offset, fd);
- if ( info.code != 0 )
- {
- // Should we keep the partially downloaded file ??
- TDEIO::filesize_t size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
- if (info.size < size)
- ::remove(dest_part.data());
-
- error(info.code, info.text);
- return;
- }
-
- if (::close(fd) != 0)
- {
- error(ERR_COULD_NOT_WRITE, dest.prettyURL());
- return;
- }
-
- //
- if (markPartial)
- {
- if (::rename(dest_part.data(), dest_orig.data()) != 0)
- {
- error (ERR_CANNOT_RENAME_PARTIAL, dest_part);
- return;
- }
- }
-
- data(TQByteArray());
- kdDebug(KIO_SFTP_DB) << "sftpCopyGet(): emit finished()" << endl;
- finished();
-}
-
-sftpProtocol::Status sftpProtocol::sftpGet( const KURL& src, TDEIO::filesize_t offset, int fd )
-{
- int code;
- sftpFileAttr attr(remoteEncoding());
-
- Status res;
- res.code = 0;
- res.size = 0;
-
- kdDebug(KIO_SFTP_DB) << "sftpGet(): " << src << endl;
-
- // stat the file first to get its size
- if( (code = sftpStat(src, attr)) != SSH2_FX_OK ) {
- return doProcessStatus(code, src.prettyURL());
- }
-
- // We cannot get file if it is a directory
- if( attr.fileType() == S_IFDIR ) {
- res.text = src.prettyURL();
- res.code = ERR_IS_DIRECTORY;
- return res;
- }
-
- TDEIO::filesize_t fileSize = attr.fileSize();
- TQ_UINT32 pflags = SSH2_FXF_READ;
- attr.clear();
-
- TQByteArray handle;
- if( (code = sftpOpen(src, pflags, attr, handle)) != SSH2_FX_OK ) {
- res.text = src.prettyURL();
- res.code = ERR_CANNOT_OPEN_FOR_READING;
- return res;
- }
-
- // needed for determining mimetype
- // note: have to emit mimetype before emitting totalsize.
- TQByteArray buff;
- TQByteArray mimeBuffer;
-
- unsigned int oldSize;
- bool foundMimetype = false;
-
- // How big should each data packet be? Definitely not bigger than 64kb or
- // you will overflow the 2 byte size variable in a sftp packet.
- TQ_UINT32 len = 60*1024;
- code = SSH2_FX_OK;
-
- kdDebug(KIO_SFTP_DB) << "sftpGet(): offset = " << offset << endl;
- while( code == SSH2_FX_OK ) {
- if( (code = sftpRead(handle, offset, len, buff)) == SSH2_FX_OK ) {
- offset += buff.size();
-
- // save data for mimetype. Pretty much follows what is in the ftp ioslave
- if( !foundMimetype ) {
- oldSize = mimeBuffer.size();
- mimeBuffer.resize(oldSize + buff.size());
- memcpy(mimeBuffer.data()+oldSize, buff.data(), buff.size());
-
- if( mimeBuffer.size() > 1024 || offset == fileSize ) {
- // determine mimetype
- KMimeMagicResult* result =
- KMimeMagic::self()->findBufferFileType(mimeBuffer, src.fileName());
- kdDebug(KIO_SFTP_DB) << "sftpGet(): mimetype is " <<
- result->mimeType() << endl;
- mimeType(result->mimeType());
-
- // Always send the total size after emitting mime-type...
- totalSize(fileSize);
-
- if (fd == -1)
- data(mimeBuffer);
- else
- {
- if ( (res.code=writeToFile(fd, mimeBuffer.data(), mimeBuffer.size())) != 0 )
- return res;
- }
-
- processedSize(mimeBuffer.size());
- mimeBuffer.resize(0);
- foundMimetype = true;
- }
- }
- else {
- if (fd == -1)
- data(buff);
- else
- {
- if ( (res.code= writeToFile(fd, buff.data(), buff.size())) != 0 )
- return res;
- }
- processedSize(offset);
- }
- }
-
- /*
- Check if slave was killed. According to slavebase.h we need to leave
- the slave methods as soon as possible if the slave is killed. This
- allows the slave to be cleaned up properly.
- */
- if( wasKilled() ) {
- res.text = i18n("An internal error occurred. Please retry the request again.");
- res.code = ERR_UNKNOWN;
- return res;
- }
- }
-
- if( code != SSH2_FX_EOF ) {
- res.text = src.prettyURL();
- res.code = ERR_COULD_NOT_READ; // return here or still send empty array to indicate end of read?
- }
-
- res.size = offset;
- sftpClose(handle);
- processedSize (offset);
- return res;
-}
-
-void sftpProtocol::get(const KURL& url) {
- kdDebug(KIO_SFTP_DB) << "get(): " << url << endl ;
-
- openConnection();
- if( !mConnected )
- return;
-
- // Get resume offset
- TQ_UINT64 offset = config()->readUnsignedLongNumEntry("resume");
- if( offset > 0 ) {
- canResume();
- kdDebug(KIO_SFTP_DB) << "get(): canResume(), offset = " << offset << endl;
- }
-
- Status info = sftpGet(url, offset);
-
- if (info.code != 0)
- {
- error(info.code, info.text);
- return;
- }
-
- data(TQByteArray());
- kdDebug(KIO_SFTP_DB) << "get(): emit finished()" << endl;
- finished();
-}
-
-
-void sftpProtocol::setHost (const TQString& h, int port, const TQString& user, const TQString& pass)
-{
- kdDebug(KIO_SFTP_DB) << "setHost(): " << user << "@" << h << ":" << port << endl;
-
- if( mHost != h || mPort != port || user != mUsername || mPassword != pass )
- closeConnection();
-
- mHost = h;
-
- if( port > 0 )
- mPort = port;
- else {
- mPort = -1;
- }
-
- mUsername = user;
- mPassword = pass;
-
- if (user.isEmpty())
- {
- KUser u;
- mUsername = u.loginName();
- }
-}
-
-
-void sftpProtocol::openConnection() {
-
- if(mConnected)
- return;
-
- kdDebug(KIO_SFTP_DB) << "openConnection(): " << mUsername << "@"
- << mHost << ":" << mPort << endl;
-
- infoMessage( i18n("Opening SFTP connection to host <b>%1:%2</b>").arg(mHost).arg(mPort));
-
- if( mHost.isEmpty() ) {
- kdDebug(KIO_SFTP_DB) << "openConnection(): Need hostname..." << endl;
- error(ERR_UNKNOWN_HOST, i18n("No hostname specified"));
- return;
- }
-
- ////////////////////////////////////////////////////////////////////////////
- // Setup AuthInfo for use with password caching and the
- // password dialog box.
- AuthInfo info;
- info.url.setProtocol("sftp");
- info.url.setHost(mHost);
- info.url.setPort(mPort);
- info.url.setUser(mUsername);
- info.caption = i18n("SFTP Login");
- info.comment = "sftp://" + mHost + ":" + TQString::number(mPort);
- info.commentLabel = i18n("site:");
- info.username = mUsername;
- info.keepPassword = true;
-
- ///////////////////////////////////////////////////////////////////////////
- // Check for cached authentication info if a username AND password were
- // not specified in setHost().
- if( mUsername.isEmpty() && mPassword.isEmpty() ) {
- kdDebug(KIO_SFTP_DB) << "openConnection(): checking cache "
- << "info.username = " << info.username
- << ", info.url = " << info.url.prettyURL() << endl;
-
- if( checkCachedAuthentication(info) ) {
- mUsername = info.username;
- mPassword = info.password;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Now setup our ssh options. If we found a cached username
- // and password we set the SSH_PASSWORD and SSH_USERNAME
- // options right away. Otherwise we wait. The other options are
- // necessary for running sftp over ssh.
- KSshProcess::SshOpt opt; // a ssh option, this can be reused
- KSshProcess::SshOptList opts; // list of SshOpts
- KSshProcess::SshOptListIterator passwdIt; // points to the opt in opts that specifies the password
- KSshProcess::SshOptListIterator usernameIt;
-
-// opt.opt = KSshProcess::SSH_VERBOSE;
-// opts.append(opt);
-// opts.append(opt);
-
- if( mPort != -1 ) {
- opt.opt = KSshProcess::SSH_PORT;
- opt.num = mPort;
- opts.append(opt);
- }
-
- opt.opt = KSshProcess::SSH_SUBSYSTEM;
- opt.str = "sftp";
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_FORWARDX11;
- opt.boolean = false;
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_FORWARDAGENT;
- opt.boolean = false;
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_PROTOCOL;
- opt.num = 2;
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_HOST;
- opt.str = mHost;
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_ESCAPE_CHAR;
- opt.num = -1; // don't use any escape character
- opts.append(opt);
-
- // set the username and password if we have them
- if( !mUsername.isEmpty() ) {
- opt.opt = KSshProcess::SSH_USERNAME;
- opt.str = mUsername;
- usernameIt = opts.append(opt);
- }
-
- if( !mPassword.isEmpty() ) {
- opt.opt = KSshProcess::SSH_PASSWD;
- opt.str = mPassword;
- passwdIt = opts.append(opt);
- }
-
- ssh.setOptions(opts);
- ssh.printArgs();
-
- ///////////////////////////////////////////////////////////////////////////
- // Start the ssh connection process.
- //
-
- int err; // error code from KSshProcess
- TQString msg; // msg for dialog box
- TQString caption; // dialog box caption
- bool firstTime = true;
- bool dlgResult;
-
- while( !(mConnected = ssh.connect()) ) {
- err = ssh.error();
- kdDebug(KIO_SFTP_DB) << "openConnection(): "
- "Got " << err << " from KSshProcess::connect()" << endl;
-
- switch(err) {
- case KSshProcess::ERR_NEED_PASSWD:
- case KSshProcess::ERR_NEED_PASSPHRASE:
- // At this point we know that either we didn't set
- // an username or password in the ssh options list,
- // or what we did pass did not work. Therefore we
- // must prompt the user.
- if( err == KSshProcess::ERR_NEED_PASSPHRASE )
- info.prompt = i18n("Please enter your username and key passphrase.");
- else
- info.prompt = i18n("Please enter your username and password.");
-
- kdDebug(KIO_SFTP_DB) << "openConnection(): info.username = " << info.username
- << ", info.url = " << info.url.prettyURL() << endl;
-
- if( firstTime )
- dlgResult = openPassDlg(info);
- else
- dlgResult = openPassDlg(info, i18n("Incorrect username or password"));
-
- if( dlgResult ) {
- if( info.username.isEmpty() || info.password.isEmpty() ) {
- error(ERR_COULD_NOT_AUTHENTICATE,
- i18n("Please enter a username and password"));
- continue;
- }
- }
- else {
- // user canceled or dialog failed to open
- error(ERR_USER_CANCELED, TQString::null);
- kdDebug(KIO_SFTP_DB) << "openConnection(): user canceled, dlgResult = " << dlgResult << endl;
- closeConnection();
- return;
- }
-
- firstTime = false;
-
- // Check if the username has changed. SSH only accepts
- // the username at startup. If the username has changed
- // we must disconnect ssh, change the SSH_USERNAME
- // option, and reset the option list. We will also set
- // the password option so the user is not prompted for
- // it again.
- if( mUsername != info.username ) {
- kdDebug(KIO_SFTP_DB) << "openConnection(): Username changed from "
- << mUsername << " to " << info.username << endl;
-
- ssh.disconnect();
-
- // if we haven't yet added the username
- // or password option to the ssh options list then
- // the iterators will be equal to the empty iterator.
- // Create the opts now and add them to the opt list.
- if( usernameIt == KSshProcess::SshOptListIterator() ) {
- kdDebug(KIO_SFTP_DB) << "openConnection(): "
- "Adding username to options list" << endl;
- opt.opt = KSshProcess::SSH_USERNAME;
- usernameIt = opts.append(opt);
- }
-
- if( passwdIt == KSshProcess::SshOptListIterator() ) {
- kdDebug(KIO_SFTP_DB) << "openConnection(): "
- "Adding password to options list" << endl;
- opt.opt = KSshProcess::SSH_PASSWD;
- passwdIt = opts.append(opt);
- }
-
- (*usernameIt).str = info.username;
- (*passwdIt).str = info.password;
- ssh.setOptions(opts);
- ssh.printArgs();
- }
- else { // just set the password
- ssh.setPassword(info.password);
- }
-
- mUsername = info.username;
- mPassword = info.password;
-
- break;
-
- case KSshProcess::ERR_NEW_HOST_KEY:
- caption = i18n("Warning: Cannot verify host's identity.");
- msg = ssh.errorMsg();
- if( KMessageBox::Yes != messageBox(WarningYesNo, msg, caption) ) {
- closeConnection();
- error(ERR_USER_CANCELED, TQString::null);
- return;
- }
- ssh.acceptHostKey(true);
- break;
-
- case KSshProcess::ERR_DIFF_HOST_KEY:
- caption = i18n("Warning: Host's identity changed.");
- msg = ssh.errorMsg();
- if( KMessageBox::Yes != messageBox(WarningYesNo, msg, caption) ) {
- closeConnection();
- error(ERR_USER_CANCELED, TQString::null);
- return;
- }
- ssh.acceptHostKey(true);
- break;
-
- case KSshProcess::ERR_AUTH_FAILED:
- infoMessage(i18n("Authentication failed."));
- error(ERR_COULD_NOT_LOGIN, i18n("Authentication failed."));
- return;
-
- case KSshProcess::ERR_AUTH_FAILED_NEW_KEY:
- msg = ssh.errorMsg();
- error(ERR_COULD_NOT_LOGIN, msg);
- return;
-
- case KSshProcess::ERR_AUTH_FAILED_DIFF_KEY:
- msg = ssh.errorMsg();
- error(ERR_COULD_NOT_LOGIN, msg);
- return;
-
- case KSshProcess::ERR_CLOSED_BY_REMOTE_HOST:
- infoMessage(i18n("Connection failed."));
- caption = i18n("Connection closed by remote host.");
- msg = ssh.errorMsg();
- messageBox(Information, msg, caption);
- closeConnection();
- error(ERR_COULD_NOT_LOGIN, msg);
- return;
-
- case KSshProcess::ERR_INTERACT:
- case KSshProcess::ERR_INTERNAL:
- case KSshProcess::ERR_UNKNOWN:
- case KSshProcess::ERR_INVALID_STATE:
- case KSshProcess::ERR_CANNOT_LAUNCH:
- case KSshProcess::ERR_HOST_KEY_REJECTED:
- default:
- infoMessage(i18n("Connection failed."));
- caption = i18n("Unexpected SFTP error: %1").arg(err);
- msg = ssh.errorMsg();
- messageBox(Information, msg, caption);
- closeConnection();
- error(ERR_UNKNOWN, msg);
- return;
- }
- }
-
- // catch all in case we did something wrong above
- if( !mConnected ) {
- error(ERR_INTERNAL, TQString::null);
- return;
- }
-
- // Now send init packet.
- kdDebug(KIO_SFTP_DB) << "openConnection(): Sending SSH2_FXP_INIT packet." << endl;
- TQByteArray p;
- TQDataStream packet(p, IO_WriteOnly);
- packet << (TQ_UINT32)5; // packet length
- packet << (TQ_UINT8) SSH2_FXP_INIT; // packet type
- packet << (TQ_UINT32)SSH2_FILEXFER_VERSION; // client version
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream s(p, IO_ReadOnly);
- TQ_UINT32 version;
- TQ_UINT8 type;
- s >> type;
- kdDebug(KIO_SFTP_DB) << "openConnection(): Got type " << type << endl;
-
- if( type == SSH2_FXP_VERSION ) {
- s >> version;
- kdDebug(KIO_SFTP_DB) << "openConnection(): Got server version " << version << endl;
-
- // XXX Get extensions here
- sftpVersion = version;
-
- /* Server should return lowest common version supported by
- * client and server, but double check just in case.
- */
- if( sftpVersion > SSH2_FILEXFER_VERSION ) {
- error(ERR_UNSUPPORTED_PROTOCOL,
- i18n("SFTP version %1").arg(version));
- closeConnection();
- return;
- }
- }
- else {
- error(ERR_UNKNOWN, i18n("Protocol error."));
- closeConnection();
- return;
- }
-
- // Login succeeded!
- infoMessage(i18n("Successfully connected to %1").arg(mHost));
- info.url.setProtocol("sftp");
- info.url.setHost(mHost);
- info.url.setPort(mPort);
- info.url.setUser(mUsername);
- info.username = mUsername;
- info.password = mPassword;
- kdDebug(KIO_SFTP_DB) << "sftpProtocol(): caching info.username = " << info.username <<
- ", info.url = " << info.url.prettyURL() << endl;
- cacheAuthentication(info);
- mConnected = true;
- connected();
-
- mPassword.fill('x');
- info.password.fill('x');
-
- return;
-}
-
-void sftpProtocol::closeConnection() {
- kdDebug(KIO_SFTP_DB) << "closeConnection()" << endl;
- ssh.disconnect();
- mConnected = false;
-}
-
-void sftpProtocol::sftpCopyPut(const KURL& src, const KURL& dest, int permissions, bool overwrite) {
-
- KDE_struct_stat buff;
- TQCString file (TQFile::encodeName(src.path()));
-
- if (KDE_lstat(file.data(), &buff) == -1) {
- error (ERR_DOES_NOT_EXIST, src.prettyURL());
- return;
- }
-
- if (S_ISDIR (buff.st_mode)) {
- error (ERR_IS_DIRECTORY, src.prettyURL());
- return;
- }
-
- int fd = KDE_open (file.data(), O_RDONLY);
- if (fd == -1) {
- error (ERR_CANNOT_OPEN_FOR_READING, src.prettyURL());
- return;
- }
-
- totalSize (buff.st_size);
-
- sftpPut (dest, permissions, false, overwrite, fd);
-
- // Close the file descriptor...
- ::close( fd );
-}
-
-void sftpProtocol::sftpPut( const KURL& dest, int permissions, bool resume, bool overwrite, int fd ) {
-
- openConnection();
- if( !mConnected )
- return;
-
- kdDebug(KIO_SFTP_DB) << "sftpPut(): " << dest
- << ", resume=" << resume
- << ", overwrite=" << overwrite << endl;
-
- KURL origUrl( dest );
- sftpFileAttr origAttr(remoteEncoding());
- bool origExists = false;
-
- // Stat original (without part ext) to see if it already exists
- int code = sftpStat(origUrl, origAttr);
-
- if( code == SSH2_FX_OK ) {
- kdDebug(KIO_SFTP_DB) << "sftpPut(): <file> already exists" << endl;
-
- // Delete remote file if its size is zero
- if( origAttr.fileSize() == 0 ) {
- if( sftpRemove(origUrl, true) != SSH2_FX_OK ) {
- error(ERR_CANNOT_DELETE_ORIGINAL, origUrl.prettyURL());
- return;
- }
- }
- else {
- origExists = true;
- }
- }
- else if( code != SSH2_FX_NO_SUCH_FILE ) {
- processStatus(code, origUrl.prettyURL());
- return;
- }
-
- // Do not waste time/resources with more remote stat calls if the file exists
- // and we weren't instructed to overwrite it...
- if( origExists && !overwrite ) {
- error(ERR_FILE_ALREADY_EXIST, origUrl.prettyURL());
- return;
- }
-
- // Stat file with part ext to see if it already exists...
- KURL partUrl( origUrl );
- partUrl.setFileName( partUrl.fileName() + ".part" );
-
- TQ_UINT64 offset = 0;
- bool partExists = false;
- bool markPartial = config()->readBoolEntry("MarkPartial", true);
-
- if( markPartial ) {
-
- sftpFileAttr partAttr(remoteEncoding());
- code = sftpStat(partUrl, partAttr);
-
- if( code == SSH2_FX_OK ) {
- kdDebug(KIO_SFTP_DB) << "sftpPut(): .part file already exists" << endl;
- partExists = true;
- offset = partAttr.fileSize();
-
- // If for some reason, both the original and partial files exist,
- // skip resumption just like we would if the size of the partial
- // file is zero...
- if( origExists || offset == 0 )
- {
- if( sftpRemove(partUrl, true) != SSH2_FX_OK ) {
- error(ERR_CANNOT_DELETE_PARTIAL, partUrl.prettyURL());
- return;
- }
-
- if( sftpRename(origUrl, partUrl) != SSH2_FX_OK ) {
- error(ERR_CANNOT_RENAME_ORIGINAL, origUrl.prettyURL());
- return;
- }
-
- offset = 0;
- }
- else if( !overwrite && !resume ) {
- if (fd != -1)
- resume = (KDE_lseek(fd, offset, SEEK_SET) != -1);
- else
- resume = canResume( offset );
-
- kdDebug(KIO_SFTP_DB) << "sftpPut(): can resume = " << resume
- << ", offset = " << offset;
-
- if( !resume ) {
- error(ERR_FILE_ALREADY_EXIST, partUrl.prettyURL());
- return;
- }
- }
- else {
- offset = 0;
- }
- }
- else if( code == SSH2_FX_NO_SUCH_FILE ) {
- if( origExists && sftpRename(origUrl, partUrl) != SSH2_FX_OK ) {
- error(ERR_CANNOT_RENAME_ORIGINAL, origUrl.prettyURL());
- return;
- }
- }
- else {
- processStatus(code, partUrl.prettyURL());
- return;
- }
- }
-
- // Determine the url we will actually write to...
- KURL writeUrl (markPartial ? partUrl:origUrl);
-
- TQ_UINT32 pflags = 0;
- if( overwrite && !resume )
- pflags = SSH2_FXF_WRITE | SSH2_FXF_CREAT | SSH2_FXF_TRUNC;
- else if( !overwrite && !resume )
- pflags = SSH2_FXF_WRITE | SSH2_FXF_CREAT | SSH2_FXF_EXCL;
- else if( overwrite && resume )
- pflags = SSH2_FXF_WRITE | SSH2_FXF_CREAT;
- else if( !overwrite && resume )
- pflags = SSH2_FXF_WRITE | SSH2_FXF_CREAT | SSH2_FXF_APPEND;
-
- sftpFileAttr attr(remoteEncoding());
- TQByteArray handle;
-
- // Set the permissions of the file we write to if it didn't already exist
- // and the permission info is supplied, i.e it is not -1
- if( !partExists && !origExists && permissions != -1)
- attr.setPermissions(permissions);
-
- code = sftpOpen( writeUrl, pflags, attr, handle );
- if( code != SSH2_FX_OK ) {
-
- // Rename the file back to its original name if a
- // put fails due to permissions problems...
- if( markPartial && overwrite ) {
- (void) sftpRename(partUrl, origUrl);
- writeUrl = origUrl;
- }
-
- if( code == SSH2_FX_FAILURE ) { // assume failure means file exists
- error(ERR_FILE_ALREADY_EXIST, writeUrl.prettyURL());
- return;
- }
- else {
- processStatus(code, writeUrl.prettyURL());
- return;
- }
- }
-
- long nbytes;
- TQByteArray buff;
-
- do {
-
- if( fd != -1 ) {
- buff.resize( 16*1024 );
- if ( (nbytes = ::read(fd, buff.data(), buff.size())) > -1 )
- buff.resize( nbytes );
- }
- else {
- dataReq();
- nbytes = readData( buff );
- }
-
- if( nbytes >= 0 ) {
- if( (code = sftpWrite(handle, offset, buff)) != SSH2_FX_OK ) {
- error(ERR_COULD_NOT_WRITE, dest.prettyURL());
- return;
- }
-
- offset += nbytes;
- processedSize(offset);
-
- /* Check if slave was killed. According to slavebase.h we
- * need to leave the slave methods as soon as possible if
- * the slave is killed. This allows the slave to be cleaned
- * up properly.
- */
- if( wasKilled() ) {
- sftpClose(handle);
- closeConnection();
- error(ERR_UNKNOWN, i18n("An internal error occurred. Please try again."));
- return;
- }
- }
-
- } while( nbytes > 0 );
-
- if( nbytes < 0 ) {
- sftpClose(handle);
-
- if( markPartial ) {
- // Remove remote file if it smaller than our keep size
- uint minKeepSize = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
-
- if( sftpStat(writeUrl, attr) == SSH2_FX_OK ) {
- if( attr.fileSize() < minKeepSize ) {
- sftpRemove(writeUrl, true);
- }
- }
- }
-
- error( ERR_UNKNOWN, i18n("Unknown error was encountered while copying the file "
- "to '%1'. Please try again.").arg(dest.host()) );
- return;
- }
-
- if( (code = sftpClose(handle)) != SSH2_FX_OK ) {
- error(ERR_COULD_NOT_WRITE, writeUrl.prettyURL());
- return;
- }
-
- // If wrote to a partial file, then remove the part ext
- if( markPartial ) {
- if( sftpRename(partUrl, origUrl) != SSH2_FX_OK ) {
- error(ERR_CANNOT_RENAME_PARTIAL, origUrl.prettyURL());
- return;
- }
- }
-
- finished();
-}
-
-void sftpProtocol::put ( const KURL& url, int permissions, bool overwrite, bool resume ){
- kdDebug(KIO_SFTP_DB) << "put(): " << url << ", overwrite = " << overwrite
- << ", resume = " << resume << endl;
-
- sftpPut( url, permissions, resume, overwrite );
-}
-
-void sftpProtocol::stat ( const KURL& url ){
- kdDebug(KIO_SFTP_DB) << "stat(): " << url << endl;
-
- openConnection();
- if( !mConnected )
- return;
-
- // If the stat URL has no path, do not attempt to determine the real
- // path and do a redirect. KRun will simply ignore such requests.
- // Instead, simply return the mime-type as a directory...
- if( !url.hasPath() ) {
- UDSEntry entry;
- UDSAtom atom;
-
- atom.m_uds = TDEIO::UDS_NAME;
- atom.m_str = TQString::null;
- entry.append( atom );
-
- atom.m_uds = TDEIO::UDS_FILE_TYPE;
- atom.m_long = S_IFDIR;
- entry.append( atom );
-
- atom.m_uds = TDEIO::UDS_ACCESS;
- atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- entry.append( atom );
-
- atom.m_uds = TDEIO::UDS_USER;
- atom.m_str = mUsername;
- entry.append( atom );
- atom.m_uds = TDEIO::UDS_GROUP;
- entry.append( atom );
-
- // no size
- statEntry( entry );
- finished();
- return;
- }
-
- int code;
- sftpFileAttr attr(remoteEncoding());
- if( (code = sftpStat(url, attr)) != SSH2_FX_OK ) {
- processStatus(code, url.prettyURL());
- return;
- }
- else {
- //kdDebug() << "We sent and received stat packet ok" << endl;
- attr.setFilename(url.fileName());
- statEntry(attr.entry());
- }
-
- finished();
-
- kdDebug(KIO_SFTP_DB) << "stat: END" << endl;
- return;
-}
-
-
-void sftpProtocol::mimetype ( const KURL& url ){
- kdDebug(KIO_SFTP_DB) << "mimetype(): " << url << endl;
-
- openConnection();
- if( !mConnected )
- return;
-
- TQ_UINT32 pflags = SSH2_FXF_READ;
- TQByteArray handle, mydata;
- sftpFileAttr attr(remoteEncoding());
- int code;
- if( (code = sftpOpen(url, pflags, attr, handle)) != SSH2_FX_OK ) {
- error(ERR_CANNOT_OPEN_FOR_READING, url.prettyURL());
- return;
- }
-
- TQ_UINT32 len = 1024; // Get first 1k for determining mimetype
- TQ_UINT64 offset = 0;
- code = SSH2_FX_OK;
- while( offset < len && code == SSH2_FX_OK ) {
- if( (code = sftpRead(handle, offset, len, mydata)) == SSH2_FX_OK ) {
- data(mydata);
- offset += mydata.size();
- processedSize(offset);
-
- kdDebug(KIO_SFTP_DB) << "mimetype(): offset = " << offset << endl;
- }
- }
-
-
- data(TQByteArray());
- processedSize(offset);
- sftpClose(handle);
- finished();
- kdDebug(KIO_SFTP_DB) << "mimetype(): END" << endl;
-}
-
-
-void sftpProtocol::listDir(const KURL& url) {
- kdDebug(KIO_SFTP_DB) << "listDir(): " << url << endl;
-
- openConnection();
- if( !mConnected )
- return;
-
- if( !url.hasPath() ) {
- KURL newUrl ( url );
- if( sftpRealPath(url, newUrl) == SSH2_FX_OK ) {
- kdDebug(KIO_SFTP_DB) << "listDir: Redirecting to " << newUrl << endl;
- redirection(newUrl);
- finished();
- return;
- }
- }
-
- int code;
- TQByteArray handle;
-
- if( (code = sftpOpenDirectory(url, handle)) != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "listDir(): open directory failed" << endl;
- processStatus(code, url.prettyURL());
- return;
- }
-
-
- code = SSH2_FX_OK;
- while( code == SSH2_FX_OK ) {
- code = sftpReadDir(handle, url);
- if( code != SSH2_FX_OK && code != SSH2_FX_EOF )
- processStatus(code, url.prettyURL());
- kdDebug(KIO_SFTP_DB) << "listDir(): return code = " << code << endl;
- }
-
- if( (code = sftpClose(handle)) != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "listdir(): closing of directory failed" << endl;
- processStatus(code, url.prettyURL());
- return;
- }
-
- finished();
- kdDebug(KIO_SFTP_DB) << "listDir(): END" << endl;
-}
-
-/** Make a directory.
- OpenSSH does not follow the internet draft for sftp in this case.
- The format of the mkdir request expected by OpenSSH sftp server is:
- uint32 id
- string path
- ATTR attr
- */
-void sftpProtocol::mkdir(const KURL&url, int permissions){
-
- kdDebug(KIO_SFTP_DB) << "mkdir() creating dir: " << url.path() << endl;
-
- openConnection();
- if( !mConnected )
- return;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- sftpFileAttr attr(remoteEncoding());
-
- if (permissions != -1)
- attr.setPermissions(permissions);
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << TQ_UINT32(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len + attr.size());
- s << (TQ_UINT8)SSH2_FXP_MKDIR;
- s << id;
- s.writeBytes(path.data(), len);
- s << attr;
-
- kdDebug(KIO_SFTP_DB) << "mkdir(): packet size is " << p.size() << endl;
-
- putPacket(p);
- getPacket(p);
-
- TQ_UINT8 type;
- TQDataStream r(p, IO_ReadOnly);
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "mkdir: sftp packet id mismatch" << endl;
- error(ERR_COULD_NOT_MKDIR, path);
- finished();
- return;
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "mkdir(): unexpected packet type of " << type << endl;
- error(ERR_COULD_NOT_MKDIR, path);
- finished();
- return;
- }
-
- int code;
- r >> code;
- if( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "mkdir(): failed with code " << code << endl;
-
- // Check if mkdir failed because the directory already exists so that
- // we can return the appropriate message...
- sftpFileAttr dirAttr(remoteEncoding());
- if ( sftpStat(url, dirAttr) == SSH2_FX_OK )
- {
- error( ERR_DIR_ALREADY_EXIST, url.prettyURL() );
- return;
- }
-
- error(ERR_COULD_NOT_MKDIR, path);
- }
-
- finished();
-}
-
-void sftpProtocol::rename(const KURL& src, const KURL& dest, bool overwrite){
- kdDebug(KIO_SFTP_DB) << "rename(" << src << " -> " << dest << ")" << endl;
-
- if (!isSupportedOperation(SSH2_FXP_RENAME)) {
- error(ERR_UNSUPPORTED_ACTION,
- i18n("The remote host does not support renaming files."));
- return;
- }
-
- openConnection();
- if( !mConnected )
- return;
-
- // Always stat the destination before attempting to rename
- // a file or a directory...
- sftpFileAttr attr(remoteEncoding());
- int code = sftpStat(dest, attr);
-
- // If the destination directory, exists tell it to the job
- // so it the proper action can be presented to the user...
- if( code == SSH2_FX_OK )
- {
- if (!overwrite)
- {
- if ( S_ISDIR(attr.permissions()) )
- error( TDEIO::ERR_DIR_ALREADY_EXIST, dest.url() );
- else
- error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.url() );
- return;
- }
-
- // If overwrite is specified, then simply remove the existing file/dir first...
- if( (code = sftpRemove( dest, !S_ISDIR(attr.permissions()) )) != SSH2_FX_OK )
- {
- processStatus(code);
- return;
- }
- }
-
- // Do the renaming...
- if( (code = sftpRename(src, dest)) != SSH2_FX_OK ) {
- processStatus(code);
- return;
- }
-
- finished();
- kdDebug(KIO_SFTP_DB) << "rename(): END" << endl;
-}
-
-void sftpProtocol::symlink(const TQString& target, const KURL& dest, bool overwrite){
- kdDebug(KIO_SFTP_DB) << "symlink()" << endl;
-
- if (!isSupportedOperation(SSH2_FXP_SYMLINK)) {
- error(ERR_UNSUPPORTED_ACTION,
- i18n("The remote host does not support creating symbolic links."));
- return;
- }
-
- openConnection();
- if( !mConnected )
- return;
-
- int code;
- bool failed = false;
- if( (code = sftpSymLink(target, dest)) != SSH2_FX_OK ) {
- if( overwrite ) { // try to delete the destination
- sftpFileAttr attr(remoteEncoding());
- if( (code = sftpStat(dest, attr)) != SSH2_FX_OK ) {
- failed = true;
- }
- else {
- if( (code = sftpRemove(dest, !S_ISDIR(attr.permissions())) ) != SSH2_FX_OK ) {
- failed = true;
- }
- else {
- // XXX what if rename fails again? We have lost the file.
- // Maybe rename dest to a temporary name first? If rename is
- // successful, then delete?
- if( (code = sftpSymLink(target, dest)) != SSH2_FX_OK )
- failed = true;
- }
- }
- }
- else if( code == SSH2_FX_FAILURE ) {
- error(ERR_FILE_ALREADY_EXIST, dest.prettyURL());
- return;
- }
- else
- failed = true;
- }
-
- // What error code do we return? Code for the original symlink command
- // or for the last command or for both? The second one is implemented here.
- if( failed )
- processStatus(code);
-
- finished();
-}
-
-void sftpProtocol::chmod(const KURL& url, int permissions){
- TQString perms;
- perms.setNum(permissions, 8);
- kdDebug(KIO_SFTP_DB) << "chmod(" << url << ", " << perms << ")" << endl;
-
- openConnection();
- if( !mConnected )
- return;
-
- sftpFileAttr attr(remoteEncoding());
-
- if (permissions != -1)
- attr.setPermissions(permissions);
-
- int code;
- if( (code = sftpSetStat(url, attr)) != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "chmod(): sftpSetStat failed with error " << code << endl;
- if( code == SSH2_FX_FAILURE )
- error(ERR_CANNOT_CHMOD, TQString::null);
- else
- processStatus(code, url.prettyURL());
- }
- finished();
-}
-
-
-void sftpProtocol::del(const KURL &url, bool isfile){
- kdDebug(KIO_SFTP_DB) << "del(" << url << ", " << (isfile?"file":"dir") << ")" << endl;
-
- openConnection();
- if( !mConnected )
- return;
-
- int code;
- if( (code = sftpRemove(url, isfile)) != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "del(): sftpRemove failed with error code " << code << endl;
- processStatus(code, url.prettyURL());
- }
- finished();
-}
-
-void sftpProtocol::slave_status() {
- kdDebug(KIO_SFTP_DB) << "slave_status(): connected to "
- << mHost << "? " << mConnected << endl;
-
- slaveStatus ((mConnected ? mHost : TQString::null), mConnected);
-}
-
-bool sftpProtocol::getPacket(TQByteArray& msg) {
- TQByteArray buf(4096);
-
- // Get the message length...
- ssize_t len = atomicio(ssh.stdioFd(), buf.data(), 4, true /*read*/);
-
- if( len == 0 || len == -1 ) {
- kdDebug(KIO_SFTP_DB) << "getPacket(): read of packet length failed, ret = "
- << len << ", error =" << strerror(errno) << endl;
- closeConnection();
- error( ERR_CONNECTION_BROKEN, mHost);
- msg.resize(0);
- return false;
- }
-
- uint msgLen;
- TQDataStream s(buf, IO_ReadOnly);
- s >> msgLen;
-
- //kdDebug(KIO_SFTP_DB) << "getPacket(): Message size = " << msgLen << endl;
-
- msg.resize(0);
-
- TQBuffer b( msg );
- b.open( IO_WriteOnly );
-
- while( msgLen ) {
- len = atomicio(ssh.stdioFd(), buf.data(), kMin((uint)buf.size(), msgLen), true /*read*/);
-
- if( len == 0 || len == -1) {
- TQString errmsg;
- if (len == 0)
- errmsg = i18n("Connection closed");
- else
- errmsg = i18n("Could not read SFTP packet");
- kdDebug(KIO_SFTP_DB) << "getPacket(): nothing to read, ret = " <<
- len << ", error =" << strerror(errno) << endl;
- closeConnection();
- error(ERR_CONNECTION_BROKEN, errmsg);
- b.close();
- return false;
- }
-
- b.writeBlock(buf.data(), len);
-
- //kdDebug(KIO_SFTP_DB) << "getPacket(): Read Message size = " << len << endl;
- //kdDebug(KIO_SFTP_DB) << "getPacket(): Copy Message size = " << msg.size() << endl;
-
- msgLen -= len;
- }
-
- b.close();
-
- return true;
-}
-
-/** Send an sftp packet to stdin of the ssh process. */
-bool sftpProtocol::putPacket(TQByteArray& p){
-// kdDebug(KIO_SFTP_DB) << "putPacket(): size == " << p.size() << endl;
- int ret;
- ret = atomicio(ssh.stdioFd(), p.data(), p.size(), false /*write*/);
- if( ret <= 0 ) {
- kdDebug(KIO_SFTP_DB) << "putPacket(): write failed, ret =" << ret <<
- ", error = " << strerror(errno) << endl;
- return false;
- }
-
- return true;
-}
-
-/** Used to have the server canonicalize any given path name to an absolute path.
-This is useful for converting path names containing ".." components or relative
-pathnames without a leading slash into absolute paths.
-Returns the canonicalized url. */
-int sftpProtocol::sftpRealPath(const KURL& url, KURL& newUrl){
-
- kdDebug(KIO_SFTP_DB) << "sftpRealPath(" << url << ", newUrl)" << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << TQ_UINT32(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len);
- s << (TQ_UINT8)SSH2_FXP_REALPATH;
- s << id;
- s.writeBytes(path.data(), len);
-
- putPacket(p);
- getPacket(p);
-
- TQ_UINT8 type;
- TQDataStream r(p, IO_ReadOnly);
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpRealPath: sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type == SSH2_FXP_STATUS ) {
- TQ_UINT32 code;
- r >> code;
- return code;
- }
-
- if( type != SSH2_FXP_NAME ) {
- kdError(KIO_SFTP_DB) << "sftpRealPath(): unexpected packet type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 count;
- r >> count;
- if( count != 1 ) {
- kdError(KIO_SFTP_DB) << "sftpRealPath(): Bad number of file attributes for realpath command" << endl;
- return -1;
- }
-
- TQCString newPath;
- r >> newPath;
-
- newPath.truncate(newPath.size());
- if (newPath.isEmpty())
- newPath = "/";
- newUrl.setPath(newPath);
-
- return SSH2_FX_OK;
-}
-
-sftpProtocol::Status sftpProtocol::doProcessStatus(TQ_UINT8 code, const TQString& message)
-{
- Status res;
- res.code = 0;
- res.size = 0;
- res.text = message;
-
- switch(code)
- {
- case SSH2_FX_OK:
- case SSH2_FX_EOF:
- break;
- case SSH2_FX_NO_SUCH_FILE:
- res.code = ERR_DOES_NOT_EXIST;
- break;
- case SSH2_FX_PERMISSION_DENIED:
- res.code = ERR_ACCESS_DENIED;
- break;
- case SSH2_FX_FAILURE:
- res.text = i18n("SFTP command failed for an unknown reason.");
- res.code = ERR_UNKNOWN;
- break;
- case SSH2_FX_BAD_MESSAGE:
- res.text = i18n("The SFTP server received a bad message.");
- res.code = ERR_UNKNOWN;
- break;
- case SSH2_FX_OP_UNSUPPORTED:
- res.text = i18n("You attempted an operation unsupported by the SFTP server.");
- res.code = ERR_UNKNOWN;
- break;
- default:
- res.text = i18n("Error code: %1").arg(code);
- res.code = ERR_UNKNOWN;
- }
-
- return res;
-}
-
-/** Process SSH_FXP_STATUS packets. */
-void sftpProtocol::processStatus(TQ_UINT8 code, const TQString& message){
- Status st = doProcessStatus( code, message );
- if( st.code != 0 )
- error( st.code, st.text );
-}
-
-/** Opens a directory handle for url.path. Returns true if succeeds. */
-int sftpProtocol::sftpOpenDirectory(const KURL& url, TQByteArray& handle){
-
- kdDebug(KIO_SFTP_DB) << "sftpOpenDirectory(" << url << ", handle)" << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len);
- s << (TQ_UINT8)SSH2_FXP_OPENDIR;
- s << (TQ_UINT32)id;
- s.writeBytes(path.data(), len);
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpOpenDirectory: sftp packet id mismatch: " <<
- "expected " << expectedId << ", got " << id << endl;
- return -1;
- }
-
- if( type == SSH2_FXP_STATUS ) {
- TQ_UINT32 errCode;
- r >> errCode;
- return errCode;
- }
-
- if( type != SSH2_FXP_HANDLE ) {
- kdError(KIO_SFTP_DB) << "sftpOpenDirectory: unexpected message type of " << type << endl;
- return -1;
- }
-
- r >> handle;
- if( handle.size() > 256 ) {
- kdError(KIO_SFTP_DB) << "sftpOpenDirectory: handle exceeds max length" << endl;
- return -1;
- }
-
- kdDebug(KIO_SFTP_DB) << "sftpOpenDirectory: handle (" << handle.size() << "): [" << handle << "]" << endl;
- return SSH2_FX_OK;
-}
-
-/** Closes a directory or file handle. */
-int sftpProtocol::sftpClose(const TQByteArray& handle){
-
- kdDebug(KIO_SFTP_DB) << "sftpClose()" << endl;
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + handle.size());
- s << (TQ_UINT8)SSH2_FXP_CLOSE;
- s << (TQ_UINT32)id;
- s << handle;
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpClose: sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "sftpClose: unexpected message type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 code;
- r >> code;
- if( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "sftpClose: close failed with err code " << code << endl;
- }
-
- return code;
-}
-
-/** Set a files attributes. */
-int sftpProtocol::sftpSetStat(const KURL& url, const sftpFileAttr& attr){
-
- kdDebug(KIO_SFTP_DB) << "sftpSetStat(" << url << ", attr)" << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len + attr.size());
- s << (TQ_UINT8)SSH2_FXP_SETSTAT;
- s << (TQ_UINT32)id;
- s.writeBytes(path.data(), len);
- s << attr;
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpSetStat(): sftp packet id mismatch" << endl;
- return -1;
- // XXX How do we do a fatal error?
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "sftpSetStat(): unexpected message type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 code;
- r >> code;
- if( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "sftpSetStat(): set stat failed with err code " << code << endl;
- }
-
- return code;
-}
-
-/** Sends a sftp command to remove a file or directory. */
-int sftpProtocol::sftpRemove(const KURL& url, bool isfile){
-
- kdDebug(KIO_SFTP_DB) << "sftpRemove(): " << url << ", isFile ? " << isfile << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len);
- s << (TQ_UINT8)(isfile ? SSH2_FXP_REMOVE : SSH2_FXP_RMDIR);
- s << (TQ_UINT32)id;
- s.writeBytes(path.data(), len);
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "del(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "del(): unexpected message type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 code;
- r >> code;
- if( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "del(): del failed with err code " << code << endl;
- }
-
- return code;
-}
-
-/** Send a sftp command to rename a file or directoy. */
-int sftpProtocol::sftpRename(const KURL& src, const KURL& dest){
-
- kdDebug(KIO_SFTP_DB) << "sftpRename(" << src << " -> " << dest << ")" << endl;
-
- TQCString srcPath = remoteEncoding()->encode(src.path());
- TQCString destPath = remoteEncoding()->encode(dest.path());
-
- uint slen = srcPath.length();
- uint dlen = destPath.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ +
- 4 /*str length*/ + slen +
- 4 /*str length*/ + dlen);
- s << (TQ_UINT8)SSH2_FXP_RENAME;
- s << (TQ_UINT32)id;
- s.writeBytes(srcPath.data(), slen);
- s.writeBytes(destPath.data(), dlen);
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpRename(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "sftpRename(): unexpected message type of " << type << endl;
- return -1;
- }
-
- int code;
- r >> code;
- if( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "sftpRename(): rename failed with err code " << code << endl;
- }
-
- return code;
-}
-/** Get directory listings. */
-int sftpProtocol::sftpReadDir(const TQByteArray& handle, const KURL& url){
- // url is needed so we can lookup the link destination
- kdDebug(KIO_SFTP_DB) << "sftpReadDir(): " << url << endl;
-
- TQ_UINT32 id, expectedId, count;
- TQ_UINT8 type;
-
- sftpFileAttr attr (remoteEncoding());
- attr.setDirAttrsFlag(true);
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- id = expectedId = mMsgId++;
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + handle.size());
- s << (TQ_UINT8)SSH2_FXP_READDIR;
- s << (TQ_UINT32)id;
- s << handle;
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- r >> type >> id;
-
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpReadDir(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- int code;
- if( type == SSH2_FXP_STATUS ) {
- r >> code;
- return code;
- }
-
- if( type != SSH2_FXP_NAME ) {
- kdError(KIO_SFTP_DB) << "kio_sftpProtocl::sftpReadDir(): Unexpected message" << endl;
- return -1;
- }
-
- r >> count;
- kdDebug(KIO_SFTP_DB) << "sftpReadDir(): got " << count << " entries" << endl;
-
- while(count--) {
- r >> attr;
-
- if( S_ISLNK(attr.permissions()) ) {
- KURL myurl ( url );
- myurl.addPath(attr.filename());
-
- // Stat the symlink to find out its type...
- sftpFileAttr attr2 (remoteEncoding());
- (void) sftpStat(myurl, attr2);
-
- attr.setLinkType(attr2.linkType());
- attr.setLinkDestination(attr2.linkDestination());
- }
-
- listEntry(attr.entry(), false);
- }
-
- listEntry(attr.entry(), true);
-
- return SSH2_FX_OK;
-}
-
-int sftpProtocol::sftpReadLink(const KURL& url, TQString& target){
-
- kdDebug(KIO_SFTP_DB) << "sftpReadLink(): " << url << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- //kdDebug(KIO_SFTP_DB) << "sftpReadLink(): Encoded Path: " << path << endl;
- //kdDebug(KIO_SFTP_DB) << "sftpReadLink(): Encoded Size: " << len << endl;
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len);
- s << (TQ_UINT8)SSH2_FXP_READLINK;
- s << id;
- s.writeBytes(path.data(), len);
-
-
- putPacket(p);
- getPacket(p);
-
- TQ_UINT8 type;
- TQDataStream r(p, IO_ReadOnly);
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpReadLink(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type == SSH2_FXP_STATUS ) {
- TQ_UINT32 code;
- r >> code;
- kdDebug(KIO_SFTP_DB) << "sftpReadLink(): read link failed with code " << code << endl;
- return code;
- }
-
- if( type != SSH2_FXP_NAME ) {
- kdError(KIO_SFTP_DB) << "sftpReadLink(): unexpected packet type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 count;
- r >> count;
- if( count != 1 ) {
- kdError(KIO_SFTP_DB) << "sftpReadLink(): Bad number of file attributes for realpath command" << endl;
- return -1;
- }
-
- TQCString linkAddress;
- r >> linkAddress;
-
- linkAddress.truncate(linkAddress.size());
- kdDebug(KIO_SFTP_DB) << "sftpReadLink(): Link address: " << linkAddress << endl;
-
- target = remoteEncoding()->decode(linkAddress);
-
- return SSH2_FX_OK;
-}
-
-int sftpProtocol::sftpSymLink(const TQString& _target, const KURL& dest){
-
- TQCString destPath = remoteEncoding()->encode(dest.path());
- TQCString target = remoteEncoding()->encode(_target);
- uint dlen = destPath.length();
- uint tlen = target.length();
-
- kdDebug(KIO_SFTP_DB) << "sftpSymLink(" << target << " -> " << destPath << ")" << endl;
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ +
- 4 /*str length*/ + tlen +
- 4 /*str length*/ + dlen);
- s << (TQ_UINT8)SSH2_FXP_SYMLINK;
- s << (TQ_UINT32)id;
- s.writeBytes(target.data(), tlen);
- s.writeBytes(destPath.data(), dlen);
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpSymLink(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "sftpSymLink(): unexpected message type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 code;
- r >> code;
- if( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "sftpSymLink(): rename failed with err code " << code << endl;
- }
-
- return code;
-}
-
-/** Stats a file. */
-int sftpProtocol::sftpStat(const KURL& url, sftpFileAttr& attr) {
-
- kdDebug(KIO_SFTP_DB) << "sftpStat(): " << url << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ + 4 /*str length*/ + len);
- s << (TQ_UINT8)SSH2_FXP_LSTAT;
- s << (TQ_UINT32)id;
- s.writeBytes(path.data(), len);
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpStat(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type == SSH2_FXP_STATUS ) {
- TQ_UINT32 errCode;
- r >> errCode;
- kdError(KIO_SFTP_DB) << "sftpStat(): stat failed with code " << errCode << endl;
- return errCode;
- }
-
- if( type != SSH2_FXP_ATTRS ) {
- kdError(KIO_SFTP_DB) << "sftpStat(): unexpected message type of " << type << endl;
- return -1;
- }
-
- r >> attr;
- attr.setFilename(url.fileName());
- kdDebug(KIO_SFTP_DB) << "sftpStat(): " << attr << endl;
-
- // If the stat'ed resource is a symlink, perform a recursive stat
- // to determine the actual destination's type (file/dir).
- if( S_ISLNK(attr.permissions()) && isSupportedOperation(SSH2_FXP_READLINK) ) {
-
- TQString target;
- int code = sftpReadLink( url, target );
-
- if ( code != SSH2_FX_OK ) {
- kdError(KIO_SFTP_DB) << "sftpStat(): Unable to stat symlink destination" << endl;
- return -1;
- }
-
- kdDebug(KIO_SFTP_DB) << "sftpStat(): Resource is a symlink to -> " << target << endl;
-
- KURL dest( url );
- if( target[0] == '/' )
- dest.setPath(target);
- else
- dest.setFileName(target);
-
- dest.cleanPath();
-
- // Ignore symlinks that point to themselves...
- if ( dest != url ) {
-
- sftpFileAttr attr2 (remoteEncoding());
- (void) sftpStat(dest, attr2);
-
- if (attr2.linkType() == 0)
- attr.setLinkType(attr2.fileType());
- else
- attr.setLinkType(attr2.linkType());
-
- attr.setLinkDestination(target);
-
- kdDebug(KIO_SFTP_DB) << "sftpStat(): File type: " << attr.fileType() << endl;
- }
- }
-
- return SSH2_FX_OK;
-}
-
-
-int sftpProtocol::sftpOpen(const KURL& url, const TQ_UINT32 pflags,
- const sftpFileAttr& attr, TQByteArray& handle) {
- kdDebug(KIO_SFTP_DB) << "sftpOpen(" << url << ", handle" << endl;
-
- TQCString path = remoteEncoding()->encode(url.path());
- uint len = path.length();
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
-
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ +
- 4 /*str length*/ + len +
- 4 /*pflags*/ + attr.size());
- s << (TQ_UINT8)SSH2_FXP_OPEN;
- s << (TQ_UINT32)id;
- s.writeBytes(path.data(), len);
- s << pflags;
- s << attr;
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpOpen(): sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type == SSH2_FXP_STATUS ) {
- TQ_UINT32 errCode;
- r >> errCode;
- return errCode;
- }
-
- if( type != SSH2_FXP_HANDLE ) {
- kdError(KIO_SFTP_DB) << "sftpOpen(): unexpected message type of " << type << endl;
- return -1;
- }
-
- r >> handle;
- if( handle.size() > 256 ) {
- kdError(KIO_SFTP_DB) << "sftpOpen(): handle exceeds max length" << endl;
- return -1;
- }
-
- kdDebug(KIO_SFTP_DB) << "sftpOpen(): handle (" << handle.size() << "): [" << handle << "]" << endl;
- return SSH2_FX_OK;
-}
-
-
-int sftpProtocol::sftpRead(const TQByteArray& handle, TDEIO::filesize_t offset, TQ_UINT32 len, TQByteArray& data)
-{
- // kdDebug(KIO_SFTP_DB) << "sftpRead( offset = " << offset << ", len = " << len << ")" << endl;
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ +
- 4 /*str length*/ + handle.size() +
- 8 /*offset*/ + 4 /*length*/);
- s << (TQ_UINT8)SSH2_FXP_READ;
- s << (TQ_UINT32)id;
- s << handle;
- s << offset; // we don't have a convienient 64 bit int so set upper int to zero
- s << len;
-
- putPacket(p);
- getPacket(p);
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpRead: sftp packet id mismatch" << endl;
- return -1;
- }
-
- if( type == SSH2_FXP_STATUS ) {
- TQ_UINT32 errCode;
- r >> errCode;
- kdError(KIO_SFTP_DB) << "sftpRead: read failed with code " << errCode << endl;
- return errCode;
- }
-
- if( type != SSH2_FXP_DATA ) {
- kdError(KIO_SFTP_DB) << "sftpRead: unexpected message type of " << type << endl;
- return -1;
- }
-
- r >> data;
-
- return SSH2_FX_OK;
-}
-
-
-int sftpProtocol::sftpWrite(const TQByteArray& handle, TDEIO::filesize_t offset, const TQByteArray& data){
-// kdDebug(KIO_SFTP_DB) << "sftpWrite( offset = " << offset <<
-// ", data sz = " << data.size() << ")" << endl;
- TQByteArray p;
- TQDataStream s(p, IO_WriteOnly);
-
- TQ_UINT32 id, expectedId;
- id = expectedId = mMsgId++;
- s << (TQ_UINT32)(1 /*type*/ + 4 /*id*/ +
- 4 /*str length*/ + handle.size() +
- 8 /*offset*/ +
- 4 /* data size */ + data.size());
- s << (TQ_UINT8)SSH2_FXP_WRITE;
- s << (TQ_UINT32)id;
- s << handle;
- s << offset; // we don't have a convienient 64 bit int so set upper int to zero
- s << data;
-
-// kdDebug(KIO_SFTP_DB) << "sftpWrite(): SSH2_FXP_WRITE, id:"
-// << id << ", handle:" << handle << ", offset:" << offset << ", some data" << endl;
-
-// kdDebug(KIO_SFTP_DB) << "sftpWrite(): send packet [" << p << "]" << endl;
-
- putPacket(p);
- getPacket(p);
-
-// kdDebug(KIO_SFTP_DB) << "sftpWrite(): received packet [" << p << "]" << endl;
-
- TQDataStream r(p, IO_ReadOnly);
- TQ_UINT8 type;
-
- r >> type >> id;
- if( id != expectedId ) {
- kdError(KIO_SFTP_DB) << "sftpWrite(): sftp packet id mismatch, got "
- << id << ", expected " << expectedId << endl;
- return -1;
- }
-
- if( type != SSH2_FXP_STATUS ) {
- kdError(KIO_SFTP_DB) << "sftpWrite(): unexpected message type of " << type << endl;
- return -1;
- }
-
- TQ_UINT32 code;
- r >> code;
- return code;
-}
-
-
diff --git a/kioslave/sftp/kio_sftp.h b/kioslave/sftp/kio_sftp.h
deleted file mode 100644
index e9120452b..000000000
--- a/kioslave/sftp/kio_sftp.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/***************************************************************************
- sftpProtocol.h - description
- -------------------
- begin : Sat Jun 30 20:08:47 CDT 2001
- copyright : (C) 2001 by Lucas Fisher
- email : ljfisher@purdue.edu
-***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-#ifndef __kio_sftp_h__
-#define __kio_sftp_h__
-
-#include <tqstring.h>
-#include <tqcstring.h>
-#include <tqobject.h>
-
-#include <kurl.h>
-#include <kio/global.h>
-#include <kio/slavebase.h>
-#include <kdebug.h>
-
-#include "process.h"
-#include "sftpfileattr.h"
-#include "ksshprocess.h"
-
-#define KIO_SFTP_DB 7120
-
-
-class sftpProtocol : public TDEIO::SlaveBase
-{
-
-public:
- sftpProtocol(const TQCString &pool_socket, const TQCString &app_socket);
- virtual ~sftpProtocol();
- virtual void setHost(const TQString& h, int port, const TQString& user, const TQString& pass);
- virtual void get(const KURL& url);
- virtual void listDir(const KURL& url) ;
- virtual void mimetype(const KURL& url);
- virtual void stat(const KURL& url);
- virtual void copy(const KURL &src, const KURL &dest, int permissions, bool overwrite);
- virtual void put(const KURL& url, int permissions, bool overwrite, bool resume);
- virtual void closeConnection();
- virtual void slave_status();
- virtual void del(const KURL &url, bool isfile);
- virtual void chmod(const KURL& url, int permissions);
- virtual void symlink(const TQString& target, const KURL& dest, bool overwrite);
- virtual void rename(const KURL& src, const KURL& dest, bool overwrite);
- virtual void mkdir(const KURL&url, int permissions);
- virtual void openConnection();
-
-private: // Private variables
- /** True if ioslave is connected to sftp server. */
- bool mConnected;
-
- /** Host we are connected to. */
- TQString mHost;
-
- /** Port we are connected to. */
- int mPort;
-
- /** Ssh process to which we send the sftp packets. */
- KSshProcess ssh;
-
- /** Username to use when connecting */
- TQString mUsername;
-
- /** User's password */
- TQString mPassword;
-
- /** Message id of the last sftp packet we sent. */
- unsigned int mMsgId;
-
- /** Type of packet we are expecting to receive next. */
- unsigned char mExpected;
-
- /** Version of the sftp protocol we are using. */
- int sftpVersion;
-
- struct Status
- {
- int code;
- TDEIO::filesize_t size;
- TQString text;
- };
-
-private: // private methods
- bool getPacket(TQByteArray& msg);
-
- /* Type is a sftp packet type found in .sftp.h'.
- * Example: SSH2_FXP_READLINK, SSH2_FXP_RENAME, etc.
- *
- * Returns true if the type is supported by the sftp protocol
- * version negotiated by the client and server (sftpVersion).
- */
- bool isSupportedOperation(int type);
- /** Used to have the server canonicalize any given path name to an absolute path.
- This is useful for converting path names containing ".." components or relative
- pathnames without a leading slash into absolute paths.
- Returns the canonicalized url. */
- int sftpRealPath(const KURL& url, KURL& newUrl);
-
- /** Send an sftp packet to stdin of the ssh process. */
- bool putPacket(TQByteArray& p);
- /** Process SSH_FXP_STATUS packets. */
- void processStatus(TQ_UINT8, const TQString& message = TQString::null);
- /** Process SSH_FXP_STATUS packes and return the result. */
- Status doProcessStatus(TQ_UINT8, const TQString& message = TQString::null);
- /** Opens a directory handle for url.path. Returns true if succeeds. */
- int sftpOpenDirectory(const KURL& url, TQByteArray& handle);
- /** Closes a directory or file handle. */
- int sftpClose(const TQByteArray& handle);
- /** Send a sftp command to rename a file or directoy. */
- int sftpRename(const KURL& src, const KURL& dest);
- /** Set a files attributes. */
- int sftpSetStat(const KURL& url, const sftpFileAttr& attr);
- /** Sends a sftp command to remove a file or directory. */
- int sftpRemove(const KURL& url, bool isfile);
- /** Creates a symlink named dest to target. */
- int sftpSymLink(const TQString& target, const KURL& dest);
- /** Get directory listings. */
- int sftpReadDir(const TQByteArray& handle, const KURL& url);
- /** Retrieves the destination of a link. */
- int sftpReadLink(const KURL& url, TQString& target);
- /** Stats a file. */
- int sftpStat(const KURL& url, sftpFileAttr& attr);
- /** No descriptions */
- int sftpOpen(const KURL& url, const TQ_UINT32 pflags, const sftpFileAttr& attr, TQByteArray& handle);
- /** No descriptions */
- int sftpRead(const TQByteArray& handle, TDEIO::filesize_t offset, TQ_UINT32 len, TQByteArray& data);
- /** No descriptions */
- int sftpWrite(const TQByteArray& handle, TDEIO::filesize_t offset, const TQByteArray& data);
-
- /** Performs faster upload when the source is a local file... */
- void sftpCopyPut(const KURL& src, const KURL& dest, int mode, bool overwrite);
- /** Performs faster download when the destination is a local file... */
- void sftpCopyGet(const KURL& dest, const KURL& src, int mode, bool overwrite);
-
- /** */
- Status sftpGet( const KURL& src, TDEIO::filesize_t offset = 0, int fd = -1);
- void sftpPut( const KURL& dest, int permissions, bool resume, bool overwrite, int fd = -1);
-};
-#endif
diff --git a/kioslave/sftp/ksshprocess.cpp b/kioslave/sftp/ksshprocess.cpp
deleted file mode 100644
index 3393f8934..000000000
--- a/kioslave/sftp/ksshprocess.cpp
+++ /dev/null
@@ -1,1114 +0,0 @@
-/***************************************************************************
- ksshprocess.cpp - description
- -------------------
- begin : Tue Jul 31 2001
- copyright : (C) 2001 by Lucas Fisher
- email : ljfisher@purdue.edu
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-/*
- * See the KSshProcess header for examples on use.
- *
- * This class uses a hacked version of the PTYProcess
- * class. This was needed because the tdelibs PTYProcess does not provide
- * access to the pty file descriptor which we need, because ssh prints the
- * password prompt to the pty and reads the password from the pty. I don't
- * feel I know enough about ptys to confidently modify the orignial
- * PTYProcess class.
- *
- * To start ssh we take the arguments the user gave us
- * in the SshOptList and build the ssh command arguments based on the version
- * of ssh we are using. This command and its arguments are passed to
- * PTYProcess for execution. Once ssh is started we scan each line of input
- * from stdin, stderr, and the pty for recognizable strings. The recognizable
- * strings are taken from several string tables. Each table contains a string
- * for each specific version of ssh we support and a string for a generic
- * version of OpenSSH and commercial SSH incase we don't recognized the
- * specific ssh version strings (as when a new SSH version is released after
- * a release of KSshProcess). There are tables for ssh version strings,
- * password prompts, new host key errors, different host key errors,
- * messages than indicate a successful connect, authentication errors, etc.
- * If we find user interaction is necessary, for instance to provide a
- * password or passphrase, we return a err code to the user who can send
- * a message to KSshProcess, using one of several methods, to correct
- * the error.
- *
- * Determining when the ssh connection has successfully authenticationed has
- * proved to be the most difficult challenge. OpenSSH does not print a message
- * on successful authentication, thus the only way to know is to send data
- * and wait for a return. The problem here is sometimes it can take a bit
- * to establish the connection (for example, do to DNS lookups). This means
- * the user may be sitting there waiting for a connection that failed.
- * Instead, ssh is always started with the verbose flag. Then we look for
- * a message that indicates auth succeeded. This is hazardous because
- * debug messages are more likely to change between OpenSSH releases.
- * Thus, we could become incompatible with new OpenSSH releases.
- */
-
-#include <config.h>
-
-#include "ksshprocess.h"
-
-#include <stdio.h>
-#include <errno.h>
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <kstandarddirs.h>
-#include <klocale.h>
-#include <tqregexp.h>
-
-/*
- * The following are tables of string and regexps we match
- * against the output of ssh. An entry in each array
- * corresponds the the version of ssh found in versionStrs[].
- *
- * The version strings must be ordered in the array from most
- * specific to least specific in cases where the beginning
- * of several version strings are the similar. For example,
- * consider the openssh version strings. The generic "OpenSSH"
- * must be the last of the openssh version strings in the array
- * so that is matched last. We use these generic version strings
- * so we can do a best effor to support unknown ssh versions.
- */
-TQRegExp KSshProcess::versionStrs[] = {
- TQRegExp("OpenSSH_3\\.[6-9]|OpenSSH_[1-9]*[4-9]\\.[0-9]"),
- TQRegExp("OpenSSH"),
- TQRegExp("SSH Secure Shell")
-};
-
-const char * const KSshProcess::passwordPrompt[] = {
- "password:", // OpenSSH
- "password:", // OpenSSH
- "password:" // SSH
-};
-
-const char * const KSshProcess::passphrasePrompt[] = {
- "Enter passphrase for key",
- "Enter passphrase for key",
- "Passphrase for key"
-};
-
-const char * const KSshProcess::authSuccessMsg[] = {
- "Authentication succeeded",
- "ssh-userauth2 successful",
- "Received SSH_CROSS_AUTHENTICATED packet"
-};
-
-const char* const KSshProcess::authFailedMsg[] = {
- "Permission denied (",
- "Permission denied (",
- "Authentication failed."
-};
-
-const char* const KSshProcess::tryAgainMsg[] = {
- "please try again",
- "please try again",
- "adjfhjsdhfdsjfsjdfhuefeufeuefe"
-};
-
-TQRegExp KSshProcess::hostKeyMissingMsg[] = {
- TQRegExp("The authenticity of host|No (DSA|RSA) host key is known for"),
- TQRegExp("The authenticity of host|No (DSA|RSA) host key is known for"),
- TQRegExp("Host key not found from database")
-};
-
-const char* const KSshProcess::continuePrompt[] = {
- "Are you sure you want to continue connecting (yes/no)?",
- "Are you sure you want to continue connecting (yes/no)?",
- "Are you sure you want to continue connecting (yes/no)?"
-};
-
-const char* const KSshProcess::hostKeyChangedMsg[] = {
- "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!",
- "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!",
- "WARNING: HOST IDENTIFICATION HAS CHANGED!"
-};
-
-TQRegExp KSshProcess::keyFingerprintMsg[] = {
- TQRegExp("..(:..){15}"),
- TQRegExp("..(:..){15}"),
- TQRegExp(".....(-.....){10}")
-};
-
-TQRegExp KSshProcess::knownHostsFileMsg[] = {
- TQRegExp("Add correct host key in (.*) to get rid of this message."),
- TQRegExp("Add correct host key in (.*) to get rid of this message."),
- TQRegExp("Add correct host key to \"(.*)\"")
-};
-
-
-// This prompt only applies to commerical ssh.
-const char* const KSshProcess::changeHostKeyOnDiskPrompt[] = {
- "as;jf;sajkfdslkfjas;dfjdsa;fj;dsajfdsajf",
- "as;jf;sajkfdslkfjas;dfjdsa;fj;dsajfdsajf",
- "Do you want to change the host key on disk (yes/no)?"
-};
-
-// We need this in addition the authFailedMsg because when
-// OpenSSH gets a changed host key it will fail to connect
-// depending on the StrictHostKeyChecking option. Depending
-// how this option is set, it will print "Permission denied"
-// and quit, or print "Host key verification failed." and
-// quit. The later if StrictHostKeyChecking is "no".
-// The former if StrictHostKeyChecking is
-// "yes" or explicitly set to "ask".
-TQRegExp KSshProcess::hostKeyVerifyFailedMsg[] = {
- TQRegExp("Host key verification failed\\."),
- TQRegExp("Host key verification failed\\."),
- TQRegExp("Disconnected; key exchange or algorithm? negotiation failed \\(Key exchange failed\\.\\)\\.")
-};
-
-const char * const KSshProcess::connectionClosedMsg[] = {
- "Connection closed by remote host",
- "Connection closed by remote host",
- "Connection closed by remote host"
-};
-
-
-void KSshProcess::SIGCHLD_handler(int) {
- while(waitpid(-1, NULL, WNOHANG) > 0);
-}
-
-void KSshProcess::installSignalHandlers() {
- struct sigaction act;
- memset(&act,0,sizeof(act));
- act.sa_handler = SIGCHLD_handler;
- act.sa_flags = 0
-#ifdef SA_NOCLDSTOP
- | SA_NOCLDSTOP
-#endif
-#ifdef SA_RESTART
- | SA_RESTART
-#endif
- ;
- sigaction(SIGCHLD,&act,NULL);
-}
-
-void KSshProcess::removeSignalHandlers() {
- struct sigaction act;
- memset(&act,0,sizeof(act));
- act.sa_handler = SIG_DFL;
- sigaction(SIGCHLD,&act,NULL);
-}
-
-KSshProcess::KSshProcess()
- : mVersion(UNKNOWN_VER), mConnected(false),
- mRunning(false), mConnectState(0) {
- mSshPath = KStandardDirs::findExe(TQString::fromLatin1("ssh"));
- kdDebug(KSSHPROC) << "KSshProcess::KSshProcess(): ssh path [" <<
- mSshPath << "]" << endl;
-
- installSignalHandlers();
-}
-
-KSshProcess::KSshProcess(TQString pathToSsh)
- : mSshPath(pathToSsh), mVersion(UNKNOWN_VER), mConnected(false),
- mRunning(false), mConnectState(0) {
- installSignalHandlers();
-}
-
-KSshProcess::~KSshProcess(){
- disconnect();
- removeSignalHandlers();
- while(waitpid(-1, NULL, WNOHANG) > 0);
-}
-
-bool KSshProcess::setSshPath(TQString pathToSsh) {
- mSshPath = pathToSsh;
- version();
- if( mVersion == UNKNOWN_VER )
- return false;
-
- return true;
-}
-
-KSshProcess::SshVersion KSshProcess::version() {
- TQString cmd;
- cmd = mSshPath+" -V 2>&1";
-
- // Get version string from ssh client.
- FILE *p;
- if( (p = popen(cmd.latin1(), "r")) == NULL ) {
- kdDebug(KSSHPROC) << "KSshProcess::version(): "
- "failed to start ssh: " << strerror(errno) << endl;
- return UNKNOWN_VER;
- }
-
- // Determine of the version from the version string.
- size_t len;
- char buf[128];
- if( (len = fread(buf, sizeof(char), sizeof(buf)-1, p)) == 0 ) {
- kdDebug(KSSHPROC) << "KSshProcess::version(): "
- "Read of ssh version string failed " <<
- strerror(ferror(p)) << endl;
- return UNKNOWN_VER;
- }
- if( pclose(p) == -1 ) {
- kdError(KSSHPROC) << "KSshProcess::version(): pclose failed." << endl;
- }
- buf[len] = '\0';
- TQString ver;
- ver = buf;
- kdDebug(KSSHPROC) << "KSshProcess::version(): "
- "got version string [" << ver << "]" << endl;
-
- mVersion = UNKNOWN_VER;
- for(int i = 0; i < SSH_VER_MAX; i++) {
- if( ver.find(versionStrs[i]) != -1 ) {
- mVersion = (SshVersion)i;
- break;
- }
- }
-
- kdDebug(KSSHPROC) << "KSshPRocess::version(): version number = "
- << mVersion << endl;
-
- if( mVersion == UNKNOWN_VER ) {
- kdDebug(KSSHPROC) << "KSshProcess::version(): "
- "Sorry, I don't know about this version of ssh" << endl;
- mError = ERR_UNKNOWN_VERSION;
- return UNKNOWN_VER;
- }
-
- return mVersion;
-}
-/*
-TQString KSshProcess::versionStr() {
- if( mVersion == UNKNOWN_VER ) {
- version();
- if( mVersion == UNKNOWN_VER )
- return TQString::null;
- }
-
- return TQString::fromLatin1(versionStrs[mVersion]);
-}
-*/
-
-bool KSshProcess::setOptions(const SshOptList& opts) {
- kdDebug(KSSHPROC) << "KSshProcess::setOptions()" << endl;
- mArgs.clear();
- SshOptListConstIterator it;
- TQString cmd, subsystem;
- mPassword = mUsername = mHost = TQString::null;
- TQCString tmp;
- for(it = opts.begin(); it != opts.end(); ++it) {
- //kdDebug(KSSHPROC) << "opt.opt = " << (*it).opt << endl;
- //kdDebug(KSSHPROC) << "opt.str = " << (*it).str << endl;
- //kdDebug(KSSHPROC) << "opt.num = " << (*it).num << endl;
- switch( (*it).opt ) {
- case SSH_VERBOSE:
- mArgs.append("-v");
- break;
-
- case SSH_SUBSYSTEM:
- subsystem = (*it).str;
- break;
-
- case SSH_PORT:
- mArgs.append("-p");
- tmp.setNum((*it).num);
- mArgs.append(tmp);
- mPort = (*it).num;
- break;
-
- case SSH_HOST:
- mHost = (*it).str;
- break;
-
- case SSH_USERNAME:
- mArgs.append("-l");
- mArgs.append((*it).str.latin1());
- mUsername = (*it).str;
- break;
-
- case SSH_PASSWD:
- mPassword = (*it).str;
- break;
-
- case SSH_PROTOCOL:
- if( mVersion <= OPENSSH ) {
- tmp = "Protocol=";
- tmp += TQString::number((*it).num).latin1();
- mArgs.append("-o");
- mArgs.append(tmp);
- }
- else if( mVersion <= SSH ) {
- if( (*it).num == 1 ) {
- mArgs.append("-1");
- }
- // else uses version 2 by default
- }
- break;
-
- case SSH_FORWARDX11:
- tmp = "ForwardX11=";
- tmp += (*it).boolean ? "yes" : "no";
- mArgs.append("-o");
- mArgs.append(tmp);
- break;
-
- case SSH_FORWARDAGENT:
- tmp = "ForwardAgent=";
- tmp += (*it).boolean ? "yes" : "no";
- mArgs.append("-o");
- mArgs.append(tmp);
- break;
-
- case SSH_ESCAPE_CHAR:
- if( (*it).num == -1 )
- tmp = "none";
- else
- tmp = (char)((*it).num);
- mArgs.append("-e");
- mArgs.append(tmp);
- break;
-
- case SSH_OPTION:
- // don't allow NumberOfPasswordPrompts or StrictHostKeyChecking
- // since KSshProcess depends on specific setting of these for
- // preforming authentication correctly.
- tmp = (*it).str.latin1();
- if( tmp.contains("NumberOfPasswordPrompts") ||
- tmp.contains("StrictHostKeyChecking") ) {
- mError = ERR_INVALID_OPT;
- return false;
- }
- else {
- mArgs.append("-o");
- mArgs.append(tmp);
- }
- break;
-
- case SSH_COMMAND:
- cmd = (*it).str;
- break;
-
- default:
- kdDebug(KSSHPROC) << "KSshProcess::setOptions(): "
- "unrecognized ssh opt " << (*it).opt << endl;
- }
- }
-
- if( !subsystem.isEmpty() && !cmd.isEmpty() ) {
- kdDebug(KSSHPROC) << "KSshProcess::setOptions(): "
- "cannot use a subsystem and command at the same time" << endl;
- mError = ERR_CMD_SUBSYS_CONFLICT;
- mErrorMsg = i18n("Cannot specify a subsystem and command at the same time.");
- return false;
- }
-
- // These options govern the behavior of ssh and
- // cannot be defined by the user
- //mArgs.append("-o");
- //mArgs.append("StrictHostKeyChecking=ask");
- mArgs.append("-v"); // So we get a message that the
- // connection was successful
- if( mVersion <= OPENSSH ) {
- // nothing
- }
- else if( mVersion <= SSH ) {
- mArgs.append("-o"); // So we can check if the connection was successful
- mArgs.append("AuthenticationSuccessMsg=yes");
- }
-
- if( mHost.isEmpty() ) {
- kdDebug(KSSHPROC) << "KSshProcess::setOptions(): "
- "a host name must be supplied" << endl;
- return false;
- }
- else {
- mArgs.append(mHost.latin1());
- }
-
- if( !subsystem.isEmpty() ) {
- mArgs.append("-s");
- mArgs.append(subsystem.latin1());
- }
-
- if( !cmd.isEmpty() ) {
- mArgs.append(cmd.latin1());
- }
-
- return true;
-}
-
-void KSshProcess::printArgs() {
- TQValueListIterator<TQCString> it;
- for( it = mArgs.begin(); it != mArgs.end(); ++it) {
- kdDebug(KSSHPROC) << "arg: " << *it << endl;
- }
-}
-
-
-int KSshProcess::error(TQString& msg) {
- kdDebug(KSSHPROC) << "KSshProcess::error()" << endl;
- kdDebug() << mErrorMsg << endl;
- msg = mErrorMsg;
- return mError;
-}
-
-void KSshProcess::kill(int signal) {
- int pid = ssh.pid();
-
- kdDebug(KSSHPROC) << "KSshProcess::kill(signal:" << signal
- << "): ssh pid is " << pid << endl;
- kdDebug(KSSHPROC) << "KSshPRocess::kill(): we are "
- << (mConnected ? "" : "not ") << "connected" << endl;
- kdDebug(KSSHPROC) << "KSshProcess::kill(): we are "
- << (mRunning ? "" : "not ") << "running a ssh process" << endl;
-
- if( mRunning && pid > 1 ) {
- // Kill the child process...
- if ( ::kill(pid, signal) == 0 ) {
- // clean up if we tried to kill the process
- if( signal == SIGTERM || signal == SIGKILL ) {
- while(waitpid(-1, NULL, WNOHANG) > 0);
- mConnected = false;
- mRunning = false;
- }
- }
- else
- kdDebug(KSSHPROC) << "KSshProcess::kill(): kill failed" << endl;
- }
- else
- kdDebug(KSSHPROC) << "KSshProcess::kill(): "
- "Refusing to kill ssh process" << endl;
-}
-
-
-
-/**
- * Try to open an ssh connection.
- * SSH prints certain messages to certain file descriptiors:
- * passwordPrompt - pty
- * passphrasePrompt - pty
- * authSuccessMsg - stderr (OpenSSH),
- * authFailedMsg - stderr
- * hostKeyMissing - stderr
- * hostKeyChanged - stderr
- * continuePrompt - stderr
- *
- * We will use a select to wait for a line on each descriptor. Then get
- * each line that available and take action based on it. The type
- * of messages we are looking for and the action we take on each
- * message are:
- * passwordPrompt - Return false, set error to ERR_NEED_PASSWD.
- * On the next call to connect() we expect a password
- * to be available.
- *
- * passpharsePrompt - Return false, set error to ERR_NEED_PASSPHRASE.
- * On the next call to connect() we expect a
- * passphrase to be available.
- *
- * authSuccessMsg - Return true, as we have successfully established a
- * ssh connection.
- *
- * authFailedMsg - Return false, set error to ERR_AUTH_FAILED. We
- * were unable to authenticate the connection given
- * the available authentication information.
- *
- * hostKeyMissing - Return false, set error to ERR_NEW_HOST_KEY. Caller
- * must call KSshProcess.acceptHostKey(bool) to accept
- * or reject the key before calling connect() again.
- *
- * hostKeyChanged - Return false, set error to ERR_DIFF_HOST_KEY. Caller
- * must call KSshProcess.acceptHostKey(bool) to accept
- * or reject the key before calling connect() again.
- *
- * continuePrompt - Send 'yes' or 'no' to accept or reject a key,
- * respectively.
- *
- */
-
-
-void KSshProcess::acceptHostKey(bool accept) {
- kdDebug(KSSHPROC) << "KSshProcess::acceptHostKey(accept:"
- << accept << ")" << endl;
- mAcceptHostKey = accept;
-}
-
-void KSshProcess::setPassword(TQString password) {
- kdDebug(KSSHPROC) << "KSshProcess::setPassword(password:xxxxxxxx)" << endl;
- mPassword = password;
-}
-
-TQString KSshProcess::getLine() {
- static TQStringList buffer;
- TQString line = TQString::null;
- TQCString ptyLine, errLine;
-
- if( buffer.empty() ) {
- // PtyProcess buffers lines. First check that there
- // isn't something on the PtyProces buffer or that there
- // is not data ready to be read from the pty or stderr.
- ptyLine = ssh.readLineFromPty(false);
- errLine = ssh.readLineFromStderr(false);
-
- // If PtyProcess did have something for us, get it and
- // place it in our line buffer.
- if( ! ptyLine.isEmpty() ) {
- buffer.prepend(TQString(ptyLine));
- }
-
- if( ! errLine.isEmpty() ) {
- buffer.prepend(TQString(errLine));
- }
-
- // If we still don't have anything in our buffer so there must
- // not be anything on the pty or stderr. Setup a select()
- // to wait for some data from SSH.
- // Hack around select() failure on newer systems
- unsigned long milliseconds = 0;
- while ((buffer.size() == 0) && (milliseconds < (60*1000))) {
- //kdDebug(KSSHPROC) << "KSshProcess::getLine(): " <<
- // "Line buffer empty, calling select() to wait for data." << endl;
- int errfd = ssh.stderrFd();
- int ptyfd = ssh.fd();
- fd_set rfds;
- fd_set efds;
- struct timeval tv;
-
- // find max file descriptor
- int maxfd = ptyfd > errfd ? ptyfd : errfd;
-
- FD_ZERO(&rfds);
- FD_SET(ptyfd, &rfds); // Add pty file descriptor
- FD_SET(errfd, &rfds); // Add std error file descriptor
-
- FD_ZERO(&efds);
- FD_SET(ptyfd, &efds);
- FD_SET(errfd, &efds);
-
- tv.tv_sec = 60; tv.tv_usec = 0; // 60 second timeout
-
- // Wait for a message from ssh on stderr or the pty.
- int ret = -1;
- do
- ret = ::select(maxfd+1, &rfds, NULL, &efds, &tv);
- while( ret == -1 && errno == EINTR );
-
- // Handle any errors from select
- if( ret == 0 ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): " <<
- "timed out waiting for a response" << endl;
- mError = ERR_TIMED_OUT;
- return TQString::null;
- }
- else if( ret == -1 ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- << "select error: " << strerror(errno) << endl;
- mError = ERR_INTERNAL;
- return TQString::null;
- }
-
- // We are not respecting any type of order in which the
- // lines were received. Who knows whether pty or stderr
- // had data on it first.
- if( FD_ISSET(ptyfd, &rfds) ) {
- ptyLine = ssh.readLineFromPty(false);
- if (ptyLine.size() > 0) {
- buffer.prepend(TQString(ptyLine));
- }
- //kdDebug(KSSHPROC) << "KSshProcess::getLine(): "
- // "line from pty -" << ptyLine << endl;
- }
-
- if( FD_ISSET(errfd, &rfds) ) {
- errLine = ssh.readLineFromStderr(false);
- if (errLine.size() > 0) {
- buffer.prepend(TQString(errLine));
- }
- //kdDebug(KSSHPROC) << "KSshProcess::getLine(): "
- // "line from err -" << errLine << endl;
- }
-
- if( FD_ISSET(ptyfd, &efds) ) {
- kdDebug(KSSHPROC) << "KSshProcess::getLine(): "
- "Exception on pty file descriptor." << endl;
- }
-
- if( FD_ISSET(errfd, &efds) ) {
- kdDebug(KSSHPROC) << "KSshProcess::getLine(): "
- "Exception on std err file descriptor." << endl;
- }
-
- if (buffer.size() == 0) {
- milliseconds++;
- usleep(1000);
- }
- }
- }
-
- // We should have something in our buffer now.
- // Return the last line.
- //it = buffer.end();
- //line = *it;
- //buffer.remove(it);
-
- line = buffer.last();
- buffer.pop_back();
-
- if( line.isNull() && buffer.count() > 0 ) {
- line = buffer.last();
- buffer.pop_back();
- }
-
-// kdDebug(KSSHPROC) << "KSshProcess::getLine(): " <<
-// buffer.count() << " lines in buffer" << endl;
- kdDebug(KSSHPROC) << "KSshProcess::getLine(): "
- "ssh: " << line << endl;
-
-
- return line;
-}
-
-// All the different states we could go through while trying to connect.
-enum sshConnectState {
- STATE_START, STATE_TRY_PASSWD, STATE_WAIT_PROMPT, STATE_NEW_KEY_CONTINUE,
- STATE_DIFF_KEY_CONTINUE, STATE_FATAL, STATE_WAIT_CONTINUE_PROMPT,
- STATE_SEND_CONTINUE, STATE_AUTH_FAILED, STATE_NEW_KEY_WAIT_CONTINUE,
- STATE_DIFF_KEY_WAIT_CONTINUE, STATE_TRY_PASSPHRASE
-};
-
-// Print the state as a string. Good for debugging
-const char* stateStr(int state) {
- switch(state) {
- case STATE_START:
- return "STATE_START";
- case STATE_TRY_PASSWD:
- return "STATE_TRY_PASSWD";
- case STATE_WAIT_PROMPT:
- return "STATE_WAIT_PROMPT";
- case STATE_NEW_KEY_CONTINUE:
- return "STATE_NEW_KEY_CONTINUE";
- case STATE_DIFF_KEY_CONTINUE:
- return "STATE_DIFF_KEY_CONTINUE";
- case STATE_FATAL:
- return "STATE_FATAL";
- case STATE_WAIT_CONTINUE_PROMPT:
- return "STATE_WAIT_CONTINUE_PROMPT";
- case STATE_SEND_CONTINUE:
- return "STATE_SEND_CONTINE";
- case STATE_AUTH_FAILED:
- return "STATE_AUTH_FAILED";
- case STATE_NEW_KEY_WAIT_CONTINUE:
- return "STATE_NEW_KEY_WAIT_CONTINUE";
- case STATE_DIFF_KEY_WAIT_CONTINUE:
- return "STATE_DIFF_KEY_WAIT_CONTINUE";
- case STATE_TRY_PASSPHRASE:
- return "STATE_TRY_PASSPHRASE";
- }
- return "UNKNOWN";
-}
-
-bool KSshProcess::connect() {
- if( mVersion == UNKNOWN_VER ) {
- // we don't know the ssh version yet, so find out
- version();
- if( mVersion == -1 ) {
- return false;
- }
- }
-
- // We'll put a limit on the number of state transitions
- // to ensure we don't go out of control.
- int transitionLimit = 500;
-
- while(--transitionLimit) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- << "Connect state " << stateStr(mConnectState) << endl;
-
- TQString line; // a line from ssh
- TQString msgBuf; // buffer for important messages from ssh
- // which are to be returned to the user
-
- switch(mConnectState) {
- // STATE_START:
- // Executes the ssh binary with the options provided. If no options
- // have been specified, sets error and returns false. Continue to
- // state 1 if execution is successful, otherwise set error and
- // return false.
- case STATE_START:
- // reset some key values to safe values
- mAcceptHostKey = false;
- mKeyFingerprint = TQString::null;
- mKnownHostsFile = TQString::null;
-
- if( mArgs.isEmpty() ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): ssh options "
- "need to be set first using setArgs()" << endl;
- mError = ERR_NO_OPTIONS;
- mErrorMsg = i18n("No options provided for ssh execution.");
- return false;
- }
-
- if( ssh.exec(mSshPath.latin1(), mArgs) ) {
- kdDebug(KSSHPROC) <<
- "KSshProcess::connect(): ssh exec failed" << endl;
- mError = ERR_CANNOT_LAUNCH;
- mErrorMsg = i18n("Failed to execute ssh process.");
- return false;
- }
-
- kdDebug(KSSHPROC) << "KSshPRocess::connect(): ssh pid = " << ssh.pid() << endl;
-
- // set flag to indicate what have started a ssh process
- mRunning = true;
- mConnectState = STATE_WAIT_PROMPT;
- break;
-
- // STATE_WAIT_PROMPT:
- // Get a line of input from the ssh process. Check the contents
- // of the line to determine the next state. Ignore the line
- // if we don't recognize its contents. If the line contains
- // the continue prompt, we have an error since we should never
- // get that line in this state. Set ERR_INVALID_STATE error
- // and return false.
- case STATE_WAIT_PROMPT:
- line = getLine();
- if( line.isNull() ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- "Got null line in STATE_WAIT_PROMPT." << endl;
- mError = ERR_INTERACT;
- mErrorMsg =
- i18n("Error encountered while talking to ssh.");
- mConnectState = STATE_FATAL;
- }
- else if( line.find(TQString::fromLatin1(passwordPrompt[mVersion]), 0, false) != -1 ) {
- mConnectState = STATE_TRY_PASSWD;
- }
- else if( line.find(passphrasePrompt[mVersion]) != -1 ) {
- mConnectState = STATE_TRY_PASSPHRASE;
- }
- else if( line.find(authSuccessMsg[mVersion]) != -1 ) {
- return true;
- }
- else if( line.find(authFailedMsg[mVersion]) != -1
- && line.find(tryAgainMsg[mVersion]) == -1 ) {
- mConnectState = STATE_AUTH_FAILED;
- }
- else if( line.find(hostKeyMissingMsg[mVersion]) != -1 ) {
- mConnectState = STATE_NEW_KEY_WAIT_CONTINUE;
- }
- else if( line.find(hostKeyChangedMsg[mVersion]) != -1 ) {
- mConnectState = STATE_DIFF_KEY_WAIT_CONTINUE;
- }
- else if( line.find(continuePrompt[mVersion]) != -1 ) {
- //mConnectState = STATE_SEND_CONTINUE;
- kdDebug(KSSHPROC) << "KSshProcess:connect(): "
- "Got continue prompt where we shouldn't (STATE_WAIT_PROMPT)"
- << endl;
- mError = ERR_INTERACT;
- mErrorMsg =
- i18n("Error encountered while talking to ssh.");
- }
- else if( line.find(connectionClosedMsg[mVersion]) != -1 ) {
- mConnectState = STATE_FATAL;
- mError = ERR_CLOSED_BY_REMOTE_HOST;
- mErrorMsg = i18n("Connection closed by remote host.");
- }
- else if( line.find(changeHostKeyOnDiskPrompt[mVersion]) != -1 ) {
- // always say yes to this. It always comes after commerical ssh
- // prints a "continue to connect prompt". We assume that if the
- // user choose to continue, then they also want to save the
- // host key to disk.
- ssh.writeLine("yes");
- }
- else {
- // ignore line
- }
- break;
-
- // STATE_TRY_PASSWD:
- // If we have password send it to the ssh process, else
- // set error ERR_NEED_PASSWD and return false to the caller.
- // The caller then must then call KSshProcess::setPassword(TQString)
- // before calling KSshProcess::connect() again.
- //
- // Almost exactly liek STATE_TRY_PASSPHRASE. Check there if you
- // make changes here.
- case STATE_TRY_PASSWD:
- // We have a password prompt waiting for us to supply
- // a password. Send that password to ssh. If the caller
- // did not supply a password like we asked, then ask
- // again.
- if( !mPassword.isEmpty() ) {
-// ssh.WaitSlave();
- ssh.writeLine(mPassword.latin1());
-
- // Overwrite the password so it isn't in memory.
- mPassword.fill(TQChar('X'));
-
- // Set the password to null so we will request another
- // password if this one fails.
- mPassword = TQString::null;
-
- mConnectState = STATE_WAIT_PROMPT;
- }
- else {
- kdDebug(KSSHPROC) << "KSshProcess::connect() "
- "Need password from caller." << endl;
- // The caller needs to supply a password before
- // connecting can continue.
- mError = ERR_NEED_PASSWD;
- mErrorMsg = i18n("Please supply a password.");
- mConnectState = STATE_TRY_PASSWD;
- return false;
- }
- break;
-
- // STATE_TRY_KEY_PASSPHRASE:
- // If we have passphrase send it to the ssh process, else
- // set error ERR_NEED_PASSPHRASE and return false to the caller.
- // The caller then must then call KSshProcess::setPassword(TQString)
- // before calling KSshProcess::connect() again.
- //
- // Almost exactly like STATE_TRY_PASSWD. The only difference is
- // the error we set if we don't have a passphrase. We duplicate
- // this code to keep in the spirit of the state machine.
- case STATE_TRY_PASSPHRASE:
- // We have a passphrase prompt waiting for us to supply
- // a passphrase. Send that passphrase to ssh. If the caller
- // did not supply a passphrase like we asked, then ask
- // again.
- if( !mPassword.isEmpty() ) {
-// ssh.WaitSlave();
- ssh.writeLine(mPassword.latin1());
-
- // Overwrite the password so it isn't in memory.
- mPassword.fill(TQChar('X'));
-
- // Set the password to null so we will request another
- // password if this one fails.
- mPassword = TQString::null;
-
- mConnectState = STATE_WAIT_PROMPT;
- }
- else {
- kdDebug(KSSHPROC) << "KSshProcess::connect() "
- "Need passphrase from caller." << endl;
- // The caller needs to supply a passphrase before
- // connecting can continue.
- mError = ERR_NEED_PASSPHRASE;
- mErrorMsg = i18n("Please supply the passphrase for "
- "your SSH private key.");
- mConnectState = STATE_TRY_PASSPHRASE;
- return false;
- }
- break;
-
- // STATE_AUTH_FAILED:
- // Authentication has failed. Tell the caller by setting the
- // ERR_AUTH_FAILED error and returning false. If
- // auth has failed then ssh should have exited, but
- // we will kill it to make sure.
- case STATE_AUTH_FAILED:
- mError = ERR_AUTH_FAILED;
- mErrorMsg = i18n("Authentication to %1 failed").arg(mHost);
- mConnectState = STATE_FATAL;
- break;
-
- // STATE_NEW_KEY_WAIT_CONTINUE:
- // Grab lines from ssh until we get a continue prompt or a auth
- // denied. We will get the later if StrictHostKeyChecking is set
- // to yes. Go to STATE_NEW_KEY_CONTINUE if we get a continue prompt.
- case STATE_NEW_KEY_WAIT_CONTINUE:
- line = getLine();
- if( line.isNull() ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- "Got null line in STATE_NEW_KEY_WAIT_CONTINUE." << endl;
- mError = ERR_INTERACT;
- mErrorMsg =
- i18n("Error encountered while talking to ssh.");
- mConnectState = STATE_FATAL;
- }
- else if( (line.find(authFailedMsg[mVersion]) != -1
- && line.find(tryAgainMsg[mVersion]) == -1)
- || line.find(hostKeyVerifyFailedMsg[mVersion]) != -1 ) {
- mError = ERR_AUTH_FAILED_NEW_KEY;
- mErrorMsg = i18n(
- "The identity of the remote host '%1' could not be verified "
- "because the host's key is not in the \"known hosts\" file."
- ).arg(mHost);
-
- if( mKnownHostsFile.isEmpty() ) {
- mErrorMsg += i18n(
- " Manually, add the host's key to the \"known hosts\" "
- "file or contact your administrator."
- );
- }
- else {
- mErrorMsg += i18n(
- " Manually, add the host's key to %1 "
- "or contact your administrator."
- ).arg(mKnownHostsFile);
- }
-
- mConnectState = STATE_FATAL;
- }
- else if( line.find(continuePrompt[mVersion]) != -1 ) {
- mConnectState = STATE_NEW_KEY_CONTINUE;
- }
- else if( line.find(connectionClosedMsg[mVersion]) != -1 ) {
- mConnectState = STATE_FATAL;
- mError = ERR_CLOSED_BY_REMOTE_HOST;
- mErrorMsg = i18n("Connection closed by remote host.");
- }
- else if( line.find(keyFingerprintMsg[mVersion]) != -1 ) {
- mKeyFingerprint = keyFingerprintMsg[mVersion].cap();
- kdDebug(KSSHPROC) << "Found key fingerprint: " << mKeyFingerprint << endl;
- mConnectState = STATE_NEW_KEY_WAIT_CONTINUE;
- }
- else {
- // ignore line
- }
- break;
-
-
- // STATE_NEW_KEY_CONTINUE:
- // We got a continue prompt for the new key message. Set the error
- // message to reflect this, return false and hope for caller response.
- case STATE_NEW_KEY_CONTINUE:
- mError = ERR_NEW_HOST_KEY;
- mErrorMsg = i18n(
- "The identity of the remote host '%1' could not be "
- "verified. The host's key fingerprint is:\n%2\nYou should "
- "verify the fingerprint with the host's administrator before "
- "connecting.\n\n"
- "Would you like to accept the host's key and connect anyway? "
- ).arg(mHost).arg(mKeyFingerprint);
- mConnectState = STATE_SEND_CONTINUE;
- return false;
-
- // STATE_DIFF_KEY_WAIT_CONTINUE:
- // Grab lines from ssh until we get a continue prompt or a auth
- // denied. We will get the later if StrictHostKeyChecking is set
- // to yes. Go to STATE_DIFF_KEY_CONTINUE if we get a continue prompt.
- case STATE_DIFF_KEY_WAIT_CONTINUE:
- line = getLine();
- if( line.isNull() ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- "Got null line in STATE_DIFF_KEY_WAIT_CONTINUE." << endl;
- mError = ERR_INTERACT;
- mErrorMsg =
- i18n("Error encountered while talking to ssh.");
- mConnectState = STATE_FATAL;
- }
- else if( (line.find(authFailedMsg[mVersion]) != -1
- && line.find(tryAgainMsg[mVersion]) == -1)
- || line.find(hostKeyVerifyFailedMsg[mVersion]) != -1 ) {
- mError = ERR_AUTH_FAILED_DIFF_KEY;
- mErrorMsg = i18n(
- "WARNING: The identity of the remote host '%1' has changed!\n\n"
- "Someone could be eavesdropping on your connection, or the "
- "administrator may have just changed the host's key. "
- "Either way, you should verify the host's key fingerprint with the host's "
- "administrator. The key fingerprint is:\n%2\n"
- "Add the correct host key to \"%3\" to "
- "get rid of this message."
- ).arg(mHost).arg(mKeyFingerprint).arg(mKnownHostsFile);
- mConnectState = STATE_FATAL;
- }
- else if( line.find(continuePrompt[mVersion]) != -1 ) {
- mConnectState = STATE_DIFF_KEY_CONTINUE;
- }
- else if( line.find(keyFingerprintMsg[mVersion]) != -1 ) {
- mKeyFingerprint = keyFingerprintMsg[mVersion].cap();
- kdDebug(KSSHPROC) << "Found key fingerprint: " << mKeyFingerprint << endl;
- mConnectState = STATE_DIFF_KEY_WAIT_CONTINUE;
- }
- else if( line.find(knownHostsFileMsg[mVersion]) != -1 ) {
- mKnownHostsFile = (knownHostsFileMsg[mVersion]).cap(1);
- kdDebug(KSSHPROC) << "Found known hosts file name: " << mKnownHostsFile << endl;
- mConnectState = STATE_DIFF_KEY_WAIT_CONTINUE;
- }
- else {
- // ignore line
- }
- break;
-
- // STATE_DIFF_KEY_CONTINUE:
- // We got a continue prompt for the different key message.
- // Set ERR_DIFF_HOST_KEY error
- // and return false to signal need to caller action.
- case STATE_DIFF_KEY_CONTINUE:
- mError = ERR_DIFF_HOST_KEY;
- mErrorMsg = i18n(
- "WARNING: The identity of the remote host '%1' has changed!\n\n"
- "Someone could be eavesdropping on your connection, or the "
- "administrator may have just changed the host's key. "
- "Either way, you should verify the host's key fingerprint with the host's "
- "administrator before connecting. The key fingerprint is:\n%2\n\n"
- "Would you like to accept the host's new key and connect anyway?"
- ).arg(mHost).arg(mKeyFingerprint);
- mConnectState = STATE_SEND_CONTINUE;
- return false;
-
- // STATE_SEND_CONTINUE:
- // We found a continue prompt. Send our answer.
- case STATE_SEND_CONTINUE:
- if( mAcceptHostKey ) {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- "host key accepted" << endl;
- ssh.writeLine("yes");
- mConnectState = STATE_WAIT_PROMPT;
- }
- else {
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- "host key rejected" << endl;
- ssh.writeLine("no");
- mError = ERR_HOST_KEY_REJECTED;
- mErrorMsg = i18n("Host key was rejected.");
- mConnectState = STATE_FATAL;
- }
- break;
-
- // STATE_FATAL:
- // Something bad happened that we cannot recover from.
- // Kill the ssh process and set flags to show we have
- // ended the connection and killed ssh.
- //
- // mError and mErrorMsg should be set by the immediately
- // previous state.
- case STATE_FATAL:
- kill();
- mConnected = false;
- mRunning = false;
- mConnectState = STATE_START;
- // mError, mErroMsg set by last state
- return false;
-
- default:
- kdDebug(KSSHPROC) << "KSshProcess::connect(): "
- "Invalid state number - " << mConnectState << endl;
- mError = ERR_INVALID_STATE;
- mConnectState = STATE_FATAL;
- }
- }
-
- // we should never get here
- kdDebug(KSSHPROC) << "KSshProcess::connect(): " <<
- "After switch(). We shouldn't be here." << endl;
- mError = ERR_INTERNAL;
- return false;
-}
-
-void KSshProcess::disconnect() {
- kill();
- mConnected = false;
- mRunning = false;
- mConnectState = STATE_START;
-}
-
diff --git a/kioslave/sftp/ksshprocess.h b/kioslave/sftp/ksshprocess.h
deleted file mode 100644
index 5130628e4..000000000
--- a/kioslave/sftp/ksshprocess.h
+++ /dev/null
@@ -1,623 +0,0 @@
-/***************************************************************************
- ksshprocess.h - description
- -------------------
- begin : Tue Jul 31 2001
- copyright : (C) 2001 by Lucas Fisher
- email : ljfisher@purdue.edu
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef KSSHPROCESS_H
-#define KSSHPROCESS_H
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include <tqvaluelist.h>
-
-#include <kdebug.h>
-
-#include "process.h"
-
-#define KSSHPROC 7120
-
-/**
- * Provides version independent access to ssh. Currently supported
- * versions of SSH are:
- * OpenSSH 2.9p1
- * OpenSSH 2.9p2
- * OpenSSH 3.0
- * OpenSSH 3.1
- * Commercial SSH 3.0.0
- * Other versions of OpenSSH and commerical SSH will probably work also.
- *
- * To setup a SSH connection first create a list of options to use and tell
- * KSshProcess about your options. Then start the ssh connection. Once the
- * connection is setup use the stdin, stdout, stderr, and pty file descriptors
- * to communicate with ssh. For a detailed example of how to use, see
- * ksshprocesstest.cpp.
- *
- * @author Lucas Fisher
- *
- * Example: Connect to ssh server on localhost
- * KSshProcess::SshOpt opt;
- * KSshProcess::SshOptList options;
- *
- * opt.opt = KSshProcess::SSH_HOST;
- * opt.str = "localhost";
- * options.append(opt);
- *
- * opt.opt = KSshProcess::SSH_USERNAME;
- * opt.str = "me";
- * options.append(opt);
- *
- * KSshProcess ssh;
- * if( !ssh.setOptions(options) ) {
- * int err = ssh.error();
- * // process error
- * return false;
- * }
- *
- * int err;
- * TQString errMsg;
- * while( !ssh.connect() ) {
- * err = ssh.error(errMsg);
- *
- * switch( err ) {
- * case KSshProcess::ERR_NEW_HOST_KEY:
- * case KSshProcess::ERR_DIFF_HOST_KEY:
- * // ask user to accept key
- * if( acceptHostKey ) {
- * ssh.acceptKey(true);
- * }
- * break;
- *
- * case KSshProcess::ERR_NEED_PASSWORD:
- * // ask user for password
- * ssh.password(userPassword);
- * break;
- *
- * case KSshProcess::ERR_NEED_KEY_PASSPHRASE:
- * // ask user for their key passphrase
- * ssh.keyPassphrase(keyPassphrase);
- * break;
- *
- * default:
- * // somethings wrong, alert user
- * return;
- * }
- * }
- * // We have an open ssh connection to localhost
- *
- */
-
-class KSshProcess {
-public:
- /**
- * SSH Option
- *
- * Stores SSH options for use with KSshProcess.
- *
- * SSH options are configured much like UDS entries.
- * Each option is assigned a constant and a string, bool,
- * or number is assigned based on the option.
- *
- * @author Lucas Fisher (ljfisher@iastate.edu)
- */
- class SshOpt {
- public:
- TQ_UINT32 opt;
- TQString str;
- TQ_INT32 num;
- bool boolean;
- };
-
- /**
- * List of SshOptions and associated iterators
- */
- typedef TQValueList<SshOpt> SshOptList;
- typedef TQValueListIterator<SshOpt> SshOptListIterator;
- typedef TQValueListConstIterator<SshOpt> SshOptListConstIterator;
-
- /**
- * Ssh versions supported by KSshProcess. Subject to change
- * at any time.
- */
- enum SshVersion {
- OPENSSH_3_6,
- OPENSSH,
- SSH,
- SSH_VER_MAX,
- UNKNOWN_VER
- };
-
- /**
- * SSH options supported by KSshProcess. Set SshOpt::opt to one of these
- * values.
- */
- // we cannot do this like UDSAtomType (ORing the type with the name) because
- // we have too many options for ssh and not enough bits.
- enum SshOptType {
- /**
- * Request server to invoke subsystem. (str)
- */
- SSH_SUBSYSTEM,
- /**
- * Connect to port on the server. (num)
- */
- SSH_PORT,
- /**
- * Connect to host. (str)
- */
- SSH_HOST,
- /**
- * connect using this username. (str)
- */
- SSH_USERNAME,
- /**
- * connect using this password. (str)
- */
- SSH_PASSWD,
- /**
- * connect using this version of the SSH protocol. num == 1 or 2
- */
- SSH_PROTOCOL,
- /**
- * whether to forward X11 connections. (boolean)
- */
- SSH_FORWARDX11,
- /**
- * whether to do agent forwarding. (boolean)
- */
- SSH_FORWARDAGENT,
- /**
- * use as escape character. 0 for none (num)
- */
- SSH_ESCAPE_CHAR,
- /**
- * command for ssh to perform once it is connected (str)
- */
- SSH_COMMAND,
- /**
- * Set ssh verbosity. This may be added multiple times. It may also cause KSSHProcess
- * to fail since we don't understand all the debug messages.
- */
- SSH_VERBOSE,
- /**
- * Set a ssh option as one would find in the ssh_config file
- * The str member should be set to 'optName value'
- */
- SSH_OPTION,
- /**
- * Set some other option not supported by KSSHProcess. The option should
- * be specified in the str member of SshOpt. Careful with this since
- * not all versions of SSH support the same options.
- */
- SSH_OTHER,
- SSH_OPT_MAX // always last
- }; // that's all for now
-
- /**
- * Errors that KSshProcess can encounter. When a member function returns
- * false, call error() to retrieve one of these error codes.
- */
- enum SshError {
- /**
- * Don't recognize the ssh version
- */
- ERR_UNKNOWN_VERSION,
- /**
- * Cannot lauch ssh client
- */
- ERR_CANNOT_LAUNCH,
- /**
- * Interaction with the ssh client failed. This happens when we can't
- * find the password prompt or something similar
- */
- ERR_INTERACT,
- /**
- * Arguments for both a remotely executed subsystem and command were provide.
- * Only one or the other may be used
- */
- ERR_CMD_SUBSYS_CONFLICT,
- /**
- * No password was supplied
- */
- ERR_NEED_PASSWD,
- /**
- * No passphrase was supplied.
- */
- ERR_NEED_PASSPHRASE,
- /**
- * No usename was supplied
- */
- ERR_NEED_USERNAME,
- /**
- * Timed out waiting for a response from ssh or the server
- */
- ERR_TIMED_OUT,
- /**
- * Internal error, probably from a system call
- */
- ERR_INTERNAL,
- /**
- * ssh was disconnect from the host
- */
- ERR_DISCONNECTED,
- /**
- * No ssh options have been set. Call setArgs() before calling connect.
- */
- ERR_NO_OPTIONS,
- /**
- * A host key was received from an unknown host.
- * Call connect() with the acceptHostKey argument to accept the key.
- */
- ERR_NEW_HOST_KEY,
- /**
- * A host key different from what is stored in the user's known_hosts file
- * has be received. This is an indication of an attack
- */
- ERR_DIFF_HOST_KEY,
- /**
- * A new or different host key was rejected by the caller. The ssh
- * connection was terminated and the ssh process killed.
- */
- ERR_HOST_KEY_REJECTED,
- /**
- * An invalid option was found in the SSH option list
- */
- ERR_INVALID_OPT,
- /**
- * SSH accepted host key without prompting user.
- */
- ERR_ACCEPTED_KEY,
- /**
- * Authentication failed
- */
- ERR_AUTH_FAILED,
- /**
- * Authentication failed because a new host key was detected and
- * SSH is configured with strict host key checking enabled.
- */
- ERR_AUTH_FAILED_NEW_KEY,
- /**
- * Authentication failed because a changed host key was detected and
- * SSH is configured with strict host key checking enabled.
- */
- ERR_AUTH_FAILED_DIFF_KEY,
- /**
- * The remote host closed the connection for unknown reasons.
- */
- ERR_CLOSED_BY_REMOTE_HOST,
- /**
- * We have no idea what happened
- */
- ERR_UNKNOWN,
- /**
- * The connect state machine entered an invalid state.
- */
- ERR_INVALID_STATE,
- ERR_MAX
- };
-
- /**
- * Initialize a SSH process using the first SSH binary found in the PATH
- */
- KSshProcess();
-
- /**
- * Initialize a SSH process using the specified SSH binary.
- * @param pathToSsh The fully qualified path name of the ssh binary
- * KSshProcess should use to setup a SSH connection.
- */
- KSshProcess(TQString pathToSsh);
- ~KSshProcess();
-
- /**
- * Set the ssh binary KSshProcess should use. This will only affect the
- * next ssh connection attempt using this instance.
- *
- * @param pathToSsh Full path to the ssh binary.
- *
- * @return True if the ssh binary is found and KSshProcess
- * recognizes the version.
- *
- */
- bool setSshPath(TQString pathToSsh);
-
- /**
- * Get the ssh version.
- *
- * @return The ssh version or -1 if KSshProcess does not recognize
- * the ssh version. The returned value corresponds to the
- * member of the SshVersion enum.
- */
- SshVersion version();
-
- /**
- * Get a string describing the ssh version
- *
- * @return A string describing the ssh version recognized by KSshProcess
- */
- //TQString versionStr();
-
- /**
- * Get the last error encountered by KSshProcess.
- *
- * @param msg Set to the error message, if any, outputted by ssh when it is run.
- *
- * @return The error number. See SshError for descriptions.
- */
- int error(TQString& msg);
-
- /**
- * Get the last error encountered by KSshProcess.
- * @return The error number. See SshError for descriptions.
- */
- int error() { return mError; }
-
- TQString errorMsg() { return mErrorMsg; }
-
- /**
- * Send a signal to the ssh process. Do not use this to end the
- * ssh connection as it will not correctly reset the internal
- * state of the KSshProcess object. Use KSshProcess::disconnect()
- * instead.
- *
- * @param signal The signal to send to the ssh process. See 'kill -l'
- * for a list of possible signals.
- * The default signal is SIGKILL which kills ssh.
- *
- */
- void kill(int signal = SIGKILL);
-
- /**
- * The pid of the ssh process started by this instance of KSshProcess.
- * Only valid if KSshProcess::running() returns true;
- *
- * @return The pid of the running ssh process.
- */
- int pid() { return ssh.pid(); }
-
- /**
- * Whether a ssh connection has been established with a
- * remote host. A establish connection means ssh has successfully
- * authenticated with the remote host and user data can be transfered
- * between the local and remote host. This cannot return
- * true unless the most recent call to KSshProccess::connect() returned true.
- *
- * @return True if a ssh connection has been established with a remote
- * host. False otherwise.
- */
- bool connected() { return mConnected; }
-
- /**
- * Whether a ssh process is currently running. This only indicates
- * if a ssh process has been started and is still running. It does not
- * tell if authentication has been successful. This may return true
- * even if the most recent call to KSshProcess::connect() returned false.
- *
- * @return True if a ssh process started by this instance of KSshProcess
- * is running. False otherwise.
- */
- bool running() { return mRunning; }
-
- /**
- * Print the command line arguments ssh is run with using kdDebug.
- */
- void printArgs();
-
- /**
- * Set the SSH options.
- * This must be called before connect(). See SshOptType for a list of
- * supported ssh options. The required options are SSH_USERNAME
- * and SSH_HOST.
- *
- * To reset the saved options, just recall setOptions() again with
- * a different options list.
- *
- * @param opts A list of SshOpt objects specifying the ssh options.
- *
- * @return True if all options are valid. False if unrecognized options
- * or a required option is missing. Call error()
- * for details.
- *
- */
- bool setOptions(const SshOptList& opts);
-
- /**
- * Create a ssh connection based on the options provided by setOptions().
- * Sets one of the following error codes on failure:
- * <ul>
- * <li>ERR_NO_OPTIONS</li>
- * <li>ERR_CANNOT_LAUNCH</li>
- * <li>ERR_INVALID_STATE</li>
- * <li>ERR_NEED_PASSWD</li>
- * <li>ERR_AUTH_FAILED</li>
- * <li>ERR_NEW_HOST_KEY</li>
- * <li>ERR_KEY_ACCEPTED</li>
- * <li>ERR_DIFF_HOST_KEY</li>
- * <li>ERR_INTERNAL</li>
- * <li>ERR_INTERACT</li>
- * </ul>
- *
- * @param acceptHostKey When true KSshProcess will automatically accept
- * unrecognized or changed host keys.
- *
- * @return True if the ssh connection is successful. False if the connection
- * fails. Call error() to get the reason for the failure.
- */
- bool connect();
-
-
- /**
- * Disconnect ssh from the host. This kills the ssh process and
- * resets the internal state of this KSshProcess object. After a
- * disconnect, the same KSshProcess can be used to connect to a
- * host.
- */
- void disconnect();
-
- /**
- * Call to respond to a ERR_NEW_HOST_KEY or ERR_DIFF_HOST_KEY error.
- *
- * @param accept True to accept the host key, false to not accept the
- * host key and kill ssh.
- *
- */
- void acceptHostKey(bool accept);
-
- /**
- * Call to respond to a ERR_NEED_PASSWD or ERR_NEED_PASSPHRASE error.
- *
- * @param password The user password to give ssh.
- */
- void setPassword(TQString password);
-
- /**
- * Access to standard in and out of the ssh process.
- *
- * @return The file description for stdin and stdout of the ssh process.
- */
- int stdioFd() { return ssh.stdioFd(); }
-
- /**
- * Access to standard error of the ssh process.
- *
- * @return The file descriptior for stderr of the ssh process.
- */
- int stderrFd() { return ssh.stderrFd(); }
-
- /**
- * Access the pty to which the ssh process is attached.
- *
- * @return The file descriptor of pty to which ssh is attached.
- */
- int pty() { return ssh.fd(); }
-private:
- /**
- * Path the the ssh binary.
- */
- TQString mSshPath;
-
- /**
- * SSH version. This is an index into the supported SSH
- * versions array, and the various messages arrays.
- */
- SshVersion mVersion;
-
- /**
- * User's password. Zero this out when it is no longer needed.
- */
- TQString mPassword;
-
- /**
- * User's username.
- */
- TQString mUsername;
-
- /**
- * Name of host we are connecting to.
- */
- TQString mHost;
-
- /**
- * Accept new or changed host keys if true.
- */
- bool mAcceptHostKey;
-
- /**
- * Flag to tell use if we have an open, authenticated ssh
- * session going.
- */
- bool mConnected;
-
- /**
- * Flag to tell us if we have started a ssh process, we use this
- * to make sure we kill ssh before going away.
- */
- bool mRunning;
-
- /**
- * Save any key fingerprint msg from ssh so we can present
- * it to the caller.
- */
- TQString mKeyFingerprint;
-
- /**
- * The location of the known host key file. We grab this from
- * any error messages ssh prints out.
- */
- TQString mKnownHostsFile;
-
- /**
- * The state of our connect state machine.
- */
- int mConnectState;
-
- /**
- * Port on on which the target ssh server is listening.
- */
- int mPort;
-
- /**
- * The last error number encountered. This is only valid for the
- * last error.
- */
- SshError mError;
-
- /**
- * An error message that corresponds to the error number set in
- * mError. Optional.
- */
- TQString mErrorMsg;
-
- /**
- * Interface to the SSH process we ceate. Handles communication
- * to and from the SSH process using stdin, stdout, stderr, and
- * pty.
- */
- MyPtyProcess ssh;
-
- /**
- * List of arguments we start SSH with.
- */
- QCStringList mArgs;
- void init();
-
- /**
- * Handler to clean up when ssh process terminates.
- */
- static void SIGCHLD_handler(int signo);
- void installSignalHandlers();
- void removeSignalHandlers();
-
- TQString getLine();
-
- static TQRegExp versionStrs[];
- static const char * const passwordPrompt[];
- static const char * const passphrasePrompt[];
- static const char * const authSuccessMsg[];
- static const char * const authFailedMsg[];
- static TQRegExp hostKeyMissingMsg[];
- static const char * const hostKeyChangedMsg[];
- static const char * const continuePrompt[];
- static const char * const hostKeyAcceptedMsg[];
- static const char * const tryAgainMsg[];
- static TQRegExp hostKeyVerifyFailedMsg[];
- static const char * const connectionClosedMsg[];
- static const char * const changeHostKeyOnDiskPrompt[];
- static TQRegExp keyFingerprintMsg[];
- static TQRegExp knownHostsFileMsg[];
-};
-#endif
diff --git a/kioslave/sftp/ksshprocesstest.cpp b/kioslave/sftp/ksshprocesstest.cpp
deleted file mode 100644
index 59dbf58c7..000000000
--- a/kioslave/sftp/ksshprocesstest.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "ksshprocess.h"
-#include <iostream>
-
-using namespace std;
-
-int main(int argc, char *argv[]) {
-
- if( argc < 5 ) {
- cout << "Usage: " << argv[0] <<
- " <ssh path> <host> <username> <password>" << endl;
- return 1;
- }
-
- KSshProcess ssh(argv[1]);
- cout << ssh.version() << endl;
-
- KSshProcess::SshOptList opts;
- KSshProcess::SshOpt opt;
-
- opt.opt = KSshProcess::SSH_PORT;
- opt.num = 22;
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_HOST;
- opt.str = TQString(argv[2]);
- opts.append(opt);
-
- opt.opt = KSshProcess::SSH_USERNAME;
- opt.str = TQString(argv[3]);
- opts.append(opt);
-
-// opt.opt = KSshProcess::SSH_PASSWD;
-// opt.str = TQString(argv[4]);
-// opts.append(opt);
-
- if( !ssh.setOptions(opts) ) {
- cout << "ksshprocesstest: setOptions failed" << endl;
- return -1;
- }
-
- ssh.printArgs();
-
- bool stop = false;
- bool connected;
- char buf[256];
- char c;
- while( !stop && !(connected = ssh.connect()) ) {
- cout << "ksshprocesstest: Error num - " << ssh.error() << endl;
- cout << "ksshprocesstest: Error msg - " << ssh.errorMsg().latin1() << endl;
- switch( ssh.error() ) {
- case KSshProcess::ERR_NEED_PASSWD:
- case KSshProcess::ERR_NEED_PASSPHRASE:
- cout << "Password: ";
- cin >> buf;
- cout << "password is " << buf << endl;
- ssh.setPassword(TQString(buf));
- break;
- case KSshProcess::ERR_NEW_HOST_KEY:
- case KSshProcess::ERR_DIFF_HOST_KEY:
- cout << "Accept host key? (y/n): ";
- cin >> c;
- cout << "Answered " << c << endl;
- ssh.acceptHostKey(c == 'y' ? true : false);
- break;
- case KSshProcess::ERR_AUTH_FAILED:
- cout << "ksshprocesstest: auth failed." << endl;
- stop = true;
- break;
- case KSshProcess::ERR_AUTH_FAILED_NEW_KEY:
- cout << "ksshprocesstest: auth failed because of new key." << endl;
- stop = true;
- break;
- case KSshProcess::ERR_AUTH_FAILED_DIFF_KEY:
- cout << "ksshprocesstest: auth failed because of changed key." << endl;
- stop = true;
- break;
-
- case KSshProcess::ERR_INTERACT:
- case KSshProcess::ERR_INTERNAL:
- case KSshProcess::ERR_UNKNOWN:
- case KSshProcess::ERR_INVALID_STATE:
- case KSshProcess::ERR_CANNOT_LAUNCH:
- case KSshProcess::ERR_HOST_KEY_REJECTED:
- cout << "ksshprocesstest: FATAL ERROR" << endl;
- stop = true;
- break;
-
- }
- }
-
- if( connected ) {
- cout << "ksshprocesstest: Successfully connected to " << argv[2] << endl;
- }
- else {
- cout << "ksshprocesstest: Connect to " << argv[2] << " failed." << endl;
- }
-
-}
diff --git a/kioslave/sftp/process.cpp b/kioslave/sftp/process.cpp
deleted file mode 100644
index 885fe7636..000000000
--- a/kioslave/sftp/process.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/* vi: ts=8 sts=4 sw=4
- *
- *
- * This file is part of the KDE project, module tdesu.
- * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
- *
- * This file contains code from TEShell.C of the KDE konsole.
- * Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
- *
- * This is free software; you can use this library under the GNU Library
- * General Public License, version 2. See the file "COPYING.LIB" for the
- * exact licensing terms.
- *
- * process.cpp: Functionality to build a front end to password asking
- * terminal programs.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <termios.h>
-#include <signal.h>
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-
-#if defined(__SVR4) && defined(sun)
-#include <stropts.h>
-#include <sys/stream.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h> // Needed on some systems.
-#endif
-
-#include <tqglobal.h>
-#include <tqcstring.h>
-#include <tqfile.h>
-
-#include <kdebug.h>
-#include <kstandarddirs.h>
-
-#include "process.h"
-#include <tdesu/tdesu_pty.h>
-#include <tdesu/kcookie.h>
-
-
-MyPtyProcess::MyPtyProcess()
-{
- m_bTerminal = false;
- m_bErase = false;
- m_pPTY = 0L;
- m_Pid = -1;
- m_Fd = -1;
-}
-
-
-int MyPtyProcess::init()
-{
- delete m_pPTY;
- m_pPTY = new PTY();
- m_Fd = m_pPTY->getpt();
- if (m_Fd < 0)
- return -1;
- if ((m_pPTY->grantpt() < 0) || (m_pPTY->unlockpt() < 0))
- {
- kdError(PTYPROC) << k_lineinfo << "Master setup failed.\n" << endl;
- m_Fd = -1;
- return -1;
- }
- m_TTY = m_pPTY->ptsname();
- m_stdoutBuf.resize(0);
- m_stderrBuf.resize(0);
- m_ptyBuf.resize(0);
- return 0;
-}
-
-
-MyPtyProcess::~MyPtyProcess()
-{
- delete m_pPTY;
-}
-
-
-/*
- * Read one line of input. The terminal is in canonical mode, so you always
- * read a line at at time, but it's possible to receive multiple lines in
- * one time.
- */
-
-
-TQCString MyPtyProcess::readLineFrom(int fd, TQCString& inbuf, bool block)
-{
- int pos;
- TQCString ret;
-
- if (!inbuf.isEmpty())
- {
-
- pos = inbuf.find('\n');
-
- if (pos == -1)
- {
- ret = inbuf;
- inbuf.resize(0);
- } else
- {
- ret = inbuf.left(pos);
- inbuf = inbuf.mid(pos+1);
- }
- return ret;
-
- }
-
- int flags = fcntl(fd, F_GETFL);
- if (flags < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "fcntl(F_GETFL): " << perror << "\n";
- return ret;
- }
- if (block)
- flags &= ~O_NONBLOCK;
- else
- flags |= O_NONBLOCK;
- if (fcntl(fd, F_SETFL, flags) < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "fcntl(F_SETFL): " << perror << "\n";
- return ret;
- }
-
- int nbytes;
- char buf[256];
- while (1)
- {
- nbytes = read(fd, buf, 255);
- if (nbytes == -1)
- {
- if (errno == EINTR)
- continue;
- else break;
- }
- if (nbytes == 0)
- break; // eof
-
- buf[nbytes] = '\000';
- inbuf += buf;
-
- pos = inbuf.find('\n');
- if (pos == -1)
- {
- ret = inbuf;
- inbuf.resize(0);
- } else
- {
- ret = inbuf.left(pos);
- inbuf = inbuf.mid(pos+1);
- }
- break;
-
- }
-
- return ret;
-}
-
-void MyPtyProcess::writeLine(TQCString line, bool addnl)
-{
- if (!line.isEmpty())
- write(m_Fd, line, line.length());
- if (addnl)
- write(m_Fd, "\n", 1);
-}
-
-void MyPtyProcess::unreadLineFrom(TQCString inbuf, TQCString line, bool addnl)
-{
- if (addnl)
- line += '\n';
- if (!line.isEmpty())
- inbuf.prepend(line);
-}
-
-
-/*
- * Fork and execute the command. This returns in the parent.
- */
-
-int MyPtyProcess::exec(TQCString command, QCStringList args)
-{
- kdDebug(PTYPROC) << "MyPtyProcess::exec(): " << command << endl;// << ", args = " << args << endl;
-
- if (init() < 0)
- return -1;
-
- // Open the pty slave before forking. See SetupTTY()
- int slave = open(m_TTY, O_RDWR);
- if (slave < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "Could not open slave pty.\n";
- return -1;
- }
-
- // Also create a socket pair to connect to standard in/out.
- // This will allow use to bypass the terminal.
- int inout[2];
- int err[2];
- int ok = 1;
- ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, inout) >= 0;
- ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err ) >= 0;
- if( !ok ) {
- kdDebug(PTYPROC) << "Could not create socket" << endl;
- return -1;
- }
- m_stdinout = inout[0];
- m_err = err[0];
-
- if ((m_Pid = fork()) == -1)
- {
- kdError(PTYPROC) << k_lineinfo << "fork(): " << perror << "\n";
- return -1;
- }
-
- // Parent
- if (m_Pid)
- {
- close(slave);
- close(inout[1]);
- close(err[1]);
- return 0;
- }
-
- // Child
-
- ok = 1;
- ok &= dup2(inout[1], STDIN_FILENO) >= 0;
- ok &= dup2(inout[1], STDOUT_FILENO) >= 0;
- ok &= dup2(err[1], STDERR_FILENO) >= 0;
-
- if( !ok )
- {
- kdError(PTYPROC) << "dup of socket descriptor failed" << endl;
- _exit(1);
- }
-
- close(inout[1]);
- close(inout[0]);
- close(err[1]);
- close(err[0]);
-
- if (SetupTTY(slave) < 0)
- _exit(1);
-
- // From now on, terminal output goes through the tty.
- TQCString path;
- if (command.contains('/'))
- path = command;
- else
- {
- TQString file = KStandardDirs::findExe(command);
- if (file.isEmpty())
- {
- kdError(PTYPROC) << k_lineinfo << command << " not found\n";
- _exit(1);
- }
- path = TQFile::encodeName(file);
- }
-
- int i;
- const char * argp[32];
- argp[0] = path;
- QCStringList::Iterator it;
- for (i=1, it=args.begin(); it!=args.end() && i<31; it++) {
- argp[i++] = *it;
- kdDebug(PTYPROC) << *it << endl;
- }
- argp[i] = 0L;
- execv(path, (char * const *)argp);
- kdError(PTYPROC) << k_lineinfo << "execv(\"" << path << "\"): " << perror << "\n";
- _exit(1);
- return -1; // Shut up compiler. Never reached.
-}
-
-/*
- * Wait until the terminal is set into no echo mode. At least one su
- * (RH6 w/ Linux-PAM patches) sets noecho mode AFTER writing the Password:
- * prompt, using TCSAFLUSH. This flushes the terminal I/O queues, possibly
- * taking the password with it. So we wait until no echo mode is set
- * before writing the password.
- * Note that this is done on the slave fd. While Linux allows tcgetattr() on
- * the master side, Solaris doesn't.
- */
-
-int MyPtyProcess::WaitSlave()
-{
- int slave = open(m_TTY, O_RDWR);
- if (slave < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "Could not open slave tty.\n";
- return -1;
- }
-
- struct termios tio;
- struct timeval tv;
- while (1)
- {
- if (tcgetattr(slave, &tio) < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "tcgetattr(): " << perror << "\n";
- close(slave);
- return -1;
- }
- if (tio.c_lflag & ECHO)
- {
- kdDebug(PTYPROC) << k_lineinfo << "Echo mode still on." << endl;
- // sleep 1/10 sec
- tv.tv_sec = 0; tv.tv_usec = 100000;
- select(slave, 0L, 0L, 0L, &tv);
- continue;
- }
- break;
- }
- close(slave);
- return 0;
-}
-
-
-int MyPtyProcess::enableLocalEcho(bool enable)
-{
- int slave = open(m_TTY, O_RDWR);
- if (slave < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "Could not open slave tty.\n";
- return -1;
- }
- struct termios tio;
- if (tcgetattr(slave, &tio) < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "tcgetattr(): " << perror << "\n";
- close(slave); return -1;
- }
- if (enable)
- tio.c_lflag |= ECHO;
- else
- tio.c_lflag &= ~ECHO;
- if (tcsetattr(slave, TCSANOW, &tio) < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "tcsetattr(): " << perror << "\n";
- close(slave); return -1;
- }
- close(slave);
- return 0;
-}
-
-
-/*
- * Copy output to stdout until the child process exists, or a line of output
- * matches `m_Exit'.
- * We have to use waitpid() to test for exit. Merely waiting for EOF on the
- * pty does not work, because the target process may have children still
- * attached to the terminal.
- */
-
-int MyPtyProcess::waitForChild()
-{
- int ret, state, retval = 1;
- struct timeval tv;
-
- fd_set fds;
- FD_ZERO(&fds);
-
- while (1)
- {
- tv.tv_sec = 1; tv.tv_usec = 0;
- FD_SET(m_Fd, &fds);
- ret = select(m_Fd+1, &fds, 0L, 0L, &tv);
- if (ret == -1)
- {
- if (errno == EINTR) continue;
- else
- {
- kdError(PTYPROC) << k_lineinfo << "select(): " << perror << "\n";
- return -1;
- }
- }
-
- if (ret)
- {
- TQCString line = readLine(false);
- while (!line.isNull())
- {
- if (!m_Exit.isEmpty() && !tqstrnicmp(line, m_Exit, m_Exit.length()))
- kill(m_Pid, SIGTERM);
- if (m_bTerminal)
- {
- fputs(line, stdout);
- fputc('\n', stdout);
- }
- line = readLine(false);
- }
- }
-
- // Check if the process is still alive
- ret = waitpid(m_Pid, &state, WNOHANG);
- if (ret < 0)
- {
- if (errno == ECHILD)
- retval = 0;
- else
- kdError(PTYPROC) << k_lineinfo << "waitpid(): " << perror << "\n";
- break;
- }
- if (ret == m_Pid)
- {
- if (WIFEXITED(state))
- retval = WEXITSTATUS(state);
- break;
- }
- }
-
- return -retval;
-}
-
-/*
- * SetupTTY: Creates a new session. The filedescriptor "fd" should be
- * connected to the tty. It is closed after the tty is reopened to make it
- * our controlling terminal. This way the tty is always opened at least once
- * so we'll never get EIO when reading from it.
- */
-
-int MyPtyProcess::SetupTTY(int fd)
-{
- // Reset signal handlers
- for (int sig = 1; sig < NSIG; sig++)
- signal(sig, SIG_DFL);
- signal(SIGHUP, SIG_IGN);
-
- // Close all file handles
-// struct rlimit rlp;
-// getrlimit(RLIMIT_NOFILE, &rlp);
-// for (int i = 0; i < (int)rlp.rlim_cur; i++)
-// if (i != fd) close(i);
-
- // Create a new session.
- setsid();
-
- // Open slave. This will make it our controlling terminal
- int slave = open(m_TTY, O_RDWR);
- if (slave < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "Could not open slave side: " << perror << "\n";
- return -1;
- }
- close(fd);
-
-#if defined(__SVR4) && defined(sun)
-
- // Solaris STREAMS environment.
- // Push these modules to make the stream look like a terminal.
- ioctl(slave, I_PUSH, "ptem");
- ioctl(slave, I_PUSH, "ldterm");
-
-#endif
-
- // Connect stdin, stdout and stderr
-// dup2(slave, 0); dup2(slave, 1); dup2(slave, 2);
-// if (slave > 2)
-// close(slave);
-
- // Disable OPOST processing. Otherwise, '\n' are (on Linux at least)
- // translated to '\r\n'.
- struct termios tio;
- if (tcgetattr(slave, &tio) < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "tcgetattr(): " << perror << "\n";
- return -1;
- }
- tio.c_oflag &= ~OPOST;
- if (tcsetattr(slave, TCSANOW, &tio) < 0)
- {
- kdError(PTYPROC) << k_lineinfo << "tcsetattr(): " << perror << "\n";
- return -1;
- }
-
- return 0;
-}
diff --git a/kioslave/sftp/process.h b/kioslave/sftp/process.h
deleted file mode 100644
index 215c51ea7..000000000
--- a/kioslave/sftp/process.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* vi: ts=8 sts=4 sw=4
- *
- *
- * This file is part of the KDE project, module tdesu.
- * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
- *
- * This is free software; you can use this library under the GNU Library
- * General Public License, version 2. See the file "COPYING.LIB" for the
- * exact licensing terms.
- */
-
-#ifndef __Process_h_Included__
-#define __Process_h_Included__
-
-#include <tqcstring.h>
-#include <tqstring.h>
-#include <tqstringlist.h>
-#include <tqvaluelist.h>
-
-#define PTYPROC 7120
-
-class PTY;
-typedef TQValueList<TQCString> QCStringList;
-
-/**
- * Synchronous communication with tty programs.
- *
- * PtyProcess provides synchronous communication with tty based programs.
- * The communications channel used is a pseudo tty (as opposed to a pipe)
- * This means that programs which require a terminal will work.
- */
-
-class MyPtyProcess
-{
-public:
- MyPtyProcess();
- virtual ~MyPtyProcess();
-
- /**
- * Fork off and execute a command. The command's standard in and output
- * are connected to the pseudo tty. They are accessible with @ref #readLine
- * and @ref #writeLine.
- * @param command The command to execute.
- * @param args The arguments to the command.
- */
- int exec(TQCString command, QCStringList args);
-
- /**
- * Read a line from the program's standard out. Depending on the @em block
- * parameter, this call blocks until a single, full line is read.
- * @param block Block until a full line is read?
- * @return The output string.
- */
- TQCString readLine(bool block = true)
- { return readLineFrom(m_Fd, m_ptyBuf, block); }
-
- TQCString readLineFromPty(bool block = true)
- { return readLineFrom(m_Fd, m_ptyBuf, block); }
-
- TQCString readLineFromStdout(bool block = true)
- { return readLineFrom(m_stdinout, m_stdoutBuf, block); }
-
- TQCString readLineFromStderr(bool block = true)
- { return readLineFrom(m_err, m_stderrBuf, block); }
-
- /**
- * Write a line of text to the program's standard in.
- * @param line The text to write.
- * @param addNewline Adds a '\n' to the line.
- */
- void writeLine(TQCString line, bool addNewline=true);
-
- /**
- * Put back a line of input.
- * @param line The line to put back.
- * @param addNewline Adds a '\n' to the line.
- */
-
- void unreadLine(TQCString line, bool addNewline = true)
- { unreadLineFrom(m_ptyBuf, line, addNewline); }
-
- void unreadLineFromPty(TQCString line, bool addNewline = true)
- { unreadLineFrom(m_ptyBuf, line, addNewline); }
-
- void unreadLineFromStderr(TQCString line, bool addNewline = true)
- { unreadLineFrom(m_stderrBuf, line, addNewline); }
-
- void unreadLineFromStdout(TQCString line, bool addNewline = true)
- { unreadLineFrom(m_stdoutBuf, line, addNewline); }
-
- /**
- * Set exit string. If a line of program output matches this,
- * @ref #waitForChild() will terminate the program and return.
- */
- void setExitString(TQCString exit) { m_Exit = exit; }
-
- /**
- * Wait for the child to exit. See also @ref #setExitString.
- */
- int waitForChild();
-
- /**
- * Wait until the pty has cleared the ECHO flag. This is useful
- * when programs write a password prompt before they disable ECHO.
- * Disabling it might flush any input that was written.
- */
- int WaitSlave();
-
- /** Enables/disables local echo on the pseudo tty. */
- int enableLocalEcho(bool enable=true);
-
- /** Enable/disable terminal output. Relevant only to some subclasses. */
- void setTerminal(bool terminal) { m_bTerminal = terminal; }
-
- /** Overwritte the password as soon as it is used. Relevant only to
- * some subclasses. */
- void setErase(bool erase) { m_bErase = erase; }
-
- /** Return the filedescriptor of the process. */
- int fd() {return m_Fd;}
-
- /** Return the pid of the process. */
- int pid() {return m_Pid;}
-
- int stdioFd() {return m_stdinout;}
-
- int stderrFd() {return m_err;}
-
-protected:
- bool m_bErase, m_bTerminal;
- int m_Pid, m_Fd, m_stdinout, m_err;
- TQCString m_Command, m_Exit;
-
-private:
- int init();
- int SetupTTY(int fd);
-
- PTY *m_pPTY;
- TQCString m_TTY;
- TQCString m_ptyBuf, m_stderrBuf, m_stdoutBuf;
-
- TQCString readLineFrom(int fd, TQCString& inbuf, bool block);
- void unreadLineFrom(TQCString inbuf, TQCString line, bool addnl);
- class PtyProcessPrivate;
- PtyProcessPrivate *d;
-};
-
-#endif
diff --git a/kioslave/sftp/sftp.h b/kioslave/sftp/sftp.h
deleted file mode 100644
index 95518130d..000000000
--- a/kioslave/sftp/sftp.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */
-
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * 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.
- */
-
-/*
- * draft-ietf-secsh-filexfer-01.txt
- */
-
-/* version */
-#define SSH2_FILEXFER_VERSION 3
-
-/* client to server */
-#define SSH2_FXP_INIT 1
-#define SSH2_FXP_OPEN 3
-#define SSH2_FXP_CLOSE 4
-#define SSH2_FXP_READ 5
-#define SSH2_FXP_WRITE 6
-#define SSH2_FXP_LSTAT 7
-#define SSH2_FXP_FSTAT 8
-#define SSH2_FXP_SETSTAT 9
-#define SSH2_FXP_FSETSTAT 10
-#define SSH2_FXP_OPENDIR 11
-#define SSH2_FXP_READDIR 12
-#define SSH2_FXP_REMOVE 13
-#define SSH2_FXP_MKDIR 14
-#define SSH2_FXP_RMDIR 15
-#define SSH2_FXP_REALPATH 16
-#define SSH2_FXP_STAT 17
-#define SSH2_FXP_RENAME 18
-#define SSH2_FXP_READLINK 19
-#define SSH2_FXP_SYMLINK 20
-
-/* server to client */
-#define SSH2_FXP_VERSION 2
-#define SSH2_FXP_STATUS 101
-#define SSH2_FXP_HANDLE 102
-#define SSH2_FXP_DATA 103
-#define SSH2_FXP_NAME 104
-#define SSH2_FXP_ATTRS 105
-
-#define SSH2_FXP_EXTENDED 200
-#define SSH2_FXP_EXTENDED_REPLY 201
-
-/* attributes */
-#define SSH2_FILEXFER_ATTR_SIZE 0x00000001
-#define SSH2_FILEXFER_ATTR_UIDGID 0x00000002
-#define SSH2_FILEXFER_ATTR_PERMISSIONS 0x00000004
-#define SSH2_FILEXFER_ATTR_ACMODTIME 0x00000008
-#define SSH2_FILEXFER_ATTR_EXTENDED 0x80000000
-
-/* portable open modes */
-#define SSH2_FXF_READ 0x00000001
-#define SSH2_FXF_WRITE 0x00000002
-#define SSH2_FXF_APPEND 0x00000004
-#define SSH2_FXF_CREAT 0x00000008
-#define SSH2_FXF_TRUNC 0x00000010
-#define SSH2_FXF_EXCL 0x00000020
-
-/* status messages */
-#define SSH2_FX_OK 0
-#define SSH2_FX_EOF 1
-#define SSH2_FX_NO_SUCH_FILE 2
-#define SSH2_FX_PERMISSION_DENIED 3
-#define SSH2_FX_FAILURE 4
-#define SSH2_FX_BAD_MESSAGE 5
-#define SSH2_FX_NO_CONNECTION 6
-#define SSH2_FX_CONNECTION_LOST 7
-#define SSH2_FX_OP_UNSUPPORTED 8
-#define SSH2_FX_MAX 8
diff --git a/kioslave/sftp/sftp.protocol b/kioslave/sftp/sftp.protocol
deleted file mode 100644
index 177cd86e9..000000000
--- a/kioslave/sftp/sftp.protocol
+++ /dev/null
@@ -1,84 +0,0 @@
-[Protocol]
-exec=kio_sftp
-protocol=sftp
-input=none
-listing=Name,Type,Size,Date,Access,Owner,Group,Link
-output=filesystem
-copyToFile=true
-copyFromFile=true
-reading=true
-writing=true
-makedir=true
-deleting=true
-moving=true
-Icon=ftp
-Description=A kioslave for sftp
-Description[af]='n Kioslave vir sftp
-Description[be]=Kioslave для sftp
-Description[bg]=kioslave за sftp
-Description[bn]=এস.এফ.টি.পি-র জন্য একটি kioslave
-Description[br]=Ur kioslave evit sftp
-Description[bs]=kioslave za SFTP
-Description[ca]=Un kioslave per a sftp
-Description[cs]=Protokol KDE pro sftp
-Description[csb]=Plugins dlô procedurë òbsłużënkù sftp
-Description[da]=En kioslave for sftp
-Description[de]=Ein-/Ausgabemodul für das sftp-Protokoll
-Description[el]=Ένας kioslave για sftp
-Description[eo]=kenelsklavo por sftp
-Description[es]=Un kioslave para sftp
-Description[et]=SFTP IO-moodul
-Description[eu]=Sftp-rako kioslave bat
-Description[fa]=یک kioslave برای sftp
-Description[fi]=Sftp:n liitin
-Description[fr]=Un module d'entrées / sorties pour le sftp
-Description[fy]=Een kioslave Foar sftp
-Description[ga]=kioslave le haghaidh sftp
-Description[gl]=Un kioslave para sftp
-Description[he]=ממשק kioslave עבור sftp
-Description[hi]=एसएफटीपी के लिए केआईओस्लेव
-Description[hr]=Kioslave za SFTP
-Description[hu]=KDE-protokoll az sftp-hez
-Description[is]=kioslave fyrir sftp
-Description[it]=Un kioslave per sftp
-Description[ja]=sftp のための kioslave
-Description[kk]=sftp-ке арналған енгізу-шығару модулі
-Description[km]=kioslave របស់ sftp
-Description[ko]=SFTP KIO 슬레이브
-Description[lt]=Kiovergas sftp protokolui
-Description[lv]=KIO vergs priekš sftp
-Description[mk]=kio-служител за sftp
-Description[ms]=Kioslave untuk sftp
-Description[nb]=En kioslave for sftp
-Description[nds]=En In-/Utgaavdeenst för sftpl
-Description[ne]=sftp का लागि एउटा किओस्लेभ
-Description[nl]=Een kioslave voor sftp
-Description[nn]=Ein kioslave for sftp
-Description[pa]=sftp ਲਈ kioslave
-Description[pl]=Wtyczka protokołu sftp
-Description[pt]=Um 'kioslave' para sftp
-Description[pt_BR]=Uma implementação para o sftp
-Description[ro]=Un dispozitiv de I/E pentru SFTP
-Description[ru]=Модуль ввода-вывода для sftp
-Description[rw]=kioslave ya sftp
-Description[se]=ŠO-šláva sftp-protokolla várás
-Description[sk]=kioslave pre sftp
-Description[sl]=kioslave za sftp
-Description[sr]=Kioslave за SFTP
-Description[sr@Latn]=Kioslave za SFTP
-Description[sv]=En I/O-slav för SFTP
-Description[ta]=sftpக்கான ஒரு க்யோஸ்லேவ்
-Description[te]=ఎస్ ఎఫ్ టి పి కొరకు ఐఒ బానిస
-Description[th]=ตัวนำข้อมูลเข้า-ออกสำหรับ sftp
-Description[tr]=Sftp için kioslave
-Description[tt]=sftp öçen kioslave
-Description[uk]=Підлеглий В/В для sftp
-Description[uz]=SFTP uchun KCH-sleyv
-Description[uz@cyrillic]=SFTP учун КЧ-слейв
-Description[vi]=A kioslave (đày tớ vào ra KDE) cho sftp
-Description[wa]=On kioslave po sftp
-Description[zh_CN]=sftp 的 kioslave
-Description[zh_TW]=sftp 的 kioslave
-DocPath=kioslave/sftp.html
-Icon=ftp
-Class=:internet
diff --git a/kioslave/sftp/sftpfileattr.cpp b/kioslave/sftp/sftpfileattr.cpp
deleted file mode 100644
index 95a82677f..000000000
--- a/kioslave/sftp/sftpfileattr.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-/***************************************************************************
- sftpfileattr.cpp - description
- -------------------
- begin : Sat Jun 30 2001
- copyright : (C) 2001 by Lucas Fisher
- email : ljfisher@iastate.edu
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "sftpfileattr.h"
-
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <tqstring.h>
-#include <tqdatastream.h>
-
-#include <kio/global.h>
-#include <kremoteencoding.h>
-
-using namespace TDEIO;
-
-sftpFileAttr::sftpFileAttr(){
- clear();
- mDirAttrs = false;
-}
-
-sftpFileAttr::sftpFileAttr(KRemoteEncoding* encoding){
- clear();
- mDirAttrs = false;
- mEncoding = encoding;
-}
-
-
-/** Constructor to initialize the file attributes on declaration. */
-sftpFileAttr::sftpFileAttr(TQ_ULLONG size, uid_t uid, gid_t gid,
- mode_t permissions, time_t atime,
- time_t mtime, TQ_UINT32 extendedCount) {
- clear();
- mDirAttrs = false;
- mSize = size;
- mUid = uid;
- mGid = gid;
- mAtime = atime;
- mMtime = mtime;
- mPermissions = permissions;
- mExtendedCount = extendedCount;
-}
-
-sftpFileAttr::~sftpFileAttr(){
-}
-
-/** Returns a UDSEntry describing the file.
-The UDSEntry is generated from the sftp file attributes. */
-UDSEntry sftpFileAttr::entry() {
- UDSEntry entry;
- UDSAtom atom;
-
- atom.m_uds = UDS_NAME;
- atom.m_str = mFilename;
- entry.append(atom);
-
- if( mFlags & SSH2_FILEXFER_ATTR_SIZE ) {
- atom.m_uds = UDS_SIZE;
- atom.m_long = mSize;
- entry.append(atom);
- }
-
- if( mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) {
- atom.m_uds = UDS_ACCESS_TIME;
- atom.m_long = mAtime;
- entry.append(atom);
-
- atom.m_uds = UDS_MODIFICATION_TIME;
- atom.m_long = mMtime;
- entry.append(atom);
- }
-
- if( mFlags & SSH2_FILEXFER_ATTR_UIDGID ) {
- if( mUserName.isEmpty() || mGroupName.isEmpty() )
- getUserGroupNames();
-
- atom.m_uds = UDS_USER;
- atom.m_str = mUserName;
- entry.append(atom);
-
- atom.m_uds = UDS_GROUP;
- atom.m_str = mGroupName;
- entry.append(atom);
- }
-
- if( mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) {
- atom.m_uds = UDS_ACCESS;
- atom.m_long = mPermissions;
- entry.append(atom);
-
- mode_t type = fileType();
-
- // Set the type if we know what it is
- if( type != 0 ) {
- atom.m_uds = UDS_FILE_TYPE;
- atom.m_long = (mLinkType ? mLinkType:type);
- entry.append(atom);
- }
-
- if( S_ISLNK(type) ) {
- atom.m_uds = UDS_LINK_DEST;
- atom.m_str = mLinkDestination;
- entry.append(atom);
- }
- }
-
- return entry;
-}
-
-/** Use to output the file attributes to a sftp packet */
-TQDataStream& operator<< (TQDataStream& s, const sftpFileAttr& fa) {
- s << (TQ_UINT32)fa.mFlags;
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_SIZE )
- { s << (TQ_ULLONG)fa.mSize; }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_UIDGID )
- { s << (TQ_UINT32)fa.mUid << (TQ_UINT32)fa.mGid; }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS )
- { s << (TQ_UINT32)fa.mPermissions; }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_ACMODTIME )
- { s << (TQ_UINT32)fa.mAtime << (TQ_UINT32)fa.mMtime; }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) {
- s << (TQ_UINT32)fa.mExtendedCount;
- // XXX: Write extensions to data stream here
- // s.writeBytes(extendedtype).writeBytes(extendeddata);
- }
- return s;
-}
-
-
-/** Use to read a file attribute from a sftp packet */
-TQDataStream& operator>> (TQDataStream& s, sftpFileAttr& fa) {
-
- // XXX Add some error checking in here in case
- // we get a bad sftp packet.
-
- fa.clear();
-
- if( fa.mDirAttrs ) {
- TQCString fn;
- s >> fn;
- fn.truncate( fn.size() );
-
- fa.mFilename = fa.mEncoding->decode( fn );
-
- s >> fa.mLongname;
- fa.mLongname.truncate( fa.mLongname.size() );
- //kdDebug() << ">>: ftpfileattr long filename (" << fa.mLongname.size() << ")= " << fa.mLongname << endl;
- }
-
- s >> fa.mFlags; // get flags
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_SIZE ) {
- TQ_ULLONG fileSize;
- s >> fileSize;
- fa.setFileSize(fileSize);
- }
-
- TQ_UINT32 x;
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_UIDGID ) {
- s >> x; fa.setUid(x);
- s >> x; fa.setGid(x);
- }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) {
- s >> x; fa.setPermissions(x);
- }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) {
- s >> x; fa.setAtime(x);
- s >> x; fa.setMtime(x);
- }
-
- if( fa.mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) {
- s >> x; fa.setExtendedCount(x);
- // XXX: Read in extensions from data stream here
- // s.readBytes(extendedtype).readBytes(extendeddata);
- }
-
- fa.getUserGroupNames();
- return s;
-}
-/** Parse longname for the owner and group names. */
-void sftpFileAttr::getUserGroupNames(){
- // Get the name of the owner and group of the file from longname.
- TQString user, group;
- if( mLongname.isEmpty() ) {
- // do not have the user name so use the user id instead
- user.setNum(mUid);
- group.setNum(mGid);
- }
- else {
- int field = 0;
- int i = 0;
- int l = mLongname.length();
-
- TQString longName = mEncoding->decode( mLongname );
-
- kdDebug(7120) << "Decoded: " << longName << endl;
-
- // Find the beginning of the third field which contains the user name.
- while( field != 2 ) {
- if( longName[i].isSpace() ) {
- field++; i++;
- while( i < l && longName[i].isSpace() ) { i++; }
- }
- else { i++; }
- }
- // i is the index of the first character of the third field.
- while( i < l && !longName[i].isSpace() ) {
- user.append(longName[i]);
- i++;
- }
-
- // i is the first character of the space between fields 3 and 4
- // user contains the owner's user name
- while( i < l && longName[i].isSpace() ) {
- i++;
- }
-
- // i is the first character of the fourth field
- while( i < l && !longName[i].isSpace() ) {
- group.append(longName[i]);
- i++;
- }
- // group contains the name of the group.
- }
-
- mUserName = user;
- mGroupName = group;
-}
-
-/** No descriptions */
-kdbgstream& operator<< (kdbgstream& s, sftpFileAttr& a) {
- s << "Filename: " << a.mFilename
- << ", Uid: " << a.mUid
- << ", Gid: " << a.mGid
- << ", Username: " << a.mUserName
- << ", GroupName: " << a.mGroupName
- << ", Permissions: " << a.mPermissions
- << ", size: " << a.mSize
- << ", atime: " << a.mAtime
- << ", mtime: " << a.mMtime
- << ", extended cnt: " << a.mExtendedCount;
-
- if (S_ISLNK(a.mLinkType)) {
- s << ", Link Type: " << a.mLinkType;
- s << ", Link Destination: " << a.mLinkDestination;
- }
-
- return s;
-}
-
-/** Make sure it builds with NDEBUG */
-kndbgstream& operator<< (kndbgstream& s, sftpFileAttr& ) {
- return s;
-}
-
-/** Clear all attributes and flags. */
-void sftpFileAttr::clear(){
- clearAtime();
- clearMtime();
- clearGid();
- clearUid();
- clearFileSize();
- clearPermissions();
- clearExtensions();
- mFilename = TQString::null;
- mGroupName = TQString::null;
- mUserName = TQString::null;
- mLinkDestination = TQString::null;
- mFlags = 0;
- mLongname = "\0";
- mLinkType = 0;
-}
-
-/** Return the size of the sftp attribute. */
-TQ_UINT32 sftpFileAttr::size() const{
- TQ_UINT32 size = 4; // for the attr flag
- if( mFlags & SSH2_FILEXFER_ATTR_SIZE )
- size += 8;
-
- if( mFlags & SSH2_FILEXFER_ATTR_UIDGID )
- size += 8;
-
- if( mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS )
- size += 4;
-
- if( mFlags & SSH2_FILEXFER_ATTR_ACMODTIME )
- size += 8;
-
- if( mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) {
- size += 4;
- // add size of extensions
- }
- return size;
-}
-
-/** Returns the file type as determined from the file permissions */
-mode_t sftpFileAttr::fileType() const{
- mode_t type = 0;
-
- if( S_ISLNK(mPermissions) )
- type |= S_IFLNK;
-
- if( S_ISREG(mPermissions) )
- type |= S_IFREG;
- else if( S_ISDIR(mPermissions) )
- type |= S_IFDIR;
- else if( S_ISCHR(mPermissions) )
- type |= S_IFCHR;
- else if( S_ISBLK(mPermissions) )
- type |= S_IFBLK;
- else if( S_ISFIFO(mPermissions) )
- type |= S_IFIFO;
- else if( S_ISSOCK(mPermissions) )
- type |= S_IFSOCK;
-
- return type;
-}
-
-void sftpFileAttr::setEncoding( KRemoteEncoding* encoding )
-{
- mEncoding = encoding;
-}
-// vim:ts=4:sw=4
diff --git a/kioslave/sftp/sftpfileattr.h b/kioslave/sftp/sftpfileattr.h
deleted file mode 100644
index 543153b5e..000000000
--- a/kioslave/sftp/sftpfileattr.h
+++ /dev/null
@@ -1,261 +0,0 @@
-/***************************************************************************
- sftpfileattr.h - description
- -------------------
- begin : Sat Jun 30 2001
- copyright : (C) 2001 by Lucas Fisher
- email : ljfisher@iastate.edu
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef SFTPFILEATTR_H
-#define SFTPFILEATTR_H
-
-#include <sys/types.h>
-
-#include <tqglobal.h>
-#include <tqstring.h>
-#include <tqdatastream.h>
-
-#include <kio/global.h>
-#include <kdebug.h>
-
-#include "sftp.h"
-
-/**
- *@author Lucas Fisher
- */
-
-class KRemoteEncoding;
-
-class sftpFileAttr {
-
-private: // Private attributes
- /** Name of file. */
- TQString mFilename;
-
- /** Specifies which fields of the file attribute are available. */
- TQ_UINT32 mFlags;
-
- /** Size of the file in bytes. Should be 64 bit safe. */
- TQ_ULLONG mSize;
-
- /** User id of the owner of the file. */
- uid_t mUid;
-
- /** Group id of the group to which the file belongs. */
- gid_t mGid;
-
- /** POSIX permissions of the file. */
- mode_t mPermissions;
-
- /** Last access time of the file in seconds from Jan 1, 1970. */
- time_t mAtime;
-
- /** Last modification time of file in seconds since Jan. 1, 1970. */
- time_t mMtime;
-
- /** Number of file attribute extensions.
- Not currently implemented */
- TQ_UINT32 mExtendedCount;
-
- /** Longname of the file as found in a SSH_FXP_NAME sftp packet.
- These contents are parse to return the file's owner name and
- gr oup name. */
- TQCString mLongname;
-
- TQString mUserName;
- TQString mGroupName;
-
- /** If file is a link, contains the destination of the link */
- TQString mLinkDestination;
-
- /** If resource is a link, contains the type the link,e.g. file,dir... */
- mode_t mLinkType;
-
- /** Whether >> operator should read filename and longname from the stream. */
- bool mDirAttrs;
-
- /** Holds the encoding of the remote host */
- KRemoteEncoding* mEncoding;
-
-public:
- sftpFileAttr();
-
- sftpFileAttr(KRemoteEncoding* encoding);
-
- ~sftpFileAttr();
-
- /** Constructor to initialize the file attributes on declaration. */
- sftpFileAttr(TQ_ULLONG size_, uid_t uid_, gid_t gid_, mode_t permissions_,
- time_t atime_, time_t mtime_, TQ_UINT32 extendedCount_ = 0);
-
- /** Return the size of the sftp attribute not including filename or longname*/
- TQ_UINT32 size() const;
-
- /** Clear all attributes and flags. */
- void clear();
-
- /** Set the size of the file. */
- void setFileSize(TQ_ULLONG s)
- { mSize = s; mFlags |= SSH2_FILEXFER_ATTR_SIZE; }
-
- /** The size file attribute will not be included in the UDSEntry
- or when the file attribute is written to the sftp packet. */
- void clearFileSize()
- { mSize = 0; mFlags &= ~SSH2_FILEXFER_ATTR_SIZE; }
-
- /** Returns the size of the file. */
- TQ_ULLONG fileSize() const { return mSize; }
-
- /** Sets the POSIX permissions of the file. */
- void setPermissions(mode_t p)
- { mPermissions = p; mFlags |= SSH2_FILEXFER_ATTR_PERMISSIONS; }
-
- /** The permissions file attribute will not be included in the UDSEntry
- or when the file attribute is written to the sftp packet. */
- void clearPermissions()
- { mPermissions = 0; mFlags &= ~SSH2_FILEXFER_ATTR_PERMISSIONS; }
-
- /** Returns the POSIX permissons of the file. */
- mode_t permissions() const { return mPermissions; }
-
- /** Sets the group id of the file. */
- void setGid(gid_t id)
- { mGid = id; mFlags |= SSH2_FILEXFER_ATTR_UIDGID; }
-
- /** Neither the gid or uid file attributes will not be included in the UDSEntry
- or when the file attribute is written to the sftp packet. This is
- equivalent to clearUid() */
- void clearGid()
- { mGid = 0; mFlags &= SSH2_FILEXFER_ATTR_UIDGID; }
-
- /** Returns the group id of the file. */
- gid_t gid() const { return mGid; }
-
- /** Sets the uid of the file. */
- void setUid(uid_t id)
- { mUid = id; mFlags |= SSH2_FILEXFER_ATTR_UIDGID; }
-
- /** Neither the gid or uid file attributes will not be included in the UDSEntry
- or when the file attribute is written to the sftp packet. This is
- equivalent to clearGid() */
- void clearUid()
- { mUid = 0; mFlags &= SSH2_FILEXFER_ATTR_UIDGID; }
-
- /** Returns the user id of the file. */
- gid_t uid() const { return mUid; }
-
- /** Set the modificatoin time of the file in seconds since Jan. 1, 1970. */
- void setMtime(time_t t)
- { mMtime = t; mFlags |= SSH2_FILEXFER_ATTR_ACMODTIME; }
-
- /** Neither the mtime or atime file attributes will not be included in the UDSEntry
- or when the file attribute is written to the sftp packet. This is
- equivalent to clearAtime() */
- void clearMtime()
- { mMtime = 0; mFlags &= SSH2_FILEXFER_ATTR_ACMODTIME; }
-
- /** Returns the modification time of the file in seconds since Jan. 1, 1970. */
- time_t mtime() const { return mMtime; }
-
- /** Sets the access time of the file in seconds since Jan. 1, 1970. */
- void setAtime(time_t t)
- { mAtime = t; mFlags |= SSH2_FILEXFER_ATTR_ACMODTIME; }
-
- /** Neither the atime or mtime file attributes will not be included in the UDSEntry
- or when the file attribute is written to the sftp packet. This is
- equivalent to clearMtime() */
- void clearAtime()
- { mAtime = 0; mFlags &= SSH2_FILEXFER_ATTR_ACMODTIME; }
-
- /** Returns the last access time of the file in seconds since Jan. 1, 1970. */
- time_t atime() const { return mAtime; }
-
- /** Sets the number of file attribute extensions. */
- void setExtendedCount(unsigned int c)
- { mExtendedCount = c; mFlags |= SSH2_FILEXFER_ATTR_EXTENDED; }
-
- /** No extensions will be included when the file attribute is written
- to a sftp packet. */
- void clearExtensions()
- { mExtendedCount = 0; mFlags &= ~SSH2_FILEXFER_ATTR_EXTENDED; }
-
- /** Returns the number of file attribute extentsions. */
- unsigned int extendedCount() const { return mExtendedCount; }
-
- /** Returns the flags for the sftp file attributes. */
- unsigned int flags() const { return mFlags; }
-
- /** Sets file's longname. See sftpFileAttr::longname. */
- void setLongname(TQString l) { mLongname = l.latin1(); }
-
- /** Returns a string describing the file attributes. The format is specific
- to the implementation of the sftp server. In most cases (ie OpenSSH)
- this is similar to the long output of 'ls'. */
- TQString longname() const { return mLongname; }
-
- void setLinkDestination(const TQString& target)
- { mLinkDestination = target; }
-
- TQString linkDestination()
- { return mLinkDestination; }
-
- /** Sets the actual type a symbolic link points to. */
- void setLinkType (mode_t type) { mLinkType = type; }
-
- mode_t linkType() const { return mLinkType; }
-
- /** No descriptions */
- void setFilename(const TQString& fn)
- { mFilename = fn; }
-
- TQString filename() const
- { return mFilename; }
-
- /** Returns a UDSEntry describing the file.
- The UDSEntry is generated from the sftp file attributes. */
- TDEIO::UDSEntry entry();
-
- /** Use to output the file attributes to a sftp packet
- This will only write the sftp ATTR structure to the stream.
- It will never write the filename and longname because the client
- never sends those to the server. */
- friend TQDataStream& operator<< (TQDataStream&, const sftpFileAttr&);
-
- /** Use to read a file attribute from a sftp packet.
- Read this carefully! If the DirAttrs flag is true, this will
- read the filename, longname, and file attributes from the stream.
- This is for use with listing directories.
- If the DirAttrs flag is false, this will only read file attributes
- from the stream.
- BY DEFAULT, A NEW INSTANCE HAS DirAttrs == false */
- friend TQDataStream& operator>> (TQDataStream&, sftpFileAttr&);
-
- /** Parse longname for the owner and group names. */
- void getUserGroupNames();
-
- /** Sets the DirAttrs flag. This flag affects how the >> operator works on data streams. */
- void setDirAttrsFlag(bool flag){ mDirAttrs = flag; }
-
- /** Gets the DirAttrs flag. */
- bool getDirAttrsFlag() const { return mDirAttrs; }
-
- friend kdbgstream& operator<< (kdbgstream& s, sftpFileAttr& a);
- friend kndbgstream& operator<< (kndbgstream& s, sftpFileAttr& a);
-
- /** Returns the file type as determined from the file permissions */
- mode_t fileType() const;
-
- /** Set the encoding of the remote file system */
- void setEncoding( KRemoteEncoding* encoding );
-};
-
-#endif