summaryrefslogtreecommitdiffstats
path: root/torrentparser.cpp
blob: 635d8a7d2ba2f49fdea9f97a55117504777e1963 (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
#include <QFile>

#include "torrentparser.h"

TorrentParser::TorrentParser(const QString file, QObject *parent) : QObject(parent), mFile(file), mPos(0) {}

const QList<QVariant> TorrentParser::parse(){
    QFile f(mFile);
    QList<QVariant> retval;
    if(f.size() > 4*1024*1024){ //this is an arbitray value
        mLastError = tr("File is too big!");
        return retval;
    }
    f.open(QIODevice::ReadOnly);
    mData = f.readAll();
    f.close();
    while(mPos < mData.size()){
        retval << parseObject();
    }
    return retval;
}

const QStringList TorrentParser::files(QList<QVariant> data){
    QStringList retval;
    foreach(QVariant cur, data){
        if(cur.canConvert<QVariantHash>()){
            QVariantHash h = cur.toHash();
            QHash<QString, QVariant>::const_iterator it = h.constBegin();
            while(it != h.constEnd()){
                if(it.key() == "info"){
                    QVariantHash infoD = it.value().toHash();
                    if(infoD.contains("files")){
                        QVariantList fileList = infoD.value("files").toList();
                        foreach(QVariant fn, fileList){
                            QVariantHash e = fn.toHash();
                            QVariantList path = e.value("path").toList();
                            retval << path.last().toString();
                        }
                    }else{
                        retval << infoD.value("name").toString();
                    }
                    break;
                }
                ++it;
            }
        }
    }
    return retval;
}

const QVariant TorrentParser::parseObject(){
    QChar cur = mData.at(mPos);
    if(cur == 'i'){
        return parseInt();
    }
    if(cur == 'l'){
        return parseList();
    }
    if(cur == 'd'){
        return parseDict();
    }
    if(cur.isNumber()){
        return parseString();
    }
    ++mPos;
    return QVariant();
}

const QByteArray TorrentParser::parseString(){
    int lenlen = mData.indexOf(':', mPos) - mPos;
    if(lenlen <= 0){
        ++mPos;
        return QByteArray();
    }
    int len = mData.mid(mPos, lenlen).toInt();
    if(mPos + len > mData.size()){
        return QByteArray();
    }
    mPos = mPos + lenlen + 1;
    QByteArray retval = mData.mid(mPos, len);
    mPos += len;
    return retval;
}

int TorrentParser::parseInt(){
    if(mData.at(mPos) != 'i'){
        return 0;
    }
    ++mPos;
    int len = mData.indexOf('e', mPos) - mPos;
    if(len <= 0){
        return 0;
    }
    int retval = mData.mid(mPos, len).toInt();
    mPos = mPos + len + 1;
    return retval;
}

const QList<QVariant> TorrentParser::parseList(){
    if(mData.at(mPos) != 'l'){
        return QList<QVariant>();
    }
    ++mPos;
    QList<QVariant> retval;
    while(mPos < mData.size() && mData.at(mPos) != 'e'){
        retval.append(parseObject());
    }
    ++mPos;
    return retval;
}

const QHash<QString,QVariant> TorrentParser::parseDict(){
    QHash<QString,QVariant> retval;
    if(mData.at(mPos) != 'd'){
        return retval;
    }
    ++mPos;
    while(mPos < mData.size() && mData.at(mPos) != 'e'){
        QString key = parseString();
        QVariant value = parseObject();
        if(key.isEmpty() || value.isNull()){
            return retval;
        }
        retval.insert(key, value);
    }
    ++mPos;
    return retval;
}