1 /* $Id: filter_http_file.cpp,v 1.4 2006-03-16 10:40:59 adam Exp $
2 Copyright (c) 2005-2006, Index Data.
10 #include "package.hpp"
12 #include <boost/thread/mutex.hpp>
15 #include "filter_http_file.hpp"
23 #include <sys/types.h>
30 namespace mp = metaproxy_1;
31 namespace yf = mp::filter;
33 namespace metaproxy_1 {
35 struct HttpFile::Area {
36 std::string m_url_path_prefix;
37 std::string m_file_root;
39 class HttpFile::Mime {
43 Mime(std::string type);
47 friend class HttpFile;
49 typedef std::list<Area> AreaList;
50 typedef std::map<std::string,Mime> MimeMap;
54 void fetch_uri(mp::Session &session,
55 Z_HTTP_Request *req, mp::Package &package);
56 void fetch_file(mp::Session &session,
58 std::string &fname, mp::Package &package);
59 std::string get_mime_type(std::string &fname);
64 yf::HttpFile::Mime::Mime() {}
66 yf::HttpFile::Mime::Mime(std::string type) : m_type(type) {}
68 yf::HttpFile::HttpFile() : m_p(new Rep)
71 m_p->m_ext_to_map["html"] = Mime("text/html");
72 m_p->m_ext_to_map["htm"] = Mime("text/html");
73 m_p->m_ext_to_map["png"] = Mime("image/png");
74 m_p->m_ext_to_map["txt"] = Mime("text/plain");
75 m_p->m_ext_to_map["text"] = Mime("text/plain");
76 m_p->m_ext_to_map["asc"] = Mime("text/plain");
77 m_p->m_ext_to_map["xml"] = Mime("application/xml");
78 m_p->m_ext_to_map["xsl"] = Mime("application/xml");
82 a.m_url_path_prefix = "/etc";
84 m_p->m_area_list.push_back(a);
88 yf::HttpFile::~HttpFile()
92 std::string yf::HttpFile::Rep::get_mime_type(std::string &fname)
94 std::string file_part = fname;
95 std::string::size_type p = fname.find_last_of('/');
97 if (p != std::string::npos)
98 file_part = fname.substr(p+1);
100 p = file_part.find_last_of('.');
101 std::string content_type;
102 if (p != std::string::npos)
104 std::string ext = file_part.substr(p+1);
105 MimeMap::const_iterator it = m_ext_to_map.find(ext);
107 if (it != m_ext_to_map.end())
108 content_type = it->second.m_type;
110 if (content_type.length() == 0)
111 content_type = "application/octet-stream";
115 void yf::HttpFile::Rep::fetch_file(mp::Session &session,
117 std::string &fname, mp::Package &package)
121 FILE *f = fopen(fname.c_str(), "rb");
124 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
125 package.response() = gdu;
128 if (fseek(f, 0L, SEEK_END) == -1)
131 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
132 package.response() = gdu;
139 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
140 package.response() = gdu;
145 Z_GDU *gdu = o.create_HTTP_Response(session, req, 200);
147 Z_HTTP_Response *hres = gdu->u.HTTP_Response;
148 hres->content_len = sz;
149 hres->content_buf = (char*) odr_malloc(o, hres->content_len);
150 fread(hres->content_buf, 1, hres->content_len, f);
154 std::string content_type = get_mime_type(fname);
156 z_HTTP_header_add(o, &hres->headers,
157 "Content-Type", content_type.c_str());
158 package.response() = gdu;
161 void yf::HttpFile::Rep::fetch_uri(mp::Session &session,
162 Z_HTTP_Request *req, mp::Package &package)
165 std::string path = req->path;
167 // we don't consider ?, # yet..
170 std::string::size_type p = path.find("..");
171 if (p != std::string::npos)
176 AreaList::const_iterator it;
177 for (it = m_area_list.begin(); it != m_area_list.end(); it++)
179 std::string::size_type l = it->m_url_path_prefix.length();
181 if (path.compare(0, l, it->m_url_path_prefix) == 0)
183 std::string fname = it->m_file_root + path.substr(l);
184 std::cout << "fname = " << fname << "\n";
185 fetch_file(session, req, fname, package);
191 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
192 package.response() = gdu;
195 void yf::HttpFile::process(mp::Package &package) const
197 Z_GDU *gdu = package.request().get();
198 if (gdu && gdu->which == Z_GDU_HTTP_Request)
199 m_p->fetch_uri(package.session(), gdu->u.HTTP_Request, package);
204 void mp::filter::HttpFile::configure(const xmlNode * ptr)
206 for (ptr = ptr->children; ptr; ptr = ptr->next)
208 if (ptr->type != XML_ELEMENT_NODE)
210 if (!strcmp((const char *) ptr->name, "mimetypes"))
212 std::string fname = mp::xml::get_text(ptr);
218 throw mp::filter::FilterException
219 ("Can not open mime types file " + fname);
222 std::vector<std::string> args;
223 while (f.getline(args))
226 for (i = 1; i<args.size(); i++)
227 m_p->m_ext_to_map[args[i]] = args[0];
230 else if (!strcmp((const char *) ptr->name, "area"))
232 xmlNode *a_node = ptr->children;
234 for (; a_node; a_node = a_node->next)
236 if (a_node->type != XML_ELEMENT_NODE)
239 if (mp::xml::is_element_yp2(a_node, "documentroot"))
240 a.m_file_root = mp::xml::get_text(a_node);
241 else if (mp::xml::is_element_yp2(a_node, "prefix"))
242 a.m_url_path_prefix = mp::xml::get_text(a_node);
244 throw mp::filter::FilterException
246 + std::string((const char *) a_node->name)
250 if (a.m_file_root.length())
252 m_p->m_area_list.push_back(a);
257 throw mp::filter::FilterException
259 + std::string((const char *) ptr->name)
260 + " in virt_db filter");
265 static mp::filter::Base* filter_creator()
267 return new mp::filter::HttpFile;
271 struct metaproxy_1_filter_struct metaproxy_1_filter_http_file = {
282 * indent-tabs-mode: nil
283 * c-file-style: "stroustrup"
285 * vim: shiftwidth=4 tabstop=8 expandtab