Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qresourcerelocater.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant
4
6
7#include <QXmlStreamReader>
8#include <QFile>
9#include <QDir>
10
12
13/*!
14 \internal
15 Changes all the paths in resource file \a input so that they are relative to
16 location \a output and writes the result to resource file \a output.
17 */
18int qRelocateResourceFile(const QString &input, const QString &output)
19{
20 enum State {
21 InitialState,
22 InRCC,
23 InResource,
24 InFile
25 };
26 State state = InitialState;
27
28 QString prefix;
29 QString currentFileName;
30 QXmlStreamAttributes fileAttributes;
31
32 QFile file(input);
33 if (!file.open(QIODevice::ReadOnly)) {
34 fprintf(stderr, "Cannot open %s for reading.\n", qPrintable(input));
35 return EXIT_FAILURE;
36 }
37
38 QDir inputDirectory = QFileInfo(file).absoluteDir();
39 QDir outputDirectory = QFileInfo(output).absoluteDir();
40
41 QString outputString;
42 QXmlStreamWriter writer(&outputString);
43 writer.setAutoFormatting(true);
44
45 QXmlStreamReader reader(&file);
46 while (!reader.atEnd()) {
47 switch (reader.readNext()) {
48 case QXmlStreamReader::StartDocument: {
49 QStringView version = reader.documentVersion();
50 if (!version.isEmpty())
51 writer.writeStartDocument(version.toString());
52 else
53 writer.writeStartDocument();
54 break;
55 }
56 case QXmlStreamReader::EndDocument:
57 writer.writeEndDocument();
58 break;
59 case QXmlStreamReader::StartElement:
60 if (reader.name() == QStringLiteral("RCC")) {
61 if (state != InitialState) {
62 fprintf(stderr, "Unexpected RCC tag in line %d\n", int(reader.lineNumber()));
63 return EXIT_FAILURE;
64 }
65 state = InRCC;
66 } else if (reader.name() == QStringLiteral("qresource")) {
67 if (state != InRCC) {
68 fprintf(stderr, "Unexpected qresource tag in line %d\n", int(reader.lineNumber()));
69 return EXIT_FAILURE;
70 }
71 state = InResource;
72 QXmlStreamAttributes attributes = reader.attributes();
73 if (attributes.hasAttribute(QStringLiteral("prefix")))
74 prefix = attributes.value(QStringLiteral("prefix")).toString();
75 if (!prefix.startsWith(QLatin1Char('/')))
76 prefix.prepend(QLatin1Char('/'));
77 if (!prefix.endsWith(QLatin1Char('/')))
78 prefix.append(QLatin1Char('/'));
79 } else if (reader.name() == QStringLiteral("file")) {
80 if (state != InResource) {
81 fprintf(stderr, "Unexpected file tag in line %d\n", int(reader.lineNumber()));
82 return EXIT_FAILURE;
83 }
84 state = InFile;
85 fileAttributes = reader.attributes();
86 continue;
87 }
88 writer.writeStartElement(reader.name().toString());
89 writer.writeAttributes(reader.attributes());
90 continue;
91
92 case QXmlStreamReader::EndElement:
93 if (reader.name() == QStringLiteral("file")) {
94 if (state != InFile) {
95 fprintf(stderr, "Unexpected end of file tag in line %d\n", int(reader.lineNumber()));
96 return EXIT_FAILURE;
97 }
98 state = InResource;
99 continue;
100 } else if (reader.name() == QStringLiteral("qresource")) {
101 if (state != InResource) {
102 fprintf(stderr, "Unexpected end of qresource tag in line %d\n", int(reader.lineNumber()));
103 return EXIT_FAILURE;
104 }
105 state = InRCC;
106 } else if (reader.name() == QStringLiteral("RCC")) {
107 if (state != InRCC) {
108 fprintf(stderr, "Unexpected end of RCC tag in line %d\n", int(reader.lineNumber()));
109 return EXIT_FAILURE;
110 }
111 state = InitialState;
112 }
113 writer.writeEndElement();
114 continue;
115
116 case QXmlStreamReader::Characters:
117 if (reader.isWhitespace())
118 break;
119 if (state != InFile)
120 return EXIT_FAILURE;
121 currentFileName = reader.text().toString();
122 if (currentFileName.isEmpty())
123 continue;
124
125 writer.writeStartElement(QStringLiteral("file"));
126
127 if (!fileAttributes.hasAttribute(QStringLiteral("alias")))
128 fileAttributes.append(QStringLiteral("alias"), currentFileName);
129
130 currentFileName = inputDirectory.absoluteFilePath(currentFileName);
131 currentFileName = outputDirectory.relativeFilePath(currentFileName);
132
133 writer.writeAttributes(fileAttributes);
134 writer.writeCharacters(currentFileName);
135 writer.writeEndElement();
136 continue;
137
138 default: break;
139 }
140 }
141
142 QFile outputFile(output);
143 if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
144 fprintf(stderr, "Cannot open %s for writing.\n", qPrintable(output));
145 return EXIT_FAILURE;
146 }
147 const QByteArray outputStringUtf8 = outputString.toUtf8();
148 if (outputFile.write(outputStringUtf8) != outputStringUtf8.size())
149 return EXIT_FAILURE;
150
151 outputFile.close();
152 if (outputFile.error() != QFileDevice::NoError)
153 return EXIT_FAILURE;
154
155
156 return EXIT_SUCCESS;
157}
158
159QT_END_NAMESPACE
QT_BEGIN_NAMESPACE int qRelocateResourceFile(const QString &input, const QString &output)