Branch: Tag:

1996-11-11

1996-11-11 23:31:54 by Per Hedbor <ph@opera.com>

Ny version... HATA CVS ibland

Rev: .cvsignore:1.1.1.1
Rev: BUGS:1.1.1.1
Rev: CHANGES:1.1.1.1
Rev: COPYING:1.1.1.1
Rev: INSTALLING:1.1.1.1
Rev: Makefile.in:1.1.1.1
Rev: README:1.1.1.1
Rev: TODO:1.1.1.1
Rev: configure.in:1.1.1.1
Rev: extern/.cvsignore:1.1.1.1
Rev: extern/Makefile.in:1.1.1.1
Rev: extern/README:1.1.1.1
Rev: extern/cgi.c:1.1.1.1
Rev: extern/configure.in:1.1.1.1
Rev: extern/fast_cgi/LICENSE.TERMS:1.1.1.1
Rev: extern/fast_cgi/Makefile.in:1.1.1.1
Rev: extern/fast_cgi/README:1.1.1.1
Rev: extern/fast_cgi/acconfig.h:1.1.1.1
Rev: extern/fast_cgi/cgi-fcgi/Makefile.in:1.1.1.1
Rev: extern/fast_cgi/cgi-fcgi/cgi-fcgi.c:1.1.1.1
Rev: extern/fast_cgi/configure.in:1.1.1.1
Rev: extern/fast_cgi/include/fastcgi.h:1.1.1.1
Rev: extern/fast_cgi/include/fcgi_stdio.h:1.1.1.1
Rev: extern/fast_cgi/include/fcgiapp.h:1.1.1.1
Rev: extern/fast_cgi/include/fcgiappmisc.h:1.1.1.1
Rev: extern/fast_cgi/include/fcgimisc.h:1.1.1.1
Rev: extern/fast_cgi/libfcgi/Makefile.in:1.1.1.1
Rev: extern/fast_cgi/libfcgi/fcgi_stdio.c:1.1.1.1
Rev: extern/fast_cgi/libfcgi/fcgiapp.c:1.1.1.1
Rev: extern/fast_cgi/libfcgi/strerror.c:1.1.1.1
Rev: extern/roxen_hostname.c:1.1.1.1
Rev: extern/shuffle.c:1.1.1.1
Rev: extern/ssl.c:1.1.1.1
Rev: install-sh:1.1.1.1
Rev: mkdir:1.1.1.1
Rev: pike/.cvsignore:1.1.1.1
Rev: pike/Makefile.in:1.1.1.1
Rev: pike/README:1.1.1.1
Rev: pike/ROXEN_PIKE_BASE:1.1.1.1
Rev: pike/configure.in:1.1.1.1
Rev: server/base_server/cache.pike:1.1.1.1
Rev: server/base_server/config/builders.pike:1.1.1.1
Rev: server/base_server/config/describers.pike:1.1.1.1
Rev: server/base_server/config/low_describers.pike:1.1.1.1
Rev: server/base_server/config/savers.pike:1.1.1.1
Rev: server/base_server/configuration.pike:1.1.1.1
Rev: server/base_server/db.pike:1.1.1.1
Rev: server/base_server/disk_cache.pike:1.1.1.1
Rev: server/base_server/dummy_hosts.pike:1.1.1.1
Rev: server/base_server/hosts.pike:1.1.1.1
Rev: server/base_server/html.pike:1.1.1.1
Rev: server/base_server/http.pike:1.1.1.1
Rev: server/base_server/language.pike:1.1.1.1
Rev: server/base_server/lock.pike:1.1.1.1
Rev: server/base_server/mainconfig.pike:1.1.1.1
Rev: server/base_server/module.pike:1.1.1.1
Rev: server/base_server/module_support.pike:1.1.1.1
Rev: server/base_server/newdecode.pike:1.1.1.1
Rev: server/base_server/persistent.pike:1.1.1.1
Rev: server/base_server/proxyauth.pike:1.1.1.1
Rev: server/base_server/read_config.pike:1.1.1.1
Rev: server/base_server/roxen.pike:1.1.1.1
Rev: server/base_server/roxenlib.pike:1.1.1.1
Rev: server/base_server/roxenloader.pike:1.1.1.1
Rev: server/base_server/socket.pike:1.1.1.1
Rev: server/base_server/spinnerlib.pike:1.1.1.1
Rev: server/base_server/struct/ftp_gateway_request.pike:1.1.1.1
Rev: server/base_server/struct/node.pike:1.1.1.1
Rev: server/bin/.cvsignore:1.1.1.1
Rev: server/bin/garbagecollector.pike:1.1.1.1
Rev: server/bin/install.pike:1.1.1.1
Rev: server/configvar:1.1.1.1
Rev: server/etc/config.html:1.1.1.1
Rev: server/etc/extensions:1.1.1.1
Rev: server/etc/include/array.h:1.1.1.1
Rev: server/etc/include/array.pre.pike:1.1.1.1
Rev: server/etc/include/config.h:1.1.1.1
Rev: server/etc/include/confignode.h:1.1.1.1
Rev: server/etc/include/fifo.h:1.1.1.1
Rev: server/etc/include/fifo.pre.pike:1.1.1.1
Rev: server/etc/include/getopt.h:1.1.1.1
Rev: server/etc/include/getopt.pre.pike:1.1.1.1
Rev: server/etc/include/module.h:1.1.1.1
Rev: server/etc/include/process.h:1.1.1.1
Rev: server/etc/include/process.pre.pike:1.1.1.1
Rev: server/etc/include/roxen.h:1.1.1.1
Rev: server/etc/include/simulate.h:1.1.1.1
Rev: server/etc/include/simulate.pre.pike:1.1.1.1
Rev: server/etc/include/stat.h:1.1.1.1
Rev: server/etc/include/stdio.h:1.1.1.1
Rev: server/etc/include/stdio.pre.pike:1.1.1.1
Rev: server/etc/include/string.h:1.1.1.1
Rev: server/etc/include/string.pre.pike:1.1.1.1
Rev: server/etc/include/syslog.h:1.1.1.1
Rev: server/etc/include/variables.h:1.1.1.1
Rev: server/etc/newconfig.html:1.1.1.1
Rev: server/etc/restart.html:1.1.1.1
Rev: server/etc/roxen_master.pike:1.1.1.1
Rev: server/etc/shutdown.html:1.1.1.1
Rev: server/etc/supports:1.1.1.1
Rev: server/etc/welcome.html:1.1.1.1
Rev: server/install:1.1.1.1
Rev: server/languages/catala.pike:1.1.1.1
Rev: server/languages/dutch.pike:1.1.1.1
Rev: server/languages/english.pike:1.1.1.1
Rev: server/languages/finnish.pike:1.1.1.1
Rev: server/languages/french.pike:1.1.1.1
Rev: server/languages/german.pike:1.1.1.1
Rev: server/languages/japanese.pike:1.1.1.1
Rev: server/languages/norwegian.pike:1.1.1.1
Rev: server/languages/spanish.pike:1.1.1.1
Rev: server/languages/swedish.pike:1.1.1.1
Rev: server/mkdir:1.1.1.1
Rev: server/modules/cgi.pike:1.1.1.1
Rev: server/modules/client_logger.pike:1.1.1.1
Rev: server/modules/connect.pike:1.1.1.1
Rev: server/modules/contenttypes.pike:1.1.1.1
Rev: server/modules/directories.pike:1.1.1.1
Rev: server/modules/fastdir.pike:1.1.1.1
Rev: server/modules/fcgi.pike:1.1.1.1
Rev: server/modules/filesystem.pike:1.1.1.1
Rev: server/modules/ftpgateway.pike:1.1.1.1
Rev: server/modules/gopher.pike:1.1.1.1
Rev: server/modules/header.pike:1.1.1.1
Rev: server/modules/home_logger.pike:1.1.1.1
Rev: server/modules/hostredirect.pike:1.1.1.1
Rev: server/modules/htaccess.pike:1.1.1.1
Rev: server/modules/htmlparse.pike:1.1.1.1
Rev: server/modules/indexfiles.pike:1.1.1.1
Rev: server/modules/indirect_href.pike:1.1.1.1
Rev: server/modules/ismap.pike:1.1.1.1
Rev: server/modules/language.pike:1.1.1.1
Rev: server/modules/lpcscript.pike:1.1.1.1
Rev: server/modules/lpctag.pike:1.1.1.1
Rev: server/modules/nologging.pike:1.1.1.1
Rev: server/modules/proxy.pike:1.1.1.1
Rev: server/modules/redirect.pike:1.1.1.1
Rev: server/modules/relay.pike:1.1.1.1
Rev: server/modules/secure_fs.pike:1.1.1.1
Rev: server/modules/tablist.pike:1.1.1.1
Rev: server/modules/userdb.pike:1.1.1.1
Rev: server/modules/userfs.pike:1.1.1.1
Rev: server/modules/variable.pike:1.1.1.1
Rev: server/modules/wais.pike:1.1.1.1
Rev: server/more_modules/bofh.pike:1.1.1.1
Rev: server/more_modules/clock.pike:1.1.1.1
Rev: server/more_modules/configure.pike:1.1.1.1
Rev: server/more_modules/lysator.pike:1.1.1.1
Rev: server/more_modules/tablify.pike:1.1.1.1
Rev: server/protocols/ftp.pike:1.1.1.1
Rev: server/protocols/gopher.pike:1.1.1.1
Rev: server/protocols/http.pike:1.1.1.1
Rev: server/protocols/ssl.pike:1.1.1.1
Rev: server/roxen-images/back.gif:1.1.1.1
Rev: server/roxen-images/background.jpg:1.1.1.1
Rev: server/roxen-images/changed.gif:1.1.1.1
Rev: server/roxen-images/delconf.gif:1.1.1.1
Rev: server/roxen-images/delmod.gif:1.1.1.1
Rev: server/roxen-images/delmodcop.gif:1.1.1.1
Rev: server/roxen-images/dir/binary.gif:1.1.1.1
Rev: server/roxen-images/dir/image.gif:1.1.1.1
Rev: server/roxen-images/dir/menu.gif:1.1.1.1
Rev: server/roxen-images/dir/sound.gif:1.1.1.1
Rev: server/roxen-images/dir/text.gif:1.1.1.1
Rev: server/roxen-images/dir/unknown.gif:1.1.1.1
Rev: server/roxen-images/fold.gif:1.1.1.1
Rev: server/roxen-images/fold2.gif:1.1.1.1
Rev: server/roxen-images/foldall.gif:1.1.1.1
Rev: server/roxen-images/infovav.gif:1.1.1.1
Rev: server/roxen-images/left.gif:1.1.1.1
Rev: server/roxen-images/newconf.gif:1.1.1.1
Rev: server/roxen-images/newmod.gif:1.1.1.1
Rev: server/roxen-images/off.gif:1.1.1.1
Rev: server/roxen-images/on.gif:1.1.1.1
Rev: server/roxen-images/power.gif:1.1.1.1
Rev: server/roxen-images/power_anim.gif:1.1.1.1
Rev: server/roxen-images/refresh.gif:1.1.1.1
Rev: server/roxen-images/restart.gif:1.1.1.1
Rev: server/roxen-images/right.gif:1.1.1.1
Rev: server/roxen-images/roxen.gif:1.1.1.1
Rev: server/roxen-images/save.gif:1.1.1.1
Rev: server/roxen-images/shutdown.gif:1.1.1.1
Rev: server/roxen-images/tablists/1.gif:1.1.1.1
Rev: server/roxen-images/tablists/10.gif:1.1.1.1
Rev: server/roxen-images/tablists/11.gif:1.1.1.1
Rev: server/roxen-images/tablists/12.gif:1.1.1.1
Rev: server/roxen-images/tablists/13.gif:1.1.1.1
Rev: server/roxen-images/tablists/14.gif:1.1.1.1
Rev: server/roxen-images/tablists/15.gif:1.1.1.1
Rev: server/roxen-images/tablists/16.gif:1.1.1.1
Rev: server/roxen-images/tablists/2.gif:1.1.1.1
Rev: server/roxen-images/tablists/3.gif:1.1.1.1
Rev: server/roxen-images/tablists/4.gif:1.1.1.1
Rev: server/roxen-images/tablists/5.gif:1.1.1.1
Rev: server/roxen-images/tablists/6.gif:1.1.1.1
Rev: server/roxen-images/tablists/7.gif:1.1.1.1
Rev: server/roxen-images/tablists/8.gif:1.1.1.1
Rev: server/roxen-images/tablists/9.gif:1.1.1.1
Rev: server/roxen-images/top.gif:1.1.1.1
Rev: server/roxen-images/unfold.gif:1.1.1.1
Rev: server/roxen-images/unfold2.gif:1.1.1.1
Rev: server/roxen-images/unmod.gif:1.1.1.1
Rev: server/roxen-images/up.gif:1.1.1.1
Rev: server/roxen-images/zap.gif:1.1.1.1
Rev: server/start:1.1.1.1
Rev: server/unfinishedmodules/deepthought.pike:1.1.1.1
Rev: server/unfinishedmodules/extended_logger.pike:1.1.1.1
Rev: server/unfinishedmodules/fastcgi.pike:1.1.1.1
Rev: server/unfinishedmodules/hedbor.pike:1.1.1.1
Rev: server/unfinishedmodules/httpc.lpc.gz:1.1.1.1
Rev: server/unfinishedmodules/javascript.pike:1.1.1.1
Rev: server/unfinishedmodules/mirror.lpc.gz:1.1.1.1
Rev: server/unfinishedmodules/mountserver.pike:1.1.1.1
Rev: server/unfinishedmodules/tree.pike:1.1.1.1
Rev: server/unfinishedmodules/whois++.pike:1.1.1.1
Rev: tools/Makefile:1.1.1.1
Rev: tools/accessed.lpc:1.1.1.1
Rev: tools/backlog-bumper:1.1.1.1
Rev: tools/htpasswd.c:1.1.1.1
Rev: tools/init.d_roxen:1.1.1.1
Rev: tools/xdumpfont/Makefile:1.1.1.1
Rev: tools/xdumpfont/README:1.1.1.1
Rev: tools/xdumpfont/banner.c:1.1.1.1
Rev: tools/xdumpfont/fontdemo.c:1.1.1.1
Rev: tools/xdumpfont/makefonts.lpc:1.1.1.1
Rev: tools/xdumpfont/readfont.c:1.1.1.1
Rev: tools/xdumpfont/readfont.h:1.1.1.1
Rev: tools/xdumpfont/xdumpfont.c:1.1.1.1

1: + #include <config.h> + inherit "roxenlib"; + int first;    -  + function decode = roxen->decode; +  + #define SPEED_MAX +  +  + function _time=time; + private string cache; + object conf; +  +  + #ifdef REQUEST_DEBUG + int kept_alive; + #endif +  + #include <roxen.h> + #include <module.h> +  + #undef QUERY + #define QUERY(X) roxen->variables->X[VAR_VALUE] +  + int time; + string raw_url; + int do_not_disconnect = 0; +  + mapping (string:string) variables = ([ ]); + mapping (string:mixed) misc = ([ ]); +  + multiset (string) prestate = (< >); + multiset (string) config = (< >); + multiset (string) supports = (< >); +  + string remoteaddr, host; +  + array (string) client = ({ "Unknown" }); + array (string) referer = ({ }); + multiset (string) pragma = (< >); +  + mapping (string:string) cookies = ([ ]); +  + mixed file; +  + object my_fd; /* The client. */ + object pipe; +  + // string range; + string prot; + string method; +  + string realfile, virtfile; + string rest_query=""; + string raw; + string query; + string not_query; + string extra_extension = ""; // special hack for the language module + string data; + array (int|string) auth; + string rawauth, realauth; + string since; +  + // Parse a HTTP/1.1 HTTP/1.0 or 0.9 request, including form data and + // state variables. Return 0 if more is expected, 1 if done, and -1 + // if fatal error. +  + void end(string|void); +  + private void setup_pipe(int noend) + { +  if(!my_fd) return end(); +  if(!pipe) pipe=clone((program)"/precompiled/pipe"); +  if(!noend) pipe->set_done_callback(end); + #ifdef REQUEST_DEBUG +  perror("REQUEST: Pipe setup.\n"); + #endif + // pipe->output(my_fd); + } +  + void send(string|object what, int|void noend) + { +  if(!what) return; +  if(!pipe) setup_pipe(noend); +  + #ifdef REQUEST_DEBUG +  perror("REQUEST: Sending some data\n"); + #endif +  if(stringp(what)) pipe->write(what); +  else pipe->input(what); + } +  + string scan_for_query( string f ) + { +  if(sscanf(f,"%s?%s", f, query) == 2) +  { +  string v, a, b; +  +  foreach(query / "&", v) +  if(sscanf(v, "%s=%s", a, b) == 2) +  { +  a = http_decode_string(replace(a, "+", " ")); +  b = http_decode_string(replace(b, "+", " ")); +  +  if(variables[ a ]) +  variables[ a ] += "\0" + b; +  else +  variables[ a ] = b; +  } else +  if(strlen( rest_query )) +  rest_query += "&" + http_decode_string( v ); +  else +  rest_query = http_decode_string( v ); +  } +  rest_query=replace(rest_query, "+", "\000"); /* IDIOTIC STUPID STANDARD */ +  return f; + } +  +  + private int really_set_config(array mod_config) + { +  string url, m; +  string base; +  base = roxen->query("MyWorldLocation"); +  base = base[..strlen(base)]; +  my_fd->set_blocking(); +  roxen->current_configuration = conf; +  +  if(supports->cookies) +  { + #ifdef REQUEST_DEBUG +  perror("Setting cookie..\n"); + #endif +  if(mod_config) +  foreach(mod_config, m) +  if(m[-1]=='-') +  config[m[1..]]=0; +  else +  config[m]=1; +  +  if(sscanf(replace(raw_url,({"%3c","%3e","%3C","%3E" }), +  ({"<",">","<",">"})),"/<%*s>/%s",url)!=2) +  url = "/"; +  +  url = base + url; +  +  my_fd->write(prot+" 302 Config in cookie!\r\n" +  "Set-Cookie: " +  +http_roxen_config_cookie(indices(config)*",")+"\r\n" +  "Location: "+url+"\r\n" +  "Content-Type: text/html\r\n" +  "Content-Length: 0\r\n\r\n"); +  } else { + #ifdef REQUEST_DEBUG +  perror("Setting {config} for user without Cookie support..\n"); + #endif +  if(mod_config) +  foreach(mod_config, m) +  if(m[-1]=='-') +  prestate[m[1..]]=0; +  else +  prestate[m]=1; +  +  sscanf(replace(raw_url, ({ "%3c", "%3e", "%3C", "%3E" }), +  ({ "<", ">", "<", ">" })), "/<%*s>/%s", url); +  sscanf(replace(url, ({ "%28", "%29" }), ({ "(", ")" })),"/(%*s)/%s", url); +  +  my_fd->write(prot+" 302 Config In Prestate!\r\n" +  +"\r\nLocation: "+roxen->query("MyWorldLocation")+ +  add_pre_state(url, aggregate_list(@prestate))+"\r\n" +  +"Content-Type: text/html\r\n" +  +"Content-Length: 0\r\n\r\n"); +  } +  return -2; + } +  + private int parse_got(string s) + { +  multiset (string) sup; +  array mod_config; +  mixed f, line; +  string a, b, linename, contents, real_raw; +  int config_in_url; +  +  real_raw = s; +  s -= "\r"; // I just hate all thoose CR LF. +  +  if(strlen(s) < 3) +  return 0; // Not finished, I promise. +  +  if(!(s[-1] == '\n' && search(s, "HTTP/") == -1)) +  if(search(s, "\n\n") == -1) +  return 0; +  raw = s; +  +  s = replace(s, "\t", " "); +  +  if(sscanf(s,"%s %s %s\n%s", method, f, prot, s) < 4) +  { +  if(sscanf(s,"%s %s\n", method, f) < 2) +  f=""; +  s=""; +  prot = "HTTP/0.9"; +  } +  +  if(!method) +  method = "GET"; +  method = upper_case(method); +  if(method == "PING") +  { +  my_fd->write("PONG\n"); +  return -2; +  } +  +  raw_url = f; +  time = _time(1); +  if(!remoteaddr) +  { +  catch(remoteaddr = ((my_fd->query_address()||"")/" ")[0]); +  if(!remoteaddr) this_object()->end(); +  } +  + #if 0 +  sscanf(f,"%s;%s", f, range); + #endif +  +  f = scan_for_query( f ); +  f = http_decode_string( f ); +  +  if (sscanf(f, "/<%s>%s", a, f)) +  { +  config_in_url = 1; +  mod_config = (a/","); +  } +  +  if (sscanf(f, "/(%s)%s", a, f) && strlen(a)) +  prestate = aggregate_multiset(@(a/","-({""}))); +  +  not_query = f; +  +  if(strlen(s)) +  { +  sscanf(real_raw, "%s\r\n\r\n%s", s, data); +  +  /* We do _not_ want to parse the 'GET ...\n' line. /Per */ +  sscanf(s, "%*s\n%s", s); +  +  s = replace(s, "\n\t", ", ") - "\r"; +  // Handle rfc822 continuation lines and strip \r +  +  foreach(s/"\n" - ({ "" }), line) +  { +  linename=contents=0; +  sscanf(line, "%s:%s", linename, contents); +  if(linename&&contents) +  { +  linename=lower_case(linename); +  sscanf(contents, "%*[\t ]%s", contents); +  +  if(strlen(contents)) +  { +  switch (linename) +  { +  case "content-length": +  misc->len = (int)(contents-" "); +  +  if(method == "POST") +  { +  int l = (int)(contents-" ")-1; /* Length - 1 */ +  if(strlen(data) <= l) // \r are included. +  return 0; +  data = data[..l]; +  string v; +  if(l < 200000) +  { +  foreach(replace(data-"\n", "+", " ")/"&", v) +  if(sscanf(v, "%s=%s", a, b) == 2) +  { +  a = http_decode_string( a ); +  b = http_decode_string( b ); +  +  if(variables[ a ]) +  variables[ a ] += "\0" + b; +  else +  variables[ a ] = b; +  } +  } +  } +  break; +  +  case "authorization": +  string *y; +  rawauth = contents; +  y = contents /= " "; +  if(sizeof(y) < 2) +  break; +  y[1] = decode(y[1]); +  realauth=y[1]; +  if(conf && conf->auth_module) +  y = conf->auth_module->auth( y, this_object() ); +  auth=y; +  break; +  +  case "proxy-authorization": +  string *y; +  y = contents /= " "; +  if(sizeof(y) < 2) +  break; +  y[1] = decode(y[1]); +  if(conf && conf->auth_module) +  y = conf->auth_module->auth( y, this_object() ); +  misc->proxyauth=y; +  break; +  +  case "pragma": +  pragma|=aggregate_multiset(@explode(replace(contents, " ", ""), ",")); +  break; +  +  case "user-agent": +  sscanf(contents, "%s via", contents); +  client = explode(contents, " ") - ({ "" }); +  break; +  +  case "referer": +  referer = contents/" "; +  break; +  +  case "extension": + #ifdef DEBUG +  perror("Client extension: "+contents+"\n"); + #endif +  linename="extension"; +  +  case "connection": +  contents = lower_case(contents); +  +  case "content-type": +  misc[linename] = lower_case(contents); +  break; +  +  case "accept": +  case "accept-encoding": +  case "accept-language": +  case "session-id": +  case "message-id": +  case "from": +  if(misc[linename]) +  misc[linename] += explode(contents-" ", ","); +  else +  misc[linename] = explode(contents-" ", ","); +  break; +  +  case "cookie": /* This header is quite heavily parsed */ +  string c; +  misc->cookies = contents; +  foreach(contents/";", c) +  { +  string name, value; +  while(c[0]==' ') c=c[1..]; +  if(sscanf(c, "%s=%s", name, value) == 2) +  { +  value=http_decode_string(value); +  name=http_decode_string(name); +  cookies[ name ]=value; +  if(name == "RoxenConfig" && strlen(value)) +  { +  array tmpconfig = value/"," + ({ }); +  string m; +  +  if(mod_config && sizeof(mod_config)) +  foreach(mod_config, m) +  if(!strlen(m)) +  { continue; } /* Bug in parser force { and } */ +  else if(m[0]=='-') +  tmpconfig -= ({ m[1..] }); +  else +  tmpconfig |= ({ m }); +  mod_config = 0; +  config = aggregate_multiset(@tmpconfig); +  } +  } +  } +  break; +  +  case "host": +  case "proxy-connection": +  case "security-scheme": +  misc[linename] = contents; +  break; +  +  case "proxy-by": +  case "proxy-maintainer": +  case "proxy-software": + #ifdef MORE_HEADERS +  if(misc[linename]) +  misc[linename] += explode(contents-" ", ","); +  else +  misc[linename] = explode(contents-" ", ","); + #endif +  case "mime-version": +  break; +  +  case "if-modified-since": +  if(QUERY(IfModified)) +  since=contents; +  break; +  +  case "forwarded": +  misc["forwarded"]=contents; +  break; + #ifdef DEBUG +  default: +  /* x-* headers are experimental. */ +  if(linename[0] != 'x') +  perror("Unknown header: `"+linename+"' -> `"+contents+"'\n"); + #endif +  } +  } +  } +  } +  } +  supports = roxen->find_supports(lower_case(client*" ")); +  +  int tmp1,tmp2; +  +  if(0 && (tmp1 = search(lower_case(raw), "proxy-authentification:")) != -1 && +  (tmp2 = search(lower_case(raw[tmp1..]), "\n") != -1)) +  { +  perror(raw); +  raw = raw[..tmp1-1] + raw[tmp2..]; +  perror(raw); +  } +  +  if(config_in_url) +  return really_set_config( mod_config ); +  +  if(!supports->cookies) +  config = prestate; +  else +  if(conf +  &&!cookies->RoxenUserID && strlen(not_query) +  &&not_query[0]=='/' +  && QUERY(set_cookie)) +  { + #ifdef DEBUG +  perror("Setting unique ID.\n"); + #endif +  misc->moreheads = ([ "Set-Cookie":http_roxen_id_cookie(), ]); +  } + #ifdef DEBUG + #if DEBUG_LEVEL > 30 +  else +  perror("Unique ID: "+cookies->RoxenUserID+"\n"); + #endif + #endif +  not_query = simplify_path(not_query); +  return 1; // Done. + } +  + void disconnect() + { +  if(do_not_disconnect) +  { + #ifdef REQUEST_DEBUG +  perror("REQUEST: Not disconnecting...\n"); + #endif +  return; +  } + #ifdef REQUEST_DEBUG +  perror("REQUEST: Disconnecting...\n"); + #endif +  if(mappingp(file) && objectp(file->file)) +  destruct(file->file); +  if(objectp(pipe) && pipe != previous_object()) +  destruct(pipe); +  --roxen->num_connections; + #ifdef REQUEST_DEBUG +  perror(sprintf("Request: Current number of open connections: %d\n", +  roxen->num_connections)); + #endif +  my_fd = 0; +  destruct(this_object()); + } +  + void no_more_keep_connection_alive(mapping foo) + { +  if(!pipe || !objectp(my_fd)) end(); + } +  +  + void end(string|void s) + { + #ifdef REQUEST_DEBUG +  perror("REQUEST: End...\n"); + #endif +  remove_call_out(no_more_keep_connection_alive); +  if(objectp(my_fd)) +  { +  if(s) +  my_fd->write(s); +  destruct(my_fd); +  } +  disconnect(); + } +  + static void timeout(mapping foo) + { +  end(prot+" 408 Timeout\n"); + } +  +  + void got_data(mixed fooid, string s); +  + void keep_connection_alive() + { +  object fd, p; +  string c; +  fd = my_fd; +  c = cache; +  my_fd = fd; +  cache = c; +  pipe=0; +  my_fd->set_nonblocking(got_data, lambda() { }, end); +  if(cache && strlen(cache)) +  got_data(1, ""); +  else +  call_out(no_more_keep_connection_alive, 100); + } +  +  + mapping internal_error(array err) + { +  if(QUERY(show_internals)) +  file = http_low_answer(500, "<h1>Error: Internal server error.</h1>" +  + "<font size=+1><pre>"+ describe_backtrace(err) +  + "</pre></font>"); +  else +  file = http_low_answer(500, "<h1>Error: The server failed to " +  "fulfill your query.</h1>"); +  +  +  report_error("Internal server error: " + +  describe_backtrace(err) + "\n"); + } +  + /* We got some data on a socket. +  * ================================================= +  */ +  + void got_data(mixed fooid, string s) + { +  mixed *err; +  int tmp, keep_alive; +  function funp; +  mapping heads; +  string head_string, tmp2, tmp3; +  + #ifdef DUMB_TEST + /* Speedometer, to check how long the connect() and accept() calls take, +  * and the cloning of this object. +  */ +  end("FOO!!!\n"); +  /* On a SS4: 47 requests/sec, or 20msec/request. This is socket overhead to +  * 99.9% or so. +  */ +  +  return; + #endif +  +  + #ifdef HIT_ME +  perror("Got data: "+s+"\n"); + #endif +  +  if(!s || (!strlen(s) && fooid != 1)) +  return; +  +  if(cache) +  { +  s = cache + s; +  cache = 0; +  } +  remove_call_out(no_more_keep_connection_alive); +  tmp = parse_got(s); +  switch(-tmp) +  { +  case 0: +  cache = s; // More on the way. +  return; +  +  case 1: +  my_fd->write(prot+" 500 Stupid Client Error\r\n" +  "Content-Length: 0\r\n\r\n"); +  end(); +  return; // Stupid request. +  +  case 2: +  end(); +  return; +  } +  my_fd->set_blocking(); +  +  sscanf(s-"\r", "%s\n\n%s", s, cache); +  + #ifndef SPEED_MAX +  remove_call_out(timeout); + #endif +  +  if(conf) +  { +  roxen->current_configuration = conf; +  conf->add_received(strlen(s)); +  conf->requests++; +  +  foreach(conf->first_modules(), funp) if(file = funp( this_object())) break; +  +  if(!file) err=catch(file = roxen->get_file(this_object())); +  +  if(err) internal_error(err); +  +  if(!mappingp(file)) +  foreach(conf->last_modules(), funp) if(file = funp(this_object())) break; +  + #ifdef API_COMPAT +  if(mappingp(file)) +  if(file["string"]) +  file->data = file["string"]; // Compatibility... + #endif +  } else if(err=catch(file = roxen->configuration_parse( this_object() ))) { +  if(err==-1) return; +  internal_error(err); +  } +  +  if(!mappingp(file)) +  { +  if(method != "GET" && method != "HEAD" && method != "POST") +  file = http_low_answer(501, "Not implemented."); +  else +  { +  +  s = replace(parse_rxml(roxen->query("ZNoSuchFile"), this_object()), +  ({"$File", "$Me"}), +  ({ not_query, roxen->query("MyWorldLocation") })); +  file=http_low_answer(404, s); +  } +  } +  +  if((file->file == -1) || file->leave_me) +  { +  if(!file->stay) +  disconnect(); +  return; +  } +  +  if(file->type == "raw") +  file->raw = 1; +  else if(!file->type) +  file->type="text/plain"; +  +  +  if(!file->raw && prot != "HTTP/0.9") +  { +  string h; +  heads= +  ([ +  "Content-type":file["type"], +  "Server":roxen->version(), +  "Date":http_date(time) +  ]); +  +  if(file->encoding) +  heads["Content-Encoding"] = file->encoding; +  +  if(!file->error) +  file->error=200; +  +  if(file->expires) +  heads->Expires = http_date(file->expires); +  +  if(!file->len) +  { +  if(objectp(file->file)) +  if(!file->stat) +  file->stat = (int *)file->file->stat(); +  array fstat; +  if(arrayp(fstat = file->stat)) +  { +  if(file->file && !file->len) +  file->len = fstat[1]; +  +  +  heads["Last-Modified"] = http_date(fstat[3]); +  +  if(since) +  { +  if(is_modified(since, fstat[3], fstat[1])) +  { +  file->error = 304; +  method="HEAD"; +  } +  } +  } +  if(stringp(file->data)) +  file->len += strlen(file->data); +  } +  + #ifdef KEEP_CONNECTION_ALIVE + #ifdef REQUEST_DEBUG +  if(kept_alive) +  perror(sprintf("Connection: Kept alive %d times.\n", kept_alive)); + #endif +  if(misc->connection && search(misc->connection, "keep-alive") != -1) +  { +  if(file->len > 0) +  { +  heads->Connection = "keep-alive; timeout=100, maxreq=666"; +  keep_alive=1; + #ifdef REQUEST_DEBUG +  kept_alive++; + #endif +  } +  } + #endif +  +  if(mappingp(file->extra_heads)) +  heads |= file->extra_heads; +  +  if(mappingp(misc->moreheads)) +  heads |= misc->moreheads; +  +  head_string = prot+" "+(file->rettext||roxen->errors[file->error])+"\r\n"; +  foreach(indices(heads), h) +  if(arrayp(heads[h])) +  foreach(heads[h], tmp) +  head_string += sum(h, ": ", tmp, "\r\n"); +  else +  head_string += sum(h, ": ", heads[h], "\r\n"); +  +  +  if(file->len > -1) +  head_string += "Content-length: " + file->len + "\r\n"; +  head_string += "\r\n"; +  +  if(conf) +  { +  conf->add_sent(file->len>0 ? file->len : 1000); +  conf->add_hsent(strlen(head_string||"")); +  } +  +  if(method=="HEAD") +  { +  roxen->log(file, this_object()); +  if(keep_alive) +  { +  my_fd->write(head_string); +  misc->connection = 0; +  keep_connection_alive(); +  } else { +  end(head_string); +  } +  return; +  } +  +  if(!keep_alive && file->len < 3000 && file->len >= 0) +  { +  if(file->data) head_string += file->data; +  if(file->file) +  { +  head_string += file->file->read(3000); +  roxen->current_configuration = 0; +  destruct(file->file); +  } +  file->len=strlen(head_string); +  roxen->log(file, this_object()); +  end(head_string); +  return; +  } +  } +  + #if efun(send_fd) +  if((file->len<=0 || (file->len > 10000)) +  && !keep_alive && roxen->shuffle_fd && objectp(file->file) +  && (!file->data || strlen(file->data) < 2000)) +  { +  my_fd->set_blocking(); +  file->file->set_blocking(); +  +  if(file->data) head_string += file->data; +  if(head_string) my_fd->write(head_string); +  if(send_fd(roxen->shuffle_fd, file->file->query_fd()) +  && send_fd(roxen->shuffle_fd, my_fd->query_fd())) +  { +  roxen->log(file, this_object()); +  roxen->current_configuration = 0; +  end(); +  return; +  } else { +  report_error("Failed to send fd to shuffler process.\n"); +  roxen->init_shuffler(); +  } +  } + #endif +  +  if(head_string) send(head_string); +  if(file->data) send(file->data); +  if(file->file) send(file->file); +  pipe->output(my_fd); +  +  if(file->len > 65535) +  my_fd->set_buffer(65535, "w"); // Max is really 65535. +  else +  pipe->start(); // I give small files higher priority. +  +  roxen->log(file, this_object()); +  + #ifdef KEEP_CONNECTION_ALIVE +  if(keep_alive) +  { +  if(my_fd) +  { +  misc->connection = 0; +  pipe->set_done_callback(keep_connection_alive); +  } +  } + #endif +  file = 0; +  roxen->current_configuration = 0; + } +  + /* Get a somewhat identical copy of this object, used when doing +  * 'simulated' requests. */ +  + object clone_me() + { +  object c; +  c=clone(object_program(this_object())); +  +  c->my_fd = 0; +  c->conf = conf; +  c->time = time; +  c->method = method; +  c->prot = prot; +  c->pragma = pragma; +  c->cookies = cookies; +  c->prestate = prestate; +  c->supports = supports; +  c->remoteaddr = remoteaddr; +  c->client = client; +  c->auth = auth; +  c->misc = copy_value(misc); +  c->misc->orig = this_object(); +  c->realauth = realauth; +  return c; + } +  + void clean() + { +  if(!(my_fd && objectp(my_fd))) end(); +  else if((_time(1) - time) > 4800) end(); + } +  + void assign(object f, object c) + { +  ++roxen->num_connections; + #ifdef REQUEST_DEBUG +  perror(sprintf("REQUEST: Current number of open connections: %d\n", +  roxen->num_connections)); + #endif +  my_fd = f; +  my_fd->set_id(0); +  my_fd->set_nonblocking(got_data, lambda(){}, end); +  conf = c; +  mark_fd(my_fd->query_fd(), "HTTP connection"); +  + #ifndef SPEED_MAX +  call_out(timeout, 60); + #endif + } +    Newline at end of file added.