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 
13 using 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 
33 bool 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 
131 qint64 Upload::pos() const
132 {
133  Q_D(const Upload);
134  return d->pos;
135 }
136 
137 qint64 Upload::size() const
138 {
139  Q_D(const Upload);
140  return d->endOffset - d->startOffset;
141 }
142 
143 bool 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 
154 Upload::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 
179 Upload::~Upload()
180 {
181  delete d_ptr;
182 }
183 
185 {
186  Q_D(const Upload);
187  return d->name;
188 }
189 
190 qint64 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 
202 qint64 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 
214 qint64 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"
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
virtual bool atEnd() const const
virtual bool seek(qint64 pos)
virtual qint64 readLineData(char *data, qint64 maxlen) override
Definition: upload.cpp:202
bool remove()
QString errorString() const const
virtual qint64 writeData(const char *data, qint64 maxSize) override
Definition: upload.cpp:214
virtual bool open(QIODeviceBase::OpenMode mode)
QString contentType() const
Definition: upload.cpp:21
QByteArray read(qint64 maxSize)
Cutelyst Upload handles file upload request
Definition: upload.h:22
bool isEmpty() const const
qint64 write(const QByteArray &data)
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:7
virtual bool seek(qint64 pos) override
Definition: upload.cpp:143
Headers headers() const
Definition: upload.cpp:27
virtual void close() override
virtual bool seek(qint64 pos) override
QString filename() const
Definition: upload.cpp:15
bool save(const QString &filename)
Definition: upload.cpp:33
void setErrorString(const QString &str)
Upload(UploadPrivate *prv)
Definition: upload.cpp:154
virtual qint64 pos() const override
Definition: upload.cpp:131
virtual qint64 readData(char *data, qint64 maxlen) override
Definition: upload.cpp:190
QString arg(Args &&... args) const const
QTemporaryFile * createTemporaryFile(const QString &templateName=QString())
Definition: upload.cpp:83
virtual qint64 size() const override
Definition: upload.cpp:137
QString name() const
Definition: upload.cpp:184