1 /* $Id: filter_http_file.cpp,v 1.1 2006-01-19 21:44:26 adam Exp $
2 Copyright (c) 2005, 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 yf = yp2::filter;
34 struct HttpFile::Area {
35 std::string m_url_path_prefix;
36 std::string m_file_root;
38 class HttpFile::Mime {
42 Mime(std::string type);
46 friend class HttpFile;
48 typedef std::list<Area> AreaList;
49 typedef std::map<std::string,Mime> MimeMap;
53 void fetch_uri(yp2::Session &session,
54 Z_HTTP_Request *req, yp2::Package &package);
55 void fetch_file(yp2::Session &session,
57 std::string &fname, yp2::Package &package);
58 std::string get_mime_type(std::string &fname);
63 yf::HttpFile::Mime::Mime() {}
65 yf::HttpFile::Mime::Mime(std::string type) : m_type(type) {}
67 yf::HttpFile::HttpFile() : m_p(new Rep)
69 m_p->m_ext_to_map["html"] = Mime("text/html");
70 m_p->m_ext_to_map["htm"] = Mime("text/html");
71 m_p->m_ext_to_map["png"] = Mime("image/png");
72 m_p->m_ext_to_map["txt"] = Mime("text/plain");
73 m_p->m_ext_to_map["text"] = Mime("text/plain");
74 m_p->m_ext_to_map["asc"] = Mime("text/plain");
75 m_p->m_ext_to_map["xml"] = Mime("application/xml");
76 m_p->m_ext_to_map["xsl"] = Mime("application/xml");
79 a.m_url_path_prefix = "/etc";
81 m_p->m_area_list.push_back(a);
84 yf::HttpFile::~HttpFile()
88 std::string yf::HttpFile::Rep::get_mime_type(std::string &fname)
90 std::string file_part = fname;
91 std::string::size_type p = fname.find_last_of('/');
93 if (p != std::string::npos)
94 file_part = fname.substr(p+1);
96 p = file_part.find_last_of('.');
97 std::string content_type;
98 if (p != std::string::npos)
100 std::string ext = file_part.substr(p+1);
101 MimeMap::const_iterator it = m_ext_to_map.find(ext);
103 if (it != m_ext_to_map.end())
104 content_type = it->second.m_type;
106 if (content_type.length() == 0)
107 content_type = "application/octet-stream";
111 void yf::HttpFile::Rep::fetch_file(yp2::Session &session,
113 std::string &fname, yp2::Package &package)
118 if (stat(fname.c_str(), &sbuf))
120 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
121 package.response() = gdu;
124 if ((sbuf.st_mode & S_IFMT) != S_IFREG)
126 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
127 package.response() = gdu;
130 if (sbuf.st_size > (off_t) 1000000)
132 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
133 package.response() = gdu;
137 FILE *f = fopen(fname.c_str(), "rb");
140 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
141 package.response() = gdu;
144 Z_GDU *gdu = o.create_HTTP_Response(session, req, 200);
146 Z_HTTP_Response *hres = gdu->u.HTTP_Response;
147 hres->content_len = sbuf.st_size;
148 hres->content_buf = (char*) odr_malloc(o, hres->content_len);
149 fread(hres->content_buf, 1, hres->content_len, f);
153 std::string content_type = get_mime_type(fname);
155 z_HTTP_header_add(o, &hres->headers,
156 "Content-Type", content_type.c_str());
157 package.response() = gdu;
160 void yf::HttpFile::Rep::fetch_uri(yp2::Session &session,
161 Z_HTTP_Request *req, yp2::Package &package)
164 std::string path = req->path;
166 // we don't consider ?, # yet..
169 std::string::size_type p = path.find("..");
170 if (p != std::string::npos)
175 AreaList::const_iterator it;
176 for (it = m_area_list.begin(); it != m_area_list.end(); it++)
178 std::string::size_type l = it->m_url_path_prefix.length();
180 if (path.compare(0, l, it->m_url_path_prefix) == 0)
182 std::string fname = it->m_file_root + path;
183 fetch_file(session, req, fname, package);
189 Z_GDU *gdu = o.create_HTTP_Response(session, req, 404);
190 package.response() = gdu;
193 void yf::HttpFile::process(yp2::Package &package) const
195 Z_GDU *gdu = package.request().get();
196 if (gdu && gdu->which == Z_GDU_HTTP_Request)
197 m_p->fetch_uri(package.session(), gdu->u.HTTP_Request, package);
202 static yp2::filter::Base* filter_creator()
204 return new yp2::filter::HttpFile;
208 struct yp2_filter_struct yp2_filter_http_file = {
219 * indent-tabs-mode: nil
220 * c-file-style: "stroustrup"
222 * vim: shiftwidth=4 tabstop=8 expandtab