diff options
Diffstat (limited to 'rbutil/rbutilqt/base')
22 files changed, 2837 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/base/autodetection.cpp b/rbutil/rbutilqt/base/autodetection.cpp new file mode 100644 index 0000000000..67e95b998d --- /dev/null +++ b/rbutil/rbutilqt/base/autodetection.cpp | |||
@@ -0,0 +1,391 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include "autodetection.h" | ||
22 | |||
23 | #if defined(Q_OS_LINUX) || defined(Q_OS_MACX) | ||
24 | #include <stdio.h> | ||
25 | #include <usb.h> | ||
26 | #endif | ||
27 | #if defined(Q_OS_LINUX) | ||
28 | #include <mntent.h> | ||
29 | #endif | ||
30 | #if defined(Q_OS_MACX) | ||
31 | #include <sys/param.h> | ||
32 | #include <sys/ucred.h> | ||
33 | #include <sys/mount.h> | ||
34 | #endif | ||
35 | #if defined(Q_OS_WIN32) | ||
36 | #if defined(UNICODE) | ||
37 | #define _UNICODE | ||
38 | #endif | ||
39 | #include <stdio.h> | ||
40 | #include <tchar.h> | ||
41 | #include <windows.h> | ||
42 | #include <setupapi.h> | ||
43 | #include <winioctl.h> | ||
44 | #endif | ||
45 | #include "detect.h" | ||
46 | #include "utils.h" | ||
47 | |||
48 | Autodetection::Autodetection(QObject* parent): QObject(parent) | ||
49 | { | ||
50 | |||
51 | } | ||
52 | |||
53 | bool Autodetection::detect() | ||
54 | { | ||
55 | m_device = ""; | ||
56 | m_mountpoint = ""; | ||
57 | m_errdev = ""; | ||
58 | |||
59 | detectUsb(); | ||
60 | |||
61 | // Try detection via rockbox.info / rbutil.log | ||
62 | QStringList mountpoints = getMountpoints(); | ||
63 | |||
64 | for(int i=0; i< mountpoints.size();i++) | ||
65 | { | ||
66 | // do the file checking | ||
67 | QDir dir(mountpoints.at(i)); | ||
68 | qDebug() << "paths to check for player specific files:" << mountpoints; | ||
69 | if(dir.exists()) | ||
70 | { | ||
71 | // check logfile first. | ||
72 | if(QFile(mountpoints.at(i) + "/.rockbox/rbutil.log").exists()) { | ||
73 | QSettings log(mountpoints.at(i) + "/.rockbox/rbutil.log", | ||
74 | QSettings::IniFormat, this); | ||
75 | if(!log.value("platform").toString().isEmpty()) { | ||
76 | if(m_device.isEmpty()) | ||
77 | m_device = log.value("platform").toString(); | ||
78 | m_mountpoint = mountpoints.at(i); | ||
79 | qDebug() << "rbutil.log detected:" << m_device << m_mountpoint; | ||
80 | return true; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | // check rockbox-info.txt afterwards. | ||
85 | QFile file(mountpoints.at(i) + "/.rockbox/rockbox-info.txt"); | ||
86 | if(file.exists()) | ||
87 | { | ||
88 | file.open(QIODevice::ReadOnly | QIODevice::Text); | ||
89 | QString line = file.readLine(); | ||
90 | if(line.startsWith("Target: ")) | ||
91 | { | ||
92 | line.remove("Target: "); | ||
93 | if(m_device.isEmpty()) | ||
94 | m_device = line.trimmed(); // trim whitespaces | ||
95 | m_mountpoint = mountpoints.at(i); | ||
96 | qDebug() << "rockbox-info.txt detected:" << m_device << m_mountpoint; | ||
97 | return true; | ||
98 | } | ||
99 | } | ||
100 | // check for some specific files in root folder | ||
101 | QDir root(mountpoints.at(i)); | ||
102 | QStringList rootentries = root.entryList(QDir::Files); | ||
103 | if(rootentries.contains("archos.mod", Qt::CaseInsensitive)) | ||
104 | { | ||
105 | // archos.mod in root folder -> Archos Player | ||
106 | m_device = "player"; | ||
107 | m_mountpoint = mountpoints.at(i); | ||
108 | return true; | ||
109 | } | ||
110 | if(rootentries.contains("ONDIOST.BIN", Qt::CaseInsensitive)) | ||
111 | { | ||
112 | // ONDIOST.BIN in root -> Ondio FM | ||
113 | m_device = "ondiofm"; | ||
114 | m_mountpoint = mountpoints.at(i); | ||
115 | return true; | ||
116 | } | ||
117 | if(rootentries.contains("ONDIOSP.BIN", Qt::CaseInsensitive)) | ||
118 | { | ||
119 | // ONDIOSP.BIN in root -> Ondio SP | ||
120 | m_device = "ondiosp"; | ||
121 | m_mountpoint = mountpoints.at(i); | ||
122 | return true; | ||
123 | } | ||
124 | if(rootentries.contains("ajbrec.ajz", Qt::CaseInsensitive)) | ||
125 | { | ||
126 | qDebug() << "ajbrec.ajz found. Trying detectAjbrec()"; | ||
127 | if(detectAjbrec(mountpoints.at(i))) { | ||
128 | m_mountpoint = mountpoints.at(i); | ||
129 | qDebug() << m_device; | ||
130 | return true; | ||
131 | } | ||
132 | } | ||
133 | // detection based on player specific folders | ||
134 | QStringList rootfolders = root.entryList(QDir::Dirs | ||
135 | | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); | ||
136 | if(rootfolders.contains("GBSYSTEM", Qt::CaseInsensitive)) | ||
137 | { | ||
138 | // GBSYSTEM folder -> Gigabeat | ||
139 | m_device = "gigabeatf"; | ||
140 | m_mountpoint = mountpoints.at(i); | ||
141 | return true; | ||
142 | } | ||
143 | #if defined(Q_OS_WIN32) | ||
144 | // on windows, try to detect the drive letter of an Ipod | ||
145 | if(rootfolders.contains("iPod_Control", Qt::CaseInsensitive)) | ||
146 | { | ||
147 | // iPod_Control folder -> Ipod found | ||
148 | // detecting of the Ipod type is done below using ipodpatcher | ||
149 | m_mountpoint = mountpoints.at(i); | ||
150 | } | ||
151 | #endif | ||
152 | } | ||
153 | |||
154 | } | ||
155 | |||
156 | int n; | ||
157 | // try ipodpatcher | ||
158 | // initialize sector buffer. Needed. | ||
159 | ipod_sectorbuf = NULL; | ||
160 | ipod_alloc_buffer(&ipod_sectorbuf, BUFFER_SIZE); | ||
161 | struct ipod_t ipod; | ||
162 | n = ipod_scan(&ipod); | ||
163 | if(n == 1) { | ||
164 | qDebug() << "Ipod found:" << ipod.modelstr << "at" << ipod.diskname; | ||
165 | m_device = ipod.targetname; | ||
166 | m_mountpoint = resolveMountPoint(ipod.diskname); | ||
167 | return true; | ||
168 | } | ||
169 | else { | ||
170 | qDebug() << "ipodpatcher: no Ipod found." << n; | ||
171 | } | ||
172 | free(ipod_sectorbuf); | ||
173 | ipod_sectorbuf = NULL; | ||
174 | |||
175 | // try sansapatcher | ||
176 | // initialize sector buffer. Needed. | ||
177 | sansa_sectorbuf = NULL; | ||
178 | sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE); | ||
179 | struct sansa_t sansa; | ||
180 | n = sansa_scan(&sansa); | ||
181 | if(n == 1) { | ||
182 | qDebug() << "Sansa found:" << sansa.targetname << "at" << sansa.diskname; | ||
183 | m_device = QString("sansa%1").arg(sansa.targetname); | ||
184 | m_mountpoint = resolveMountPoint(sansa.diskname); | ||
185 | return true; | ||
186 | } | ||
187 | else { | ||
188 | qDebug() << "sansapatcher: no Sansa found." << n; | ||
189 | } | ||
190 | free(sansa_sectorbuf); | ||
191 | sansa_sectorbuf = NULL; | ||
192 | |||
193 | if(m_mountpoint.isEmpty() && m_device.isEmpty() && m_errdev.isEmpty() && m_incompat.isEmpty()) | ||
194 | return false; | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | |||
199 | QStringList Autodetection::getMountpoints() | ||
200 | { | ||
201 | QStringList tempList; | ||
202 | #if defined(Q_OS_WIN32) | ||
203 | QFileInfoList list = QDir::drives(); | ||
204 | for(int i=0; i<list.size();i++) | ||
205 | { | ||
206 | tempList << list.at(i).absolutePath(); | ||
207 | } | ||
208 | |||
209 | #elif defined(Q_OS_MACX) | ||
210 | int num; | ||
211 | struct statfs *mntinf; | ||
212 | |||
213 | num = getmntinfo(&mntinf, MNT_WAIT); | ||
214 | while(num--) { | ||
215 | tempList << QString(mntinf->f_mntonname); | ||
216 | mntinf++; | ||
217 | } | ||
218 | #elif defined(Q_OS_LINUX) | ||
219 | |||
220 | FILE *mn = setmntent("/etc/mtab", "r"); | ||
221 | if(!mn) | ||
222 | return QStringList(""); | ||
223 | |||
224 | struct mntent *ent; | ||
225 | while((ent = getmntent(mn))) | ||
226 | tempList << QString(ent->mnt_dir); | ||
227 | endmntent(mn); | ||
228 | |||
229 | #else | ||
230 | #error Unknown Plattform | ||
231 | #endif | ||
232 | return tempList; | ||
233 | } | ||
234 | |||
235 | QString Autodetection::resolveMountPoint(QString device) | ||
236 | { | ||
237 | qDebug() << "Autodetection::resolveMountPoint(QString)" << device; | ||
238 | |||
239 | #if defined(Q_OS_LINUX) | ||
240 | FILE *mn = setmntent("/etc/mtab", "r"); | ||
241 | if(!mn) | ||
242 | return QString(""); | ||
243 | |||
244 | struct mntent *ent; | ||
245 | while((ent = getmntent(mn))) { | ||
246 | if(QString(ent->mnt_fsname).startsWith(device) | ||
247 | && QString(ent->mnt_type).contains("vfat", Qt::CaseInsensitive)) { | ||
248 | endmntent(mn); | ||
249 | return QString(ent->mnt_dir); | ||
250 | } | ||
251 | } | ||
252 | endmntent(mn); | ||
253 | |||
254 | #endif | ||
255 | |||
256 | #if defined(Q_OS_MACX) | ||
257 | int num; | ||
258 | struct statfs *mntinf; | ||
259 | |||
260 | num = getmntinfo(&mntinf, MNT_WAIT); | ||
261 | while(num--) { | ||
262 | if(QString(mntinf->f_mntfromname).startsWith(device) | ||
263 | && QString(mntinf->f_fstypename).contains("vfat", Qt::CaseInsensitive)) | ||
264 | return QString(mntinf->f_mntonname); | ||
265 | mntinf++; | ||
266 | } | ||
267 | #endif | ||
268 | |||
269 | #if defined(Q_OS_WIN32) | ||
270 | QString result; | ||
271 | unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt(); | ||
272 | |||
273 | for(int letter = 'A'; letter <= 'Z'; letter++) { | ||
274 | DWORD written; | ||
275 | HANDLE h; | ||
276 | TCHAR uncpath[MAX_PATH]; | ||
277 | UCHAR buffer[0x400]; | ||
278 | PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer; | ||
279 | |||
280 | _stprintf(uncpath, _TEXT("\\\\.\\%c:"), letter); | ||
281 | h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, | ||
282 | NULL, OPEN_EXISTING, 0, NULL); | ||
283 | if(h == INVALID_HANDLE_VALUE) { | ||
284 | //qDebug() << "error getting extents for" << uncpath; | ||
285 | continue; | ||
286 | } | ||
287 | // get the extents | ||
288 | if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, | ||
289 | NULL, 0, extents, sizeof(buffer), &written, NULL)) { | ||
290 | for(unsigned int a = 0; a < extents->NumberOfDiskExtents; a++) { | ||
291 | qDebug() << "Disk:" << extents->Extents[a].DiskNumber; | ||
292 | if(extents->Extents[a].DiskNumber == driveno) { | ||
293 | result = letter; | ||
294 | qDebug("drive found for volume %i: %c", driveno, letter); | ||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | } | ||
300 | |||
301 | } | ||
302 | if(!result.isEmpty()) | ||
303 | return result + ":/"; | ||
304 | #endif | ||
305 | return QString(""); | ||
306 | } | ||
307 | |||
308 | |||
309 | /** @brief detect devices based on usb pid / vid. | ||
310 | * @return true upon success, false otherwise. | ||
311 | */ | ||
312 | bool Autodetection::detectUsb() | ||
313 | { | ||
314 | // usbids holds the mapping in the form | ||
315 | // ((VID<<16)|(PID)), targetname | ||
316 | // the ini file needs to hold the IDs as hex values. | ||
317 | QMap<int, QString> usbids = settings->usbIdMap(); | ||
318 | QMap<int, QString> usberror = settings->usbIdErrorMap(); | ||
319 | QMap<int, QString> usbincompat = settings->usbIdIncompatMap(); | ||
320 | |||
321 | // usb pid detection | ||
322 | QList<uint32_t> attached; | ||
323 | attached = Detect::listUsbIds(); | ||
324 | |||
325 | int i = attached.size(); | ||
326 | while(i--) { | ||
327 | if(usbids.contains(attached.at(i))) { | ||
328 | m_device = usbids.value(attached.at(i)); | ||
329 | qDebug() << "[USB] detected supported player" << m_device; | ||
330 | return true; | ||
331 | } | ||
332 | if(usberror.contains(attached.at(i))) { | ||
333 | m_errdev = usberror.value(attached.at(i)); | ||
334 | qDebug() << "[USB] detected problem with player" << m_errdev; | ||
335 | return true; | ||
336 | } | ||
337 | if(usbincompat.contains(attached.at(i))) { | ||
338 | m_incompat = usbincompat.value(attached.at(i)); | ||
339 | qDebug() << "[USB] detected incompatible player" << m_incompat; | ||
340 | return true; | ||
341 | } | ||
342 | } | ||
343 | return false; | ||
344 | } | ||
345 | |||
346 | |||
347 | bool Autodetection::detectAjbrec(QString root) | ||
348 | { | ||
349 | QFile f(root + "/ajbrec.ajz"); | ||
350 | char header[24]; | ||
351 | f.open(QIODevice::ReadOnly); | ||
352 | if(!f.read(header, 24)) return false; | ||
353 | |||
354 | // check the header of the file. | ||
355 | // recorder v1 had a 6 bytes sized header | ||
356 | // recorder v2, FM, Ondio SP and FM have a 24 bytes header. | ||
357 | |||
358 | // recorder v1 has the binary length in the first 4 bytes, so check | ||
359 | // for them first. | ||
360 | int len = (header[0]<<24) | (header[1]<<16) | (header[2]<<8) | header[3]; | ||
361 | qDebug() << "possible bin length:" << len; | ||
362 | qDebug() << "file len:" << f.size(); | ||
363 | if((f.size() - 6) == len) | ||
364 | m_device = "recorder"; | ||
365 | |||
366 | // size didn't match, now we need to assume we have a headerlength of 24. | ||
367 | switch(header[11]) { | ||
368 | case 2: | ||
369 | m_device = "recorderv2"; | ||
370 | break; | ||
371 | |||
372 | case 4: | ||
373 | m_device = "fmrecorder"; | ||
374 | break; | ||
375 | |||
376 | case 8: | ||
377 | m_device = "ondiofm"; | ||
378 | break; | ||
379 | |||
380 | case 16: | ||
381 | m_device = "ondiosp"; | ||
382 | break; | ||
383 | |||
384 | default: | ||
385 | break; | ||
386 | } | ||
387 | f.close(); | ||
388 | |||
389 | if(m_device.isEmpty()) return false; | ||
390 | return true; | ||
391 | } | ||
diff --git a/rbutil/rbutilqt/base/autodetection.h b/rbutil/rbutilqt/base/autodetection.h new file mode 100644 index 0000000000..1fbe47f9a7 --- /dev/null +++ b/rbutil/rbutilqt/base/autodetection.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * $Id$ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #ifndef AUTODETECTION_H_ | ||
24 | #define AUTODETECTION_H_ | ||
25 | |||
26 | #include <QtCore> | ||
27 | #include "rbsettings.h" | ||
28 | |||
29 | #include "../ipodpatcher/ipodpatcher.h" | ||
30 | #include "../sansapatcher/sansapatcher.h" | ||
31 | |||
32 | class Autodetection :public QObject | ||
33 | { | ||
34 | Q_OBJECT | ||
35 | |||
36 | public: | ||
37 | Autodetection(QObject* parent=0); | ||
38 | |||
39 | void setSettings(RbSettings* sett) {settings = sett;} | ||
40 | |||
41 | bool detect(); | ||
42 | |||
43 | QString getDevice() {return m_device;} | ||
44 | QString getMountPoint() {return m_mountpoint;} | ||
45 | QString errdev(void) { return m_errdev; } | ||
46 | QString incompatdev(void) { return m_incompat; } | ||
47 | |||
48 | private: | ||
49 | QStringList getMountpoints(void); | ||
50 | QString resolveMountPoint(QString); | ||
51 | bool detectUsb(void); | ||
52 | bool detectAjbrec(QString); | ||
53 | |||
54 | QString m_device; | ||
55 | QString m_mountpoint; | ||
56 | QString m_errdev; | ||
57 | QString m_incompat; | ||
58 | QList<int> m_usbconid; | ||
59 | RbSettings* settings; | ||
60 | }; | ||
61 | |||
62 | |||
63 | #endif /*AUTODETECTION_H_*/ | ||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallbase.cpp b/rbutil/rbutilqt/base/bootloaderinstallbase.cpp new file mode 100644 index 0000000000..d0abffa44d --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallbase.cpp | |||
@@ -0,0 +1,184 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | |||
21 | #include <QtCore> | ||
22 | |||
23 | #include "bootloaderinstallbase.h" | ||
24 | #include "utils.h" | ||
25 | |||
26 | BootloaderInstallBase::BootloaderType BootloaderInstallBase::installed(void) | ||
27 | { | ||
28 | return BootloaderUnknown; | ||
29 | } | ||
30 | |||
31 | |||
32 | BootloaderInstallBase::Capabilities BootloaderInstallBase::capabilities(void) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | |||
38 | void BootloaderInstallBase::downloadBlStart(QUrl source) | ||
39 | { | ||
40 | m_http.setFile(&m_tempfile); | ||
41 | m_http.setCache(true); | ||
42 | connect(&m_http, SIGNAL(done(bool)), this, SLOT(downloadBlFinish(bool))); | ||
43 | // connect the http read signal to our logProgess *signal* | ||
44 | // to immediately emit it without any helper function. | ||
45 | connect(&m_http, SIGNAL(dataReadProgress(int, int)), | ||
46 | this, SIGNAL(logProgress(int, int))); | ||
47 | m_http.getFile(source); | ||
48 | } | ||
49 | |||
50 | |||
51 | void BootloaderInstallBase::downloadReqFinished(int id, bool error) | ||
52 | { | ||
53 | qDebug() << __FILE__ << "::" << __func__ << id << error; | ||
54 | qDebug() << "error:" << m_http.errorString(); | ||
55 | |||
56 | downloadBlFinish(error); | ||
57 | } | ||
58 | |||
59 | |||
60 | void BootloaderInstallBase::downloadBlFinish(bool error) | ||
61 | { | ||
62 | qDebug() << __FILE__ << "::" << __func__ << ": error =" << error; | ||
63 | |||
64 | // update progress bar | ||
65 | emit logProgress(100, 100); | ||
66 | |||
67 | if(m_http.httpResponse() != 200) { | ||
68 | emit logItem(tr("Download error: received HTTP error %1.") | ||
69 | .arg(m_http.errorString()), LOGERROR); | ||
70 | emit done(true); | ||
71 | return; | ||
72 | } | ||
73 | if(error) { | ||
74 | emit logItem(tr("Download error: %1") | ||
75 | .arg(m_http.error()), LOGERROR); | ||
76 | emit done(true); | ||
77 | return; | ||
78 | } | ||
79 | else if(m_http.isCached()) | ||
80 | emit logItem(tr("Download finished (cache used)."), LOGOK); | ||
81 | else | ||
82 | emit logItem(tr("Download finished."), LOGOK); | ||
83 | |||
84 | m_blversion = m_http.timestamp(); | ||
85 | emit downloadDone(); | ||
86 | } | ||
87 | |||
88 | void BootloaderInstallBase::installBlfile(void) | ||
89 | { | ||
90 | qDebug() << __FILE__ << __func__; | ||
91 | } | ||
92 | |||
93 | |||
94 | //! @brief backup OF file. | ||
95 | //! @param to folder to write backup file to. Folder will get created. | ||
96 | //! @return true on success, false on error. | ||
97 | |||
98 | bool BootloaderInstallBase::backup(QString to) | ||
99 | { | ||
100 | qDebug() << __func__; | ||
101 | QDir targetDir("."); | ||
102 | emit logItem(tr("Creating backup of original firmware file."), LOGINFO); | ||
103 | if(!targetDir.mkpath(to)) { | ||
104 | emit logItem(tr("Creating backup folder failed"), LOGERROR); | ||
105 | return false; | ||
106 | } | ||
107 | QString tofile = to + "/" + QFileInfo(m_blfile).fileName(); | ||
108 | qDebug() << "trying to backup" << m_blfile << "to" << tofile; | ||
109 | if(!QFile::copy(resolvePathCase(m_blfile), tofile)) { | ||
110 | emit logItem(tr("Creating backup copy failed."), LOGERROR); | ||
111 | return false; | ||
112 | } | ||
113 | emit logItem(tr("Backup created."), LOGOK); | ||
114 | return true; | ||
115 | } | ||
116 | |||
117 | |||
118 | //! @brief log installation to logfile. | ||
119 | //! @param mode action to perform. 0: add to log, 1: remove from log. | ||
120 | //! @return 0 on success | ||
121 | int BootloaderInstallBase::logInstall(LogMode mode) | ||
122 | { | ||
123 | int result = 0; | ||
124 | QString section = m_blurl.path().section('/', -1); | ||
125 | QSettings s(m_logfile, QSettings::IniFormat, this); | ||
126 | emit logItem(tr("Creating installation log"), LOGINFO); | ||
127 | |||
128 | if(mode == LogAdd) { | ||
129 | s.setValue("Bootloader/" + section, m_blversion.toString(Qt::ISODate)); | ||
130 | qDebug() << m_blversion.toString(Qt::ISODate); | ||
131 | } | ||
132 | else { | ||
133 | s.remove("Bootloader/" + section); | ||
134 | } | ||
135 | s.sync(); | ||
136 | |||
137 | return result; | ||
138 | } | ||
139 | |||
140 | |||
141 | //! @brief Return post install hints string. | ||
142 | //! @param model model string | ||
143 | //! @return hints. | ||
144 | QString BootloaderInstallBase::postinstallHints(QString model) | ||
145 | { | ||
146 | bool hint = false; | ||
147 | QString msg = tr("Bootloader installation is almost complete. " | ||
148 | "Installation <b>requires</b> you to perform the " | ||
149 | "following steps manually:"); | ||
150 | |||
151 | msg += tr("<ol>"); | ||
152 | msg += tr("<li>Safely remove your player.</li>"); | ||
153 | if(model == "h100" || model == "h120" || model == "h300") { | ||
154 | hint = true; | ||
155 | msg += tr("<li>Reboot your player into the original firmware.</li>" | ||
156 | "<li>Perform a firmware upgrade using the update functionality " | ||
157 | "of the original firmware. Please refer to your player's manual " | ||
158 | "on details.</li>" | ||
159 | "<li>After the firmware has been updated reboot your player.</li>"); | ||
160 | } | ||
161 | if(model == "iaudiox5" || model == "iaudiom5" | ||
162 | || model == "iaudiox5v" || model == "iaudiom3") { | ||
163 | hint = true; | ||
164 | msg += tr("<li>Turn the player off</li>" | ||
165 | "<li>Insert the charger</li>"); | ||
166 | } | ||
167 | if(model == "gigabeatf") { | ||
168 | hint = true; | ||
169 | msg += tr("<li>Unplug USB and power adaptors</li>" | ||
170 | "<li>Hold <i>Power</i> to turn the player off</li>" | ||
171 | "<li>Toggle the battery switch on the player</li>" | ||
172 | "<li>Hold <i>Power</i> to boot into Rockbox</li>"); | ||
173 | } | ||
174 | |||
175 | msg += "</ol>"; | ||
176 | msg += tr("<p><b>Note:</b> You can safely install other parts first, but " | ||
177 | "the above steps are <b>required</b> to finish the installation!</p>"); | ||
178 | |||
179 | if(hint) | ||
180 | return msg; | ||
181 | else | ||
182 | return QString(""); | ||
183 | } | ||
184 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallbase.h b/rbutil/rbutilqt/base/bootloaderinstallbase.h new file mode 100644 index 0000000000..0916935208 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallbase.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef BOOTLOADERINSTALLBASE_H | ||
21 | #define BOOTLOADERINSTALLBASE_H | ||
22 | |||
23 | #include <QtCore> | ||
24 | #include "progressloggerinterface.h" | ||
25 | #include "httpget.h" | ||
26 | |||
27 | |||
28 | class BootloaderInstallBase : public QObject | ||
29 | { | ||
30 | Q_OBJECT | ||
31 | |||
32 | public: | ||
33 | enum Capability | ||
34 | { Install = 0x01, Uninstall = 0x02, Backup = 0x04, | ||
35 | IsFile = 0x08, IsRaw = 0x10, NeedsFlashing = 0x20, | ||
36 | CanCheckInstalled = 0x40, CanCheckVersion = 0x80 }; | ||
37 | Q_DECLARE_FLAGS(Capabilities, Capability) | ||
38 | |||
39 | enum BootloaderType | ||
40 | { BootloaderNone, BootloaderRockbox, BootloaderOther, BootloaderUnknown }; | ||
41 | |||
42 | BootloaderInstallBase(QObject *parent = 0) : QObject(parent) | ||
43 | { } | ||
44 | |||
45 | virtual bool install(void) | ||
46 | { return false; } | ||
47 | virtual bool uninstall(void) | ||
48 | { return false; } | ||
49 | virtual BootloaderType installed(void); | ||
50 | virtual Capabilities capabilities(void); | ||
51 | bool backup(QString to); | ||
52 | |||
53 | void setBlFile(QString f) | ||
54 | { m_blfile = f; } | ||
55 | void setBlUrl(QUrl u) | ||
56 | { m_blurl = u; } | ||
57 | void setLogfile(QString f) | ||
58 | { m_logfile = f; } | ||
59 | |||
60 | static QString postinstallHints(QString model); | ||
61 | |||
62 | protected slots: | ||
63 | void downloadReqFinished(int id, bool error); | ||
64 | void downloadBlFinish(bool error); | ||
65 | void installBlfile(void); | ||
66 | protected: | ||
67 | enum LogMode | ||
68 | { LogAdd, LogRemove }; | ||
69 | |||
70 | void downloadBlStart(QUrl source); | ||
71 | int logInstall(LogMode mode); | ||
72 | |||
73 | HttpGet m_http; //! http download object | ||
74 | QString m_blfile; //! bootloader filename on player | ||
75 | QString m_logfile; //! file for installation log | ||
76 | QUrl m_blurl; //! bootloader download URL | ||
77 | QTemporaryFile m_tempfile; //! temporary file for download | ||
78 | QDateTime m_blversion; //! download timestamp used for version information | ||
79 | |||
80 | signals: | ||
81 | void downloadDone(void); //! internal signal sent when download finished. | ||
82 | void done(bool); | ||
83 | void logItem(QString, int); //! set logger item | ||
84 | void logProgress(int, int); //! set progress bar. | ||
85 | }; | ||
86 | |||
87 | Q_DECLARE_OPERATORS_FOR_FLAGS(BootloaderInstallBase::Capabilities) | ||
88 | |||
89 | #endif | ||
90 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallfile.cpp b/rbutil/rbutilqt/base/bootloaderinstallfile.cpp new file mode 100644 index 0000000000..daa1ad8af7 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallfile.cpp | |||
@@ -0,0 +1,145 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include <QtDebug> | ||
22 | #include <QtDebug> | ||
23 | #include "bootloaderinstallfile.h" | ||
24 | #include "utils.h" | ||
25 | |||
26 | |||
27 | BootloaderInstallFile::BootloaderInstallFile(QObject *parent) | ||
28 | : BootloaderInstallBase(parent) | ||
29 | { | ||
30 | } | ||
31 | |||
32 | |||
33 | bool BootloaderInstallFile::install(void) | ||
34 | { | ||
35 | emit logItem(tr("Downloading bootloader"), LOGINFO); | ||
36 | qDebug() << __func__; | ||
37 | downloadBlStart(m_blurl); | ||
38 | connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2())); | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | void BootloaderInstallFile::installStage2(void) | ||
43 | { | ||
44 | emit logItem(tr("Installing Rockbox bootloader"), LOGINFO); | ||
45 | |||
46 | // if an old bootloader is present (Gigabeat) move it out of the way. | ||
47 | QString fwfile(resolvePathCase(m_blfile)); | ||
48 | if(!fwfile.isEmpty()) { | ||
49 | QString moved = resolvePathCase(m_blfile) + ".ORIG"; | ||
50 | qDebug() << "renaming" << fwfile << "->" << moved; | ||
51 | QFile::rename(fwfile, moved); | ||
52 | } | ||
53 | |||
54 | // if no old file found resolve path without basename | ||
55 | QFileInfo fi(m_blfile); | ||
56 | QString absPath = resolvePathCase(fi.absolutePath()); | ||
57 | |||
58 | // if it's not possible to locate the base path try to create it | ||
59 | if(absPath.isEmpty()) { | ||
60 | QStringList pathElements = m_blfile.split("/"); | ||
61 | // remove filename from list and save last path element | ||
62 | pathElements.removeLast(); | ||
63 | QString lastElement = pathElements.last(); | ||
64 | // remove last path element for base | ||
65 | pathElements.removeLast(); | ||
66 | QString basePath = pathElements.join("/"); | ||
67 | |||
68 | // check for base and bail out if not found. Otherwise create folder. | ||
69 | absPath = resolvePathCase(basePath); | ||
70 | QDir d(absPath); | ||
71 | d.mkpath(lastElement); | ||
72 | absPath = resolvePathCase(fi.absolutePath()); | ||
73 | |||
74 | if(absPath.isEmpty()) { | ||
75 | emit logItem(tr("Error accessing output folder"), LOGERROR); | ||
76 | emit done(true); | ||
77 | return; | ||
78 | } | ||
79 | } | ||
80 | fwfile = absPath + "/" + fi.fileName(); | ||
81 | |||
82 | // place (new) bootloader | ||
83 | m_tempfile.open(); | ||
84 | qDebug() << "renaming" << m_tempfile.fileName() << "->" << fwfile; | ||
85 | m_tempfile.close(); | ||
86 | m_tempfile.rename(fwfile); | ||
87 | |||
88 | emit logItem(tr("Bootloader successful installed"), LOGOK); | ||
89 | logInstall(LogAdd); | ||
90 | |||
91 | emit done(false); | ||
92 | } | ||
93 | |||
94 | |||
95 | bool BootloaderInstallFile::uninstall(void) | ||
96 | { | ||
97 | qDebug() << __func__; | ||
98 | emit logItem(tr("Removing Rockbox bootloader"), LOGINFO); | ||
99 | // check if a .ORIG file is present, and allow moving it back. | ||
100 | QString origbl = resolvePathCase(m_blfile + ".ORIG"); | ||
101 | if(origbl.isEmpty()) { | ||
102 | emit logItem(tr("No original firmware file found."), LOGERROR); | ||
103 | emit done(true); | ||
104 | return false; | ||
105 | } | ||
106 | QString fwfile = resolvePathCase(m_blfile); | ||
107 | if(!QFile::remove(fwfile)) { | ||
108 | emit logItem(tr("Can't remove Rockbox bootloader file."), LOGERROR); | ||
109 | emit done(true); | ||
110 | return false; | ||
111 | } | ||
112 | if(!QFile::rename(origbl, fwfile)) { | ||
113 | emit logItem(tr("Can't restore bootloader file."), LOGERROR); | ||
114 | emit done(true); | ||
115 | return false; | ||
116 | } | ||
117 | emit logItem(tr("Original bootloader restored successfully."), LOGOK); | ||
118 | logInstall(LogRemove); | ||
119 | emit done(false); | ||
120 | |||
121 | return true; | ||
122 | } | ||
123 | |||
124 | |||
125 | //! @brief check if bootloader is installed. | ||
126 | //! @return BootloaderRockbox, BootloaderOther or BootloaderUnknown. | ||
127 | BootloaderInstallBase::BootloaderType BootloaderInstallFile::installed(void) | ||
128 | { | ||
129 | qDebug("%s()", __func__); | ||
130 | if(!resolvePathCase(m_blfile).isEmpty() | ||
131 | && !resolvePathCase(m_blfile + ".ORIG").isEmpty()) | ||
132 | return BootloaderRockbox; | ||
133 | else if(!resolvePathCase(m_blfile).isEmpty()) | ||
134 | return BootloaderOther; | ||
135 | else | ||
136 | return BootloaderUnknown; | ||
137 | } | ||
138 | |||
139 | |||
140 | BootloaderInstallBase::Capabilities BootloaderInstallFile::capabilities(void) | ||
141 | { | ||
142 | qDebug() << __func__; | ||
143 | return Install | IsFile | CanCheckInstalled | Backup; | ||
144 | } | ||
145 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallfile.h b/rbutil/rbutilqt/base/bootloaderinstallfile.h new file mode 100644 index 0000000000..075f047ed2 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallfile.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include "progressloggerinterface.h" | ||
22 | #include "bootloaderinstallbase.h" | ||
23 | |||
24 | //! install a bootloader by putting a single file on the player. | ||
25 | // This installation method is used by Iaudio (firmware is flashed | ||
26 | // automatically) and Gigabeat (Firmware is a file, OF needs to get | ||
27 | // renamed). | ||
28 | class BootloaderInstallFile : public BootloaderInstallBase | ||
29 | { | ||
30 | Q_OBJECT | ||
31 | |||
32 | public: | ||
33 | BootloaderInstallFile(QObject *parent = 0); | ||
34 | bool install(void); | ||
35 | bool uninstall(void); | ||
36 | BootloaderInstallBase::BootloaderType installed(void); | ||
37 | Capabilities capabilities(void); | ||
38 | |||
39 | private slots: | ||
40 | void installStage2(void); | ||
41 | |||
42 | private: | ||
43 | }; | ||
44 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallhex.cpp b/rbutil/rbutilqt/base/bootloaderinstallhex.cpp new file mode 100644 index 0000000000..aa42beb994 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallhex.cpp | |||
@@ -0,0 +1,244 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include "bootloaderinstallbase.h" | ||
22 | #include "bootloaderinstallhex.h" | ||
23 | |||
24 | #include "../../tools/iriver.h" | ||
25 | #include "../../tools/mkboot.h" | ||
26 | |||
27 | struct md5s { | ||
28 | const char* orig; | ||
29 | const char* patched; | ||
30 | }; | ||
31 | |||
32 | struct md5s md5sums[] = { | ||
33 | #include "irivertools/h100sums.h" | ||
34 | { 0, 0 }, | ||
35 | #include "irivertools/h120sums.h" | ||
36 | { 0, 0 }, | ||
37 | #include "irivertools/h300sums.h" | ||
38 | { 0, 0 } | ||
39 | }; | ||
40 | |||
41 | |||
42 | BootloaderInstallHex::BootloaderInstallHex(QObject *parent) | ||
43 | : BootloaderInstallBase(parent) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | |||
48 | bool BootloaderInstallHex::install(void) | ||
49 | { | ||
50 | if(m_hex.isEmpty()) | ||
51 | return false; | ||
52 | m_hashindex = -1; | ||
53 | |||
54 | // md5sum hex file | ||
55 | emit logItem(tr("checking MD5 hash of input file ..."), LOGINFO); | ||
56 | QByteArray filedata; | ||
57 | // read hex file into QByteArray | ||
58 | QFile file(m_hex); | ||
59 | file.open(QIODevice::ReadOnly); | ||
60 | filedata = file.readAll(); | ||
61 | file.close(); | ||
62 | QString hash = QCryptographicHash::hash(filedata, | ||
63 | QCryptographicHash::Md5).toHex(); | ||
64 | qDebug() << "hexfile hash:" << hash; | ||
65 | if(file.error() != QFile::NoError) { | ||
66 | emit logItem(tr("Could not verify original firmware file"), LOGERROR); | ||
67 | emit done(true); | ||
68 | return false; | ||
69 | } | ||
70 | // check hash and figure model from md5sum | ||
71 | int i = sizeof(md5sums) / sizeof(struct md5s); | ||
72 | m_model = 4; | ||
73 | // 3: h300, 2: h120, 1: h100, 0:invalid | ||
74 | while(i--) { | ||
75 | if(md5sums[i].orig == 0) | ||
76 | m_model--; | ||
77 | if(!qstrcmp(md5sums[i].orig, hash.toAscii())) | ||
78 | break; | ||
79 | } | ||
80 | if(i < 0) { | ||
81 | emit logItem(tr("Firmware file not recognized."), LOGERROR); | ||
82 | return false; | ||
83 | } | ||
84 | else { | ||
85 | emit logItem(tr("MD5 hash ok"), LOGOK); | ||
86 | m_hashindex = i; | ||
87 | } | ||
88 | |||
89 | // check model agains download link. | ||
90 | QString match[] = {"", "h100", "h120", "h300"}; | ||
91 | if(!m_blurl.path().contains(match[m_model])) { | ||
92 | emit logItem(tr("Firmware file doesn't match selected player."), | ||
93 | LOGERROR); | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | emit logItem(tr("Descrambling file"), LOGINFO); | ||
98 | m_descrambled.open(); | ||
99 | int result; | ||
100 | result = iriver_decode(m_hex.toAscii().data(), | ||
101 | m_descrambled.fileName().toAscii().data(), FALSE, STRIP_NONE); | ||
102 | qDebug() << "iriver_decode" << result; | ||
103 | |||
104 | if(result < 0) { | ||
105 | emit logItem(tr("Error in descramble: %1").arg(scrambleError(result)), LOGERROR); | ||
106 | return false; | ||
107 | } | ||
108 | |||
109 | // download firmware from server | ||
110 | emit logItem(tr("Downloading bootloader file"), LOGINFO); | ||
111 | connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2())); | ||
112 | |||
113 | downloadBlStart(m_blurl); | ||
114 | return true; | ||
115 | } | ||
116 | |||
117 | |||
118 | void BootloaderInstallHex::installStage2(void) | ||
119 | { | ||
120 | emit logItem(tr("Adding bootloader to firmware file"), LOGINFO); | ||
121 | |||
122 | // local temp file | ||
123 | QTemporaryFile tempbin; | ||
124 | tempbin.open(); | ||
125 | QString tempbinName = tempbin.fileName(); | ||
126 | tempbin.close(); | ||
127 | // get temporary files filenames -- external tools need this. | ||
128 | m_descrambled.open(); | ||
129 | QString descrambledName = m_descrambled.fileName(); | ||
130 | m_descrambled.close(); | ||
131 | m_tempfile.open(); | ||
132 | QString tempfileName = m_tempfile.fileName(); | ||
133 | m_tempfile.close(); | ||
134 | |||
135 | int origin = 0; | ||
136 | switch(m_model) { | ||
137 | case 3: | ||
138 | origin = 0x3f0000; | ||
139 | break; | ||
140 | case 2: | ||
141 | case 1: | ||
142 | origin = 0x1f0000; | ||
143 | break; | ||
144 | default: | ||
145 | origin = 0; | ||
146 | break; | ||
147 | } | ||
148 | |||
149 | // iriver decode already done in stage 1 | ||
150 | int result; | ||
151 | if((result = mkboot(descrambledName.toLocal8Bit().constData(), | ||
152 | tempfileName.toLocal8Bit().constData(), | ||
153 | tempbinName.toLocal8Bit().constData(), origin)) < 0) | ||
154 | { | ||
155 | QString error; | ||
156 | switch(result) { | ||
157 | case -1: error = tr("could not open input file"); break; | ||
158 | case -2: error = tr("reading header failed"); break; | ||
159 | case -3: error = tr("reading firmware failed"); break; | ||
160 | case -4: error = tr("can't open bootloader file"); break; | ||
161 | case -5: error = tr("reading bootloader file failed"); break; | ||
162 | case -6: error = tr("can't open output file"); break; | ||
163 | case -7: error = tr("writing output file failed"); break; | ||
164 | } | ||
165 | emit logItem(tr("Error in patching: %1").arg(error), LOGERROR); | ||
166 | |||
167 | emit done(true); | ||
168 | return; | ||
169 | } | ||
170 | QTemporaryFile targethex; | ||
171 | targethex.open(); | ||
172 | QString targethexName = targethex.fileName(); | ||
173 | if((result = iriver_encode(tempbinName.toLocal8Bit().constData(), | ||
174 | targethexName.toLocal8Bit().constData(), FALSE)) < 0) | ||
175 | { | ||
176 | emit logItem(tr("Error in scramble: %1").arg(scrambleError(result)), LOGERROR); | ||
177 | targethex.close(); | ||
178 | |||
179 | emit done(true); | ||
180 | return; | ||
181 | } | ||
182 | |||
183 | // finally check the md5sum of the created file | ||
184 | QByteArray filedata; | ||
185 | filedata = targethex.readAll(); | ||
186 | targethex.close(); | ||
187 | QString hash = QCryptographicHash::hash(filedata, | ||
188 | QCryptographicHash::Md5).toHex(); | ||
189 | qDebug() << "created hexfile hash:" << hash; | ||
190 | |||
191 | emit logItem(tr("Checking modified firmware file"), LOGINFO); | ||
192 | if(hash != QString(md5sums[m_hashindex].patched)) { | ||
193 | emit logItem(tr("Error: modified file checksum wrong"), LOGERROR); | ||
194 | targethex.remove(); | ||
195 | emit done(true); | ||
196 | return; | ||
197 | } | ||
198 | // finally copy file to player | ||
199 | targethex.copy(m_blfile); | ||
200 | |||
201 | emit logItem(tr("Success: modified firmware file created"), LOGINFO); | ||
202 | logInstall(LogAdd); | ||
203 | emit done(false); | ||
204 | |||
205 | return; | ||
206 | } | ||
207 | |||
208 | |||
209 | bool BootloaderInstallHex::uninstall(void) | ||
210 | { | ||
211 | emit logItem("Uninstallation not possible, only installation info removed", LOGINFO); | ||
212 | logInstall(LogRemove); | ||
213 | return false; | ||
214 | } | ||
215 | |||
216 | |||
217 | BootloaderInstallBase::BootloaderType BootloaderInstallHex::installed(void) | ||
218 | { | ||
219 | return BootloaderUnknown; | ||
220 | } | ||
221 | |||
222 | |||
223 | BootloaderInstallBase::Capabilities BootloaderInstallHex::capabilities(void) | ||
224 | { | ||
225 | return (Install | NeedsFlashing); | ||
226 | } | ||
227 | |||
228 | QString BootloaderInstallHex::scrambleError(int err) | ||
229 | { | ||
230 | QString error; | ||
231 | switch(err) { | ||
232 | case -1: error = tr("Can't open input file"); break; | ||
233 | case -2: error = tr("Can't open output file"); break; | ||
234 | case -3: error = tr("invalid file: header length wrong"); break; | ||
235 | case -4: error = tr("invalid file: unrecognized header"); break; | ||
236 | case -5: error = tr("invalid file: \"length\" field wrong"); break; | ||
237 | case -6: error = tr("invalid file: \"length2\" field wrong"); break; | ||
238 | case -7: error = tr("invalid file: internal checksum error"); break; | ||
239 | case -8: error = tr("invalid file: \"length3\" field wrong"); break; | ||
240 | default: error = tr("unknown"); break; | ||
241 | } | ||
242 | return error; | ||
243 | } | ||
244 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallhex.h b/rbutil/rbutilqt/base/bootloaderinstallhex.h new file mode 100644 index 0000000000..04b657a193 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallhex.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef BOOTLOADERINSTALLHEX_H | ||
21 | #define BOOTLOADERINSTALLHEX_H | ||
22 | |||
23 | #include <QtCore> | ||
24 | #include "bootloaderinstallbase.h" | ||
25 | |||
26 | |||
27 | // bootloader installation derivate based on fwpatcher | ||
28 | // This will patch a given hex file using (de)scramble / mkboot | ||
29 | // and put it on the player. | ||
30 | class BootloaderInstallHex : public BootloaderInstallBase | ||
31 | { | ||
32 | Q_OBJECT | ||
33 | |||
34 | public: | ||
35 | BootloaderInstallHex(QObject *parent = 0); | ||
36 | bool install(void); | ||
37 | bool uninstall(void); | ||
38 | BootloaderInstallBase::BootloaderType installed(void); | ||
39 | Capabilities capabilities(void); | ||
40 | |||
41 | void setHexfile(QString h) | ||
42 | { m_hex = h; } | ||
43 | |||
44 | private: | ||
45 | QString m_hex; | ||
46 | int m_hashindex; | ||
47 | int m_model; | ||
48 | QTemporaryFile m_descrambled; | ||
49 | QString scrambleError(int); | ||
50 | |||
51 | private slots: | ||
52 | void installStage2(void); | ||
53 | }; | ||
54 | |||
55 | |||
56 | #endif | ||
57 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp new file mode 100644 index 0000000000..e47c96b239 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp | |||
@@ -0,0 +1,235 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include "bootloaderinstallbase.h" | ||
22 | #include "bootloaderinstallipod.h" | ||
23 | |||
24 | #include "../ipodpatcher/ipodpatcher.h" | ||
25 | |||
26 | |||
27 | BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) | ||
28 | : BootloaderInstallBase(parent) | ||
29 | { | ||
30 | (void)parent; | ||
31 | // initialize sector buffer. ipod_sectorbuf is defined in ipodpatcher. | ||
32 | ipod_sectorbuf = NULL; | ||
33 | ipod_alloc_buffer(&ipod_sectorbuf, BUFFER_SIZE); | ||
34 | } | ||
35 | |||
36 | |||
37 | BootloaderInstallIpod::~BootloaderInstallIpod() | ||
38 | { | ||
39 | free(ipod_sectorbuf); | ||
40 | } | ||
41 | |||
42 | |||
43 | bool BootloaderInstallIpod::install(void) | ||
44 | { | ||
45 | if(ipod_sectorbuf == NULL) { | ||
46 | emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR); | ||
47 | emit done(true); | ||
48 | return false; | ||
49 | } | ||
50 | |||
51 | struct ipod_t ipod; | ||
52 | |||
53 | int n = ipod_scan(&ipod); | ||
54 | if(n == -1) { | ||
55 | emit logItem(tr("No Ipod detected\n" | ||
56 | "Permission for disc access denied!"), | ||
57 | LOGERROR); | ||
58 | emit done(true); | ||
59 | return false; | ||
60 | } | ||
61 | if(n == 0) { | ||
62 | emit logItem(tr("No Ipod detected!"), LOGERROR); | ||
63 | emit done(true); | ||
64 | return false; | ||
65 | } | ||
66 | |||
67 | if(ipod.macpod) { | ||
68 | emit logItem(tr("Warning: This is a MacPod, Rockbox only runs on WinPods.\n" | ||
69 | "See http://www.rockbox.org/wiki/IpodConversionToFAT32"), LOGERROR); | ||
70 | emit done(true); | ||
71 | return false; | ||
72 | } | ||
73 | emit logItem(tr("Downloading bootloader file"), LOGINFO); | ||
74 | |||
75 | downloadBlStart(m_blurl); | ||
76 | connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2())); | ||
77 | return true; | ||
78 | } | ||
79 | |||
80 | |||
81 | void BootloaderInstallIpod::installStage2(void) | ||
82 | { | ||
83 | struct ipod_t ipod; | ||
84 | |||
85 | if(!ipodInitialize(&ipod)) { | ||
86 | emit done(true); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | read_directory(&ipod); | ||
91 | |||
92 | if(ipod.nimages <= 0) { | ||
93 | emit logItem(tr("Failed to read firmware directory"), LOGERROR); | ||
94 | emit done(true); | ||
95 | return; | ||
96 | } | ||
97 | if(getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0) { | ||
98 | emit logItem(tr("Unknown version number in firmware (%1)").arg( | ||
99 | ipod.ipod_directory[0].vers), LOGERROR); | ||
100 | emit done(true); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | if(ipod.macpod) { | ||
105 | emit logItem(tr("Warning: This is a MacPod. Rockbox only runs on WinPods.\n" | ||
106 | "See http://www.rockbox.org/wiki/IpodConversionToFAT32"), LOGERROR); | ||
107 | emit done(true); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | if(ipod_reopen_rw(&ipod) < 0) { | ||
112 | emit logItem(tr("Could not open Ipod in R/W mode"), LOGERROR); | ||
113 | emit done(true); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | m_tempfile.open(); | ||
118 | QString blfile = m_tempfile.fileName(); | ||
119 | m_tempfile.close(); | ||
120 | if(add_bootloader(&ipod, blfile.toLatin1().data(), FILETYPE_DOT_IPOD) == 0) { | ||
121 | emit logItem(tr("Successfull added bootloader"), LOGOK); | ||
122 | logInstall(LogAdd); | ||
123 | emit done(false); | ||
124 | ipod_close(&ipod); | ||
125 | return; | ||
126 | } | ||
127 | else { | ||
128 | emit logItem(tr("Failed to add bootloader"), LOGERROR); | ||
129 | ipod_close(&ipod); | ||
130 | emit done(true); | ||
131 | return; | ||
132 | } | ||
133 | qDebug() << "version installed:" << m_blversion.toString(Qt::ISODate); | ||
134 | } | ||
135 | |||
136 | |||
137 | bool BootloaderInstallIpod::uninstall(void) | ||
138 | { | ||
139 | struct ipod_t ipod; | ||
140 | |||
141 | if(!ipodInitialize(&ipod)) { | ||
142 | emit done(true); | ||
143 | return false; | ||
144 | } | ||
145 | |||
146 | read_directory(&ipod); | ||
147 | |||
148 | if (ipod.nimages <= 0) { | ||
149 | emit logItem(tr("Failed to read firmware directory"),LOGERROR); | ||
150 | emit done(true); | ||
151 | return false; | ||
152 | } | ||
153 | if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0) { | ||
154 | emit logItem(tr("Unknown version number in firmware (%1)").arg( | ||
155 | ipod.ipod_directory[0].vers), LOGERROR); | ||
156 | emit done(true); | ||
157 | return false; | ||
158 | } | ||
159 | |||
160 | if (ipod_reopen_rw(&ipod) < 0) { | ||
161 | emit logItem(tr("Could not open Ipod in RW mode"), LOGERROR); | ||
162 | emit done(true); | ||
163 | return false; | ||
164 | } | ||
165 | |||
166 | if (ipod.ipod_directory[0].entryOffset == 0) { | ||
167 | emit logItem(tr("No bootloader detected."), LOGERROR); | ||
168 | emit done(true); | ||
169 | return false; | ||
170 | } | ||
171 | |||
172 | if (delete_bootloader(&ipod)==0) { | ||
173 | emit logItem(tr("Successfully removed Bootloader"), LOGOK); | ||
174 | logInstall(LogRemove); | ||
175 | emit done(false); | ||
176 | ipod_close(&ipod); | ||
177 | return true; | ||
178 | } | ||
179 | else { | ||
180 | emit logItem(tr("Removing the bootloader failed."), LOGERROR); | ||
181 | emit done(true); | ||
182 | ipod_close(&ipod); | ||
183 | return false; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | |||
188 | BootloaderInstallBase::BootloaderType BootloaderInstallIpod::installed(void) | ||
189 | { | ||
190 | struct ipod_t ipod; | ||
191 | BootloaderInstallBase::BootloaderType result = BootloaderRockbox; | ||
192 | |||
193 | if(!ipodInitialize(&ipod)) { | ||
194 | qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown"; | ||
195 | result = BootloaderUnknown; | ||
196 | } | ||
197 | |||
198 | if (ipod.ipod_directory[0].entryOffset == 0) { | ||
199 | qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther"; | ||
200 | result = BootloaderOther; | ||
201 | } | ||
202 | qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox"; | ||
203 | ipod_close(&ipod); | ||
204 | |||
205 | return result; | ||
206 | } | ||
207 | |||
208 | |||
209 | BootloaderInstallBase::Capabilities BootloaderInstallIpod::capabilities(void) | ||
210 | { | ||
211 | return (Install | Uninstall | IsRaw); | ||
212 | } | ||
213 | |||
214 | |||
215 | bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod) | ||
216 | { | ||
217 | ipod_scan(ipod); | ||
218 | if(ipod_open(ipod, 0) < 0) { | ||
219 | emit logItem(tr("Could not open Ipod"), LOGERROR); | ||
220 | return false; | ||
221 | } | ||
222 | |||
223 | if(read_partinfo(ipod, 0) < 0) { | ||
224 | emit logItem(tr("Could not read partition table"), LOGERROR); | ||
225 | return false; | ||
226 | } | ||
227 | |||
228 | if(ipod->pinfo[0].start == 0) { | ||
229 | emit logItem(tr("No firmware partition on disk"), LOGERROR); | ||
230 | |||
231 | return false; | ||
232 | } | ||
233 | return true; | ||
234 | } | ||
235 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallipod.h b/rbutil/rbutilqt/base/bootloaderinstallipod.h new file mode 100644 index 0000000000..5867b754f1 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallipod.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef BOOTLOADERINSTALLIPOD_H | ||
21 | #define BOOTLOADERINSTALLIPOD_H | ||
22 | |||
23 | #include <QtCore> | ||
24 | #include "bootloaderinstallbase.h" | ||
25 | #include "../ipodpatcher/ipodpatcher.h" | ||
26 | |||
27 | // installer class derivate for Ipod installation | ||
28 | // based on ipodpatcher. | ||
29 | class BootloaderInstallIpod : public BootloaderInstallBase | ||
30 | { | ||
31 | Q_OBJECT | ||
32 | |||
33 | public: | ||
34 | BootloaderInstallIpod(QObject *parent = 0); | ||
35 | ~BootloaderInstallIpod(); | ||
36 | bool install(void); | ||
37 | bool uninstall(void); | ||
38 | BootloaderInstallBase::BootloaderType installed(void); | ||
39 | Capabilities capabilities(void); | ||
40 | |||
41 | private slots: | ||
42 | void installStage2(void); | ||
43 | |||
44 | private: | ||
45 | bool ipodInitialize(struct ipod_t *); | ||
46 | }; | ||
47 | |||
48 | |||
49 | #endif | ||
50 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallmi4.cpp b/rbutil/rbutilqt/base/bootloaderinstallmi4.cpp new file mode 100644 index 0000000000..fa0ebb2f02 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallmi4.cpp | |||
@@ -0,0 +1,140 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include <QtDebug> | ||
22 | #include <QtDebug> | ||
23 | #include "bootloaderinstallmi4.h" | ||
24 | #include "utils.h" | ||
25 | |||
26 | BootloaderInstallMi4::BootloaderInstallMi4(QObject *parent) | ||
27 | : BootloaderInstallBase(parent) | ||
28 | { | ||
29 | } | ||
30 | |||
31 | |||
32 | bool BootloaderInstallMi4::install(void) | ||
33 | { | ||
34 | emit logItem(tr("Downloading bootloader"), LOGINFO); | ||
35 | qDebug() << __func__; | ||
36 | downloadBlStart(m_blurl); | ||
37 | connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2())); | ||
38 | return true; | ||
39 | } | ||
40 | |||
41 | void BootloaderInstallMi4::installStage2(void) | ||
42 | { | ||
43 | emit logItem(tr("Installing Rockbox bootloader"), LOGINFO); | ||
44 | |||
45 | // move old bootloader out of the way | ||
46 | QString fwfile(resolvePathCase(m_blfile)); | ||
47 | QFile oldbl(fwfile); | ||
48 | QString moved = QFileInfo(resolvePathCase(m_blfile)).absolutePath() | ||
49 | + "/OF.mi4"; | ||
50 | qDebug() << "renaming" << fwfile << "->" << moved; | ||
51 | oldbl.rename(moved); | ||
52 | |||
53 | // place new bootloader | ||
54 | m_tempfile.open(); | ||
55 | qDebug() << "renaming" << m_tempfile.fileName() << "->" << fwfile; | ||
56 | m_tempfile.close(); | ||
57 | m_tempfile.rename(fwfile); | ||
58 | |||
59 | emit logItem(tr("Bootloader successful installed"), LOGOK); | ||
60 | logInstall(LogAdd); | ||
61 | |||
62 | emit done(true); | ||
63 | } | ||
64 | |||
65 | |||
66 | bool BootloaderInstallMi4::uninstall(void) | ||
67 | { | ||
68 | qDebug() << __func__; | ||
69 | |||
70 | // check if it's actually a Rockbox bootloader | ||
71 | emit logItem(tr("Checking for Rockbox bootloader"), LOGINFO); | ||
72 | if(installed() != BootloaderRockbox) { | ||
73 | emit logItem(tr("No Rockbox bootloader found"), LOGERROR); | ||
74 | return false; | ||
75 | } | ||
76 | |||
77 | // check if OF file present | ||
78 | emit logItem(tr("Checking for original firmware file"), LOGINFO); | ||
79 | QString original = QFileInfo(resolvePathCase(m_blfile)).absolutePath() | ||
80 | + "/OF.mi4"; | ||
81 | |||
82 | if(resolvePathCase(original).isEmpty()) { | ||
83 | emit logItem(tr("Error finding original firmware file"), LOGERROR); | ||
84 | return false; | ||
85 | } | ||
86 | |||
87 | // finally remove RB bootloader | ||
88 | QString resolved = resolvePathCase(m_blfile); | ||
89 | QFile blfile(resolved); | ||
90 | blfile.remove(); | ||
91 | |||
92 | QFile oldbl(resolvePathCase(original)); | ||
93 | oldbl.rename(m_blfile); | ||
94 | emit logItem(tr("Rockbox bootloader successful removed"), LOGINFO); | ||
95 | logInstall(LogRemove); | ||
96 | emit done(false); | ||
97 | |||
98 | return true; | ||
99 | } | ||
100 | |||
101 | |||
102 | //! check if a bootloader is installed and return its state. | ||
103 | BootloaderInstallBase::BootloaderType BootloaderInstallMi4::installed(void) | ||
104 | { | ||
105 | // for MI4 files we can check if we actually have a RB bootloader | ||
106 | // installed. | ||
107 | // RB bootloader has "RBBL" at 0x1f8 in the mi4 file. | ||
108 | |||
109 | // make sure to resolve case to prevent case issues | ||
110 | QString resolved; | ||
111 | resolved = resolvePathCase(m_blfile); | ||
112 | if(resolved.isEmpty()) { | ||
113 | qDebug("%s: BootloaderNone", __func__); | ||
114 | return BootloaderNone; | ||
115 | } | ||
116 | |||
117 | QFile f(resolved); | ||
118 | f.open(QIODevice::ReadOnly); | ||
119 | f.seek(0x1f8); | ||
120 | char magic[4]; | ||
121 | f.read(magic, 4); | ||
122 | f.close(); | ||
123 | |||
124 | if(!memcmp(magic, "RBBL", 4)) { | ||
125 | qDebug("%s: BootloaderRockbox", __func__); | ||
126 | return BootloaderRockbox; | ||
127 | } | ||
128 | else { | ||
129 | qDebug("%s: BootloaderOther", __func__); | ||
130 | return BootloaderOther; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | |||
135 | BootloaderInstallBase::Capabilities BootloaderInstallMi4::capabilities(void) | ||
136 | { | ||
137 | qDebug() << __func__; | ||
138 | return Install | Uninstall | Backup | IsFile | CanCheckInstalled | CanCheckVersion; | ||
139 | } | ||
140 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallmi4.h b/rbutil/rbutilqt/base/bootloaderinstallmi4.h new file mode 100644 index 0000000000..c746b0c87f --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallmi4.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include "progressloggerinterface.h" | ||
22 | #include "bootloaderinstallbase.h" | ||
23 | |||
24 | |||
25 | // mi4 bootloader file based installation. | ||
26 | // Puts the bootloader file to the correct location and | ||
27 | // renames the OF to OF.mi4. | ||
28 | class BootloaderInstallMi4 : public BootloaderInstallBase | ||
29 | { | ||
30 | Q_OBJECT | ||
31 | |||
32 | public: | ||
33 | BootloaderInstallMi4(QObject *parent = 0); | ||
34 | bool install(void); | ||
35 | bool uninstall(void); | ||
36 | BootloaderInstallBase::BootloaderType installed(void); | ||
37 | Capabilities capabilities(void); | ||
38 | |||
39 | private slots: | ||
40 | void installStage2(void); | ||
41 | |||
42 | private: | ||
43 | }; | ||
44 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp new file mode 100644 index 0000000000..9294cdd497 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp | |||
@@ -0,0 +1,244 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include "bootloaderinstallbase.h" | ||
22 | #include "bootloaderinstallsansa.h" | ||
23 | |||
24 | #include "../sansapatcher/sansapatcher.h" | ||
25 | |||
26 | BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) | ||
27 | : BootloaderInstallBase(parent) | ||
28 | { | ||
29 | (void)parent; | ||
30 | // initialize sector buffer. sansa_sectorbuf is instantiated by | ||
31 | // sansapatcher. | ||
32 | sansa_sectorbuf = NULL; | ||
33 | sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE); | ||
34 | } | ||
35 | |||
36 | |||
37 | BootloaderInstallSansa::~BootloaderInstallSansa() | ||
38 | { | ||
39 | free(sansa_sectorbuf); | ||
40 | } | ||
41 | |||
42 | |||
43 | /** Start bootloader installation. | ||
44 | */ | ||
45 | bool BootloaderInstallSansa::install(void) | ||
46 | { | ||
47 | if(sansa_sectorbuf == NULL) { | ||
48 | emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR); | ||
49 | return false; | ||
50 | emit done(true); | ||
51 | } | ||
52 | |||
53 | emit logItem(tr("Searching for Sansa"), LOGINFO); | ||
54 | |||
55 | struct sansa_t sansa; | ||
56 | |||
57 | int n = sansa_scan(&sansa); | ||
58 | if(n == -1) { | ||
59 | emit logItem(tr("Permission for disc access denied!\n" | ||
60 | "This is required to install the bootloader"), | ||
61 | LOGERROR); | ||
62 | emit done(true); | ||
63 | return false; | ||
64 | } | ||
65 | if(n == 0) { | ||
66 | emit logItem(tr("No Sansa detected!"), LOGERROR); | ||
67 | emit done(true); | ||
68 | return false; | ||
69 | } | ||
70 | emit logItem(tr("Downloading bootloader file"), LOGINFO); | ||
71 | |||
72 | downloadBlStart(m_blurl); | ||
73 | connect(this, SIGNAL(downloadDone()), this, SLOT(installStage2())); | ||
74 | return true; | ||
75 | } | ||
76 | |||
77 | |||
78 | /** Finish bootloader installation. | ||
79 | */ | ||
80 | void BootloaderInstallSansa::installStage2(void) | ||
81 | { | ||
82 | struct sansa_t sansa; | ||
83 | sansa_scan(&sansa); | ||
84 | |||
85 | if(sansa_open(&sansa, 0) < 0) { | ||
86 | emit logItem(tr("could not open Sansa"), LOGERROR); | ||
87 | emit done(true); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | if(sansa_read_partinfo(&sansa, 0) < 0) | ||
92 | { | ||
93 | emit logItem(tr("could not read partitiontable"), LOGERROR); | ||
94 | emit done(true); | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | int i = is_sansa(&sansa); | ||
99 | if(i < 0) { | ||
100 | |||
101 | emit logItem(tr("Disk is not a Sansa (Error: %1), aborting.").arg(i), LOGERROR); | ||
102 | emit done(true); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | if(sansa.hasoldbootloader) { | ||
107 | emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n" | ||
108 | "You must reinstall the original Sansa firmware before running\n" | ||
109 | "sansapatcher for the first time.\n" | ||
110 | "See http://www.rockbox.org/wiki/SansaE200Install\n"), | ||
111 | LOGERROR); | ||
112 | emit done(true); | ||
113 | return; | ||
114 | } | ||
115 | |||
116 | if(sansa_reopen_rw(&sansa) < 0) { | ||
117 | emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR); | ||
118 | emit done(true); | ||
119 | return; | ||
120 | } | ||
121 | |||
122 | m_tempfile.open(); | ||
123 | QString blfile = m_tempfile.fileName(); | ||
124 | m_tempfile.close(); | ||
125 | if(sansa_add_bootloader(&sansa, blfile.toLatin1().data(), | ||
126 | FILETYPE_MI4) == 0) { | ||
127 | emit logItem(tr("Successfully installed bootloader"), LOGOK); | ||
128 | logInstall(LogAdd); | ||
129 | emit done(false); | ||
130 | sansa_close(&sansa); | ||
131 | return; | ||
132 | } | ||
133 | else { | ||
134 | emit logItem(tr("Failed to install bootloader"), LOGERROR); | ||
135 | sansa_close(&sansa); | ||
136 | emit done(true); | ||
137 | return; | ||
138 | } | ||
139 | |||
140 | } | ||
141 | |||
142 | |||
143 | /** Uninstall the bootloader. | ||
144 | */ | ||
145 | bool BootloaderInstallSansa::uninstall(void) | ||
146 | { | ||
147 | struct sansa_t sansa; | ||
148 | |||
149 | if(sansa_scan(&sansa) != 1) { | ||
150 | emit logItem(tr("Can't find Sansa"), LOGERROR); | ||
151 | emit done(true); | ||
152 | return false; | ||
153 | } | ||
154 | |||
155 | if (sansa_open(&sansa, 0) < 0) { | ||
156 | emit logItem(tr("Could not open Sansa"), LOGERROR); | ||
157 | emit done(true); | ||
158 | return false; | ||
159 | } | ||
160 | |||
161 | if (sansa_read_partinfo(&sansa,0) < 0) { | ||
162 | emit logItem(tr("Could not read partition table"), LOGERROR); | ||
163 | emit done(true); | ||
164 | return false; | ||
165 | } | ||
166 | |||
167 | int i = is_sansa(&sansa); | ||
168 | if(i < 0) { | ||
169 | emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR); | ||
170 | emit done(true); | ||
171 | return false; | ||
172 | } | ||
173 | |||
174 | if (sansa.hasoldbootloader) { | ||
175 | emit logItem(tr("OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n" | ||
176 | "You must reinstall the original Sansa firmware before running\n" | ||
177 | "sansapatcher for the first time.\n" | ||
178 | "See http://www.rockbox.org/wiki/SansaE200Install\n"), | ||
179 | LOGERROR); | ||
180 | emit done(true); | ||
181 | return false; | ||
182 | } | ||
183 | |||
184 | if (sansa_reopen_rw(&sansa) < 0) { | ||
185 | emit logItem(tr("Could not open Sansa in R/W mode"), LOGERROR); | ||
186 | emit done(true); | ||
187 | return false; | ||
188 | } | ||
189 | |||
190 | if (sansa_delete_bootloader(&sansa)==0) { | ||
191 | emit logItem(tr("Successfully removed bootloader"), LOGOK); | ||
192 | logInstall(LogRemove); | ||
193 | emit done(false); | ||
194 | sansa_close(&sansa); | ||
195 | return true; | ||
196 | } | ||
197 | else { | ||
198 | emit logItem(tr("Removing bootloader failed."),LOGERROR); | ||
199 | emit done(true); | ||
200 | sansa_close(&sansa); | ||
201 | return false; | ||
202 | } | ||
203 | |||
204 | return false; | ||
205 | } | ||
206 | |||
207 | |||
208 | /** Check if bootloader is already installed | ||
209 | */ | ||
210 | BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void) | ||
211 | { | ||
212 | struct sansa_t sansa; | ||
213 | int num; | ||
214 | |||
215 | if(sansa_scan(&sansa) != 1) { | ||
216 | return BootloaderUnknown; | ||
217 | } | ||
218 | if (sansa_open(&sansa, 0) < 0) { | ||
219 | return BootloaderUnknown; | ||
220 | } | ||
221 | if (sansa_read_partinfo(&sansa,0) < 0) { | ||
222 | return BootloaderUnknown; | ||
223 | } | ||
224 | if(is_sansa(&sansa) < 0) { | ||
225 | return BootloaderUnknown; | ||
226 | } | ||
227 | if((num = sansa_list_images(&sansa)) == 2) { | ||
228 | return BootloaderRockbox; | ||
229 | } | ||
230 | else if(num == 1) { | ||
231 | return BootloaderOther; | ||
232 | } | ||
233 | return BootloaderUnknown; | ||
234 | |||
235 | } | ||
236 | |||
237 | |||
238 | /** Get capabilities of subclass installer. | ||
239 | */ | ||
240 | BootloaderInstallBase::Capabilities BootloaderInstallSansa::capabilities(void) | ||
241 | { | ||
242 | return (Install | Uninstall | IsRaw | CanCheckInstalled); | ||
243 | } | ||
244 | |||
diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.h b/rbutil/rbutilqt/base/bootloaderinstallsansa.h new file mode 100644 index 0000000000..a3911057a0 --- /dev/null +++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #ifndef BOOTLOADERINSTALLSANSA_H | ||
21 | #define BOOTLOADERINSTALLSANSA_H | ||
22 | |||
23 | #include <QtCore> | ||
24 | #include "bootloaderinstallbase.h" | ||
25 | |||
26 | |||
27 | // bootloader installation class for devices handled by sansapatcher. | ||
28 | class BootloaderInstallSansa : public BootloaderInstallBase | ||
29 | { | ||
30 | Q_OBJECT | ||
31 | |||
32 | public: | ||
33 | BootloaderInstallSansa(QObject *parent = 0); | ||
34 | ~BootloaderInstallSansa(); | ||
35 | bool install(void); | ||
36 | bool uninstall(void); | ||
37 | BootloaderInstallBase::BootloaderType installed(void); | ||
38 | Capabilities capabilities(void); | ||
39 | |||
40 | private: | ||
41 | |||
42 | private slots: | ||
43 | void installStage2(void); | ||
44 | }; | ||
45 | |||
46 | |||
47 | #endif | ||
48 | |||
diff --git a/rbutil/rbutilqt/base/httpget.cpp b/rbutil/rbutilqt/base/httpget.cpp new file mode 100644 index 0000000000..129545d158 --- /dev/null +++ b/rbutil/rbutilqt/base/httpget.cpp | |||
@@ -0,0 +1,413 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <QtCore> | ||
21 | #include <QtNetwork> | ||
22 | #include <QtDebug> | ||
23 | |||
24 | #include "httpget.h" | ||
25 | |||
26 | QDir HttpGet::m_globalCache; //< global cach path value for new objects | ||
27 | QUrl HttpGet::m_globalProxy; //< global proxy value for new objects | ||
28 | bool HttpGet::m_globalDumbCache = false; //< globally set cache "dumb" mode | ||
29 | QString HttpGet::m_globalUserAgent; //< globally set user agent for requests | ||
30 | |||
31 | HttpGet::HttpGet(QObject *parent) | ||
32 | : QObject(parent) | ||
33 | { | ||
34 | outputToBuffer = true; | ||
35 | m_cached = false; | ||
36 | m_dumbCache = m_globalDumbCache; | ||
37 | getRequest = -1; | ||
38 | headRequest = -1; | ||
39 | // if a request is cancelled before a reponse is available return some | ||
40 | // hint about this in the http response instead of nonsense. | ||
41 | m_response = -1; | ||
42 | |||
43 | // default to global proxy / cache if not empty. | ||
44 | // proxy is automatically enabled, disable it by setting an empty proxy | ||
45 | // cache is enabled to be in line, can get disabled with setCache(bool) | ||
46 | if(!m_globalProxy.isEmpty()) | ||
47 | setProxy(m_globalProxy); | ||
48 | m_usecache = false; | ||
49 | m_cachedir = m_globalCache; | ||
50 | |||
51 | m_serverTimestamp = QDateTime(); | ||
52 | |||
53 | connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool))); | ||
54 | connect(&http, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(dataReadProgress(int, int))); | ||
55 | connect(&http, SIGNAL(requestFinished(int, bool)), this, SLOT(httpFinished(int, bool))); | ||
56 | connect(&http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), this, SLOT(httpResponseHeader(const QHttpResponseHeader&))); | ||
57 | connect(&http, SIGNAL(stateChanged(int)), this, SLOT(httpState(int))); | ||
58 | connect(&http, SIGNAL(requestStarted(int)), this, SLOT(httpStarted(int))); | ||
59 | |||
60 | connect(&http, SIGNAL(readyRead(const QHttpResponseHeader&)), this, SLOT(httpResponseHeader(const QHttpResponseHeader&))); | ||
61 | |||
62 | } | ||
63 | |||
64 | |||
65 | //! @brief set cache path | ||
66 | // @param d new directory to use as cache path | ||
67 | void HttpGet::setCache(QDir d) | ||
68 | { | ||
69 | m_cachedir = d; | ||
70 | bool result; | ||
71 | result = initializeCache(d); | ||
72 | qDebug() << "[HTTP]"<< __func__ << "(QDir)" << d.absolutePath() << result; | ||
73 | m_usecache = result; | ||
74 | } | ||
75 | |||
76 | |||
77 | /** @brief enable / disable cache useage | ||
78 | * @param c set cache usage | ||
79 | */ | ||
80 | void HttpGet::setCache(bool c) | ||
81 | { | ||
82 | qDebug() << "[HTTP]" << __func__ << "(bool) =" << c; | ||
83 | m_usecache = c; | ||
84 | // make sure cache is initialized | ||
85 | if(c) | ||
86 | m_usecache = initializeCache(m_cachedir); | ||
87 | } | ||
88 | |||
89 | |||
90 | bool HttpGet::initializeCache(const QDir& d) | ||
91 | { | ||
92 | bool result; | ||
93 | QString p = d.absolutePath() + "/rbutil-cache"; | ||
94 | if(QFileInfo(d.absolutePath()).isDir()) | ||
95 | { | ||
96 | if(!QFileInfo(p).isDir()) | ||
97 | result = d.mkdir("rbutil-cache"); | ||
98 | else | ||
99 | result = true; | ||
100 | } | ||
101 | else | ||
102 | result = false; | ||
103 | |||
104 | return result; | ||
105 | |||
106 | } | ||
107 | |||
108 | |||
109 | /** @brief read all downloaded data into a buffer | ||
110 | * @return data | ||
111 | */ | ||
112 | QByteArray HttpGet::readAll() | ||
113 | { | ||
114 | return dataBuffer; | ||
115 | } | ||
116 | |||
117 | |||
118 | /** @brief get http error | ||
119 | * @return http error | ||
120 | */ | ||
121 | QHttp::Error HttpGet::error() | ||
122 | { | ||
123 | return http.error(); | ||
124 | } | ||
125 | |||
126 | |||
127 | void HttpGet::setProxy(const QUrl &proxy) | ||
128 | { | ||
129 | qDebug() << "[HTTP]" << __func__ << "(QUrl)" << proxy.toString(); | ||
130 | m_proxy = proxy; | ||
131 | http.setProxy(m_proxy.host(), m_proxy.port(), m_proxy.userName(), m_proxy.password()); | ||
132 | } | ||
133 | |||
134 | |||
135 | void HttpGet::setProxy(bool enable) | ||
136 | { | ||
137 | qDebug() << "[HTTP]" << __func__ << "(bool)" << enable; | ||
138 | if(enable) | ||
139 | http.setProxy(m_proxy.host(), m_proxy.port(), m_proxy.userName(), m_proxy.password()); | ||
140 | else | ||
141 | http.setProxy("", 0); | ||
142 | } | ||
143 | |||
144 | |||
145 | void HttpGet::setFile(QFile *file) | ||
146 | { | ||
147 | outputFile = file; | ||
148 | outputToBuffer = false; | ||
149 | qDebug() << "[HTTP]" << __func__ << "(QFile*)" << outputFile->fileName(); | ||
150 | } | ||
151 | |||
152 | |||
153 | void HttpGet::abort() | ||
154 | { | ||
155 | http.abort(); | ||
156 | if(!outputToBuffer) | ||
157 | outputFile->close(); | ||
158 | } | ||
159 | |||
160 | |||
161 | bool HttpGet::getFile(const QUrl &url) | ||
162 | { | ||
163 | if (!url.isValid()) { | ||
164 | qDebug() << "[HTTP] Error: Invalid URL" << endl; | ||
165 | return false; | ||
166 | } | ||
167 | |||
168 | if (url.scheme() != "http") { | ||
169 | qDebug() << "[HTTP] Error: URL must start with 'http:'" << endl; | ||
170 | return false; | ||
171 | } | ||
172 | |||
173 | if (url.path().isEmpty()) { | ||
174 | qDebug() << "[HTTP] Error: URL has no path" << endl; | ||
175 | return false; | ||
176 | } | ||
177 | m_serverTimestamp = QDateTime(); | ||
178 | // if no output file was set write to buffer | ||
179 | if(!outputToBuffer) { | ||
180 | if (!outputFile->open(QIODevice::ReadWrite)) { | ||
181 | qDebug() << "[HTTP] Error: Cannot open " << qPrintable(outputFile->fileName()) | ||
182 | << " for writing: " << qPrintable(outputFile->errorString()) | ||
183 | << endl; | ||
184 | return false; | ||
185 | } | ||
186 | } | ||
187 | qDebug() << "[HTTP] downloading" << url.toEncoded(); | ||
188 | // create request | ||
189 | http.setHost(url.host(), url.port(80)); | ||
190 | // construct query (if any) | ||
191 | QList<QPair<QString, QString> > qitems = url.queryItems(); | ||
192 | if(url.hasQuery()) { | ||
193 | m_query = "?"; | ||
194 | for(int i = 0; i < qitems.size(); i++) | ||
195 | m_query += QUrl::toPercentEncoding(qitems.at(i).first, "/") + "=" | ||
196 | + QUrl::toPercentEncoding(qitems.at(i).second, "/") + "&"; | ||
197 | } | ||
198 | |||
199 | // create hash used for caching | ||
200 | m_hash = QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Md5).toHex(); | ||
201 | m_path = QString(QUrl::toPercentEncoding(url.path(), "/")); | ||
202 | |||
203 | // construct request header | ||
204 | m_header.setValue("Host", url.host()); | ||
205 | m_header.setValue("User-Agent", m_globalUserAgent); | ||
206 | m_header.setValue("Connection", "Keep-Alive"); | ||
207 | |||
208 | if(m_dumbCache || !m_usecache) { | ||
209 | getFileFinish(); | ||
210 | } | ||
211 | else { | ||
212 | // schedule HTTP header request | ||
213 | connect(this, SIGNAL(headerFinished()), this, SLOT(getFileFinish())); | ||
214 | m_header.setRequest("HEAD", m_path + m_query); | ||
215 | headRequest = http.request(m_header); | ||
216 | } | ||
217 | |||
218 | return true; | ||
219 | } | ||
220 | |||
221 | |||
222 | void HttpGet::getFileFinish() | ||
223 | { | ||
224 | m_cachefile = m_cachedir.absolutePath() + "/rbutil-cache/" + m_hash; | ||
225 | if(m_usecache) { | ||
226 | // check if the file is present in cache | ||
227 | qDebug() << "[HTTP] cache ENABLED"; | ||
228 | QFileInfo cachefile = QFileInfo(m_cachefile); | ||
229 | if(cachefile.isReadable() | ||
230 | && cachefile.size() > 0 | ||
231 | && cachefile.lastModified() > m_serverTimestamp) { | ||
232 | |||
233 | qDebug() << "[HTTP] cached file found:" << m_cachefile; | ||
234 | |||
235 | getRequest = -1; | ||
236 | QFile c(m_cachefile); | ||
237 | if(!outputToBuffer) { | ||
238 | qDebug() << "[HTTP] copying cache file to output" << outputFile->fileName(); | ||
239 | c.open(QIODevice::ReadOnly); | ||
240 | outputFile->open(QIODevice::ReadWrite); | ||
241 | outputFile->write(c.readAll()); | ||
242 | outputFile->close(); | ||
243 | c.close(); | ||
244 | } | ||
245 | else { | ||
246 | qDebug() << "[HTTP] reading cache file into buffer"; | ||
247 | c.open(QIODevice::ReadOnly); | ||
248 | dataBuffer = c.readAll(); | ||
249 | c.close(); | ||
250 | } | ||
251 | m_response = 200; // fake "200 OK" HTTP response | ||
252 | m_cached = true; | ||
253 | httpDone(false); // we're done now. Fake http "done" signal. | ||
254 | return; | ||
255 | } | ||
256 | else { | ||
257 | if(cachefile.isReadable()) | ||
258 | qDebug() << "[HTTP] file in cache timestamp:" << cachefile.lastModified(); | ||
259 | else | ||
260 | qDebug() << "[HTTP] file not in cache."; | ||
261 | qDebug() << "[HTTP] server file timestamp:" << m_serverTimestamp; | ||
262 | qDebug() << "[HTTP] downloading file to" << m_cachefile; | ||
263 | // unlink old cache file | ||
264 | if(cachefile.isReadable()) | ||
265 | QFile(m_cachefile).remove(); | ||
266 | } | ||
267 | |||
268 | } | ||
269 | else { | ||
270 | qDebug() << "[HTTP] cache DISABLED"; | ||
271 | } | ||
272 | // schedule GET request | ||
273 | m_header.setRequest("GET", m_path + m_query); | ||
274 | if(outputToBuffer) { | ||
275 | qDebug() << "[HTTP] downloading to buffer."; | ||
276 | getRequest = http.request(m_header); | ||
277 | } | ||
278 | else { | ||
279 | qDebug() << "[HTTP] downloading to file:" | ||
280 | << qPrintable(outputFile->fileName()); | ||
281 | getRequest = http.request(m_header, 0, outputFile); | ||
282 | } | ||
283 | qDebug() << "[HTTP] GET request scheduled, id:" << getRequest; | ||
284 | |||
285 | return; | ||
286 | } | ||
287 | |||
288 | |||
289 | void HttpGet::httpDone(bool error) | ||
290 | { | ||
291 | if (error) { | ||
292 | qDebug() << "[HTTP] Error: " << qPrintable(http.errorString()) << httpResponse(); | ||
293 | } | ||
294 | if(!outputToBuffer) | ||
295 | outputFile->close(); | ||
296 | |||
297 | if(m_usecache && !m_cached && !error) { | ||
298 | qDebug() << "[HTTP] creating cache file" << m_cachefile; | ||
299 | QFile c(m_cachefile); | ||
300 | c.open(QIODevice::ReadWrite); | ||
301 | if(!outputToBuffer) { | ||
302 | outputFile->open(QIODevice::ReadOnly | QIODevice::Truncate); | ||
303 | c.write(outputFile->readAll()); | ||
304 | outputFile->close(); | ||
305 | } | ||
306 | else | ||
307 | c.write(dataBuffer); | ||
308 | |||
309 | c.close(); | ||
310 | } | ||
311 | // if cached file found and cache enabled ignore http errors | ||
312 | if(m_usecache && m_cached && !http.hasPendingRequests()) { | ||
313 | error = false; | ||
314 | } | ||
315 | // take care of concurring requests. If there is still one running, | ||
316 | // don't emit done(). That request will call this slot again. | ||
317 | if(http.currentId() == 0 && !http.hasPendingRequests()) | ||
318 | emit done(error); | ||
319 | } | ||
320 | |||
321 | |||
322 | void HttpGet::httpFinished(int id, bool error) | ||
323 | { | ||
324 | qDebug() << "[HTTP]" << __func__ << "(int, bool) =" << id << error; | ||
325 | if(id == getRequest) { | ||
326 | dataBuffer = http.readAll(); | ||
327 | |||
328 | emit requestFinished(id, error); | ||
329 | } | ||
330 | qDebug() << "[HTTP] hasPendingRequests =" << http.hasPendingRequests(); | ||
331 | |||
332 | |||
333 | if(id == headRequest) { | ||
334 | QHttpResponseHeader h = http.lastResponse(); | ||
335 | |||
336 | QString date = h.value("Last-Modified").simplified(); | ||
337 | if(date.isEmpty()) { | ||
338 | m_serverTimestamp = QDateTime(); // no value = invalid | ||
339 | emit headerFinished(); | ||
340 | return; | ||
341 | } | ||
342 | // to successfully parse the date strip weekday and timezone | ||
343 | date.remove(0, date.indexOf(" ") + 1); | ||
344 | if(date.endsWith("GMT")) | ||
345 | date.truncate(date.indexOf(" GMT")); | ||
346 | // distinguish input formats (see RFC1945) | ||
347 | // RFC 850 | ||
348 | if(date.contains("-")) | ||
349 | m_serverTimestamp = QDateTime::fromString(date, "dd-MMM-yy hh:mm:ss"); | ||
350 | // asctime format | ||
351 | else if(date.at(0).isLetter()) | ||
352 | m_serverTimestamp = QDateTime::fromString(date, "MMM d hh:mm:ss yyyy"); | ||
353 | // RFC 822 | ||
354 | else | ||
355 | m_serverTimestamp = QDateTime::fromString(date, "dd MMM yyyy hh:mm:ss"); | ||
356 | qDebug() << "[HTTP] Header Request Date:" << date << ", parsed:" << m_serverTimestamp; | ||
357 | emit headerFinished(); | ||
358 | return; | ||
359 | } | ||
360 | if(id == getRequest) | ||
361 | emit requestFinished(id, error); | ||
362 | } | ||
363 | |||
364 | void HttpGet::httpStarted(int id) | ||
365 | { | ||
366 | qDebug() << "[HTTP]" << __func__ << "(int) =" << id; | ||
367 | qDebug() << "headRequest" << headRequest << "getRequest" << getRequest; | ||
368 | } | ||
369 | |||
370 | |||
371 | QString HttpGet::errorString() | ||
372 | { | ||
373 | return http.errorString(); | ||
374 | } | ||
375 | |||
376 | |||
377 | void HttpGet::httpResponseHeader(const QHttpResponseHeader &resp) | ||
378 | { | ||
379 | // if there is a network error abort all scheduled requests for | ||
380 | // this download | ||
381 | m_response = resp.statusCode(); | ||
382 | if(m_response != 200) { | ||
383 | qDebug() << "[HTTP] response error =" << m_response << resp.reasonPhrase(); | ||
384 | http.abort(); | ||
385 | } | ||
386 | // 301 -- moved permanently | ||
387 | // 302 -- found | ||
388 | // 303 -- see other | ||
389 | // 307 -- moved temporarily | ||
390 | // in all cases, header: location has the correct address so we can follow. | ||
391 | if(m_response == 301 || m_response == 302 || m_response == 303 || m_response == 307) { | ||
392 | // start new request with new url | ||
393 | qDebug() << "[HTTP] response =" << m_response << "- following"; | ||
394 | getFile(resp.value("location") + m_query); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | |||
399 | int HttpGet::httpResponse() | ||
400 | { | ||
401 | return m_response; | ||
402 | } | ||
403 | |||
404 | |||
405 | void HttpGet::httpState(int state) | ||
406 | { | ||
407 | QString s[] = {"Unconnected", "HostLookup", "Connecting", "Sending", | ||
408 | "Reading", "Connected", "Closing"}; | ||
409 | if(state <= 6) | ||
410 | qDebug() << "[HTTP]" << __func__ << "() = " << s[state]; | ||
411 | else qDebug() << "[HTTP]" << __func__ << "() = " << state; | ||
412 | } | ||
413 | |||
diff --git a/rbutil/rbutilqt/base/httpget.h b/rbutil/rbutilqt/base/httpget.h new file mode 100644 index 0000000000..ba4cbc821e --- /dev/null +++ b/rbutil/rbutilqt/base/httpget.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #ifndef HTTPGET_H | ||
24 | #define HTTPGET_H | ||
25 | |||
26 | #include <QtCore> | ||
27 | #include <QtNetwork> | ||
28 | |||
29 | class QUrl; | ||
30 | |||
31 | class HttpGet : public QObject | ||
32 | { | ||
33 | Q_OBJECT | ||
34 | |||
35 | public: | ||
36 | HttpGet(QObject *parent = 0); | ||
37 | |||
38 | bool getFile(const QUrl &url); | ||
39 | void setProxy(const QUrl &url); | ||
40 | void setProxy(bool); | ||
41 | QHttp::Error error(void); | ||
42 | QString errorString(void); | ||
43 | void setFile(QFile*); | ||
44 | void setCache(QDir); | ||
45 | void setCache(bool); | ||
46 | int httpResponse(void); | ||
47 | QByteArray readAll(void); | ||
48 | bool isCached() | ||
49 | { return m_cached; } | ||
50 | QDateTime timestamp(void) | ||
51 | { return m_serverTimestamp; } | ||
52 | void setDumbCache(bool b) //< disable checking of http header timestamp for caching | ||
53 | { m_dumbCache = b; } | ||
54 | static void setGlobalCache(const QDir d) //< set global cache path | ||
55 | { m_globalCache = d; } | ||
56 | static void setGlobalProxy(const QUrl p) //< set global proxy value | ||
57 | { m_globalProxy = p; } | ||
58 | static void setGlobalDumbCache(bool b) //< set "dumb" (ignore server status) caching mode | ||
59 | { m_globalDumbCache = b; } | ||
60 | static void setGlobalUserAgent(QString u) //< set global user agent string | ||
61 | { m_globalUserAgent = u; } | ||
62 | |||
63 | public slots: | ||
64 | void abort(void); | ||
65 | |||
66 | signals: | ||
67 | void done(bool); | ||
68 | void dataReadProgress(int, int); | ||
69 | void requestFinished(int, bool); | ||
70 | void headerFinished(void); | ||
71 | |||
72 | private slots: | ||
73 | void httpDone(bool error); | ||
74 | void httpFinished(int, bool); | ||
75 | void httpResponseHeader(const QHttpResponseHeader&); | ||
76 | void httpState(int); | ||
77 | void httpStarted(int); | ||
78 | void getFileFinish(void); | ||
79 | |||
80 | private: | ||
81 | bool initializeCache(const QDir&); | ||
82 | QHttp http; //< download object | ||
83 | QFile *outputFile; | ||
84 | int m_response; //< http response | ||
85 | int getRequest; //! get file http request id | ||
86 | int headRequest; //! get http header request id | ||
87 | QByteArray dataBuffer; | ||
88 | bool outputToBuffer; | ||
89 | bool m_usecache; | ||
90 | QDir m_cachedir; | ||
91 | QString m_cachefile; // cached filename | ||
92 | bool m_cached; | ||
93 | QUrl m_proxy; | ||
94 | QDateTime m_serverTimestamp; //< timestamp of file on server | ||
95 | QString m_query; //< constructed query to pass http getter | ||
96 | QString m_path; //< constructed path to pass http getter | ||
97 | QString m_hash; //< caching hash | ||
98 | bool m_dumbCache; //< true if caching should ignore the server header | ||
99 | QHttpRequestHeader m_header; | ||
100 | |||
101 | static QDir m_globalCache; //< global cache path value | ||
102 | static QUrl m_globalProxy; //< global proxy value | ||
103 | static bool m_globalDumbCache; //< cache "dumb" mode global setting | ||
104 | static QString m_globalUserAgent; //< global user agent string | ||
105 | }; | ||
106 | |||
107 | #endif | ||
diff --git a/rbutil/rbutilqt/base/rbunzip.cpp b/rbutil/rbutilqt/base/rbunzip.cpp new file mode 100644 index 0000000000..49d12156ea --- /dev/null +++ b/rbutil/rbutilqt/base/rbunzip.cpp | |||
@@ -0,0 +1,48 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "rbunzip.h" | ||
21 | #include <QtCore> | ||
22 | |||
23 | |||
24 | UnZip::ErrorCode RbUnZip::extractArchive(const QString& dest) | ||
25 | { | ||
26 | QStringList files = this->fileList(); | ||
27 | UnZip::ErrorCode error = Ok; | ||
28 | m_abortunzip = false; | ||
29 | |||
30 | int total = files.size(); | ||
31 | for(int i = 0; i < total; i++) { | ||
32 | qDebug() << __func__ << files.at(i); | ||
33 | error = this->extractFile(files.at(i), dest, UnZip::ExtractPaths); | ||
34 | emit unzipProgress(i + 1, total); | ||
35 | QCoreApplication::processEvents(); // update UI | ||
36 | if(m_abortunzip) | ||
37 | error = SkipAll; | ||
38 | if(error != Ok) | ||
39 | break; | ||
40 | } | ||
41 | return error; | ||
42 | } | ||
43 | |||
44 | void RbUnZip::abortUnzip(void) | ||
45 | { | ||
46 | m_abortunzip = true; | ||
47 | } | ||
48 | |||
diff --git a/rbutil/rbutilqt/base/rbunzip.h b/rbutil/rbutilqt/base/rbunzip.h new file mode 100644 index 0000000000..133437a4e2 --- /dev/null +++ b/rbutil/rbutilqt/base/rbunzip.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Riebeling | ||
10 | * $Id$ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef RBUNZIP_H | ||
23 | #define RBUNZIP_H | ||
24 | |||
25 | #include <QtCore> | ||
26 | #include "zip/unzip.h" | ||
27 | #include "zip/zip.h" | ||
28 | |||
29 | class RbUnZip : public QObject, public UnZip | ||
30 | { | ||
31 | Q_OBJECT | ||
32 | public: | ||
33 | UnZip::ErrorCode extractArchive(const QString&); | ||
34 | |||
35 | signals: | ||
36 | void unzipProgress(int, int); | ||
37 | |||
38 | public slots: | ||
39 | void abortUnzip(void); | ||
40 | |||
41 | private: | ||
42 | bool m_abortunzip; | ||
43 | }; | ||
44 | |||
45 | #endif | ||
46 | |||
diff --git a/rbutil/rbutilqt/base/rbzip.cpp b/rbutil/rbutilqt/base/rbzip.cpp new file mode 100644 index 0000000000..b5cfb22416 --- /dev/null +++ b/rbutil/rbutilqt/base/rbzip.cpp | |||
@@ -0,0 +1,65 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Wenger | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "rbzip.h" | ||
21 | #include <QtCore> | ||
22 | |||
23 | |||
24 | Zip::ErrorCode RbZip::createZip(QString zip,QString dir) | ||
25 | { | ||
26 | Zip::ErrorCode error = Ok; | ||
27 | m_curEntry = 1; | ||
28 | m_numEntrys=0; | ||
29 | |||
30 | QCoreApplication::processEvents(); | ||
31 | |||
32 | // get number of entrys in dir | ||
33 | QDirIterator it(dir, QDirIterator::Subdirectories); | ||
34 | while (it.hasNext()) | ||
35 | { | ||
36 | it.next(); | ||
37 | m_numEntrys++; | ||
38 | QCoreApplication::processEvents(); | ||
39 | } | ||
40 | |||
41 | |||
42 | //! create zip | ||
43 | error = Zip::createArchive(zip); | ||
44 | if(error != Ok) | ||
45 | return error; | ||
46 | |||
47 | //! add the content | ||
48 | error = Zip::addDirectory(dir); | ||
49 | if(error != Ok) | ||
50 | return error; | ||
51 | |||
52 | //! close zip | ||
53 | error = Zip::closeArchive(); | ||
54 | |||
55 | return error; | ||
56 | } | ||
57 | |||
58 | void RbZip::progress() | ||
59 | { | ||
60 | m_curEntry++; | ||
61 | emit zipProgress(m_curEntry,m_numEntrys); | ||
62 | QCoreApplication::processEvents(); // update UI | ||
63 | } | ||
64 | |||
65 | |||
diff --git a/rbutil/rbutilqt/base/rbzip.h b/rbutil/rbutilqt/base/rbzip.h new file mode 100644 index 0000000000..d7cf05f3de --- /dev/null +++ b/rbutil/rbutilqt/base/rbzip.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2008 by Dominik Wenger | ||
10 | * $Id$ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #ifndef RBZIP_H | ||
23 | #define RBZIP_H | ||
24 | |||
25 | #include <QtCore> | ||
26 | #include "zip/zip.h" | ||
27 | |||
28 | class RbZip : public QObject, public Zip | ||
29 | { | ||
30 | Q_OBJECT | ||
31 | public: | ||
32 | Zip::ErrorCode createZip(QString zip,QString dir); | ||
33 | |||
34 | virtual void progress(); | ||
35 | |||
36 | signals: | ||
37 | void zipProgress(int, int); | ||
38 | |||
39 | private: | ||
40 | int m_curEntry; | ||
41 | int m_numEntrys; | ||
42 | }; | ||
43 | |||
44 | #endif | ||
45 | |||
diff --git a/rbutil/rbutilqt/base/utils.cpp b/rbutil/rbutilqt/base/utils.cpp new file mode 100644 index 0000000000..a6a80c6eef --- /dev/null +++ b/rbutil/rbutilqt/base/utils.cpp | |||
@@ -0,0 +1,101 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * $Id$ | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "utils.h" | ||
21 | #ifdef UNICODE | ||
22 | #define _UNICODE | ||
23 | #endif | ||
24 | |||
25 | #include <QtCore> | ||
26 | #include <QDebug> | ||
27 | #include <cstdlib> | ||
28 | #include <stdio.h> | ||
29 | |||
30 | #if defined(Q_OS_WIN32) | ||
31 | #include <windows.h> | ||
32 | #include <tchar.h> | ||
33 | #include <winioctl.h> | ||
34 | #endif | ||
35 | |||
36 | // recursive function to delete a dir with files | ||
37 | bool recRmdir( const QString &dirName ) | ||
38 | { | ||
39 | QString dirN = dirName; | ||
40 | QDir dir(dirN); | ||
41 | // make list of entries in directory | ||
42 | QStringList list = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot); | ||
43 | QFileInfo fileInfo; | ||
44 | QString curItem, lstAt; | ||
45 | for(int i = 0; i < list.size(); i++){ // loop through all items of list | ||
46 | QString name = list.at(i); | ||
47 | curItem = dirN + "/" + name; | ||
48 | fileInfo.setFile(curItem); | ||
49 | if(fileInfo.isDir()) // is directory | ||
50 | recRmdir(curItem); // call recRmdir() recursively for deleting subdirectory | ||
51 | else // is file | ||
52 | QFile::remove(curItem); // ok, delete file | ||
53 | } | ||
54 | dir.cdUp(); | ||
55 | return dir.rmdir(dirN); // delete empty dir and return if (now empty) dir-removing was successfull | ||
56 | } | ||
57 | |||
58 | |||
59 | //! @brief resolves the given path, ignoring case. | ||
60 | //! @param path absolute path to resolve. | ||
61 | //! @return returns exact casing of path, empty string if path not found. | ||
62 | QString resolvePathCase(QString path) | ||
63 | { | ||
64 | QStringList elems; | ||
65 | QString realpath; | ||
66 | |||
67 | elems = path.split("/", QString::SkipEmptyParts); | ||
68 | int start; | ||
69 | #if defined(Q_OS_WIN32) | ||
70 | // on windows we must make sure to start with the first entry (i.e. the | ||
71 | // drive letter) instead of a single / to make resolving work. | ||
72 | start = 1; | ||
73 | realpath = elems.at(0) + "/"; | ||
74 | #else | ||
75 | start = 0; | ||
76 | realpath = "/"; | ||
77 | #endif | ||
78 | |||
79 | for(int i = start; i < elems.size(); i++) { | ||
80 | QStringList direlems | ||
81 | = QDir(realpath).entryList(QDir::AllEntries|QDir::Hidden|QDir::System); | ||
82 | if(direlems.contains(elems.at(i), Qt::CaseInsensitive)) { | ||
83 | // need to filter using QRegExp as QStringList::filter(QString) | ||
84 | // matches any substring | ||
85 | QString expr = QString("^" + elems.at(i) + "$"); | ||
86 | QRegExp rx = QRegExp(expr, Qt::CaseInsensitive); | ||
87 | QStringList a = direlems.filter(rx); | ||
88 | |||
89 | if(a.size() != 1) | ||
90 | return QString(""); | ||
91 | if(!realpath.endsWith("/")) | ||
92 | realpath += "/"; | ||
93 | realpath += a.at(0); | ||
94 | } | ||
95 | else | ||
96 | return QString(""); | ||
97 | } | ||
98 | qDebug() << __func__ << path << "->" << realpath; | ||
99 | return realpath; | ||
100 | } | ||
101 | |||
diff --git a/rbutil/rbutilqt/base/utils.h b/rbutil/rbutilqt/base/utils.h new file mode 100644 index 0000000000..19cdca92c9 --- /dev/null +++ b/rbutil/rbutilqt/base/utils.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * $Id$ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | |||
23 | #ifndef UTILS_H | ||
24 | #define UTILS_H | ||
25 | |||
26 | #include <QString> | ||
27 | #include <QUrl> | ||
28 | |||
29 | bool recRmdir( const QString &dirName ); | ||
30 | QString resolvePathCase(QString path); | ||
31 | |||
32 | #endif | ||
33 | |||