bool FirmwareInfo::ParseXml(QXmlStreamReader& xml) { Clear(); bool foundName = false; bool foundVersion = false; bool foundPlatform = false; bool foundDevelopers = false; bool foundUrl = false; bool foundDonateUrl = false; bool foundDevices = false; bool foundPit = false; bool foundRepartition = false; bool foundNoReboot = false; bool foundFiles = false; if (!xml.readNextStartElement()) { Alerts::DisplayError("Failed to find <firmware> element."); return (false); } if (xml.name() != "firmware") { Alerts::DisplayError(QString("Expected <firmware> element but found <%1>.").arg(xml.name().toString())); return (false); } QString formatVersionString; formatVersionString += xml.attributes().value("version"); if (formatVersionString.isEmpty()) { Alerts::DisplayError("<firmware> is missing the version attribute."); return (false); } bool parsedVersion = false; int formatVersion = formatVersionString.toInt(&parsedVersion); if (!parsedVersion) { Alerts::DisplayError("<firmware> contains a malformed version."); return (false); } if (formatVersion > kVersion) { Alerts::DisplayError("Package is for a newer version of Heimdall Frontend.\nPlease download the latest version of Heimdall Frontend."); return (false); } while (!xml.atEnd()) { QXmlStreamReader::TokenType nextToken = xml.readNext(); if (nextToken == QXmlStreamReader::StartElement) { if (xml.name() == "name") { if (foundName) { Alerts::DisplayError("Found multiple <name> elements in <firmware>."); return (false); } foundName = true; name = xml.readElementText(); } else if (xml.name() == "version") { if (foundVersion) { Alerts::DisplayError("Found multiple <version> elements in <firmware>."); return (false); } foundVersion = true; version = xml.readElementText(); } else if (xml.name() == "platform") { if (foundPlatform) { Alerts::DisplayError("Found multiple <platform> elements in <firmware>."); return (false); } foundPlatform = true; if (!platformInfo.ParseXml(xml)) return (false); } else if (xml.name() == "developers") { if (foundDevelopers) { Alerts::DisplayError("Found multiple <developers> elements in <firmware>."); return (false); } foundDevelopers = true; while (!xml.atEnd()) { nextToken = xml.readNext(); if (nextToken == QXmlStreamReader::StartElement) { if (xml.name() == "name") { developers.append(xml.readElementText()); } else { Alerts::DisplayError(QString("<%1> is not a valid child of <developers>.").arg(xml.name().toString())); return (false); } } else if (nextToken == QXmlStreamReader::EndElement) { if (xml.name() == "developers") break; } else { if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) { Alerts::DisplayError("Unexpected token found in <developers>."); return (false); } } } } else if (xml.name() == "url") { if (foundUrl) { Alerts::DisplayError("Found multiple <url> elements in <firmware>."); return (false); } foundUrl = true; url = xml.readElementText(); } else if (xml.name() == "donateurl") { if (foundDonateUrl) { Alerts::DisplayError("Found multiple <donateurl> elements in <firmware>."); return (false); } foundDonateUrl = true; donateUrl = xml.readElementText(); } else if (xml.name() == "devices") { if (foundDevices) { Alerts::DisplayError("Found multiple <devices> elements in <firmware>."); return (false); } foundDevices = true; while (!xml.atEnd()) { nextToken = xml.readNext(); if (nextToken == QXmlStreamReader::StartElement) { if (xml.name() == "device") { DeviceInfo deviceInfo; if (!deviceInfo.ParseXml(xml)) return (false); deviceInfos.append(deviceInfo); } else { Alerts::DisplayError(QString("<%1> is not a valid child of <devices>.").arg(xml.name().toString())); return (false); } } else if (nextToken == QXmlStreamReader::EndElement) { if (xml.name() == "devices") break; } else { if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) { Alerts::DisplayError("Unexpected token found in <devices>."); return (false); } } } } else if (xml.name() == "pit") { if (foundPit) { Alerts::DisplayError("Found multiple <pit> elements in <firmware>."); return (false); } foundPit = true; pitFilename = xml.readElementText(); } else if (xml.name() == "repartition") { if (foundRepartition) { Alerts::DisplayError("Found multiple <repartition> elements in <firmware>."); return (false); } foundRepartition = true; repartition = (xml.readElementText().toInt() != 0); } else if (xml.name() == "noreboot") { if (foundNoReboot) { Alerts::DisplayError("Found multiple <noreboot> elements in <firmware>."); return (false); } foundNoReboot = true; noReboot = (xml.readElementText().toInt() != 0); } else if (xml.name() == "files") { if (foundFiles) { Alerts::DisplayError("Found multiple <files> elements in <firmware>."); return (false); } foundFiles = true; while (!xml.atEnd()) { nextToken = xml.readNext(); if (nextToken == QXmlStreamReader::StartElement) { if (xml.name() == "file") { FileInfo fileInfo; if (!fileInfo.ParseXml(xml)) return (false); fileInfos.append(fileInfo); } else { Alerts::DisplayError(QString("<%1> is not a valid child of <files>.").arg(xml.name().toString())); return (false); } } else if (nextToken == QXmlStreamReader::EndElement) { if (xml.name() == "files") break; } else { if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) { Alerts::DisplayError("Unexpected token found in <devices>."); return (false); } } } } else { Alerts::DisplayError(QString("<%1> is not a valid child of <firmware>.").arg(xml.name().toString())); return (false); } } else if (nextToken == QXmlStreamReader::EndElement) { if (xml.name() == "firmware") { if (!(foundName && foundVersion && foundPlatform && foundDevelopers && foundDevices && foundPit && foundRepartition && foundNoReboot && foundFiles)) { Alerts::DisplayError("Required elements are missing from <firmware>."); return (false); } else { break; } } } else { if (!(nextToken == QXmlStreamReader::Characters && xml.isWhitespace())) { Alerts::DisplayError("Unexpected token found in <firmware>."); return (false); } } } // Read whitespaces at the end of the file (if there are any) xml.readNext(); if (!xml.atEnd()) { Alerts::DisplayError("Found data after </firmware>."); return (false); } return (true); }