--- a
+++ b/libupnpp/vdir.cxx
@@ -0,0 +1,186 @@
+/* Copyright (C) 2013 J.F.Dockes
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/types.h>
+#include <memory.h>
+#include <iostream>
+
+#include "upnpplib.hxx"
+#include "upnpp_p.hxx"
+#include "vdir.hxx"
+
+using namespace std;
+
+static VirtualDir *theDir;
+
+struct Handle {
+ Handle(VirtualDir::FileEnt *e)
+ : entry(e), offset(0)
+ {}
+ VirtualDir::FileEnt *entry;
+ size_t offset;
+};
+
+static int vdclose(UpnpWebFileHandle fileHnd)
+{
+ Handle *h = (Handle*)fileHnd;
+ delete h;
+ return 0;
+}
+
+static VirtualDir::FileEnt *vdgetentry(const char *pathname)
+{
+ VirtualDir *thedir = VirtualDir::getVirtualDir();
+ if (thedir == 0)
+ return 0;
+
+ string dir = path_getfather(pathname);
+ string fn = path_getsimple(pathname);
+
+ return theDir->getFile(dir, fn);
+}
+
+static int vdgetinfo(const char *fn, struct File_Info* info )
+{
+ cerr << "vdgetinfo: " << fn << endl;
+ VirtualDir::FileEnt *entry = vdgetentry(fn);
+ if (entry == 0) {
+ cerr << "vdgetinfo: no entry" << endl;
+ return -1;
+ }
+ info->file_length = entry->content.size();
+ info->last_modified = entry->mtime;
+ info->is_directory = 0;
+ info->is_readable = 1;
+ info->content_type = ixmlCloneDOMString(entry->mimetype.c_str());
+ return 0;
+}
+static UpnpWebFileHandle vdopen(const char* fn, enum UpnpOpenFileMode Mode)
+{
+ cerr << "vdopen: " << fn << endl;
+ VirtualDir::FileEnt *entry = vdgetentry(fn);
+ if (entry == 0) {
+ cerr << "vdopen: no entry" << endl;
+ return NULL;
+ }
+ return new Handle(entry);
+}
+
+static int vdread(UpnpWebFileHandle fileHnd, char* buf, size_t buflen)
+{
+ cerr << "vdread: " << endl;
+ if (buflen == 0)
+ return 0;
+ Handle *h = (Handle *)fileHnd;
+ if (h->offset >= h->entry->content.size())
+ return 0;
+ size_t toread = buflen > h->entry->content.size() - h->offset ?
+ h->entry->content.size() - h->offset : buflen;
+ memcpy(buf, h->entry->content.c_str() + h->offset, toread);
+ h->offset += toread;
+ return toread;
+}
+
+static int vdseek(UpnpWebFileHandle fileHnd, long offset, int origin)
+{
+ cerr << "vdseek: " << endl;
+ Handle *h = (Handle *)fileHnd;
+ if (origin == 0)
+ h->offset = offset;
+ else if (origin == 1)
+ h->offset += offset;
+ else if (origin == 2)
+ h->offset = h->entry->content.size() + offset;
+ else
+ return -1;
+ return offset;
+}
+static int vdwrite(UpnpWebFileHandle fileHnd, char* buf, size_t buflen)
+{
+ cerr << "vdwrite" << endl;
+ return -1;
+}
+
+static struct UpnpVirtualDirCallbacks myvdcalls = {
+ vdgetinfo, vdopen, vdread, vdwrite, vdseek, vdclose
+};
+
+VirtualDir *VirtualDir::getVirtualDir()
+{
+ if (theDir == 0) {
+ theDir = new VirtualDir();
+ if (UpnpSetVirtualDirCallbacks(&myvdcalls) != UPNP_E_SUCCESS) {
+ cerr<< "SetVirtualDirCallbacks failed" << endl;
+ delete theDir;
+ theDir = 0;
+ return 0;
+ }
+ }
+ return theDir;
+}
+
+bool VirtualDir::addFile(const string& _path, const string& name,
+ const string& content, const string& mimetype)
+{
+ string path(_path);
+ if (path.empty() || path[path.size()-1] != '/') {
+ path += '/';
+ }
+ if (m_dirs.find(path) == m_dirs.end()) {
+ m_dirs[path] = map<string, VirtualDir::FileEnt>();
+ UpnpAddVirtualDir(path.c_str());
+ }
+ VirtualDir::FileEnt entry;
+ entry.mtime = time(0);
+ entry.mimetype = mimetype;
+ entry.content = content;
+ m_dirs[path][name] = entry;
+ cerr << "VirtualDir::addFile: added entry for dir " <<
+ path << " name " << name << endl;
+}
+
+VirtualDir::FileEnt *VirtualDir::getFile(const string& _path,
+ const string& name)
+{
+ string path(_path);
+ if (path.empty() || path[path.size()-1] != '/') {
+ path += '/';
+ }
+
+ cerr << "VirtualDir::getFile: path " << path << " name " << name << endl;
+
+ map<string, map<string,VirtualDir::FileEnt> >::iterator dir =
+ m_dirs.find(path);
+ if (dir == m_dirs.end()) {
+ cerr << "VirtualDir::getFile: no dir" << endl;
+ return 0;
+ }
+ map<string, FileEnt>::iterator f = dir->second.find(name);
+ if (f == dir->second.end()) {
+ cerr << "VirtualDir::getFile: no file" << endl;
+ return 0;
+ }
+
+ return &(f->second);
+}
+
+/* Local Variables: */
+/* mode: c++ */
+/* c-basic-offset: 4 */
+/* tab-width: 4 */
+/* indent-tabs-mode: t */
+/* End: */