20 #include <metaproxy/filter.hpp>
21 #include <metaproxy/package.hpp>
22 #include <metaproxy/util.hpp>
29 #include <boost/thread/mutex.hpp>
36 #include <sys/types.h>
44 namespace yf = mp::filter;
59 Mime(std::string type);
66 typedef std::map<std::string,Mime>
MimeMap;
71 Z_HTTP_Request *req, mp::Package &package);
74 std::string &fname, mp::Package &package,
75 bool raw,
bool passthru);
81 yf::HttpFile::Area::Area() : m_raw(false), m_passthru(false)
85 yf::HttpFile::Mime::Mime() {}
87 yf::HttpFile::Mime::Mime(std::string type) : m_type(type) {}
89 yf::HttpFile::HttpFile() :
m_p(new
Rep)
92 m_p->m_ext_to_map[
"html"] =
Mime(
"text/html");
93 m_p->m_ext_to_map[
"htm"] =
Mime(
"text/html");
94 m_p->m_ext_to_map[
"png"] =
Mime(
"image/png");
95 m_p->m_ext_to_map[
"txt"] =
Mime(
"text/plain");
96 m_p->m_ext_to_map[
"text"] =
Mime(
"text/plain");
97 m_p->m_ext_to_map[
"asc"] =
Mime(
"text/plain");
98 m_p->m_ext_to_map[
"xml"] =
Mime(
"application/xml");
99 m_p->m_ext_to_map[
"xsl"] =
Mime(
"application/xml");
105 m_p->m_area_list.push_back(a);
109 yf::HttpFile::~HttpFile()
113 std::string yf::HttpFile::Rep::get_mime_type(std::string &fname)
115 std::string file_part = fname;
116 std::string::size_type p = fname.find_last_of(
'/');
118 if (p != std::string::npos)
119 file_part = fname.substr(p+1);
121 p = file_part.find_last_of(
'.');
122 std::string content_type;
123 if (p != std::string::npos)
125 std::string ext = file_part.substr(p+1);
126 MimeMap::const_iterator it = m_ext_to_map.find(ext);
128 if (it != m_ext_to_map.end())
129 content_type = it->second.m_type;
131 if (content_type.length() == 0)
132 content_type =
"application/octet-stream";
136 void yf::HttpFile::Rep::fetch_file(mp::Session &session,
138 std::string &fname, mp::Package &package,
139 bool raw,
bool passthru)
141 mp::odr o(ODR_ENCODE);
143 if (strcmp(req->method,
"GET"))
151 Z_GDU *gdu = o.create_HTTP_Response(session, req, 405);
152 package.response() = gdu;
158 if (stat(fname.c_str(), &st) == -1 || (st.st_mode & S_IFMT) != S_IFREG)
166 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
167 package.response() = gdu;
172 FILE *f = fopen(fname.c_str(),
"rb");
175 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
176 package.response() = gdu;
179 if (fseek(f, 0L, SEEK_END) == -1)
182 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
183 package.response() = gdu;
190 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
191 package.response() = gdu;
195 char *fbuf = (
char*) odr_malloc(o, sz);
198 if (fread(fbuf, sz, 1, f) != 1)
200 Z_GDU *gdu = o.create_HTTP_Response(session, req, 500);
201 package.response() = gdu;
209 mp::odr decode(ODR_DECODE);
212 odr_setbuf(decode, (
char *) fbuf, sz, 0);
213 int r = z_GDU(decode, &gdu, 0, 0);
216 gdu = o.create_HTTP_Response(session, req, 500);
221 gdu = o.create_HTTP_Response(session, req, 200);
222 Z_HTTP_Response *hres = gdu->u.HTTP_Response;
223 hres->content_len = sz;
224 hres->content_buf = fbuf;
225 std::string content_type = get_mime_type(fname);
226 z_HTTP_header_add(o, &hres->headers,
227 "Content-Type", content_type.c_str());
229 package.response() = gdu;
232 void yf::HttpFile::Rep::fetch_uri(mp::Session &session,
233 Z_HTTP_Request *req, mp::Package &package)
236 std::string::size_type p;
237 std::string path = req->path;
240 if (p != std::string::npos)
241 path = path.erase(p);
244 if (p != std::string::npos)
245 path = path.erase(p);
247 path = mp::util::uri_decode(path);
251 if (p != std::string::npos)
256 AreaList::const_iterator it;
257 for (it = m_area_list.begin(); it != m_area_list.end(); it++)
259 std::string::size_type l = it->m_url_path_prefix.length();
261 if (path.compare(0, l, it->m_url_path_prefix) == 0)
263 std::string fname = it->m_file_root + path.substr(l);
264 package.log(
"http_file", YLOG_LOG,
"%s", fname.c_str());
265 fetch_file(session, req, fname, package, it->m_raw,
274 void yf::HttpFile::process(mp::Package &package)
const
276 Z_GDU *gdu = package.request().get();
277 if (gdu && gdu->which == Z_GDU_HTTP_Request)
278 m_p->fetch_uri(package.session(), gdu->u.HTTP_Request, package);
283 void mp::filter::HttpFile::configure(
const xmlNode * ptr,
bool test_only,
286 for (ptr = ptr->children; ptr; ptr = ptr->next)
288 if (ptr->type != XML_ELEMENT_NODE)
290 if (!strcmp((
const char *) ptr->name,
"mimetypes"))
292 std::string fname = mp::xml::get_text(ptr);
298 throw mp::filter::FilterException
299 (
"Can not open mime types file " + fname);
302 std::vector<std::string> args;
303 while (f.getline(args))
306 for (i = 1; i<args.size(); i++)
307 m_p->m_ext_to_map[args[i]] = args[0];
310 else if (!strcmp((
const char *) ptr->name,
"area"))
312 xmlNode *a_node = ptr->children;
315 for (; a_node; a_node = a_node->next)
317 if (a_node->type != XML_ELEMENT_NODE)
320 if (mp::xml::is_element_mp(a_node,
"documentroot"))
322 else if (mp::xml::is_element_mp(a_node,
"prefix"))
324 else if (mp::xml::is_element_mp(a_node,
"raw"))
325 a.
m_raw = mp::xml::get_bool(a_node,
false);
326 else if (mp::xml::is_element_mp(a_node,
"passthru"))
327 a.
m_passthru = mp::xml::get_bool(a_node,
false);
329 throw mp::filter::FilterException
331 + std::string((
const char *) a_node->name)
337 m_p->m_area_list.push_back(a);
342 throw mp::filter::FilterException
344 + std::string((
const char *) ptr->name)
345 +
" in virt_db filter");
352 return new mp::filter::HttpFile;
static mp::filter::Base * filter_creator()
struct metaproxy_1_filter_struct metaproxy_1_filter_http_file