summaryrefslogtreecommitdiff
path: root/daemon/bundle.cpp
blob: bfd4b830233d547b7a5446bddeda52ff33b55d3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "bundle.h"
#include <QSharedData>
#include <QScopedPointer>
#include <QDir>
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <quazip/quazipfile.h>

class BundleData : public QSharedData {
public:
    bool isValid;
    QString path;
    QJsonObject manifest;

    BundleData() : isValid(false) {}
};

QLoggingCategory Bundle::l("Bundle");

Bundle::Bundle() : b(new BundleData)
{}

Bundle::Bundle(const Bundle &rhs) : b(rhs.b)
{}

Bundle &Bundle::operator=(const Bundle &rhs)
{
    if (this != &rhs)
        b.operator=(rhs.b);
    return *this;
}

Bundle::~Bundle()
{}

QString Bundle::type() const
{
    return b->manifest.value("type").toString();
}

QString Bundle::path() const
{
    return b->path;
}

bool Bundle::isValid() const
{
    return b->isValid;
}

Bundle Bundle::fromPath(const QString &path)
{
    Bundle bundle;

    QFileInfo bundlePath(path);
    if (!bundlePath.isReadable()) {
        qCWarning(l) << "bundle" << bundlePath.absolutePath() << "is not readable";
        return Bundle();
    }

    bundle.b->path = path;

    QScopedPointer<QIODevice> manifestJSON(bundle.openFile(Bundle::MANIFEST, QIODevice::Text));
    if (!manifestJSON) {
        qCWarning(l) << "cannot find" << path << "manifest json";
        return Bundle();
    }

    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(manifestJSON->readAll(), &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        qCWarning(l) << "cannot parse" << path << "manifest json" << parseError.errorString();
        return Bundle();
    }
    manifestJSON->close();
    bundle.b->manifest = doc.object();

    bundle.b->isValid = true;
    return bundle;
}

QIODevice *Bundle::openFile(enum Bundle::File file, QIODevice::OpenMode mode) const
{
    QString fileName;
    switch (file) {
    case Bundle::MANIFEST:
        fileName = "manifest.json";
        break;
    case Bundle::INFO:
        fileName = "appinfo.json";
        break;
    case Bundle::APPJS:
        fileName = "pebble-js-app.js";
        break;
    case Bundle::BINARY:
        fileName = b->manifest.value(type()).toObject().value("name").toString();
        break;
    case Bundle::RESOURCES:
        fileName = b->manifest.value("resources").toObject().value("name").toString();
        break;
    }

    QIODevice *dev = 0;
    QFileInfo bundlePath(path());
    if (bundlePath.isDir()) {
        QDir bundleDir(path());
        if (bundleDir.exists(fileName)) {
            dev = new QFile(bundleDir.absoluteFilePath(fileName));
        }
    } else if (bundlePath.isFile()) {
        dev =  new QuaZipFile(path(), fileName);
    }

    if (dev && !dev->open(QIODevice::ReadOnly | mode)) {
        delete dev;
        return 0;
    }

    return dev;
}

bool Bundle::fileExists(enum Bundle::File file) const
{
    QIODevice *dev = openFile(file);
    bool exists = dev && dev->isOpen();
    delete dev;
    return exists;
}