summaryrefslogtreecommitdiffstats
path: root/kio
diff options
context:
space:
mode:
Diffstat (limited to 'kio')
-rw-r--r--kio/Makefile.am5
-rw-r--r--kio/kfile/kfilespeedbar.cpp50
-rw-r--r--kio/kfile/kpropertiesdialog.cpp9
-rw-r--r--kio/kio/kdirwatch.cpp28
-rw-r--r--kio/kio/kdirwatch.cpp.orig1770
-rw-r--r--kio/kio/krun.cpp102
-rw-r--r--kio/kio/krun.h11
-rw-r--r--kio/kio/kservice.cpp33
-rw-r--r--kio/kio/kurlcompletion.cpp3
-rw-r--r--kio/kpasswdserver/Makefile.am2
-rw-r--r--kio/misc/Makefile.am2
-rwxr-xr-xkio/misc/fileshareset7
-rw-r--r--kio/misc/kdesasl/Makefile.am2
-rw-r--r--kio/misc/kntlm/Makefile.am2
-rw-r--r--kio/misc/kpac/Makefile.am4
-rw-r--r--kio/misc/kssld/Makefile.am2
-rw-r--r--kio/misc/kwalletd/Makefile.am2
-rw-r--r--kio/misc/kwalletd/kwalletd.cpp48
18 files changed, 2019 insertions, 63 deletions
diff --git a/kio/Makefile.am b/kio/Makefile.am
index cfe25006e..d1fe7c6b2 100644
--- a/kio/Makefile.am
+++ b/kio/Makefile.am
@@ -20,7 +20,8 @@ AM_CPPFLAGS = -D_LARGEFILE64_SOURCE
INCLUDES= -I$(srcdir)/.. $(all_includes) $(SSL_INCLUDES)
-SUBDIRS = kssl kio bookmarks kfile . kpasswdserver misc pics tests kioexec httpfilter
+SUBDIRS = kssl kio bookmarks kfile . pics tests kioexec httpfilter
+DIST_SUBDIRS = kpasswdserver misc
lib_LTLIBRARIES = libkio.la
@@ -32,7 +33,7 @@ libkio_la_LIBADD = kssl/libkssl.la kio/libkiocore.la \
kio/libksycoca.la bookmarks/libkbookmarks.la kfile/libkfile.la \
../kdeui/libkdeui.la ../kdesu/libkdesu.la \
../kwallet/client/libkwalletclient.la \
- $(LIBZ) $(LIBFAM) $(LIBVOLMGT) $(ACL_LIBS)
+ $(LIBZ) $(LIBFAM) $(LIBVOLMGT) $(ACL_LIBS) $(LIB_QT) $(LIB_KDECORE) $(top_builddir)/dcop/libDCOP.la $(LIB_X11)
kde_mime_DATA = magic
kde_servicetypes_DATA = application.desktop kurifilterplugin.desktop \
diff --git a/kio/kfile/kfilespeedbar.cpp b/kio/kfile/kfilespeedbar.cpp
index 86ee85f52..350423d35 100644
--- a/kio/kfile/kfilespeedbar.cpp
+++ b/kio/kfile/kfilespeedbar.cpp
@@ -20,6 +20,9 @@
#include "config-kfile.h"
#include <qdir.h>
+#include <qfile.h>
+#include <qtextcodec.h>
+#include <qtextstream.h>
#include <kconfig.h>
#include <kglobal.h>
@@ -50,7 +53,7 @@ KFileSpeedBar::KFileSpeedBar( QWidget *parent, const char *name )
QDir(KGlobalSettings::documentPath()).exists())
{
u.setPath( KGlobalSettings::documentPath() );
- insertItem( u, i18n("Documents"), false, "document" );
+ insertItem( u, i18n("Documents"), false, "folder_txt" );
}
u.setPath( QDir::homeDirPath() );
@@ -62,6 +65,51 @@ KFileSpeedBar::KFileSpeedBar( QWidget *parent, const char *name )
insertItem( u, i18n("Storage Media"), false,
KProtocolInfo::icon( "media" ) );
+ if ( QFile::exists( QDir::homeDirPath()+"/.config/user-dirs.dirs" ) )
+ {
+ QString download, music, pictures, videos, templates, publicShares;
+
+ QFile f( QDir::homeDirPath()+"/.config/user-dirs.dirs" );
+ if (!f.open(IO_ReadOnly))
+ return;
+
+ QTextStream s( &f );
+ s.setCodec( QTextCodec::codecForLocale() );
+
+ // read the xdg user dirs
+ QString line = s.readLine();
+ while (!line.isNull())
+ {
+ if (line.startsWith("XDG_DOWNLOAD_DIR="))
+ download = line.remove("XDG_DOWNLOAD_DIR=").remove("\"").replace("$HOME", QDir::homeDirPath());
+ else if (line.startsWith("XDG_MUSIC_DIR="))
+ music = line.remove("XDG_MUSIC_DIR=").remove("\"").replace("$HOME", QDir::homeDirPath());
+ else if (line.startsWith("XDG_PICTURES_DIR="))
+ pictures = line.remove("XDG_PICTURES_DIR=").remove("\"").replace("$HOME", QDir::homeDirPath());
+ else if (line.startsWith("XDG_VIDEOS_DIR="))
+ videos = line.remove("XDG_VIDEOS_DIR=").remove("\"").replace("$HOME", QDir::homeDirPath());
+ else if (line.startsWith("XDG_TEMPLATES_DIR="))
+ templates = line.remove("XDG_TEMPLATES_DIR=").remove("\"").replace("$HOME", QDir::homeDirPath());
+ else if (line.startsWith("XDG_PUBLICSHARES_DIR="))
+ publicShares = line.remove("XDG_PUBLICSHARES_DIR=").remove("\"").replace("$HOME", QDir::homeDirPath());
+
+ line = s.readLine();
+ }
+ // now add in the speedbar
+ if (!download.isEmpty())
+ insertItem( download, i18n( "Download" ), false, "folder_html" );
+ if (!music.isEmpty())
+ insertItem( music, i18n( "Music" ), false, "folder_sound" );
+ if (!pictures.isEmpty())
+ insertItem( pictures, i18n( "Pictures" ), false, "folder_image" );
+ if (!videos.isEmpty())
+ insertItem( videos, i18n( "Videos" ), false, "folder_video" );
+ if (!templates.isEmpty())
+ insertItem( templates, i18n( "Templates" ), false, "folder_video" );
+ if (!publicShares.isEmpty())
+ insertItem( publicShares, i18n( "Public" ), false, "folder_video" );
+ }
+
u = "remote:/";
if ( KProtocolInfo::isKnownProtocol( u ) )
insertItem( u, i18n("Network Folders"), false,
diff --git a/kio/kfile/kpropertiesdialog.cpp b/kio/kfile/kpropertiesdialog.cpp
index fd08d906d..f02e80eaf 100644
--- a/kio/kfile/kpropertiesdialog.cpp
+++ b/kio/kfile/kpropertiesdialog.cpp
@@ -1881,7 +1881,14 @@ static bool fileSystemSupportsACL( const QCString& pathCString )
fileSystemSupportsACLs = ( statfs( pathCString.data(), &buf ) == 0 ) && ( buf.f_flags & MNT_ACLS );
#else
fileSystemSupportsACLs =
- getxattr( pathCString.data(), "system.posix_acl_access", NULL, 0 ) >= 0 || errno == ENODATA;
+ getxattr( pathCString.data(), "system.posix_acl_access", NULL, 0 ) >= 0
+#ifdef ENODATA
+ || (errno == ENODATA)
+#endif
+#ifdef ENOATTR
+ || (errno == ENOATTR)
+#endif
+ ;
#endif
return fileSystemSupportsACLs;
}
diff --git a/kio/kio/kdirwatch.cpp b/kio/kio/kdirwatch.cpp
index b80a23473..aaa807ed6 100644
--- a/kio/kio/kdirwatch.cpp
+++ b/kio/kio/kdirwatch.cpp
@@ -64,36 +64,17 @@
// debug
#include <sys/ioctl.h>
-#ifdef HAVE_SYS_INOTIFY
-#include <sys/inotify.h>
-#include <fcntl.h>
-#elif HAVE_INOTIFY
+#ifdef HAVE_INOTIFY
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>
+#include <linux/types.h>
// Linux kernel headers are documented to not compile
#define _S390_BITOPS_H
-#include <linux/inotify.h>
-
-static inline int inotify_init (void)
-{
- return syscall (__NR_inotify_init);
-}
-
-static inline int inotify_add_watch (int fd, const char *name, __u32 mask)
-{
- return syscall (__NR_inotify_add_watch, fd, name, mask);
-}
-
-static inline int inotify_rm_watch (int fd, __u32 wd)
-{
- return syscall (__NR_inotify_rm_watch, fd, wd);
-}
-#endif
+#include <sys/inotify.h>
-#ifdef HAVE_INOTIFY
#ifndef IN_ONLYDIR
-#define IN_ONLYDIR 0x01000000
+#define IN_ONLYDIR 0x01000000
#endif
#ifndef IN_DONT_FOLLOW
@@ -103,6 +84,7 @@ static inline int inotify_rm_watch (int fd, __u32 wd)
#ifndef IN_MOVE_SELF
#define IN_MOVE_SELF 0x00000800
#endif
+
#endif
#include <sys/utsname.h>
diff --git a/kio/kio/kdirwatch.cpp.orig b/kio/kio/kdirwatch.cpp.orig
new file mode 100644
index 000000000..b80a23473
--- /dev/null
+++ b/kio/kio/kdirwatch.cpp.orig
@@ -0,0 +1,1770 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at>
+
+ 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.
+*/
+
+
+// CHANGES:
+// Oct 4, 2005 - Inotify support (Dirk Mueller)
+// Februar 2002 - Add file watching and remote mount check for STAT
+// Mar 30, 2001 - Native support for Linux dir change notification.
+// Jan 28, 2000 - Usage of FAM service on IRIX (Josef.Weidendorfer@in.tum.de)
+// May 24. 1998 - List of times introduced, and some bugs are fixed. (sven)
+// May 23. 1998 - Removed static pointer - you can have more instances.
+// It was Needed for KRegistry. KDirWatch now emits signals and doesn't
+// call (or need) KFM. No more URL's - just plain paths. (sven)
+// Mar 29. 1998 - added docs, stop/restart for particular Dirs and
+// deep copies for list of dirs. (sven)
+// Mar 28. 1998 - Created. (sven)
+
+
+#include <config.h>
+#include <errno.h>
+
+#ifdef HAVE_DNOTIFY
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#endif
+
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qintdict.h>
+#include <qptrlist.h>
+#include <qsocketnotifier.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kstaticdeleter.h>
+#include <kde_file.h>
+
+// debug
+#include <sys/ioctl.h>
+
+#ifdef HAVE_SYS_INOTIFY
+#include <sys/inotify.h>
+#include <fcntl.h>
+#elif HAVE_INOTIFY
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/syscall.h>
+// Linux kernel headers are documented to not compile
+#define _S390_BITOPS_H
+#include <linux/inotify.h>
+
+static inline int inotify_init (void)
+{
+ return syscall (__NR_inotify_init);
+}
+
+static inline int inotify_add_watch (int fd, const char *name, __u32 mask)
+{
+ return syscall (__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int inotify_rm_watch (int fd, __u32 wd)
+{
+ return syscall (__NR_inotify_rm_watch, fd, wd);
+}
+#endif
+
+#ifdef HAVE_INOTIFY
+#ifndef IN_ONLYDIR
+#define IN_ONLYDIR 0x01000000
+#endif
+
+#ifndef IN_DONT_FOLLOW
+#define IN_DONT_FOLLOW 0x02000000
+#endif
+
+#ifndef IN_MOVE_SELF
+#define IN_MOVE_SELF 0x00000800
+#endif
+#endif
+
+#include <sys/utsname.h>
+
+#include "kdirwatch.h"
+#include "kdirwatch_p.h"
+#include "global.h" // KIO::probably_slow_mounted
+
+#define NO_NOTIFY (time_t) 0
+
+static KDirWatchPrivate* dwp_self = 0;
+
+#ifdef HAVE_DNOTIFY
+
+static int dnotify_signal = 0;
+
+/* DNOTIFY signal handler
+ *
+ * As this is called asynchronously, only a flag is set and
+ * a rescan is requested.
+ * This is done by writing into a pipe to trigger a QSocketNotifier
+ * watching on this pipe: a timer is started and after a timeout,
+ * the rescan is done.
+ */
+void KDirWatchPrivate::dnotify_handler(int, siginfo_t *si, void *)
+{
+ if (!dwp_self) return;
+
+ // write might change errno, we have to save it and restore it
+ // (Richard Stevens, Advanced programming in the Unix Environment)
+ int saved_errno = errno;
+
+ Entry* e = dwp_self->fd_Entry.find(si->si_fd);
+
+// kdDebug(7001) << "DNOTIFY Handler: fd " << si->si_fd << " path "
+// << QString(e ? e->path:"unknown") << endl;
+
+ if(e && e->dn_fd == si->si_fd)
+ e->dirty = true;
+
+ char c = 0;
+ write(dwp_self->mPipe[1], &c, 1);
+ errno = saved_errno;
+}
+
+static struct sigaction old_sigio_act;
+/* DNOTIFY SIGIO signal handler
+ *
+ * When the kernel queue for the dnotify_signal overflows, a SIGIO is send.
+ */
+void KDirWatchPrivate::dnotify_sigio_handler(int sig, siginfo_t *si, void *p)
+{
+ if (dwp_self)
+ {
+ // write might change errno, we have to save it and restore it
+ // (Richard Stevens, Advanced programming in the Unix Environment)
+ int saved_errno = errno;
+
+ dwp_self->rescan_all = true;
+ char c = 0;
+ write(dwp_self->mPipe[1], &c, 1);
+
+ errno = saved_errno;
+ }
+
+ // Call previous signal handler
+ if (old_sigio_act.sa_flags & SA_SIGINFO)
+ {
+ if (old_sigio_act.sa_sigaction)
+ (*old_sigio_act.sa_sigaction)(sig, si, p);
+ }
+ else
+ {
+ if ((old_sigio_act.sa_handler != SIG_DFL) &&
+ (old_sigio_act.sa_handler != SIG_IGN))
+ (*old_sigio_act.sa_handler)(sig);
+ }
+}
+#endif
+
+
+//
+// Class KDirWatchPrivate (singleton)
+//
+
+/* All entries (files/directories) to be watched in the
+ * application (coming from multiple KDirWatch instances)
+ * are registered in a single KDirWatchPrivate instance.
+ *
+ * At the moment, the following methods for file watching
+ * are supported:
+ * - Polling: All files to be watched are polled regularly
+ * using stat (more precise: QFileInfo.lastModified()).
+ * The polling frequency is determined from global kconfig
+ * settings, defaulting to 500 ms for local directories
+ * and 5000 ms for remote mounts
+ * - FAM (File Alternation Monitor): first used on IRIX, SGI
+ * has ported this method to LINUX. It uses a kernel part
+ * (IMON, sending change events to /dev/imon) and a user
+ * level damon (fam), to which applications connect for
+ * notification of file changes. For NFS, the fam damon
+ * on the NFS server machine is used; if IMON is not built
+ * into the kernel, fam uses polling for local files.
+ * - DNOTIFY: In late LINUX 2.3.x, directory notification was
+ * introduced. By opening a directory, you can request for
+ * UNIX signals to be sent to the process when a directory
+ * is changed.
+ * - INOTIFY: In LINUX 2.6.13, inode change notification was
+ * introduced. You're now able to watch arbitrary inode's
+ * for changes, and even get notification when they're
+ * unmounted.
+ */
+
+KDirWatchPrivate::KDirWatchPrivate()
+ : rescan_timer(0, "KDirWatchPrivate::rescan_timer")
+{
+ timer = new QTimer(this, "KDirWatchPrivate::timer");
+ connect (timer, SIGNAL(timeout()), this, SLOT(slotRescan()));
+ freq = 3600000; // 1 hour as upper bound
+ statEntries = 0;
+ delayRemove = false;
+ m_ref = 0;
+
+ KConfigGroup config(KGlobal::config(), QCString("DirWatch"));
+ m_nfsPollInterval = config.readNumEntry("NFSPollInterval", 5000);
+ m_PollInterval = config.readNumEntry("PollInterval", 500);
+
+ QString available("Stat");
+
+ // used for FAM and DNOTIFY
+ rescan_all = false;
+ connect(&rescan_timer, SIGNAL(timeout()), this, SLOT(slotRescan()));
+
+#ifdef HAVE_FAM
+ // It's possible that FAM server can't be started
+ if (FAMOpen(&fc) ==0) {
+ available += ", FAM";
+ use_fam=true;
+ sn = new QSocketNotifier( FAMCONNECTION_GETFD(&fc),
+ QSocketNotifier::Read, this);
+ connect( sn, SIGNAL(activated(int)),
+ this, SLOT(famEventReceived()) );
+ }
+ else {
+ kdDebug(7001) << "Can't use FAM (fam daemon not running?)" << endl;
+ use_fam=false;
+ }
+#endif
+
+#ifdef HAVE_INOTIFY
+ supports_inotify = true;
+
+ m_inotify_fd = inotify_init();
+
+ if ( m_inotify_fd <= 0 ) {
+ kdDebug(7001) << "Can't use Inotify, kernel doesn't support it" << endl;
+ supports_inotify = false;
+ }
+
+ {
+ struct utsname uts;
+ int major, minor, patch;
+ if (uname(&uts) < 0)
+ supports_inotify = false; // *shrug*
+ else if (sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3)
+ supports_inotify = false; // *shrug*
+ else if( major * 1000000 + minor * 1000 + patch < 2006014 ) { // <2.6.14
+ kdDebug(7001) << "Can't use INotify, Linux kernel too old" << endl;
+ supports_inotify = false;
+ }
+ }
+
+ if ( supports_inotify ) {
+ available += ", Inotify";
+ fcntl(m_inotify_fd, F_SETFD, FD_CLOEXEC);
+
+ mSn = new QSocketNotifier( m_inotify_fd, QSocketNotifier::Read, this );
+ connect( mSn, SIGNAL(activated( int )), this, SLOT( slotActivated() ) );
+ }
+#endif
+
+#ifdef HAVE_DNOTIFY
+
+ // if we have inotify, disable dnotify.
+#ifdef HAVE_INOTIFY
+ supports_dnotify = !supports_inotify;
+#else
+ // otherwise, not guilty until proven guilty.
+ supports_dnotify = true;
+#endif
+
+ struct utsname uts;
+ int major, minor, patch;
+ if (uname(&uts) < 0)
+ supports_dnotify = false; // *shrug*
+ else if (sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3)
+ supports_dnotify = false; // *shrug*
+ else if( major * 1000000 + minor * 1000 + patch < 2004019 ) { // <2.4.19
+ kdDebug(7001) << "Can't use DNotify, Linux kernel too old" << endl;
+ supports_dnotify = false;
+ }
+
+ if( supports_dnotify ) {
+ available += ", DNotify";
+
+ pipe(mPipe);
+ fcntl(mPipe[0], F_SETFD, FD_CLOEXEC);
+ fcntl(mPipe[1], F_SETFD, FD_CLOEXEC);
+ fcntl(mPipe[0], F_SETFL, O_NONBLOCK | fcntl(mPipe[0], F_GETFL));
+ fcntl(mPipe[1], F_SETFL, O_NONBLOCK | fcntl(mPipe[1], F_GETFL));
+ mSn = new QSocketNotifier( mPipe[0], QSocketNotifier::Read, this);
+ connect(mSn, SIGNAL(activated(int)), this, SLOT(slotActivated()));
+ // Install the signal handler only once
+ if ( dnotify_signal == 0 )
+ {
+ dnotify_signal = SIGRTMIN + 8;
+
+ struct sigaction act;
+ act.sa_sigaction = KDirWatchPrivate::dnotify_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+ sigaction(dnotify_signal, &act, NULL);
+
+ act.sa_sigaction = KDirWatchPrivate::dnotify_sigio_handler;
+ sigaction(SIGIO, &act, &old_sigio_act);
+ }
+ }
+ else
+ {
+ mPipe[0] = -1;
+ mPipe[1] = -1;
+ }
+#endif
+
+ kdDebug(7001) << "Available methods: " << available << endl;
+}
+
+/* This is called on app exit (KStaticDeleter) */
+KDirWatchPrivate::~KDirWatchPrivate()
+{
+ timer->stop();
+
+ /* remove all entries being watched */
+ removeEntries(0);
+
+#ifdef HAVE_FAM
+ if (use_fam) {
+ FAMClose(&fc);
+ kdDebug(7001) << "KDirWatch deleted (FAM closed)" << endl;
+ }
+#endif
+#ifdef HAVE_INOTIFY
+ if ( supports_inotify )
+ ::close( m_inotify_fd );
+#endif
+#ifdef HAVE_DNOTIFY
+ close(mPipe[0]);
+ close(mPipe[1]);
+#endif
+}
+
+#include <stdlib.h>
+
+void KDirWatchPrivate::slotActivated()
+{
+#ifdef HAVE_DNOTIFY
+ if ( supports_dnotify )
+ {
+ char dummy_buf[4096];
+ read(mPipe[0], &dummy_buf, 4096);
+
+ if (!rescan_timer.isActive())
+ rescan_timer.start(m_PollInterval, true /* singleshot */);
+
+ return;
+ }
+#endif
+
+#ifdef HAVE_INOTIFY
+ if ( !supports_inotify )
+ return;
+
+ int pending = -1;
+ int offset = 0;
+ char buf[4096];
+ assert( m_inotify_fd > -1 );
+ ioctl( m_inotify_fd, FIONREAD, &pending );
+
+ while ( pending > 0 ) {
+
+ if ( pending > (int)sizeof( buf ) )
+ pending = sizeof( buf );
+
+ pending = read( m_inotify_fd, buf, pending);
+
+ while ( pending > 0 ) {
+ struct inotify_event *event = (struct inotify_event *) &buf[offset];
+ pending -= sizeof( struct inotify_event ) + event->len;
+ offset += sizeof( struct inotify_event ) + event->len;
+
+ QString path;
+ if ( event->len )
+ path = QFile::decodeName( QCString( event->name, event->len ) );
+
+ if ( path.length() && isNoisyFile( path.latin1() ) )
+ continue;
+
+ kdDebug(7001) << "ev wd: " << event->wd << " mask " << event->mask << " path: " << path << endl;
+
+ // now we're in deep trouble of finding the
+ // associated entries
+ // for now, we suck and iterate
+ for ( EntryMap::Iterator it = m_mapEntries.begin();
+ it != m_mapEntries.end(); ++it ) {
+ Entry* e = &( *it );
+ if ( e->wd == event->wd ) {
+ e->dirty = true;
+
+ if ( 1 || e->isDir) {
+ if( event->mask & IN_DELETE_SELF) {
+ kdDebug(7001) << "-->got deleteself signal for " << e->path << endl;
+ e->m_status = NonExistent;
+ if (e->isDir)
+ addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true);
+ else
+ addEntry(0, QFileInfo(e->path).dirPath(true), e, true);
+ }
+ if ( event->mask & IN_IGNORED ) {
+ e->wd = 0;
+ }
+ if ( event->mask & (IN_CREATE|IN_MOVED_TO) ) {
+ Entry *sub_entry = e->m_entries.first();
+ for(;sub_entry; sub_entry = e->m_entries.next())
+ if (sub_entry->path == e->path + "/" + path) break;
+
+ if (sub_entry /*&& sub_entry->isDir*/) {
+ removeEntry(0,e->path, sub_entry);
+ KDE_struct_stat stat_buf;
+ QCString tpath = QFile::encodeName(path);
+ KDE_stat(tpath, &stat_buf);
+
+ //sub_entry->isDir = S_ISDIR(stat_buf.st_mode);
+ //sub_entry->m_ctime = stat_buf.st_ctime;
+ //sub_entry->m_status = Normal;
+ //sub_entry->m_nlink = stat_buf.st_nlink;
+
+ if(!useINotify(sub_entry))
+ useStat(sub_entry);
+ sub_entry->dirty = true;
+ }
+ }
+ }
+
+ if (!rescan_timer.isActive())
+ rescan_timer.start(m_PollInterval, true /* singleshot */);
+
+ break; // there really should be only one matching wd
+ }
+ }
+
+ }
+ }
+#endif
+}
+
+/* In DNOTIFY/FAM mode, only entries which are marked dirty are scanned.
+ * We first need to mark all yet nonexistent, but possible created
+ * entries as dirty...
+ */
+void KDirWatchPrivate::Entry::propagate_dirty()
+{
+ for (QPtrListIterator<Entry> sub_entry (m_entries);
+ sub_entry.current(); ++sub_entry)
+ {
+ if (!sub_entry.current()->dirty)
+ {
+ sub_entry.current()->dirty = true;
+ sub_entry.current()->propagate_dirty();
+ }
+ }
+}
+
+
+/* A KDirWatch instance is interested in getting events for
+ * this file/Dir entry.
+ */
+void KDirWatchPrivate::Entry::addClient(KDirWatch* instance)
+{
+ Client* client = m_clients.first();
+ for(;client; client = m_clients.next())
+ if (client->instance == instance) break;
+
+ if (client) {
+ client->count++;
+ return;
+ }
+
+ client = new Client;
+ client->instance = instance;
+ client->count = 1;
+ client->watchingStopped = instance->isStopped();
+ client->pending = NoChange;
+
+ m_clients.append(client);
+}
+
+void KDirWatchPrivate::Entry::removeClient(KDirWatch* instance)
+{
+ Client* client = m_clients.first();
+ for(;client; client = m_clients.next())
+ if (client->instance == instance) break;
+
+ if (client) {
+ client->count--;
+ if (client->count == 0) {
+ m_clients.removeRef(client);
+ delete client;
+ }
+ }
+}
+
+/* get number of clients */
+int KDirWatchPrivate::Entry::clients()
+{
+ int clients = 0;
+ Client* client = m_clients.first();
+ for(;client; client = m_clients.next())
+ clients += client->count;
+
+ return clients;
+}
+
+
+KDirWatchPrivate::Entry* KDirWatchPrivate::entry(const QString& _path)
+{
+// we only support absolute paths
+ if (QDir::isRelativePath(_path)) {
+ return 0;
+ }
+
+ QString path = _path;
+
+ if ( path.length() > 1 && path.right(1) == "/" )
+ path.truncate( path.length() - 1 );
+
+ EntryMap::Iterator it = m_mapEntries.find( path );
+ if ( it == m_mapEntries.end() )
+ return 0;
+ else
+ return &(*it);
+}
+
+// set polling frequency for a entry and adjust global freq if needed
+void KDirWatchPrivate::useFreq(Entry* e, int newFreq)
+{
+ e->freq = newFreq;
+
+ // a reasonable frequency for the global polling timer
+ if (e->freq < freq) {
+ freq = e->freq;
+ if (timer->isActive()) timer->changeInterval(freq);
+ kdDebug(7001) << "Global Poll Freq is now " << freq << " msec" << endl;
+ }
+}
+
+
+#ifdef HAVE_FAM
+// setup FAM notification, returns false if not possible
+bool KDirWatchPrivate::useFAM(Entry* e)
+{
+ if (!use_fam) return false;
+
+ // handle FAM events to avoid deadlock
+ // (FAM sends back all files in a directory when monitoring)
+ famEventReceived();
+
+ e->m_mode = FAMMode;
+ e->dirty = false;
+
+ if (e->isDir) {
+ if (e->m_status == NonExistent) {
+ // If the directory does not exist we watch the parent directory
+ addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true);
+ }
+ else {
+ int res =FAMMonitorDirectory(&fc, QFile::encodeName(e->path),
+ &(e->fr), e);
+ if (res<0) {
+ e->m_mode = UnknownMode;
+ use_fam=false;
+ return false;
+ }
+ kdDebug(7001) << " Setup FAM (Req "
+ << FAMREQUEST_GETREQNUM(&(e->fr))
+ << ") for " << e->path << endl;
+ }
+ }
+ else {
+ if (e->m_status == NonExistent) {
+ // If the file does not exist we watch the directory
+ addEntry(0, QFileInfo(e->path).dirPath(true), e, true);
+ }
+ else {
+ int res = FAMMonitorFile(&fc, QFile::encodeName(e->path),
+ &(e->fr), e);
+ if (res<0) {
+ e->m_mode = UnknownMode;
+ use_fam=false;
+ return false;
+ }
+
+ kdDebug(7001) << " Setup FAM (Req "
+ << FAMREQUEST_GETREQNUM(&(e->fr))
+ << ") for " << e->path << endl;
+ }
+ }
+
+ // handle FAM events to avoid deadlock
+ // (FAM sends back all files in a directory when monitoring)
+ famEventReceived();
+
+ return true;
+}
+#endif
+
+
+#ifdef HAVE_DNOTIFY
+// setup DNotify notification, returns false if not possible
+bool KDirWatchPrivate::useDNotify(Entry* e)
+{
+ e->dn_fd = 0;
+ e->dirty = false;
+ if (!supports_dnotify) return false;
+
+ e->m_mode = DNotifyMode;
+
+ if (e->isDir) {
+ if (e->m_status == Normal) {
+ int fd = KDE_open(QFile::encodeName(e->path).data(), O_RDONLY);
+ // Migrate fd to somewhere above 128. Some libraries have
+ // constructs like:
+ // fd = socket(...)
+ // if (fd > ARBITRARY_LIMIT)
+ // return error;
+ //
+ // Since programs might end up using a lot of KDirWatch objects
+ // for a rather long time the above braindamage could get
+ // triggered.
+ //
+ // By moving the kdirwatch fd's to > 128, calls like socket() will keep
+ // returning fd's < ARBITRARY_LIMIT for a bit longer.
+ int fd2 = fcntl(fd, F_DUPFD, 128);
+ if (fd2 >= 0)
+ {
+ close(fd);
+ fd = fd2;
+ }
+ if (fd<0) {
+ e->m_mode = UnknownMode;
+ return false;
+ }
+
+ int mask = DN_DELETE|DN_CREATE|DN_RENAME|DN_MULTISHOT;
+ // if dependant is a file watch, we check for MODIFY & ATTRIB too
+ for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next())
+ if (!dep->isDir) { mask |= DN_MODIFY|DN_ATTRIB; break; }
+
+ if(fcntl(fd, F_SETSIG, dnotify_signal) < 0 ||
+ fcntl(fd, F_NOTIFY, mask) < 0) {
+
+ kdDebug(7001) << "Not using Linux Directory Notifications."
+ << endl;
+ supports_dnotify = false;
+ ::close(fd);
+ e->m_mode = UnknownMode;
+ return false;
+ }
+
+ fd_Entry.replace(fd, e);
+ e->dn_fd = fd;
+
+ kdDebug(7001) << " Setup DNotify (fd " << fd
+ << ") for " << e->path << endl;
+ }
+ else { // NotExisting
+ addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true);
+ }
+ }
+ else { // File
+ // we always watch the directory (DNOTIFY can't watch files alone)
+ // this notifies us about changes of files therein
+ addEntry(0, QFileInfo(e->path).dirPath(true), e, true);
+ }
+
+ return true;
+}
+#endif
+
+#ifdef HAVE_INOTIFY
+// setup INotify notification, returns false if not possible
+bool KDirWatchPrivate::useINotify( Entry* e )
+{
+ e->wd = 0;
+ e->dirty = false;
+ if (!supports_inotify) return false;
+
+ e->m_mode = INotifyMode;
+
+ int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW;
+ if(!e->isDir)
+ mask |= IN_MODIFY|IN_ATTRIB;
+ else
+ mask |= IN_ONLYDIR;
+
+ // if dependant is a file watch, we check for MODIFY & ATTRIB too
+ for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next()) {
+ if (!dep->isDir) { mask |= IN_MODIFY|IN_ATTRIB; break; }
+ }
+
+ if ( ( e->wd = inotify_add_watch( m_inotify_fd,
+ QFile::encodeName( e->path ), mask) ) > 0 )
+ return true;
+
+ if ( e->m_status == NonExistent ) {
+ if (e->isDir)
+ addEntry(0, QDir::cleanDirPath(e->path+"/.."), e, true);
+ else
+ addEntry(0, QFileInfo(e->path).dirPath(true), e, true);
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+bool KDirWatchPrivate::useStat(Entry* e)
+{
+ if (KIO::probably_slow_mounted(e->path))
+ useFreq(e, m_nfsPollInterval);
+ else
+ useFreq(e, m_PollInterval);
+
+ if (e->m_mode != StatMode) {
+ e->m_mode = StatMode;
+ statEntries++;
+
+ if ( statEntries == 1 ) {
+ // if this was first STAT entry (=timer was stopped)
+ timer->start(freq); // then start the timer
+ kdDebug(7001) << " Started Polling Timer, freq " << freq << endl;
+ }
+ }
+
+ kdDebug(7001) << " Setup Stat (freq " << e->freq
+ << ") for " << e->path << endl;
+
+ return true;
+}
+
+
+/* If <instance> !=0, this KDirWatch instance wants to watch at <_path>,
+ * providing in <isDir> the type of the entry to be watched.
+ * Sometimes, entries are dependant on each other: if <sub_entry> !=0,
+ * this entry needs another entry to watch himself (when notExistent).
+ */
+void KDirWatchPrivate::addEntry(KDirWatch* instance, const QString& _path,
+ Entry* sub_entry, bool isDir)
+{
+ QString path = _path;
+ if (path.startsWith("/dev/") || (path == "/dev"))
+ return; // Don't even go there.
+
+ if ( path.length() > 1 && path.right(1) == "/" )
+ path.truncate( path.length() - 1 );
+
+ EntryMap::Iterator it = m_mapEntries.find( path );
+ if ( it != m_mapEntries.end() )
+ {
+ if (sub_entry) {
+ (*it).m_entries.append(sub_entry);
+ kdDebug(7001) << "Added already watched Entry " << path
+ << " (for " << sub_entry->path << ")" << endl;
+
+#ifdef HAVE_DNOTIFY
+ {
+ Entry* e = &(*it);
+ if( (e->m_mode == DNotifyMode) && (e->dn_fd > 0) ) {
+ int mask = DN_DELETE|DN_CREATE|DN_RENAME|DN_MULTISHOT;
+ // if dependant is a file watch, we check for MODIFY & ATTRIB too
+ for(Entry* dep=e->m_entries.first();dep;dep=e->m_entries.next())
+ if (!dep->isDir) { mask |= DN_MODIFY|DN_ATTRIB; break; }
+ if( fcntl(e->dn_fd, F_NOTIFY, mask) < 0) { // shouldn't happen
+ ::close(e->dn_fd);
+ e->m_mode = UnknownMode;
+ fd_Entry.remove(e->dn_fd);
+ e->dn_fd = 0;
+ useStat( e );
+ }
+ }
+ }
+#endif
+
+#ifdef HAVE_INOTIFY
+ {
+ Entry* e = &(*it);
+ if( (e->m_mode == INotifyMode) && (e->wd > 0) ) {
+ int mask = IN_DELETE|IN_DELETE_SELF|IN_CREATE|IN_MOVE|IN_MOVE_SELF|IN_DONT_FOLLOW;
+ if(!e->isDir)
+ mask |= IN_MODIFY|IN_ATTRIB;
+ else
+ mask |= IN_ONLYDIR;
+
+ inotify_rm_watch (m_inotify_fd, e->wd);
+ e->wd = inotify_add_watch( m_inotify_fd, QFile::encodeName( e->path ), mask);
+ }
+ }
+#endif
+
+ }
+ else {
+ (*it).addClient(instance);
+ kdDebug(7001) << "Added already watched Entry " << path
+ << " (now " << (*it).clients() << " clients)"
+ << QString(" [%1]").arg(instance->name()) << endl;
+ }
+ return;
+ }
+
+ // we have a new path to watch
+
+ KDE_struct_stat stat_buf;
+ QCString tpath = QFile::encodeName(path);
+ bool exists = (KDE_stat(tpath, &stat_buf) == 0);
+
+ Entry newEntry;
+ m_mapEntries.insert( path, newEntry );
+ // the insert does a copy, so we have to use <e> now
+ Entry* e = &(m_mapEntries[path]);
+
+ if (exists) {
+ e->isDir = S_ISDIR(stat_buf.st_mode);
+
+ if (e->isDir && !isDir)
+ kdWarning() << "KDirWatch: " << path << " is a directory. Use addDir!" << endl;
+ else if (!e->isDir && isDir)
+ kdWarning() << "KDirWatch: " << path << " is a file. Use addFile!" << endl;
+
+ e->m_ctime = stat_buf.st_ctime;
+ e->m_status = Normal;
+ e->m_nlink = stat_buf.st_nlink;
+ }
+ else {
+ e->isDir = isDir;
+ e->m_ctime = invalid_ctime;
+ e->m_status = NonExistent;
+ e->m_nlink = 0;
+ }
+
+ e->path = path;
+ if (sub_entry)
+ e->m_entries.append(sub_entry);
+ else
+ e->addClient(instance);
+
+ kdDebug(7001) << "Added " << (e->isDir ? "Dir ":"File ") << path
+ << (e->m_status == NonExistent ? " NotExisting" : "")
+ << (sub_entry ? QString(" for %1").arg(sub_entry->path) : QString(""))
+ << (instance ? QString(" [%1]").arg(instance->name()) : QString(""))
+ << endl;
+
+
+ // now setup the notification method
+ e->m_mode = UnknownMode;
+ e->msecLeft = 0;
+
+ if ( isNoisyFile( tpath ) )
+ return;
+
+#ifdef HAVE_FAM
+ if (useFAM(e)) return;
+#endif
+
+#ifdef HAVE_INOTIFY
+ if (useINotify(e)) return;
+#endif
+
+#ifdef HAVE_DNOTIFY
+ if (useDNotify(e)) return;
+#endif
+
+ useStat(e);
+}
+
+
+void KDirWatchPrivate::removeEntry( KDirWatch* instance,
+ const QString& _path, Entry* sub_entry )
+{
+ kdDebug(7001) << "KDirWatchPrivate::removeEntry for '" << _path << "' sub_entry: " << sub_entry << endl;
+ Entry* e = entry(_path);
+ if (!e) {
+ kdDebug(7001) << "KDirWatchPrivate::removeEntry can't handle '" << _path << "'" << endl;
+ return;
+ }
+
+ if (sub_entry)
+ e->m_entries.removeRef(sub_entry);
+ else
+ e->removeClient(instance);
+
+ if (e->m_clients.count() || e->m_entries.count()) {
+ kdDebug(7001) << "removeEntry: unwatched " << e->path << " " << _path << endl;
+ return;
+ }
+
+ if (delayRemove) {
+ // removeList is allowed to contain any entry at most once
+ if (removeList.findRef(e)==-1)
+ removeList.append(e);
+ // now e->isValid() is false
+ return;
+ }
+
+#ifdef HAVE_FAM
+ if (e->m_mode == FAMMode) {
+ if ( e->m_status == Normal) {
+ FAMCancelMonitor(&fc, &(e->fr) );
+ kdDebug(7001) << "Cancelled FAM (Req "
+ << FAMREQUEST_GETREQNUM(&(e->fr))
+ << ") for " << e->path << endl;
+ }
+ else {
+ if (e->isDir)
+ removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e);
+ else
+ removeEntry(0, QFileInfo(e->path).dirPath(true), e);
+ }
+ }
+#endif
+
+#ifdef HAVE_INOTIFY
+ kdDebug(7001) << "inotify remove " << ( e->m_mode == INotifyMode ) << " " << ( e->m_status == Normal ) << endl;
+ if (e->m_mode == INotifyMode) {
+ if ( e->m_status == Normal ) {
+ (void) inotify_rm_watch( m_inotify_fd, e->wd );
+ kdDebug(7001) << "Cancelled INotify (fd " <<
+ m_inotify_fd << ", " << e->wd <<
+ ") for " << e->path << endl;
+ }
+ else {
+ if (e->isDir)
+ removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e);
+ else
+ removeEntry(0, QFileInfo(e->path).dirPath(true), e);
+ }
+ }
+#endif
+
+#ifdef HAVE_DNOTIFY
+ if (e->m_mode == DNotifyMode) {
+ if (!e->isDir) {
+ removeEntry(0, QFileInfo(e->path).dirPath(true), e);
+ }
+ else { // isDir
+ // must close the FD.
+ if ( e->m_status == Normal) {
+ if (e->dn_fd) {
+ ::close(e->dn_fd);
+ fd_Entry.remove(e->dn_fd);
+
+ kdDebug(7001) << "Cancelled DNotify (fd " << e->dn_fd
+ << ") for " << e->path << endl;
+ e->dn_fd = 0;
+
+ }
+ }
+ else {
+ removeEntry(0, QDir::cleanDirPath(e->path+"/.."), e);
+ }
+ }
+ }
+#endif
+
+ if (e->m_mode == StatMode) {
+ statEntries--;
+ if ( statEntries == 0 ) {
+ timer->stop(); // stop timer if lists are empty
+ kdDebug(7001) << " Stopped Polling Timer" << endl;
+ }
+ }
+
+ kdDebug(7001) << "Removed " << (e->isDir ? "Dir ":"File ") << e->path
+ << (sub_entry ? QString(" for %1").arg(sub_entry->path) : QString(""))
+ << (instance ? QString(" [%1]").arg(instance->name()) : QString(""))
+ << endl;
+ m_mapEntries.remove( e->path ); // <e> not valid any more
+}
+
+
+/* Called from KDirWatch destructor:
+ * remove <instance> as client from all entries
+ */
+void KDirWatchPrivate::removeEntries( KDirWatch* instance )
+{
+ QPtrList<Entry> list;
+ int minfreq = 3600000;
+
+ // put all entries where instance is a client in list
+ EntryMap::Iterator it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it ) {
+ Client* c = (*it).m_clients.first();
+ for(;c;c=(*it).m_clients.next())
+ if (c->instance == instance) break;
+ if (c) {
+ c->count = 1; // forces deletion of instance as client
+ list.append(&(*it));
+ }
+ else if ( (*it).m_mode == StatMode && (*it).freq < minfreq )
+ minfreq = (*it).freq;
+ }
+
+ for(Entry* e=list.first();e;e=list.next())
+ removeEntry(instance, e->path, 0);
+
+ if (minfreq > freq) {
+ // we can decrease the global polling frequency
+ freq = minfreq;
+ if (timer->isActive()) timer->changeInterval(freq);
+ kdDebug(7001) << "Poll Freq now " << freq << " msec" << endl;
+ }
+}
+
+// instance ==0: stop scanning for all instances
+bool KDirWatchPrivate::stopEntryScan( KDirWatch* instance, Entry* e)
+{
+ int stillWatching = 0;
+ Client* c = e->m_clients.first();
+ for(;c;c=e->m_clients.next()) {
+ if (!instance || instance == c->instance)
+ c->watchingStopped = true;
+ else if (!c->watchingStopped)
+ stillWatching += c->count;
+ }
+
+ kdDebug(7001) << instance->name() << " stopped scanning " << e->path
+ << " (now " << stillWatching << " watchers)" << endl;
+
+ if (stillWatching == 0) {
+ // if nobody is interested, we don't watch
+ e->m_ctime = invalid_ctime; // invalid
+ e->m_status = NonExistent;
+ // e->m_status = Normal;
+ }
+ return true;
+}
+
+// instance ==0: start scanning for all instances
+bool KDirWatchPrivate::restartEntryScan( KDirWatch* instance, Entry* e,
+ bool notify)
+{
+ int wasWatching = 0, newWatching = 0;
+ Client* c = e->m_clients.first();
+ for(;c;c=e->m_clients.next()) {
+ if (!c->watchingStopped)
+ wasWatching += c->count;
+ else if (!instance || instance == c->instance) {
+ c->watchingStopped = false;
+ newWatching += c->count;
+ }
+ }
+ if (newWatching == 0)
+ return false;
+
+ kdDebug(7001) << (instance ? instance->name() : "all") << " restarted scanning " << e->path
+ << " (now " << wasWatching+newWatching << " watchers)" << endl;
+
+ // restart watching and emit pending events
+
+ int ev = NoChange;
+ if (wasWatching == 0) {
+ if (!notify) {
+ KDE_struct_stat stat_buf;
+ bool exists = (KDE_stat(QFile::encodeName(e->path), &stat_buf) == 0);
+ if (exists) {
+ e->m_ctime = stat_buf.st_ctime;
+ e->m_status = Normal;
+ e->m_nlink = stat_buf.st_nlink;
+ }
+ else {
+ e->m_ctime = invalid_ctime;
+ e->m_status = NonExistent;
+ e->m_nlink = 0;
+ }
+ }
+ e->msecLeft = 0;
+ ev = scanEntry(e);
+ }
+ emitEvent(e,ev);
+
+ return true;
+}
+
+// instance ==0: stop scanning for all instances
+void KDirWatchPrivate::stopScan(KDirWatch* instance)
+{
+ EntryMap::Iterator it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it )
+ stopEntryScan(instance, &(*it));
+}
+
+
+void KDirWatchPrivate::startScan(KDirWatch* instance,
+ bool notify, bool skippedToo )
+{
+ if (!notify)
+ resetList(instance,skippedToo);
+
+ EntryMap::Iterator it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it )
+ restartEntryScan(instance, &(*it), notify);
+
+ // timer should still be running when in polling mode
+}
+
+
+// clear all pending events, also from stopped
+void KDirWatchPrivate::resetList( KDirWatch* /*instance*/,
+ bool skippedToo )
+{
+ EntryMap::Iterator it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it ) {
+
+ Client* c = (*it).m_clients.first();
+ for(;c;c=(*it).m_clients.next())
+ if (!c->watchingStopped || skippedToo)
+ c->pending = NoChange;
+ }
+}
+
+// Return event happened on <e>
+//
+int KDirWatchPrivate::scanEntry(Entry* e)
+{
+#ifdef HAVE_FAM
+ if (e->m_mode == FAMMode) {
+ // we know nothing has changed, no need to stat
+ if(!e->dirty) return NoChange;
+ e->dirty = false;
+ }
+#endif
+
+ // Shouldn't happen: Ignore "unknown" notification method
+ if (e->m_mode == UnknownMode) return NoChange;
+
+#if defined ( HAVE_DNOTIFY ) || defined( HAVE_INOTIFY )
+ if (e->m_mode == DNotifyMode || e->m_mode == INotifyMode ) {
+ // we know nothing has changed, no need to stat
+ if(!e->dirty) return NoChange;
+ kdDebug(7001) << "scanning " << e->path << " " << e->m_status << " " << e->m_ctime << endl;
+ e->dirty = false;
+ }
+#endif
+
+ if (e->m_mode == StatMode) {
+ // only scan if timeout on entry timer happens;
+ // e.g. when using 500msec global timer, a entry
+ // with freq=5000 is only watched every 10th time
+
+ e->msecLeft -= freq;
+ if (e->msecLeft>0) return NoChange;
+ e->msecLeft += e->freq;
+ }
+
+ KDE_struct_stat stat_buf;
+ bool exists = (KDE_stat(QFile::encodeName(e->path), &stat_buf) == 0);
+ if (exists) {
+
+ if (e->m_status == NonExistent) {
+ e->m_ctime = stat_buf.st_ctime;
+ e->m_status = Normal;
+ e->m_nlink = stat_buf.st_nlink;
+ return Created;
+ }
+
+ if ( (e->m_ctime != invalid_ctime) &&
+ ((stat_buf.st_ctime != e->m_ctime) ||
+ (stat_buf.st_nlink != (nlink_t) e->m_nlink)) ) {
+ e->m_ctime = stat_buf.st_ctime;
+ e->m_nlink = stat_buf.st_nlink;
+ return Changed;
+ }
+
+ return NoChange;
+ }
+
+ // dir/file doesn't exist
+
+ if (e->m_ctime == invalid_ctime && e->m_status == NonExistent) {
+ e->m_nlink = 0;
+ e->m_status = NonExistent;
+ return NoChange;
+ }
+
+ e->m_ctime = invalid_ctime;
+ e->m_nlink = 0;
+ e->m_status = NonExistent;
+
+ return Deleted;
+}
+
+/* Notify all interested KDirWatch instances about a given event on an entry
+ * and stored pending events. When watching is stopped, the event is
+ * added to the pending events.
+ */
+void KDirWatchPrivate::emitEvent(Entry* e, int event, const QString &fileName)
+{
+ QString path = e->path;
+ if (!fileName.isEmpty()) {
+ if (!QDir::isRelativePath(fileName))
+ path = fileName;
+ else
+#ifdef Q_OS_UNIX
+ path += "/" + fileName;
+#elif defined(Q_WS_WIN)
+ //current drive is passed instead of /
+ path += QDir::currentDirPath().left(2) + "/" + fileName;
+#endif
+ }
+
+ QPtrListIterator<Client> cit( e->m_clients );
+ for ( ; cit.current(); ++cit )
+ {
+ Client* c = cit.current();
+
+ if (c->instance==0 || c->count==0) continue;
+
+ if (c->watchingStopped) {
+ // add event to pending...
+ if (event == Changed)
+ c->pending |= event;
+ else if (event == Created || event == Deleted)
+ c->pending = event;
+ continue;
+ }
+ // not stopped
+ if (event == NoChange || event == Changed)
+ event |= c->pending;
+ c->pending = NoChange;
+ if (event == NoChange) continue;
+
+ if (event & Deleted) {
+ c->instance->setDeleted(path);
+ // emit only Deleted event...
+ continue;
+ }
+
+ if (event & Created) {
+ c->instance->setCreated(path);
+ // possible emit Change event after creation
+ }
+
+ if (event & Changed)
+ c->instance->setDirty(path);
+ }
+}
+
+// Remove entries which were marked to be removed
+void KDirWatchPrivate::slotRemoveDelayed()
+{
+ Entry* e;
+ delayRemove = false;
+ for(e=removeList.first();e;e=removeList.next())
+ removeEntry(0, e->path, 0);
+ removeList.clear();
+}
+
+/* Scan all entries to be watched for changes. This is done regularly
+ * when polling and once after a DNOTIFY signal. This is NOT used by FAM.
+ */
+void KDirWatchPrivate::slotRescan()
+{
+ EntryMap::Iterator it;
+
+ // People can do very long things in the slot connected to dirty(),
+ // like showing a message box. We don't want to keep polling during
+ // that time, otherwise the value of 'delayRemove' will be reset.
+ bool timerRunning = timer->isActive();
+ if ( timerRunning )
+ timer->stop();
+
+ // We delay deletions of entries this way.
+ // removeDir(), when called in slotDirty(), can cause a crash otherwise
+ delayRemove = true;
+
+#if defined(HAVE_DNOTIFY) || defined(HAVE_INOTIFY)
+ QPtrList<Entry> dList, cList;
+#endif
+
+ if (rescan_all)
+ {
+ // mark all as dirty
+ it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it )
+ (*it).dirty = true;
+ rescan_all = false;
+ }
+ else
+ {
+ // progate dirty flag to dependant entries (e.g. file watches)
+ it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it )
+ if (((*it).m_mode == INotifyMode || (*it).m_mode == DNotifyMode) && (*it).dirty )
+ (*it).propagate_dirty();
+ }
+
+ it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it ) {
+ // we don't check invalid entries (i.e. remove delayed)
+ if (!(*it).isValid()) continue;
+
+ int ev = scanEntry( &(*it) );
+
+
+#ifdef HAVE_INOTIFY
+ if ((*it).m_mode == INotifyMode && ev == Created && (*it).wd == 0) {
+ cList.append( &(*it) );
+ if (! useINotify( &(*it) )) {
+ useStat( &(*it) );
+ }
+ }
+#endif
+
+#ifdef HAVE_DNOTIFY
+ if ((*it).m_mode == DNotifyMode) {
+ if ((*it).isDir && (ev == Deleted)) {
+ dList.append( &(*it) );
+
+ // must close the FD.
+ if ((*it).dn_fd) {
+ ::close((*it).dn_fd);
+ fd_Entry.remove((*it).dn_fd);
+ (*it).dn_fd = 0;
+ }
+ }
+
+ else if ((*it).isDir && (ev == Created)) {
+ // For created, but yet without DNOTIFYing ...
+ if ( (*it).dn_fd == 0) {
+ cList.append( &(*it) );
+ if (! useDNotify( &(*it) )) {
+ // if DNotify setup fails...
+ useStat( &(*it) );
+ }
+ }
+ }
+ }
+#endif
+
+ if ( ev != NoChange )
+ emitEvent( &(*it), ev);
+ }
+
+
+#if defined(HAVE_DNOTIFY) || defined(HAVE_INOTIFY)
+ // Scan parent of deleted directories for new creation
+ Entry* e;
+ for(e=dList.first();e;e=dList.next())
+ addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true);
+
+ // Remove watch of parent of new created directories
+ for(e=cList.first();e;e=cList.next())
+ removeEntry(0, QDir::cleanDirPath( e->path+"/.."), e);
+#endif
+
+ if ( timerRunning )
+ timer->start(freq);
+
+ QTimer::singleShot(0, this, SLOT(slotRemoveDelayed()));
+}
+
+bool KDirWatchPrivate::isNoisyFile( const char * filename )
+{
+ // $HOME/.X.err grows with debug output, so don't notify change
+ if ( *filename == '.') {
+ if (strncmp(filename, ".X.err", 6) == 0) return true;
+ if (strncmp(filename, ".xsession-errors", 16) == 0) return true;
+ // fontconfig updates the cache on every KDE app start
+ // (inclusive kio_thumbnail slaves)
+ if (strncmp(filename, ".fonts.cache", 12) == 0) return true;
+ }
+
+ return false;
+}
+
+#ifdef HAVE_FAM
+void KDirWatchPrivate::famEventReceived()
+{
+ static FAMEvent fe;
+
+ delayRemove = true;
+
+ while(use_fam && FAMPending(&fc)) {
+ if (FAMNextEvent(&fc, &fe) == -1) {
+ kdWarning(7001) << "FAM connection problem, switching to polling."
+ << endl;
+ use_fam = false;
+ delete sn; sn = 0;
+
+ // Replace all FAMMode entries with DNotify/Stat
+ EntryMap::Iterator it;
+ it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it )
+ if ((*it).m_mode == FAMMode && (*it).m_clients.count()>0) {
+#ifdef HAVE_INOTIFY
+ if (useINotify( &(*it) )) continue;
+#endif
+#ifdef HAVE_DNOTIFY
+ if (useDNotify( &(*it) )) continue;
+#endif
+ useStat( &(*it) );
+ }
+ }
+ else
+ checkFAMEvent(&fe);
+ }
+
+ QTimer::singleShot(0, this, SLOT(slotRemoveDelayed()));
+}
+
+void KDirWatchPrivate::checkFAMEvent(FAMEvent* fe)
+{
+ // Don't be too verbose ;-)
+ if ((fe->code == FAMExists) ||
+ (fe->code == FAMEndExist) ||
+ (fe->code == FAMAcknowledge)) return;
+
+ if ( isNoisyFile( fe->filename ) )
+ return;
+
+ Entry* e = 0;
+ EntryMap::Iterator it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it )
+ if (FAMREQUEST_GETREQNUM(&( (*it).fr )) ==
+ FAMREQUEST_GETREQNUM(&(fe->fr)) ) {
+ e = &(*it);
+ break;
+ }
+
+ // Entry* e = static_cast<Entry*>(fe->userdata);
+
+#if 0 // #88538
+ kdDebug(7001) << "Processing FAM event ("
+ << ((fe->code == FAMChanged) ? "FAMChanged" :
+ (fe->code == FAMDeleted) ? "FAMDeleted" :
+ (fe->code == FAMStartExecuting) ? "FAMStartExecuting" :
+ (fe->code == FAMStopExecuting) ? "FAMStopExecuting" :
+ (fe->code == FAMCreated) ? "FAMCreated" :
+ (fe->code == FAMMoved) ? "FAMMoved" :
+ (fe->code == FAMAcknowledge) ? "FAMAcknowledge" :
+ (fe->code == FAMExists) ? "FAMExists" :
+ (fe->code == FAMEndExist) ? "FAMEndExist" : "Unknown Code")
+ << ", " << fe->filename
+ << ", Req " << FAMREQUEST_GETREQNUM(&(fe->fr))
+ << ")" << endl;
+#endif
+
+ if (!e) {
+ // this happens e.g. for FAMAcknowledge after deleting a dir...
+ // kdDebug(7001) << "No entry for FAM event ?!" << endl;
+ return;
+ }
+
+ if (e->m_status == NonExistent) {
+ kdDebug(7001) << "FAM event for nonExistent entry " << e->path << endl;
+ return;
+ }
+
+ // Delayed handling. This rechecks changes with own stat calls.
+ e->dirty = true;
+ if (!rescan_timer.isActive())
+ rescan_timer.start(m_PollInterval, true);
+
+ // needed FAM control actions on FAM events
+ if (e->isDir)
+ switch (fe->code)
+ {
+ case FAMDeleted:
+ // file absolute: watched dir
+ if (!QDir::isRelativePath(fe->filename))
+ {
+ // a watched directory was deleted
+
+ e->m_status = NonExistent;
+ FAMCancelMonitor(&fc, &(e->fr) ); // needed ?
+ kdDebug(7001) << "Cancelled FAMReq "
+ << FAMREQUEST_GETREQNUM(&(e->fr))
+ << " for " << e->path << endl;
+ // Scan parent for a new creation
+ addEntry(0, QDir::cleanDirPath( e->path+"/.."), e, true);
+ }
+ break;
+
+ case FAMCreated: {
+ // check for creation of a directory we have to watch
+ Entry *sub_entry = e->m_entries.first();
+ for(;sub_entry; sub_entry = e->m_entries.next())
+ if (sub_entry->path == e->path + "/" + fe->filename) break;
+ if (sub_entry && sub_entry->isDir) {
+ QString path = e->path;
+ removeEntry(0,e->path,sub_entry); // <e> can be invalid here!!
+ sub_entry->m_status = Normal;
+ if (!useFAM(sub_entry))
+#ifdef HAVE_INOTIFY
+ if (!useINotify(sub_entry ))
+#endif
+ useStat(sub_entry);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+#else
+void KDirWatchPrivate::famEventReceived() {}
+#endif
+
+
+void KDirWatchPrivate::statistics()
+{
+ EntryMap::Iterator it;
+
+ kdDebug(7001) << "Entries watched:" << endl;
+ if (m_mapEntries.count()==0) {
+ kdDebug(7001) << " None." << endl;
+ }
+ else {
+ it = m_mapEntries.begin();
+ for( ; it != m_mapEntries.end(); ++it ) {
+ Entry* e = &(*it);
+ kdDebug(7001) << " " << e->path << " ("
+ << ((e->m_status==Normal)?"":"Nonexistent ")
+ << (e->isDir ? "Dir":"File") << ", using "
+ << ((e->m_mode == FAMMode) ? "FAM" :
+ (e->m_mode == INotifyMode) ? "INotify" :
+ (e->m_mode == DNotifyMode) ? "DNotify" :
+ (e->m_mode == StatMode) ? "Stat" : "Unknown Method")
+ << ")" << endl;
+
+ Client* c = e->m_clients.first();
+ for(;c; c = e->m_clients.next()) {
+ QString pending;
+ if (c->watchingStopped) {
+ if (c->pending & Deleted) pending += "deleted ";
+ if (c->pending & Created) pending += "created ";
+ if (c->pending & Changed) pending += "changed ";
+ if (!pending.isEmpty()) pending = " (pending: " + pending + ")";
+ pending = ", stopped" + pending;
+ }
+ kdDebug(7001) << " by " << c->instance->name()
+ << " (" << c->count << " times)"
+ << pending << endl;
+ }
+ if (e->m_entries.count()>0) {
+ kdDebug(7001) << " dependent entries:" << endl;
+ Entry* d = e->m_entries.first();
+ for(;d; d = e->m_entries.next()) {
+ kdDebug(7001) << " " << d << endl;
+ kdDebug(7001) << " " << d->path << " (" << d << ") " << endl;
+ }
+ }
+ }
+ }
+}
+
+
+//
+// Class KDirWatch
+//
+
+static KStaticDeleter<KDirWatch> sd_dw;
+KDirWatch* KDirWatch::s_pSelf = 0L;
+
+KDirWatch* KDirWatch::self()
+{
+ if ( !s_pSelf ) {
+ sd_dw.setObject( s_pSelf, new KDirWatch );
+ }
+
+ return s_pSelf;
+}
+
+bool KDirWatch::exists()
+{
+ return s_pSelf != 0;
+}
+
+KDirWatch::KDirWatch (QObject* parent, const char* name)
+ : QObject(parent,name)
+{
+ if (!name) {
+ static int nameCounter = 0;
+
+ nameCounter++;
+ setName(QString("KDirWatch-%1").arg(nameCounter).ascii());
+ }
+
+ if (!dwp_self)
+ dwp_self = new KDirWatchPrivate;
+ d = dwp_self;
+ d->ref();
+
+ _isStopped = false;
+}
+
+KDirWatch::~KDirWatch()
+{
+ d->removeEntries(this);
+ if ( d->deref() )
+ {
+ // delete it if it's the last one
+ delete d;
+ dwp_self = 0L;
+ }
+}
+
+
+// TODO: add watchFiles/recursive support
+void KDirWatch::addDir( const QString& _path,
+ bool watchFiles, bool recursive)
+{
+ if (watchFiles || recursive) {
+ kdDebug(7001) << "addDir - recursive/watchFiles not supported yet in KDE 3.x" << endl;
+ }
+ if (d) d->addEntry(this, _path, 0, true);
+}
+
+void KDirWatch::addFile( const QString& _path )
+{
+ if (d) d->addEntry(this, _path, 0, false);
+}
+
+QDateTime KDirWatch::ctime( const QString &_path )
+{
+ KDirWatchPrivate::Entry* e = d->entry(_path);
+
+ if (!e)
+ return QDateTime();
+
+ QDateTime result;
+ result.setTime_t(e->m_ctime);
+ return result;
+}
+
+void KDirWatch::removeDir( const QString& _path )
+{
+ if (d) d->removeEntry(this, _path, 0);
+}
+
+void KDirWatch::removeFile( const QString& _path )
+{
+ if (d) d->removeEntry(this, _path, 0);
+}
+
+bool KDirWatch::stopDirScan( const QString& _path )
+{
+ if (d) {
+ KDirWatchPrivate::Entry *e = d->entry(_path);
+ if (e && e->isDir) return d->stopEntryScan(this, e);
+ }
+ return false;
+}
+
+bool KDirWatch::restartDirScan( const QString& _path )
+{
+ if (d) {
+ KDirWatchPrivate::Entry *e = d->entry(_path);
+ if (e && e->isDir)
+ // restart without notifying pending events
+ return d->restartEntryScan(this, e, false);
+ }
+ return false;
+}
+
+void KDirWatch::stopScan()
+{
+ if (d) d->stopScan(this);
+ _isStopped = true;
+}
+
+void KDirWatch::startScan( bool notify, bool skippedToo )
+{
+ _isStopped = false;
+ if (d) d->startScan(this, notify, skippedToo);
+}
+
+
+bool KDirWatch::contains( const QString& _path ) const
+{
+ KDirWatchPrivate::Entry* e = d->entry(_path);
+ if (!e)
+ return false;
+
+ KDirWatchPrivate::Client* c = e->m_clients.first();
+ for(;c;c=e->m_clients.next())
+ if (c->instance == this) return true;
+
+ return false;
+}
+
+void KDirWatch::statistics()
+{
+ if (!dwp_self) {
+ kdDebug(7001) << "KDirWatch not used" << endl;
+ return;
+ }
+ dwp_self->statistics();
+}
+
+
+void KDirWatch::setCreated( const QString & _file )
+{
+ kdDebug(7001) << name() << " emitting created " << _file << endl;
+ emit created( _file );
+}
+
+void KDirWatch::setDirty( const QString & _file )
+{
+ kdDebug(7001) << name() << " emitting dirty " << _file << endl;
+ emit dirty( _file );
+}
+
+void KDirWatch::setDeleted( const QString & _file )
+{
+ kdDebug(7001) << name() << " emitting deleted " << _file << endl;
+ emit deleted( _file );
+}
+
+KDirWatch::Method KDirWatch::internalMethod()
+{
+#ifdef HAVE_FAM
+ if (d->use_fam)
+ return KDirWatch::FAM;
+#endif
+#ifdef HAVE_INOTIFY
+ if (d->supports_inotify)
+ return KDirWatch::INotify;
+#endif
+#ifdef HAVE_DNOTIFY
+ if (d->supports_dnotify)
+ return KDirWatch::DNotify;
+#endif
+ return KDirWatch::Stat;
+}
+
+
+#include "kdirwatch.moc"
+#include "kdirwatch_p.moc"
+
+//sven
+
+// vim: sw=2 ts=8 et
diff --git a/kio/kio/krun.cpp b/kio/kio/krun.cpp
index b90f603f0..6acfb3b74 100644
--- a/kio/kio/krun.cpp
+++ b/kio/kio/krun.cpp
@@ -77,6 +77,7 @@ public:
QString m_localPath;
QString m_suggestedFileName;
QGuardedPtr <QWidget> m_window;
+ QCString m_asn;
};
pid_t KRun::runURL( const KURL& u, const QString& _mimetype )
@@ -109,14 +110,20 @@ bool KRun::isExecutableFile( const KURL& url, const QString &mimetype )
return false;
}
-// This is called by foundMimeType, since it knows the mimetype of the URL
pid_t KRun::runURL( const KURL& u, const QString& _mimetype, bool tempFile, bool runExecutables, const QString& suggestedFileName )
{
+ return runURL( u, _mimetype, NULL, "", tempFile, runExecutables, suggestedFileName );
+}
+
+// This is called by foundMimeType, since it knows the mimetype of the URL
+pid_t KRun::runURL( const KURL& u, const QString& _mimetype, QWidget* window, const QCString& asn,
+ bool tempFile, bool runExecutables, const QString& suggestedFileName )
+{
bool noRun = false;
bool noAuth = false;
if ( _mimetype == "inode/directory-locked" )
{
- KMessageBoxWrapper::error( 0L,
+ KMessageBoxWrapper::error( window,
i18n("<qt>Unable to enter <b>%1</b>.\nYou do not have access rights to this location.</qt>").arg(u.htmlURL()) );
return 0;
}
@@ -133,7 +140,7 @@ pid_t KRun::runURL( const KURL& u, const QString& _mimetype, bool tempFile, bool
{
QString path = u.path();
shellQuote( path );
- return (KRun::runCommand(path)); // just execute the url as a command
+ return (KRun::runCommand(path, QString::null, QString::null, window, asn)); // just execute the url as a command
// ## TODO implement deleting the file if tempFile==true
}
else
@@ -155,14 +162,14 @@ pid_t KRun::runURL( const KURL& u, const QString& _mimetype, bool tempFile, bool
if ( noRun )
{
- KMessageBox::sorry( 0L,
+ KMessageBox::sorry( window,
i18n("<qt>The file <b>%1</b> is an executable program. "
"For safety it will not be started.</qt>").arg(u.htmlURL()));
return 0;
}
if ( noAuth )
{
- KMessageBoxWrapper::error( 0L,
+ KMessageBoxWrapper::error( window,
i18n("<qt>You do not have permission to run <b>%1</b>.</qt>").arg(u.htmlURL()) );
return 0;
}
@@ -182,7 +189,7 @@ pid_t KRun::runURL( const KURL& u, const QString& _mimetype, bool tempFile, bool
return displayOpenWithDialog( lst, tempFile, suggestedFileName );
}
- return KRun::run( *offer, lst, 0 /*window*/, tempFile, suggestedFileName );
+ return KRun::run( *offer, lst, window, asn, tempFile, suggestedFileName );
}
bool KRun::displayOpenWithDialog( const KURL::List& lst )
@@ -536,13 +543,13 @@ QString KRun::binaryName( const QString & execLine, bool removePath )
}
static pid_t runCommandInternal( KProcess* proc, const KService* service, const QString& binName,
- const QString &execName, const QString & iconName )
+ const QString &execName, const QString & iconName, QWidget* window, QCString asn )
{
if (service && !service->desktopEntryPath().isEmpty()
&& !KDesktopFile::isAuthorizedDesktopFile( service->desktopEntryPath() ))
{
kdWarning() << "No authorization to execute " << service->desktopEntryPath() << endl;
- KMessageBox::sorry(0, i18n("You are not authorized to execute this file."));
+ KMessageBox::sorry(window, i18n("You are not authorized to execute this file."));
return 0;
}
QString bin = KRun::binaryName( binName, true );
@@ -550,10 +557,10 @@ static pid_t runCommandInternal( KProcess* proc, const KService* service, const
bool silent;
QCString wmclass;
KStartupInfoId id;
- bool startup_notify = KRun::checkStartupNotify( binName, service, &silent, &wmclass );
+ bool startup_notify = ( asn != "0" && KRun::checkStartupNotify( binName, service, &silent, &wmclass ));
if( startup_notify )
{
- id.initId();
+ id.initId( asn );
id.setupStartupEnv();
KStartupInfoData data;
data.setHostname();
@@ -572,6 +579,8 @@ static pid_t runCommandInternal( KProcess* proc, const KService* service, const
if( silent )
data.setSilent( KStartupInfoData::Yes );
data.setDesktop( KWin::currentDesktop());
+ if( window )
+ data.setLaunchedBy( window->winId());
KStartupInfo::sendStartup( id, data );
}
pid_t pid = KProcessRunner::run( proc, binName, id );
@@ -635,7 +644,8 @@ bool KRun::checkStartupNotify( const QString& /*binName*/, const KService* servi
return true;
}
-static pid_t runTempService( const KService& _service, const KURL::List& _urls, bool tempFiles, const QString& suggestedFileName )
+static pid_t runTempService( const KService& _service, const KURL::List& _urls, QWidget* window,
+ const QCString& asn, bool tempFiles, const QString& suggestedFileName )
{
if (!_urls.isEmpty()) {
kdDebug(7010) << "runTempService: first url " << _urls.first().url() << endl;
@@ -654,7 +664,7 @@ static pid_t runTempService( const KService& _service, const KURL::List& _urls,
{
KURL::List singleUrl;
singleUrl.append(*it);
- runTempService( _service, singleUrl, tempFiles, suggestedFileName );
+ runTempService( _service, singleUrl, window, "", tempFiles, suggestedFileName );
}
KURL::List singleUrl;
singleUrl.append(_urls.first());
@@ -673,7 +683,7 @@ static pid_t runTempService( const KService& _service, const KURL::List& _urls,
proc->setWorkingDirectory(_service.path());
return runCommandInternal( proc, &_service, KRun::binaryName( _service.exec(), false ),
- _service.name(), _service.icon() );
+ _service.name(), _service.icon(), window, asn );
}
// WARNING: don't call this from processDesktopExec, since klauncher uses that too...
@@ -734,11 +744,22 @@ pid_t KRun::run( const KService& _service, const KURL::List& _urls, bool tempFil
pid_t KRun::run( const KService& _service, const KURL::List& _urls, QWidget* window, bool tempFiles )
{
- return run( _service, _urls, window, tempFiles, QString::null );
+ return run( _service, _urls, window, "", tempFiles, QString::null );
+}
+
+pid_t KRun::run( const KService& _service, const KURL::List& _urls, QWidget* window, const QCString& asn, bool tempFiles )
+{
+ return run( _service, _urls, window, asn, tempFiles, QString::null );
}
pid_t KRun::run( const KService& _service, const KURL::List& _urls, QWidget* window, bool tempFiles, const QString& suggestedFileName )
{
+ return run( _service, _urls, window, "", tempFiles, suggestedFileName );
+}
+
+pid_t KRun::run( const KService& _service, const KURL::List& _urls, QWidget* window, const QCString& asn,
+ bool tempFiles, const QString& suggestedFileName )
+{
if (!_service.desktopEntryPath().isEmpty() &&
!KDesktopFile::isAuthorizedDesktopFile( _service.desktopEntryPath()))
{
@@ -759,7 +780,7 @@ pid_t KRun::run( const KService& _service, const KURL::List& _urls, QWidget* win
if ( tempFiles || _service.desktopEntryPath().isEmpty() || !suggestedFileName.isEmpty() )
{
- return runTempService(_service, _urls, tempFiles, suggestedFileName);
+ return runTempService(_service, _urls, window, asn, tempFiles, suggestedFileName);
}
kdDebug(7010) << "KRun::run " << _service.desktopEntryPath() << endl;
@@ -773,9 +794,25 @@ pid_t KRun::run( const KService& _service, const KURL::List& _urls, QWidget* win
QString error;
int pid = 0;
-
+
+ QCString myasn = asn;
+ // startServiceByDesktopPath() doesn't take QWidget*, add it to the startup info now
+ if( window != NULL )
+ {
+ if( myasn.isEmpty())
+ myasn = KStartupInfo::createNewStartupId();
+ if( myasn != "0" )
+ {
+ KStartupInfoId id;
+ id.initId( myasn );
+ KStartupInfoData data;
+ data.setLaunchedBy( window->winId());
+ KStartupInfo::sendChange( id, data );
+ }
+ }
+
int i = KApplication::startServiceByDesktopPath(
- _service.desktopEntryPath(), urls.toStringList(), &error, 0L, &pid
+ _service.desktopEntryPath(), urls.toStringList(), &error, 0L, &pid, myasn
);
if (i != 0)
@@ -800,33 +837,47 @@ pid_t KRun::run( const QString& _exec, const KURL::List& _urls, const QString& _
pid_t KRun::runCommand( QString cmd )
{
- return KRun::runCommand( cmd, QString::null, QString::null );
+ return KRun::runCommand( cmd, QString::null, QString::null, NULL, "" );
}
pid_t KRun::runCommand( const QString& cmd, const QString &execName, const QString & iconName )
{
+ return KRun::runCommand( cmd, execName, iconName, NULL, "" );
+}
+
+pid_t KRun::runCommand( const QString& cmd, const QString &execName, const QString & iconName,
+ QWidget* window, const QCString& asn )
+{
kdDebug(7010) << "runCommand " << cmd << "," << execName << endl;
KProcess * proc = new KProcess;
proc->setUseShell(true);
*proc << cmd;
KService::Ptr service = KService::serviceByDesktopName( binaryName( execName, true ) );
- return runCommandInternal( proc, service.data(), binaryName( execName, false ), execName, iconName );
+ return runCommandInternal( proc, service.data(), binaryName( execName, false ), execName, iconName,
+ window, asn );
}
KRun::KRun( const KURL& url, mode_t mode, bool isLocalFile, bool showProgressInfo )
:m_timer(0,"KRun::timer")
{
- init (url, 0, mode, isLocalFile, showProgressInfo);
+ init (url, 0, "", mode, isLocalFile, showProgressInfo);
}
KRun::KRun( const KURL& url, QWidget* window, mode_t mode, bool isLocalFile,
bool showProgressInfo )
:m_timer(0,"KRun::timer")
{
- init (url, window, mode, isLocalFile, showProgressInfo);
+ init (url, window, "", mode, isLocalFile, showProgressInfo);
+}
+
+KRun::KRun( const KURL& url, QWidget* window, const QCString& asn, mode_t mode, bool isLocalFile,
+ bool showProgressInfo )
+ :m_timer(0,"KRun::timer")
+{
+ init (url, window, asn, mode, isLocalFile, showProgressInfo);
}
-void KRun::init ( const KURL& url, QWidget* window, mode_t mode, bool isLocalFile,
+void KRun::init ( const KURL& url, QWidget* window, const QCString& asn, mode_t mode, bool isLocalFile,
bool showProgressInfo )
{
m_bFault = false;
@@ -842,6 +893,7 @@ void KRun::init ( const KURL& url, QWidget* window, mode_t mode, bool isLocalFil
d = new KRunPrivate;
d->m_runExecutables = true;
d->m_window = window;
+ d->m_asn = asn;
setEnableExternalBrowser(true);
// Start the timer. This means we will return to the event
@@ -942,7 +994,7 @@ void KRun::init()
KService::Ptr service = KService::serviceByStorageId( exec );
if (service)
{
- run( *service, urls );
+ run( *service, urls, d->m_window, d->m_asn );
ok = true;
}
}
@@ -1235,7 +1287,7 @@ void KRun::foundMimeType( const QString& type )
{
KURL::List lst;
lst.append( m_strURL );
- m_bFinished = KRun::run( *serv, lst );
+ m_bFinished = KRun::run( *serv, lst, d->m_window, d->m_asn );
/// Note: the line above means that if that service failed, we'll
/// go to runURL to maybe find another service, even though a dialog
/// box was displayed. That's good if runURL tries another service,
@@ -1250,7 +1302,7 @@ void KRun::foundMimeType( const QString& type )
m_strURL.setPath( d->m_localPath );
}
- if (!m_bFinished && KRun::runURL( m_strURL, type, false, d->m_runExecutables, d->m_suggestedFileName )){
+ if (!m_bFinished && KRun::runURL( m_strURL, type, d->m_window, d->m_asn, false, d->m_runExecutables, d->m_suggestedFileName )){
m_bFinished = true;
}
else{
diff --git a/kio/kio/krun.h b/kio/kio/krun.h
index c4f9bee0e..385b227af 100644
--- a/kio/kio/krun.h
+++ b/kio/kio/krun.h
@@ -111,6 +111,8 @@ public:
*/
KRun( const KURL& url, QWidget* window, mode_t mode = 0,
bool isLocalFile = false, bool showProgressInfo = true );
+ KRun( const KURL& url, QWidget* window, const QCString& asn, mode_t mode = 0,
+ bool isLocalFile = false, bool showProgressInfo = true );
/**
* Destructor. Don't call it yourself, since a KRun object auto-deletes
@@ -210,6 +212,8 @@ public:
* @since 3.5.2
*/
static pid_t run( const KService& _service, const KURL::List& _urls, QWidget* window, bool tempFiles = false );
+ static pid_t run( const KService& _service, const KURL::List& _urls, QWidget* window,
+ const QCString& asn, bool tempFiles = false );
/**
* Open a list of URLs with a certain service (application).
*
@@ -226,6 +230,8 @@ public:
/// @since 3.5.3
/// @internal
static pid_t run( const KService& _service, const KURL::List& _urls, QWidget* window, bool tempFiles, const QString& suggestedFileName );
+ static pid_t run( const KService& _service, const KURL::List& _urls, QWidget* window,
+ const QCString& asn, bool tempFiles, const QString& suggestedFileName );
/**
* Open a list of URLs with.
@@ -269,6 +275,7 @@ public:
static pid_t runURL( const KURL& _url, const QString& _mimetype );
/// @since 3.5.3
/// @internal
+ static pid_t runURL( const KURL& _url, const QString& _mimetype, QWidget* window, const QCString& asn, bool tempFile, bool runExecutables, const QString& suggestedFileName );
static pid_t runURL( const KURL& _url, const QString& _mimetype, bool tempFile, bool runExecutables, const QString& suggestedFileName );
/**
@@ -299,6 +306,8 @@ public:
* of running command) if command was unsafe for map notification.
*/
static pid_t runCommand( const QString& cmd, const QString & execName, const QString & icon );
+ static pid_t runCommand( const QString& cmd, const QString & execName, const QString & icon,
+ QWidget* window, const QCString& asn );
/**
* Display the Open-With dialog for those URLs, and run the chosen application.
@@ -438,7 +447,7 @@ protected:
virtual void virtual_hook( int id, void* data );
private:
- void init (const KURL& url, QWidget* window, mode_t mode,
+ void init (const KURL& url, QWidget* window, const QCString& asn, mode_t mode,
bool isLocalFile, bool showProgressInfo);
private:
class KRunPrivate;
diff --git a/kio/kio/kservice.cpp b/kio/kio/kservice.cpp
index bfb5ba2e7..d33e33530 100644
--- a/kio/kio/kservice.cpp
+++ b/kio/kio/kservice.cpp
@@ -97,6 +97,7 @@ KService::init( KDesktopFile *config )
m_bValid = true;
bool absPath = !QDir::isRelativePath(entryPath());
+ bool kde4application = config->fileName().startsWith("/usr/share/applications/kde4/");
config->setDesktopGroup();
@@ -196,9 +197,28 @@ KService::init( KDesktopFile *config )
name = name.left(pos);
m_strExec = config->readPathEntry( "Exec" );
+ if (kde4application && !m_strExec.startsWith("/")) {
+ m_strExec = "KDEHOME=$HOME/.kde XDG_DATA_DIRS=/usr/share KDEDIRS=/usr/ XDG_CONFIG_DIRS=/etc/xdg/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:$PATH "+m_strExec;
+ } else if (config->readBoolEntry("X-KDE-SubstituteUID")) {
+ int space = m_strExec.find(" ");
+ if (space==-1)
+ m_strExec = KStandardDirs::findExe(m_strExec);
+ else {
+ const QString command = m_strExec.left(space);
+ m_strExec.replace(command,KStandardDirs::findExe(command));
+ }
+ }
+
entryMap.remove("Exec");
m_strIcon = config->readEntry( "Icon", "unknown" );
+ if (kde4application) {
+ if (QFile::exists("/usr/share/icons/oxygen/22x22/apps/" + m_strIcon + ".png")) {
+ m_strIcon = "/usr/share/icons/oxygen/22x22/apps/" + m_strIcon + ".png";
+ } else if (QFile::exists("/usr/share/icons/hicolor/22x22/apps/" + m_strIcon + ".png")) {
+ m_strIcon = "/usr/share/icons/hicolor/22x22/apps/" + m_strIcon + ".png";
+ }
+ }
entryMap.remove("Icon");
m_bTerminal = (config->readBoolEntry( "Terminal" )); // should be a property IMHO
entryMap.remove("Terminal");
@@ -209,6 +229,9 @@ KService::init( KDesktopFile *config )
m_strComment = config->readEntry( "Comment" );
entryMap.remove("Comment");
m_strGenName = config->readEntry( "GenericName" );
+ if (kde4application) {
+ m_strGenName += " [KDE4]";
+ }
entryMap.remove("GenericName");
QString untranslatedGenericName = config->readEntryUntranslated( "GenericName" );
if (!untranslatedGenericName.isEmpty())
@@ -226,7 +249,8 @@ KService::init( KDesktopFile *config )
m_lstServiceTypes = config->readListEntry( "ServiceTypes" );
entryMap.remove("ServiceTypes");
// For compatibility with KDE 1.x
- m_lstServiceTypes += config->readListEntry( "MimeType", ';' );
+ if (!kde4application)
+ m_lstServiceTypes += config->readListEntry( "MimeType", ';' );
entryMap.remove("MimeType");
if ( m_strType == "Application" && !m_lstServiceTypes.contains("Application") )
@@ -245,6 +269,8 @@ KService::init( KDesktopFile *config )
m_DCOPServiceType = DCOP_None;
m_strDesktopEntryName = name.lower();
+ if (kde4application)
+ m_strDesktopEntryName = "kde4-" + m_strDesktopEntryName;
m_bAllowAsDefault = config->readBoolEntry( "AllowDefault", true );
entryMap.remove("AllowDefault");
@@ -260,7 +286,10 @@ KService::init( KDesktopFile *config )
for( ; it != entryMap.end();++it)
{
//qDebug(" Key = %s Data = %s", it.key().latin1(), it.data().latin1());
- m_mapProps.insert( it.key(), QVariant( it.data()));
+ QString key = it.key();
+ if (kde4application && key=="OnlyShowIn" && it.data()=="KDE;")
+ key = "NotShowIn";
+ m_mapProps.insert( key, QVariant( it.data()));
}
}
diff --git a/kio/kio/kurlcompletion.cpp b/kio/kio/kurlcompletion.cpp
index 72a41d9a3..cddd9fa79 100644
--- a/kio/kio/kurlcompletion.cpp
+++ b/kio/kio/kurlcompletion.cpp
@@ -231,6 +231,9 @@ void DirectoryListThread::run()
while ( !terminationRequested() &&
(dirEntry = ::readdir( dir)))
#else
+#if !defined(MAXPATHLEN) && defined(__GNU__)
+#define MAXPATHLEN UCHAR_MAX
+#endif
struct dirent *dirPosition = (struct dirent *) malloc( sizeof( struct dirent ) + MAXPATHLEN + 1 );
struct dirent *dirEntry = 0;
while ( !terminationRequested() &&
diff --git a/kio/kpasswdserver/Makefile.am b/kio/kpasswdserver/Makefile.am
index fcc3e2b1b..4ddb85be4 100644
--- a/kio/kpasswdserver/Makefile.am
+++ b/kio/kpasswdserver/Makefile.am
@@ -10,6 +10,6 @@ kde_module_LTLIBRARIES = kded_kpasswdserver.la
kded_kpasswdserver_la_SOURCES = kpasswdserver.cpp kpasswdserver.skel
kded_kpasswdserver_la_METASOURCES = AUTO
kded_kpasswdserver_la_LDFLAGS = $(all_libraries) -module -avoid-version
-kded_kpasswdserver_la_LIBADD = $(top_builddir)/kwallet/client/libkwalletclient.la $(LIB_KIO) $(LIB_KDED)
+kded_kpasswdserver_la_LIBADD = $(top_builddir)/kwallet/client/libkwalletclient.la $(LIB_KIO) $(LIB_KDED) $(LIB_QT) $(LIB_KDEUI) $(LIB_KDECORE) $(top_builddir)/dcop/libDCOP.la $(LIB_X11) $(top_builddir)/kded/libkdeinit_kded.la
include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kio/misc/Makefile.am b/kio/misc/Makefile.am
index 5dab3a23e..6dc6bcd60 100644
--- a/kio/misc/Makefile.am
+++ b/kio/misc/Makefile.am
@@ -29,7 +29,7 @@ bin_PROGRAMS = kmailservice ktelnetservice
observer_DIR = $(top_srcdir)/kio/kio
kio_uiserver_la_SOURCES = uiserver.cpp uiserver.skel observer.stub
-kio_uiserver_la_LIBADD = $(LIB_KIO)
+kio_uiserver_la_LIBADD = $(LIB_KIO) $(LIB_KDEUI) $(LIB_QT) $(top_builddir)/dcop/libDCOP.la $(LIB_KDECORE)
kio_uiserver_la_LDFLAGS = $(all_libraries) -module -avoid-version
METASOURCES = AUTO
diff --git a/kio/misc/fileshareset b/kio/misc/fileshareset
index f73e5f008..4c921ba38 100755
--- a/kio/misc/fileshareset
+++ b/kio/misc/fileshareset
@@ -285,7 +285,12 @@ sub update_server {
system('PATH=/bin:/sbin pidof nfsd >/dev/null') != 0) {
# trying to start the server...
system('/etc/init.d/portmap start') if system('/etc/init.d/portmap status') != 0;
- system('/etc/init.d/nfs', $_) foreach 'stop', 'start';
+ if ( -f '/etc/init.d/nfs' ) {
+ system('/etc/init.d/nfs', $_) foreach 'stop', 'start';
+ }
+ elsif ( -f '/etc/init.d/nfs-kernel-server' ) {
+ system('/etc/init.d/nfs-kernel-server', $_) foreach 'stop', 'start';
+ }
}
exit 0;
}
diff --git a/kio/misc/kdesasl/Makefile.am b/kio/misc/kdesasl/Makefile.am
index 854757d37..4020a966c 100644
--- a/kio/misc/kdesasl/Makefile.am
+++ b/kio/misc/kdesasl/Makefile.am
@@ -8,5 +8,5 @@ kdesaslinclude_HEADERS = kdesasl.h
libkdesasl_la_SOURCES = kdesasl.cpp
libkdesasl_la_LDFLAGS = $(all_libraries) -version-info 3:0:2 -no-undefined
-libkdesasl_la_LIBADD = $(LIB_KDECORE)
+libkdesasl_la_LIBADD = $(LIB_KDECORE) $(LIB_QT)
diff --git a/kio/misc/kntlm/Makefile.am b/kio/misc/kntlm/Makefile.am
index 192ddc0af..7136310d9 100644
--- a/kio/misc/kntlm/Makefile.am
+++ b/kio/misc/kntlm/Makefile.am
@@ -8,5 +8,5 @@ kntlminclude_HEADERS = kntlm.h
libkntlm_la_SOURCES = kntlm.cpp des.cpp
libkntlm_la_LDFLAGS = $(all_libraries) -version-info 0:0:0 -no-undefined
-libkntlm_la_LIBADD = $(LIB_KDECORE)
+libkntlm_la_LIBADD = $(LIB_KDECORE) $(LIB_QT)
diff --git a/kio/misc/kpac/Makefile.am b/kio/misc/kpac/Makefile.am
index 173071318..33d7d0196 100644
--- a/kio/misc/kpac/Makefile.am
+++ b/kio/misc/kpac/Makefile.am
@@ -10,7 +10,9 @@ KDE_CXXFLAGS = $(USE_EXCEPTIONS)
kded_proxyscout_la_SOURCES = proxyscout.skel proxyscout.cpp script.cpp \
downloader.cpp discovery.cpp
kded_proxyscout_la_LDFLAGS = $(all_libraries) -module -avoid-version
-kded_proxyscout_la_LIBADD = $(LIB_KIO) $(top_builddir)/kjs/libkjs.la $(LIB_KDED)
+kded_proxyscout_la_LIBADD = $(LIB_KIO) $(top_builddir)/kjs/libkjs.la $(LIB_KDED) $(LIB_QT) \
+ $(top_builddir)/dcop/libDCOP.la $(top_builddir)/kded/libkdeinit_kded.la \
+ $(LIB_KDECORE) $(LIBRESOLV)
kpac_dhcp_helper_SOURCES = kpac_dhcp_helper.c
kpac_dhcp_helper_CFLAGS = $(KDE_USE_FPIE)
diff --git a/kio/misc/kssld/Makefile.am b/kio/misc/kssld/Makefile.am
index 63252f46c..24faf2e28 100644
--- a/kio/misc/kssld/Makefile.am
+++ b/kio/misc/kssld/Makefile.am
@@ -21,7 +21,7 @@ INCLUDES= -I$(srcdir)/.. -I$(top_srcdir) $(SSL_INCLUDES) -I$(top_srcdir)/kio/kss
kde_module_LTLIBRARIES = kded_kssld.la
kded_kssld_la_LDFLAGS = $(all_libraries) -module -avoid-version
-kded_kssld_la_LIBADD = $(LIB_KIO) $(LIB_KDED)
+kded_kssld_la_LIBADD = $(LIB_KIO) $(LIB_KDED) $(LIB_QT) $(top_builddir)/dcop/libDCOP.la $(top_builddir)/kded/libkdeinit_kded.la $(LIB_KDECORE)
kded_kssld_la_SOURCES = kssld.cpp kssld.skel
METASOURCES = AUTO
diff --git a/kio/misc/kwalletd/Makefile.am b/kio/misc/kwalletd/Makefile.am
index f57f2c692..1c198c46e 100644
--- a/kio/misc/kwalletd/Makefile.am
+++ b/kio/misc/kwalletd/Makefile.am
@@ -21,7 +21,7 @@ INCLUDES= -I$(srcdir)/.. -I$(top_srcdir) -I$(top_srcdir)/kwallet/backend -I$(top
kde_module_LTLIBRARIES = kded_kwalletd.la
kded_kwalletd_la_LDFLAGS = $(all_libraries) -module -avoid-version
-kded_kwalletd_la_LIBADD = $(LIB_KIO) ../../../kwallet/backend/libkwalletbackend.la ../../../kwallet/client/libkwalletclient.la $(LIB_KDED)
+kded_kwalletd_la_LIBADD = $(LIB_KIO) ../../../kwallet/backend/libkwalletbackend.la ../../../kwallet/client/libkwalletclient.la $(LIB_KDED) $(LIB_QT) $(top_builddir)/dcop/libDCOP.la $(LIB_KDECORE) $(LIB_KDEUI) $(top_builddir)/kded/libkdeinit_kded.la
kded_kwalletd_la_SOURCES = kwalletd.cpp kwalletd.skel ktimeout.cpp kwalletwizard.ui kbetterthankdialogbase.ui
METASOURCES = AUTO
diff --git a/kio/misc/kwalletd/kwalletd.cpp b/kio/misc/kwalletd/kwalletd.cpp
index 686a99d6f..3fa32ff71 100644
--- a/kio/misc/kwalletd/kwalletd.cpp
+++ b/kio/misc/kwalletd/kwalletd.cpp
@@ -829,6 +829,12 @@ bool KWalletD::removeFolder(int handle, const QString& f) {
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
bool rc = b->removeFolder(f);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
QByteArray data;
QDataStream ds(data, IO_WriteOnly);
ds << b->walletName();
@@ -845,6 +851,12 @@ bool KWalletD::createFolder(int handle, const QString& f) {
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
bool rc = b->createFolder(f);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
QByteArray data;
QDataStream ds(data, IO_WriteOnly);
ds << b->walletName();
@@ -987,6 +999,12 @@ int KWalletD::writeMap(int handle, const QString& folder, const QString& key, co
e.setValue(value);
e.setType(KWallet::Wallet::Map);
b->writeEntry(&e);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
emitFolderUpdated(b->walletName(), folder);
return 0;
}
@@ -1005,6 +1023,12 @@ int KWalletD::writeEntry(int handle, const QString& folder, const QString& key,
e.setValue(value);
e.setType(KWallet::Wallet::EntryType(entryType));
b->writeEntry(&e);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
emitFolderUpdated(b->walletName(), folder);
return 0;
}
@@ -1023,6 +1047,12 @@ int KWalletD::writeEntry(int handle, const QString& folder, const QString& key,
e.setValue(value);
e.setType(KWallet::Wallet::Stream);
b->writeEntry(&e);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
emitFolderUpdated(b->walletName(), folder);
return 0;
}
@@ -1041,6 +1071,12 @@ int KWalletD::writePassword(int handle, const QString& folder, const QString& ke
e.setValue(value);
e.setType(KWallet::Wallet::Password);
b->writeEntry(&e);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
emitFolderUpdated(b->walletName(), folder);
return 0;
}
@@ -1090,6 +1126,12 @@ int KWalletD::removeEntry(int handle, const QString& folder, const QString& key)
}
b->setFolder(folder);
bool rc = b->removeEntry(key);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
emitFolderUpdated(b->walletName(), folder);
return rc ? 0 : -3;
}
@@ -1183,6 +1225,12 @@ int KWalletD::renameEntry(int handle, const QString& folder, const QString& oldN
if ((b = getWallet(friendlyDCOPPeerName(), handle))) {
b->setFolder(folder);
int rc = b->renameEntry(oldName, newName);
+ // write changes to disk immediately
+ QByteArray p;
+ QString wallet = b->walletName();
+ p.duplicate(_passwords[wallet].data(), _passwords[wallet].length());
+ b->sync(p);
+ p.fill(0);
emitFolderUpdated(b->walletName(), folder);
return rc;
}