bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, const QString &fname, QString currentPath, bool ignoreErrors) { Q_ASSERT(m_errorDevice); const QChar slash = QLatin1Char('/'); if (!currentPath.isEmpty() && !currentPath.endsWith(slash)) currentPath += slash; QDomDocument document; { QString errorMsg; int errorLine = 0; int errorColumn = 0; if (!document.setContent(inputDevice, &errorMsg, &errorLine, &errorColumn)) { if (ignoreErrors) return true; const QString msg = QString::fromUtf8("RCC Parse Error: '%1' Line: %2 Column: %3 [%4]\n").arg(fname).arg(errorLine).arg(errorColumn).arg(errorMsg); m_errorDevice->write(msg.toUtf8()); return false; } } QDomElement domRoot = document.firstChildElement(m_strings.TAG_RCC).toElement(); if (!domRoot.isNull() && domRoot.tagName() == m_strings.TAG_RCC) { for (QDomNode node = domRoot.firstChild(); !node.isNull(); node = node.nextSibling()) { if (!node.isElement()) continue; QDomElement child = node.toElement(); if (!child.isNull() && child.tagName() == m_strings.TAG_RESOURCE) { QLocale::Language language = QLocale::c().language(); QLocale::Country country = QLocale::c().country(); if (child.hasAttribute(m_strings.ATTRIBUTE_LANG)) { QString attribute = child.attribute(m_strings.ATTRIBUTE_LANG); QLocale lang = QLocale(attribute); language = lang.language(); if (2 == attribute.length()) { // Language only country = QLocale::AnyCountry; } else { country = lang.country(); } } QString prefix; if (child.hasAttribute(m_strings.ATTRIBUTE_PREFIX)) prefix = child.attribute(m_strings.ATTRIBUTE_PREFIX); if (!prefix.startsWith(slash)) prefix.prepend(slash); if (!prefix.endsWith(slash)) prefix += slash; for (QDomNode res = child.firstChild(); !res.isNull(); res = res.nextSibling()) { if (res.isElement() && res.toElement().tagName() == m_strings.TAG_FILE) { QString fileName(res.firstChild().toText().data()); if (fileName.isEmpty()) { const QString msg = QString::fromUtf8("RCC: Warning: Null node in XML of '%1'\n").arg(fname); m_errorDevice->write(msg.toUtf8()); } QString alias; if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_ALIAS)) alias = res.toElement().attribute(m_strings.ATTRIBUTE_ALIAS); else alias = fileName; int compressLevel = m_compressLevel; if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) compressLevel = res.toElement().attribute(m_strings.ATTRIBUTE_COMPRESS).toInt(); int compressThreshold = m_compressThreshold; if (res.toElement().hasAttribute(m_strings.ATTRIBUTE_THRESHOLD)) compressThreshold = res.toElement().attribute(m_strings.ATTRIBUTE_THRESHOLD).toInt(); // Special case for -no-compress. Overrides all other settings. if (m_compressLevel == -2) compressLevel = 0; alias = QDir::cleanPath(alias); while (alias.startsWith(QLatin1String("../"))) alias.remove(0, 3); alias = QDir::cleanPath(m_resourceRoot) + prefix + alias; QString absFileName = fileName; if (QDir::isRelativePath(absFileName)) absFileName.prepend(currentPath); QFileInfo file(absFileName); if (!file.exists()) { m_failedResources.push_back(absFileName); const QString msg = QString::fromUtf8("RCC: Error in '%1': Cannot find file '%2'\n").arg(fname).arg(fileName); m_errorDevice->write(msg.toUtf8()); if (ignoreErrors) continue; else return false; } else if (file.isFile()) { const bool arc = addFile(alias, RCCFileInfo(alias.section(slash, -1), file, language, country, RCCFileInfo::NoFlags, compressLevel, compressThreshold) ); if (!arc) m_failedResources.push_back(absFileName); } else { QDir dir; if (file.isDir()) { dir.setPath(file.filePath()); } else { dir.setPath(file.path()); dir.setNameFilters(QStringList(file.fileName())); if (alias.endsWith(file.fileName())) alias = alias.left(alias.length()-file.fileName().length()); } if (!alias.endsWith(slash)) alias += slash; QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); while (it.hasNext()) { it.next(); QFileInfo child(it.fileInfo()); if (child.fileName() != QLatin1String(".") && child.fileName() != QLatin1String("..")) { const bool arc = addFile(alias + child.fileName(), RCCFileInfo(child.fileName(), child, language, country, RCCFileInfo::NoFlags, compressLevel, compressThreshold) ); if (!arc) m_failedResources.push_back(child.fileName()); } } } } } } } } if (m_root == 0) { const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname); m_errorDevice->write(msg.toUtf8()); if (!ignoreErrors && m_format == Binary) { // create dummy entry, otherwise loading qith QResource will crash m_root = new RCCFileInfo(QString(), QFileInfo(), QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory); } } return true; }
bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, QString fname, QString currentPath) { if (!currentPath.isEmpty() && !currentPath.endsWith(QLatin1String("/"))) currentPath += '/'; QDomDocument document; { QString errorMsg; int errorLine, errorColumn; if(!document.setContent(inputDevice, &errorMsg, &errorLine, &errorColumn)) { fprintf(stderr, "pyrcc4 Parse Error:%s:%d:%d [%s]\n", fname.toLatin1().constData(), errorLine, errorColumn, errorMsg.toLatin1().constData()); return false; } } for(QDomElement root = document.firstChild().toElement(); !root.isNull(); root = root.nextSibling().toElement()) { if (root.tagName() != QLatin1String(TAG_RCC)) continue; for (QDomElement child = root.firstChild().toElement(); !child.isNull(); child = child.nextSibling().toElement()) { if (child.tagName() == QLatin1String(TAG_RESOURCE)) { QLocale lang = QLocale::c(); if (child.hasAttribute(ATTRIBUTE_LANG)) lang = QLocale(child.attribute(ATTRIBUTE_LANG)); QString prefix; if (child.hasAttribute(ATTRIBUTE_PREFIX)) prefix = child.attribute(ATTRIBUTE_PREFIX); if (!prefix.startsWith(QLatin1String("/"))) prefix.prepend('/'); if (!prefix.endsWith(QLatin1String("/"))) prefix += '/'; for (QDomNode res = child.firstChild(); !res.isNull(); res = res.nextSibling()) { if (res.toElement().tagName() == QLatin1String(TAG_FILE)) { QString fileName(res.firstChild().toText().data()); if (fileName.isEmpty()) fprintf(stderr, "Warning: Null node in XML\n"); QString alias; if (res.toElement().hasAttribute(ATTRIBUTE_ALIAS)) alias = res.toElement().attribute(ATTRIBUTE_ALIAS); else alias = fileName; int compressLevel = mCompressLevel; if (res.toElement().hasAttribute(ATTRIBUTE_COMPRESS)) compressLevel = res.toElement().attribute(ATTRIBUTE_COMPRESS).toInt(); int compressThreshold = mCompressThreshold; if (res.toElement().hasAttribute(ATTRIBUTE_THRESHOLD)) compressThreshold = res.toElement().attribute(ATTRIBUTE_THRESHOLD).toInt(); // Special case for -no-compress. Overrides all other settings. if (mCompressLevel == -2) compressLevel = 0; alias = QDir::cleanPath(alias); while (alias.startsWith("../")) alias.remove(0, 3); alias = prefix + alias; QFileInfo file(currentPath + fileName); if (!file.exists()) { fprintf(stderr, "Cannot find file: %s\n", fileName.toLatin1().constData()); continue ; } else if (file.isFile()) { addFile(alias, RCCFileInfo(alias.section('/', -1), file, lang, RCCFileInfo::NoFlags, compressLevel, compressThreshold)); } else { QDir dir; if(file.isDir()) { dir.setPath(file.filePath()); } else { dir.setPath(file.path()); dir.setNameFilters(QStringList(file.fileName())); if(alias.endsWith(file.fileName())) alias = alias.left(alias.length()-file.fileName().length()); } if (!alias.endsWith(QLatin1String("/"))) alias += '/'; QFileInfoList children = dir.entryInfoList(); for(int i = 0; i < children.size(); ++i) { if(children[i].fileName() != QLatin1String(".") && children[i].fileName() != QLatin1String("..")) addFile(alias + children[i].fileName(), RCCFileInfo(children[i].fileName(), children[i], lang, RCCFileInfo::NoFlags, compressLevel, compressThreshold)); } } } } } } } if(this->root == 0) { fprintf(stderr, "No resources in resource description.\n"); return false; } return true; }
bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, const QString &fname, QString currentPath, bool ignoreErrors) { Q_ASSERT(m_errorDevice); const QChar slash = QLatin1Char('/'); if (!currentPath.isEmpty() && !currentPath.endsWith(slash)) currentPath += slash; QXmlStreamReader reader(inputDevice); QStack<RCCXmlTag> tokens; QString prefix; QLocale::Language language = QLocale::c().language(); QLocale::Country country = QLocale::c().country(); QString alias; int compressLevel = m_compressLevel; int compressThreshold = m_compressThreshold; while (!reader.atEnd()) { QXmlStreamReader::TokenType t = reader.readNext(); switch (t) { case QXmlStreamReader::StartElement: if (reader.name() == m_strings.TAG_RCC) { if (!tokens.isEmpty()) reader.raiseError(QLatin1String("expected <RCC> tag")); else tokens.push(RccTag); } else if (reader.name() == m_strings.TAG_RESOURCE) { if (tokens.isEmpty() || tokens.top() != RccTag) { reader.raiseError(QLatin1String("unexpected <RESOURCE> tag")); } else { tokens.push(ResourceTag); QXmlStreamAttributes attributes = reader.attributes(); language = QLocale::c().language(); country = QLocale::c().country(); if (attributes.hasAttribute(m_strings.ATTRIBUTE_LANG)) { QString attribute = attributes.value(m_strings.ATTRIBUTE_LANG).toString(); QLocale lang = QLocale(attribute); language = lang.language(); if (2 == attribute.length()) { // Language only country = QLocale::AnyCountry; } else { country = lang.country(); } } prefix.clear(); if (attributes.hasAttribute(m_strings.ATTRIBUTE_PREFIX)) prefix = attributes.value(m_strings.ATTRIBUTE_PREFIX).toString(); if (!prefix.startsWith(slash)) prefix.prepend(slash); if (!prefix.endsWith(slash)) prefix += slash; } } else if (reader.name() == m_strings.TAG_FILE) { if (tokens.isEmpty() || tokens.top() != ResourceTag) { reader.raiseError(QLatin1String("unexpected <FILE> tag")); } else { tokens.push(FileTag); QXmlStreamAttributes attributes = reader.attributes(); alias.clear(); if (attributes.hasAttribute(m_strings.ATTRIBUTE_ALIAS)) alias = attributes.value(m_strings.ATTRIBUTE_ALIAS).toString(); compressLevel = m_compressLevel; if (attributes.hasAttribute(m_strings.ATTRIBUTE_COMPRESS)) compressLevel = attributes.value(m_strings.ATTRIBUTE_COMPRESS).toString().toInt(); compressThreshold = m_compressThreshold; if (attributes.hasAttribute(m_strings.ATTRIBUTE_THRESHOLD)) compressThreshold = attributes.value(m_strings.ATTRIBUTE_THRESHOLD).toString().toInt(); // Special case for -no-compress. Overrides all other settings. if (m_compressLevel == -2) compressLevel = 0; } } else { reader.raiseError(QString(QLatin1String("unexpected tag: %1")).arg(reader.name().toString())); } break; case QXmlStreamReader::EndElement: if (reader.name() == m_strings.TAG_RCC) { if (!tokens.isEmpty() && tokens.top() == RccTag) tokens.pop(); else reader.raiseError(QLatin1String("unexpected closing tag")); } else if (reader.name() == m_strings.TAG_RESOURCE) { if (!tokens.isEmpty() && tokens.top() == ResourceTag) tokens.pop(); else reader.raiseError(QLatin1String("unexpected closing tag")); } else if (reader.name() == m_strings.TAG_FILE) { if (!tokens.isEmpty() && tokens.top() == FileTag) tokens.pop(); else reader.raiseError(QLatin1String("unexpected closing tag")); } break; case QXmlStreamReader::Characters: if (reader.isWhitespace()) break; if (tokens.isEmpty() || tokens.top() != FileTag) { reader.raiseError(QLatin1String("unexpected text")); } else { QString fileName = reader.text().toString(); if (fileName.isEmpty()) { const QString msg = QString::fromLatin1("RCC: Warning: Null node in XML of '%1'\n").arg(fname); m_errorDevice->write(msg.toUtf8()); } if (alias.isNull()) alias = fileName; alias = QDir::cleanPath(alias); while (alias.startsWith(QLatin1String("../"))) alias.remove(0, 3); alias = QDir::cleanPath(m_resourceRoot) + prefix + alias; QString absFileName = fileName; if (QDir::isRelativePath(absFileName)) absFileName.prepend(currentPath); QFileInfo file(absFileName); if (!file.exists()) { m_failedResources.push_back(absFileName); const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n").arg(fname).arg(fileName); m_errorDevice->write(msg.toUtf8()); if (ignoreErrors) continue; else return false; } else if (file.isFile()) { const bool arc = addFile(alias, RCCFileInfo(alias.section(slash, -1), file, language, country, RCCFileInfo::NoFlags, compressLevel, compressThreshold) ); if (!arc) m_failedResources.push_back(absFileName); } else { QDir dir; if (file.isDir()) { dir.setPath(file.filePath()); } else { dir.setPath(file.path()); dir.setNameFilters(QStringList(file.fileName())); if (alias.endsWith(file.fileName())) alias = alias.left(alias.length()-file.fileName().length()); } if (!alias.endsWith(slash)) alias += slash; QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); while (it.hasNext()) { it.next(); QFileInfo child(it.fileInfo()); if (child.fileName() != QLatin1String(".") && child.fileName() != QLatin1String("..")) { const bool arc = addFile(alias + child.fileName(), RCCFileInfo(child.fileName(), child, language, country, child.isDir() ? RCCFileInfo::Directory : RCCFileInfo::NoFlags, compressLevel, compressThreshold) ); if (!arc) m_failedResources.push_back(child.fileName()); } } } } break; default: break; } } if (reader.hasError()) { if (ignoreErrors) return true; int errorLine = reader.lineNumber(); int errorColumn = reader.columnNumber(); QString errorMessage = reader.errorString(); QString msg = QString::fromLatin1("RCC Parse Error: '%1' Line: %2 Column: %3 [%4]\n").arg(fname).arg(errorLine).arg(errorColumn).arg(errorMessage); m_errorDevice->write(msg.toUtf8()); return false; } if (m_root == 0) { const QString msg = QString::fromUtf8("RCC: Warning: No resources in '%1'.\n").arg(fname); m_errorDevice->write(msg.toUtf8()); if (!ignoreErrors && m_format == Binary) { // create dummy entry, otherwise loading with QResource will crash m_root = new RCCFileInfo(QString(), QFileInfo(), QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory); } } return true; }