1 /* This file is part of the KDE project
2 Copyright (C) 1999-2006 David Faure <faure@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 #include "kioclient.h"
21 #include <ktoolinvocation.h>
23 #include <kio/copyjob.h>
24 #include <kio/jobuidelegate.h>
25 #include <kcmdlineargs.h>
26 #include <kpropertiesdialog.h>
28 #include <kstandarddirs.h>
29 #include <kurlrequesterdialog.h>
30 #include <kmessagebox.h>
31 #include <kmimetypetrader.h>
32 #include <kfiledialog.h>
37 #include <QtDBus/QtDBus>
38 #include <kcomponentdata.h>
41 static const char appName
[] = "kioclient";
42 static const char programName
[] = I18N_NOOP("KIO Client");
43 static const char description
[] = I18N_NOOP("Command-line tool for network-transparent operations");
44 static const char version
[] = "2.0";
46 bool ClientApp::m_ok
= true;
47 static bool s_interactive
= true;
48 static KIO::JobFlags s_jobFlags
= KIO::DefaultFlags
;
50 #ifdef KIOCLIENT_AS_KIOCLIENT
53 KCmdLineArgs::enable_i18n();
54 puts(i18n("\nSyntax:\n").toLocal8Bit());
55 puts(i18n(" kioclient openProperties 'url'\n"
56 " # Opens a properties menu\n\n").toLocal8Bit());
57 puts(i18n(" kioclient exec 'url' ['mimetype']\n"
58 " # Tries to open the document pointed to by 'url', in the application\n"
59 " # associated with it in KDE. You may omit 'mimetype'.\n"
60 " # In this case the mimetype is determined\n"
61 " # automatically. Of course URL may be the URL of a\n"
62 " # document, or it may be a *.desktop file.\n").toLocal8Bit());
63 puts(i18n(" kioclient move 'src' 'dest'\n"
64 " # Moves the URL 'src' to 'dest'.\n"
65 " # 'src' may be a list of URLs.\n").toLocal8Bit());
66 //puts(i18n(" # 'dest' may be \"trash:/\" to move the files\n"
67 // " # in the trash bin.\n\n").toLocal8Bit());
68 puts(i18n(" kioclient download ['src']\n"
69 " # Copies the URL 'src' to a user-specified location'.\n"
70 " # 'src' may be a list of URLs, if not present then\n"
71 " # a URL will be requested.\n\n").toLocal8Bit());
72 puts(i18n(" kioclient copy 'src' 'dest'\n"
73 " # Copies the URL 'src' to 'dest'.\n"
74 " # 'src' may be a list of URLs.\n\n").toLocal8Bit());
75 puts(i18n(" kioclient cat 'url'\n"
76 " # Writes out the contents of 'url' to stdout\n\n").toLocal8Bit());
78 puts(i18n("*** Examples:\n"
79 " kioclient exec file:/root/Desktop/cdrom.desktop \"Mount default\"\n"
80 " // Mounts the CDROM\n\n").toLocal8Bit());
81 puts(i18n(" kioclient exec file:/home/weis/data/test.html\n"
82 " // Opens the file with default binding\n\n").toLocal8Bit());
83 puts(i18n(" kioclient exec file:/home/weis/data/test.html Netscape\n"
84 " // Opens the file with netscape\n\n").toLocal8Bit());
85 puts(i18n(" kioclient exec ftp://localhost/\n"
86 " // Opens new window with URL\n\n").toLocal8Bit());
87 puts(i18n(" kioclient exec file:/root/Desktop/emacs.desktop\n"
88 " // Starts emacs\n\n").toLocal8Bit());
89 puts(i18n(" kioclient exec file:/root/Desktop/cdrom.desktop\n"
90 " // Opens the CDROM's mount directory\n\n").toLocal8Bit());
91 puts(i18n(" kioclient exec .\n"
92 " // Opens the current directory. Very convenient.\n\n").toLocal8Bit());
96 int main( int argc
, char **argv
)
98 KCmdLineArgs::init(argc
, argv
, appName
, 0, ki18n(programName
), version
, ki18n(description
), false);
101 KCmdLineOptions options
;
102 options
.add("noninteractive", ki18n("Non-interactive use: no message boxes"));
103 #if defined(KIOCLIENT_AS_KDEOPEN)
104 options
.add("+urls", ki18n("URL or URLs"));
105 #elif defined(KIOCLIENT_AS_KDECP)
106 options
.add("+src", ki18n("Source URL or URLs"));
107 options
.add("+dest", ki18n("Destination URL"));
108 #elif defined(KIOCLIENT_AS_KDEMV)
109 options
.add("+src", ki18n("Source URL or URLs"));
110 options
.add("+dest", ki18n("Destination URL"));
111 #elif defined(KIOCLIENT_AS_KIOCLIENT)
112 options
.add("commands", ki18n("Show available commands"));
113 options
.add("+command", ki18n("Command (see --commands)"));
114 options
.add("+[URL(s)]", ki18n("Arguments for command"));
117 KCmdLineArgs::addCmdLineOptions( options
);
118 KCmdLineArgs::addTempFileOption();
120 #ifdef KIOCLIENT_AS_KIOCLIENT
121 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
123 if ( argc
== 1 || args
->isSet("commands") )
130 return ClientApp::doIt() ? 0 /*no error*/ : 1 /*error*/;
133 bool krun_has_error
= false;
135 void ClientApp::delayedQuit()
137 // Quit in 2 seconds. This leaves time for KRun to pop up
138 // "app not found" in KProcessRunner, if that was the case.
139 QTimer::singleShot( 2000, this, SLOT(deref()) );
140 // don't access the KRun instance later, it will be deleted after calling slots
141 if( static_cast< const KRun
* >( sender())->hasError())
142 krun_has_error
= true;
145 static void checkArgumentCount(int count
, int min
, int max
)
149 fputs( i18n("Syntax Error: Not enough arguments\n").toLocal8Bit(), stderr
);
152 if (max
&& (count
> max
))
154 fputs( i18n("Syntax Error: Too many arguments\n").toLocal8Bit(), stderr
);
159 bool ClientApp::kde_open( const KUrl
& url
, const QString
& mimeType
)
161 if ( mimeType
.isEmpty() ) {
163 KRun
* run
= new KRun( url
, 0 );
164 QObject::connect( run
, SIGNAL( finished() ), this, SLOT( delayedQuit() ));
165 QObject::connect( run
, SIGNAL( error() ), this, SLOT( delayedQuit() ));
167 return !krun_has_error
;
171 const KService::List offers
= KMimeTypeTrader::self()->query(
172 mimeType
, QLatin1String( "Application" ) );
173 if (offers
.isEmpty()) return 1;
174 KService::Ptr serv
= offers
.first();
175 return KRun::run( *serv
, urls
, 0 );
179 bool ClientApp::doCopy( int firstArg
)
181 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
182 int argc
= args
->count();
184 for ( int i
= firstArg
; i
<= argc
- 2; i
++ )
185 srcLst
.append( args
->url(i
) );
186 KIO::Job
* job
= KIO::copy( srcLst
, args
->url(argc
- 1), s_jobFlags
);
187 if ( !s_interactive
)
188 job
->setUiDelegate( 0 );
189 connect( job
, SIGNAL( result( KJob
* ) ), this, SLOT( slotResult( KJob
* ) ) );
194 bool ClientApp::doMove( int firstArg
)
196 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
197 int argc
= args
->count();
199 for ( int i
= firstArg
; i
<= argc
- 2; i
++ )
200 srcLst
.append( args
->url(i
) );
202 KIO::Job
* job
= KIO::move( srcLst
, args
->url(argc
- 1), s_jobFlags
);
203 if ( !s_interactive
)
204 job
->setUiDelegate( 0 );
205 connect( job
, SIGNAL( result( KJob
* ) ), this, SLOT( slotResult( KJob
* ) ) );
210 bool ClientApp::doIt()
212 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
213 int argc
= args
->count();
214 checkArgumentCount(argc
, 1, 0);
216 if ( !args
->isSet( "ninteractive" ) ) {
217 s_interactive
= false;
218 s_jobFlags
= KIO::HideProgressInfo
;
221 kDebug() << "Creating ClientApp";
223 char** fake_argv
= 0;
224 ClientApp
app( fake_argc
, fake_argv
);
225 KComponentData
componentData("kioclient"); // needed by KIO's internal use of KConfig
226 app
.setApplicationName(componentData
.componentName());
228 KGlobal::setAllowQuit(true);
230 // KIO needs dbus (for uiserver communication)
231 extern void qDBusBindToApplication();
232 qDBusBindToApplication();
233 if (!QDBusConnection::sessionBus().isConnected())
234 kFatal(101) << "Session bus not found" ;
237 #ifdef KIOCLIENT_AS_KDEOPEN
238 app
.kde_open( args
->url(0), QByteArray() );
240 #elif defined(KIOCLIENT_AS_KDECP)
241 checkArgumentCount(argc
, 2, 0);
242 return app
.doCopy(0);
243 #elif defined(KIOCLIENT_AS_KDEMV)
244 checkArgumentCount(argc
, 2, 0);
245 return app
.doMove(0);
247 // Normal kioclient mode
248 const QByteArray command
= args
->arg(0).toLocal8Bit();
249 if ( command
== "openProperties" )
251 checkArgumentCount(argc
, 2, 2);
252 KPropertiesDialog
* p
= new KPropertiesDialog( args
->url(1), 0 /*no parent*/ );
253 QObject::connect( p
, SIGNAL( destroyed() ), &app
, SLOT( quit() ));
254 QObject::connect( p
, SIGNAL( canceled() ), &app
, SLOT( slotDialogCanceled() ));
259 else if ( command
== "cat" )
261 checkArgumentCount(argc
, 2, 2);
262 KIO::TransferJob
* job
= KIO::get(args
->url(1), KIO::NoReload
, s_jobFlags
);
263 if ( !s_interactive
)
264 job
->setUiDelegate( 0 );
265 connect(job
, SIGNAL(data(KIO::Job
*,QByteArray
) ), &app
, SLOT(slotPrintData(KIO::Job
*,QByteArray
)));
266 connect( job
, SIGNAL( result( KJob
* ) ), &app
, SLOT( slotResult( KJob
* ) ) );
270 else if ( command
== "exec" )
272 checkArgumentCount(argc
, 2, 3);
273 app
.kde_open( args
->url( 1 ),
274 argc
== 3 ? args
->arg( 2 ) : QString() );
276 else if ( command
== "download" )
278 checkArgumentCount(argc
, 0, 0);
282 KUrl src
= KUrlRequesterDialog::getUrl();
283 if (!src
.isEmpty()) {
284 if (!src
.isValid()) {
285 KMessageBox::error(0, i18n("Unable to download from an invalid URL."));
293 for ( int i
= 1; i
<= argc
- 1; i
++ )
294 srcLst
.append( args
->url(i
) );
296 if (srcLst
.count() == 0)
299 KFileDialog::getSaveFileName( (argc
<2) ? QString() : (args
->url(1).fileName()) );
300 if (dst
.isEmpty()) // canceled
301 return m_ok
; // AK - really okay?
303 dsturl
.setPath( dst
);
304 KIO::Job
* job
= KIO::copy( srcLst
, dsturl
, s_jobFlags
);
305 if ( !s_interactive
)
306 job
->setUiDelegate( 0 );
307 connect( job
, SIGNAL( result( KJob
* ) ), &app
, SLOT( slotResult( KJob
* ) ) );
311 else if ( command
== "copy" )
313 checkArgumentCount(argc
, 2, 0);
314 return app
.doCopy( 1 );
316 else if ( command
== "move" )
318 checkArgumentCount(argc
, 2, 0);
319 return app
.doMove( 1 );
323 fprintf( stderr
, "%s", i18n("Syntax Error: Unknown command '%1'\n", QString::fromLocal8Bit(command
)).toLocal8Bit().data() );
330 void ClientApp::slotResult( KJob
* job
)
332 if (job
->error() && s_interactive
)
333 static_cast<KIO::Job
*>(job
)->ui()->showErrorMessage();
334 m_ok
= !job
->error();
338 void ClientApp::slotDialogCanceled()
344 void ClientApp::deref()
349 void ClientApp::slotPrintData(KIO::Job
*, const QByteArray
&data
)
352 std::cout
<< data
.constData();
355 #include "kioclient.moc"