void HttpServer::handlePost(HttpClientHandler* hdlr,const QHttpRequestHeader & hdr,const QByteArray & data) { Out(SYS_WEB|LOG_DEBUG) << "POST " << hdr.path() << endl; KUrl url; url.setEncodedPathAndQuery(hdr.path()); WebContentGenerator* gen = content_generators.find(url.path()); if (gen) { if ((gen->getPermissions() == WebContentGenerator::LOGIN_REQUIRED && (!session.logged_in || !checkSession(hdr))) && WebInterfacePluginSettings::authentication()) { // redirect to login page redirectToLoginPage(hdlr); } else { gen->post(hdlr,hdr,data); } } else { KUrl url; url.setEncodedPathAndQuery(hdr.path()); QString path = commonDir() + url.path(); // first try the common dir if (!bt::Exists(path)) // doesn't exist so it must be in the skin dir path = skinDir() + url.path(); handleFile(hdlr,hdr,path); } }
void HttpServer::handleFile(HttpClientHandler* hdlr,const QHttpRequestHeader & hdr,const QString & path) { // check if the file exists (if not send 404) if (!bt::Exists(path)) { HttpResponseHeader rhdr(404,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(rhdr,"text/html",false); hdlr->send404(rhdr,path); return; } QString file = hdr.path(); if (file == "/" && WebInterfacePluginSettings::authentication()) file = "/login.html"; else if (file == "/") file = "/interface.html"; QFileInfo fi(path); QString ext = fi.suffix();; if (ext == "html") { // html pages require a login unless it is the login.html page if ((file != "/login.html" && (!session.logged_in || !checkSession(hdr))) && WebInterfacePluginSettings::authentication()) { // redirect to login page redirectToLoginPage(hdlr); return; } HttpResponseHeader rhdr(200,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(rhdr,"text/html",true); if (path.endsWith("login.html")) { // clear cookie in case of login page QDateTime dt = QDateTime::currentDateTime().addDays(-1); QString cookie = QString("KT_SESSID=666; expires=%1 +0000").arg(DateTimeToString(dt,true)); rhdr.setValue("Set-Cookie",cookie); } if (!hdlr->sendFile(rhdr,path)) { HttpResponseHeader nhdr(404,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(nhdr,"text/html",false); hdlr->send404(nhdr,path); } } else if (ext == "css" || ext == "js" || ext == "png" || ext == "ico" || ext == "gif" || ext == "jpg") { handleNormalFile(hdlr,hdr,path); } else { HttpResponseHeader rhdr(404,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(rhdr,"text/html",false); hdlr->send404(rhdr,file); } }
void HttpServer::handleGet(HttpClientHandler* hdlr,const QHttpRequestHeader & hdr) { if (rootDir.isEmpty()) { HttpResponseHeader rhdr(500,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(rhdr,"text/html",false); hdlr->send500(rhdr,i18n("Cannot find web interface skins.")); return; } QString file = hdr.path(); if (file == "/" && WebInterfacePluginSettings::authentication()) file = "/login.html"; else if (file == "/") file = "/interface.html"; KUrl url; url.setEncodedPathAndQuery(file); Out(SYS_WEB|LOG_DEBUG) << "GET " << hdr.path() << endl; WebContentGenerator* gen = content_generators.find(url.path()); if (gen) { if ((gen->getPermissions() == WebContentGenerator::LOGIN_REQUIRED && (!session.logged_in || !checkSession(hdr))) && WebInterfacePluginSettings::authentication()) { // redirect to login page redirectToLoginPage(hdlr); } else { gen->get(hdlr,hdr); } } else { QString path = commonDir() + url.path(); // first try the common dir if (!bt::Exists(path)) // doesn't exist so it must be in the skin dir path = skinDir() + url.path(); handleFile(hdlr,hdr,path); } }
/*---------------------------------------------------------------------------*/ QVariant HttpRecognizer::comment( IConnection* connection ) { Q_ASSERT (connection); if (!mConnections.contains( connection->networkInfo() )) return "No comment yet"; const HttpConnection con = mConnections.value( connection->networkInfo() ); const QHttpRequestHeader request = con.lastRequestHeader(); const QHttpResponseHeader response = con.lastResponseHeader(); return request.method() + " " + request.value( "host" ) + request.path() + (response.isValid() ? "\nHTTP " + QString::number( response.statusCode() ) + " " + response.reasonPhrase() : "" ); }
void TorrentPostHandler::post(HttpClientHandler* hdlr, const QHttpRequestHeader& hdr, const QByteArray& data) { const char* ptr = data.data(); int len = data.size(); int pos = QString(data).indexOf("\r\n\r\n"); if (pos == -1 || pos + 4 >= len) { HttpResponseHeader rhdr(500); server->setDefaultResponseHeaders(rhdr, "text/html", false); hdlr->send500(rhdr, i18n("Invalid data received")); return; } // save torrent to a temporary file QString save_file = kt::DataDir() + "webgui_load_torrent"; QFile tmp_file(save_file); if (!tmp_file.open(QIODevice::WriteOnly)) { HttpResponseHeader rhdr(500); server->setDefaultResponseHeaders(rhdr, "text/html", false); hdlr->send500(rhdr, i18n("Failed to open temporary file")); return; } QDataStream out(&tmp_file); out.writeRawData(ptr + (pos + 4), len - (pos + 4)); tmp_file.close(); Out(SYS_WEB | LOG_NOTICE) << "Loading file " << save_file << endl; core->loadSilently(KUrl(save_file), QString()); KUrl url; url.setEncodedPathAndQuery(hdr.path()); QString page = url.queryItem("page"); // there needs to be a page to send back if (page.isEmpty()) { server->redirectToLoginPage(hdlr); } else { // redirect to page mentioned in page parameter HttpResponseHeader rhdr(301); server->setDefaultResponseHeaders(rhdr, "text/html", true); rhdr.setValue("Location", "/" + page); hdlr->send(rhdr, QByteArray()); } }
void HttpServer::handleGet(HttpClientHandler* hdlr,const QHttpRequestHeader & hdr,bool do_not_check_session) { QString file = hdr.path(); if (file == "/") file = "/login.html"; //Out(SYS_WEB|LOG_DEBUG) << "GET " << hdr.path() << endl; KURL url; url.setEncodedPathAndQuery(file); QString path = rootDir + bt::DirSeparator() + WebInterfacePluginSettings::skin() + url.path(); // first check if the file exists (if not send 404) if (!bt::Exists(path)) { HttpResponseHeader rhdr(404); setDefaultResponseHeaders(rhdr,"text/html",false); hdlr->send404(rhdr,path); return; } QFileInfo fi(path); QString ext = fi.extension(); // if it is the login page send that if (file == "/login.html" || file == "/") { session.logged_in = false; ext = "html"; path = rootDir + bt::DirSeparator() + WebInterfacePluginSettings::skin() + "/login.html"; } else if (!session.logged_in && (ext == "html" || ext == "php")) { // for any html or php page, a login is necessary redirectToLoginPage(hdlr); return; } else if (session.logged_in && !do_not_check_session && (ext == "html" || ext == "php")) { // if we are logged in and it's a html or php page, check the session id if (!checkSession(hdr)) { session.logged_in = false; // redirect to login page redirectToLoginPage(hdlr); return; } } if (ext == "html") { HttpResponseHeader rhdr(200); setDefaultResponseHeaders(rhdr,"text/html",true); if (path.endsWith("login.html")) { // clear cookie in case of login page QDateTime dt = QDateTime::currentDateTime().addDays(-1); QString cookie = QString("KT_SESSID=666; expires=%1 +0000").arg(DateTimeToString(dt,true)); rhdr.setValue("Set-Cookie",cookie); } if (!hdlr->sendFile(rhdr,path)) { HttpResponseHeader nhdr(404); setDefaultResponseHeaders(nhdr,"text/html",false); hdlr->send404(nhdr,path); } } else if (ext == "css" || ext == "js" || ext == "png" || ext == "ico" || ext == "gif" || ext == "jpg") { if (hdr.hasKey("If-Modified-Since")) { QDateTime dt = parseDate(hdr.value("If-Modified-Since")); if (dt.isValid() && dt < fi.lastModified()) { HttpResponseHeader rhdr(304); setDefaultResponseHeaders(rhdr,"text/html",true); rhdr.setValue("Cache-Control","max-age=0"); rhdr.setValue("Last-Modified",DateTimeToString(fi.lastModified(),false)); rhdr.setValue("Expires",DateTimeToString(QDateTime::currentDateTime(Qt::UTC).addSecs(3600),false)); hdlr->sendResponse(rhdr); return; } } HttpResponseHeader rhdr(200); setDefaultResponseHeaders(rhdr,ExtensionToContentType(ext),true); rhdr.setValue("Last-Modified",DateTimeToString(fi.lastModified(),false)); rhdr.setValue("Expires",DateTimeToString(QDateTime::currentDateTime(Qt::UTC).addSecs(3600),false)); rhdr.setValue("Cache-Control","private"); if (!hdlr->sendFile(rhdr,path)) { HttpResponseHeader nhdr(404); setDefaultResponseHeaders(nhdr,"text/html",false); hdlr->send404(nhdr,path); } } else if (ext == "php") { bool redirect = false; bool shutdown = false; if (url.queryItems().count() > 0 && session.logged_in) redirect = php_i->exec(url,shutdown); if (shutdown) { // first send back login page redirectToLoginPage(hdlr); QTimer::singleShot(1000,kapp,SLOT(quit())); } else if (redirect) { HttpResponseHeader rhdr(301); setDefaultResponseHeaders(rhdr,"text/html",true); rhdr.setValue("Location",url.encodedPathAndQuery()); hdlr->executePHPScript(php_i,rhdr,WebInterfacePluginSettings::phpExecutablePath(), path,url.queryItems()); } else { HttpResponseHeader rhdr(200); setDefaultResponseHeaders(rhdr,"text/html",true); hdlr->executePHPScript(php_i,rhdr,WebInterfacePluginSettings::phpExecutablePath(), path,url.queryItems()); } } else { HttpResponseHeader rhdr(404); setDefaultResponseHeaders(rhdr,"text/html",false); hdlr->send404(rhdr,path); } }
void MainWidget::request( QTcpSocket *id, const QHttpRequestHeader &header ) { mpMessageBuffer->addItem( header.toString() ); while( mpMessageBuffer->count() > 200 ) { QListWidgetItem *item = mpMessageBuffer->takeItem( 0 ); if( item ) { delete item; } } mpMessageBuffer->scrollToBottom(); #if 0 if( header.path() == "/favicon.ico" ) { QFile file( ":/favicon.ico" ); file.open( QIODevice::ReadOnly | QIODevice::Text ); emit response( id, QHttpResponseHeader( 200, "OK" ), file.readAll() ); file.close(); return; } #endif if( header.path() == "/wait" ) { mDelayList.append( id ); return; } if( header.path() == "/get" ) { QString reply( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" "<response>\n" " <reply>%1</reply>\n" " <artist>%2</artist>\n" " <title>%3</title>\n" " <album>%4</album>\n" " <track>%5</track>\n" "</response>\n" ); QByteArray replyMsg( reply.arg( Qt::escape( QString::fromUtf8(mMsg.constData()) ), Qt::escape( mTrackInfo.mArtist ), Qt::escape( mTrackInfo.mTitle ), Qt::escape( mTrackInfo.mAlbum ), QString::number(mTrackInfo.mTrackNr) ).toUtf8() ); emit response( id, QHttpResponseHeader( 200, "OK XML" ), replyMsg ); return; } QString html("<html>\n<head>\n<title>%1</title>\n" "<meta http-equiv='content-type' content='text/html; charset=UTF-8'>\n" "<link rel='shortcut icon' href='/favicon.ico' type='image/x-icon'>\n" "<script src='ajax.js' type='text/javascript'>\n" "</script>\n" "</head>\n<body>\n" "<h1>%2</h1>\n" "<p>HTTP Request: %3 %4</p>\n" "<table border='1'>\n" "<tr valign='top'><td>Artist:</td><td><textarea cols='80' rows='1' name='artist' wrap='off' readonly></textarea></td></tr>\n" "<tr valign='top'><td>Title:</td><td><textarea cols='80' rows='1' name='title' wrap='off' readonly></textarea></td></tr>\n" "<tr valign='top'><td>Album:</td><td><textarea cols='80' rows='1' name='album' wrap='off' readonly></textarea></td></tr>\n" "<tr valign='top'><td>Track:</td><td><textarea cols='80' rows='1' name='track' wrap='off' readonly></textarea></td></tr>\n" "<tr valign='top'><td>Reply:</td><td><textarea cols='80' rows='5' name='reply' wrap='off' readonly></textarea></td></tr>\n" "<tr valign='top'><td>Status:</td><td><input name='status' size='12' readonly>" "<input type='button' value='refresh' onclick='loadFields();'></td></tr>\n" "</table></body></html>\n" ); html = html.arg( QApplication::organizationName() + ": " + QApplication::applicationName(), QApplication::organizationName() + ": " + QApplication::applicationName(), header.method(), header.path() ); emit response( id, QHttpResponseHeader( 200, "OK" ), html.toUtf8() ); }
/*! * Handles incoming HTTP requests and dispatches them to the appropriate service. * * The \a requestID is an opaque value generated by the connector. * * Subclasses may override this function to perform preprocessing on each * request, but they must call the base class implementation in order to * generate and dispatch the appropriate events. * * To facilitate use with multi-threaded applications, the event will remain * valid until a response is posted. */ void QxtHttpSessionManager::incomingRequest(quint32 requestID, const QHttpRequestHeader& header, QxtWebContent* content) { QMultiHash<QString, QString> cookies; foreach(const QString& cookie, header.allValues("cookie")) // QHttpHeader is case-insensitive, thankfully { foreach(const QString& kv, cookie.split("; ")) { int pos = kv.indexOf('='); if (pos == -1) continue; cookies.insert(kv.left(pos), kv.mid(pos + 1)); } } int sessionID; QString sessionCookie = cookies.value(qxt_d().sessionCookieName); qxt_d().sessionLock.lock(); if (qxt_d().sessionKeys.contains(sessionCookie)) { sessionID = qxt_d().sessionKeys[sessionCookie]; if(!sessionID && header.majorVersion() > 0 && qxt_d().autoCreateSession) sessionID = newSession(); } else if (header.majorVersion() > 0 && qxt_d().autoCreateSession) { sessionID = newSession(); } else { sessionID = 0; } QIODevice* device = connector()->getRequestConnection(requestID); QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; state.sessionID = sessionID; state.httpMajorVersion = header.majorVersion(); state.httpMinorVersion = header.minorVersion(); if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0) || header.value("connection").toLower() == "close") state.keepAlive = false; else state.keepAlive = true; qxt_d().sessionLock.unlock(); QxtWebRequestEvent* event = new QxtWebRequestEvent(sessionID, requestID, QUrl::fromEncoded(header.path().toUtf8())); qxt_d().eventLock.lock(); qxt_d().pendingRequests.insert(QPair<int,int>(sessionID, requestID), event); qxt_d().eventLock.unlock(); QTcpSocket* socket = qobject_cast<QTcpSocket*>(device); if (socket) { event->remoteAddress = socket->peerAddress(); #if defined(QT_SECURETRANSPORT) || !defined(QT_NO_OPENSSL) QSslSocket* sslSocket = qobject_cast<QSslSocket*>(socket); if(sslSocket) { event->isSecure = true; event->clientCertificate = sslSocket->peerCertificate(); } #endif } event->method = header.method(); event->cookies = cookies; event->url.setScheme("http"); if (event->url.host().isEmpty()) event->url.setHost(header.value("host")); if (event->url.port() == -1) event->url.setPort(port()); event->contentType = header.contentType(); event->content = content; typedef QPair<QString, QString> StringPair; foreach(const StringPair& line, header.values()) { if (line.first.toLower() == "cookie") continue; event->headers.insert(line.first, line.second); } event->headers.insert("X-Request-Protocol", "HTTP/" + QString::number(state.httpMajorVersion) + '.' + QString::number(state.httpMinorVersion)); if (sessionID && session(sessionID)) { QxtAbstractWebService *service = session(sessionID); if(content) content->setParent(service); // Set content ownership to the service service->pageRequestedEvent(event); } else if (qxt_d().staticService) { qxt_d().staticService->pageRequestedEvent(event); } else { postEvent(new QxtWebErrorEvent(0, requestID, 500, "Internal Configuration Error")); } }
void InspectorServerRequestHandlerQt::tcpReadyRead() { QHttpRequestHeader header; bool isWebSocket = false; if (!m_tcpConnection) return; if (!m_endOfHeaders) { while (m_tcpConnection->bytesAvailable() && !m_endOfHeaders) { QByteArray line = m_tcpConnection->readLine(); m_data.append(line); if (line == "\r\n") m_endOfHeaders = true; } if (m_endOfHeaders) { header = QHttpRequestHeader(QString::fromLatin1(m_data)); if (header.isValid()) { m_path = header.path(); m_contentType = header.contentType().toLatin1(); m_contentLength = header.contentLength(); if (header.hasKey("Upgrade") && (header.value("Upgrade") == QLatin1String("WebSocket"))) isWebSocket = true; m_data.clear(); } } } if (m_endOfHeaders) { QStringList pathAndQuery = m_path.split("?"); m_path = pathAndQuery[0]; QStringList words = m_path.split(QString::fromLatin1("/")); if (isWebSocket) { // switch to websocket-style WebSocketService messaging if (m_tcpConnection) { m_tcpConnection->disconnect(SIGNAL(readyRead())); connect(m_tcpConnection, SIGNAL(readyRead()), SLOT(webSocketReadyRead())); QByteArray key3 = m_tcpConnection->read(8); quint32 number1 = parseWebSocketChallengeNumber(header.value("Sec-WebSocket-Key1")); quint32 number2 = parseWebSocketChallengeNumber(header.value("Sec-WebSocket-Key2")); char responseData[16]; generateWebSocketChallengeResponse(number1, number2, (unsigned char*)key3.data(), (unsigned char*)responseData); QByteArray response(responseData, sizeof(responseData)); QHttpResponseHeader responseHeader(101, "WebSocket Protocol Handshake", 1, 1); responseHeader.setValue("Upgrade", header.value("Upgrade")); responseHeader.setValue("Connection", header.value("Connection")); responseHeader.setValue("Sec-WebSocket-Origin", header.value("Origin")); responseHeader.setValue("Sec-WebSocket-Location", ("ws://" + header.value("Host") + m_path)); responseHeader.setContentLength(response.size()); m_tcpConnection->write(responseHeader.toString().toLatin1()); m_tcpConnection->write(response); m_tcpConnection->flush(); if ((words.size() == 4) && (words[1] == QString::fromLatin1("devtools")) && (words[2] == QString::fromLatin1("page"))) { int pageNum = words[3].toInt(); m_inspectorClient = m_server->inspectorClientForPage(pageNum); // Attach remoteFrontendChannel to inspector, also transferring ownership. if (m_inspectorClient) m_inspectorClient->attachAndReplaceRemoteFrontend(new RemoteFrontendChannel(this)); } } return; } if (m_contentLength && (m_tcpConnection->bytesAvailable() < m_contentLength)) return; QByteArray content = m_tcpConnection->read(m_contentLength); m_endOfHeaders = false; QByteArray response; int code = 200; QString text = QString::fromLatin1("OK"); // If no path is specified, generate an index page. if ((m_path == "") || (m_path == "/")) { QString indexHtml = "<html><head><title>Remote Web Inspector</title></head><body><ul>\n"; for (QMap<int, InspectorClientQt* >::const_iterator it = m_server->m_inspectorClients.begin(); it != m_server->m_inspectorClients.end(); ++it) { indexHtml.append(QString("<li><a href=\"/webkit/inspector/inspector.html?page=%1\">%2</li>\n") .arg(it.key()) .arg(it.value()->m_inspectedWebPage->mainFrame()->url().toString())); } indexHtml.append("</ul></body></html>"); response = indexHtml.toLatin1(); } else { QString path = QString(":%1").arg(m_path); QFile file(path); // It seems that there should be an enum or define for these status codes somewhere in Qt or WebKit, // but grep fails to turn one up. // QNetwork uses the numeric values directly. if (file.exists()) { file.open(QIODevice::ReadOnly); response = file.readAll(); } else { code = 404; text = QString::fromLatin1("Not OK"); } } QHttpResponseHeader responseHeader(code, text, 1, 0); responseHeader.setContentLength(response.size()); if (!m_contentType.isEmpty()) responseHeader.setContentType(QString::fromLatin1(m_contentType)); QByteArray asciiHeader = responseHeader.toString().toAscii(); m_tcpConnection->write(asciiHeader); m_tcpConnection->write(response); m_tcpConnection->flush(); m_tcpConnection->close(); return; } }