summaryrefslogtreecommitdiffstats
path: root/krdc/main.cpp
blob: 5c2423bd6fa566af86724a28205cb4f899de3e0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/***************************************************************************
                           main.cpp  -  main control
                             -------------------
    begin                : Thu Dec 20 15:11:42 CET 2001
    copyright            : (C) 2001-2003 by Tim Jansen
    email                : tim@tjansen.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/


#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <kapplication.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kwallet.h>
#include <qwindowdefs.h>
#include <qtimer.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qregexp.h>

#include "../config.h"
#include "main.h"

// NOTE: I'm not comfortable with the wallet being global data and this high up
// in the heirarchy, but there are 3 reasons for its current placement here:
// 1) There are some important threading issues where it comes to the password
// handling code, and a lot of it is done outside of the objects. 
// 2) Different backends need access to the same wallet. so that it is not
// opened multiple times.
// 3) MainController is about the only thing that isn't deleted in between connection
// attempts.
KWallet::Wallet *wallet = 0;

static const char description[] = I18N_NOOP("Remote desktop connection");

static KCmdLineOptions options[] =
{
	{ "f", 0, 0 },
	{ "fullscreen", I18N_NOOP("Start in fullscreen mode"), 0 },
	{ "w", 0, 0 },
	{ "window", I18N_NOOP("Start in regular window"), 0 },
	{ "l", 0, 0 },
	{ "low-quality", I18N_NOOP("Low quality mode (Tight Encoding, 8 bit color)"), 0 },
	{ "m", 0, 0 },
	{ "medium-quality", I18N_NOOP("Medium quality mode (Tight Encoding, lossy)"), 0 },
	{ "h", 0, 0 },
	{ "high-quality", I18N_NOOP("High quality mode, default (Hextile Encoding)"), 0 },
	{ "s", 0, 0 },
	{ "scale", I18N_NOOP("Start VNC in scaled mode"), 0 },
	{ "c", 0, 0 },
	{ "local-cursor", I18N_NOOP("Show local cursor (VNC only)"), 0 },
	{ "e", 0, 0 },
	{ "encodings ", I18N_NOOP("Override VNC encoding list (e.g. 'hextile raw')"), 0 },
	{ "p", 0, 0 },
	{ "password-file ", I18N_NOOP("Provide the password in a file"), 0 },
	{ "+[host]", I18N_NOOP("The name of the host, e.g. 'localhost:1'"), 0 },
	KCmdLineLastOption
};


int main(int argc, char *argv[])
{
	KAboutData aboutData( "krdc", I18N_NOOP("Remote Desktop Connection"),
			      VERSION, description, KAboutData::License_GPL,
		"(c) 2009-2010, Timothy Pearson\n"
		"(c) 2001-2003, Tim Jansen\n"
		"(c) 2002-2003, Arend van Beelen jr.\n"
		"(c) 2000-2002, Const Kaplinsky\n"
		"(c) 2000, Tridia Corporation\n"
		"(c) 1999, AT&T Laboratories Cambridge\n"
		"(c) 1999-2003, Matthew Chapman\n", 0, 0,
			      "tim@tjansen.de");
	aboutData.addAuthor("Timothy Pearson",0, "kb9vqf@pearsoncomputing.net");
	aboutData.addAuthor("Tim Jansen",0, "tim@tjansen.de");
	aboutData.addAuthor("Arend van Beelen jr.",
			    I18N_NOOP("RDP backend"), "arend@auton.nl");
	aboutData.addCredit("AT&T Laboratories Cambridge",
			    I18N_NOOP("Original VNC viewer and protocol design"));
	aboutData.addCredit("Const Kaplinsky",
			    I18N_NOOP("TightVNC encoding"));
	aboutData.addCredit("Tridia Corporation",
			    I18N_NOOP("ZLib encoding"));
	KCmdLineArgs::init( argc, argv, &aboutData );
	KCmdLineArgs::addCmdLineOptions( options );

	KApplication a;

	QString host = QString::null;
	Quality quality = QUALITY_UNKNOWN;
	QString encodings = QString::null;
	QString password = QString::null;
	QString resolution = QString::null;
	QString keymap = QString::null;
	WindowMode wm = WINDOW_MODE_AUTO;
	bool scale = false;
	bool localCursor = kapp->config()->readBoolEntry("alwaysShowLocalCursor", false);
	QSize initialWindowSize;

	KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

	if (args->isSet("low-quality"))
		quality = QUALITY_LOW;
	else if (args->isSet("medium-quality"))
		quality = QUALITY_MEDIUM;
	else if (args->isSet("high-quality"))
		quality = QUALITY_HIGH;

	if (args->isSet("fullscreen"))
		wm = WINDOW_MODE_FULLSCREEN;
	else if (args->isSet("window"))
		wm = WINDOW_MODE_NORMAL;

	if (args->isSet("scale"))
		scale = true;

	if (args->isSet("local-cursor"))
		localCursor = true;

	if (args->isSet("encodings"))
		encodings = args->getOption("encodings");

	if (args->isSet("password-file")) {
		QString passwordFile = args->getOption("password-file");
		QFile f(passwordFile);
		if (!f.open(IO_ReadOnly)) {
			KMessageBox::error(0, i18n("The password file '%1' does not exist.").arg(passwordFile));
			return 1;
		}
		password = QTextStream(&f).readLine();
		f.close();
	}

	if (args->count() > 0)
		host = args->arg(0);

	QString is = a.geometryArgument();
	if (!is.isNull()) {
		QRegExp re("([0-9]+)[xX]([0-9]+)");
		if (!re.exactMatch(is))
			args->usage(i18n("Wrong geometry format, must be widthXheight"));
		initialWindowSize = QSize(re.cap(1).toInt(), re.cap(2).toInt());
	}

	MainController mc(&a, wm, host, quality, encodings, password,
			  scale, localCursor, initialWindowSize);
	return mc.main();
}

MainController::MainController(KApplication *app, WindowMode wm,
			       const QString &host,
			       Quality quality,
			       const QString &encodings,
			       const QString &password,
			       bool scale,
			       bool localCursor,
			       QSize initialWindowSize) :
        m_windowMode(wm),
	m_host(host),
        m_encodings(encodings),
        m_password(password),
	m_scale(scale),
	m_localCursor(localCursor),
	m_initialWindowSize(initialWindowSize),
	m_quality(quality),
	m_app(app) {
}

MainController::~MainController() {
	if ( wallet ) {
		delete wallet; wallet = 0;
	}
}

int MainController::main() {

	if (start())
		return m_app->exec();
	else
		return 0;
}

void MainController::errorRestartRequested() {
	QTimer::singleShot(0, this, SLOT(errorRestart()));
}

bool MainController::start() {
	m_krdc = new KRDC(m_windowMode, m_host,
			  m_quality, m_encodings, m_password,
			  m_scale, m_localCursor, m_initialWindowSize);
	m_app->setMainWidget(m_krdc);

	QObject::connect(m_krdc, SIGNAL(disconnected()),
			 m_app, SLOT(quit()));
	connect(m_krdc, SIGNAL(disconnectedError()),
		SLOT(errorRestartRequested()));

	return m_krdc->start();
}

void MainController::errorRestart() {
	if (!m_host.isEmpty())
		KRDC::setLastHost(m_host);
	m_host = QString::null; // only auto-connect once

	// unset KRDC as main widget, to avoid quit on delete
	m_app->setMainWidget(0);

	m_krdc = 0;

	if (!start())
		m_app->quit();
}

#include "main.moc"