/* Copyright (C) 2000, 2001, 2002 Dawit Alemayehu 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 #include #include #include #include #include #include #include #include #include #include #define HAVE_TERMIOS_H 1 #define HAVE_GRANTPT 1 #include #ifdef HAVE_PTY_H #include #endif #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_STROPTS #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_LIBUTIL_H #include #endif #ifdef HAVE_UTIL_H #include #endif #include #include #include "krsync.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(0), 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(); #elif defined(HAVE_POSIX_OPENTPT) master = posix_openpt(O_RDWR); #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, KIO::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, KIO::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, KIO::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("").append(i18n("An error ocurred on the remote system")).append(":
")); fullError.replace("\n", ""); fullError.replace(": unable", ":
Unable"); fullError.replace(")", ")
"); fullError.replace("(", "
("); 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("") + i18n("WARNING: Both the local and remote file have been modified") + TQString("

") + i18n("Local") + TQString(": ") + prettylocalfolder + file_name + TQString("
") + i18n("Remote") + TQString(": ") + prettyremotepath + file_name + TQString("

") + i18n("Please select the file to duplicate (the other will be overwritten)") + TQString("
") + 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() { KConfig 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; KConfig 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 "krsync.moc"