add more spacing
[personal-kdebase.git] / workspace / plasma / scriptengines / webkit / bundle.cpp
blob8394cc513793257f24f329b1c516ea98bbf3458a
1 /*
2 Copyright (c) 2007 Zack Rusin <zack@kde.org>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
23 #include "bundle.h"
25 #include <QBuffer>
26 #include <QDebug>
27 #include <QDir>
28 #include <QFile>
29 #include <QXmlStreamReader>
31 #include <KIO/CopyJob>
32 #include <KIO/Job>
34 #include <Plasma/PackageMetadata>
35 #include <Plasma/Package>
37 void recursive_print(const KArchiveDirectory *dir, const QString &path)
39 const QStringList l = dir->entries();
40 QStringList::const_iterator it = l.constBegin();
41 for (; it != l.end(); ++it)
43 const KArchiveEntry* entry = dir->entry((*it));
44 printf("mode=%07o %s %s size: %lld pos: %lld %s%s isdir=%d%s",
45 entry->permissions(),
46 entry->user().toLatin1().constData(),
47 entry->group().toLatin1().constData(),
48 entry->isDirectory() ? 0 : ((KArchiveFile*)entry)->size(),
49 entry->isDirectory() ? 0 : ((KArchiveFile*)entry)->position(),
50 path.toLatin1().constData(),
51 (*it).toLatin1().constData(), entry->isDirectory(),
52 entry->symLinkTarget().isEmpty() ? "" :
53 QString(" symlink: %1").arg(
54 entry->symLinkTarget()).toLatin1().constData());
56 //if (!entry->isDirectory()) printf("%d",
57 // ((KArchiveFile*)entry)->size());
58 printf("\n");
59 if (entry->isDirectory())
60 recursive_print((KArchiveDirectory *)entry, path+(*it)+'/');
65 static const KArchiveDirectory *recursiveFind(const KArchiveDirectory *dir)
67 const QStringList l = dir->entries();
68 QStringList::const_iterator it;
69 for (it = l.constBegin(); it != l.constEnd(); ++it) {
70 const KArchiveEntry* entry = dir->entry((*it));
71 if (entry->isDirectory()) {
72 QString name = *it;
73 if (name.startsWith(QLatin1String("__MACOSX"))) {
74 //skip this
75 continue;
76 } else if (name.endsWith(QLatin1String(".wdgt"))) {
77 //got our bad boy
78 return static_cast<const KArchiveDirectory*>(entry);
79 } else {
80 const KArchiveDirectory *fd =
81 recursiveFind(static_cast<const KArchiveDirectory*>(entry));
82 if (fd)
83 return fd;
87 return 0;
90 Bundle::Bundle(const QString &path)
91 : PackageStructure(0, "MacDashboard"),
92 m_isValid(false),
93 m_width(0), m_height(0)
95 setContentsPrefix(QString());
96 QFile f(path);
97 f.open(QIODevice::ReadOnly);
98 m_data = f.readAll();
99 f.close();
100 initTempDir();
101 open();
104 Bundle::Bundle(const QByteArray &data)
105 : PackageStructure(0, "MacDashboard"),
106 m_isValid(false),
107 m_width(0),
108 m_height(0)
110 setContentsPrefix(QString());
111 m_data = data;
112 initTempDir();
113 open();
116 Bundle::Bundle(QObject *parent, QVariantList args)
117 : PackageStructure(parent, "MacDashboard"),
118 m_isValid(false),
119 m_tempDir(0),
120 m_width(0),
121 m_height(0)
123 Q_UNUSED(args)
124 setContentsPrefix(QString());
127 Bundle::~Bundle()
129 close();
130 qWarning("done");
133 void Bundle::setData(const QByteArray &data)
135 m_data = data;
136 close();
137 open();
140 QByteArray Bundle::data() const
142 return m_data;
145 bool Bundle::open()
147 if (!m_tempDir) {
148 initTempDir();
151 if (m_data.isEmpty()) {
152 return false;
155 QBuffer buffer(&m_data);
156 KZip zip(&buffer);
157 if (!zip.open(QIODevice::ReadOnly)) {
158 qWarning("Couldn't open the bundle!");
159 return false;
162 const KArchiveDirectory *dir = zip.directory();
164 const KArchiveDirectory *foundDir = recursiveFind(dir);
165 if (!foundDir) {
166 qWarning("not a bundle");
167 m_isValid = false;
168 zip.close();
169 return 0;
172 m_isValid = extractArchive(foundDir, QLatin1String(""));
173 qDebug()<<"Dir = "<<foundDir->name() << m_isValid;
175 if (m_isValid) {
176 setPath(m_tempDir->name());
179 zip.close();
181 return m_isValid;
184 bool Bundle::close()
186 bool ret = m_tempDir;
187 delete m_tempDir;
188 m_tempDir = 0;
189 return ret;
192 bool Bundle::extractArchive(const KArchiveDirectory *dir, const QString &path)
194 const QStringList l = dir->entries();
196 QStringList::const_iterator it;
197 for (it = l.constBegin(); it != l.constEnd(); ++it) {
198 const KArchiveEntry* entry = dir->entry((*it));
199 QString fullPath = QString("%1/%2").arg(path).arg(*it);
200 if (entry->isDirectory()) {
201 QString outDir = QString("%1%2").arg(m_tempDir->name()).arg(path);
202 QDir qdir(outDir);
203 qdir.mkdir(*it);
204 extractArchive(static_cast<const KArchiveDirectory*>(entry), fullPath);
205 } else if (entry->isFile()) {
206 QString outName = QString("%1%2").arg(m_tempDir->name()).arg(fullPath.remove(0, 1));
207 //qDebug()<<"-------- "<<outName;
208 QFile f(outName);
209 if (!f.open(QIODevice::WriteOnly)) {
210 qWarning("Couldn't create %s", qPrintable(outName));
211 continue;
213 const KArchiveFile *archiveFile = static_cast<const KArchiveFile*>(entry);
214 f.write(archiveFile->data());
215 f.close();
216 } else {
217 qWarning("Unidentified entry at %s", qPrintable(fullPath));
220 return true;
223 void Bundle::pathChanged()
225 //qDebug() << "path changed";
226 m_isValid = extractInfo();
229 bool Bundle::extractInfo()
231 QString plistLocation = QString("%1Info.plist").arg(path());
232 QString configXml = QString("%1config.xml").arg(path());
233 if (QFile::exists(plistLocation)) {
234 //qDebug() << "doing plist";
235 return parsePlist(plistLocation);
236 } else if (QFile::exists(configXml)) {
237 return parseConfigXml(configXml);
240 return false;
243 bool Bundle::parsePlist(const QString &loc)
245 QFile f(loc);
246 if (!f.open(QIODevice::ReadOnly)) {
247 qWarning("Couldn't open info file: '%s'", qPrintable(loc));
248 return false;
251 QMap<QString, QString> infoMap;
252 QString str = f.readAll();
253 QXmlStreamReader reader(str);
254 while (!reader.atEnd()) {
255 reader.readNext();
256 // do processing
257 if (reader.isStartElement()) {
258 //qDebug() << reader.name().toString();
259 if (reader.name() == "key") {
260 QString key, value;
261 reader.readNext();
262 if (reader.isCharacters()) {
263 QString str = reader.text().toString();
264 str = str.trimmed();
265 if (!str.isEmpty())
266 key = str;
268 if (key.isEmpty())
269 continue;
270 while (!reader.isStartElement())
271 reader.readNext();
272 if (reader.name() != "string" &&
273 reader.name() != "integer") {
274 qDebug()<<"Unrecognized val "<<reader.name().toString()
275 <<" for key "<<key;
276 continue;
278 reader.readNext();
279 if (reader.isCharacters()) {
280 QString str = reader.text().toString();
281 str = str.trimmed();
282 if (!str.isEmpty())
283 value = str;
285 //qDebug()<<"key = "<<key<<", value = "<<value;
286 infoMap.insert(key, value);
291 QMap<QString, QString>::const_iterator itr;
292 for (itr = infoMap.constBegin(); itr != infoMap.constEnd(); ++itr) {
293 kDebug() << itr.key() << itr.value();
294 if (itr.key() == QLatin1String("CFBundleIdentifier")) {
295 m_bundleId = itr.value();
296 } else if (itr.key() == QLatin1String("CFBundleName")) {
297 m_description = itr.value();
298 } else if (itr.key() == QLatin1String("CFBundleDisplayName")) {
299 m_name = itr.value();
300 } else if (itr.key() == QLatin1String("CFBundleVersion")) {
301 m_version = itr.value();
302 } else if (itr.key() == QLatin1String("CloseBoxInsetX")) {
304 } else if (itr.key() == QLatin1String("CloseBoxInsetY")) {
306 } else if (itr.key() == QLatin1String("Height")) {
307 m_height = itr.value().toInt();
308 } else if (itr.key() == QLatin1String("Width")) {
309 m_width = itr.value().toInt();
310 } else if (itr.key() == QLatin1String("MainHTML")) {
311 m_htmlLocation = QString("%1%2").arg(path()).arg(itr.value());
312 addFileDefinition("mainscript", itr.value(), i18n("Main Webpage"));
313 } else {
314 qDebug()<<"Unrecognized key = "<<itr.key();
317 m_iconLocation = QString("%1Icon.png").arg(path());
318 kDebug() << path();
319 addDirectoryDefinition("root", "/", i18n("Root HTML directory"));
321 //qDebug()<<"name = "<<m_name;
322 //qDebug()<<"id = "<<m_bundleId;
323 //qDebug()<<"html = "<<m_htmlLocation;
324 //qDebug()<<"icon = "<<m_iconLocation;
326 return !m_bundleId.isEmpty();
329 bool Bundle::installPackage(const QString &archivePath, const QString &packageRoot)
331 //kDebug() << "??????????????" << archivePath << packageRoot;
332 QFile f(archivePath);
333 f.open(QIODevice::ReadOnly);
334 m_data = f.readAll();
335 f.close();
336 open();
338 if (m_isValid) {
339 m_tempDir->setAutoRemove(false);
340 QString pluginName = "dashboard_" + m_bundleId;
341 //kDebug() << "valid, so going to move it in to" << pluginName;
342 KIO::CopyJob* job = KIO::move(m_tempDir->name(), packageRoot + pluginName, KIO::HideProgressInfo);
343 m_isValid = job->exec();
345 if (m_isValid) {
346 //kDebug() << "still so good ... registering";
347 Plasma::PackageMetadata data;
348 data.setName(m_name);
349 data.setDescription(m_description);
350 data.setPluginName(pluginName);
351 data.setImplementationApi("dashboard");
352 Plasma::Package::registerPackage(data, m_iconLocation);
356 if (!m_isValid) {
357 // make sure we clean up after ourselves afterwards on failure
358 m_tempDir->setAutoRemove(true);
361 return m_isValid;
364 bool Bundle::parseConfigXml(const QString &loc)
366 QFile f(loc);
367 if (!f.open(QIODevice::ReadOnly)) {
368 qWarning("Couldn't open info file: '%s'", qPrintable(loc));
369 return false;
372 qWarning("FIXME: Widgets 1.0 not implemented");
374 return false;
377 void Bundle::initTempDir()
379 m_tempDir = new KTempDir();
380 //make it explicit
381 m_tempDir->setAutoRemove(true);
384 QString Bundle::bundleId() const
386 return m_bundleId;
389 QString Bundle::name() const
391 return m_name;
394 QString Bundle::version() const
396 return m_version;
399 QString Bundle::description() const
401 return m_description;
404 int Bundle::width() const
406 return m_width;
409 int Bundle::height() const
411 return m_height;
414 QString Bundle::htmlLocation() const
416 return m_htmlLocation;
419 QString Bundle::iconLocation() const
421 return m_iconLocation;
424 bool Bundle::isValid() const
426 return m_isValid;