diff options
-rw-r--r-- | konq-plugins/rsync/rsyncconfigdialog.cpp | 6 | ||||
-rw-r--r-- | konq-plugins/rsync/rsyncplugin.cpp | 173 | ||||
-rw-r--r-- | konq-plugins/rsync/rsyncplugin.h | 7 |
3 files changed, 171 insertions, 15 deletions
diff --git a/konq-plugins/rsync/rsyncconfigdialog.cpp b/konq-plugins/rsync/rsyncconfigdialog.cpp index b28a02c..0549356 100644 --- a/konq-plugins/rsync/rsyncconfigdialog.cpp +++ b/konq-plugins/rsync/rsyncconfigdialog.cpp @@ -134,14 +134,14 @@ RsyncConfigDialog::RsyncConfigDialog(QWidget* parent, const char* name, // Insert radiobuttons 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); + rsync_rb3 = new QRadioButton(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 ); + else if (syncmode == 3) + rsync_rb3->setChecked( TRUE ); //(void)new QRadioButton( "R&adiobutton 2", layoutg ); //(void)new QRadioButton( "Ra&diobutton 3", layoutg ); diff --git a/konq-plugins/rsync/rsyncplugin.cpp b/konq-plugins/rsync/rsyncplugin.cpp index ebf7dd7..bc16a5a 100644 --- a/konq-plugins/rsync/rsyncplugin.cpp +++ b/konq-plugins/rsync/rsyncplugin.cpp @@ -292,7 +292,7 @@ bool RsyncPlugin::syncUnidirectional(QString synccommand, QString syncflags, int if (FD_ISSET(childFd,&rfds)) { rc = read(childFd,buf+offset,32768-offset); if (rc > 0) { - int noff = establishConnection(buf,rc+offset); + int noff = establishConnectionRsync(buf,rc+offset); if (noff < 0) return false; if (noff > 0) memmove(buf,buf+offset+rc-noff,noff); offset = noff; @@ -312,11 +312,16 @@ bool RsyncPlugin::syncUnidirectional(QString synccommand, QString syncflags, int /** creates the bidirectional sync subprocess */ -bool RsyncPlugin::syncBidirectional(QString localfolder, QString remotepath) { +bool RsyncPlugin::syncBidirectional(QString synccommand, QString syncflags, int parameter_order, QString localfolder, QString remotepath) { int fd[2]; int rc, flags; thisFn = QString::null; + // 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); @@ -335,8 +340,8 @@ bool RsyncPlugin::syncBidirectional(QString localfolder, QString remotepath) { // Create the rsync command to run QString execstring; // FIXME - //execstring = synccommand + syncflags + localfolder + QString("/ ") + remotepath; - exit -1; + execstring = synccommand + syncflags + localfolder + QString(" ") + remotepath; + printf("Will execute %s\n\r", execstring.ascii()); // taken from konsole, see TEPty.C for details // note: if we're running on socket pairs, @@ -426,7 +431,7 @@ bool RsyncPlugin::syncBidirectional(QString localfolder, QString remotepath) { if (FD_ISSET(childFd,&rfds)) { rc = read(childFd,buf+offset,32768-offset); if (rc > 0) { - int noff = establishConnection(buf,rc+offset); + 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; @@ -463,7 +468,7 @@ void RsyncPlugin::writeChild(const char *buf, KIO::fileoffset_t len) { /** manages initial communication setup including password queries */ -int RsyncPlugin::establishConnection(char *buffer, KIO::fileoffset_t len) { +int RsyncPlugin::establishConnectionRsync(char *buffer, KIO::fileoffset_t len) { QString buf; buf.setLatin1(buffer,len); int pos; @@ -569,6 +574,143 @@ int RsyncPlugin::establishConnection(char *buffer, KIO::fileoffset_t len) { } /** +manages initial communication setup including password queries +*/ +int RsyncPlugin::establishConnectionUnison(char *buffer, KIO::fileoffset_t len, QString localfolder, QString remotepath) { + QString 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) { + qApp->processEvents(); + } + pos++; + QString 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); + } + 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, SIGNAL(cancelClicked()), SLOT(slotUnisonCancelled())); + 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 = QString::null; + writeChild(connectionAuth.password.latin1(),connectionAuth.password.length()); + } else { + myDebug( << "sending mpass" << endl); + connectionAuth.prompt = thisFn+buf; + connectionAuth.password = QString::null; // don't prefill + QCString thispass; + if (KPasswordDialog::getPassword (thispass, i18n("Remote authorization required") + QString("\n") + i18n("Please input") + QString(" ") + QString(buf), NULL) != 1) { + slotUnisonCancelled(); + return -1; + } + else { + connectionAuth.password = QString(thispass); + } + connectionAuth.password += "\n"; + myDebug( << "sending pass" << endl); + writeChild(connectionAuth.password.latin1(),connectionAuth.password.length()); + } + thisFn = QString::null; + return 0; + } + else if (buf.endsWith("?") || buf.endsWith("? []")) { + buf.replace("[]", ""); + if (buf.endsWith("? []")) { + int rc = KMessageBox::questionYesNo(NULL, buf); + if (rc == KMessageBox::Yes) { + writeChild("y\n",3); + } else { + writeChild("n\n",3); + } + } + else { + int rc = KMessageBox::questionYesNo(NULL, buf); + if (rc == KMessageBox::Yes) { + writeChild("yes\n",4); + } else { + writeChild("no\n",3); + } + } + thisFn = QString::null; + 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); + } + QString file_name; + file_name = buf; + file_name.replace("[]", ""); + file_name.replace(QString("changed "), ""); + //file_name = file_name.simplifyWhiteSpace(); + 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")); + int rc = KMessageBox::createKMessageBox(dialog, QMessageBox::Warning, QString("<b>") + i18n("WARNING: Both the local and remote file have been modified") + QString("</b><p>") + i18n("Local") + QString(": ") + localfolder + QString("/") + file_name + QString("<br>") + i18n("Remote") + QString(": ") + remotepath + QString("/") + file_name + QString("<p>") + i18n("Please select the file to duplicate (the other will be overwritten)") + QString("<br>") + i18n("Or, select Ignore to skip synchronization of this file for now"), QStringList(), QString::null, 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")) { + if (m_progressDialogExists == true) { + m_progressDialog->progressBar()->setFormat("%v / %m"); + m_progressDialog->progressBar()->setTotalSteps(2); + m_progressDialog->progressBar()->setValue(m_progressDialog->progressBar()->totalSteps()); + } + } + else { + 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, @@ -879,6 +1021,17 @@ void RsyncPlugin::slotRsyncCancelled() m_pSyncNow->setEnabled (true); } +void RsyncPlugin::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()); + } + m_pSyncNow->setEnabled (true); +} + void RsyncPlugin::slotSync() { if (!m_part) @@ -899,10 +1052,10 @@ void RsyncPlugin::slotSync() 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; -// } - + else if (syncmethod == "rsync_bidirectional") { + syncBidirectional(QString("unison"), QString(" -ui text -auto "), 1, url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true))); + } + m_progressDialogExists = false; m_pSyncNow->setEnabled (true); } diff --git a/konq-plugins/rsync/rsyncplugin.h b/konq-plugins/rsync/rsyncplugin.h index 4deb2b3..86aa17f 100644 --- a/konq-plugins/rsync/rsyncplugin.h +++ b/konq-plugins/rsync/rsyncplugin.h @@ -65,11 +65,13 @@ protected: 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); + int establishConnectionRsync(char *buffer, KIO::fileoffset_t len); + /** manages initial communication setup including password queries */ + int establishConnectionUnison(char *buffer, KIO::fileoffset_t len, 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); + bool syncBidirectional(QString synccommand, QString syncflags, int parameter_order, 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 */ @@ -89,6 +91,7 @@ private slots: void slotSetupOK(); void slotSetupCancelled(); void slotRsyncCancelled(); + void slotUnisonCancelled(); private: KURL m_pURL; |