Cutelyst  1.11.0
sessionstorefile.cpp
1 /*
2  * Copyright (C) 2015-2017 Daniel Nicoletti <dantti12@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 #include "sessionstorefile.h"
19 
20 #include <Cutelyst/Context>
21 
22 #include <QDir>
23 #include <QFile>
24 #include <QLockFile>
25 #include <QDataStream>
26 #include <QLoggingCategory>
27 #include <QCoreApplication>
28 
29 using namespace Cutelyst;
30 
31 Q_LOGGING_CATEGORY(C_SESSION_FILE, "cutelyst.plugin.sessionfile")
32 
33 #define SESSION_STORE_FILE_SAVE "__session_store_file_save"
34 #define SESSION_STORE_FILE_DATA "__session_store_file_data"
35 
36 static QVariantHash loadSessionData(Context *c, const QString &sid);
37 
39 {
40 
41 }
42 
43 SessionStoreFile::~SessionStoreFile()
44 {
45 }
46 
47 QVariant SessionStoreFile::getSessionData(Context *c, const QString &sid, const QString &key, const QVariant &defaultValue)
48 {
49  const QVariantHash data = loadSessionData(c, sid);
50 
51  return data.value(key, defaultValue);
52 }
53 
54 bool SessionStoreFile::storeSessionData(Context *c, const QString &sid, const QString &key, const QVariant &value)
55 {
56  QVariantHash data = loadSessionData(c, sid);
57 
58  data.insert(key, value);
59  c->setProperty(SESSION_STORE_FILE_DATA, data);
60  c->setProperty(SESSION_STORE_FILE_SAVE, true);
61 
62  return true;
63 }
64 
65 bool SessionStoreFile::deleteSessionData(Context *c, const QString &sid, const QString &key)
66 {
67  QVariantHash data = loadSessionData(c, sid);
68 
69  data.remove(key);
70  c->setProperty(SESSION_STORE_FILE_DATA, data);
71  c->setProperty(SESSION_STORE_FILE_SAVE, true);
72 
73  return true;
74 }
75 
77 {
78  Q_UNUSED(c)
79  Q_UNUSED(expires)
80  return true;
81 }
82 
83 QVariantHash loadSessionData(Context *c, const QString &sid)
84 {
85  QVariantHash data;
86  const QVariant sessionVariant = c->property(SESSION_STORE_FILE_DATA);
87  if (!sessionVariant.isNull()) {
88  data = sessionVariant.toHash();
89  return data;
90  }
91 
92  const static QString root = QDir::tempPath()
93  + QLatin1Char('/')
94  + QCoreApplication::applicationName()
95  + QLatin1String("/session/data");
96 
97  auto file = new QFile(root + QLatin1Char('/') + sid, c);
98  if (!file->open(QIODevice::ReadWrite)) {
99  if (!QDir().mkpath(root)) {
100  qCWarning(C_SESSION_FILE) << "Failed to create path for session object" << root;
101  return data;
102  }
103 
104  if (!file->open(QIODevice::ReadWrite)) {
105  return data;
106  }
107  }
108 
109  // Commit data when Context gets deleted
110  QObject::connect(c, &Context::destroyed, [=] () {
111  if (!c->property(SESSION_STORE_FILE_SAVE).toBool()) {
112  return;
113  }
114 
115  QVariantHash data = c->property(SESSION_STORE_FILE_DATA).toHash();
116 
117  if (data.isEmpty()) {
118  QFile::remove(file->fileName());
119  } else {
120  QLockFile lock(file->fileName() + QLatin1String(".lock"));
121  if (lock.lock()) {
122  QDataStream in(file);
123 
124  if (file->pos()) {
125  file->seek(0);
126  }
127 
128  in << data;
129 
130  if (file->pos() < file->size()) {
131  file->resize(file->pos());
132  }
133 
134  file->flush();
135  lock.unlock();
136  }
137  }
138  });
139 
140  // Load data
141  QLockFile lock(file->fileName() + QLatin1String(".lock"));
142  if (lock.lock()) {
143  QDataStream in(file);
144  in >> data;
145  lock.unlock();
146  }
147 
148  c->setProperty(SESSION_STORE_FILE_DATA, data);
149 
150  return data;
151 }
152 
153 #include "moc_sessionstorefile.cpp"
SessionStoreFile(QObject *parent=nullptr)
The Cutelyst Context.
Definition: context.h:50
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:7
virtual QVariant getSessionData(Context *c, const QString &sid, const QString &key, const QVariant &defaultValue) final
virtual bool storeSessionData(Context *c, const QString &sid, const QString &key, const QVariant &value) final
virtual bool deleteExpiredSessions(Context *c, quint64 expires) final
virtual bool deleteSessionData(Context *c, const QString &sid, const QString &key) final