File indexing completed on 2025-01-05 03:58:12
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2011-03-22 0007 * Description : a MediaWiki C++ interface 0008 * 0009 * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2011 by Alexandre Mendes <alex dot mendes1988 at gmail dot com> 0011 * SPDX-FileCopyrightText: 2011 by Hormiere Guillaume <hormiere dot guillaume at gmail dot com> 0012 * SPDX-FileCopyrightText: 2011 by Manuel Campomanes <campomanes dot manuel at gmail dot com> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "fakeserver.h" 0019 0020 // C++ includes 0021 0022 #include <iostream> 0023 0024 // Qt includes 0025 0026 #include <QFile> 0027 #include <QRegularExpression> 0028 0029 FakeServer::FakeServer(QObject* const parent) 0030 : QThread (parent), 0031 m_tcpServer (nullptr), 0032 m_clientSocket(nullptr) 0033 { 0034 moveToThread(this); 0035 } 0036 0037 FakeServer::~FakeServer() 0038 { 0039 quit(); 0040 wait(); 0041 } 0042 0043 void FakeServer::startAndWait() 0044 { 0045 start(); 0046 0047 // this will block until the event queue starts 0048 0049 QMetaObject::invokeMethod(this, "started", Qt::BlockingQueuedConnection); 0050 } 0051 0052 void FakeServer::newConnection() 0053 { 0054 QMutexLocker locker(&m_mutex); 0055 m_clientSocket = m_tcpServer->nextPendingConnection(); 0056 0057 connect(m_clientSocket, SIGNAL(readyRead()), 0058 this, SLOT(dataAvailable())); 0059 } 0060 0061 void FakeServer::dataAvailable() 0062 { 0063 QMutexLocker locker(&m_mutex); 0064 0065 if (m_clientSocket->canReadLine()) 0066 { 0067 QStringList token = QString::fromUtf8(m_clientSocket->readAll()).split(QRegularExpression(QStringLiteral("[ \r\n][ \r\n]*"))); 0068 0069 if (token.size() > 2) 0070 { 0071 FakeServer::Request request; 0072 request.type = token[0]; 0073 request.value = token[1]; 0074 0075 int index = token.indexOf(QLatin1String("User-Agent:")); 0076 0077 if ((index > 0) && ((index + 1) < token.size())) 0078 { 0079 request.agent = token[index + 1]; 0080 } 0081 0082 // It might happen that the same request cames through more than once, so you need to check that you are 0083 // counting each different request only once. 0084 // 0085 // For more information, see: qt-project.org/forums/viewthread/25521 0086 0087 if (!m_request.contains(request)) 0088 { 0089 m_request << request; 0090 0091 QString retour = m_scenarios.isEmpty() ? QStringLiteral("empty") : m_scenarios.takeFirst(); 0092 QString cookie = m_cookie.isEmpty() ? QStringLiteral("empty") : m_cookie.takeFirst(); 0093 QString scenario = QStringLiteral("HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=\"utf-8\"\r\nSet-Cookie:") + cookie + QStringLiteral("\r\n\r\n") + retour; 0094 m_clientSocket->write(scenario.toLocal8Bit()); 0095 } 0096 } 0097 } 0098 0099 m_clientSocket->close(); 0100 } 0101 0102 void FakeServer::run() 0103 { 0104 m_tcpServer = new QTcpServer(); 0105 0106 if (!m_tcpServer->listen(QHostAddress(QHostAddress::LocalHost), 12566)) 0107 { 0108 // TODO 0109 } 0110 0111 connect(m_tcpServer, SIGNAL(newConnection()), 0112 this, SLOT(newConnection())); 0113 0114 exec(); 0115 0116 delete m_clientSocket; 0117 delete m_tcpServer; 0118 } 0119 0120 void FakeServer::started() 0121 { 0122 // do nothing: this is a dummy slot used by startAndWait() 0123 } 0124 0125 void FakeServer::setScenario(const QString& scenario, const QString& cookie) 0126 { 0127 QMutexLocker locker(&m_mutex); 0128 0129 m_scenarios.clear(); 0130 m_scenarios << scenario; 0131 m_cookie.clear(); 0132 m_cookie << cookie; 0133 m_request.clear(); 0134 } 0135 0136 void FakeServer::addScenario(const QString& scenario, const QString& cookie ) 0137 { 0138 QMutexLocker locker(&m_mutex); 0139 0140 m_scenarios << scenario; 0141 m_cookie << cookie; 0142 } 0143 0144 void FakeServer::addScenarioFromFile(const QString& fileName, const QString& cookie ) 0145 { 0146 QFile file(fileName); 0147 0148 if (!file.open(QFile::ReadOnly)) 0149 { 0150 return; 0151 } 0152 0153 QTextStream in(&file); 0154 QString scenario; 0155 0156 // When loading from files we never have the authentication phase 0157 // force jumping directly to authenticated state. 0158 0159 while (!in.atEnd()) 0160 { 0161 scenario.append(in.readLine()); 0162 } 0163 0164 file.close(); 0165 0166 addScenario(scenario, cookie); 0167 } 0168 0169 bool FakeServer::isScenarioDone( int scenarioNumber ) const 0170 { 0171 QMutexLocker locker(&m_mutex); 0172 0173 if (scenarioNumber < m_scenarios.size()) 0174 { 0175 return m_scenarios[scenarioNumber].isEmpty(); 0176 } 0177 else 0178 { 0179 return true; // Non existent hence empty, right? 0180 } 0181 } 0182 0183 bool FakeServer::isAllScenarioDone() const 0184 { 0185 QMutexLocker locker(&m_mutex); 0186 0187 Q_FOREACH (const QString& scenario, m_scenarios) 0188 { 0189 if (!scenario.isEmpty()) 0190 { // cppcheck-suppress useStlAlgorithm 0191 return false; 0192 } 0193 } 0194 0195 return true; 0196 } 0197 0198 const QList<FakeServer::Request>& FakeServer::getRequest() 0199 { 0200 return m_request; 0201 } 0202 0203 FakeServer::Request FakeServer::takeLastRequest() 0204 { 0205 return m_request.takeLast(); 0206 } 0207 0208 FakeServer::Request FakeServer::takeFirstRequest() 0209 { 0210 return m_request.takeFirst(); 0211 } 0212 0213 void FakeServer::clearRequest() 0214 { 0215 m_request.clear(); 0216 } 0217 0218 #include "moc_fakeserver.cpp"