cutelyst 5.0.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/Application>
8#include <Cutelyst/Context>
9
10#include <QCoreApplication>
11#include <QDataStream>
12#include <QDir>
13#include <QFile>
14#include <QLockFile>
15#include <QLoggingCategory>
16
17using namespace Cutelyst;
18
19Q_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
24namespace {
25QVariantHash loadSessionData(Context *c, const QByteArray &sid);
26
27inline QString rootPath()
28{
29 static QString rootPath =
30 QDir::tempPath() + u'/' + QCoreApplication::applicationName() + u"/session/data";
31 return rootPath;
32}
33} // namespace
34
39
43
45 const QByteArray &sid,
46 const QString &key,
47 const QVariant &defaultValue)
48{
49 const QVariantHash data = loadSessionData(c, sid);
50
51 return data.value(key, defaultValue);
52}
53
55 const QByteArray &sid,
56 const QString &key,
57 const QVariant &value)
58{
59 QVariantHash data = loadSessionData(c, sid);
60
61 data.insert(key, value);
62 c->setStash(SESSION_STORE_FILE_DATA, data);
63 c->setStash(SESSION_STORE_FILE_SAVE, true);
64
65 return true;
66}
67
69{
70 QVariantHash data = loadSessionData(c, sid);
71
72 data.remove(key);
73 c->setStash(SESSION_STORE_FILE_DATA, data);
74 c->setStash(SESSION_STORE_FILE_SAVE, true);
75
76 return true;
77}
78
80{
81 Q_UNUSED(c)
82 if (!expires) {
83 QDir dir(rootPath());
85 }
86 return true;
87}
88
89namespace {
90QVariantHash loadSessionData(Context *c, const QByteArray &sid)
91{
92 QVariantHash data;
93 const QVariant sessionVariant = c->stash(SESSION_STORE_FILE_DATA);
94 if (!sessionVariant.isNull()) {
95 data = sessionVariant.toHash();
96 return data;
97 }
98
99 const QString root = rootPath();
100
101 auto file = new QFile(root + u'/' + QString::fromLatin1(sid), c);
102 if (!file->open(QIODevice::ReadWrite)) {
103 if (!QDir().mkpath(root)) {
104 qCWarning(C_SESSION_FILE) << "Failed to create path for session object" << root;
105 return data;
106 }
107
108 if (!file->open(QIODevice::ReadWrite)) {
109 return data;
110 }
111 }
112
113 // Commit data when Context gets deleted
114 QObject::connect(c->app(), &Application::afterDispatch, c, [c, file] {
115 if (!c->stash(SESSION_STORE_FILE_SAVE).toBool()) {
116 return;
117 }
118
119 const QVariantHash data = c->stash(SESSION_STORE_FILE_DATA).toHash();
120
121 if (data.isEmpty()) {
122 QFile::remove(file->fileName());
123 } else {
124 QLockFile lock(file->fileName() + QLatin1String(".lock"));
125 if (lock.lock()) {
126 QDataStream in(file);
127
128 if (file->pos()) {
129 file->seek(0);
130 }
131
132 in << data;
133
134 if (file->pos() < file->size()) {
135 file->resize(file->pos());
136 }
137
138 file->flush();
139 lock.unlock();
140 }
141 }
142 });
143
144 // Load data
145 QLockFile lock(file->fileName() + QLatin1String(".lock"));
146 if (lock.lock()) {
147 QDataStream in(file);
148 in >> data;
149 lock.unlock();
150 }
151
152 c->setStash(SESSION_STORE_FILE_DATA, data);
153
154 return data;
155}
156} // namespace
157
158#include "moc_sessionstorefile.cpp"
void afterDispatch(Cutelyst::Context *c)
The Cutelyst Context.
Definition context.h:42
void stash(const QVariantHash &unite)
Definition context.cpp:563
void setStash(const QString &key, const QVariant &value)
Definition context.cpp:213
Application * app() const noexcept
Definition context.cpp:92
SessionStoreFile(QObject *parent=nullptr)
virtual bool storeSessionData(Context *c, const QByteArray &sid, const QString &key, const QVariant &value) final
virtual bool deleteSessionData(Context *c, const QByteArray &sid, const QString &key) final
virtual QVariant getSessionData(Context *c, const QByteArray &sid, const QString &key, const QVariant &defaultValue) final
virtual bool deleteExpiredSessions(Context *c, quint64 expires) final
Abstract class to create a session store.
Definition session.h:36
The Cutelyst namespace holds all public Cutelyst API.
bool removeRecursively()
QString tempPath()
bool remove()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString fromLatin1(QByteArrayView str)
bool isNull() const const
QHash< QString, QVariant > toHash() const const