TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

295 lines
10 KiB

  1. /* This file is part of the KDE project
  2. Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
  3. Copyright (C) 2000 David Faure <faure@kde.org>
  4. Copyright (C) 2001 Waldo Bastian <bastian@kde.org>
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; see the file COPYING. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA.
  17. */
  18. #include <config.h>
  19. #include <unistd.h>
  20. #include <stdlib.h>
  21. #include <sys/stat.h>
  22. #include <tqfile.h>
  23. #include <tdeapplication.h>
  24. #include <kstandarddirs.h>
  25. #include <kdebug.h>
  26. #include <tdemessagebox.h>
  27. #include <tdeio/job.h>
  28. #include <krun.h>
  29. #include <tdeio/netaccess.h>
  30. #include <kprocess.h>
  31. #include <kservice.h>
  32. #include <tdelocale.h>
  33. #include <tdecmdlineargs.h>
  34. #include <tdeaboutdata.h>
  35. #include <tdestartupinfo.h>
  36. #include <kshell.h>
  37. #include <kde_file.h>
  38. #include "main.h"
  39. static const char description[] =
  40. I18N_NOOP("TDEIO Exec - Opens remote files, watches modifications, asks for upload");
  41. static TDECmdLineOptions options[] =
  42. {
  43. { "tempfiles", I18N_NOOP("Treat URLs as local files and delete them afterwards"), 0 },
  44. { "suggestedfilename <file name>", I18N_NOOP("Suggested file name for the downloaded file"), 0 },
  45. { "+command", I18N_NOOP("Command to execute"), 0 },
  46. { "+[URLs]", I18N_NOOP("URL(s) or local file(s) used for 'command'"), 0 },
  47. TDECmdLineLastOption
  48. };
  49. int jobCounter = 0;
  50. TQPtrList<TDEIO::Job>* jobList = 0L;
  51. KIOExec::KIOExec()
  52. {
  53. jobList = new TQPtrList<TDEIO::Job>;
  54. jobList->setAutoDelete( false ); // jobs autodelete themselves
  55. TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
  56. if (args->count() < 1)
  57. TDECmdLineArgs::usage(i18n("'command' expected.\n"));
  58. tempfiles = args->isSet("tempfiles");
  59. if ( args->isSet( "suggestedfilename" ) )
  60. suggestedFileName = TQString::fromLocal8Bit( args->getOption( "suggestedfilename" ) );
  61. expectedCounter = 0;
  62. command = args->arg(0);
  63. kdDebug() << "command=" << command << endl;
  64. for ( int i = 1; i < args->count(); i++ )
  65. {
  66. KURL url = args->url(i);
  67. // we need to map system:/ etc to make sure we get this right
  68. url = TDEIO::NetAccess::mostLocalURL( url, 0 );
  69. //kdDebug() << "url=" << url.url() << " filename=" << url.fileName() << endl;
  70. // A local file, not an URL ?
  71. // => It is not encoded and not shell escaped, too.
  72. if ( url.isLocalFile() )
  73. {
  74. fileInfo file;
  75. file.path = url.path();
  76. file.url = url;
  77. fileList.append(file);
  78. }
  79. // It is an URL
  80. else
  81. {
  82. if ( !url.isValid() )
  83. KMessageBox::error( 0L, i18n( "The URL %1\nis malformed" ).arg( url.url() ) );
  84. else if ( tempfiles )
  85. KMessageBox::error( 0L, i18n( "Remote URL %1\nnot allowed with --tempfiles switch" ).arg( url.url() ) );
  86. else
  87. // We must fetch the file
  88. {
  89. TQString fileName = TDEIO::encodeFileName( url.fileName() );
  90. if ( !suggestedFileName.isEmpty() )
  91. fileName = suggestedFileName;
  92. // Build the destination filename, in ~/.trinity/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. TQString tmp = TDEGlobal::dirs()->saveLocation( "cache", "krun/" ) +
  96. TQString("%1.%2.%3").arg(getpid()).arg(jobCounter++).arg(fileName);
  97. fileInfo file;
  98. file.path = tmp;
  99. file.url = url;
  100. fileList.append(file);
  101. expectedCounter++;
  102. KURL dest;
  103. dest.setPath( tmp );
  104. kdDebug() << "Copying " << url.prettyURL() << " to " << dest << endl;
  105. TDEIO::Job *job = TDEIO::file_copy( url, dest );
  106. jobList->append( job );
  107. connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), TQT_SLOT( slotResult( TDEIO::Job * ) ) );
  108. }
  109. }
  110. }
  111. args->clear();
  112. if ( tempfiles ) {
  113. // #113991
  114. TQTimer::singleShot( 0, this, TQT_SLOT( slotRunApp() ) );
  115. //slotRunApp(); // does not return
  116. return;
  117. }
  118. counter = 0;
  119. if ( counter == expectedCounter )
  120. slotResult( 0L );
  121. }
  122. void KIOExec::slotResult( TDEIO::Job * job )
  123. {
  124. if (job && job->error())
  125. {
  126. // That error dialog would be queued, i.e. not immediate...
  127. //job->showErrorDialog();
  128. if ( (job->error() != TDEIO::ERR_USER_CANCELED) )
  129. KMessageBox::error( 0L, job->errorString() );
  130. TQString path = static_cast<TDEIO::FileCopyJob*>(job)->destURL().path();
  131. TQValueList<fileInfo>::Iterator it = fileList.begin();
  132. for(;it != fileList.end(); ++it)
  133. {
  134. if ((*it).path == path)
  135. break;
  136. }
  137. if ( it != fileList.end() )
  138. fileList.remove( it );
  139. else
  140. kdDebug() << static_cast<TDEIO::FileCopyJob*>(job)->destURL().path() << " not found in list" << endl;
  141. }
  142. counter++;
  143. if ( counter < expectedCounter )
  144. return;
  145. kdDebug() << "All files downloaded, will call slotRunApp shortly" << endl;
  146. // We know we can run the app now - but let's finish the job properly first.
  147. TQTimer::singleShot( 0, this, TQT_SLOT( slotRunApp() ) );
  148. jobList->clear();
  149. }
  150. void KIOExec::slotRunApp()
  151. {
  152. if ( fileList.isEmpty() ) {
  153. kdDebug() << k_funcinfo << "No files downloaded -> exiting" << endl;
  154. exit(1);
  155. }
  156. KService service("dummy", command, TQString::null);
  157. KURL::List list;
  158. // Store modification times
  159. TQValueList<fileInfo>::Iterator it = fileList.begin();
  160. for ( ; it != fileList.end() ; ++it )
  161. {
  162. KDE_struct_stat buff;
  163. (*it).time = KDE_stat( TQFile::encodeName((*it).path), &buff ) ? 0 : buff.st_mtime;
  164. KURL url;
  165. url.setPath((*it).path);
  166. list << url;
  167. }
  168. TQStringList params = KRun::processDesktopExec(service, list, false /*no shell*/);
  169. kdDebug() << "EXEC " << KShell::joinArgs( params ) << endl;
  170. #ifdef Q_WS_X11
  171. // propagate the startup indentification to the started process
  172. TDEStartupInfoId id;
  173. id.initId( kapp->startupId());
  174. id.setupStartupEnv();
  175. #endif
  176. TDEProcess proc;
  177. proc << params;
  178. proc.start( TDEProcess::Block );
  179. #ifdef Q_WS_X11
  180. TDEStartupInfo::resetStartupEnv();
  181. #endif
  182. kdDebug() << "EXEC done" << endl;
  183. // Test whether one of the files changed
  184. it = fileList.begin();
  185. for( ;it != fileList.end(); ++it )
  186. {
  187. KDE_struct_stat buff;
  188. TQString src = (*it).path;
  189. KURL dest = (*it).url;
  190. if ( (KDE_stat( TQFile::encodeName(src), &buff ) == 0) &&
  191. ((*it).time != buff.st_mtime) )
  192. {
  193. if ( tempfiles )
  194. {
  195. if ( KMessageBox::questionYesNo( 0L,
  196. i18n( "The supposedly temporary file\n%1\nhas been modified.\nDo you still want to delete it?" ).arg(dest.prettyURL()),
  197. i18n( "File Changed" ), KStdGuiItem::del(), i18n("Do Not Delete") ) != KMessageBox::Yes )
  198. continue; // don't delete the temp file
  199. }
  200. else if ( ! dest.isLocalFile() ) // no upload when it's already a local file
  201. {
  202. if ( KMessageBox::questionYesNo( 0L,
  203. i18n( "The file\n%1\nhas been modified.\nDo you want to upload the changes?" ).arg(dest.prettyURL()),
  204. i18n( "File Changed" ), i18n("Upload"), i18n("Do Not Upload") ) == KMessageBox::Yes )
  205. {
  206. kdDebug() << TQString(TQString("src='%1' dest='%2'").arg(src).arg(dest.url())).ascii() << endl;
  207. // Do it the synchronous way.
  208. if ( !TDEIO::NetAccess::upload( src, dest, 0 ) )
  209. {
  210. KMessageBox::error( 0L, TDEIO::NetAccess::lastErrorString() );
  211. continue; // don't delete the temp file
  212. }
  213. }
  214. }
  215. }
  216. if ( !dest.isLocalFile() || tempfiles ) {
  217. // Wait for a reasonable time so that even if the application forks on startup (like OOo or amarok)
  218. // it will have time to start up and read the file before it gets deleted. #130709.
  219. kdDebug() << "sleeping..." << endl;
  220. sleep(180); // 3 mn
  221. kdDebug() << "about to delete " << src << endl;
  222. unlink( TQFile::encodeName(src) );
  223. }
  224. }
  225. //kapp->quit(); not efficient enough
  226. exit(0);
  227. }
  228. int main( int argc, char **argv )
  229. {
  230. TDEAboutData aboutData( "tdeioexec", I18N_NOOP("KIOExec"),
  231. VERSION, description, TDEAboutData::License_GPL,
  232. "(c) 1998-2000,2003 The KFM/Konqueror Developers");
  233. aboutData.addAuthor("David Faure",0, "faure@kde.org");
  234. aboutData.addAuthor("Stephan Kulow",0, "coolo@kde.org");
  235. aboutData.addAuthor("Bernhard Rosenkraenzer",0, "bero@arklinux.org");
  236. aboutData.addAuthor("Waldo Bastian",0, "bastian@kde.org");
  237. aboutData.addAuthor("Oswald Buddenhagen",0, "ossi@kde.org");
  238. TDECmdLineArgs::init( argc, argv, &aboutData );
  239. TDECmdLineArgs::addCmdLineOptions( options );
  240. TDEApplication app;
  241. KIOExec exec;
  242. kdDebug() << "Constructor returned..." << endl;
  243. return app.exec();
  244. }
  245. #include "main.moc"