VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/net/UIDownloaderExtensionPack.cpp@ 82781

Last change on this file since 82781 was 79365, checked in by vboxsync, 5 years ago

Renaming VBoxGlobal to UICommon for bugref:9049 as planned.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: UIDownloaderExtensionPack.cpp 79365 2019-06-26 15:57:32Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIDownloaderExtensionPack class implementation.
4 */
5
6/*
7 * Copyright (C) 2011-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QDir>
20#include <QFile>
21#include <QVariant>
22
23/* GUI includes: */
24#include "QIFileDialog.h"
25#include "UICommon.h"
26#include "UIDownloaderExtensionPack.h"
27#include "UIMessageCenter.h"
28#include "UIModalWindowManager.h"
29#include "UINetworkReply.h"
30#include "UIVersion.h"
31
32/* Other VBox includes: */
33#include <iprt/sha.h>
34
35
36/* static */
37UIDownloaderExtensionPack *UIDownloaderExtensionPack::s_pInstance = 0;
38
39/* static */
40UIDownloaderExtensionPack *UIDownloaderExtensionPack::create()
41{
42 if (!s_pInstance)
43 s_pInstance = new UIDownloaderExtensionPack;
44 return s_pInstance;
45}
46
47UIDownloaderExtensionPack::UIDownloaderExtensionPack()
48{
49 /* Prepare instance: */
50 if (!s_pInstance)
51 s_pInstance = this;
52
53 /* Get version number and adjust it for test and trunk builds. The server only has official releases. */
54 const QString strVersion = UIVersion(uiCommon().vboxVersionStringNormalized()).effectiveReleasedVersion().toString();
55
56 /* Prepare source/target: */
57 const QString strUnderscoredName = QString(GUI_ExtPackName).replace(' ', '_');
58 const QString strSourceName = QString("%1-%2.vbox-extpack").arg(strUnderscoredName, strVersion);
59 const QString strSourcePath = QString("https://download.virtualbox.org/virtualbox/%1/").arg(strVersion);
60 const QString strSource = strSourcePath + strSourceName;
61 const QString strPathSHA256SumsFile = QString("https://www.virtualbox.org/download/hashes/%1/SHA256SUMS").arg(strVersion);
62 const QString strTarget = QDir(uiCommon().homeFolder()).absoluteFilePath(strSourceName);
63
64 /* Set source/target: */
65 setSource(strSource);
66 setTarget(strTarget);
67 setPathSHA256SumsFile(strPathSHA256SumsFile);
68}
69
70UIDownloaderExtensionPack::~UIDownloaderExtensionPack()
71{
72 /* Cleanup instance: */
73 if (s_pInstance == this)
74 s_pInstance = 0;
75}
76
77const QString UIDownloaderExtensionPack::description() const
78{
79 return UIDownloader::description().arg(tr("VirtualBox Extension Pack"));
80}
81
82bool UIDownloaderExtensionPack::askForDownloadingConfirmation(UINetworkReply *pReply)
83{
84 return msgCenter().confirmDownloadExtensionPack(GUI_ExtPackName, source().toString(), pReply->header(UINetworkReply::ContentLengthHeader).toInt());
85}
86
87void UIDownloaderExtensionPack::handleDownloadedObject(UINetworkReply *pReply)
88{
89 m_receivedData = pReply->readAll();
90}
91
92void UIDownloaderExtensionPack::handleVerifiedObject(UINetworkReply *pReply)
93{
94 /* Try to verify the SHA-256 checksum: */
95 QString strCalculatedSumm;
96 bool fSuccess = false;
97 do
98 {
99 /* Read received data into the buffer: */
100 const QByteArray receivedData(pReply->readAll());
101 /* Make sure it's not empty: */
102 if (receivedData.isEmpty())
103 break;
104
105 /* Parse buffer contents to dictionary: */
106 const QStringList dictionary(QString(receivedData).split("\n", QString::SkipEmptyParts));
107 /* Make sure it's not empty: */
108 if (dictionary.isEmpty())
109 break;
110
111 /* Parse each record to tags, look for the required one: */
112 foreach (const QString &strRecord, dictionary)
113 {
114 QRegExp separator(" \\*| ");
115 const QString strFileName = strRecord.section(separator, 1);
116 const QString strDownloadedSumm = strRecord.section(separator, 0, 0);
117 if (strFileName == source().fileName())
118 {
119 /* Calc the SHA-256 on the bytes, creating a string: */
120 uint8_t abHash[RTSHA256_HASH_SIZE];
121 RTSha256(m_receivedData.constData(), m_receivedData.length(), abHash);
122 char szDigest[RTSHA256_DIGEST_LEN + 1];
123 int rc = RTSha256ToString(abHash, szDigest, sizeof(szDigest));
124 if (RT_FAILURE(rc))
125 {
126 AssertRC(rc);
127 szDigest[0] = '\0';
128 }
129 strCalculatedSumm = szDigest;
130 //printf("Downloaded SHA-256 summ: [%s]\n", strDownloadedSumm.toUtf8().constData());
131 //printf("Calculated SHA-256 summ: [%s]\n", strCalculatedSumm.toUtf8().constData());
132 /* Make sure checksum is valid: */
133 fSuccess = strDownloadedSumm == strCalculatedSumm;
134 break;
135 }
136 }
137 }
138 while (false);
139
140 /* If SHA-256 checksum verification failed: */
141 if (!fSuccess)
142 {
143 /* Warn the user about additions-image was downloaded and saved but checksum is invalid: */
144 msgCenter().cannotValidateExtentionPackSHA256Sum(GUI_ExtPackName, source().toString(), QDir::toNativeSeparators(target()));
145 return;
146 }
147
148 /* Serialize that buffer into the file: */
149 while (true)
150 {
151 /* Make sure the file already exists. If we reached
152 * this place, it's already written and checked. */
153 QFile file(target());
154 bool fSuccess = false;
155 /* Check step. Try to open file for reading first. */
156 if (file.open(QIODevice::ReadOnly))
157 fSuccess = true;
158 /* Failsafe step. Try to open file for writing otherwise. */
159 if (!fSuccess && file.open(QIODevice::WriteOnly))
160 {
161 /* Write buffer into the file: */
162 file.write(m_receivedData);
163 file.close();
164 fSuccess = true;
165 }
166 /* If the file already exists or was just written: */
167 if (fSuccess)
168 {
169 /* Warn the listener about extension-pack was downloaded: */
170 emit sigDownloadFinished(source().toString(), target(), strCalculatedSumm);
171 break;
172 }
173
174 /* Warn the user about extension-pack was downloaded but was NOT saved: */
175 msgCenter().cannotSaveExtensionPack(GUI_ExtPackName, source().toString(), QDir::toNativeSeparators(target()));
176
177 /* Ask the user for another location for the extension-pack file: */
178 QString strTarget = QIFileDialog::getExistingDirectory(QFileInfo(target()).absolutePath(),
179 windowManager().networkManagerOrMainWindowShown(),
180 tr("Select folder to save %1 to").arg(GUI_ExtPackName), true);
181
182 /* Check if user had really set a new target: */
183 if (!strTarget.isNull())
184 setTarget(QDir(strTarget).absoluteFilePath(QFileInfo(target()).fileName()));
185 else
186 break;
187 }
188}
189
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use