From 3768653a2aed91290e05dd3fd42d5af2006c7ed4 Mon Sep 17 00:00:00 2001
From: tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>
Date: Fri, 26 Mar 2010 07:19:43 +0000
Subject: Fixed up rsync and dirfilter plugins

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaddons@1107600 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
---
 konq-plugins/dirfilter/dirfilterplugin.cpp |   9 ++
 konq-plugins/rsync/rsyncconfigdialog.cpp   |  31 +++-
 konq-plugins/rsync/rsyncconfigdialog.h     |  14 +-
 konq-plugins/rsync/rsyncplugin.cpp         | 238 ++++++++++++++++++++++++++---
 konq-plugins/rsync/rsyncplugin.h           |   9 +-
 5 files changed, 268 insertions(+), 33 deletions(-)

diff --git a/konq-plugins/dirfilter/dirfilterplugin.cpp b/konq-plugins/dirfilter/dirfilterplugin.cpp
index 0966f19..eee1284 100644
--- a/konq-plugins/dirfilter/dirfilterplugin.cpp
+++ b/konq-plugins/dirfilter/dirfilterplugin.cpp
@@ -388,6 +388,15 @@ void DirFilterPlugin::slotItemsAdded (const KFileItemList& list)
     m_pFilterMenu->setEnabled (m_part->nameFilter().isEmpty());
     return;
   }
+  if ( ::qt_cast<KListView*>(m_part->scrollWidget()) )
+  {
+    static_cast<KListViewSearchLine*>(m_searchWidget)->updateSearch();
+  }
+  else if ( ::qt_cast<QIconView*>(m_part->scrollWidget()) )
+  {
+    static_cast<KIconViewSearchLine*>(m_searchWidget)->updateSearch();
+  }
+  //m_searchWidget->updateSearch();
 
   // Make sure the filter menu is enabled once a named
   // filter is removed.
diff --git a/konq-plugins/rsync/rsyncconfigdialog.cpp b/konq-plugins/rsync/rsyncconfigdialog.cpp
index f990fc8..b28a02c 100644
--- a/konq-plugins/rsync/rsyncconfigdialog.cpp
+++ b/konq-plugins/rsync/rsyncconfigdialog.cpp
@@ -103,7 +103,7 @@
 RsyncConfigDialog::RsyncConfigDialog(QWidget* parent, const char* name,
                                  const QString& caption, const QString& text,
                                  const QString& localfolder, const QString& remotefolder,
-                                 bool modal)
+                                 int syncmode, bool modal)
     : KDialogBase(KDialogBase::Plain, caption, KDialogBase::Cancel | KDialogBase::Ok,
                   KDialogBase::Ok, parent, name, modal),
       mAutoClose(true),
@@ -123,22 +123,31 @@ RsyncConfigDialog::RsyncConfigDialog(QWidget* parent, const char* name,
 
     QFrame* mainWidget = plainPage();
     QVBoxLayout* layout = new QVBoxLayout(mainWidget, 10);
-    mLabel = new QLabel(QString("<b>") + text + QString("</b><br>Setting up synchronization for local folder<br><i>") + localfolder, mainWidget);
+    mLabel = new QLabel(QString("<b>") + text + QString("</b><br>")+i18n("Setting up synchronization for local folder")+QString("<br><i>") + localfolder, mainWidget);
     layout->addWidget(mLabel);
 
     // Create an exclusive button group
-    QButtonGroup *layoutg = new QButtonGroup( 1, QGroupBox::Horizontal, "Synchronization Method:", mainWidget);
+    QButtonGroup *layoutg = new QButtonGroup( 1, QGroupBox::Horizontal, i18n("Synchronization Method")+QString(":"), mainWidget);
     layout->addWidget( layoutg );
     layoutg->setExclusive( TRUE );
 
     // Insert radiobuttons
-    QRadioButton *rsync_rb = new QRadioButton("&Utilize rsync + ssh\nExample: servername:/path/to/remote/folder", layoutg);
-    rsync_rb->setChecked( TRUE );
+    rsync_rb1 = new QRadioButton(i18n("&Utilize rsync + ssh for upload to remote server\nExample: servername:/path/to/remote/folder"), layoutg);
+    rsync_rb2 = new QRadioButton(i18n("&Utilize rsync + ssh for download from remote server\nExample: servername:/path/to/remote/folder"), layoutg);
+    //rsync_rb3 = new QRadioButton(i18n("&Utilize rsync + ssh for synchronization with remote server\nExample: 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 QRadioButton( "R&adiobutton 2", layoutg );
     //(void)new QRadioButton( "Ra&diobutton 3", layoutg );
 
     // Create an exclusive button group
-    QButtonGroup *layoutm = new QButtonGroup( 1, QGroupBox::Horizontal, "Remote Folder:", mainWidget);
+    QButtonGroup *layoutm = new QButtonGroup( 1, QGroupBox::Horizontal, i18n("Remote Folder")+QString(":"), mainWidget);
     layout->addWidget( layoutm );
     layoutg->setExclusive( TRUE );
 
@@ -149,6 +158,16 @@ RsyncConfigDialog::RsyncConfigDialog(QWidget* parent, const char* name,
     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;
+}
+
 QLineEdit* RsyncConfigDialog::lineEdit()
 {
     return m_rsync_txt;
diff --git a/konq-plugins/rsync/rsyncconfigdialog.h b/konq-plugins/rsync/rsyncconfigdialog.h
index 83314e8..9099ad3 100644
--- a/konq-plugins/rsync/rsyncconfigdialog.h
+++ b/konq-plugins/rsync/rsyncconfigdialog.h
@@ -22,6 +22,7 @@
 #include <qmap.h>
 #include <qstringlist.h>
 #include <qlineedit.h>
+#include <qradiobutton.h>
 
 #include <kurl.h>
 #include <kprocess.h>
@@ -39,7 +40,7 @@ class RsyncConfigDialog : public KDialogBase
                         const QString& text = QString::null,
                         const QString& localfolder = QString::null,
                         const QString& remotefolder = QString::null,
-                        bool modal = false);
+                        int syncmode = 1, bool modal = false);
 
         ~RsyncConfigDialog() {}
 //
@@ -182,6 +183,14 @@ class RsyncConfigDialog : public KDialogBase
          */
         bool wasCancelled() const;
 
+        /**
+         * Returns index of selected synchronization mode
+         * 1: Upload
+         * 2: Download
+         * 3: Bidirectional
+         */
+        int getSyncMode();
+
         /**
          * Ignores the last cancel action if the cancel button was
          * pressed. Useful for kdialog when combined with a KMessageBox
@@ -249,6 +258,9 @@ class RsyncConfigDialog : public KDialogBase
         KTextEdit* mTextBox;
         QTimer*    mShowTimer;
         QLineEdit* m_rsync_txt;
+        QRadioButton *rsync_rb1;
+        QRadioButton *rsync_rb2;
+        QRadioButton *rsync_rb3;
 //     protected:
 // 	virtual void virtual_hook( int id, void* data );
 };
diff --git a/konq-plugins/rsync/rsyncplugin.cpp b/konq-plugins/rsync/rsyncplugin.cpp
index 11785ac..ebf7dd7 100644
--- a/konq-plugins/rsync/rsyncplugin.cpp
+++ b/konq-plugins/rsync/rsyncplugin.cpp
@@ -173,9 +173,9 @@ close_master:
 #endif
 }
 /**
-creates the subprocess
+creates the unidirectional sync subprocess
 */
-bool RsyncPlugin::connectionStart(QString localfolder, QString remotepath) {
+bool RsyncPlugin::syncUnidirectional(QString synccommand, QString syncflags, int parameter_order, QString localfolder, QString remotepath) {
     int fd[2];
     int rc, flags;
     thisFn = QString::null;
@@ -186,8 +186,6 @@ bool RsyncPlugin::connectionStart(QString localfolder, QString remotepath) {
         return true;
     }
 
-    //myDebug( << "Exec: " << (local ? suPath : rsyncPath) << " Port: " << connectionPort << " User: " << connectionUser << endl);
-    //infoMessage(rsyncPath);
     childPid = fork();
     if (childPid == -1) {
         myDebug( << "fork failed, error: " << strerror(errno) << endl);
@@ -199,7 +197,146 @@ bool RsyncPlugin::connectionStart(QString localfolder, QString remotepath) {
     if (childPid == 0) {
         // Create the rsync command to run
         QString execstring;
-        execstring = QString(rsyncPath) + QString(" -avtzAXE --delete --progress ") + localfolder + QString("/ ") + remotepath;
+        if (parameter_order == 0) {
+            execstring = synccommand + syncflags + localfolder + QString("/ ") + remotepath;
+        }
+        else {
+            execstring = synccommand + syncflags + remotepath + QString("/ ") + 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);
+
+        system(execstring.ascii());
+        #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 = establishConnection(buf,rc+offset);
+                if (noff < 0) return false;
+                if (noff > 0) memmove(buf,buf+offset+rc-noff,noff);
+                offset = noff;
+            } else {
+                if (errno == EINTR)
+                    continue;
+                //if (errno == EAGAIN)
+                //    continue;
+                myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+/**
+creates the bidirectional sync subprocess
+*/
+bool RsyncPlugin::syncBidirectional(QString localfolder, QString remotepath) {
+    int fd[2];
+    int rc, flags;
+    thisFn = QString::null;
+
+    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
+        QString execstring;
+        // FIXME
+        //execstring = synccommand + syncflags + localfolder + QString("/ ") + remotepath;
+        exit -1;
 
         // taken from konsole, see TEPty.C for details
         // note: if we're running on socket pairs,
@@ -471,15 +608,11 @@ void RsyncPlugin::saveSettings()
   KConfig cfg ("rsyncrc", false, false);
   cfg.setGroup ("General");
 
-  bool min_entry = false;
   QString longstring = QString("");
-  for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
-	if (min_entry)
-		longstring = longstring + QString(";");
+  for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end();) {
 	longstring = longstring + (*i);
 	i++;
-	longstring = longstring + QString(";") + (*i);
-	min_entry = true;
+	longstring = longstring + QString(";");
   }
 
   cfg.writeEntry("LocalFolders", longstring);
@@ -508,6 +641,24 @@ QString RsyncPlugin::findLocalFolderByName(QString folderurl)
 	if (QString::compare((*i), folderurl_stripped) == 0) {
 		i++;
 		return (*i);
+		i++;
+		i++;
+	}
+  }
+  return NULL;
+}
+
+QString RsyncPlugin::findSyncMethodByName(QString folderurl)
+{
+  QString folderurl_stripped;
+  folderurl_stripped = folderurl;
+  folderurl_stripped.replace(QString("file://"), QString(""));
+  for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
+	if (QString::compare((*i), folderurl_stripped) == 0) {
+		i++;
+		i++;
+		return (*i);
+		i++;
 	}
   }
   return NULL;
@@ -520,6 +671,8 @@ int RsyncPlugin::deleteLocalFolderByName(QString folderurl)
   folderurl_stripped.replace(QString("file://"), QString(""));
   for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) {
 	if (QString::compare((*i), folderurl_stripped) == 0) {
+		i=cfgfolderlist.remove(i);
+		i=cfgfolderlist.remove(i);
 		i=cfgfolderlist.remove(i);
 		cfgfolderlist.remove(i);
 		return 0;
@@ -528,13 +681,15 @@ int RsyncPlugin::deleteLocalFolderByName(QString folderurl)
   return 1;
 }
 
-int RsyncPlugin::addLocalFolderByName(QString folderurl, QString remoteurl)
+int RsyncPlugin::addLocalFolderByName(QString folderurl, QString remoteurl, QString syncmethod, QString excludelist)
 {
   QString folderurl_stripped;
   folderurl_stripped = folderurl;
   folderurl_stripped.replace(QString("file://"), QString(""));
   cfgfolderlist.append(folderurl);
   cfgfolderlist.append(remoteurl);
+  cfgfolderlist.append(syncmethod);
+  cfgfolderlist.append(excludelist);
   return 1;
 }
 
@@ -647,8 +802,22 @@ void RsyncPlugin::slotSetup()
 	// Look up settings
 	QString localfolder = url.directory(true, true) + QString("/") + url.fileName(true);
 	QString remotefolder = findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true));
+	QString syncmethod = findSyncMethodByName(url.directory(true, true) + QString("/") + url.fileName(true));
+	int syncint;
+	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, true);
+	m_configDialog = new RsyncConfigDialog(0, "rsyncConfig", i18n("Remote Folder Synchronization"), i18n("Configuring Remote Folder Synchronization"), localfolder, remotefolder, syncint, true);
 	m_configDialog->show();
 
 	connect (m_configDialog, SIGNAL(okClicked()), SLOT(slotSetupOK()));
@@ -666,13 +835,24 @@ void RsyncPlugin::slotSetupOK()
 	QString localfolder = url.directory(true, true) + QString("/") + url.fileName(true);
 	QString remotefolder = findLocalFolderByName(localfolder);
 	QString remotefolder_new = m_configDialog->lineEdit()->text().ascii();
+	int syncmethod = m_configDialog->getSyncMode();
+	QString 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";
+	}
 
 	// See if an old entry has to be deleted
 	if (remotefolder.isEmpty() == false) {
 		deleteLocalFolderByName(localfolder);
 	}
 	if (remotefolder_new.isEmpty() == false) {
-		addLocalFolderByName(localfolder, remotefolder_new);
+		addLocalFolderByName(localfolder, remotefolder_new, syncmethod_new, "");
 	}
 	saveSettings();
 
@@ -701,18 +881,30 @@ void RsyncPlugin::slotRsyncCancelled()
 
 void RsyncPlugin::slotSync()
 {
-  if (!m_part)
-    return;
-
-  KURL url = m_part->url();
+	if (!m_part)
+		return;
 
-  m_pSyncNow->setEnabled (false);
+	KURL url = m_part->url();
 
-  // Initiate rsync
-  connectionStart(url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true)));
+	m_pSyncNow->setEnabled (false);
 
-  m_progressDialogExists = false;
-  m_pSyncNow->setEnabled (true);
+	QString syncmethod = findSyncMethodByName(url.directory(true, true) + QString("/") + url.fileName(true));
+	if (syncmethod == NULL) {
+		// Do nothing
+	}
+	else if (syncmethod == "rsync_upload") {
+		// Initiate rsync
+		syncUnidirectional(QString("rsync"), QString(" -avtzAXE --delete --progress "), 0, url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true)));
+	}
+ 	else if (syncmethod == "rsync_download") {
+ 		syncUnidirectional(QString("rsync"), QString(" -avtzAXE --delete --progress "), 1, url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true)));
+ 	}
+// 	else if (syncmethod == "rsync_bidirectional") {
+// 		syncint = 3;
+// 	}
+	
+	m_progressDialogExists = false;
+	m_pSyncNow->setEnabled (true);
 }
 
 typedef KGenericFactory<RsyncPlugin> RsyncFactory;
diff --git a/konq-plugins/rsync/rsyncplugin.h b/konq-plugins/rsync/rsyncplugin.h
index 0e8c22d..4deb2b3 100644
--- a/konq-plugins/rsync/rsyncplugin.h
+++ b/konq-plugins/rsync/rsyncplugin.h
@@ -62,11 +62,14 @@ protected:
   void saveSettings();
   QString findLocalFolderByName(QString folderurl);
   int deleteLocalFolderByName(QString folderurl);
-  int addLocalFolderByName(QString folderurl, QString remoteurl);
+  int addLocalFolderByName(QString folderurl, QString remoteurl, QString syncmethod, QString excludelist);
+  QString findSyncMethodByName(QString folderurl);
   /** manages initial communication setup including password queries */
   int establishConnection(char *buffer, KIO::fileoffset_t len);
-  /** creates the subprocess */
-  bool connectionStart(QString localfolder, QString remotepath);
+  /** creates the unidirectional sync subprocess */
+  bool syncUnidirectional(QString synccommand, QString syncflags, int parameter_order, QString localfolder, QString remotepath);
+  /** creates the bidirectional sync subprocess */
+  bool syncBidirectional(QString localfolder, QString remotepath);
   /** writes one chunk of data to stdin of child process */
   void writeChild(const char *buf, KIO::fileoffset_t len);
   /** AuthInfo object used for logging in */
-- 
cgit v1.2.3

