src/publishsubscribe/psmapperserver_symbian/qcrmlparser.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qcrmlparser_p.h"
       
    43 #include <QStringList>
       
    44 #include <QFile>
       
    45 #include <QXmlStreamAttributes>
       
    46 
       
    47 QTM_BEGIN_NAMESPACE
       
    48 
       
    49 KeyData::KeyData(const QString &path, quint64 uid, Target target, quint32 bitIndex)
       
    50 {
       
    51     m_path = path;
       
    52     m_UID = uid;
       
    53     m_target = target;
       
    54     m_bitIndex = bitIndex;
       
    55 }
       
    56 
       
    57 QList<KeyData> QCrmlParser::parseQCrml(const QString &filePath)
       
    58 {
       
    59     QList<KeyData> rv;
       
    60     QFile inputFile(filePath);
       
    61 
       
    62     if (!inputFile.exists()) {
       
    63         setError(FileNotFound, QObject::tr("File does not exist: %1").arg(filePath));
       
    64         return rv;
       
    65     }
       
    66 
       
    67     if (!inputFile.open(QFile::ReadOnly)) {
       
    68         setError(FileOpenError, QObject::tr("Error opening file: %1").arg(filePath));
       
    69     }
       
    70 
       
    71     setDevice(&inputFile);
       
    72 
       
    73     readNext();
       
    74     if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
    75         setError(ParseError, QXmlStreamReader::errorString());
       
    76         rv.clear();
       
    77         return rv;
       
    78     }
       
    79 
       
    80     if(isStartDocument()) {
       
    81         readNext();
       
    82         if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
    83             setError(ParseError, QXmlStreamReader::errorString());
       
    84             rv.clear();
       
    85             return rv;
       
    86         }
       
    87     }
       
    88 
       
    89     if (isStartElement()) {
       
    90         if (name() == "repository") {
       
    91             rv = parseRepository();
       
    92         } else {
       
    93             setError(ParseError, QObject::tr("root element is not a repository element"));
       
    94         }
       
    95     }
       
    96     return rv;
       
    97 }
       
    98 
       
    99 QList<KeyData> QCrmlParser::parseRepository()
       
   100 {
       
   101     QList<KeyData> rv;
       
   102     QStringList mandatoryAttributes;
       
   103     mandatoryAttributes << QLatin1String("uidValue");
       
   104     setError(NoError, QString());
       
   105     if (!checkMandatoryAttributes(mandatoryAttributes))
       
   106         return rv;
       
   107 
       
   108     bool ok;
       
   109     quint32 uidValue =
       
   110         uidStringToUInt32(attributes().value(QLatin1String("uidValue")).toString(), &ok);
       
   111     if (!ok) {
       
   112         setError(ParseError, QObject::tr("repository element has invalid uidValue on line %1")
       
   113                                .arg(QString::number(lineNumber())));
       
   114         return rv;
       
   115     }
       
   116 
       
   117     QString targetStr = attributes().value(QLatin1String("target")).toString();
       
   118     if (targetStr.isEmpty() || targetStr == QLatin1String("CRepository")) {
       
   119         m_target = KeyData::CRepository;
       
   120     } else if (targetStr == QLatin1String("RProperty")) {
       
   121         m_target = KeyData::RProperty;
       
   122     } else {
       
   123         setError(ParseError, QObject::tr("repository element has unrecognised target attribute "
       
   124                                         "on line %1, attribute must be CRepository, RProperty or "
       
   125                                         "be left undefined").arg(QString::number(lineNumber())));
       
   126         return rv;
       
   127     }
       
   128 
       
   129     while (!atEnd())
       
   130     {
       
   131         readNext();
       
   132          if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   133             setError(ParseError, QXmlStreamReader::errorString());
       
   134             rv.clear();
       
   135            return rv;
       
   136         }
       
   137 
       
   138         if (isEndElement()  && name() == "repository")
       
   139             break;
       
   140 
       
   141         if (isStartElement()) {
       
   142             if (name() == "key")
       
   143                 rv.append(parseKey(uidValue));
       
   144             else if (name() == "keyRange")
       
   145                 rv.append(parseKeyRange(uidValue));
       
   146             else
       
   147                 parseUnknownElement();
       
   148         }
       
   149 
       
   150         if (m_error != NoError) {
       
   151             rv.clear();
       
   152             break;
       
   153         }
       
   154     }
       
   155 
       
   156     if (!isEndElement() && name() != "repository") {
       
   157         setError(ParseError, QObject::tr("File did not end with a repository end tag"));
       
   158         rv.clear();
       
   159         return rv;
       
   160     }
       
   161 
       
   162     return rv;
       
   163 
       
   164 }
       
   165 
       
   166 QList<KeyData> QCrmlParser::parseKey(quint32 repoUid)
       
   167 {
       
   168     QList<KeyData> rv;
       
   169     QStringList mandatoryAttributes;
       
   170     mandatoryAttributes << QLatin1String("int");
       
   171     if (!checkMandatoryAttributes(mandatoryAttributes))
       
   172         return rv;
       
   173 
       
   174     QXmlStreamAttributes attribs = attributes();
       
   175     QString keyIntStr = attribs.value(QLatin1String("int")).toString();
       
   176     bool ok =false;
       
   177     quint32 keyInt = uidStringToUInt32(keyIntStr, &ok);
       
   178     if (!ok) {
       
   179         setError(ParseError,QObject::tr("key element has invalid int attribute on line %1").
       
   180                 arg(QString::number(lineNumber())));
       
   181         return rv;
       
   182     }
       
   183 
       
   184     if (attribs.value(QLatin1String("ref")).isNull()) {
       
   185         //no ref attribute so this must be
       
   186         //a bitmask key
       
   187         while (!atEnd()) {
       
   188             readNext();
       
   189             if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   190                  setError(ParseError, QXmlStreamReader::errorString());
       
   191                  rv.clear();
       
   192                  return rv;
       
   193             }
       
   194             if (isEndElement())
       
   195                 break;
       
   196 
       
   197             if (isStartElement()) {
       
   198                 if (name() == "bit") {
       
   199                     rv.append(parseBit(repoUid, keyInt));
       
   200                 } else {
       
   201                     parseUnknownElement();
       
   202                 }
       
   203             }
       
   204         }
       
   205     } else {
       
   206         QString keyRef = attribs.value(QLatin1String("ref")).toString();
       
   207         if (keyRef.isEmpty()) {
       
   208             setError(ParseError, QObject::tr("ref attribute of key element is empty on line %1")
       
   209                     .arg(QString::number(lineNumber())));
       
   210             rv.clear();
       
   211             return rv;
       
   212         }
       
   213 
       
   214         while (!atEnd()) {
       
   215             readNext();
       
   216             if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   217                 setError(ParseError, QXmlStreamReader::errorString());
       
   218                 rv.clear();
       
   219                 return rv;
       
   220             }
       
   221             if (isEndElement() && name() == "key") {
       
   222                 break;
       
   223             }
       
   224 
       
   225             if (isStartElement()) {
       
   226                 if (name() == "key" || name() == "keyRange") {
       
   227                     setError(ParseError, QObject::tr("key and/or keyRange element has "
       
   228                                 "been nested in a key element on line %1").arg(QString::number(lineNumber())));
       
   229                     rv.clear();
       
   230                     return rv;
       
   231                 } else {
       
   232                     parseUnknownElement();
       
   233                 }
       
   234             }
       
   235         }
       
   236 
       
   237         QString keyPath(keyRef);
       
   238         if (!keyPath.startsWith(QLatin1Char('/')))
       
   239             keyPath.prepend(QLatin1Char('/'));
       
   240         quint64 uid = repoUid;
       
   241         uid = uid << 32;
       
   242         uid += keyInt;
       
   243         rv.append(KeyData(keyPath, uid,m_target));
       
   244     }
       
   245     return rv;
       
   246 }
       
   247 
       
   248 QList<KeyData> QCrmlParser::parseKeyRange(quint32 repoUid)
       
   249 {
       
   250     QList<KeyData> rv;
       
   251 
       
   252     //if keyRange has no ref attribute it must
       
   253     //only be used for creating access control
       
   254     //policies which we do not need to worry about
       
   255     if (attributes().value(QLatin1String("ref")).isNull())
       
   256         return rv;
       
   257 
       
   258     QStringList mandatoryAttributes;
       
   259     mandatoryAttributes << QLatin1String("firstInt") << QLatin1String("lastInt");
       
   260     if (!checkMandatoryAttributes(mandatoryAttributes))
       
   261         return rv;
       
   262 
       
   263     bool ok = false;
       
   264     QString pathPrefix;
       
   265     pathPrefix = attributes().value(QLatin1String("ref")).toString();
       
   266     if (!pathPrefix.startsWith(QLatin1Char('/')))
       
   267         pathPrefix.prepend(QLatin1Char('/'));
       
   268 
       
   269     if (!attributes().value(QLatin1String("countInt")).isNull()) {
       
   270         quint32 countInt =
       
   271             uidStringToUInt32(attributes().value(QLatin1String("countInt")).toString(), &ok);
       
   272         if (!ok) {
       
   273             setError(ParseError, QObject::tr("keyRange element has invalid countInt attribute on line %1")
       
   274                     .arg(QString::number(lineNumber())));
       
   275             rv.clear();
       
   276             return rv;
       
   277         }
       
   278 
       
   279         rv.append(KeyData(pathPrefix,(quint64)countInt + (((quint64)repoUid) << 32), m_target));
       
   280     }
       
   281 
       
   282     if (!pathPrefix.endsWith(QLatin1Char('/')))
       
   283         pathPrefix.append(QLatin1Char('/'));
       
   284 
       
   285     quint32 firstInt =
       
   286         uidStringToUInt32(attributes().value(QLatin1String("firstInt")).toString(), &ok);
       
   287     if (!ok) {
       
   288         setError(ParseError, QObject::tr("keyRange element has invalid firstInt attribute on line %1")
       
   289                 .arg(QString::number(lineNumber())));
       
   290         rv.clear();
       
   291         return rv;
       
   292     }
       
   293 
       
   294     quint32 lastInt =
       
   295         uidStringToUInt32(attributes().value(QLatin1String("lastInt")).toString(),&ok);
       
   296     if (!ok) {
       
   297         setError(ParseError, QObject::tr("keyRange element has invalid lastInt attribute on line %1")
       
   298                 .arg(QString::number(lineNumber())));
       
   299         rv.clear();
       
   300         return rv;
       
   301     }
       
   302 
       
   303     quint32 maxNum =0;
       
   304     quint32 indexBits = 0;
       
   305     quint32 firstIndex = 0;
       
   306     if (attributes().value(QLatin1String("indexBits")).isNull()) {
       
   307         //keyRange doesn't map to sequence setting
       
   308 
       
   309         maxNum = lastInt - firstInt + 1;
       
   310         for (quint32 i=0; i < maxNum; i++) {
       
   311             rv.append(KeyData(pathPrefix + QString::number(i),
       
   312                                 (quint64)firstInt + (((quint64)repoUid) << 32) + i,
       
   313                                 m_target));
       
   314         }
       
   315 
       
   316         while (!atEnd()) {
       
   317             readNext();
       
   318             if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   319                 setError(ParseError, QXmlStreamReader::errorString());
       
   320                 rv.clear();
       
   321                 return rv;
       
   322             }
       
   323 
       
   324             if (isEndElement())
       
   325                 break;
       
   326 
       
   327             if (isStartElement())
       
   328                 parseUnknownElement();
       
   329         }
       
   330     } else {
       
   331         //keyRanges does  map to sequence setting
       
   332         indexBits =
       
   333             uidStringToUInt32(attributes().value(QLatin1String("indexBits")).toString(), &ok);
       
   334         if (!ok) {
       
   335             setError(ParseError, QObject::tr("keyRange elment has invalid indexBits attribute on line %1")
       
   336                     .arg(QString::number(lineNumber())));
       
   337             rv.clear();
       
   338             return rv;
       
   339         }
       
   340 
       
   341         if (!attributes().value(QLatin1String("firstIndex")).isNull()) {
       
   342             QString firstIndexStr = attributes().value(QLatin1String("firstIndex")).toString();
       
   343             firstIndex = firstIndexStr.toUInt(&ok, 10);
       
   344             if (!ok) {
       
   345                 setError(ParseError, QObject::tr("keyRange element has invalid firstIndex attribute on line %1")
       
   346                         .arg(QString::number(lineNumber())));
       
   347                 rv.clear();
       
   348                 return rv;
       
   349             }
       
   350         }
       
   351 
       
   352         int indexBitsLSB =0;
       
   353         quint32 bitmask = 1;
       
   354         while ( (bitmask & indexBits) == 0) {
       
   355             bitmask = bitmask << 1;
       
   356             bitmask +=1;
       
   357             indexBitsLSB+=1;
       
   358         }
       
   359 
       
   360         maxNum =( ((lastInt - firstInt) & indexBits) >> indexBitsLSB) + 1 - firstIndex;
       
   361 
       
   362         int indexBitsMSB=31;
       
   363         bitmask = 0x80000000;
       
   364         while ((bitmask & indexBits) == 0) {
       
   365             bitmask = bitmask >> 1;
       
   366             bitmask += 0x80000000;
       
   367             indexBitsMSB -=1;
       
   368         }
       
   369         bitmask = bitmask << 1;
       
   370         quint32 settingIdentifier = lastInt & bitmask;
       
   371 
       
   372         QList<KeyData> subSettings;
       
   373 
       
   374         while (!atEnd()) {
       
   375             readNext();
       
   376             if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   377                 setError(ParseError, QXmlStreamReader::errorString());
       
   378                 rv.clear();
       
   379                 return rv;
       
   380             }
       
   381 
       
   382             if (isEndElement())
       
   383                 break;
       
   384 
       
   385             if (isStartElement()) {
       
   386                 if (name() == "key") {
       
   387                     subSettings.append(parseKey(repoUid));
       
   388 
       
   389                     if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   390                         rv.clear();
       
   391                         return rv;
       
   392                     }
       
   393                 } else {
       
   394                     parseUnknownElement();
       
   395                 }
       
   396             }
       
   397 
       
   398         }
       
   399 
       
   400         for(quint32 i = 0; i < maxNum; i++) {
       
   401             for(int j = 0; j < subSettings.count(); j++) {
       
   402                 rv.append(KeyData(pathPrefix + QString::number(i) + subSettings.at(j).path(),
       
   403                                  subSettings.at(j).uid() + settingIdentifier + ((firstIndex + 1*i)  << indexBitsLSB),
       
   404                                  m_target, subSettings.at(j).bitIndex()));
       
   405             }
       
   406         }
       
   407     }
       
   408 
       
   409     return rv;
       
   410 }
       
   411 
       
   412 QList<KeyData> QCrmlParser::parseBit(quint32 repoUid, quint32 keyInt)
       
   413 {
       
   414     QList <KeyData> rv;
       
   415     QStringList mandatoryAttributes;
       
   416     mandatoryAttributes << QLatin1String("ref");
       
   417     if (!checkMandatoryAttributes(mandatoryAttributes)) {
       
   418         rv.clear();
       
   419         return rv;
       
   420     }
       
   421 
       
   422     QString keyPath = attributes().value(QLatin1String("ref")).toString();
       
   423     if (!keyPath.startsWith(QLatin1Char('/')))
       
   424         keyPath.prepend(QLatin1Char('/'));
       
   425 
       
   426     int bitIndex = 0;
       
   427     while(!atEnd()) {
       
   428         readNext();
       
   429         if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   430             setError(ParseError, QXmlStreamReader::errorString());
       
   431             rv.clear();
       
   432             return rv;
       
   433         }
       
   434 
       
   435         if (isEndElement() && name() == "bit")
       
   436             break;
       
   437         if(isStartElement()) {
       
   438             parseUnknownElement();
       
   439             if (error() != NoError) {
       
   440                 rv.clear();
       
   441                 return rv;
       
   442             }
       
   443         } else if (isCharacters()) {
       
   444             bool ok;
       
   445             QString txt = text().toString();
       
   446             if (txt.simplified().isEmpty())
       
   447                 continue;
       
   448             bitIndex = txt.toInt(&ok);
       
   449             if (!ok || bitIndex <= 0) {
       
   450                 //Note: binary keys have no maximum bit index
       
   451                 setError(ParseError, QObject::tr("bit element has invalid text value on line %1")
       
   452                         .arg(QString::number(lineNumber())));
       
   453                 rv.clear();
       
   454                 return rv;
       
   455             }
       
   456         }
       
   457     }
       
   458 
       
   459     if (!isEndElement() && name() !="bit") {
       
   460         setError(ParseError, QObject::tr("bit element does not have end tag at line: %1")
       
   461                             .arg(QString::number(lineNumber())));
       
   462         rv.clear();
       
   463         return rv;
       
   464     }
       
   465 
       
   466     quint64 uid = repoUid;
       
   467     uid = uid << 32;
       
   468     uid += keyInt;
       
   469     rv.append(KeyData(keyPath,uid, m_target, bitIndex));
       
   470     return rv;
       
   471 }
       
   472 
       
   473 void QCrmlParser::parseUnknownElement()
       
   474 {
       
   475     Q_ASSERT(isStartElement());
       
   476     while(!atEnd()) {
       
   477         readNext();
       
   478 
       
   479         if (QXmlStreamReader::error() != QXmlStreamReader::NoError) {
       
   480             setError(ParseError, QXmlStreamReader::errorString());
       
   481             return;
       
   482         }
       
   483 
       
   484         if (isEndElement()) {
       
   485             break;
       
   486         }
       
   487 
       
   488         if (isStartElement())
       
   489             parseUnknownElement();
       
   490     }
       
   491 }
       
   492 
       
   493 bool QCrmlParser::checkMandatoryAttributes(const QStringList &mandatoryAttributes)
       
   494 {
       
   495     QXmlStreamAttributes attrs= attributes() ;
       
   496     for (int i = 0; i < mandatoryAttributes.count(); ++i) {
       
   497         if (attrs.value(mandatoryAttributes.at(i)).isNull()) {
       
   498             setError(ParseError, QObject::tr("%1 element does not contain %2 attribute")
       
   499                     .arg(name().toString()).arg(mandatoryAttributes.at(i)));
       
   500             return false;
       
   501         }
       
   502     }
       
   503     return true;
       
   504 }
       
   505 
       
   506 QCrmlParser::Error QCrmlParser::error()
       
   507 {
       
   508     return m_error;
       
   509 }
       
   510 
       
   511 QString QCrmlParser::errorString()
       
   512 {
       
   513     return m_errorString;
       
   514 }
       
   515 
       
   516 void QCrmlParser::setError(Error error, const QString &errorString)
       
   517 {
       
   518     m_error = error;
       
   519     m_errorString = errorString;
       
   520 }
       
   521 
       
   522 quint32 QCrmlParser::uidStringToUInt32(const QString &uidString, bool *ok)
       
   523 {
       
   524     quint32 uid = 0;
       
   525     if (!uidString.startsWith(QLatin1String("0x"))) {
       
   526         if (ok != NULL)
       
   527             *ok = false;
       
   528          return 0;
       
   529     }
       
   530 
       
   531     bool isOk = false;
       
   532     uid =  uidString.toUInt(&isOk, 16);
       
   533     if (!isOk) {
       
   534         if (ok !=NULL)
       
   535             *ok =false;
       
   536         return 0;
       
   537     }
       
   538 
       
   539     if (ok != NULL)
       
   540         *ok = true;
       
   541     return uid;
       
   542 }
       
   543 
       
   544 QTM_END_NAMESPACE