VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/networking/UIDownloaderExtensionPack.cpp

Last change on this file was 103793, checked in by vboxsync, 2 months ago

FE/Qt: UICommon: Move versioning related functionality to UIVersion / UIVersionInfo; Rework user cases accordingly.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use