void HttpServer::handleNormalFile(HttpClientHandler* hdlr,const QHttpRequestHeader & hdr,const QString & path) { QFileInfo fi(path); QString ext = fi.suffix(); if (hdr.hasKey("If-Modified-Since")) { QDateTime dt = parseDate(hdr.value("If-Modified-Since")); if (dt.isValid() && dt < fi.lastModified()) { HttpResponseHeader rhdr(304,hdr.majorVersion(),hdr.minorVersion()); 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().toUTC().addSecs(3600),false)); hdlr->sendResponse(rhdr); return; } } HttpResponseHeader rhdr(200,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(rhdr,ExtensionToContentType(ext),true); rhdr.setValue("Last-Modified",DateTimeToString(fi.lastModified(),false)); rhdr.setValue("Expires",DateTimeToString(QDateTime::currentDateTime().toUTC().addSecs(3600),false)); rhdr.setValue("Cache-Control","private"); if (!hdlr->sendFile(rhdr,path)) { HttpResponseHeader nhdr(404,hdr.majorVersion(),hdr.minorVersion()); setDefaultResponseHeaders(nhdr,"text/html",false); hdlr->send404(nhdr,path); } }
bool HttpServer::checkSession(const QHttpRequestHeader & hdr) { // check session in cookie int session_id = 0; if (hdr.hasKey("Cookie")) { QString cookie = hdr.value("Cookie"); int idx = cookie.find("KT_SESSID="); if (idx == -1) return false; QString number; idx += QString("KT_SESSID=").length(); while (idx < cookie.length()) { if (cookie[idx] >= '0' && cookie[idx] <= '9') number += cookie[idx]; else break; idx++; } session_id = number.toInt(); } if (session_id == session.sessionId) { // check if the session hasn't expired yet if(session.last_access.secsTo(QTime::currentTime())<WebInterfacePluginSettings::sessionTTL()) { session.last_access=QTime::currentTime(); } else { return false; } } else return false; return true; }
bool HttpServer::checkSession(const QHttpRequestHeader & hdr) { // check session in cookie int session_id = 0; if (hdr.hasKey("Cookie")) { QString cookie = hdr.value("Cookie"); QRegExp rx("KT_SESSID=(\\d+)",Qt::CaseInsensitive); int pos = 0; while ((pos = rx.indexIn(cookie, pos)) != -1) { session_id = rx.cap(1).toInt(); if (session_id == session.sessionId) break; pos += rx.matchedLength(); } } if (session_id == session.sessionId) { // check if the session hasn't expired yet if(session.last_access.secsTo(QTime::currentTime())<WebInterfacePluginSettings::sessionTTL()) { session.last_access=QTime::currentTime(); } else { return false; } } else return false; return true; }
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 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; } }