diff options
Diffstat (limited to 'utils/rbutilqt/base/zipinstaller.cpp')
-rw-r--r-- | utils/rbutilqt/base/zipinstaller.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/utils/rbutilqt/base/zipinstaller.cpp b/utils/rbutilqt/base/zipinstaller.cpp new file mode 100644 index 0000000000..8de6c53b16 --- /dev/null +++ b/utils/rbutilqt/base/zipinstaller.cpp | |||
@@ -0,0 +1,204 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * | ||
11 | * All files in this archive are subject to the GNU General Public License. | ||
12 | * See the file COPYING in the source tree root for full license agreement. | ||
13 | * | ||
14 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
15 | * KIND, either express or implied. | ||
16 | * | ||
17 | ****************************************************************************/ | ||
18 | |||
19 | #include <QtCore> | ||
20 | #include "zipinstaller.h" | ||
21 | #include "utils.h" | ||
22 | #include "ziputil.h" | ||
23 | #include "Logger.h" | ||
24 | |||
25 | ZipInstaller::ZipInstaller(QObject* parent) : | ||
26 | QObject(parent), | ||
27 | m_unzip(true), m_usecache(false), m_getter(nullptr) | ||
28 | { | ||
29 | } | ||
30 | |||
31 | |||
32 | void ZipInstaller::install() | ||
33 | { | ||
34 | LOG_INFO() << "initializing installation"; | ||
35 | |||
36 | m_runner = 0; | ||
37 | connect(this, &ZipInstaller::cont, this, &ZipInstaller::installContinue); | ||
38 | m_url = m_urllist.at(m_runner); | ||
39 | m_logsection = m_loglist.at(m_runner); | ||
40 | m_logver = m_verlist.at(m_runner); | ||
41 | installStart(); | ||
42 | } | ||
43 | |||
44 | |||
45 | void ZipInstaller::abort() | ||
46 | { | ||
47 | LOG_INFO() << "Aborted"; | ||
48 | emit internalAborted(); | ||
49 | } | ||
50 | |||
51 | |||
52 | void ZipInstaller::installContinue() | ||
53 | { | ||
54 | LOG_INFO() << "continuing installation"; | ||
55 | |||
56 | m_runner++; // this gets called when a install finished, so increase first. | ||
57 | LOG_INFO() << "runner done:" << m_runner << "/" << m_urllist.size(); | ||
58 | if(m_runner < m_urllist.size()) { | ||
59 | emit logItem(tr("done."), LOGOK); | ||
60 | m_url = m_urllist.at(m_runner); | ||
61 | m_logsection = m_loglist.at(m_runner); | ||
62 | if(m_runner < m_verlist.size()) m_logver = m_verlist.at(m_runner); | ||
63 | else m_logver = ""; | ||
64 | installStart(); | ||
65 | } | ||
66 | else { | ||
67 | emit logItem(tr("Package installation finished successfully."), LOGOK); | ||
68 | emit done(false); | ||
69 | return; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | |||
74 | void ZipInstaller::installStart() | ||
75 | { | ||
76 | LOG_INFO() << "starting installation"; | ||
77 | |||
78 | emit logItem(tr("Downloading file %1.%2").arg(QFileInfo(m_url).baseName(), | ||
79 | QFileInfo(m_url).completeSuffix()),LOGINFO); | ||
80 | |||
81 | // temporary file needs to be opened to get the filename | ||
82 | // make sure to get a fresh one on each run. | ||
83 | // making this a parent of the temporary file ensures the file gets deleted | ||
84 | // after the class object gets destroyed. | ||
85 | m_downloadFile = new QTemporaryFile(this); | ||
86 | m_downloadFile->open(); | ||
87 | m_file = m_downloadFile->fileName(); | ||
88 | m_downloadFile->close(); | ||
89 | // get the real file. | ||
90 | if(m_getter != nullptr) m_getter->deleteLater(); | ||
91 | m_getter = new HttpGet(this); | ||
92 | if(m_usecache) { | ||
93 | m_getter->setCache(true); | ||
94 | } | ||
95 | m_getter->setFile(m_downloadFile); | ||
96 | |||
97 | connect(m_getter, &HttpGet::done, this, &ZipInstaller::downloadDone); | ||
98 | connect(m_getter, &HttpGet::dataReadProgress, this, &ZipInstaller::logProgress); | ||
99 | connect(this, &ZipInstaller::internalAborted, m_getter, &HttpGet::abort); | ||
100 | |||
101 | m_getter->getFile(QUrl(m_url)); | ||
102 | } | ||
103 | |||
104 | |||
105 | void ZipInstaller::downloadDone(bool error) | ||
106 | { | ||
107 | LOG_INFO() << "download done, error:" << error; | ||
108 | QStringList zipContents; // needed later | ||
109 | // update progress bar | ||
110 | |||
111 | emit logProgress(1, 1); | ||
112 | if(m_getter->httpResponse() != 200 && !m_getter->isCached()) { | ||
113 | emit logItem(tr("Download error: received HTTP error %1\n%2") | ||
114 | .arg(m_getter->httpResponse()).arg(m_getter->errorString()), | ||
115 | LOGERROR); | ||
116 | emit done(true); | ||
117 | return; | ||
118 | } | ||
119 | if(m_getter->isCached()) | ||
120 | emit logItem(tr("Cached file used."), LOGINFO); | ||
121 | if(error) { | ||
122 | emit logItem(tr("Download error: %1").arg(m_getter->errorString()), LOGERROR); | ||
123 | emit done(true); | ||
124 | return; | ||
125 | } | ||
126 | else emit logItem(tr("Download finished."),LOGOK); | ||
127 | QCoreApplication::processEvents(); | ||
128 | if(m_unzip) { | ||
129 | // unzip downloaded file | ||
130 | LOG_INFO() << "about to unzip" << m_file << "to" << m_mountpoint; | ||
131 | |||
132 | emit logItem(tr("Extracting file."), LOGINFO); | ||
133 | QCoreApplication::processEvents(); | ||
134 | |||
135 | ZipUtil zip(this); | ||
136 | connect(&zip, &ZipUtil::logProgress, this, &ZipInstaller::logProgress); | ||
137 | connect(&zip, &ZipUtil::logItem, this, &ZipInstaller::logItem); | ||
138 | zip.open(m_file, QuaZip::mdUnzip); | ||
139 | // check for free space. Make sure after installation will still be | ||
140 | // some room for operating (also includes calculation mistakes due to | ||
141 | // cluster sizes on the player). | ||
142 | if((qint64)Utils::filesystemFree(m_mountpoint) | ||
143 | < (zip.totalUncompressedSize( | ||
144 | Utils::filesystemSize(m_mountpoint, Utils::FilesystemClusterSize)) | ||
145 | + 1000000)) { | ||
146 | emit logItem(tr("Not enough disk space! Aborting."), LOGERROR); | ||
147 | emit logProgress(1, 1); | ||
148 | emit done(true); | ||
149 | return; | ||
150 | } | ||
151 | zipContents = zip.files(); | ||
152 | if(!zip.extractArchive(m_mountpoint)) { | ||
153 | emit logItem(tr("Extraction failed!"), LOGERROR); | ||
154 | emit logProgress(1, 1); | ||
155 | emit done(true); | ||
156 | return; | ||
157 | } | ||
158 | zip.close(); | ||
159 | } | ||
160 | else { | ||
161 | if (m_target.isEmpty()) | ||
162 | m_target = QUrl(m_url).fileName(); | ||
163 | QString destfile = m_mountpoint + "/" + m_target; | ||
164 | // only copy the downloaded file to the output location / name | ||
165 | emit logItem(tr("Installing file."), LOGINFO); | ||
166 | LOG_INFO() << "saving downloaded file (no extraction) to" << destfile; | ||
167 | |||
168 | m_downloadFile->open(); // copy fails if file is not opened (filename issue?) | ||
169 | // make sure the required path is existing | ||
170 | QString path = QFileInfo(destfile).absolutePath(); | ||
171 | QDir p; | ||
172 | p.mkpath(path); | ||
173 | // QFile::copy() doesn't overwrite files, so remove old one first | ||
174 | // TODO: compare old and new file and fail if those are different. | ||
175 | QFile(destfile).remove(); | ||
176 | if(!m_downloadFile->copy(destfile)) { | ||
177 | emit logItem(tr("Installing file failed."), LOGERROR); | ||
178 | emit done(true); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | // add file to log | ||
183 | zipContents.append(m_target); | ||
184 | } | ||
185 | if(m_logver.isEmpty()) { | ||
186 | // if no version info is set use the timestamp of the server file. | ||
187 | m_logver = m_getter->timestamp().toString(Qt::ISODate); | ||
188 | } | ||
189 | |||
190 | emit logItem(tr("Creating installation log"),LOGINFO); | ||
191 | QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, nullptr); | ||
192 | |||
193 | installlog.beginGroup(m_logsection); | ||
194 | for(int i = 0; i < zipContents.size(); i++) | ||
195 | { | ||
196 | installlog.setValue(zipContents.at(i), m_logver); | ||
197 | } | ||
198 | installlog.endGroup(); | ||
199 | installlog.sync(); | ||
200 | |||
201 | emit cont(); | ||
202 | } | ||
203 | |||
204 | |||