Switch to unified view

a b/src/dumpXML.cpp
1
// This libupnpp sample program downloads all the XML description data
2
// from a given devices and writes it to a target directory.
3
4
#include <fcntl.h>
5
#include <sys/stat.h>
6
#include <sys/types.h>
7
8
#include <string>
9
#include <iostream>
10
#include <unordered_map>
11
12
#include "libupnpp/upnpplib.hxx"
13
#include "libupnpp/log.hxx"
14
#include "libupnpp/control/description.hxx"
15
#include "libupnpp/control/discovery.hxx"
16
17
using namespace std;
18
using namespace UPnPClient;
19
using namespace UPnPP;
20
21
static void neutchars(const string& str, string& out, const string& chars)
22
{
23
    string::size_type startPos, pos;
24
    out.clear();
25
    for (pos = 0;;) {
26
        // Skip initial chars, break if this eats all.
27
        if ((startPos = str.find_first_not_of(chars, pos)) == string::npos) {
28
            break;
29
        }
30
        // Find next delimiter or end of string (end of token)
31
        pos = str.find_first_of(chars, startPos);
32
        // Add token to the output. Note: token cant be empty here
33
        if (pos == string::npos) {
34
            out += str.substr(startPos);
35
        } else {
36
            out += str.substr(startPos, pos - startPos) + "_";
37
        }
38
    }
39
}
40
41
static bool make_file(const string& nm, const string& content)
42
{
43
    int fd = open(nm.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0600);
44
    if (fd < 0) {
45
        cerr << "Could not create/open " << nm << endl;
46
        perror("open");
47
        return false;
48
    }
49
    if (write(fd, content.c_str(), content.size()) != content.size()) {
50
        close(fd);
51
        cerr << "Could not write to  " << nm << endl;
52
        perror("write");
53
        return false;
54
    }
55
    close(fd);
56
    return true;
57
}
58
59
int main(int argc, char *argv[])
60
{
61
    argv++;argc--;
62
    if (argc != 2) {
63
        cerr << "Usage: dumpXML <devNameOrUid> <targetdir>\n";
64
        cerr << "<targetdir> will be created if it does not exist\n";
65
        return 1;
66
    }
67
    string devname(*argv++); 
68
    argc--;
69
    string dirname(*argv++);
70
    argc--;
71
    
72
    // Initialize libupnpp logging
73
    Logger::getTheLog("")->setLogLevel(Logger::LLDEB);
74
75
    // Get a handle to the main lib object. You don't really need to
76
    // do this actually. We just do it to check that the lib
77
    // initialized ok, but there are other possible uses, see the doc
78
    // in the include file.
79
    LibUPnP *mylib = LibUPnP::getLibUPnP();
80
    if (!mylib) {
81
        cerr << "Can't get LibUPnP" << endl;
82
        return 1;
83
    }
84
    if (!mylib->ok()) {
85
        cerr << "Lib init failed: " <<
86
            mylib->errAsString("main", mylib->getInitError()) << endl;
87
        return 1;
88
    }
89
90
    // Get a handle to the device directory. You can call this
91
    // multiple times, only the first call does something, any further
92
    // call will just return the pointer to the singleton.
93
    UPnPDeviceDirectory *superdir = UPnPDeviceDirectory::getTheDir();
94
    if (superdir == 0) {
95
        cerr << "Cant access device directory\n";
96
        return 1;
97
    }
98
99
    if (access(dirname.c_str(), X_OK|W_OK)) {
100
        if (mkdir(dirname.c_str(), 0755)) {
101
            cerr << "Could not create " << dirname << endl;
102
            perror("mkdir");
103
            return 1;
104
        }
105
    }
106
107
    string deviceXML;
108
    unordered_map<string, string> srvsXML;
109
    if (!superdir->getDescriptionDocuments(devname, deviceXML, srvsXML)) {
110
        cerr << "Could not retrieve description documents\n";
111
        return 1;
112
    }
113
114
    string path, fn, fn1;
115
    fn = devname + "-description.xml";
116
    neutchars(fn, fn1, "/ \n\r\t");
117
    path = dirname + "/" + fn1;
118
    if (!make_file(path, deviceXML)) {
119
        return 1;
120
    }
121
    for (auto entry : srvsXML) {
122
        fn = entry.first + ".xml";
123
        neutchars(fn, fn1, "/ \n\r\t");
124
        path = dirname + "/" + fn1;
125
        if (!make_file(path, entry.second)) {
126
            return 1;
127
        }
128
    }        
129
    return 0;
130
}