1 /**
2 @file
3 @author Stefan Frings
4 */
5
6 #include "requestmapper.h"
7 #include "static.h"
8 #include "staticfilecontroller.h"
9
10 #include "controllers/versioncontroller.h"
11
12 #include "controllers/v1/librariescontroller.h"
13 #include "controllers/v1/foldercontroller.h"
14 #include "controllers/v1/covercontroller.h"
15 #include "controllers/v1/comiccontroller.h"
16 #include "controllers/v1/folderinfocontroller.h"
17 #include "controllers/v1/pagecontroller.h"
18 #include "controllers/v1/updatecomiccontroller.h"
19 #include "controllers/v1/errorcontroller.h"
20 #include "controllers/v1/comicdownloadinfocontroller.h"
21 #include "controllers/v1/synccontroller.h"
22
23 #include "controllers/v2/librariescontroller_v2.h"
24 #include "controllers/v2/covercontroller_v2.h"
25 #include "controllers/v2/comiccontroller_v2.h"
26 #include "controllers/v2/folderinfocontroller_v2.h"
27 #include "controllers/v2/pagecontroller_v2.h"
28 #include "controllers/v2/updatecomiccontroller_v2.h"
29 #include "controllers/v2/errorcontroller_v2.h"
30 #include "controllers/v2/comicdownloadinfocontroller_v2.h"
31 #include "controllers/v2/synccontroller_v2.h"
32 #include "controllers/v2/foldercontentcontroller_v2.h"
33 #include "controllers/v2/tagscontroller_v2.h"
34 #include "controllers/v2/tagcontentcontroller_v2.h"
35 #include "controllers/v2/taginfocontroller_v2.h"
36 #include "controllers/v2/favoritescontroller_v2.h"
37 #include "controllers/v2/readingcomicscontroller_v2.h"
38 #include "controllers/v2/readinglistscontroller_v2.h"
39 #include "controllers/v2/readinglistcontentcontroller_v2.h"
40 #include "controllers/v2/readinglistinfocontroller_v2.h"
41 #include "controllers/v2/comicfullinfocontroller_v2.h"
42 #include "controllers/v2/comiccontrollerinreadinglist_v2.h"
43
44 #include "db_helper.h"
45 #include "yacreader_libraries.h"
46
47 #include "yacreader_http_session.h"
48
49 #include "QsLog.h"
50
51 using stefanfrings::HttpRequest;
52 using stefanfrings::HttpRequestHandler;
53 using stefanfrings::HttpResponse;
54 using stefanfrings::HttpSession;
55
56 QMutex RequestMapper::mutex;
57
RequestMapper(QObject * parent)58 RequestMapper::RequestMapper(QObject *parent)
59 : HttpRequestHandler(parent) { }
60
loadSessionV1(HttpRequest & request,HttpResponse & response)61 void RequestMapper::loadSessionV1(HttpRequest &request, HttpResponse &response)
62 {
63 QMutexLocker locker(&mutex);
64
65 HttpSession session = Static::sessionStore->getSession(request, response);
66 if (session.contains("ySession")) //session is already alive check if it is needed to update comics
67 {
68 auto ySession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(session.getId());
69
70 QString postData = QString::fromUtf8(request.getBody());
71
72 if (postData.contains("currentPage"))
73 return;
74
75 if (postData.length() > 0) {
76
77 QList<QString> data = postData.split("\n");
78 if (data.length() > 2) {
79 ySession->setDeviceType(data.at(0).split(":").at(1));
80 ySession->setDisplayType(data.at(1).split(":").at(1));
81 QList<QString> comics = data.at(2).split(":").at(1).split("\t");
82 ySession->clearComics();
83 foreach (QString hash, comics) {
84 ySession->setComicOnDevice(hash);
85 }
86 } else {
87 if (data.length() > 1) {
88 ySession->setDeviceType(data.at(0).split(":").at(1));
89 ySession->setDisplayType(data.at(1).split(":").at(1));
90 }
91 }
92 }
93 } else {
94 auto ySession = new YACReaderHttpSession(this);
95
96 Static::yacreaderSessionStore->addYACReaderHttpSession(session.getId(), ySession);
97
98 session.set("ySession", "ok");
99
100 QString postData = QString::fromUtf8(request.getBody());
101 //response.writeText(postData);
102
103 QList<QString> data = postData.split("\n");
104
105 if (data.length() > 2) {
106 auto deviceTypeData = data.at(0).split(":");
107 if (deviceTypeData.length() == 2) {
108 ySession->setDeviceType(deviceTypeData.at(1));
109 }
110
111 auto displayTypeData = data.at(1).split(":");
112 if (displayTypeData.length() == 2) {
113 ySession->setDisplayType(displayTypeData.at(1));
114 }
115
116 auto comicsData = data.at(2).split(":");
117 if (comicsData.length() == 2) {
118 QList<QString> comics = comicsData.at(1).split("\t");
119 foreach (QString hash, comics) {
120 ySession->setComicOnDevice(hash);
121 }
122 }
123 } else //values by default, only for debug purposes.
124 {
125 ySession->setDeviceType("ipad");
126 ySession->setDisplayType("@2x");
127 }
128 }
129 }
130
loadSessionV2(HttpRequest & request,HttpResponse &)131 void RequestMapper::loadSessionV2(HttpRequest &request, HttpResponse & /* response */)
132 {
133 QMutexLocker locker(&mutex);
134
135 QByteArray token = request.getHeader("x-request-id");
136
137 if (token.isEmpty()) {
138 return;
139 }
140
141 auto yRecoveredSession = Static::yacreaderSessionStore->getYACReaderSessionHttpSession(token);
142
143 if (yRecoveredSession == nullptr) //session is already alive check if it is needed to update comics
144 {
145 auto ySession = new YACReaderHttpSession(this);
146
147 Static::yacreaderSessionStore->addYACReaderHttpSession(token, ySession);
148 }
149 }
150
service(HttpRequest & request,HttpResponse & response)151 void RequestMapper::service(HttpRequest &request, HttpResponse &response)
152 {
153 QByteArray path = request.getPath();
154
155 QLOG_TRACE() << "RequestMapper: path=" << path.data();
156 QLOG_TRACE() << "X-Request-Id: " << request.getHeader("x-request-id");
157
158 if (path.startsWith("/v2")) {
159 serviceV2(request, response);
160 } else {
161 serviceV1(request, response);
162 }
163 }
164
serviceV1(HttpRequest & request,HttpResponse & response)165 void RequestMapper::serviceV1(HttpRequest &request, HttpResponse &response)
166 {
167 QByteArray path = request.getPath();
168
169 QRegExp folder("/library/.+/folder/[0-9]+/?"); //get comic content
170 QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info
171 QRegExp comicDownloadInfo("/library/.+/comic/[0-9]+/?"); //get comic info (basic/download info)
172 QRegExp comicFullInfo("/library/.+/comic/[0-9]+/info/?"); //get comic info (full info)
173 QRegExp comicOpen("/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic
174 QRegExp comicUpdate("/library/.+/comic/[0-9]+/update/?"); //get comic info
175 QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory
176 QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation)
177 QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page
178 QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading)
179
180 QRegExp sync("/sync");
181
182 QRegExp library("/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe
183
184 path = QUrl::fromPercentEncoding(path).toUtf8();
185
186 if (!sync.exactMatch(path)) //no session is needed for syncback info, until security will be added
187 loadSessionV1(request, response);
188
189 //primera petición, se ha hecho un post, se sirven las bibliotecas si la seguridad mediante login no está habilitada
190 if (path == "/") //Don't send data to the server using '/' !!!!
191 {
192 LibrariesController().service(request, response);
193 } else {
194 if (sync.exactMatch(path))
195 SyncController().service(request, response);
196 else {
197 //se comprueba que la sesión sea la correcta con el fin de evitar accesos no autorizados
198 HttpSession session = Static::sessionStore->getSession(request, response, false);
199 if (!session.isNull() && session.contains("ySession")) {
200 if (library.indexIn(path) != -1 && DBHelper::getLibraries().contains(library.cap(1).toInt())) {
201 //listar el contenido del folder
202 if (folder.exactMatch(path)) {
203 FolderController().service(request, response);
204 } else if (folderInfo.exactMatch(path)) {
205 FolderInfoController().service(request, response);
206 } else if (cover.exactMatch(path)) {
207 CoverController().service(request, response);
208 } else if (comicDownloadInfo.exactMatch(path)) {
209 ComicDownloadInfoController().service(request, response);
210 } else if (comicFullInfo.exactMatch(path) || comicOpen.exactMatch(path)) //start download or start remote reading
211 {
212 ComicController().service(request, response);
213 } else if (comicPage.exactMatch(path) || comicPageRemote.exactMatch(path)) {
214 PageController().service(request, response);
215 } else if (comicUpdate.exactMatch(path)) {
216 UpdateComicController().service(request, response);
217 }
218 } else {
219 //response.writeText(library.cap(1));
220 Static::staticFileController->service(request, response);
221 }
222 } else //acceso no autorizado, redirección
223 {
224 ErrorController(300).service(request, response);
225 }
226 }
227 }
228 }
229
serviceV2(HttpRequest & request,HttpResponse & response)230 void RequestMapper::serviceV2(HttpRequest &request, HttpResponse &response)
231 {
232 QByteArray path = request.getPath();
233
234 QRegExp folderInfo("/v2/library/.+/folder/[0-9]+/info/?"); //get folder info
235 QRegExp comicDownloadInfo("/v2/library/.+/comic/[0-9]+/info/?"); //get comic info (full download info)
236 QRegExp comicOpenForDownloading("/v2/library/.+/comic/[0-9]+/?"); //get comic info (full info + opening)
237 QRegExp comicOpenForRemoteReading("/v2/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic
238 QRegExp comicOpenForRemoteReadingInAReadingList("/v2/library/.+/reading_list/[0-9]+/comic/[0-9]+/remote/?"); //the server will open for reading the comic
239 QRegExp comicFullInfo("/v2/library/.+/comic/[0-9]+/fullinfo/?"); //get comic info
240 QRegExp comicUpdate("/v2/library/.+/comic/[0-9]+/update/?"); //get comic info
241 QRegExp comicClose("/v2/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory
242 QRegExp cover("/v2/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation)
243 QRegExp comicPage("/v2/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page
244 QRegExp comicPageRemote("/v2/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading)
245 QRegExp serverVersion("/v2/version/?");
246 QRegExp folderContent("/v2/library/.+/folder/[0-9]+/content/?");
247 QRegExp favs("/v2/library/.+/favs/?");
248 QRegExp reading("/v2/library/.+/reading/?");
249 QRegExp tags("/v2/library/.+/tags/?");
250 QRegExp tagContent("/v2/library/.+/tag/[0-9]+/content/?");
251 QRegExp tagInfo("/v2/library/.+/tag/[0-9]+/info/?");
252 QRegExp readingLists("/v2/library/.+/reading_lists/?");
253 QRegExp readingListContent("/v2/library/.+/reading_list/[0-9]+/content/?");
254 QRegExp readingListInfo("/v2/library/.+/reading_list/[0-9]+/info/?");
255
256 QRegExp sync("/v2/sync");
257
258 QRegExp library("/v2/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe
259
260 path = QUrl::fromPercentEncoding(path).toUtf8();
261
262 if (!sync.exactMatch(path)) //no session is needed for syncback info, until security will be added
263 loadSessionV2(request, response);
264
265 //primera petición, se ha hecho un post, se sirven las bibliotecas si la seguridad mediante login no está habilitada
266 if (path == "/v2/libraries") //Don't send data to the server using '/' !!!!
267 {
268 LibrariesControllerV2().service(request, response);
269 } else {
270 if (serverVersion.exactMatch(path)) {
271 VersionController().service(request, response);
272 } else if (sync.exactMatch(path)) {
273 SyncControllerV2().service(request, response);
274 } else {
275 if (library.indexIn(path) != -1 && DBHelper::getLibraries().contains(library.cap(1).toInt())) {
276 if (folderInfo.exactMatch(path)) {
277 FolderInfoControllerV2().service(request, response);
278 } else if (cover.exactMatch(path)) {
279 CoverControllerV2().service(request, response);
280 } else if (comicDownloadInfo.exactMatch(path)) {
281 ComicDownloadInfoControllerV2().service(request, response);
282 } else if (comicOpenForRemoteReadingInAReadingList.exactMatch(path)) {
283 ComicControllerInReadingListV2().service(request, response);
284 } else if (comicOpenForDownloading.exactMatch(path) || comicOpenForRemoteReading.exactMatch(path)) { //start download or start remote reading
285 ComicControllerV2().service(request, response);
286 } else if (comicFullInfo.exactMatch(path)) {
287 ComicFullinfoController_v2().service(request, response);
288 } else if (comicPage.exactMatch(path) || comicPageRemote.exactMatch(path)) {
289 PageControllerV2().service(request, response);
290 } else if (comicUpdate.exactMatch(path)) {
291 UpdateComicControllerV2().service(request, response);
292 } else if (folderContent.exactMatch(path)) {
293 FolderContentControllerV2().service(request, response);
294 } else if (tags.exactMatch(path)) {
295 TagsControllerV2().service(request, response);
296 } else if (tagContent.exactMatch(path)) {
297 TagContentControllerV2().service(request, response);
298 } else if (favs.exactMatch(path)) {
299 FavoritesControllerV2().service(request, response);
300 } else if (reading.exactMatch(path)) {
301 ReadingComicsControllerV2().service(request, response);
302 } else if (readingLists.exactMatch(path)) {
303 ReadingListsControllerV2().service(request, response);
304 } else if (readingListContent.exactMatch(path)) {
305 ReadingListContentControllerV2().service(request, response);
306 } else if (readingListInfo.exactMatch(path)) {
307 ReadingListInfoControllerV2().service(request, response);
308 } else if (tagInfo.exactMatch(path)) {
309 TagInfoControllerV2().service(request, response);
310 }
311 } else {
312 //response.writeText(library.cap(1));
313 Static::staticFileController->service(request, response);
314 }
315 }
316 }
317 }
318