cutelyst  3.7.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
sessionstorefile.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2015-2022 Daniel Nicoletti <dantti12@gmail.com>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #include "sessionstorefile.h"
6 
7 #include <Cutelyst/Context>
8 #include <Cutelyst/Application>
9 
10 #include <QDir>
11 #include <QFile>
12 #include <QLockFile>
13 #include <QDataStream>
14 #include <QLoggingCategory>
15 #include <QCoreApplication>
16 
17 using namespace Cutelyst;
18 
19 Q_LOGGING_CATEGORY(C_SESSION_FILE, "cutelyst.plugin.sessionfile", QtWarningMsg)
20 
21 #define SESSION_STORE_FILE_SAVE QStringLiteral("_c_session_store_file_save")
22 #define SESSION_STORE_FILE_DATA QStringLiteral("_c_session_store_file_data")
23 
24 static QVariantHash loadSessionData(Context *c, const QString &sid);
25 
27 {
28 
29 }
30 
31 SessionStoreFile::~SessionStoreFile()
32 {
33 }
34 
35 QVariant SessionStoreFile::getSessionData(Context *c, const QString &sid, const QString &key, const QVariant &defaultValue)
36 {
37  const QVariantHash data = loadSessionData(c, sid);
38 
39  return data.value(key, defaultValue);
40 }
41 
42 bool SessionStoreFile::storeSessionData(Context *c, const QString &sid, const QString &key, const QVariant &value)
43 {
44  QVariantHash data = loadSessionData(c, sid);
45 
46  data.insert(key, value);
47  c->setStash(SESSION_STORE_FILE_DATA, data);
48  c->setStash(SESSION_STORE_FILE_SAVE, true);
49 
50  return true;
51 }
52 
53 bool SessionStoreFile::deleteSessionData(Context *c, const QString &sid, const QString &key)
54 {
55  QVariantHash data = loadSessionData(c, sid);
56 
57  data.remove(key);
58  c->setStash(SESSION_STORE_FILE_DATA, data);
59  c->setStash(SESSION_STORE_FILE_SAVE, true);
60 
61  return true;
62 }
63 
64 static QString rootPath()
65 {
66  static QString rootPath = QDir::tempPath()
67  + u'/'
68  + QCoreApplication::applicationName()
69  + u"/session/data";
70  return rootPath;
71 }
72 
74 {
75  Q_UNUSED(c)
76  if (!expires) {
77  QDir dir(rootPath());
78  dir.removeRecursively();
79  }
80  return true;
81 }
82 
83 QVariantHash loadSessionData(Context *c, const QString &sid)
84 {
85  QVariantHash data;
86  const QVariant sessionVariant = c->stash(SESSION_STORE_FILE_DATA);
87  if (!sessionVariant.isNull()) {
88  data = sessionVariant.toHash();
89  return data;
90  }
91 
92  const QString root = rootPath();
93 
94  auto file = new QFile(root + u'/' + sid, c);
95  if (!file->open(QIODevice::ReadWrite)) {
96  if (!QDir().mkpath(root)) {
97  qCWarning(C_SESSION_FILE) << "Failed to create path for session object" << root;
98  return data;
99  }
100 
101  if (!file->open(QIODevice::ReadWrite)) {
102  return data;
103  }
104  }
105 
106  // Commit data when Context gets deleted
107  QObject::connect(c->app(), &Application::afterDispatch, c, [c,file] {
108  if (!c->stash(SESSION_STORE_FILE_SAVE).toBool()) {
109  return;
110  }
111 
112  const QVariantHash data = c->stash(SESSION_STORE_FILE_DATA).toHash();
113 
114  if (data.isEmpty()) {
115  QFile::remove(file->fileName());
116  } else {
117  QLockFile lock(file->fileName() + QLatin1String(".lock"));
118  if (lock.lock()) {
119  QDataStream in(file);
120 
121  if (file->pos()) {
122  file->seek(0);
123  }
124 
125  in << data;
126 
127  if (file->pos() < file->size()) {
128  file->resize(file->pos());
129  }
130 
131  file->flush();
132  lock.unlock();
133  }
134  }
135  });
136 
137  // Load data
138  QLockFile lock(file->fileName() + QLatin1String(".lock"));
139  if (lock.lock()) {
140  QDataStream in(file);
141  in >> data;
142  lock.unlock();
143  }
144 
145  c->setStash(SESSION_STORE_FILE_DATA, data);
146 
147  return data;
148 }
149 
150 #include "moc_sessionstorefile.cpp"
void afterDispatch(Cutelyst::Context *c)
The Cutelyst Context.
Definition: context.h:39
void stash(const QVariantHash &unite)
Definition: context.cpp:546
void setStash(const QString &key, const QVariant &value)
Definition: context.cpp:218
Application * app() const noexcept
Definition: context.cpp:91
SessionStoreFile(QObject *parent=nullptr)
virtual bool deleteSessionData(Context *c, const QString &sid, const QString &key) final
virtual bool deleteExpiredSessions(Context *c, quint64 expires) final
virtual bool storeSessionData(Context *c, const QString &sid, const QString &key, const QVariant &value) final
virtual QVariant getSessionData(Context *c, const QString &sid, const QString &key, const QVariant &defaultValue) final
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:8