Switch to unified view

a/libupnpp/device/vdir.cxx b/libupnpp/device/vdir.cxx
1
/* Copyright (C) 2013 J.F.Dockes
1
/* Copyright (C) 2013 J.F.Dockes
2
 *     This program is free software; you can redistribute it and/or modify
2
 *   This program is free software; you can redistribute it and/or modify
3
 *     it under the terms of the GNU General Public License as published by
3
 *   it under the terms of the GNU General Public License as published by
4
 *     the Free Software Foundation; either version 2 of the License, or
4
 *   the Free Software Foundation; either version 2 of the License, or
5
 *     (at your option) any later version.
5
 *   (at your option) any later version.
6
 *
6
 *
7
 *     This program is distributed in the hope that it will be useful,
7
 *   This program is distributed in the hope that it will be useful,
8
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
8
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 *     GNU General Public License for more details.
10
 *   GNU General Public License for more details.
11
 *
11
 *
12
 *     You should have received a copy of the GNU General Public License
12
 *   You should have received a copy of the GNU General Public License
13
 *     along with this program; if not, write to the
13
 *   along with this program; if not, write to the
14
 *     Free Software Foundation, Inc.,
14
 *   Free Software Foundation, Inc.,
15
 *     59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16
 */
16
 */
17
#include "config.h"
17
#include "config.h"
18
18
19
#include <sys/types.h>
19
#include <sys/types.h>
20
#include <memory.h>
20
#include <memory.h>
...
...
25
#include "libupnpp/upnpp_p.hxx"
25
#include "libupnpp/upnpp_p.hxx"
26
#include "libupnpp/log.hxx"
26
#include "libupnpp/log.hxx"
27
#include "vdir.hxx"
27
#include "vdir.hxx"
28
28
29
using namespace std;
29
using namespace std;
30
using namespace UPnPP;
31
32
namespace UPnPProvider {
30
33
31
static VirtualDir *theDir;
34
static VirtualDir *theDir;
32
35
33
struct Handle {
36
struct Handle {
34
  Handle(VirtualDir::FileEnt *e)
37
    Handle(VirtualDir::FileEnt *e)
35
      : entry(e), offset(0)
38
        : entry(e), offset(0) {
36
      {}
39
    }
37
  VirtualDir::FileEnt *entry;  
40
    VirtualDir::FileEnt *entry;
38
  size_t offset;
41
    size_t offset;
39
};
42
};
40
43
41
static int vdclose(UpnpWebFileHandle fileHnd)
44
static int vdclose(UpnpWebFileHandle fileHnd)
42
{
45
{
43
  Handle *h = (Handle*)fileHnd;
46
    Handle *h = (Handle*)fileHnd;
44
  delete h;
47
    delete h;
45
  return 0;
48
    return 0;
46
}
49
}
47
50
48
static VirtualDir::FileEnt *vdgetentry(const char *pathname)
51
static VirtualDir::FileEnt *vdgetentry(const char *pathname)
49
{
52
{
50
  //LOGDEB("vdgetentry: [" << pathname << "]" << endl);
53
    //LOGDEB("vdgetentry: [" << pathname << "]" << endl);
51
  VirtualDir *thedir = VirtualDir::getVirtualDir();
54
    VirtualDir *thedir = VirtualDir::getVirtualDir();
52
  if (thedir == 0)
55
    if (thedir == 0) {
53
      return 0;
56
        return 0;
57
    }
54
58
55
  string dir = path_getfather(pathname);
59
    string dir = path_getfather(pathname);
56
  string fn = path_getsimple(pathname);
60
    string fn = path_getsimple(pathname);
57
61
58
  return theDir->getFile(dir, fn);
62
    return theDir->getFile(dir, fn);
59
}
63
}
60
64
61
static int vdgetinfo(const char *fn, struct File_Info* info )
65
static int vdgetinfo(const char *fn, struct File_Info* info)
62
{
66
{
63
  //LOGDEB("vdgetinfo: [" << fn << "] off_t " << sizeof(off_t) <<
67
    //LOGDEB("vdgetinfo: [" << fn << "] off_t " << sizeof(off_t) <<
64
  // " time_t " << sizeof(time_t) << endl);
68
    // " time_t " << sizeof(time_t) << endl);
65
  VirtualDir::FileEnt *entry = vdgetentry(fn);
69
    VirtualDir::FileEnt *entry = vdgetentry(fn);
66
  if (entry == 0) {
70
    if (entry == 0) {
67
      LOGERR("vdgetinfo: no entry for " << fn << endl);
71
        LOGERR("vdgetinfo: no entry for " << fn << endl);
68
      return -1;
72
        return -1;
69
  }
73
    }
70
74
71
  info->file_length = entry->content.size();
75
    info->file_length = entry->content.size();
72
  info->last_modified = entry->mtime;
76
    info->last_modified = entry->mtime;
73
  info->is_directory = 0;
77
    info->is_directory = 0;
74
  info->is_readable = 1;
78
    info->is_readable = 1;
75
  info->content_type = ixmlCloneDOMString(entry->mimetype.c_str());
79
    info->content_type = ixmlCloneDOMString(entry->mimetype.c_str());
76
80
77
  return 0;
81
    return 0;
78
}
82
}
79
83
80
static UpnpWebFileHandle vdopen(const char* fn, enum UpnpOpenFileMode Mode)
84
static UpnpWebFileHandle vdopen(const char* fn, enum UpnpOpenFileMode Mode)
81
{
85
{
82
  //LOGDEB("vdopen: " << fn << endl);
86
    //LOGDEB("vdopen: " << fn << endl);
83
  VirtualDir::FileEnt *entry = vdgetentry(fn);
87
    VirtualDir::FileEnt *entry = vdgetentry(fn);
84
  if (entry == 0) {
88
    if (entry == 0) {
85
      LOGERR("vdopen: no entry for " << fn << endl);
89
        LOGERR("vdopen: no entry for " << fn << endl);
86
      return NULL;
90
        return NULL;
87
  }
91
    }
88
  return new Handle(entry);
92
    return new Handle(entry);
89
}
93
}
90
94
91
static int vdread(UpnpWebFileHandle fileHnd, char* buf, size_t buflen)
95
static int vdread(UpnpWebFileHandle fileHnd, char* buf, size_t buflen)
92
{
96
{
93
  // LOGDEB("vdread: " << endl);
97
    // LOGDEB("vdread: " << endl);
94
  if (buflen == 0)
98
    if (buflen == 0) {
95
      return 0;
99
        return 0;
100
    }
96
  Handle *h = (Handle *)fileHnd;
101
    Handle *h = (Handle *)fileHnd;
97
  if (h->offset >= h->entry->content.size())
102
    if (h->offset >= h->entry->content.size()) {
98
      return 0;
103
        return 0;
104
    }
99
  size_t toread = buflen > h->entry->content.size() - h->offset ?
105
    size_t toread = buflen > h->entry->content.size() - h->offset ?
100
      h->entry->content.size() - h->offset : buflen;
106
                    h->entry->content.size() - h->offset : buflen;
101
  memcpy(buf, h->entry->content.c_str() + h->offset, toread);
107
    memcpy(buf, h->entry->content.c_str() + h->offset, toread);
102
  h->offset += toread;
108
    h->offset += toread;
103
  return toread;
109
    return toread;
104
}
110
}
105
111
106
static int vdseek(UpnpWebFileHandle fileHnd, off_t offset, int origin)
112
static int vdseek(UpnpWebFileHandle fileHnd, off_t offset, int origin)
107
{
113
{
108
  // LOGDEB("vdseek: " << endl);
114
    // LOGDEB("vdseek: " << endl);
109
  Handle *h = (Handle *)fileHnd;
115
    Handle *h = (Handle *)fileHnd;
110
  if (origin == 0)
116
    if (origin == 0) {
111
      h->offset = offset;
117
        h->offset = offset;
112
  else if (origin == 1)
118
    } else if (origin == 1) {
113
      h->offset += offset;
119
        h->offset += offset;
114
  else if (origin == 2)
120
    } else if (origin == 2) {
115
      h->offset = h->entry->content.size() + offset;
121
        h->offset = h->entry->content.size() + offset;
116
  else 
122
    } else {
117
      return -1;
123
        return -1;
124
    }
118
  return offset;
125
    return offset;
119
}
126
}
120
127
121
static int vdwrite(UpnpWebFileHandle fileHnd, char* buf, size_t buflen)
128
static int vdwrite(UpnpWebFileHandle fileHnd, char* buf, size_t buflen)
122
{
129
{
123
  LOGERR("vdwrite" << endl);
130
    LOGERR("vdwrite" << endl);
124
  return -1;
131
    return -1;
125
}
132
}
126
133
127
static struct UpnpVirtualDirCallbacks myvdcalls = {
134
static struct UpnpVirtualDirCallbacks myvdcalls = {
128
  vdgetinfo, vdopen, vdread, vdwrite, vdseek, vdclose
135
    vdgetinfo, vdopen, vdread, vdwrite, vdseek, vdclose
129
};
136
};
130
137
131
VirtualDir *VirtualDir::getVirtualDir()
138
VirtualDir *VirtualDir::getVirtualDir()
132
{
139
{
133
  if (theDir == 0) {
140
    if (theDir == 0) {
134
      theDir = new VirtualDir();
141
        theDir = new VirtualDir();
135
      if (UpnpSetVirtualDirCallbacks(&myvdcalls) != UPNP_E_SUCCESS) {
142
        if (UpnpSetVirtualDirCallbacks(&myvdcalls) != UPNP_E_SUCCESS) {
136
          LOGERR("SetVirtualDirCallbacks failed" << endl);
143
            LOGERR("SetVirtualDirCallbacks failed" << endl);
137
          delete theDir;
144
            delete theDir;
138
          theDir = 0;
145
            theDir = 0;
139
          return 0;
146
            return 0;
140
      }
147
        }
141
  } 
148
    }
142
  return theDir;
149
    return theDir;
143
}
150
}
144
151
145
bool VirtualDir::addFile(const string& _path, const string& name, 
152
bool VirtualDir::addFile(const string& _path, const string& name,
146
                       const string& content, const string& mimetype)
153
                         const string& content, const string& mimetype)
147
{
154
{
148
  string path(_path);
155
    string path(_path);
149
  if (path.empty() || path[path.size()-1] != '/') {
156
    if (path.empty() || path[path.size() - 1] != '/') {
150
      path += '/';
157
        path += '/';
151
  }
158
    }
152
  if (m_dirs.find(path) == m_dirs.end()) {
159
    if (m_dirs.find(path) == m_dirs.end()) {
153
      m_dirs[path] = unordered_map<string, VirtualDir::FileEnt>();
160
        m_dirs[path] = unordered_map<string, VirtualDir::FileEnt>();
154
      UpnpAddVirtualDir(path.c_str());
161
        UpnpAddVirtualDir(path.c_str());
155
  }
162
    }
156
  VirtualDir::FileEnt entry;
163
    VirtualDir::FileEnt entry;
157
  entry.mtime = time(0);
164
    entry.mtime = time(0);
158
  entry.mimetype = mimetype;
165
    entry.mimetype = mimetype;
159
  entry.content = content;
166
    entry.content = content;
160
  m_dirs[path][name] = entry;
167
    m_dirs[path][name] = entry;
161
  // LOGDEB("VirtualDir::addFile: added entry for dir " << 
168
    // LOGDEB("VirtualDir::addFile: added entry for dir " <<
162
  // path << " name " << name << endl);
169
    // path << " name " << name << endl);
163
  return true;
170
    return true;
164
}
171
}
165
172
166
VirtualDir::FileEnt *VirtualDir::getFile(const string& _path, 
173
VirtualDir::FileEnt *VirtualDir::getFile(const string& _path,
167
                                       const string& name)
174
        const string& name)
168
{
175
{
169
  string path(_path);
176
    string path(_path);
170
  if (path.empty() || path[path.size()-1] != '/') {
177
    if (path.empty() || path[path.size() - 1] != '/') {
171
      path += '/';
178
        path += '/';
172
  }
179
    }
173
180
174
  // LOGDEB("VirtualDir::getFile: path " << path << " name " << name << endl);
181
    // LOGDEB("VirtualDir::getFile: path " << path << " name " << name << endl);
175
182
176
  unordered_map<string, unordered_map<string,VirtualDir::FileEnt> >::iterator dir = 
183
    unordered_map<string, unordered_map<string, VirtualDir::FileEnt> >::iterator dir =
177
      m_dirs.find(path);
184
        m_dirs.find(path);
178
  if (dir == m_dirs.end()) {
185
    if (dir == m_dirs.end()) {
179
      LOGERR("VirtualDir::getFile: no dir: " << path << endl);
186
        LOGERR("VirtualDir::getFile: no dir: " << path << endl);
180
      return 0;
187
        return 0;
181
  }
188
    }
182
  unordered_map<string, FileEnt>::iterator f = dir->second.find(name);
189
    unordered_map<string, FileEnt>::iterator f = dir->second.find(name);
183
  if (f == dir->second.end()) {
190
    if (f == dir->second.end()) {
184
      LOGERR("VirtualDir::getFile: no file: " << path << endl);
191
        LOGERR("VirtualDir::getFile: no file: " << path << endl);
185
      return 0;
192
        return 0;
186
  }
193
    }
187
194
188
  return &(f->second);
195
    return &(f->second);
189
}
196
}
190
197
191
/* Local Variables: */
198
}
192
/* mode: c++ */
193
/* c-basic-offset: 4 */
194
/* tab-width: 4 */
195
/* indent-tabs-mode: t */
196
/* End: */