summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2019-11-18 00:38:36 +0100
committerPetr Mrázek <peterix@gmail.com>2019-11-18 00:38:36 +0100
commitaf5120c828831dfe41482ebaff79608ba8531ede (patch)
tree2e308ff3f356f8af94ce9bf7635a2884471ae5db
parent47ed2f48d4a118876263f37b9fe2ab8911c2a8fe (diff)
downloadMultiMC-af5120c828831dfe41482ebaff79608ba8531ede.tar
MultiMC-af5120c828831dfe41482ebaff79608ba8531ede.tar.gz
MultiMC-af5120c828831dfe41482ebaff79608ba8531ede.tar.lz
MultiMC-af5120c828831dfe41482ebaff79608ba8531ede.tar.xz
MultiMC-af5120c828831dfe41482ebaff79608ba8531ede.zip
GH-2859 remove twitch page and modpack import from URL
The functionality was broken, beyond repair and an ongoing maintenance nightmare.
-rw-r--r--api/logic/CMakeLists.txt2
-rw-r--r--api/logic/modplatform/flame/UrlResolvingTask.cpp175
-rw-r--r--api/logic/modplatform/flame/UrlResolvingTask.h43
-rw-r--r--application/CMakeLists.txt3
-rw-r--r--application/dialogs/NewInstanceDialog.cpp13
-rw-r--r--application/dialogs/NewInstanceDialog.h2
-rw-r--r--application/main.cpp1
-rw-r--r--application/pages/modplatform/TwitchPage.cpp65
-rw-r--r--application/pages/modplatform/TwitchPage.h69
-rw-r--r--application/pages/modplatform/TwitchPage.ui79
-rw-r--r--application/resources/assets/assets.qrc6
-rw-r--r--application/resources/assets/deadglitch.svg66
12 files changed, 2 insertions, 522 deletions
diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt
index c6b3e422..995c9d4e 100644
--- a/api/logic/CMakeLists.txt
+++ b/api/logic/CMakeLists.txt
@@ -455,8 +455,6 @@ set(FLAME_SOURCES
modplatform/flame/PackManifest.cpp
modplatform/flame/FileResolvingTask.h
modplatform/flame/FileResolvingTask.cpp
- modplatform/flame/UrlResolvingTask.h
- modplatform/flame/UrlResolvingTask.cpp
)
add_unit_test(Index
diff --git a/api/logic/modplatform/flame/UrlResolvingTask.cpp b/api/logic/modplatform/flame/UrlResolvingTask.cpp
deleted file mode 100644
index 2a96f703..00000000
--- a/api/logic/modplatform/flame/UrlResolvingTask.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-#include "UrlResolvingTask.h"
-#include <QtXml>
-#include <Json.h>
-
-
-namespace {
- const char * metabase = "https://cursemeta.dries007.net";
-}
-
-Flame::UrlResolvingTask::UrlResolvingTask(const QString& toProcess)
- : m_url(toProcess)
-{
-}
-
-void Flame::UrlResolvingTask::executeTask()
-{
- resolveUrl();
-}
-
-void Flame::UrlResolvingTask::resolveUrl()
-{
- setStatus(tr("Resolving URL..."));
- setProgress(0, 1);
- QUrl actualUrl(m_url);
- if(actualUrl.host() != "www.curseforge.com") {
- emitFailed(tr("Not a Twitch URL."));
- return;
- }
- m_dljob.reset(new NetJob("URL resolver"));
-
- bool weAreDigging = false;
- needle = QString();
-
- if(m_url.startsWith("https://")) {
- if(m_url.endsWith("?client=y")) {
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download?client=y
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088?client=y
- m_url.chop(9);
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088
- }
- if(m_url.endsWith("/download")) {
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download -> need to dig inside html...
- weAreDigging = true;
- needle = m_url;
- needle.replace("https://", "twitch://");
- needle.replace("/download", "/download-client/");
- m_url.append("?client=y");
- } else if (m_url.contains("/download/")) {
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088
- m_url.replace("/download/", "/download-client/");
- }
- }
- else if(m_url.startsWith("twitch://")) {
- // twitch://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
- m_url.replace(0, 9, "https://");
- // https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
- }
- auto dl = Net::Download::makeByteArray(QUrl(m_url), &results);
- m_dljob->addNetAction(dl);
- if(weAreDigging) {
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::processHTML);
- } else {
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::processCCIP);
- }
- m_dljob->start();
-}
-
-void Flame::UrlResolvingTask::processHTML()
-{
- QString htmlDoc = QString::fromUtf8(results);
- auto index = htmlDoc.indexOf(needle);
- if(index < 0) {
- emitFailed(tr("Couldn't find the needle in the haystack..."));
- return;
- }
- auto indexStart = index;
- int indexEnd = -1;
- while((index + 1) < htmlDoc.size() && htmlDoc[index] != '"') {
- index ++;
- if(htmlDoc[index] == '"') {
- indexEnd = index;
- break;
- }
- }
- if(indexEnd > 0) {
- QString found = htmlDoc.mid(indexStart, indexEnd - indexStart);
- qDebug() << "Found needle: " << found;
- // twitch://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
- m_url = found;
- resolveUrl();
- return;
- }
- emitFailed(tr("Couldn't find the end of the needle in the haystack..."));
- return;
-}
-
-void Flame::UrlResolvingTask::processCCIP()
-{
- QDomDocument doc;
- if (!doc.setContent(results)) {
- qDebug() << results;
- emitFailed(tr("Resolving failed."));
- return;
- }
- auto packageNode = doc.namedItem("package");
- if(!packageNode.isElement()) {
- emitFailed(tr("Resolving failed: missing package root element."));
- return;
- }
- auto projectNode = packageNode.namedItem("project");
- if(!projectNode.isElement()) {
- emitFailed(tr("Resolving failed: missing project element."));
- return;
- }
- auto attribs = projectNode.attributes();
-
- auto projectIdNode = attribs.namedItem("id");
- if(!projectIdNode.isAttr()) {
- emitFailed(tr("Resolving failed: missing id attribute."));
- return;
- }
- auto fileIdNode = attribs.namedItem("file");
- if(!fileIdNode.isAttr()) {
- emitFailed(tr("Resolving failed: missing file attribute."));
- return;
- }
-
- auto projectId = projectIdNode.nodeValue();
- auto fileId = fileIdNode.nodeValue();
- bool success = true;
- m_result.projectId = projectId.toInt(&success);
- if(!success) {
- emitFailed(tr("Failed to resolve projectId as a number."));
- return;
- }
- m_result.fileId = fileId.toInt(&success);
- if(!success) {
- emitFailed(tr("Failed to resolve fileId as a number."));
- return;
- }
- qDebug() << "Resolved" << m_url << "as" << m_result.projectId << "/" << m_result.fileId;
- resolveIDs();
-}
-
-void Flame::UrlResolvingTask::resolveIDs()
-{
- setStatus(tr("Resolving mod IDs..."));
- m_dljob.reset(new NetJob("Mod id resolver"));
- auto projectIdStr = QString::number(m_result.projectId);
- auto fileIdStr = QString::number(m_result.fileId);
- QString metaurl = QString("%1/%2/%3.json").arg(metabase, projectIdStr, fileIdStr);
- auto dl = Net::Download::makeByteArray(QUrl(metaurl), &results);
- m_dljob->addNetAction(dl);
- connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::processCursemeta);
- m_dljob->start();
-}
-
-void Flame::UrlResolvingTask::processCursemeta()
-{
- try {
- if(m_result.parseFromBytes(results)) {
- emitSucceeded();
- qDebug() << results;
- return;
- }
- } catch (const JSONValidationError &e) {
-
- qCritical() << "Resolving of" << m_result.projectId << m_result.fileId << "failed because of a parsing error:";
- qCritical() << e.cause();
- qCritical() << "JSON:";
- qCritical() << results;
- }
- emitFailed(tr("Failed to resolve the modpack file."));
-}
diff --git a/api/logic/modplatform/flame/UrlResolvingTask.h b/api/logic/modplatform/flame/UrlResolvingTask.h
deleted file mode 100644
index 98b78f67..00000000
--- a/api/logic/modplatform/flame/UrlResolvingTask.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-#include "tasks/Task.h"
-#include "net/NetJob.h"
-#include "PackManifest.h"
-
-#include "multimc_logic_export.h"
-
-namespace Flame
-{
-class MULTIMC_LOGIC_EXPORT UrlResolvingTask : public Task
-{
- Q_OBJECT
-public:
- explicit UrlResolvingTask(const QString &toProcess);
- virtual ~UrlResolvingTask() {};
-
- const Flame::File &getResults() const
- {
- return m_result;
- }
-
-protected:
- virtual void executeTask() override;
-
-protected slots:
- void processCCIP();
- void processHTML();
- void processCursemeta();
-
-private:
- void resolveUrl();
- void resolveIDs();
-
-private: /* data */
- QString m_url;
- QString needle;
- Flame::File m_result;
- QByteArray results;
- NetJobPtr m_dljob;
-};
-}
-
diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt
index 0583c451..a0e01ac8 100644
--- a/application/CMakeLists.txt
+++ b/application/CMakeLists.txt
@@ -133,8 +133,6 @@ SET(MULTIMC_SOURCES
pages/modplatform/legacy_ftb/Page.h
pages/modplatform/legacy_ftb/ListModel.h
pages/modplatform/legacy_ftb/ListModel.cpp
- pages/modplatform/TwitchPage.cpp
- pages/modplatform/TwitchPage.h
pages/modplatform/ImportPage.cpp
pages/modplatform/ImportPage.h
@@ -277,7 +275,6 @@ SET(MULTIMC_UIS
)
set(MULTIMC_QRCS
- resources/assets/assets.qrc
resources/backgrounds/backgrounds.qrc
resources/multimc/multimc.qrc
resources/pe_dark/pe_dark.qrc
diff --git a/application/dialogs/NewInstanceDialog.cpp b/application/dialogs/NewInstanceDialog.cpp
index c5936953..804340bc 100644
--- a/application/dialogs/NewInstanceDialog.cpp
+++ b/application/dialogs/NewInstanceDialog.cpp
@@ -35,7 +35,6 @@
#include "widgets/PageContainer.h"
#include <pages/modplatform/VanillaPage.h>
#include <pages/modplatform/legacy_ftb/Page.h>
-#include <pages/modplatform/TwitchPage.h>
#include <pages/modplatform/ImportPage.h>
@@ -95,14 +94,8 @@ NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString
if(!url.isEmpty())
{
QUrl actualUrl(url);
- if(actualUrl.host() == "www.curseforge.com") {
- m_container->selectPage("twitch");
- twitchPage->setUrl(url);
- }
- else {
- m_container->selectPage("import");
- importPage->setUrl(url);
- }
+ m_container->selectPage("import");
+ importPage->setUrl(url);
}
updateDialogState();
@@ -126,13 +119,11 @@ void NewInstanceDialog::accept()
QList<BasePage *> NewInstanceDialog::getPages()
{
importPage = new ImportPage(this);
- twitchPage = new TwitchPage(this);
return
{
new VanillaPage(this),
importPage,
new LegacyFTB::Page(this),
- twitchPage
};
}
diff --git a/application/dialogs/NewInstanceDialog.h b/application/dialogs/NewInstanceDialog.h
index 0b8b2fb8..c86ab73f 100644
--- a/application/dialogs/NewInstanceDialog.h
+++ b/application/dialogs/NewInstanceDialog.h
@@ -29,7 +29,6 @@ class NewInstanceDialog;
class PageContainer;
class QDialogButtonBox;
class ImportPage;
-class TwitchPage;
class NewInstanceDialog : public QDialog, public BasePageProvider
{
@@ -68,7 +67,6 @@ private:
QString InstIconKey;
ImportPage *importPage = nullptr;
- TwitchPage *twitchPage = nullptr;
std::unique_ptr<InstanceTask> creationTask;
bool importIcon = false;
diff --git a/application/main.cpp b/application/main.cpp
index c871bf1b..b0360c7e 100644
--- a/application/main.cpp
+++ b/application/main.cpp
@@ -43,7 +43,6 @@ int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(multimc);
Q_INIT_RESOURCE(backgrounds);
- Q_INIT_RESOURCE(assets);
Q_INIT_RESOURCE(pe_dark);
Q_INIT_RESOURCE(pe_light);
diff --git a/application/pages/modplatform/TwitchPage.cpp b/application/pages/modplatform/TwitchPage.cpp
deleted file mode 100644
index 389e3194..00000000
--- a/application/pages/modplatform/TwitchPage.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "TwitchPage.h"
-#include "ui_TwitchPage.h"
-
-#include "MultiMC.h"
-#include "dialogs/NewInstanceDialog.h"
-#include <InstanceImportTask.h>
-
-TwitchPage::TwitchPage(NewInstanceDialog* dialog, QWidget *parent)
- : QWidget(parent), ui(new Ui::TwitchPage), dialog(dialog)
-{
- ui->setupUi(this);
- connect(ui->checkButton, &QPushButton::clicked, this, &TwitchPage::triggerCheck);
- connect(ui->twitchLabel, &DropLabel::droppedURLs, [this](QList<QUrl> urls){
- if(urls.size()) {
- setUrl(urls[0].toString());
- }
- });
-}
-
-TwitchPage::~TwitchPage()
-{
- delete ui;
-}
-
-bool TwitchPage::shouldDisplay() const
-{
- return true;
-}
-
-void TwitchPage::openedImpl()
-{
- dialog->setSuggestedPack();
-}
-
-void TwitchPage::triggerCheck(bool)
-{
- if(m_modIdResolver) {
- return;
- }
- auto task = new Flame::UrlResolvingTask(ui->lineEdit->text());
- connect(task, &Task::finished, this, &TwitchPage::checkDone);
- m_modIdResolver.reset(task);
- task->start();
-}
-
-void TwitchPage::setUrl(const QString& url)
-{
- ui->lineEdit->setText(url);
- triggerCheck(true);
-}
-
-void TwitchPage::checkDone()
-{
- auto result = m_modIdResolver->getResults();
- auto formatted = QString("Project %1, File %2").arg(result.projectId).arg(result.fileId);
- if(result.resolved && result.type == Flame::File::Type::Modpack) {
- ui->twitchLabel->setText(formatted);
- QFileInfo fi(result.fileName);
- dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(result.url));
- } else {
- ui->twitchLabel->setPixmap(QPixmap(QString::fromUtf8(":/assets/deadglitch")));
- dialog->setSuggestedPack();
- }
- m_modIdResolver.reset();
-}
diff --git a/application/pages/modplatform/TwitchPage.h b/application/pages/modplatform/TwitchPage.h
deleted file mode 100644
index 600913cd..00000000
--- a/application/pages/modplatform/TwitchPage.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright 2013-2019 MultiMC Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <QWidget>
-
-#include "pages/BasePage.h"
-#include <MultiMC.h>
-#include "tasks/Task.h"
-#include "modplatform/flame/UrlResolvingTask.h"
-
-namespace Ui
-{
-class TwitchPage;
-}
-
-class NewInstanceDialog;
-
-class TwitchPage : public QWidget, public BasePage
-{
- Q_OBJECT
-
-public:
- explicit TwitchPage(NewInstanceDialog* dialog, QWidget *parent = 0);
- virtual ~TwitchPage();
- virtual QString displayName() const override
- {
- return tr("Twitch URL");
- }
- virtual QIcon icon() const override
- {
- return MMC->getThemedIcon("twitch");
- }
- virtual QString id() const override
- {
- return "twitch";
- }
- virtual QString helpPage() const override
- {
- return "Twitch-platform";
- }
- virtual bool shouldDisplay() const override;
-
- void openedImpl() override;
-
- void setUrl(const QString & url);
-
-private slots:
- void triggerCheck(bool checked);
- void checkDone();
-
-private:
- Ui::TwitchPage *ui = nullptr;
- NewInstanceDialog* dialog = nullptr;
- shared_qobject_ptr<Flame::UrlResolvingTask> m_modIdResolver;
-};
diff --git a/application/pages/modplatform/TwitchPage.ui b/application/pages/modplatform/TwitchPage.ui
deleted file mode 100644
index 43a775a0..00000000
--- a/application/pages/modplatform/TwitchPage.ui
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>TwitchPage</class>
- <widget class="QWidget" name="TwitchPage">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>666</width>
- <height>424</height>
- </rect>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0" colspan="3">
- <widget class="DropLabel" name="twitchLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="font">
- <font>
- <pointsize>40</pointsize>
- </font>
- </property>
- <property name="pixmap">
- <pixmap resource="../../resources/assets/assets.qrc">:/assets/deadglitch</pixmap>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QPushButton" name="checkButton">
- <property name="text">
- <string>Check</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Twitch URL:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="lineEdit"/>
- </item>
- <item row="2" column="0" colspan="3">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Drag and drop an Install button from CurseForge into the area above.</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <customwidgets>
- <customwidget>
- <class>DropLabel</class>
- <extends>QLabel</extends>
- <header>widgets/DropLabel.h</header>
- </customwidget>
- </customwidgets>
- <tabstops>
- <tabstop>lineEdit</tabstop>
- <tabstop>checkButton</tabstop>
- </tabstops>
- <resources>
- <include location="../../resources/assets/assets.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/application/resources/assets/assets.qrc b/application/resources/assets/assets.qrc
deleted file mode 100644
index 7a916f05..00000000
--- a/application/resources/assets/assets.qrc
+++ /dev/null
@@ -1,6 +0,0 @@
-<!DOCTYPE RCC>
-<RCC version="1.0">
- <qresource prefix="/assets">
- <file alias="deadglitch">deadglitch.svg</file>
- </qresource>
-</RCC>
diff --git a/application/resources/assets/deadglitch.svg b/application/resources/assets/deadglitch.svg
deleted file mode 100644
index 5682b8a3..00000000
--- a/application/resources/assets/deadglitch.svg
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- class="tw-svg__asset tw-svg__asset--deadglitch tw-svg__asset--inherit"
- width="92px"
- height="96px"
- version="1.1"
- viewBox="0 0 30 30"
- x="0px"
- y="0px"
- id="svg8"
- sodipodi:docname="deadglitch.svg"
- inkscape:version="0.92.2 2405546, 2018-03-11">
- <metadata
- id="metadata14">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <defs
- id="defs12" />
- <sodipodi:namedview
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1"
- objecttolerance="10"
- gridtolerance="10"
- guidetolerance="10"
- inkscape:pageopacity="0"
- inkscape:pageshadow="2"
- inkscape:window-width="1353"
- inkscape:window-height="828"
- id="namedview10"
- showgrid="false"
- inkscape:zoom="4.9166667"
- inkscape:cx="44.285787"
- inkscape:cy="52.833458"
- inkscape:window-x="2958"
- inkscape:window-y="702"
- inkscape:window-maximized="0"
- inkscape:current-layer="svg8" />
- <g
- id="g6"
- style="fill:#898395;fill-opacity:1">
- <path
- d="M26,17.4589613 L26,3 L4,3 L4,22.0601057 L10.0032868,22.0601057 L10.0032868,26 L14.0004537,22.0601057 L21.3322933,22.0601057 L26,17.4589613 L26,17.4589613 Z M21.0896458,26.0850335 L15.1583403,26.0850335 L11.2051771,30 L7.24798611,30 L7.24798611,26.0850335 L0,26.0850335 L0,5.21746493 L1.97773958,0 L29,0 L29,18.2620736 L21.0896458,26.0850335 L21.0896458,26.0850335 Z"
- id="path2"
- style="fill:#898395;fill-opacity:1" />
- <path
- d="M20.8587626,12.1710126 L22.4052753,13.7175252 L23.7175252,12.4052753 L22.1710126,10.8587626 L23.7175252,9.31224999 L22.4052753,8 L20.8587626,9.54651264 L19.31225,8 L18,9.31224999 L19.5465126,10.8587626 L18,12.4052753 L19.31225,13.7175252 L20.8587626,12.1710126 Z M11.8587626,12.1710126 L13.4052753,13.7175252 L14.7175252,12.4052753 L13.1710126,10.8587626 L14.7175252,9.31224999 L13.4052753,8 L11.8587626,9.54651264 L10.31225,8 L9,9.31224999 L10.5465126,10.8587626 L9,12.4052753 L10.31225,13.7175252 L11.8587626,12.1710126 Z"
- id="path4"
- style="fill:#898395;fill-opacity:1" />
- </g>
-</svg>