updaterscriptparser.cpp
1 //------------------------------------------------------------------------------
2 // updaterscriptparser.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2012 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "updaterscriptparser.h"
24 
25 #include "autoupdater.h"
26 #include <QDebug>
27 #include <cassert>
28 
29 DClass<UpdaterScriptParser>
30 {
31  public:
32  QDomDocument* pDoc;
33 };
34 
35 DPointered(UpdaterScriptParser)
37 UpdaterScriptParser::UpdaterScriptParser(QDomDocument& document)
38 {
39  d->pDoc = &document;
40 }
41 
42 UpdaterScriptParser::~UpdaterScriptParser()
43 {
44 }
45 
46 QDomNode UpdaterScriptParser::installNode(const QDomDocument& doc)
47 {
48  return doc.elementsByTagName("update").at(0).toElement()
49  .elementsByTagName("install").at(0);
50 }
51 
52 QDomElement UpdaterScriptParser::mainElement()
53 {
54  QDomNodeList nodes = d->pDoc->elementsByTagName("update");
55  return nodes.at(0).toElement();
56 }
57 
58 void UpdaterScriptParser::merge(const QDomDocument& otherDoc)
59 {
60  assert(d->pDoc != NULL && "UpdaterScriptParser::merge()");
61  if (!d->pDoc->isNull())
62  {
63  QDomNodeList listNodes;
64  // We'll copy only the "packages" and "install" files.
65  // We'll assume the rest is already set correctly in the
66  // source doc.
67  QDomNode nodePackagesDst = packagesNode(*d->pDoc);
68  QDomNode nodePackagesSrc = packagesNode(otherDoc);
69  listNodes = nodePackagesSrc.toElement().elementsByTagName("package");
70  for (int i = 0; i < listNodes.count(); ++i)
71  {
72  nodePackagesDst.appendChild(listNodes.at(i).cloneNode(true));
73  }
74 
75  QDomNode nodeInstallDst = installNode(*d->pDoc);
76  QDomNode nodeInstallSrc = installNode(otherDoc);
77  listNodes = nodeInstallSrc.toElement().elementsByTagName("file");
78  for (int i = 0; i < listNodes.count(); ++i)
79  {
80  nodeInstallDst.appendChild(listNodes.at(i).cloneNode(true));
81  }
82  }
83  else
84  {
85  *d->pDoc = otherDoc.cloneNode().toDocument();
86  }
87 }
88 
89 QString UpdaterScriptParser::msgMainElementMissingError()
90 {
91  return AutoUpdater::tr("Missing main \"update\" node.");
92 }
93 
94 QDomNode UpdaterScriptParser::packagesNode(const QDomDocument& doc)
95 {
96  return doc.elementsByTagName("update").at(0).toElement()
97  .elementsByTagName("packages").at(0);
98 }
99 
100 QString UpdaterScriptParser::setPackageName(const QString& name)
101 {
102  assert(d->pDoc != NULL && "UpdaterScriptParser::setPackageName()");
103  QString errorMsg;
104  errorMsg = setPackageNameInPackages(name);
105  if (errorMsg.isNull())
106  {
107  errorMsg = setPackageNameInFiles(name);
108  }
109  return errorMsg;
110 }
111 
112 QString UpdaterScriptParser::setPackageNameInFiles(const QString& name)
113 {
114  // Path: /"install"/"file"(*)/"package"/#text
115  QDomNodeList nodes;
116  QDomElement element;
117 
118  element = mainElement();
119  if (element.isNull())
120  {
121  return msgMainElementMissingError();
122  }
123  element = element.elementsByTagName("install").at(0).toElement();
124  if (element.isNull())
125  {
126  return AutoUpdater::tr("Missing \"install\" element.");
127  }
128  nodes = element.elementsByTagName("file");
129  for (int i = 0; i < nodes.count(); ++i)
130  {
131  QDomNode textNode = nodes.at(i).toElement()
132  .elementsByTagName("package").at(0).toElement().firstChild();
133  textNode.setNodeValue(name);
134  if (textNode.isNull())
135  {
136  return AutoUpdater::tr("Missing text node for \"package\" "
137  "element for \"file\" element %1").arg(i);
138  }
139  }
140  return QString();
141 }
142 
143 QString UpdaterScriptParser::setPackageNameInPackages(const QString& name)
144 {
145  // Path: /"packages"/"package"/"name"/#text
146  QDomNodeList nodes;
147  QDomElement element;
148 
149  element = mainElement();
150  if (element.isNull())
151  {
152  return msgMainElementMissingError();
153  }
154 
155  nodes = element.elementsByTagName("packages");
156  if (nodes.isEmpty())
157  {
158  return AutoUpdater::tr("Missing \"packages\" element.");
159  }
160  element = nodes.at(0).toElement();
161  // Now, Mendeley updater allows to have many packages defined in single
162  // script file. Mendeley iterates over these packages and then uses
163  // values of "name" elements to build filenames under which
164  // packages archives are stored. Doomseeker will always use only one
165  // package per script so if there is more than one element under "packages"
166  // tag then this should be treated as an error in the script.
167  nodes = element.elementsByTagName("package");
168  if (nodes.size() != 1)
169  {
170  if (nodes.size() > 1)
171  {
172  return AutoUpdater::tr("More than one \"package\" element found.");
173  }
174  return AutoUpdater::tr("Missing \"package\" element.");
175  }
176  // Since we now know that there is only one "package" node
177  // we can finally set its name.
178  QDomNode nameTextNode = nodes.at(0).toElement()
179  .elementsByTagName("name").at(0).toElement().firstChild();
180  nameTextNode.setNodeValue(name);
181  if (nameTextNode.isNull())
182  {
183  return AutoUpdater::tr("Failed to find \"name\" text node.");
184  }
185  return QString();
186 }
187 
Interface to Mendeley updater .xml script files.
QString setPackageName(const QString &name)
Sets value of package name tags in the script file.
void merge(const QDomDocument &otherDoc)
Merges other script with current script.