• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdenetwork API Reference
  • KDE Home
  • Contact Us
 

kget

  • sources
  • kde-4.12
  • kdenetwork
  • kget
  • extensions
  • webinterface
httpserver.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2 
3  Copyright (C) 2008 - 2009 Urs Wolfer <uwolfer @ kde.org>
4  Copyright (C) 2010 Matthias Fuchs <mat69@gmx.net>
5  Copyright (C) 2011 Lukas Appelhans <l.appelhans@gmx.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 */
12 
13 #include "httpserver.h"
14 
15 #include "core/transferhandler.h"
16 #include "core/transfergrouphandler.h"
17 #include "core/kget.h"
18 #include "settings.h"
19 
20 #include <KDebug>
21 #include <KGlobalSettings>
22 #include <KStandardDirs>
23 #include <kwallet.h>
24 
25 #include <QTcpServer>
26 #include <QTcpSocket>
27 #include <QFile>
28 #include <QDir>
29 #include <QHttpRequestHeader>
30 #include <QDateTime>
31 
32 HttpServer::HttpServer(QWidget *parent)
33  : QObject(parent),
34  m_wallet(0)
35 {
36  m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(),
37  parent->winId(),
38  KWallet::Wallet::Asynchronous);
39  if (m_wallet) {
40  connect(m_wallet, SIGNAL(walletOpened(bool)), SLOT(init(bool)));
41  } else {
42  KGet::showNotification(parent, "error", i18n("Unable to start WebInterface: Could not open KWallet"));
43  }
44 }
45 
46 HttpServer::~HttpServer()
47 {
48  delete m_wallet;
49 }
50 
51 void HttpServer::init(bool opened)
52 {
53  if (opened &&
54  m_wallet->hasFolder("KGet") &&
55  m_wallet->setFolder("KGet")) {
56  m_wallet->readPassword("Webinterface", m_pwd);
57  } else {
58  KGet::showNotification(static_cast<QWidget*>(parent()), "error", i18n("Unable to start WebInterface: Could not open KWallet"));
59  return;
60  }
61  m_tcpServer = new QTcpServer(this);
62  if (!m_tcpServer->listen(QHostAddress::Any, Settings::webinterfacePort())) {
63  KGet::showNotification(static_cast<QWidget*>(parent()), "error", i18nc("@info", "Unable to start WebInterface: %1", m_tcpServer->errorString()));
64  return;
65  }
66 
67  connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(handleRequest()));
68 }
69 
70 void HttpServer::settingsChanged()
71 {
72  if (m_wallet) {
73  m_wallet->readPassword("Webinterface", m_pwd);
74  }
75 }
76 
77 void HttpServer::handleRequest()
78 {
79  int responseCode = 200;
80  QString responseText = "OK";
81  QTcpSocket *clientConnection = m_tcpServer->nextPendingConnection();
82 
83  connect(clientConnection, SIGNAL(disconnected()),
84  clientConnection, SLOT(deleteLater()));
85 
86  if (!clientConnection->waitForReadyRead()) {
87  clientConnection->disconnectFromHost();
88  }
89 
90  QByteArray request(clientConnection->readAll());
91  QHttpRequestHeader header(request);
92 
93  QByteArray data;
94 
95  // for HTTP authorization information see: http://www.governmentsecurity.org/articles/OverviewofHTTPAuthentication.php
96  QString auth = header.value("Authorization");
97  if (auth.length() < 6 || QByteArray::fromBase64(auth.right(auth.length() - 6).toUtf8()) !=
98  QString(Settings::webinterfaceUser() + ':' + m_pwd)) {
99  responseCode = 401;
100  responseText = "Authorization Required";
101  // DO NOT TRANSLATE THE FOLLOWING MESSAGE! webserver messages are never translated.
102  QString authRequiredText = QString("<html><head><title>401 Authorization Required</title></head><body>"
103  "<h1>Authorization Required</h1>This server could not verify that you "
104  "are authorized to access the document requested. Either you supplied "
105  "the wrong credentials (e.g., bad password), or your browser does "
106  "not understand how to supply the credentials required.</body></html>");
107  data.append(authRequiredText.toUtf8());
108  } else {
109 
110  if (header.path().endsWith(QLatin1String("data.json"))) {
111  data.append("{\"downloads\":[");
112  bool needsToBeClosed = false;
113  foreach(TransferHandler *transfer, KGet::allTransfers()) {
114  if (needsToBeClosed)
115  data.append(","); // close the last line
116  data.append(QString("{\"name\":\"" + transfer->source().fileName() +
117  "\", \"src\":\"" + transfer->source().prettyUrl() +
118  "\", \"dest\":\"" + transfer->dest().pathOrUrl() +
119  "\", \"status\":\"" + transfer->statusText() +
120  "\", \"size\":\"" + KIO::convertSize(transfer->totalSize()) +
121  "\", \"progress\":\"" + QString::number(transfer->percent()) + "%"
122  "\", \"speed\":\"" + i18nc("@item speed of transfer per seconds", "%1/s",
123  KIO::convertSize(transfer->downloadSpeed())) + "\"}").toUtf8());
124  needsToBeClosed = true;
125  }
126  data.append("]}");
127  } else if (header.path().startsWith(QLatin1String("/do"))) {
128  kDebug(5001) << request;
129 
130  QString args = header.path().right(header.path().length() - 4);
131 
132  if (!args.isEmpty()) {
133  QString action;
134  QString data;
135  QString group;
136  QStringList argList = args.split('&');
137  foreach (const QString &s, argList) {
138  QStringList map = s.split('=');
139  if (map.at(0) == "action")
140  action = map.at(1);
141  else if (map.at(0) == "data")
142  data = KUrl::fromPercentEncoding(QByteArray(map.at(1).toUtf8()));
143  // action specific parameters
144  else if (map.at(0) == "group")
145  group = KUrl::fromPercentEncoding(QByteArray(map.at(1).toUtf8()));
146  }
147  kDebug(5001) << action << data << group;
148  if (action == "add") {
149  //find a folder to store the download in
150  QString defaultFolder;
151 
152  //prefer the defaultFolder of the selected group
153  TransferGroupHandler *groupHandler = KGet::findGroup(group);
154  if (groupHandler) {
155  defaultFolder = groupHandler->defaultFolder();
156  }
157  if (defaultFolder.isEmpty()) {
158  QList<TransferGroupHandler*> groups = KGet::groupsFromExceptions(KUrl(data));
159  if (groups.isEmpty() || groups.first()->defaultFolder().isEmpty()) {
160  defaultFolder = KGet::generalDestDir();
161  } else {
162  // take first item of default folder list (which should be the best one)
163  groupHandler = groups.first();
164  group = groupHandler->name();
165  defaultFolder = groupHandler->defaultFolder();
166  }
167  }
168  KGet::addTransfer(data, defaultFolder, KUrl(data).fileName(), group);
169  data.append(QString("Ok, %1 added!").arg(data).toUtf8());
170  } else if (action == "start") {
171  TransferHandler *transfer = KGet::findTransfer(data);
172  if (transfer)
173  transfer->start();
174  } else if (action == "stop") {
175  TransferHandler *transfer = KGet::findTransfer(data);
176  if (transfer)
177  transfer->stop();
178  } else if (action == "remove") {
179  TransferHandler *transfer = KGet::findTransfer(data);
180  if (transfer)
181  KGet::delTransfer(transfer);
182  } else {
183  kWarning(5001) << "not implemented action" << action << data;
184  }
185  }
186  } else { // read it from filesystem
187  QString fileName = header.path().remove(".."); // disallow changing directory
188  if (fileName.endsWith('/'))
189  fileName = "index.htm";
190 
191  QString path = KStandardDirs::locate("data", "kget/www/" + fileName);
192  QFile file(path);
193 
194  if (path.isEmpty() || !file.open(QIODevice::ReadOnly)) {
195  responseCode = 404;
196  responseText = "Not Found";
197  // DO NOT TRANSLATE THE FOLLOWING MESSAGE! webserver messages are never translated.
198  QString notfoundText = QString("<html><head><title>404 Not Found</title></head><body>"
199  "<h1>Not Found</h1>The requested URL <code>%1</code> "
200  "was not found on this server.</body></html>")
201  .arg(header.path());
202  data.append(notfoundText.toUtf8());
203  } else {
204  while (!file.atEnd()) {
205  data.append(file.readLine());
206  }
207  }
208  if (fileName == "index.htm") { // translations
209  data.replace("#{KGet Webinterface}", i18nc("@label", "KGet Web Interface").toUtf8());
210  data.replace("#{Nr}", i18nc("@label number", "Nr").toUtf8());
211  data.replace("#{File name}", i18nc("@label", "File name").toUtf8());
212  data.replace("#{Finished}", i18nc("@label Progress of transfer", "Finished").toUtf8());
213  data.replace("#{Speed}", i18nc("@label Speed of transfer", "Speed").toUtf8());
214  data.replace("#{Status}", i18nc("@label Status of transfer", "Status").toUtf8());
215  data.replace("#{Start}", i18nc("@action:button start a transfer", "Start").toUtf8());
216  data.replace("#{Stop}", i18nc("@action:button", "Stop").toUtf8());
217  data.replace("#{Remove}", i18nc("@action:button", "Remove").toUtf8());
218  data.replace("#{Source:}", i18nc("@label Download from", "Source:").toUtf8());
219  data.replace("#{Saving to:}", i18nc("@label Save download to", "Saving to:").toUtf8());
220  data.replace("#{Webinterface}", i18nc("@label Title in header", "Web Interface").toUtf8());
221  data.replace("#{Settings}", i18nc("@action", "Settings").toUtf8());
222  data.replace("#{Refresh}", i18nc("@action", "Refresh").toUtf8());
223  data.replace("#{Enter URL: }", i18nc("@action", "Enter URL: ").toUtf8());
224  data.replace("#{OK}", i18nc("@action:button", "OK").toUtf8());
225  data.replace("#{Refresh download list every}",
226  i18nc("@action Refresh download list every x (seconds)", "Refresh download list every").toUtf8());
227  data.replace("#{seconds}", i18nc("@action (Refresh very x )seconds", "seconds").toUtf8());
228  data.replace("#{Save Settings}", i18nc("@action:button", "Save Settings").toUtf8());
229  data.replace("#{Downloads}", i18nc("@title", "Downloads").toUtf8());
230  data.replace("#{KGet Webinterface | Valid XHTML 1.0 Strict &amp; CSS}",
231  i18nc("@label text in footer", "KGet Web Interface | Valid XHTML 1.0 Strict &amp; CSS").toUtf8().replace('&', "&amp;"));
232 
233  // delegate group combobox
234  QString groupOptions = "";
235  Q_FOREACH(const QString &group, KGet::transferGroupNames())
236  groupOptions += QString("<option>%1</option>").arg(group);
237  data.replace("#{groups}", groupOptions.toUtf8());
238  }
239  }
240  }
241 
242  // for HTTP information see: http://www.jmarshall.com/easy/http/
243  QByteArray block;
244  block.append(QString("HTTP/1.1 %1 %2\r\n").arg(responseCode).arg(responseText).toUtf8());
245  block.append(QString("Date: %1 GMT\r\n").arg(QDateTime(QDateTime::currentDateTime())
246  .toString("ddd, dd MMM yyyy hh:mm:ss")).toUtf8());
247  block.append(QString("Server: KGet\r\n").toUtf8()); //TODO: add KGet version
248  if (responseCode == 401)
249  block.append(QString("WWW-Authenticate: Basic realm=\"KGet Webinterface Authorization\"\r\n").toUtf8());
250  if (header.path().endsWith(QLatin1String(".png")) && responseCode == 200)
251  block.append(QString("Content-Type: image/png\r\n").toUtf8());
252  else if (header.path().endsWith(QLatin1String(".json")) && responseCode == 200)
253  block.append(QString("Content-Type: application/x-json\r\n").toUtf8());
254  else if (header.path().endsWith(QLatin1String(".gif")) && responseCode == 200)
255  block.append(QString("Content-Type: image/gif\r\n").toUtf8());
256  else if (header.path().endsWith(QLatin1String(".js")) && responseCode == 200)
257  block.append(QString("Content-Type: text/javascript\r\n").toUtf8());
258  else if (header.path().endsWith(QLatin1String(".htc")) && responseCode == 200)
259  block.append(QString("Content-Type: text/x-component\r\n").toUtf8());
260  else
261  block.append(QString("Content-Type: text/html; charset=UTF-8\r\n").toUtf8());
262  block.append(QString("Content-Length: " + QString::number(data.length())+"\r\n").toUtf8());
263  block.append(QString("\r\n").toUtf8());
264  block.append(data);
265 
266  clientConnection->write(block);
267  clientConnection->disconnectFromHost();
268 }
KGet::generalDestDir
static QString generalDestDir(bool preferXDGDownloadDir=false)
Returns a download directory.
Definition: kget.cpp:945
KGet::addTransfer
static TransferHandler * addTransfer(KUrl srcUrl, QString destDir=QString(), QString suggestedFileName=QString(), QString groupName=QString(), bool start=false)
Adds a new transfer to the KGet.
Definition: kget.cpp:179
KGet::transferGroupNames
static QStringList transferGroupNames()
Definition: kget.cpp:168
TransferHandler
Class TransferHandler:
Definition: transferhandler.h:48
TransferGroupHandler
Definition: transfergrouphandler.h:30
TransferHandler::start
virtual void start()
These are all Job-related functions.
Definition: transferhandler.cpp:51
QWidget
HttpServer::~HttpServer
~HttpServer()
Definition: httpserver.cpp:46
TransferHandler::totalSize
KIO::filesize_t totalSize() const
Definition: transferhandler.cpp:86
QObject
httpserver.h
KGet::allTransfers
static QList< TransferHandler * > allTransfers()
Gets all transfers.
Definition: kget.cpp:657
TransferHandler::dest
const KUrl & dest() const
Definition: transferhandler.h:98
TransferGroupHandler::name
const QString & name()
Definition: transfergrouphandler.h:83
transfergrouphandler.h
TransferHandler::statusText
QString statusText() const
Definition: transferhandler.h:210
TransferGroupHandler::defaultFolder
QString defaultFolder()
Definition: transfergrouphandler.h:134
TransferHandler::source
const KUrl & source() const
Definition: transferhandler.h:93
KGet::findGroup
static TransferGroupHandler * findGroup(const QString &name)
Get the group with the given name.
Definition: kget.cpp:690
HttpServer::settingsChanged
void settingsChanged()
Definition: httpserver.cpp:70
TransferHandler::downloadSpeed
int downloadSpeed() const
Definition: transferhandler.cpp:106
Settings::webinterfaceUser
static QString webinterfaceUser()
Get WebinterfaceUser.
Definition: settings.h:791
KGet::groupsFromExceptions
static QList< TransferGroupHandler * > groupsFromExceptions(const KUrl &filename)
Definition: kget.cpp:730
transferhandler.h
TransferHandler::percent
int percent() const
Definition: transferhandler.cpp:101
HttpServer::HttpServer
HttpServer(QWidget *parent=0)
Definition: httpserver.cpp:32
settings.h
kget.h
KGet::showNotification
static KNotification * showNotification(QWidget *parent, const QString &eventType, const QString &text, const QString &icon=QString("dialog-error"), const QString &title=i18n("KGet"), const KNotification::NotificationFlags &flags=KNotification::CloseOnTimeout)
Shows a knotification.
Definition: kget.cpp:1281
KGet::findTransfer
static TransferHandler * findTransfer(const KUrl &src)
Get the transfer with the given url.
Definition: kget.cpp:680
Settings::webinterfacePort
static int webinterfacePort()
Get WebinterfacePort.
Definition: settings.h:772
KGet::delTransfer
static bool delTransfer(TransferHandler *transfer, DeleteMode mode=AutoDelete)
Removes a transfer from the KGet.
Definition: kget.cpp:362
TransferHandler::stop
virtual void stop()
Definition: transferhandler.cpp:64
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:53:17 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kget

Skip menu "kget"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal