35 #include <boost/algorithm/string.hpp>
36 #include <boost/bind.hpp>
37 #include <boost/date_time.hpp>
38 #include <boost/lexical_cast.hpp>
39 #include <boost/process.hpp>
40 #include <boost/regex.hpp>
41 #include <boost/thread.hpp>
42 #include <boost/tokenizer.hpp>
45 using namespace boost;
46 using namespace boost::filesystem;
47 using boost::algorithm::to_lower_copy;
48 namespace proc = boost::process;
71 ruta_ = arrel_servidor_ / peticio.ruta().ruta();
72 assert( exists(ruta_) && is_regular_file(ruta_) );
76 if (!exists(ruta_) || !is_regular_file(ruta_)) {
84 void ProgramaCGI::envia(asio::ip::tcp::socket & socket)
const throw (std::runtime_error) {
85 std::array<char, MIDA_BUFFER> buf;
92 if (peticio().te_cos()) {
93 ctx.streams[proc::stdin_id] = proc::behavior::pipe();
96 ctx.streams[proc::stdin_id] = proc::behavior::null();
98 ctx.streams[proc::stdout_id] = proc::behavior::pipe();
99 ctx.streams[proc::stderr_id] = proc::behavior::pipe();
105 ctx.env = proc::environment();
106 if (peticio().te_cos()) {
107 ctx.env[
"CONTENT_LENGTH"] = lexical_cast<
string>(peticio().cos().lock()->mida());
110 ctx.env[
"CONTENT_LENGTH"] =
"0";
112 ctx.env[
"HTTP_COOKIE"] = peticio().capsalera(
"Cookie");
113 ctx.env[
"CONTENT_TYPE"] = peticio().capsalera(
"Content-Type");
114 ctx.env[
"DOCUMENT_ROOT"] = arrel_servidor_.string();
115 ctx.env[
"HTTP_REFERER"] = peticio().capsalera(
"Referer");
116 ctx.env[
"HTTP_USER_AGENT"] = peticio().capsalera(
"User-Agent");
118 ctx.env[
"PATH_INFO"] =
"";
119 ctx.env[
"PATH_TRANSLATED"] =
"";
120 ctx.env[
"QUERY_STRING"] = peticio().ruta().query();
121 ctx.env[
"REMOTE_ADDR"] = socket.remote_endpoint().address().to_string();
122 ctx.env[
"REMOTE_HOST"] = socket.remote_endpoint().address().to_string();
124 ctx.env[
"SCRIPT_NAME"] = peticio().ruta().ruta();
125 ctx.env[
"SERVER_NAME"] = socket.local_endpoint().address().to_string();
126 ctx.env[
"SERVER_PORT"] = lexical_cast<
string>(socket.local_endpoint().port());
137 proc::child cgi = proc::create_child(ruta_.string(), vector<string>(), ctx);
138 proc::pistream is(cgi.get_handle(proc::stdout_id));
139 proc::pistream is_err(cgi.get_handle(proc::stderr_id));
140 if (peticio().te_cos()) {
142 proc::postream os(cgi.get_handle(proc::stdin_id));
143 const string & cos = peticio().cos().lock()->contingut();
144 os.write(cos.c_str(), cos.size());
152 const regex re_final_caps(
"^[\r\n]*$");
153 while (!is.eof() && socket.is_open()) {
155 getline(is, linia,
'\n');
156 if (linia.empty() || regex_match(linia, re_final_caps)) {
160 capss << linia <<
'\n';
162 capss.write(
"\r\n", 2);
164 this->envia_literal(socket, capss.str());
168 while (!is.eof() && socket.is_open()) {
169 is.read(buf.data(), buf.size());
170 const streamsize bytes = is.gcount();
171 cerr <<
"Enviant: " << string(buf.data(), bytes) << endl;
172 this->envia(socket,
string(buf.data(), bytes));
174 int ret = cgi.wait();
177 <<
"Error d'execució de CGI " << ruta_ <<
": " << is_err.rdbuf() <<
commit;
182 const bool cal_transformar = (0 != transformacio_.get());
183 while (ifs.good() && socket.is_open()) {
184 ifs.read(buffer.data(), buffer.size());
185 const streamsize bytes = ifs.gcount();
187 string bloc(buffer.data(), bytes);
188 if (cal_transformar) {
189 bloc = transformacio_->transforma(bloc);
191 this->envia(socket, bloc);
197 if (cal_transformar && socket.is_open()) {
198 this->envia(socket, transformacio_->finalitza());