ffead.server.doc
ScriptHandler.cpp
1 /*
2  Copyright 2009-2012, Sumeet Chhetri
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 /*
17  * ScriptHandler.cpp
18  *
19  * Created on: Jun 17, 2012
20  * Author: Sumeet
21  */
22 
23 #include "ScriptHandler.h"
24 
25 Logger ScriptHandler::logger;
26 
27 ScriptHandler::ScriptHandler() {
28  logger = Logger::getLogger("ScriptHandler");
29 }
30 
31 ScriptHandler::~ScriptHandler() {
32  // TODO Auto-generated destructor stub
33 }
34 
35 string ScriptHandler::chdirExecute(string exe, string tmpf, bool retErrs)
36 {
37  if(chdir(tmpf.c_str())==0)
38  return execute(exe, retErrs);
39  return "";
40 }
41 
42 string ScriptHandler::execute(string exe, bool retErrs)
43 {
44  string data;
45  if(retErrs)
46  {
47  exe += " 2>&1";
48  }
49  FILE *pp;
50  pp = popen(exe.c_str(), "r");
51  if (pp != NULL) {
52  while (1) {
53  char *line;
54  char buf[1000];
55  line = fgets(buf, sizeof buf, pp);
56  if (line == NULL) break;
57  data.append(line);
58  //if (line[0] == 'd') printf("%s", line); /* line includes '\n' */
59  }
60  pclose(pp);
61  }
62  return data;
63 }
64 
65 int ScriptHandler::popenRWE(int *rwepipe, const char *exe, const char *const argv[],string tmpf)
66 {
67  int in[2];
68  int out[2];
69  int err[2];
70  int pid;
71  int rc;
72 
73  rc = pipe(in);
74  if (rc<0)
75  goto error_in;
76 
77  rc = pipe(out);
78  if (rc<0)
79  goto error_out;
80 
81  rc = pipe(err);
82  if (rc<0)
83  goto error_err;
84 
85  pid = fork();
86  if (pid > 0) { // parent
87  close(in[0]);
88  close(out[1]);
89  close(err[1]);
90  rwepipe[0] = in[1];
91  rwepipe[1] = out[0];
92  rwepipe[2] = err[0];
93  return pid;
94  } else if (pid == 0) { // child
95  close(in[1]);
96  close(out[0]);
97  close(err[0]);
98  close(0);
99  dup(in[0]);
100  close(1);
101  dup(out[1]);
102  close(2);
103  dup(err[1]);
104  //logger << tmpf << endl;
105  chdir(tmpf.c_str());
106  execvp(exe, (char**)argv);
107  exit(1);
108  } else
109  goto error_fork;
110 
111  return pid;
112 
113 error_fork:
114  close(err[0]);
115  close(err[1]);
116 error_err:
117  close(out[0]);
118  close(out[1]);
119 error_out:
120  close(in[0]);
121  close(in[1]);
122 error_in:
123  return -1;
124 }
125 
126 int ScriptHandler::popenRWEN(int *rwepipe, const char *exe, const char** argv)
127 {
128  int in[2];
129  int out[2];
130  int err[2];
131  int pid;
132  int rc;
133 
134  rc = pipe(in);
135  if (rc<0)
136  goto error_in;
137 
138  rc = pipe(out);
139  if (rc<0)
140  goto error_out;
141 
142  rc = pipe(err);
143  if (rc<0)
144  goto error_err;
145  pid = fork();
146  if (pid > 0) { // parent
147  close(in[0]);
148  close(out[1]);
149  close(err[1]);
150  rwepipe[0] = in[1];
151  rwepipe[1] = out[0];
152  rwepipe[2] = err[0];
153  return pid;
154  } else if (pid == 0) { // child
155  //logger << pid << endl;
156  close(in[1]);
157  close(out[0]);
158  close(err[0]);
159  close(0);
160  dup(in[0]);
161  close(1);
162  dup(out[1]);
163  close(2);
164  dup(err[1]);
165  execvp(exe, (char**)argv);
166  exit(1);
167  } else
168  goto error_fork;
169 
170  return pid;
171 
172 error_fork:
173  close(err[0]);
174  close(err[1]);
175 error_err:
176  close(out[0]);
177  close(out[1]);
178 error_out:
179  close(in[0]);
180  close(in[1]);
181 error_in:
182  return -1;
183 }
184 
185 int ScriptHandler::pcloseRWE(int pid, int *rwepipe)
186 {
187  int status;
188  close(rwepipe[0]);
189  close(rwepipe[1]);
190  close(rwepipe[2]);
191  waitpid(pid, &status, 0);
192  return status;
193 }
194 
195 bool ScriptHandler::handle(HttpRequest* req, HttpResponse& res, map<string, string> handoffs, void* dlib,
196  string ext, map<string, string> props)
197 {
198  bool skipit = false;
199  string referer = req->getReferer();
200  if(referer.find("http://")!=string::npos)
201  {
202  string appl = referer.substr(referer.find("http://")+7);
203  appl = appl.substr(referer.find("/")+1);
204  if(appl.find(req->getCntxt_name())==0 && handoffs.find(req->getCntxt_name())!=handoffs.end())
205  {
206  if(appl==req->getCntxt_name()+"/"+handoffs[req->getCntxt_name()])
207  {
208 
209  }
210  }
211  }
212  if(ext==".php")
213  {
214  skipit = true;
215  //int pipe[3];
216  //int pid;
217  string def;
218  string tmpf = "/temp/";
219  string filen;
220  if(handoffs.find(req->getCntxt_name())!=handoffs.end())
221  {
222  def = handoffs[req->getCntxt_name()];
223  tmpf = "/";
224  }
225  string phpcnts = req->toPHPVariablesString(def);
226  //logger << phpcnts << endl;
227  filen = CastUtil::lexical_cast<string>(Timer::getCurrentTime()) + ".php";
228  tmpf = req->getCntxt_root() + tmpf;
229 
230  AfcUtil::writeTofile(tmpf+filen, phpcnts, true);
231 
232  string command = "php " + filen;
233  string content = chdirExecute(command, tmpf, Constants::SCRIPT_EXEC_SHOW_ERRS);
234  if((content.length()==0))
235  {
236  res.setHTTPResponseStatus(HTTPResponseStatus::NotFound);
237  //res.setContent_len("0");
238  }
239  else
240  {
241  res.setHTTPResponseStatus(HTTPResponseStatus::Ok);
242  res.setContent_type(props[".html"]);
243  res.setContent_str(content);
244  //res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
245  }
246  }
247  else if(ext==".pl")
248  {
249  skipit = true;
250  //int pipe[3];
251  //int pid;
252  string def;
253  string tmpf = "/temp/";
254  string filen;
255  if(handoffs.find(req->getCntxt_name())!=handoffs.end())
256  {
257  def = handoffs[req->getCntxt_name()];
258  tmpf = "/";
259  }
260  filen = CastUtil::lexical_cast<string>(Timer::getCurrentTime()) + ".pl";
261  tmpf = req->getCntxt_root() + tmpf;
262  string phpcnts = req->toPerlVariablesString();
263  //logger << tmpf << endl;
264  string plfile = req->getUrl();
265  ifstream infile(plfile.c_str());
266  string xml;
267  if(infile.is_open())
268  {
269  while(getline(infile, xml))
270  {
271  phpcnts.append(xml+"\n");
272  }
273  }
274  infile.close();
275  AfcUtil::writeTofile(tmpf+filen, phpcnts, true);
276 
277  string command = "perl " + filen;
278  string content = chdirExecute(command, tmpf, Constants::SCRIPT_EXEC_SHOW_ERRS);
279  if((content.length()==0))
280  {
281  res.setHTTPResponseStatus(HTTPResponseStatus::NotFound);
282  //res.setContent_len("0");
283  }
284  else
285  {
286  res.setHTTPResponseStatus(HTTPResponseStatus::Ok);
287  res.setContent_type(props[".html"]);
288  res.setContent_str(content);
289  //res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
290  }
291  }
292  else if(ext==".rb")
293  {
294  skipit = true;
295  //int pipe[3];
296  //int pid;
297  string def;
298  string tmpf = "/temp/";
299  string filen;
300  if(handoffs.find(req->getCntxt_name())!=handoffs.end())
301  {
302  def = handoffs[req->getCntxt_name()];
303  tmpf = "/";
304  }
305  string phpcnts = req->toRubyVariablesString();
306  //logger << phpcnts << endl;
307  filen = CastUtil::lexical_cast<string>(Timer::getCurrentTime()) + ".rb";
308  tmpf = req->getCntxt_root() + tmpf;
309 
310  AfcUtil::writeTofile(tmpf+filen, phpcnts, true);
311 
312  string command = "ruby " + filen;
313  string content = chdirExecute(command, tmpf, Constants::SCRIPT_EXEC_SHOW_ERRS);
314  if((content.length()==0))
315  {
316  res.setHTTPResponseStatus(HTTPResponseStatus::NotFound);
317  //res.setContent_len("0");
318  }
319  else
320  {
321  res.setHTTPResponseStatus(HTTPResponseStatus::Ok);
322  res.setContent_type(props[".html"]);
323  res.setContent_str(content);
324  //res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
325  }
326  }
327  else if(ext==".py")
328  {
329  skipit = true;
330  //int pipe[3];
331  //int pid;
332  string def;
333  string tmpf = "/temp/";
334  string filen;
335  if(handoffs.find(req->getCntxt_name())!=handoffs.end())
336  {
337  def = handoffs[req->getCntxt_name()];
338  tmpf = "/";
339  }
340  filen = CastUtil::lexical_cast<string>(Timer::getCurrentTime()) + ".py";
341  tmpf = req->getCntxt_root() + tmpf;
342  string phpcnts = req->toPythonVariablesString();
343  string plfile = req->getUrl();
344  ifstream infile(plfile.c_str());
345  string xml;
346  if(infile.is_open())
347  {
348  while(getline(infile, xml))
349  {
350  phpcnts.append(xml+"\n");
351  }
352  }
353  infile.close();
354  AfcUtil::writeTofile(tmpf+filen, phpcnts, true);
355 
356  string command = "python " + filen;
357  string content = chdirExecute(command, tmpf, Constants::SCRIPT_EXEC_SHOW_ERRS);
358  if((content.length()==0))
359  {
360  res.setHTTPResponseStatus(HTTPResponseStatus::NotFound);
361  //res.setContent_len("0");
362  }
363  else
364  {
365  res.setHTTPResponseStatus(HTTPResponseStatus::Ok);
366  res.setContent_type(props[".html"]);
367  res.setContent_str(content);
368  //res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
369  }
370  }
371  else if(ext==".lua")
372  {
373  skipit = true;
374  //int pipe[3];
375  //int pid;
376  string def;
377  string tmpf = "/temp/";
378  string filen;
379  if(handoffs.find(req->getCntxt_name())!=handoffs.end())
380  {
381  def = handoffs[req->getCntxt_name()];
382  tmpf = "/";
383  }
384  string phpcnts = req->toLuaVariablesString();
385  //logger << phpcnts << endl;
386  filen = CastUtil::lexical_cast<string>(Timer::getCurrentTime()) + ".lua";
387  tmpf = req->getCntxt_root() + tmpf;
388 
389  AfcUtil::writeTofile(tmpf+filen, phpcnts, true);
390 
391  string command = "lua " + filen;
392  string content = chdirExecute(command, tmpf, Constants::SCRIPT_EXEC_SHOW_ERRS);
393  if((content.length()==0))
394  {
395  res.setHTTPResponseStatus(HTTPResponseStatus::NotFound);
396  //res.setContent_len("0");
397  }
398  else
399  {
400  res.setHTTPResponseStatus(HTTPResponseStatus::Ok);
401  res.setContent_type(props[".html"]);
402  res.setContent_str(content);
403  //res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
404  }
405  }
406  else if(ext==".njs")
407  {
408  skipit = true;
409  //int pipe[3];
410  //int pid;
411  string def;
412  string tmpf = "/temp/";
413  string filen;
414  if(handoffs.find(req->getCntxt_name())!=handoffs.end())
415  {
416  def = handoffs[req->getCntxt_name()];
417  tmpf = "/";
418  }
419  string phpcnts = req->toNodejsVariablesString();
420  //logger << phpcnts << endl;
421  filen = CastUtil::lexical_cast<string>(Timer::getCurrentTime()) + ".njs";
422  tmpf = req->getCntxt_root() + tmpf;
423 
424  AfcUtil::writeTofile(tmpf+filen, phpcnts, true);
425 
426  string command = "node " + filen;
427  string content = chdirExecute(command, tmpf, Constants::SCRIPT_EXEC_SHOW_ERRS);
428  if((content.length()==0))
429  {
430  res.setHTTPResponseStatus(HTTPResponseStatus::NotFound);
431  //res.setContent_len("0");
432  }
433  else
434  {
435  res.setHTTPResponseStatus(HTTPResponseStatus::Ok);
436  res.setContent_type(props[".html"]);
437  res.setContent_str(content);
438  //res.setContent_len(CastUtil::lexical_cast<string>(content.length()));
439  }
440  }
441  return skipit;
442 }