summaryrefslogtreecommitdiffstats
path: root/tdersync
diff options
context:
space:
mode:
Diffstat (limited to 'tdersync')
-rw-r--r--tdersync/CMakeLists.txt50
-rw-r--r--tdersync/rsyncconfigdialog.cpp207
-rw-r--r--tdersync/rsyncconfigdialog.h105
-rw-r--r--tdersync/tdersync.cpp1071
-rw-r--r--tdersync/tdersync.h179
5 files changed, 1612 insertions, 0 deletions
diff --git a/tdersync/CMakeLists.txt b/tdersync/CMakeLists.txt
new file mode 100644
index 000000000..20ea5b777
--- /dev/null
+++ b/tdersync/CMakeLists.txt
@@ -0,0 +1,50 @@
+#################################################
+#
+# (C) 2011 Timothy Pearson
+# kb9vqf (AT) pearsoncomputing.net
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/tdefx
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### headers ###################################
+
+install( FILES
+ tdersync.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/libtdersync )
+
+
+##### tdersync ####################################
+
+set( target tdersync )
+
+set( ${target}_SRCS
+ tdersync.cpp rsyncconfigdialog.cpp
+)
+
+tde_add_library( ${target} SHARED AUTOMOC
+ SOURCES ${${target}_SRCS}
+ VERSION 0.0.1
+ LINK tdeui-shared kio-shared
+ DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/tdersync/rsyncconfigdialog.cpp b/tdersync/rsyncconfigdialog.cpp
new file mode 100644
index 000000000..0c1cd532a
--- /dev/null
+++ b/tdersync/rsyncconfigdialog.cpp
@@ -0,0 +1,207 @@
+/*
+ Copyright (C) 2000, 2001, 2002 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define HAVE_TERMIOS_H 1
+#define HAVE_GRANTPT 1
+
+#include <stdlib.h>
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_STROPTS
+#include <stropts.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#include <tqfile.h>
+#include <tqtimer.h>
+#include <tqapplication.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqwhatsthis.h>
+#include <tqiconview.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqstring.h>
+#include <tqregexp.h>
+#include <tqstyle.h>
+#include <tqtimer.h>
+#include <tqgroupbox.h>
+#include <tqradiobutton.h>
+#include <tqbuttongroup.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kinstance.h>
+
+#include <twin.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kprogressbox.h>
+#include <kpassdlg.h>
+#include <klistview.h>
+#include <kapplication.h>
+#include <kconfigdialog.h>
+
+#include <kdirlister.h>
+#include <kstandarddirs.h>
+#include <klistviewsearchline.h>
+#include <kiconviewsearchline.h>
+#include <kstaticdeleter.h>
+#include <kgenericfactory.h>
+#include <tdeparts/browserextension.h>
+
+#include "rsyncconfigdialog.h"
+
+/*
+ * RsyncConfigDialog implementation
+ */
+RsyncConfigDialog::RsyncConfigDialog(TQWidget* parent, const char* name,
+ const TQString& caption, const TQString& text,
+ const TQString& localfolder, const TQString& remotefolder,
+ int syncmode, bool modal)
+ : KDialogBase(KDialogBase::Plain, caption, KDialogBase::Cancel | KDialogBase::Ok,
+ KDialogBase::Ok, parent, name, modal),
+ mAutoClose(true),
+ mAutoReset(false),
+ mCancelled(false),
+ mAllowCancel(true),
+ mAllowTextEdit(false),
+ mShown(false),
+ mSyncAutoLogout(false)
+{
+#ifdef TQ_WS_X11
+ KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon());
+#endif
+ mShowTimer = new TQTimer(this);
+
+ showButton(KDialogBase::Close, false);
+ mCancelText = actionButton(KDialogBase::Cancel)->text();
+
+ TQFrame* mainWidget = plainPage();
+ TQVBoxLayout* layout = new TQVBoxLayout(mainWidget, 10);
+ mLabel = new TQLabel(TQString("<b>") + text + TQString("</b><br>")+i18n("Setting up synchronization for local folder")+TQString("<br><i>") + localfolder, mainWidget);
+ layout->addWidget(mLabel);
+
+ // Create an exclusive button group
+ TQButtonGroup *layoutg = new TQButtonGroup( 1, Qt::Horizontal, i18n("Synchronization Method")+TQString(":"), mainWidget);
+ layout->addWidget( layoutg );
+ layoutg->setExclusive( TRUE );
+
+ // Insert radiobuttons
+ rsync_rb1 = new TQRadioButton(i18n("&Utilize rsync + ssh for upload to remote server\nExample: servername:/path/to/remote/folder"), layoutg);
+ rsync_rb2 = new TQRadioButton(i18n("&Utilize rsync + ssh for download from remote server\nExample: servername:/path/to/remote/folder"), layoutg);
+ rsync_rb3 = new TQRadioButton(i18n("&Utilize unison + ssh for bidirectional synchronization with remote server\nExample: ssh://servername//path/to/remote/folder"), layoutg);
+
+ if (syncmode == 1)
+ rsync_rb1->setChecked( TRUE );
+ else if (syncmode == 2)
+ rsync_rb2->setChecked( TRUE );
+ else if (syncmode == 3)
+ rsync_rb3->setChecked( TRUE );
+
+ //(void)new TQRadioButton( "R&adiobutton 2", layoutg );
+ //(void)new TQRadioButton( "Ra&diobutton 3", layoutg );
+
+ // Create an exclusive button group
+ TQButtonGroup *layoutm = new TQButtonGroup( 1, Qt::Horizontal, i18n("Remote Folder")+TQString(":"), mainWidget);
+ layout->addWidget( layoutm );
+ layoutg->setExclusive( TRUE );
+
+ m_rsync_txt = new TQLineEdit(layoutm);
+ if (remotefolder.isEmpty() == false) {
+ m_rsync_txt->setText(remotefolder);
+ }
+
+ // Create an exclusive button group
+ TQButtonGroup *layouta = new TQButtonGroup( 1, Qt::Horizontal, i18n("Automatic Synchronization")+TQString(":"), mainWidget);
+ layout->addWidget( layouta );
+ layouta->setExclusive( FALSE );
+
+ m_sync_auto_logout_cb = new TQCheckBox(layouta);
+ m_sync_auto_logout_cb->setText(i18n("Synchronize on logout"));
+ m_sync_auto_logout_cb->setChecked(mSyncAutoLogout);
+
+ setFixedSize( sizeHint() );
+
+ m_rsync_txt->setFocus();
+}
+
+int RsyncConfigDialog::getSyncMode()
+{
+ if (rsync_rb1->isChecked() == true)
+ return 1;
+ else if (rsync_rb2->isChecked() == true)
+ return 2;
+ else if (rsync_rb3->isChecked() == true)
+ return 3;
+ else
+ return 0;
+}
+
+int RsyncConfigDialog::getAutoSyncFlags()
+{
+ int flags = 0;
+ if (m_sync_auto_logout_cb->isChecked() == true)
+ flags = flags | 0x1;
+
+ return flags;
+}
+
+void RsyncConfigDialog::setAutoSyncFlags(int flags) {
+ m_sync_auto_logout_cb->setChecked((flags & 0x1) != 0);
+}
+
+TQLineEdit* RsyncConfigDialog::lineEdit()
+{
+ return m_rsync_txt;
+}
+
+const TQLineEdit* RsyncConfigDialog::lineEdit() const
+{
+ return m_rsync_txt;
+}
+
+#include "rsyncconfigdialog.moc"
diff --git a/tdersync/rsyncconfigdialog.h b/tdersync/rsyncconfigdialog.h
new file mode 100644
index 000000000..3da9e6f79
--- /dev/null
+++ b/tdersync/rsyncconfigdialog.h
@@ -0,0 +1,105 @@
+/*
+ Copyright (C) 2000, 2001, 2002 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __RSYNC_CONFIG_DIALOG_H
+#define __RSYNC_CONFIG_DIALOG_H
+
+#include <tqmap.h>
+#include <tqstringlist.h>
+#include <tqlineedit.h>
+#include <tqcheckbox.h>
+#include <tqradiobutton.h>
+
+#include <kurl.h>
+#include <kprocess.h>
+#include <kfileitem.h>
+#include <klibloader.h>
+#include <kdialogbase.h>
+
+// NOTE: If ANY of these functions are not utilized in the C file,
+// and in a manner identical to these declarations, the plugin will
+// mysteriously fail when launched with kshell but work fine under BASH
+
+class RsyncConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+
+ public:
+ RsyncConfigDialog(TQWidget* parent = 0, const char* name = 0,
+ const TQString& caption = TQString(),
+ const TQString& text = TQString(),
+ const TQString& localfolder = TQString(),
+ const TQString& remotefolder = TQString(),
+ int syncmode = 1, bool modal = false);
+
+ /**
+ * Returns the TQLineEdit used in this dialog.
+ * To set the number of lines or other text box related
+ * settings, access the KTextEdit object directly via this method.
+ */
+ TQLineEdit* lineEdit();
+
+ /**
+ * Returns the TQLineEdit used in this dialog.
+ * To set the number of lines or other text box related
+ * settings, access the KTextEdit object directly via this method.
+ */
+ const TQLineEdit* lineEdit() const;
+
+ /**
+ * Returns index of selected synchronization mode
+ * 1: Upload
+ * 2: Download
+ * 3: Bidirectional
+ */
+ int getSyncMode();
+
+ /**
+ * Returns the selected autosync flags
+ * Bit 0: Sync on logout
+ */
+ int getAutoSyncFlags();
+
+ /**
+ * Sets the selected autosync flags
+ *
+ * @see getAutoSyncFlags()
+ */
+ void setAutoSyncFlags(int flags);
+
+ private:
+ bool mAutoClose;
+ bool mAutoReset;
+ bool mCancelled;
+ bool mAllowCancel;
+ bool mAllowTextEdit;
+ bool mShown;
+ bool mSyncAutoLogout;
+ TQString mCancelText;
+ TQLabel* mLabel;
+ KProgress* mProgressBar;
+ KTextEdit* mTextBox;
+ TQTimer* mShowTimer;
+ TQLineEdit* m_rsync_txt;
+ TQCheckBox* m_sync_auto_logout_cb;
+ TQRadioButton *rsync_rb1;
+ TQRadioButton *rsync_rb2;
+ TQRadioButton *rsync_rb3;
+};
+#endif
diff --git a/tdersync/tdersync.cpp b/tdersync/tdersync.cpp
new file mode 100644
index 000000000..3e9e49981
--- /dev/null
+++ b/tdersync/tdersync.cpp
@@ -0,0 +1,1071 @@
+/*
+ Copyright (C) 2000, 2001, 2002 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define HAVE_TERMIOS_H 1
+#define HAVE_GRANTPT 1
+
+#include <stdlib.h>
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_STROPTS
+#include <stropts.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#include <kio/global.h>
+#include <kio/slavebase.h>
+
+#include "tdersync.h"
+#include "rsyncconfigdialog.h"
+
+#define myDebug(x) kdDebug(7127) << __LINE__ << ": " x
+
+#define CONFIGURATION_FILE_SEPARATOR ';'
+
+KDE_EXPORT KRsync::KRsync (TQObject* parent, const char* name)
+ : TQObject (parent, name), m_progressDialog(false), m_progressDialogExists(false), m_bSettingsLoaded(false), m_bInSpecialSync(false)
+{
+ loadSettings();
+
+ childPid = 0;
+ isLoggedIn = false;
+ firstLogin = true;
+ connectionAuth.keepPassword = true;
+ outBufPos = -1;
+ outBuf = NULL;
+ outBufLen = 0;
+ isStat = false; // FIXME: just a workaround for konq deficiencies
+ redirectUser = ""; // FIXME: just a workaround for konq deficiencies
+ redirectPass = ""; // FIXME: just a workaround for konq deficiencies
+}
+
+KDE_EXPORT KRsync::~KRsync()
+{
+
+}
+
+static int open_pty_pair(int fd[2])
+{
+#if defined(HAVE_TERMIOS_H) && defined(HAVE_GRANTPT) && !defined(HAVE_OPENPTY)
+/** with kind regards to The GNU C Library
+Reference Manual for Version 2.2.x of the GNU C Library */
+ int master, slave;
+ char *name;
+ struct ::termios ti;
+ memset(&ti,0,sizeof(ti));
+
+ ti.c_cflag = CLOCAL|CREAD|CS8;
+ ti.c_cc[VMIN] = 1;
+
+#ifdef HAVE_GETPT
+ master = getpt();
+#else
+ master = open("/dev/ptmx", O_RDWR);
+#endif
+ if (master < 0) return 0;
+
+ if (grantpt(master) < 0 || unlockpt(master) < 0) goto close_master;
+
+ name = ptsname(master);
+ if (name == NULL) goto close_master;
+
+ slave = open(name, O_RDWR);
+ if (slave == -1) goto close_master;
+
+#if (defined(HAVE_ISASTREAM) || defined(isastream)) && defined(I_PUSH)
+ if (isastream(slave) &&
+ (ioctl(slave, I_PUSH, "ptem") < 0 ||
+ ioctl(slave, I_PUSH, "ldterm") < 0))
+ goto close_slave;
+#endif
+
+ tcsetattr(slave, TCSANOW, &ti);
+ fd[0] = master;
+ fd[1] = slave;
+ return 0;
+
+#if (defined(HAVE_ISASTREAM) || defined(isastream)) && defined(I_PUSH)
+close_slave:
+#endif
+ close(slave);
+
+close_master:
+ close(master);
+ return -1;
+#else
+#ifdef HAVE_OPENPTY
+ struct ::termios ti;
+ memset(&ti,0,sizeof(ti));
+
+ ti.c_cflag = CLOCAL|CREAD|CS8;
+ ti.c_cc[VMIN] = 1;
+
+ return openpty(fd,fd+1,NULL,&ti,NULL);
+#else
+#ifdef __GNUC__
+#warning "No tty support available. Password dialog won't work."
+#endif
+ return socketpair(PF_UNIX,SOCK_STREAM,0,fd);
+#endif
+#endif
+}
+/**
+creates the unidirectional sync subprocess
+*/
+KDE_EXPORT bool KRsync::syncUnidirectional(TQString synccommand, TQString syncflags, int parameter_order, TQString localfolder, TQString remotepath) {
+ int fd[2];
+ int rc, flags;
+ thisFn = TQString();
+
+ rc = open_pty_pair(fd);
+ if (rc == -1) {
+ myDebug( << "socketpair failed, error: " << strerror(errno) << endl);
+ return true;
+ }
+
+ childPid = fork();
+ if (childPid == -1) {
+ myDebug( << "fork failed, error: " << strerror(errno) << endl);
+ close(fd[0]);
+ close(fd[1]);
+ childPid = 0;
+ return true;
+ }
+ if (childPid == 0) {
+ // Create the rsync command to run
+ TQString execstring;
+ if (parameter_order == 0) {
+ execstring = synccommand + syncflags + localfolder + TQString("/ ") + remotepath;
+ }
+ else {
+ execstring = synccommand + syncflags + remotepath + TQString("/ ") + localfolder;
+ }
+
+ // taken from konsole, see TEPty.C for details
+ // note: if we're running on socket pairs,
+ // this will fail, but thats what we expect
+
+ for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
+
+ struct rlimit rlp;
+ getrlimit(RLIMIT_NOFILE, &rlp);
+ for (int i = 0; i < (int)rlp.rlim_cur; i++)
+ if (i != fd[1]) close(i);
+
+ dup2(fd[1],0);
+ dup2(fd[1],1);
+ dup2(fd[1],2);
+ if (fd[1] > 2) close(fd[1]);
+
+ setsid();
+
+#if defined(TIOCSCTTY)
+ ioctl(0, TIOCSCTTY, 0);
+#endif
+
+ int pgrp = getpid();
+#if defined( _AIX) || defined( __hpux)
+ tcsetpgrp(0, pgrp);
+#else
+ ioctl(0, TIOCSPGRP, (char *)&pgrp);
+#endif
+
+ const char *dev = ttyname(0);
+ setpgid(0,0);
+ if (dev) close(open(dev, O_WRONLY, 0));
+ setpgid(0,0);
+
+ if (system(execstring.ascii()) < 0) {
+ // ERROR
+ }
+ #undef common_args
+ myDebug( << "could not exec! " << strerror(errno) << endl);
+ ::exit(-1);
+ }
+ close(fd[1]);
+ rc = fcntl(fd[0],F_GETFL,&flags);
+ rc = fcntl(fd[0],F_SETFL,flags|O_NONBLOCK);
+ childFd = fd[0];
+
+ fd_set rfds, wfds;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ char buf[32768];
+ int offset = 0;
+ while (!isLoggedIn) {
+ FD_SET(childFd,&rfds);
+ FD_ZERO(&wfds);
+ if (outBufPos >= 0) FD_SET(childFd,&wfds);
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 1000;
+ rc = select(childFd+1, &rfds, &wfds, NULL, &timeout);
+ if (rc < 0) {
+ if (errno == EINTR)
+ continue;
+ myDebug( << "select failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+ return true;
+ }
+ if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {
+ if (outBuf) {
+ rc = write(childFd,outBuf+outBufPos,outBufLen-outBufPos);
+ fflush(stdout);
+ }
+ else {
+ rc = 0;
+ }
+ if (rc >= 0) outBufPos += rc;
+ else {
+ if (errno == EINTR)
+ continue;
+ myDebug( << "write failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+ outBufPos = -1;
+ //return true;
+ }
+ if (outBufPos >= outBufLen) {
+ outBufPos = -1;
+ outBuf = NULL;
+ outBufLen = 0;
+ }
+ }
+ if (FD_ISSET(childFd,&rfds)) {
+ rc = read(childFd,buf+offset,32768-offset);
+ if (rc > 0) {
+ int noff = establishConnectionRsync(buf,rc+offset);
+ if (noff < 0) return false;
+ if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
+ offset = noff;
+ } else {
+ if (errno == EINTR)
+ continue;
+ //if (errno == EAGAIN)
+ // continue;
+ myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+creates the bidirectional sync subprocess
+*/
+KDE_EXPORT bool KRsync::syncBidirectional(TQString synccommand, TQString syncflags, int parameter_order, TQString localfolder, TQString remotepath) {
+ int fd[2];
+ int rc, flags;
+ thisFn = TQString();
+
+ // Check for and remove the trailing slash in localfolder
+ if (localfolder.endsWith("/")) {
+ localfolder.remove(localfolder.length()-1, 1);
+ }
+
+ rc = open_pty_pair(fd);
+ if (rc == -1) {
+ myDebug( << "socketpair failed, error: " << strerror(errno) << endl);
+ return true;
+ }
+
+ childPid = fork();
+ if (childPid == -1) {
+ myDebug( << "fork failed, error: " << strerror(errno) << endl);
+ close(fd[0]);
+ close(fd[1]);
+ childPid = 0;
+ return true;
+ }
+ if (childPid == 0) {
+ // Create the rsync command to run
+ TQString execstring;
+ execstring = synccommand + syncflags + localfolder + TQString(" ") + remotepath;
+
+ // taken from konsole, see TEPty.C for details
+ // note: if we're running on socket pairs,
+ // this will fail, but thats what we expect
+
+ for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL);
+
+ struct rlimit rlp;
+ getrlimit(RLIMIT_NOFILE, &rlp);
+ for (int i = 0; i < (int)rlp.rlim_cur; i++)
+ if (i != fd[1]) close(i);
+
+ dup2(fd[1],0);
+ dup2(fd[1],1);
+ dup2(fd[1],2);
+ if (fd[1] > 2) close(fd[1]);
+
+ setsid();
+
+#if defined(TIOCSCTTY)
+ ioctl(0, TIOCSCTTY, 0);
+#endif
+
+ int pgrp = getpid();
+#if defined( _AIX) || defined( __hpux)
+ tcsetpgrp(0, pgrp);
+#else
+ ioctl(0, TIOCSPGRP, (char *)&pgrp);
+#endif
+
+ const char *dev = ttyname(0);
+ setpgid(0,0);
+ if (dev) close(open(dev, O_WRONLY, 0));
+ setpgid(0,0);
+
+ if (system(execstring.ascii()) < 0) {
+ // ERROR
+ }
+ #undef common_args
+ myDebug( << "could not exec! " << strerror(errno) << endl);
+ ::exit(-1);
+ }
+ close(fd[1]);
+ rc = fcntl(fd[0],F_GETFL,&flags);
+ rc = fcntl(fd[0],F_SETFL,flags|O_NONBLOCK);
+ childFd = fd[0];
+
+ fd_set rfds, wfds;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ char buf[32768];
+ int offset = 0;
+ while (!isLoggedIn) {
+ FD_SET(childFd,&rfds);
+ FD_ZERO(&wfds);
+ if (outBufPos >= 0) FD_SET(childFd,&wfds);
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 1000;
+ rc = select(childFd+1, &rfds, &wfds, NULL, &timeout);
+ if (rc < 0) {
+ if (errno == EINTR)
+ continue;
+ myDebug( << "select failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+ return true;
+ }
+ if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {
+ if (outBuf) {
+ rc = write(childFd,outBuf+outBufPos,outBufLen-outBufPos);
+ fflush(stdout);
+ }
+ else {
+ rc = 0;
+ }
+ if (rc >= 0) outBufPos += rc;
+ else {
+ if (errno == EINTR)
+ continue;
+ myDebug( << "write failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+ outBufPos = -1;
+ //return true;
+ }
+ if (outBufPos >= outBufLen) {
+ outBufPos = -1;
+ outBuf = NULL;
+ outBufLen = 0;
+ }
+ }
+ if (FD_ISSET(childFd,&rfds)) {
+ rc = read(childFd,buf+offset,32768-offset);
+ if (rc > 0) {
+ int noff = establishConnectionUnison(buf,rc+offset, localfolder, remotepath);
+ if (noff < 0) return false;
+ if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
+ offset = noff;
+ } else {
+ if (errno == EINTR)
+ continue;
+ //if (errno == EAGAIN)
+ // continue;
+ myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+writes one chunk of data to stdin of child process
+*/
+KDE_EXPORT void KRsync::writeChild(const char *buf, TDEIO::fileoffset_t len) {
+ if (outBufPos >= 0 && outBuf) {
+#if 0
+ TQString debug;
+ debug.setLatin1(outBuf,outBufLen);
+ if (len > 0) myDebug( << "write request while old one is pending, throwing away input (" << outBufLen << "," << outBufPos << "," << debug.left(10) << "...)" << endl);
+#endif
+ return;
+ }
+ outBuf = buf;
+ outBufPos = 0;
+ outBufLen = len;
+}
+
+/**
+manages initial communication setup including password queries
+*/
+KDE_EXPORT int KRsync::establishConnectionRsync(char *buffer, TDEIO::fileoffset_t len) {
+ TQString buf;
+ buf.setLatin1(buffer,len);
+ int pos;
+ // Strip trailing whitespace
+ while (buf.length() && (buf[buf.length()-1] == ' '))
+ buf.truncate(buf.length()-1);
+
+ myDebug( << "establishing: got " << buf << endl);
+ while (childPid && ((pos = buf.find('\n')) >= 0 || buf.endsWith(":") || buf.endsWith("?"))) {
+ if (m_progressDialogExists == true) {
+ tqApp->processEvents();
+ }
+ pos++;
+ TQString str = buf.left(pos);
+ buf = buf.mid(pos);
+ if (str == "\n")
+ continue;
+ //if (str.contains("rsync error:")) {
+ if (str.contains("rsync:") || str.contains("failed.") || (str.contains("Could not") && str.endsWith("."))) {
+ KMessageBox::error(NULL, str, i18n("Remote Folder Synchronization"));
+ }
+ else if (!str.isEmpty()) {
+ thisFn += str;
+ if ((buf.endsWith(":") == false) && (buf.endsWith("?") == false)) {
+ // Display a nice little progress bar with text box
+ if (m_progressDialogExists == false) {
+ m_progressDialog = new KProgressBoxDialog(0, "rsyncProgress", i18n("Synchronizing Folder..."), i18n("Synchronizing Folder..."), true);
+ m_progressDialog->progressBar()->setFormat("%v / %m");
+ m_progressDialog->setAutoClose(true);
+ m_progressDialog->progressBar()->setTotalSteps(2);
+ m_progressDialog->progressBar()->setValue(1);
+ connect (m_progressDialog, TQT_SIGNAL(cancelClicked()), TQT_SLOT(slotRsyncCancelled()));
+ if (m_bInSpecialSync) m_progressDialog->move(0,0);
+ m_progressDialog->show();
+ m_progressDialogExists = true;
+ }
+ }
+ }
+ else if (buf.endsWith(":")) {
+ if (!redirectUser.isEmpty() && connectionUser != redirectUser) {
+ // FIXME: Possibly do something here; is this the success response?
+ return -1;
+ } else if (!connectionPassword.isEmpty()) {
+ myDebug( << "sending cpass" << endl);
+ connectionAuth.password = connectionPassword+"\n";
+ connectionPassword = TQString();
+ writeChild(connectionAuth.password.latin1(),connectionAuth.password.length());
+ } else {
+ myDebug( << "sending mpass" << endl);
+ connectionAuth.prompt = thisFn+buf;
+ connectionAuth.password = TQString(); // don't prefill
+ TQCString thispass;
+ if (KPasswordDialog::getPassword (thispass, i18n("Remote authorization required") + TQString("\n") + i18n("Please input") + TQString(" ") + TQString(buf), NULL) != 1) {
+ shutdownConnection(true, false);
+ return -1;
+ }
+ else {
+ connectionAuth.password = TQString(thispass);
+ }
+ connectionAuth.password += "\n";
+ myDebug( << "sending pass" << endl);
+ writeChild(connectionAuth.password.latin1(),connectionAuth.password.length());
+ }
+ thisFn = TQString();
+ return 0;
+ }
+ else if (buf.endsWith("?")) {
+ int rc = KMessageBox::questionYesNo(NULL, thisFn+buf, i18n("Remote Folder Synchronization"));
+ if (rc == KMessageBox::Yes) {
+ writeChild("yes\n",4);
+ } else {
+ writeChild("no\n",3);
+ }
+ thisFn = TQString();
+ return 0;
+ }
+
+ if (m_progressDialogExists == true) {
+ while (!m_progressDialog) {
+ usleep(100);
+ }
+ while (!m_progressDialog->textEdit()) {
+ usleep(100);
+ }
+ if (str.contains("exit()") && str.contains("ICE default IO")) {
+ if (m_progressDialogExists == true) {
+ m_progressDialog->progressBar()->setValue(m_progressDialog->progressBar()->totalSteps());
+ }
+ }
+ else {
+ if (str.contains(", to-check=")) {
+ // Parse the to-check output
+ TQString tocheck_out_cur;
+ TQString tocheck_out_tot;
+ tocheck_out_cur = str.mid(str.find(", to-check=") + 11, str.length());
+ tocheck_out_tot = tocheck_out_cur.mid(tocheck_out_cur.find("/") + 1, tocheck_out_cur.length());
+ tocheck_out_cur = tocheck_out_cur.left(tocheck_out_cur.find("/"));
+ tocheck_out_tot = tocheck_out_tot.left(tocheck_out_tot.find(")"));
+ m_progressDialog->progressBar()->setTotalSteps(tocheck_out_tot.toInt()-1);
+ m_progressDialog->progressBar()->setValue(tocheck_out_tot.toInt()-tocheck_out_cur.toInt()-2);
+ }
+ else {
+ m_progressDialog->textEdit()->append(str);
+ m_progressDialog->textEdit()->scrollToBottom();
+ }
+ }
+ }
+ }
+ return buf.length();
+}
+
+/**
+manages initial communication setup including password queries
+*/
+KDE_EXPORT int KRsync::establishConnectionUnison(char *buffer, TDEIO::fileoffset_t len, TQString localfolder, TQString remotepath) {
+ TQString buf;
+ buf.setLatin1(buffer,len);
+ int pos;
+ // Strip trailing whitespace
+ while (buf.length() && (buf[buf.length()-1] == ' '))
+ buf.truncate(buf.length()-1);
+
+ myDebug( << "establishing: got " << buf << endl);
+ while (childPid && (((pos = buf.find('\n')) >= 0) || buf.endsWith(":") || buf.endsWith("?") || buf.endsWith("]"))) {
+ if (m_progressDialogExists == true) {
+ tqApp->processEvents();
+ }
+ pos++;
+ TQString str = buf.left(pos);
+ buf = buf.mid(pos);
+ if (str == "\n")
+ continue;
+ //if (str.contains("rsync error:")) {
+ if (((str.contains("rsync:") || str.contains("failed.") || str.contains("Could not")) && str.endsWith("."))) {
+ KMessageBox::error(NULL, str, i18n("Remote Folder Synchronization"));
+ }
+ else if (str.startsWith("Fatal error")) {
+ TQString fullError = str + buf;
+ fullError.replace("Fatal error: Server:", TQString("<b>").append(i18n("An error ocurred on the remote system")).append(":</b><br>"));
+ fullError.replace("\n", "");
+ fullError.replace(": unable", ":<br>Unable");
+ fullError.replace(")", ")</i><br>");
+ fullError.replace("(", "<br><i>(");
+ KMessageBox::error(NULL, fullError, i18n("Remote Folder Synchronization"));
+ }
+ else if (!str.isEmpty()) {
+ thisFn += str;
+ if ((buf.endsWith(":") == false) && (buf.endsWith("?") == false)) {
+ // Display a nice little progress bar with text box
+ if (m_progressDialogExists == false) {
+ m_progressDialog = new KProgressBoxDialog(0, "rsyncProgress", i18n("Synchronizing Folder..."), i18n("Synchronizing Folder..."), true);
+ m_progressDialog->progressBar()->setFormat("%v / %m");
+ m_progressDialog->progressBar()->setTotalSteps(0);
+ m_progressDialog->setAutoClose(true);
+ connect (m_progressDialog, TQT_SIGNAL(cancelClicked()), TQT_SLOT(slotUnisonCancelled()));
+ if (m_bInSpecialSync) m_progressDialog->move(0,0);
+ m_progressDialog->show();
+ m_progressDialogExists = true;
+ }
+ }
+ }
+ else if (buf.endsWith(":")) {
+ if (!redirectUser.isEmpty() && connectionUser != redirectUser) {
+ // FIXME: Possibly do something here; is this the success response?
+ return -1;
+ } else if (!connectionPassword.isEmpty()) {
+ myDebug( << "sending cpass" << endl);
+ connectionAuth.password = connectionPassword+"\n";
+ connectionPassword = TQString();
+ writeChild(connectionAuth.password.latin1(),connectionAuth.password.length());
+ } else {
+ myDebug( << "sending mpass" << endl);
+ connectionAuth.prompt = thisFn+buf;
+ connectionAuth.password = TQString(); // don't prefill
+ TQCString thispass;
+ if (KPasswordDialog::getPassword (thispass, i18n("Remote authorization required") + TQString("\n") + i18n("Please input") + TQString(" ") + TQString(buf), NULL) != 1) {
+ slotUnisonCancelled();
+ return -1;
+ }
+ else {
+ connectionAuth.password = TQString(thispass);
+ }
+ connectionAuth.password += "\n";
+ myDebug( << "sending pass" << endl);
+ writeChild(connectionAuth.password.latin1(),connectionAuth.password.length());
+ }
+ thisFn = TQString();
+ return 0;
+ }
+ else if (buf.endsWith("?") || buf.endsWith("? []")) {
+ buf.replace("[]", "");
+ if (buf.endsWith("? []")) {
+ if (buf.startsWith("Proceed with propagating updates")) {
+ writeChild("y\n",3);
+ }
+ else {
+ int rc = KMessageBox::questionYesNo(NULL, buf, i18n("Remote Folder Synchronization"));
+ if (rc == KMessageBox::Yes) {
+ writeChild("y\n",3);
+ } else {
+ writeChild("n\n",3);
+ }
+ }
+ }
+ else {
+ if (buf.startsWith("Proceed with propagating updates")) {
+ writeChild("y\n",3);
+ }
+ else {
+ int rc = KMessageBox::questionYesNo(NULL, buf, i18n("Remote Folder Synchronization"));
+ if (rc == KMessageBox::Yes) {
+ writeChild("yes\n",4);
+ } else {
+ writeChild("no\n",3);
+ }
+ }
+ }
+ thisFn = TQString();
+ buf = "";
+ return 0;
+ }
+ else if (buf.endsWith("]")) {
+ if (m_progressDialogExists == true) {
+ m_progressDialog->textEdit()->append(buf);
+ m_progressDialog->textEdit()->scrollToBottom();
+ int currentPos;
+ currentPos = m_progressDialog->progressBar()->progress();
+ m_progressDialog->progressBar()->setProgress(++currentPos);
+ }
+ TQString file_name;
+ file_name = buf;
+ file_name.replace("[]", "");
+ file_name.replace(TQString("changed "), "");
+ file_name.replace(TQString("new file "), "");
+ file_name.replace("<-?->", "");
+ file_name = file_name.stripWhiteSpace();
+ if (localfolder.endsWith("Press return to continue.[]")) localfolder.truncate(localfolder.length()-TQString("Press return to continue.[]").length());
+ if (remotepath.endsWith("Press return to continue.[]")) remotepath.truncate(remotepath.length()-TQString("Press return to continue.[]").length());
+ KDialogBase *dialog= new KDialogBase(i18n("User Intervention Required"), KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel, KDialogBase::Yes, KDialogBase::Cancel, NULL, "warningYesNoCancel", true, true, i18n("Use &Local File"), i18n("Use &Remote File"), i18n("&Ignore"));
+ TQString prettyremotepath = remotepath;
+ TQString prettylocalfolder = localfolder;
+ if (!prettyremotepath.endsWith("/")) prettyremotepath = prettyremotepath + "/";
+ if (!prettylocalfolder.endsWith("/")) prettylocalfolder = prettylocalfolder + "/";
+ prettyremotepath = prettyremotepath.stripWhiteSpace();
+ prettylocalfolder = prettylocalfolder.stripWhiteSpace();
+ int rc = KMessageBox::createKMessageBox(dialog, TQMessageBox::Warning, TQString("<b>") + i18n("WARNING: Both the local and remote file have been modified") + TQString("</b><p>") + i18n("Local") + TQString(": ") + prettylocalfolder + file_name + TQString("<br>") + i18n("Remote") + TQString(": ") + prettyremotepath + file_name + TQString("<p>") + i18n("Please select the file to duplicate (the other will be overwritten)") + TQString("<br>") + i18n("Or, select Ignore to skip synchronization of this file for now"), TQStringList(), TQString(), NULL, 1);
+ if (rc == KDialogBase::Yes) {
+ writeChild(">\n",3);
+ }
+ else if (rc == KDialogBase::No) {
+ writeChild("<\n",3);
+ }
+ else {
+ writeChild("/\n",3);
+ }
+ return 0;
+ }
+
+ if (m_progressDialogExists == true) {
+ if ((str.contains("exit()") && str.contains("ICE default IO")) || (str.startsWith("Fatal error"))) {
+ if (m_progressDialogExists == true) {
+ while (!m_progressDialog) {
+ usleep(100);
+ }
+ while (!m_progressDialog->textEdit()) {
+ usleep(100);
+ }
+ m_progressDialog->progressBar()->setFormat("%v / %m");
+ m_progressDialog->progressBar()->setTotalSteps(2);
+ m_progressDialog->progressBar()->setValue(m_progressDialog->progressBar()->totalSteps());
+ }
+ }
+ else {
+ if (m_progressDialogExists == true) {
+ while (!m_progressDialog) {
+ usleep(100);
+ }
+ while (!m_progressDialog->textEdit()) {
+ usleep(100);
+ }
+ m_progressDialog->textEdit()->append(str);
+ m_progressDialog->textEdit()->scrollToBottom();
+ int currentPos;
+ currentPos = m_progressDialog->progressBar()->progress();
+ m_progressDialog->progressBar()->setProgress(++currentPos);
+ }
+ }
+ }
+ }
+ return buf.length();
+}
+
+/**
+Forced close of the connection
+
+This function gets called from the application side of the universe,
+it shouldn't send any response.
+ */
+KDE_EXPORT void KRsync::closeConnection(){
+ myDebug( << "closeConnection()" << endl);
+ shutdownConnection(true, false);
+}
+
+/**
+Closes the connection
+ */
+KDE_EXPORT void KRsync::shutdownConnection(bool forced, bool wait){
+ if (childPid) {
+ kill(childPid,SIGTERM); // We may not have permission...
+ childPid = 0;
+ if (wait == false) {
+ close(childFd); // ...in which case this should do the trick
+ childFd = -1;
+ }
+ }
+ outBufPos = -1;
+ outBuf = NULL;
+ outBufLen = 0;
+ isLoggedIn = false;
+}
+
+// --------------------------------------------------------------------------------------------
+//
+// Here begins the standard load/save/search/Konqy stuff
+//
+// --------------------------------------------------------------------------------------------
+
+KDE_EXPORT void KRsync::saveSettings()
+{
+ TDEConfig cfg ("rsyncrc", false, false);
+ cfg.setGroup ("General");
+ cfg.writeEntry("LocalFolders", cfgfolderlist, CONFIGURATION_FILE_SEPARATOR);
+ cfg.writeEntry("AutoSyncOnLogout", cfgautosync_onlogout_list, CONFIGURATION_FILE_SEPARATOR);
+ cfg.sync();
+}
+
+KDE_EXPORT void KRsync::loadSettings()
+{
+ if (m_bSettingsLoaded)
+ return;
+
+ TDEConfig cfg ("rsyncrc", false, false);
+ cfg.setGroup ("General");
+
+ cfgfolderlist = cfg.readListEntry("LocalFolders", CONFIGURATION_FILE_SEPARATOR);
+ cfgautosync_onlogout_list = cfg.readListEntry("AutoSyncOnLogout", CONFIGURATION_FILE_SEPARATOR);
+
+ m_bSettingsLoaded = true;
+}
+
+KDE_EXPORT void KRsync::executeLogoutAutoSync()
+{
+ for (TQStringList::Iterator i(cfgautosync_onlogout_list.begin()); i != cfgautosync_onlogout_list.end(); ++i) {
+ setCurrentDirectoryURL(*i);
+ m_bInSpecialSync = true;
+ slotSync();
+ m_bInSpecialSync = false;
+ }
+}
+
+KDE_EXPORT TQString KRsync::findLocalFolderByName(TQString folderurl)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ for (TQStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+ if (TQString::compare((*i), folderurl_stripped) == 0) {
+ i++;
+ return (*i);
+ i++;
+ i++;
+ i++;
+ i++;
+ i++;
+ }
+ }
+ return NULL;
+}
+
+KDE_EXPORT TQString KRsync::findSyncMethodByName(TQString folderurl)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ for (TQStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+ if (TQString::compare((*i), folderurl_stripped) == 0) {
+ i++;
+ i++;
+ return (*i);
+ i++;
+ i++;
+ i++;
+ i++;
+ }
+ }
+ return NULL;
+}
+
+KDE_EXPORT TQString KRsync::findLoginSyncEnabledByName(TQString folderurl)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ for (TQStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+ if (TQString::compare((*i), folderurl_stripped) == 0) {
+ i++;
+ i++;
+ i++;
+ i++;
+ return (*i);
+ i++;
+ i++;
+ }
+ }
+ return NULL;
+}
+
+KDE_EXPORT TQString KRsync::findLogoutSyncEnabledByName(TQString folderurl)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ for (TQStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+ if (TQString::compare((*i), folderurl_stripped) == 0) {
+ i++;
+ i++;
+ i++;
+ i++;
+ i++;
+ return (*i);
+ i++;
+ }
+ }
+ return NULL;
+}
+
+KDE_EXPORT TQString KRsync::findTimedSyncEnabledByName(TQString folderurl)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ for (TQStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+ if (TQString::compare((*i), folderurl_stripped) == 0) {
+ i++;
+ i++;
+ i++;
+ i++;
+ i++;
+ i++;
+ return (*i);
+ }
+ }
+ return NULL;
+}
+
+KDE_EXPORT int KRsync::deleteLocalFolderByName(TQString folderurl)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ for (TQStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+ if (TQString::compare((*i), folderurl_stripped) == 0) {
+ i=cfgfolderlist.remove(i);
+ i=cfgfolderlist.remove(i);
+ i=cfgfolderlist.remove(i);
+ i=cfgfolderlist.remove(i);
+ i=cfgfolderlist.remove(i);
+ i=cfgfolderlist.remove(i);
+ cfgfolderlist.remove(i);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+KDE_EXPORT int KRsync::addLocalFolderByName(TQString folderurl, TQString remoteurl, TQString syncmethod, TQString excludelist, TQString sync_on_login, TQString sync_on_logout, TQString sync_timed_interval)
+{
+ TQString folderurl_stripped;
+ folderurl_stripped = folderurl;
+ folderurl_stripped.replace(TQString("file://"), TQString(""));
+ cfgfolderlist.append(folderurl);
+ cfgfolderlist.append(remoteurl);
+ cfgfolderlist.append(syncmethod);
+ cfgfolderlist.append(excludelist);
+ cfgfolderlist.append(sync_on_login);
+ cfgfolderlist.append(sync_on_logout);
+ cfgfolderlist.append(sync_timed_interval);
+ return 1;
+}
+
+KDE_EXPORT void KRsync::setCurrentDirectoryURL (KURL url)
+{
+ m_pURL = url;
+}
+
+KDE_EXPORT void KRsync::slotSetup()
+{
+ KURL url = m_pURL;
+
+ // Look up settings
+ TQString localfolder = url.directory(true, true) + TQString("/") + url.fileName(true);
+ TQString remotefolder = findLocalFolderByName(url.directory(true, true) + TQString("/") + url.fileName(true));
+ TQString syncmethod = findSyncMethodByName(url.directory(true, true) + TQString("/") + url.fileName(true));
+ int syncint = 1;
+ if (syncmethod == NULL) {
+ syncint = 1;
+ }
+ else if (syncmethod == "rsync_upload") {
+ syncint = 1;
+ }
+ else if (syncmethod == "rsync_download") {
+ syncint = 2;
+ }
+ else if (syncmethod == "rsync_bidirectional") {
+ syncint = 3;
+ }
+
+ m_configDialog = new RsyncConfigDialog(0, "rsyncConfig", i18n("Remote Folder Synchronization"), i18n("Configuring Remote Folder Synchronization"), localfolder, remotefolder, syncint, true);
+
+ // Handle autosync flags
+ if (localfolder != "") {
+ int flags = 0;
+ if (cfgautosync_onlogout_list.contains(localfolder))
+ flags = flags | 0x1;
+ m_configDialog->setAutoSyncFlags(flags);
+ }
+
+ m_configDialog->show();
+
+ connect (m_configDialog, TQT_SIGNAL(okClicked()), TQT_SLOT(slotSetupOK()));
+ connect (m_configDialog, TQT_SIGNAL(cancelClicked()), TQT_SLOT(slotSetupCancelled()));
+}
+
+KDE_EXPORT void KRsync::slotSetupOK()
+{
+ KURL url = m_pURL;
+
+ // Look up settings
+ TQString localfolder = url.directory(true, true) + TQString("/") + url.fileName(true);
+ TQString remotefolder = findLocalFolderByName(localfolder);
+ TQString remotefolder_new = m_configDialog->lineEdit()->text().ascii();
+ int syncmethod = m_configDialog->getSyncMode();
+ TQString syncmethod_new = "";
+ if (syncmethod == 1) {
+ syncmethod_new = "rsync_upload";
+ }
+ else if (syncmethod == 2) {
+ syncmethod_new = "rsync_download";
+ }
+ else if (syncmethod == 3) {
+ syncmethod_new = "rsync_bidirectional";
+ }
+
+ // Handle autosync settings
+ int autosyncflags = m_configDialog->getAutoSyncFlags();
+ cfgautosync_onlogout_list.remove(localfolder);
+ if (autosyncflags & 0x1)
+ cfgautosync_onlogout_list.append(localfolder);
+
+ // See if an old entry has to be deleted
+ if (remotefolder.isEmpty() == false) {
+ deleteLocalFolderByName(localfolder);
+ }
+ if (remotefolder_new.isEmpty() == false) {
+ addLocalFolderByName(localfolder, remotefolder_new, syncmethod_new, "", "0", "0", "-1");
+ }
+ saveSettings();
+
+ emit setupDone();
+}
+
+KDE_EXPORT void KRsync::slotSetupCancelled()
+{
+ emit setupDone();
+}
+
+KDE_EXPORT void KRsync::slotRsyncCancelled()
+{
+ shutdownConnection(true, true);
+ if (m_progressDialogExists == true) {
+ m_progressDialog->progressBar()->setValue(m_progressDialog->progressBar()->totalSteps());
+ }
+
+ emit transferDone();
+}
+
+KDE_EXPORT void KRsync::slotUnisonCancelled()
+{
+ shutdownConnection(true, true);
+ if (m_progressDialogExists == true) {
+ m_progressDialog->progressBar()->setFormat("%v / %m");
+ m_progressDialog->progressBar()->setTotalSteps(2);
+ m_progressDialog->progressBar()->setValue(m_progressDialog->progressBar()->totalSteps());
+ }
+
+ emit transferDone();
+}
+
+KDE_EXPORT void KRsync::slotSync()
+{
+ KURL url = m_pURL;
+
+ TQString syncmethod = findSyncMethodByName(url.directory(true, true) + TQString("/") + url.fileName(true));
+ if (syncmethod == NULL) {
+ // Do nothing
+ }
+ else if (syncmethod == "rsync_upload") {
+ // Initiate rsync
+ syncUnidirectional(TQString("rsync"), TQString(" -avtzAXE --delete --progress "), 0, url.directory(true, true) + TQString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + TQString("/") + url.fileName(true)));
+ }
+ else if (syncmethod == "rsync_download") {
+ syncUnidirectional(TQString("rsync"), TQString(" -avtzAXE --delete --progress "), 1, url.directory(true, true) + TQString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + TQString("/") + url.fileName(true)));
+ }
+ else if (syncmethod == "rsync_bidirectional") {
+ syncBidirectional(TQString("unison"), TQString(" -ui text -auto "), 1, url.directory(true, true) + TQString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + TQString("/") + url.fileName(true)));
+ }
+
+ m_progressDialogExists = false;
+
+ emit transferDone();
+}
+
+#include "tdersync.moc"
diff --git a/tdersync/tdersync.h b/tdersync/tdersync.h
new file mode 100644
index 000000000..c0af479f2
--- /dev/null
+++ b/tdersync/tdersync.h
@@ -0,0 +1,179 @@
+/*
+ Copyright (C) 2000, 2001, 2002 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _LIBKRSYNC_H
+#define _LIBKRSYNC_H
+
+#include <tqmap.h>
+#include <tqstringlist.h>
+
+#include <kurl.h>
+#include <kprocess.h>
+#include <kfileitem.h>
+#include <klibloader.h>
+#include <tdeparts/plugin.h>
+#include <kio/global.h>
+#include <kio/slavebase.h>
+
+#include <tqfile.h>
+#include <tqtimer.h>
+#include <tqapplication.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <tqwhatsthis.h>
+#include <tqiconview.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqstring.h>
+#include <tqregexp.h>
+#include <tqstyle.h>
+#include <tqtimer.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kinstance.h>
+
+#include <twin.h>
+#include <kurl.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kmessagebox.h>
+#include <kiconloader.h>
+#include <kprogressbox.h>
+#include <kpassdlg.h>
+#include <klistview.h>
+#include <kapplication.h>
+#include <kconfigdialog.h>
+
+#include <kdirlister.h>
+#include <kstandarddirs.h>
+#include <klistviewsearchline.h>
+#include <kiconviewsearchline.h>
+#include <kstaticdeleter.h>
+#include <kgenericfactory.h>
+#include <tdeparts/browserextension.h>
+
+class KActionMenu;
+class KonqDirPart;
+class KLineEdit;
+class RsyncConfigDialog;
+
+namespace KParts
+{
+ struct URLArgs;
+}
+
+class KRsync : public TQObject
+{
+ Q_OBJECT
+
+
+public:
+
+ KRsync (TQObject* parent, const char* name);
+ virtual ~KRsync();
+
+public:
+ void loadSettings();
+ void saveSettings();
+ TQString findLocalFolderByName(TQString folderurl);
+ TQString findLoginSyncEnabledByName(TQString folderurl);
+ TQString findLogoutSyncEnabledByName(TQString folderurl);
+ TQString findTimedSyncEnabledByName(TQString folderurl);
+ int deleteLocalFolderByName(TQString folderurl);
+ int addLocalFolderByName(TQString folderurl, TQString remoteurl, TQString syncmethod, TQString excludelist, TQString sync_on_login, TQString sync_on_logout, TQString sync_timed_interval);
+ TQString findSyncMethodByName(TQString folderurl);
+ /** manages initial communication setup including password queries */
+ int establishConnectionRsync(char *buffer, TDEIO::fileoffset_t len);
+ /** manages initial communication setup including password queries */
+ int establishConnectionUnison(char *buffer, TDEIO::fileoffset_t len, TQString localfolder, TQString remotepath);
+ /** creates the unidirectional sync subprocess */
+ bool syncUnidirectional(TQString synccommand, TQString syncflags, int parameter_order, TQString localfolder, TQString remotepath);
+ /** creates the bidirectional sync subprocess */
+ bool syncBidirectional(TQString synccommand, TQString syncflags, int parameter_order, TQString localfolder, TQString remotepath);
+ /** writes one chunk of data to stdin of child process */
+ void writeChild(const char *buf, TDEIO::fileoffset_t len);
+ /** AuthInfo object used for logging in */
+ TDEIO::AuthInfo connectionAuth;
+ /**
+ Clean up connection
+ */
+ void shutdownConnection(bool forced=false, bool wait=false);
+ /** Forced close of the connection */
+ void closeConnection();
+ /** Set current local directory URL */
+ void setCurrentDirectoryURL(KURL url);
+
+public slots:
+ void slotSync();
+ void slotSetup();
+ void slotSetupOK();
+ void slotSetupCancelled();
+ void slotRsyncCancelled();
+ void slotUnisonCancelled();
+ void executeLogoutAutoSync();
+
+signals:
+ void setupDone();
+ void transferDone();
+
+private:
+ KURL m_pURL;
+
+ KProgressBoxDialog* m_progressDialog;
+ RsyncConfigDialog* m_configDialog;
+
+ TQStringList cfgfolderlist;
+ TQStringList cfgautosync_onlogout_list;
+ bool m_progressDialogExists;
+
+ bool m_bSettingsLoaded;
+ bool m_bInSpecialSync;
+
+ /** true if connection is logged in successfully */
+ bool isLoggedIn;
+ /** the rsync process used to communicate with the remote end */
+ pid_t childPid;
+ /** fd for reading and writing to the process */
+ int childFd;
+ /** buffer for data to be written */
+ const char *outBuf;
+ /** current write position in buffer */
+ TDEIO::fileoffset_t outBufPos;
+ /** length of buffer */
+ TDEIO::fileoffset_t outBufLen;
+ /** use su if true else use ssh */
+ //bool local;
+ /** // FIXME: just a workaround for konq deficiencies */
+ bool isStat;
+ /** // FIXME: just a workaround for konq deficiencies */
+ TQString redirectUser, redirectPass;
+ /** user name of current connection */
+ TQString connectionUser;
+ /** password of current connection */
+ TQString connectionPassword;
+ /** true if this is the first login attempt (== use cached password) */
+ bool firstLogin;
+
+ TQString thisFn;
+};
+#endif