~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to extra/kipi-plugins/dlnaexport/extra/hupnp/src/dataelements/hproduct_tokens.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg
  • Date: 2012-11-26 18:24:20 UTC
  • mfrom: (1.9.1) (3.1.23 experimental)
  • Revision ID: package-import@ubuntu.com-20121126182420-qoy6z0nx4ai0wzcl
Tags: 4:3.0.0~beta3-0ubuntu1
* New upstream release
  - Add build-deps :  libhupnp-dev, libqtgstreamer-dev, libmagickcore-dev
* Merge from debian, remaining changes:
  - Make sure libqt4-opengl-dev, libgl1-mesa-dev and libglu1-mesa-dev only
    install on i386,amd64 and powerpc
  - Depend on libtiff-dev instead of libtiff4-dev
  - Drop digikam breaks/replaces kipi-plugins-common since we're past the
    LTS release now
  - digikam to recommend mplayerthumbs | ffmpegthumbs. We currently only
    have latter in the archives, even though former is also supposed to
    be part of kdemultimedia. (LP: #890059)
  - kipi-plugins to recommend www-browser rather than konqueror directly
    since 2.8 no direct usage of konqueror is present in the flickr
    plugin anymore (LP: #1011211)
  - Keep kubuntu_mysqld_executable_name.diff
  - Don't install libkipi translations
  - Keep deps on libcv-dev, libcvaux-dev
  - Keep split packaging of libraries
  - Replace icons from KDE 3 time in debian/xpm.d/*.xpm with the new
    versions (LP: #658047)
* Update debian/not-installed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2010, 2011 Tuomo Penttinen, all rights reserved.
 
3
 *
 
4
 *  Author: Tuomo Penttinen <tp@herqq.org>
 
5
 *
 
6
 *  This file is part of Herqq UPnP (HUPnP) library.
 
7
 *
 
8
 *  Herqq UPnP is free software: you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU Lesser General Public License as published by
 
10
 *  the Free Software Foundation, either version 3 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  Herqq UPnP is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
16
 *  GNU Lesser General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU Lesser General Public License
 
19
 *  along with Herqq UPnP. If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include "hproduct_tokens.h"
 
23
 
 
24
#include "../general/hlogger_p.h"
 
25
 
 
26
#include <QtCore/QRegExp>
 
27
#include <QtCore/QVector>
 
28
 
 
29
namespace Herqq
 
30
{
 
31
 
 
32
namespace Upnp
 
33
{
 
34
 
 
35
/*******************************************************************************
 
36
 * HProductToken
 
37
 ******************************************************************************/
 
38
HProductToken::HProductToken() :
 
39
    m_token(), m_productVersion()
 
40
{
 
41
}
 
42
 
 
43
HProductToken::HProductToken(const QString& token, const QString& productVersion) :
 
44
    m_token(), m_productVersion()
 
45
{
 
46
    HLOG(H_AT, H_FUN);
 
47
 
 
48
    QString tokenTmp(token.simplified());
 
49
    QString productVersionTmp(productVersion.simplified());
 
50
    if (tokenTmp.isEmpty() || productVersionTmp.isEmpty())
 
51
    {
 
52
        HLOG_WARN(QString(
 
53
            "Invalid product token. Token: [%1], Product Version: [%2]").arg(
 
54
                tokenTmp, productVersionTmp));
 
55
 
 
56
        return;
 
57
    }
 
58
 
 
59
    m_token = tokenTmp;
 
60
    m_productVersion = productVersionTmp;
 
61
}
 
62
 
 
63
HProductToken::~HProductToken()
 
64
{
 
65
}
 
66
 
 
67
bool HProductToken::isValid(HValidityCheckLevel checkLevel) const
 
68
{
 
69
    bool looselyValid = !m_token.isEmpty() && !m_productVersion.isEmpty();
 
70
 
 
71
    if (!looselyValid)
 
72
    {
 
73
        return false;
 
74
    }
 
75
    else if (checkLevel == LooseChecks)
 
76
    {
 
77
        return true;
 
78
    }
 
79
 
 
80
    bool ok = false;
 
81
    qint32 separatorIndex = m_productVersion.indexOf('.');
 
82
    if (separatorIndex < 0)
 
83
    {
 
84
        m_productVersion.toInt(&ok);
 
85
        return ok;
 
86
    }
 
87
 
 
88
    m_productVersion.left(separatorIndex).toInt(&ok);
 
89
    if (ok)
 
90
    {
 
91
        m_productVersion.mid(
 
92
            separatorIndex+1, m_productVersion.indexOf('.', separatorIndex+1)).toInt(&ok);
 
93
    }
 
94
 
 
95
    return ok;
 
96
}
 
97
 
 
98
bool HProductToken::isValidUpnpToken() const
 
99
{
 
100
    if (!isValid(StrictChecks))
 
101
    {
 
102
        return false;
 
103
    }
 
104
 
 
105
    QString vrs = version();
 
106
 
 
107
    return (m_token.compare("upnp", Qt::CaseInsensitive) == 0) &&
 
108
           (vrs.size() == 3    &&
 
109
           (vrs[0]     == '1') &&
 
110
            vrs[1]     == '.'  &&
 
111
           (vrs[2] == '0' || vrs[2] == '1'));
 
112
}
 
113
 
 
114
QString HProductToken::toString() const
 
115
{
 
116
    if (!isValid(LooseChecks))
 
117
    {
 
118
        return QString();
 
119
    }
 
120
 
 
121
    return QString("%1/%2").arg(m_token, m_productVersion);
 
122
}
 
123
 
 
124
qint32 HProductToken::minorVersion()
 
125
{
 
126
    if (!isValid(LooseChecks))
 
127
    {
 
128
        return -1;
 
129
    }
 
130
 
 
131
    QString tokenVersion = version();
 
132
 
 
133
    qint32 separatorIndex = tokenVersion.indexOf('.');
 
134
    if (separatorIndex < 0)
 
135
    {
 
136
        return -1;
 
137
    }
 
138
 
 
139
    bool ok = false;
 
140
 
 
141
    qint32 minTmp = tokenVersion.mid(
 
142
        separatorIndex+1, tokenVersion.indexOf('.', separatorIndex+1)).toInt(&ok);
 
143
 
 
144
    return ok ? minTmp : -1;
 
145
}
 
146
 
 
147
qint32 HProductToken::majorVersion()
 
148
{
 
149
    if (!isValid(LooseChecks))
 
150
    {
 
151
        return -1;
 
152
    }
 
153
 
 
154
    QString tokenVersion = version();
 
155
 
 
156
    bool ok = false;
 
157
    qint32 majTmp = -1;
 
158
    qint32 separatorIndex = tokenVersion.indexOf('.');
 
159
    if (separatorIndex < 0)
 
160
    {
 
161
        majTmp = tokenVersion.toInt(&ok);
 
162
        return ok ? majTmp : -1;
 
163
    }
 
164
 
 
165
    majTmp = tokenVersion.left(separatorIndex).toInt(&ok);
 
166
    return ok ? majTmp : -1;
 
167
}
 
168
 
 
169
bool operator==(const HProductToken& obj1, const HProductToken& obj2)
 
170
{
 
171
    return obj1.toString() == obj2.toString();
 
172
}
 
173
 
 
174
bool operator!=(const HProductToken& obj1, const HProductToken& obj2)
 
175
{
 
176
    return !(obj1 == obj2);
 
177
}
 
178
 
 
179
/*******************************************************************************
 
180
 * HProductTokensPrivate
 
181
 ******************************************************************************/
 
182
class HProductTokensPrivate :
 
183
    public QSharedData
 
184
{
 
185
H_DISABLE_COPY(HProductTokensPrivate)
 
186
 
 
187
private:
 
188
 
 
189
    // tries to parse the string into "token/version" pairs
 
190
    // the pairs have to be delimited with white-space or commas
 
191
    // a pair can contain "trailing" data until the last delimiter after which
 
192
    // the token of a new pair is started. for instance, this is valid:
 
193
    // token/version (some data; some more data) otherToken/otherVersion finalToken/finalVersion (data)
 
194
    bool parse(const QString& tokens)
 
195
    {
 
196
        HLOG(H_AT, H_FUN);
 
197
 
 
198
        QVector<HProductToken> productTokens;
 
199
 
 
200
        QString token, buf;
 
201
 
 
202
        qint32 i = tokens.indexOf('/'), j = 0, lastDelim = 0;
 
203
        if (i < 0)
 
204
        {
 
205
            return false;
 
206
        }
 
207
 
 
208
        token = tokens.left(i);
 
209
        // the first special case "token/version token/version token/version"
 
210
        //                         ^^^^^
 
211
 
 
212
        for(i = i + 1; i < tokens.size(); ++i, ++j)
 
213
        {
 
214
            if (tokens[i] == '/')
 
215
            {
 
216
                if (lastDelim <= 0)
 
217
                {
 
218
                    // there must have been at least one space between the previous '/'
 
219
                    // and this one. it is an error otherwise.
 
220
                    return false;
 
221
                }
 
222
 
 
223
                HProductToken newToken(token, buf.left(lastDelim));
 
224
                if (newToken.isValid(LooseChecks))
 
225
                {
 
226
                    productTokens.append(newToken);
 
227
                }
 
228
                else
 
229
                {
 
230
                    return false;
 
231
                }
 
232
 
 
233
                token = buf.mid(lastDelim+1);
 
234
                buf.clear(); j = -1;
 
235
 
 
236
                continue;
 
237
            }
 
238
            else if (tokens[i] == ' ')
 
239
            {
 
240
                lastDelim = j;
 
241
            }
 
242
 
 
243
            buf.append(tokens[i]);
 
244
        }
 
245
 
 
246
        HProductToken newToken(token, buf);
 
247
        if (newToken.isValid(LooseChecks))
 
248
        {
 
249
            productTokens.append(newToken);
 
250
        }
 
251
        else
 
252
        {
 
253
            return false;
 
254
        }
 
255
 
 
256
        // at this point the provided token string is parsed into
 
257
        // valid token/version pairs, but it is not known if the tokens string
 
258
        // contained the UPnP token + we should inform the user if
 
259
        // non-std input was given.
 
260
 
 
261
        if (productTokens.size() < 3 || !productTokens[1].isValidUpnpToken())
 
262
        {
 
263
            HLOG_WARN_NONSTD(QString(
 
264
                "The specified token string [%1] is not formed according "
 
265
                "to the UDA specification").arg(tokens));
 
266
            return false;
 
267
        }
 
268
 
 
269
        m_productTokens = productTokens;
 
270
        return true;
 
271
    }
 
272
 
 
273
public:
 
274
 
 
275
    QString m_originalTokenString;
 
276
    QVector<HProductToken> m_productTokens;
 
277
 
 
278
public:
 
279
 
 
280
    HProductTokensPrivate() :
 
281
        m_originalTokenString(), m_productTokens()
 
282
    {
 
283
    }
 
284
 
 
285
    HProductTokensPrivate(const QString& tokens) :
 
286
        m_originalTokenString(tokens.simplified()), m_productTokens()
 
287
    {
 
288
        HLOG(H_AT, H_FUN);
 
289
 
 
290
        bool ok = parse(m_originalTokenString);
 
291
        if (ok)
 
292
        {
 
293
            // the string followed the UDA closely (rare, unfortunately)
 
294
            return;
 
295
        }
 
296
 
 
297
        if (m_originalTokenString.contains(','))
 
298
        {
 
299
            // some sloppy UPnP implementations uses the comma as the delimiter.
 
300
            // technically, comma could be part of the "version" part of the token,
 
301
            // but in practice, it if is present it is used as the delimiter.
 
302
 
 
303
            ok = parse(QString(m_originalTokenString).remove(','));
 
304
            if (ok)
 
305
            {
 
306
                HLOG_WARN_NONSTD(QString(
 
307
                    "Comma should not be used as a delimiter in "
 
308
                    "product tokens: [%1]").arg(tokens));
 
309
 
 
310
                return;
 
311
            }
 
312
        }
 
313
 
 
314
        if (!ok)
 
315
        {
 
316
            // tokenization failed.
 
317
            // fall back for scanning the UPnP/version only
 
318
            QRegExp rexp("(\\b|\\s+)UPnP/");
 
319
            qint32 index = m_originalTokenString.indexOf(
 
320
                rexp, Qt::CaseInsensitive);
 
321
 
 
322
            if (index >= 0)
 
323
            {
 
324
                qint32 matchedLength = rexp.matchedLength();
 
325
                qint32 slash = index + matchedLength;
 
326
                qint32 nextDelim =
 
327
                    m_originalTokenString.indexOf(QRegExp("\\s|,"), slash);
 
328
 
 
329
                HProductToken token(
 
330
                    m_originalTokenString.mid(index, matchedLength-1),
 
331
                    m_originalTokenString.mid(slash,
 
332
                        nextDelim < 0 ? -1 : nextDelim-slash));
 
333
 
 
334
                if (token.isValidUpnpToken())
 
335
                {
 
336
                    m_productTokens.push_back(token);
 
337
                }
 
338
                else
 
339
                {
 
340
                    HLOG_WARN_NONSTD(QString(
 
341
                        "Missing the mandatory UPnP token: [%1]").arg(
 
342
                            m_originalTokenString));
 
343
                }
 
344
            }
 
345
            else
 
346
            {
 
347
                HLOG_WARN_NONSTD(QString(
 
348
                    "Missing the mandatory UPnP token: [%1]").arg(
 
349
                        m_originalTokenString));
 
350
            }
 
351
        }
 
352
    }
 
353
};
 
354
 
 
355
 
 
356
/*******************************************************************************
 
357
 * HProductTokens
 
358
 ******************************************************************************/
 
359
HProductTokens::HProductTokens() :
 
360
    h_ptr(new HProductTokensPrivate())
 
361
{
 
362
}
 
363
 
 
364
HProductTokens::HProductTokens(const QString& tokens) :
 
365
    h_ptr(new HProductTokensPrivate(tokens))
 
366
{
 
367
}
 
368
 
 
369
HProductTokens::HProductTokens(const HProductTokens& other) :
 
370
    h_ptr(other.h_ptr)
 
371
{
 
372
    Q_ASSERT(&other != this);
 
373
}
 
374
 
 
375
HProductTokens& HProductTokens::operator=(const HProductTokens& other)
 
376
{
 
377
    Q_ASSERT(&other != this);
 
378
    h_ptr = other.h_ptr;
 
379
    return *this;
 
380
}
 
381
 
 
382
HProductTokens::~HProductTokens()
 
383
{
 
384
}
 
385
 
 
386
bool HProductTokens::isValid() const
 
387
{
 
388
    return h_ptr->m_productTokens.size() > 0;
 
389
}
 
390
 
 
391
bool HProductTokens::isEmpty() const
 
392
{
 
393
    return h_ptr->m_originalTokenString.isEmpty();
 
394
}
 
395
 
 
396
HProductToken HProductTokens::osToken() const
 
397
{
 
398
    if (h_ptr->m_productTokens.size() < 3)
 
399
    {
 
400
        return HProductToken();
 
401
    }
 
402
 
 
403
    return h_ptr->m_productTokens[0];
 
404
}
 
405
 
 
406
HProductToken HProductTokens::upnpToken() const
 
407
{
 
408
    qint32 size = h_ptr->m_productTokens.size();
 
409
    if (size <= 0)
 
410
    {
 
411
        return HProductToken();
 
412
    }
 
413
    else if (size == 1)
 
414
    {
 
415
        return h_ptr->m_productTokens[0];
 
416
    }
 
417
 
 
418
    return h_ptr->m_productTokens[1];
 
419
}
 
420
 
 
421
HProductToken HProductTokens::productToken() const
 
422
{
 
423
    if (h_ptr->m_productTokens.size() < 3)
 
424
    {
 
425
        return HProductToken();
 
426
    }
 
427
 
 
428
    return h_ptr->m_productTokens[2];
 
429
}
 
430
 
 
431
QVector<HProductToken> HProductTokens::extraTokens() const
 
432
{
 
433
    return h_ptr->m_productTokens.size() > 3 ?
 
434
        h_ptr->m_productTokens.mid(3) : QVector<HProductToken>();
 
435
}
 
436
 
 
437
bool HProductTokens::hasExtraTokens() const
 
438
{
 
439
    return h_ptr->m_productTokens.size() > 3;
 
440
}
 
441
 
 
442
QVector<HProductToken> HProductTokens::tokens() const
 
443
{
 
444
    return h_ptr->m_productTokens;
 
445
}
 
446
 
 
447
QString HProductTokens::toString() const
 
448
{
 
449
    return h_ptr->m_originalTokenString;
 
450
}
 
451
 
 
452
bool operator==(const HProductTokens& ht1, const HProductTokens& ht2)
 
453
{
 
454
    return ht1.toString() == ht2.toString();
 
455
}
 
456
 
 
457
}
 
458
}