add more spacing
[personal-kdebase.git] / runtime / kioexec / main.cpp
blob1f8d346b576830b1d7104a625da15244c47ad30d
1 /* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 Copyright (C) 2000-2005 David Faure <faure@kde.org>
4 Copyright (C) 2001 Waldo Bastian <bastian@kde.org>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
22 #include <QtCore/QFile>
23 #include <QtCore/Q_PID>
25 #include <kapplication.h>
26 #include <kdeversion.h>
27 #include <kstandarddirs.h>
28 #include <kdebug.h>
29 #include <kmessagebox.h>
30 #include <kio/job.h>
31 #include <krun.h>
32 #include <kio/netaccess.h>
33 #include <kservice.h>
34 #include <klocale.h>
35 #include <kcmdlineargs.h>
36 #include <kaboutdata.h>
37 #include <kstartupinfo.h>
38 #include <kshell.h>
39 #include <kde_file.h>
42 #include "main.h"
45 static const char description[] =
46 I18N_NOOP("KIO Exec - Opens remote files, watches modifications, asks for upload");
49 KIOExec::KIOExec()
50 : mExited(false)
52 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
53 if (args->count() < 1)
54 KCmdLineArgs::usageError(i18n("'command' expected.\n"));
56 tempfiles = args->isSet("tempfiles");
57 if ( args->isSet( "suggestedfilename" ) )
58 suggestedFileName = args->getOption( "suggestedfilename" );
59 expectedCounter = 0;
60 jobCounter = 0;
61 command = args->arg(0);
62 kDebug() << "command=" << command;
64 for ( int i = 1; i < args->count(); i++ )
66 KUrl url = args->url(i);
67 url = KIO::NetAccess::mostLocalUrl( url, 0 );
69 //kDebug() << "url=" << url.url() << " filename=" << url.fileName();
70 // A local file, not an URL ?
71 // => It is not encoded and not shell escaped, too.
72 if ( url.isLocalFile() )
74 FileInfo file;
75 file.path = url.path();
76 file.url = url;
77 fileList.append(file);
79 // It is an URL
80 else
82 if ( !url.isValid() )
83 KMessageBox::error( 0L, i18n( "The URL %1\nis malformed" , url.url() ) );
84 else if ( tempfiles )
85 KMessageBox::error( 0L, i18n( "Remote URL %1\nnot allowed with --tempfiles switch" , url.url() ) );
86 else
87 // We must fetch the file
89 QString fileName = KIO::encodeFileName( url.fileName() );
90 if ( !suggestedFileName.isEmpty() )
91 fileName = suggestedFileName;
92 // Build the destination filename, in ~/.kde/cache-*/krun/
93 // Unlike KDE-1.1, we put the filename at the end so that the extension is kept
94 // (Some programs rely on it)
95 QString tmp = KGlobal::dirs()->saveLocation( "cache", "krun/" ) +
96 QString("%1.%2.%3").arg(getpid()).arg(jobCounter++).arg(fileName);
97 FileInfo file;
98 file.path = tmp;
99 file.url = url;
100 fileList.append(file);
102 expectedCounter++;
103 KUrl dest;
104 dest.setPath( tmp );
105 kDebug() << "Copying " << url.prettyUrl() << " to " << dest;
106 KIO::Job *job = KIO::file_copy( url, dest );
107 jobList.append( job );
109 connect( job, SIGNAL( result( KJob * ) ), SLOT( slotResult( KJob * ) ) );
113 args->clear();
115 if ( tempfiles )
117 slotRunApp();
118 return;
121 counter = 0;
122 if ( counter == expectedCounter )
123 slotResult( 0L );
126 void KIOExec::slotResult( KJob * job )
128 if (job && job->error())
130 // That error dialog would be queued, i.e. not immediate...
131 //job->showErrorDialog();
132 if ( (job->error() != KIO::ERR_USER_CANCELED) )
133 KMessageBox::error( 0L, job->errorString() );
135 QString path = static_cast<KIO::FileCopyJob*>(job)->destUrl().path();
137 QList<FileInfo>::Iterator it = fileList.begin();
138 for(;it != fileList.end(); ++it)
140 if ((*it).path == path)
141 break;
144 if ( it != fileList.end() )
145 fileList.erase( it );
146 else
147 kDebug() << path << " not found in list";
150 counter++;
152 if ( counter < expectedCounter )
153 return;
155 kDebug() << "All files downloaded, will call slotRunApp shortly";
156 // We know we can run the app now - but let's finish the job properly first.
157 QTimer::singleShot( 0, this, SLOT( slotRunApp() ) );
159 jobList.clear();
162 void KIOExec::slotRunApp()
164 if ( fileList.isEmpty() ) {
165 kDebug() << "No files downloaded -> exiting";
166 mExited = true;
167 QApplication::exit(1);
168 return;
171 KService service("dummy", command, QString());
173 KUrl::List list;
174 // Store modification times
175 QList<FileInfo>::Iterator it = fileList.begin();
176 for ( ; it != fileList.end() ; ++it )
178 KDE_struct_stat buff;
179 (*it).time = KDE_stat( QFile::encodeName((*it).path), &buff ) ? 0 : buff.st_mtime;
180 KUrl url;
181 url.setPath((*it).path);
182 list << url;
185 QStringList params = KRun::processDesktopExec(service, list);
187 kDebug() << "EXEC " << KShell::joinArgs( params );
189 #ifdef Q_WS_X11
190 // propagate the startup identification to the started process
191 KStartupInfoId id;
192 id.initId( kapp->startupId());
193 id.setupStartupEnv();
194 #endif
196 QString exe( params.takeFirst() );
197 const int exit_code = QProcess::execute( exe, params );
199 #ifdef Q_WS_X11
200 KStartupInfo::resetStartupEnv();
201 #endif
203 kDebug() << "EXEC done";
205 // Test whether one of the files changed
206 it = fileList.begin();
207 for( ;it != fileList.end(); ++it )
209 KDE_struct_stat buff;
210 QString src = (*it).path;
211 KUrl dest = (*it).url;
212 if ( (KDE_stat( QFile::encodeName(src), &buff ) == 0) &&
213 ((*it).time != buff.st_mtime) )
215 if ( tempfiles )
217 if ( KMessageBox::questionYesNo( 0L,
218 i18n( "The supposedly temporary file\n%1\nhas been modified.\nDo you still want to delete it?" , dest.prettyUrl()),
219 i18n( "File Changed" ), KStandardGuiItem::del(), KGuiItem(i18n("Do Not Delete")) ) != KMessageBox::Yes )
220 continue; // don't delete the temp file
222 else if ( ! dest.isLocalFile() ) // no upload when it's already a local file
224 if ( KMessageBox::questionYesNo( 0L,
225 i18n( "The file\n%1\nhas been modified.\nDo you want to upload the changes?" , dest.prettyUrl()),
226 i18n( "File Changed" ), KGuiItem(i18n("Upload")), KGuiItem(i18n("Do Not Upload")) ) == KMessageBox::Yes )
228 kDebug() << "src='" << src << "' dest='" << dest << "'";
229 // Do it the synchronous way.
230 if ( !KIO::NetAccess::upload( src, dest, 0 ) )
232 KMessageBox::error( 0L, KIO::NetAccess::lastErrorString() );
233 continue; // don't delete the temp file
239 if ((!dest.isLocalFile() || tempfiles) && exit_code == 0) {
240 // Wait for a reasonable time so that even if the application forks on startup (like OOo or amarok)
241 // it will have time to start up and read the file before it gets deleted. #130709.
242 kDebug() << "sleeping...";
243 sleep(180); // 3 mn
244 kDebug() << "about to delete " << src;
245 unlink( QFile::encodeName(src) );
249 mExited = true;
250 QApplication::exit(exit_code);
253 int main( int argc, char **argv )
255 KAboutData aboutData( "kioexec", "kioexec", ki18n("KIOExec"),
256 KDE_VERSION_STRING, ki18n(description), KAboutData::License_GPL,
257 ki18n("(c) 1998-2000,2003 The KFM/Konqueror Developers"));
258 aboutData.addAuthor(ki18n("David Faure"),KLocalizedString(), "faure@kde.org");
259 aboutData.addAuthor(ki18n("Stephan Kulow"),KLocalizedString(), "coolo@kde.org");
260 aboutData.addAuthor(ki18n("Bernhard Rosenkraenzer"),KLocalizedString(), "bero@arklinux.org");
261 aboutData.addAuthor(ki18n("Waldo Bastian"),KLocalizedString(), "bastian@kde.org");
262 aboutData.addAuthor(ki18n("Oswald Buddenhagen"),KLocalizedString(), "ossi@kde.org");
264 KCmdLineArgs::init( argc, argv, &aboutData );
266 KCmdLineOptions options;
267 options.add("tempfiles", ki18n("Treat URLs as local files and delete them afterwards"));
268 options.add("suggestedfilename <file name>", ki18n("Suggested file name for the downloaded file"));
269 options.add("+command", ki18n("Command to execute"));
270 options.add("+[URLs]", ki18n("URL(s) or local file(s) used for 'command'"));
271 KCmdLineArgs::addCmdLineOptions( options );
273 KApplication app;
274 app.setQuitOnLastWindowClosed(false);
276 KIOExec exec;
278 // Don't go into the event loop if we already want to exit (#172197)
279 if (exec.exited())
280 return 0;
282 return app.exec();
285 #include "main.moc"