File indexing completed on 2024-05-19 16:02:02

0001 /*
0002  * This file is part of Office 2007 Filters for Calligra
0003  *
0004  * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
0005  *
0006  * Contact: Suresh Chande suresh.chande@nokia.com
0007  *
0008  * This library is free software; you can redistribute it and/or
0009  * modify it under the terms of the GNU Lesser General Public License
0010  * version 2.1 as published by the Free Software Foundation.
0011  *
0012  * This library is distributed in the hope that it will be useful, but
0013  * WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library; if not, write to the Free Software
0019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020  * 02110-1301 USA
0021  *
0022  */
0023 
0024 #include "MsooXmlReader.h"
0025 #include "MsooXmlSchemas.h"
0026 #include "MsooXmlUtils.h"
0027 
0028 #include <KoXmlWriter.h>
0029 #include <KoCharacterStyle.h>
0030 
0031 #include <klocalizedstring.h>
0032 
0033 QDebug operator<<(QDebug dbg, const QXmlStreamReader& reader)
0034 {
0035     dbg.nospace() << "QXmlStreamReader(";
0036     if (reader.isStartElement()) {
0037         dbg.nospace() << "<";
0038         dbg.nospace() << reader.qualifiedName().toString().toLocal8Bit().constData();
0039         QString attrsString;
0040         const QXmlStreamAttributes& attrs = reader.attributes();
0041         for (int i = 0; i < attrs.count(); i++) {
0042             dbg.nospace() << " " << attrs[i].qualifiedName().toString().toLocal8Bit().constData();
0043             dbg.nospace() << "=";
0044             dbg.nospace() << attrs[i].value().toString();
0045         }
0046         if (reader.isEndElement()) {
0047             dbg.nospace() << "/>)";
0048         } else {
0049             dbg.nospace() << ">)";
0050         }
0051     } else if (reader.isEndElement()) {
0052         dbg.nospace() << "</" << reader.qualifiedName().toString().toLocal8Bit().constData() << ">)";
0053     } else if (reader.isCharacters()) {
0054         dbg.nospace() << "characters:" << reader.text() << ")";
0055     } else if (reader.isComment()) {
0056         dbg.nospace() << "<!-- " << reader.text().toString().toLocal8Bit().constData() << " -->)";
0057     } else if (reader.isCDATA()) {
0058         dbg.nospace() << "CDATA:" << reader.text() << ")";
0059     } else if (reader.isWhitespace()) {
0060         dbg.nospace() << "whitespace:" << reader.text() << ")";
0061     } else {
0062         dbg.nospace() << reader.tokenString() << reader.text();
0063     }
0064     return dbg.space();
0065 }
0066 
0067 using namespace MSOOXML;
0068 
0069 MsooXmlReaderContext::MsooXmlReaderContext(MSOOXML::MsooXmlRelationships* _relationships)
0070         : relationships(_relationships), graphicObjectIsGroup(false)
0071 {
0072 }
0073 
0074 MsooXmlReaderContext::~MsooXmlReaderContext()
0075 {
0076 }
0077 
0078 enum State {
0079     Start,
0080     InsideDocument
0081 };
0082 
0083 MsooXmlReader::MsooXmlReader(KoOdfWriters *writers)
0084         : QXmlStreamReader()
0085         , KoOdfWriters(*writers)
0086 {
0087     init();
0088 }
0089 
0090 MsooXmlReader::MsooXmlReader(QIODevice* io, KoOdfWriters *writers)
0091         : QXmlStreamReader(io)
0092         , KoOdfWriters(*writers)
0093 {
0094     init();
0095 }
0096 
0097 MsooXmlReader::~MsooXmlReader()
0098 {
0099 }
0100 
0101 const char MsooXmlReader::constOn[] = "on";
0102 const char MsooXmlReader::constOff[] = "off";
0103 const char MsooXmlReader::constTrue[] = "true";
0104 const char MsooXmlReader::constFalse[] = "false";
0105 const char MsooXmlReader::constNone[] = "none";
0106 const char MsooXmlReader::const1[] = "1";
0107 const char MsooXmlReader::const0[]  = "0";
0108 const char MsooXmlReader::constAuto[] = "auto";
0109 const char MsooXmlReader::constFloat[] = "float";
0110 const char MsooXmlReader::constPercentage[] = "percentage";
0111 const char MsooXmlReader::constCurrency[] = "currency";
0112 const char MsooXmlReader::constDate[] = "date";
0113 const char MsooXmlReader::constTime[] = "time";
0114 const char MsooXmlReader::constBoolean[] = "boolean";
0115 const char MsooXmlReader::constString[] = "string";
0116 
0117 
0118 void MsooXmlReader::init()
0119 {
0120     m_readUndoed = false;
0121 }
0122 
0123 /*
0124 static const char * tokenNames[] = {
0125     "NoToken", "Invalid", "StartDocument", "EndDocument",
0126     "StartElement", "EndElement", "Characters", "Comment",
0127     "DTD", "EntityReference", "ProcessingInstruction", "??"
0128 };
0129 
0130 static const char* tokenName(QXmlStreamReader::TokenType t)
0131 {
0132     int i = (int)t;
0133     if (i < 0 || i > QXmlStreamReader::ProcessingInstruction)
0134         i = QXmlStreamReader::ProcessingInstruction + 1;
0135     return tokenNames[i];
0136 }
0137 */
0138 
0139 bool MsooXmlReader::readBooleanAttr(const char* attrName, bool defaultValue) const
0140 {
0141     return MSOOXML::Utils::convertBooleanAttr(attributes().value(attrName).toString(), defaultValue);
0142 }
0143 
0144 void MsooXmlReader::raiseError(const QString & message)
0145 {
0146     QXmlStreamReader::raiseError(
0147         m_fileName.isEmpty() ?
0148         i18n("%1 (line %2, column %3)", message,
0149              QString::number(lineNumber()), QString::number(columnNumber()))
0150         : i18n("%1 (%2, line %3, column %4)", message, m_fileName,
0151                QString::number(lineNumber()), QString::number(columnNumber()))
0152     );
0153     debugMsooXml << errorString();
0154 }
0155 
0156 // QXmlStreamReader::TokenType MsooXmlReader::readNext()
0157 // {
0158 //     if (m_readUndoed) {
0159 //         m_readUndoed = false;
0160 //     } else {
0161 //         m_recentType = QXmlStreamReader::readNext();
0162 //     }
0163 //     //debugMsooXml << tokenName(m_recentType) << *this;
0164 //     return m_recentType;
0165 // }
0166 
0167 // void MsooXmlReader::undoReadNext()
0168 // {
0169 //     m_readUndoed = true;
0170 // }
0171 
0172 void MsooXmlReader::raiseElNotFoundError(const char* elementName)
0173 {
0174     raiseError(i18n("Element \"%1\" not found", QLatin1String(elementName)));
0175 }
0176 
0177 void MsooXmlReader::raiseAttributeNotFoundError(const char* attrName)
0178 {
0179     raiseError(i18n("Attribute \"%1\" not found", QLatin1String(attrName)));
0180 }
0181 
0182 void MsooXmlReader::raiseNSNotFoundError(const char* nsName)
0183 {
0184     raiseError(i18n("Namespace \"%1\" not found", nsName));
0185 }
0186 
0187 void MsooXmlReader::raiseUnexpectedAttributeValueError(const QString& value, const char* attrName)
0188 {
0189     raiseError(i18n("Unexpected value \"%1\" of attribute \"%2\"", value, attrName));
0190 }
0191 
0192 void MsooXmlReader::raiseUnexpectedSecondOccurenceOfElError(const char* elementName)
0193 {
0194     raiseError(i18n("Unexpected second occurrence of \"%1\" element", QLatin1String(elementName)));
0195 }
0196 
0197 bool MsooXmlReader::expectElName(const char* elementName)
0198 {
0199     //debugMsooXml << elementName << "found:" << name();
0200     if (!isStartElement() || name() != QLatin1String(elementName)) {
0201         raiseElNotFoundError(elementName);
0202         return false;
0203     }
0204     return true;
0205 }
0206 
0207 bool MsooXmlReader::expectElNameEnd(const char* elementName)
0208 {
0209     //debugMsooXml << elementName << "found:" << name();
0210     if (!isEndElement() || name() != QLatin1String(elementName)) {
0211         raiseError(i18n("Expected closing of element \"%1\"", elementName));
0212         return false;
0213     }
0214     return true;
0215 }
0216 
0217 bool MsooXmlReader::expectEl(const char* qualifiedElementName)
0218 {
0219     //debugMsooXml << qualifiedElementName << "found:" << qualifiedName();
0220     if (!isStartElement() || qualifiedName() != QLatin1String(qualifiedElementName)) {
0221         raiseElNotFoundError(qualifiedElementName);
0222         return false;
0223     }
0224     return true;
0225 }
0226 
0227 bool MsooXmlReader::expectEl(const QString& qualifiedElementName)
0228 {
0229     //debugMsooXml << qualifiedElementName << "found:" << qualifiedName();
0230     if (!isStartElement() || qualifiedName() != qualifiedElementName) {
0231         raiseElNotFoundError(qualifiedElementName.toLatin1());
0232         return false;
0233     }
0234     return true;
0235 }
0236 
0237 bool MsooXmlReader::expectEl(const QList<QByteArray>& qualifiedElementNames)
0238 {
0239     if (isStartElement()) {
0240         foreach (const QByteArray& qualifiedElementName, qualifiedElementNames) {
0241             if (qualifiedName().toString() == qualifiedElementName) {
0242                 //debugMsooXml << qualifiedElementNames << "found:" << qualifiedName();
0243                 return true;
0244             }
0245         }
0246     }
0247     QString list;
0248     foreach (const QByteArray& qualifiedElementName, qualifiedElementNames) {
0249         if (!list.isEmpty())
0250             list += QLatin1String(", ");
0251         list += qualifiedElementName;
0252     }
0253     raiseError(i18n("None of expected elements found: %1", list));
0254     return false;
0255 }
0256 
0257 bool MsooXmlReader::expectElEnd(const QString& qualifiedElementName)
0258 {
0259     //debugMsooXml << qualifiedElementName << "found:" << qualifiedName();
0260 //    debugMsooXml << kBacktrace();
0261     if (!isEndElement() || qualifiedName() != qualifiedElementName) {
0262         raiseError(i18n("Expected closing of element \"%1\"", qualifiedElementName));
0263         return false;
0264     }
0265     return true;
0266 }
0267 
0268 bool MsooXmlReader::expectElEnd(const char* qualifiedElementName)
0269 {
0270     return expectElEnd(QLatin1String(qualifiedElementName));
0271 }
0272 
0273 bool MsooXmlReader::expectNS(const char* nsName)
0274 {
0275     const QLatin1String nsNameString(nsName);
0276     debugMsooXml << namespaceUri() << (namespaceUri().compare(nsNameString) == 0);
0277     if (0 != namespaceUri().compare(nsNameString)) {
0278         raiseNSNotFoundError(nsName);
0279         return false;
0280     }
0281     return true;
0282 }