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