cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
upload.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2014-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "common.h"
6#include "upload_p.h"
7
8#include <QDir>
9#include <QFile>
10#include <QFileInfo>
11#include <QTemporaryFile>
12
13using namespace Cutelyst;
14
16{
17 Q_D(const Upload);
18 return d->filename;
19}
20
22{
23 Q_D(const Upload);
24 return d->headers.contentType();
25}
26
28{
29 Q_D(const Upload);
30 return d->headers;
31}
32
33bool Upload::save(const QString &newName)
34{
35 Q_D(Upload);
36
37 bool error = false;
38 QString fileTemplate = QStringLiteral("%1/qt_temp.XXXXXX");
39 QFile out(fileTemplate.arg(QFileInfo(newName).path()));
40 if (!out.open(QIODevice::ReadWrite)) {
41 error = true;
42 }
43
44 if (error) {
45 out.close();
46 setErrorString(QLatin1String("Failed to open file for saving: ") + out.errorString());
47 qCWarning(CUTELYST_UPLOAD) << errorString();
48 } else {
49 qint64 posOrig = d->pos;
50 seek(0);
51
52 char block[4096];
53 while (!atEnd()) {
54 qint64 in = read(block, sizeof(block));
55 if (in <= 0)
56 break;
57 if (in != out.write(block, in)) {
58 setErrorString(QLatin1String("Failure to write block"));
59 qCWarning(CUTELYST_UPLOAD) << errorString();
60 error = true;
61 break;
62 }
63 }
64
65 if (error) {
66 out.remove();
67 }
68
69 if (!error && !out.rename(newName)) {
70 error = true;
71 setErrorString(QStringLiteral("Cannot create %1 for output").arg(newName));
72 qCWarning(CUTELYST_UPLOAD) << errorString();
73 }
74 if (error) {
75 out.remove();
76 }
77 seek(posOrig);
78 }
79
80 return !error;
81}
82
84{
85#ifndef QT_NO_TEMPORARYFILE
86 Q_D(Upload);
87 QTemporaryFile *ret;
88 if (templateName.isEmpty()) {
89 ret = new QTemporaryFile(this);
90 } else {
91 ret = new QTemporaryFile(templateName, this);
92 }
93
94 if (ret->open()) {
95 bool error = false;
96 qint64 posOrig = d->pos;
97 seek(0);
98
99 char block[4096];
100 while (!atEnd()) {
101 qint64 in = read(block, sizeof(block));
102 if (in <= 0)
103 break;
104
105 if (in != ret->write(block, in)) {
106 setErrorString(QLatin1String("Failure to write block"));
107 qCWarning(CUTELYST_UPLOAD) << errorString();
108 error = true;
109 break;
110 }
111 }
112
113 if (error) {
114 ret->remove();
115 }
116 ret->seek(0);
117 seek(posOrig);
118
119 return ret;
120 } else {
121 qCWarning(CUTELYST_UPLOAD) << "Failed to open temporary file.";
122 }
123 delete ret;
124#else
125 Q_UNUSED(templateName)
126#endif
127
128 return nullptr;
129}
130
131qint64 Upload::pos() const
132{
133 Q_D(const Upload);
134 return d->pos;
135}
136
137qint64 Upload::size() const
138{
139 Q_D(const Upload);
140 return d->endOffset - d->startOffset;
141}
142
143bool Upload::seek(qint64 pos)
144{
145 Q_D(Upload);
146 if (pos <= size()) {
148 d->pos = pos;
149 return true;
150 }
151 return false;
152}
153
154Upload::Upload(UploadPrivate *prv)
155 : d_ptr(prv)
156{
157 Q_D(Upload);
158 open(prv->device->openMode());
159 const QString disposition = prv->headers.contentDisposition();
160 int start = disposition.indexOf(u"name=\"");
161 if (start != -1) {
162 start += 6;
163 int end = disposition.indexOf(u'"', start);
164 if (end != -1) {
165 d->name = disposition.mid(start, end - start);
166 }
167 }
168
169 start = disposition.indexOf(u"filename=\"");
170 if (start != -1) {
171 start += 10;
172 int end = disposition.indexOf(QLatin1Char('"'), start);
173 if (end != -1) {
174 d->filename = disposition.mid(start, end - start);
175 }
176 }
177}
178
179Upload::~Upload()
180{
181 delete d_ptr;
182}
183
185{
186 Q_D(const Upload);
187 return d->name;
188}
189
190qint64 Upload::readData(char *data, qint64 maxlen)
191{
192 Q_D(Upload);
193 qint64 posOrig = d->device->pos();
194
195 d->device->seek(d->startOffset + d->pos);
196 qint64 len = d->device->read(data, qMin(size() - d->pos, maxlen));
197 d->device->seek(posOrig);
198 d->pos += len;
199 return len;
200}
201
202qint64 Upload::readLineData(char *data, qint64 maxlen)
203{
204 Q_D(Upload);
205 qint64 posOrig = d->device->pos();
206
207 d->device->seek(d->startOffset + d->pos);
208 qint64 len = d->device->readLine(data, qMin(size() - d->pos, maxlen));
209 d->device->seek(posOrig);
210 d->pos += len;
211 return len;
212}
213
214qint64 Upload::writeData(const char *data, qint64 maxSize)
215{
216 Q_UNUSED(data);
217 Q_UNUSED(maxSize);
218 return -1;
219}
220
221#include "moc_upload.cpp"
Upload(UploadPrivate *prv)
Definition upload.cpp:154
QString contentType() const
Definition upload.cpp:21
virtual bool seek(qint64 pos) override
Definition upload.cpp:143
virtual qint64 pos() const override
Definition upload.cpp:131
virtual qint64 readLineData(char *data, qint64 maxlen) override
Definition upload.cpp:202
QString filename() const
Definition upload.cpp:15
virtual qint64 writeData(const char *data, qint64 maxSize) override
Definition upload.cpp:214
QTemporaryFile * createTemporaryFile(const QString &templateName=QString())
Definition upload.cpp:83
QString name() const
Definition upload.cpp:184
Headers headers() const
Definition upload.cpp:27
virtual qint64 readData(char *data, qint64 maxlen) override
Definition upload.cpp:190
virtual qint64 size() const override
Definition upload.cpp:137
bool save(const QString &filename)
Definition upload.cpp:33
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
virtual bool open(OpenMode mode) override
bool remove()
bool rename(const QString &newName)
virtual void close() override
virtual bool seek(qint64 pos) override
virtual bool atEnd() const const
QString errorString() const const
virtual bool open(OpenMode mode)
qint64 read(char *data, qint64 maxSize)
virtual bool seek(qint64 pos)
void setErrorString(const QString &str)
qint64 write(const char *data, qint64 maxSize)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString mid(int position, int n) const const