From 3768653a2aed91290e05dd3fd42d5af2006c7ed4 Mon Sep 17 00:00:00 2001 From: tpearson 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/rsync/rsyncconfigdialog.cpp | 31 +++- konq-plugins/rsync/rsyncconfigdialog.h | 14 +- konq-plugins/rsync/rsyncplugin.cpp | 238 ++++++++++++++++++++++++++++--- konq-plugins/rsync/rsyncplugin.h | 9 +- 4 files changed, 259 insertions(+), 33 deletions(-) (limited to 'konq-plugins/rsync') 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("") + text + QString("
Setting up synchronization for local folder
") + localfolder, mainWidget); + mLabel = new QLabel(QString("") + text + QString("
")+i18n("Setting up synchronization for local folder")+QString("
") + 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 #include #include +#include #include #include @@ -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 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.1