24c6c12000-02-20Martin Nilsson // A vitual server's main configuration // Copyright © 1996 - 2000, Roxen IS.
199d031999-09-05Francesco Chemolli 
be16102000-08-16Per Hedbor constant cvs_version = "$Id: configuration.pike,v 1.341 2000/08/16 18:55:28 per Exp $";
4d16831999-11-17Per Hedbor constant is_configuration = 1;
b1fca01996-11-12Per Hedbor #include <module.h>
a59d252000-07-04Per Hedbor #include <module_constants.h>
14179b1997-01-29Per Hedbor #include <roxen.h>
c5e0961999-10-04Per Hedbor #include <request_trace.h>
8afc811998-02-04Per Hedbor 
cf0f682000-02-08Per Hedbor inherit "basic_defvar";
c5e0961999-10-04Per Hedbor mapping enabled_modules = ([]);
4d16831999-11-17Per Hedbor mapping(string:array(int)) error_log=([]);
8afc811998-02-04Per Hedbor  #ifdef PROFILE mapping profile_map = ([]); #endif
c7a5f01999-02-16Per Hedbor #define CATCH(P,X) do{mixed e;if(e=catch{X;})report_error("While "+P+"\n"+describe_backtrace(e));}while(0)
18be211998-05-07Henrik Grubbström (Grubba) 
23414a2000-07-21Andreas Lange // --- Locale defines --- //<locale-token project="roxen_start"> LOC_S </locale-token> //<locale-token project="roxen_config"> LOC_C </locale-token> //<locale-token project="roxen_message"> LOC_M </locale-token> //<locale-token project="roxen_config"> DLOCALE </locale-token> #define LOC_S(X,Y) _STR_LOCALE("roxen_start",X,Y) #define LOC_C(X,Y) _STR_LOCALE("roxen_config",X,Y) #define LOC_M(X,Y) _STR_LOCALE("roxen_message",X,Y)
b9a7022000-07-15Andreas Lange USE_DEFERRED_LOCALE;
23414a2000-07-21Andreas Lange #define DLOCALE(X,Y) _DEF_LOCALE("roxen_config",X,Y) #define CALL(X,Y) _LOCALE_FUN("roxen_config",X,Y)
18be211998-05-07Henrik Grubbström (Grubba) 
199d031999-09-05Francesco Chemolli #ifdef THROTTLING_DEBUG #undef THROTTLING_DEBUG
10c7e11999-12-28Martin Nilsson #define THROTTLING_DEBUG(X) werror("Throttling: "+X+"\n")
199d031999-09-05Francesco Chemolli #else #define THROTTLING_DEBUG(X) #endif
10c7e11999-12-28Martin Nilsson #ifdef REQUEST_DEBUG # define REQUEST_WERR(X) werror("CONFIG: "+X+"\n") #else # define REQUEST_WERR(X) #endif
b1fca01996-11-12Per Hedbor /* A configuration.. */
dfe0362000-03-19Martin Nilsson 
3b17831998-11-22Per Hedbor #include "rxml.pike";
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor object throttler; function store = roxen->store; function retrieve = roxen->retrieve; function remove = roxen->remove; RoxenModule types_module; RoxenModule auth_module; RoxenModule dir_module; function types_fun; function auth_fun;
b1fca01996-11-12Per Hedbor  string name;
1d7d6d2000-02-16Per Hedbor int inited;
65c6d22000-03-10Martin Nilsson int config_id;
3f2fce2000-07-09Per Hedbor 
65c6d22000-03-10Martin Nilsson int get_config_id() { if(config_id) return config_id; for(int i=sizeof(roxen->configurations); i;) if(roxen->configurations[--i]->name==name) return config_id=i; }
c7a5f01999-02-16Per Hedbor string get_doc_for( string region, string variable ) {
e351dd1999-11-29Per Hedbor  RoxenModule module;
c7a5f01999-02-16Per Hedbor  if(variable[0] == '_') return 0; if((int)reverse(region)) return 0; if(module = find_module( region )) { if(module->variables[variable])
b2c49b2000-07-09Per Hedbor  return module->variables[variable]->name()+ "\n"+module->variables[ variable ]->doc();
c7a5f01999-02-16Per Hedbor  } if(variables[ variable ])
b2c49b2000-07-09Per Hedbor  return variables[variable]->name()+ "\n"+variables[ variable ]->doc();
c7a5f01999-02-16Per Hedbor }
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor string query_internal_location(RoxenModule|void mod)
5839c31999-01-22Marcus Comstedt {
c5e0961999-10-04Per Hedbor  return QUERY(InternalLoc)+(mod?replace(otomod[mod]||"", "#", "!")+"/":"");
5839c31999-01-22Marcus Comstedt }
b1fca01996-11-12Per Hedbor  string query_name() {
10c7e11999-12-28Martin Nilsson  if(strlen(QUERY(name)))
c5e0961999-10-04Per Hedbor  return QUERY(name);
b1fca01996-11-12Per Hedbor  return name; } string comment() { return QUERY(comment); }
10c7e11999-12-28Martin Nilsson class Priority
27b0e11996-11-26Per Hedbor {
ec91501999-11-23Per Hedbor  string _sprintf() { return "Priority()"; }
e351dd1999-11-29Per Hedbor  array (RoxenModule) url_modules = ({ }); array (RoxenModule) logger_modules = ({ }); array (RoxenModule) location_modules = ({ }); array (RoxenModule) filter_modules = ({ }); array (RoxenModule) last_modules = ({ }); array (RoxenModule) first_modules = ({ }); mapping (string:array(RoxenModule)) file_extension_modules = ([ ]); mapping (RoxenModule:multiset(string)) provider_modules = ([ ]);
38dca81996-12-10Per Hedbor  void stop() {
a8f1b32000-01-31Per Hedbor  foreach(url_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping url modules",m->stop && m->stop());
a8f1b32000-01-31Per Hedbor  foreach(logger_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping logging modules",m->stop && m->stop());
a8f1b32000-01-31Per Hedbor  foreach(filter_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping filter modules",m->stop && m->stop());
a8f1b32000-01-31Per Hedbor  foreach(location_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping location modules",m->stop && m->stop());
a8f1b32000-01-31Per Hedbor  foreach(last_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping last modules",m->stop && m->stop());
a8f1b32000-01-31Per Hedbor  foreach(first_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping first modules",m->stop && m->stop());
10c7e11999-12-28Martin Nilsson  foreach(indices(provider_modules), RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping provider modules",m->stop && m->stop());
38dca81996-12-10Per Hedbor  } }
b1fca01996-11-12Per Hedbor  /* A 'pri' is one of the ten priority objects. Each one holds a list * of modules for that priority. They are all merged into one list for * performance reasons later on. */
e351dd1999-11-29Per Hedbor array (Priority) allocate_pris()
b1fca01996-11-12Per Hedbor {
c5e0961999-10-04Per Hedbor  return allocate(10, Priority)();
b1fca01996-11-12Per Hedbor }
27b0e11996-11-26Per Hedbor int requests;
2f1e892000-08-15Martin Nilsson //! The number of requests, for debug and statistics info only.
12a9c51997-08-11Henrik Grubbström (Grubba) // Protocol specific statistics. mapping(string:mixed) extra_statistics = ([]);
dc54c41997-08-28Henrik Grubbström (Grubba) mapping(string:mixed) misc = ([]); // Even more statistics.
b1fca01996-11-12Per Hedbor 
2f1e892000-08-15Martin Nilsson int sent; //! Bytes data sent int hsent; //! Bytes headers sent int received; //! Bytes data received
b1fca01996-11-12Per Hedbor  // Will write a line to the log-file. This will probably be replaced // entirely by log-modules in the future, since this would be much // cleaner.
f406ba1999-11-27Per Hedbor function(string:int) log_function;
b1fca01996-11-12Per Hedbor 
2f1e892000-08-15Martin Nilsson // The logging format used. This will probably move to the above
b1fca01996-11-12Per Hedbor // mentioned module in the future. private mapping (string:string) log_format = ([]);
c5e0961999-10-04Per Hedbor // A list of priority objects
e351dd1999-11-29Per Hedbor private array (Priority) pri = allocate_pris();
b1fca01996-11-12Per Hedbor 
f569581999-11-23Per Hedbor public mapping modules = ([]);
e75fd12000-07-26Johan Sundström //! All enabled modules in this virtual server. //! The format is "module":{ "copies":([ num:instance, ... ]) }
b1fca01996-11-12Per Hedbor 
e351dd1999-11-29Per Hedbor public mapping (RoxenModule:string) otomod = ([]);
e75fd12000-07-26Johan Sundström //! A mapping from the module objects to module names
b1fca01996-11-12Per Hedbor  // Caches to speed up the handling of the module search. // They are all sorted in priority order, and created by the functions // below. private array (function) url_module_cache, last_module_cache; private array (function) logger_module_cache, first_module_cache; private array (function) filter_module_cache; private array (array (string|function)) location_module_cache; private mapping (string:array (function)) file_extension_module_cache=([]);
e351dd1999-11-29Per Hedbor private mapping (string:array (RoxenModule)) provider_module_cache=([]);
b1fca01996-11-12Per Hedbor 
38dca81996-12-10Per Hedbor  // Call stop in all modules. void stop() {
c7a5f01999-02-16Per Hedbor  CATCH("stopping type modules", types_module && types_module->stop && types_module->stop()); CATCH("stopping auth module", auth_module && auth_module->stop && auth_module->stop()); CATCH("stopping directory module", dir_module && dir_module->stop && dir_module->stop());
10c7e11999-12-28Martin Nilsson  for(int i=0; i<10; i++)
c7a5f01999-02-16Per Hedbor  CATCH("stopping priority group",
5b0ec72000-04-03Henrik Grubbström (Grubba)  (pri[i] && pri[i]->stop && pri[i]->stop()));
f86c192000-04-03Henrik Grubbström (Grubba)  CATCH("stopping the logger", log_function && lambda(mixed m){ destruct(m); }(function_object(log_function)));
e62d482000-02-29David Hedbor  foreach( registered_urls, string url ) roxen->unregister_url(url);
38dca81996-12-10Per Hedbor }
41b77c1999-07-15David Hedbor public string type_from_filename( string file, int|void to, string|void myext )
b1fca01996-11-12Per Hedbor {
f28c112000-03-06Martin Nilsson  array(string)|string tmp;
14179b1997-01-29Per Hedbor  if(!types_fun) return to?({ "application/octet-stream", 0 }):"application/octet-stream";
dfe0362000-03-19Martin Nilsson  string ext=myext || Roxen.extension(file);
41b77c1999-07-15David Hedbor 
14179b1997-01-29Per Hedbor  if(tmp = types_fun(ext)) { mixed tmp2,nx; if(tmp[0] == "strip") { tmp2=file/"."; if(sizeof(tmp2) > 2) nx=tmp2[-2]; if(nx && (tmp2=types_fun(nx))) tmp[0] = tmp2[0];
9be5aa1998-07-03Henrik Grubbström (Grubba)  else if(tmp2=types_fun("default")) tmp[0] = tmp2[0];
14179b1997-01-29Per Hedbor  else
9be5aa1998-07-03Henrik Grubbström (Grubba)  tmp[0]="application/octet-stream";
14179b1997-01-29Per Hedbor  }
9be5aa1998-07-03Henrik Grubbström (Grubba)  } else if(!(tmp = types_fun("default"))) { tmp = ({ "application/octet-stream", 0 });
14179b1997-01-29Per Hedbor  }
9be5aa1998-07-03Henrik Grubbström (Grubba)  return to?tmp:tmp[0];
b1fca01996-11-12Per Hedbor }
e351dd1999-11-29Per Hedbor array (RoxenModule) get_providers(string provides)
2f1e892000-08-15Martin Nilsson //! Returns an array with all provider modules that provides "provides".
ae32d01998-03-23David Hedbor {
2f1e892000-08-15Martin Nilsson  // This cache is cleared in the invalidate_cache() call.
ae32d01998-03-23David Hedbor  if(!provider_module_cache[provides])
10c7e11999-12-28Martin Nilsson  {
ae32d01998-03-23David Hedbor  int i; provider_module_cache[provides] = ({ }); for(i = 9; i >= 0; i--) {
10c7e11999-12-28Martin Nilsson  foreach(indices(pri[i]->provider_modules), RoxenModule d) if(pri[i]->provider_modules[ d ][ provides ])
ae32d01998-03-23David Hedbor  provider_module_cache[provides] += ({ d }); } } return provider_module_cache[provides]; }
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor RoxenModule get_provider(string provides)
2f1e892000-08-15Martin Nilsson //! Returns the first provider module that provides "provides".
ae32d01998-03-23David Hedbor {
e351dd1999-11-29Per Hedbor  array (RoxenModule) prov = get_providers(provides);
ae32d01998-03-23David Hedbor  if(sizeof(prov)) return prov[0]; return 0; }
bdb8da1998-09-02Johan Schön array(mixed) map_providers(string provides, string fun, mixed ... args)
2f1e892000-08-15Martin Nilsson //! Maps the function "fun" over all matching provider modules.
ae32d01998-03-23David Hedbor {
e351dd1999-11-29Per Hedbor  array (RoxenModule) prov = get_providers(provides);
ae32d01998-03-23David Hedbor  array error;
bdb8da1998-09-02Johan Schön  array a=({ }); mixed m;
10c7e11999-12-28Martin Nilsson  foreach(prov, RoxenModule mod)
9bb8131998-09-12Per Hedbor  {
ae32d01998-03-23David Hedbor  if(!objectp(mod)) continue;
10c7e11999-12-28Martin Nilsson  if(functionp(mod[fun]))
bdb8da1998-09-02Johan Schön  error = catch(m=mod[fun](@args));
24fbd41999-04-21David Hedbor  if(arrayp(error)) { error[0] = "Error in map_providers(): "+error[0];
10c7e11999-12-28Martin Nilsson  report_debug(describe_backtrace(error));
24fbd41999-04-21David Hedbor  }
bdb8da1998-09-02Johan Schön  else
9bb8131998-09-12Per Hedbor  a += ({ m });
18be211998-05-07Henrik Grubbström (Grubba)  error = 0;
ae32d01998-03-23David Hedbor  }
9bb8131998-09-12Per Hedbor  return a;
ae32d01998-03-23David Hedbor } mixed call_provider(string provides, string fun, mixed ... args)
2f1e892000-08-15Martin Nilsson //! Maps the function "fun" over all matching provider modules and //! returns the first positive response.
ae32d01998-03-23David Hedbor {
10c7e11999-12-28Martin Nilsson  foreach(get_providers(provides), RoxenModule mod)
e351dd1999-11-29Per Hedbor  {
d8b7721998-05-28Henrik Grubbström (Grubba)  function f; if(objectp(mod) && functionp(f = mod[fun])) { mixed error; if (arrayp(error = catch { mixed ret; if (ret = f(@args)) {
c5e0961999-10-04Per Hedbor  return ret;
d8b7721998-05-28Henrik Grubbström (Grubba)  } })) {
24fbd41999-04-21David Hedbor  error[0] = "Error in call_provider(): "+error[0]; throw(error);
d8b7721998-05-28Henrik Grubbström (Grubba)  } }
ae32d01998-03-23David Hedbor  } }
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor array (function) file_extension_modules(string ext, RequestID id)
b1fca01996-11-12Per Hedbor { if(!file_extension_module_cache[ext])
10c7e11999-12-28Martin Nilsson  {
b1fca01996-11-12Per Hedbor  int i; file_extension_module_cache[ext] = ({ }); for(i=9; i>=0; i--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d = pri[i]->file_extension_modules[ext]) foreach(d, p) file_extension_module_cache[ext] += ({ p->handle_file_extension }); } } return file_extension_module_cache[ext]; }
e351dd1999-11-29Per Hedbor array (function) url_modules(RequestID id)
b1fca01996-11-12Per Hedbor { if(!url_module_cache) { int i; url_module_cache=({ }); for(i=9; i>=0; i--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d=pri[i]->url_modules) foreach(d, p) url_module_cache += ({ p->remap_url }); } } return url_module_cache; }
4f4bc11998-02-04Per Hedbor mapping api_module_cache = ([]);
e351dd1999-11-29Per Hedbor mapping api_functions(void|RequestID id)
4f4bc11998-02-04Per Hedbor { return copy_value(api_module_cache); }
e351dd1999-11-29Per Hedbor array (function) logger_modules(RequestID id)
b1fca01996-11-12Per Hedbor { if(!logger_module_cache) { int i; logger_module_cache=({ }); for(i=9; i>=0; i--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d=pri[i]->logger_modules) foreach(d, p) if(p->log) logger_module_cache += ({ p->log }); } } return logger_module_cache; }
e351dd1999-11-29Per Hedbor array (function) last_modules(RequestID id)
b1fca01996-11-12Per Hedbor { if(!last_module_cache) { int i; last_module_cache=({ }); for(i=9; i>=0; i--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d=pri[i]->last_modules) foreach(d, p) if(p->last_resort) last_module_cache += ({ p->last_resort }); } } return last_module_cache; }
ca44e51998-07-02Henrik Grubbström (Grubba) #ifdef __NT__
e351dd1999-11-29Per Hedbor static mixed strip_fork_information(RequestID id)
ca44e51998-07-02Henrik Grubbström (Grubba) { array a = id->not_query/"::"; id->not_query = a[0]; id->misc->fork_information = a[1..];
c5e0961999-10-04Per Hedbor  return 0;
ca44e51998-07-02Henrik Grubbström (Grubba) } #endif /* __NT__ */
e351dd1999-11-29Per Hedbor array (function) first_modules(RequestID id)
b1fca01996-11-12Per Hedbor { if(!first_module_cache) { int i;
ca44e51998-07-02Henrik Grubbström (Grubba)  first_module_cache=({ #ifdef __NT__ strip_fork_information, // Always first! #endif /* __NT__ */ });
b1fca01996-11-12Per Hedbor  for(i=9; i>=0; i--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; RoxenModule p;
f128901997-08-15Henrik Grubbström (Grubba)  if(d=pri[i]->first_modules) { foreach(d, p) { if(p->first_try) {
b1fca01996-11-12Per Hedbor  first_module_cache += ({ p->first_try });
f128901997-08-15Henrik Grubbström (Grubba)  } } }
b1fca01996-11-12Per Hedbor  } }
f128901997-08-15Henrik Grubbström (Grubba) 
b1fca01996-11-12Per Hedbor  return first_module_cache; }
e351dd1999-11-29Per Hedbor array location_modules(RequestID id)
cd92872000-08-15Johan Sundström //! Return an array of all location modules the request would be //! mapped through, by order of priority.
b1fca01996-11-12Per Hedbor { if(!location_module_cache) { int i;
8cc31b1997-10-12Henrik Grubbström (Grubba)  array new_location_module_cache=({ });
b1fca01996-11-12Per Hedbor  for(i=9; i>=0; i--) {
10c7e11999-12-28Martin Nilsson  array(RoxenModule) d;
e351dd1999-11-29Per Hedbor  RoxenModule p;
8cc31b1997-10-12Henrik Grubbström (Grubba)  if(d=pri[i]->location_modules) { array level_find_files = ({}); array level_locations = ({}); foreach(d, p) { string location; // FIXME: Should there be a catch() here? if(p->find_file && (location = p->query_location())) { level_find_files += ({ p->find_file }); level_locations += ({ location }); } } sort(level_locations, level_find_files); int j; for (j = sizeof(level_locations); j--;) { // Order after longest path first. new_location_module_cache += ({ ({ level_locations[j], level_find_files[j] }) }); } }
b1fca01996-11-12Per Hedbor  }
8cc31b1997-10-12Henrik Grubbström (Grubba)  location_module_cache = new_location_module_cache;
b1fca01996-11-12Per Hedbor  } return location_module_cache; }
fd93022000-05-05Martin Nilsson array(function) filter_modules(RequestID id)
b1fca01996-11-12Per Hedbor { if(!filter_module_cache) { int i; filter_module_cache=({ }); for(i=9; i>=0; i--) {
10c7e11999-12-28Martin Nilsson  array(RoxenModule) d;
e351dd1999-11-29Per Hedbor  RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d=pri[i]->filter_modules) foreach(d, p) if(p->filter) filter_module_cache+=({ p->filter }); } } return filter_module_cache; }
3bb38c2000-01-20Martin Bähr static string cached_hostname = gethostname();
1c78232000-03-13Per Hedbor class LogFile
b1fca01996-11-12Per Hedbor {
1c78232000-03-13Per Hedbor  Stdio.File fd; int opened; string fname; void do_open() {
5b0ec72000-04-03Henrik Grubbström (Grubba)  mixed parent; if (catch { parent = function_object(object_program(this_object())); } || !parent) {
2f1e892000-08-15Martin Nilsson  // Our parent (aka the configuration) has been destructed. // Time to die.
5b0ec72000-04-03Henrik Grubbström (Grubba)  remove_call_out(do_open); remove_call_out(do_close); destruct(); return; }
6513612000-03-14Per Hedbor  string ff = fname;
26ddbb2000-07-23Martin Nilsson  mapping m = localtime(time(1));
2f1e892000-08-15Martin Nilsson  m->year += 1900; // Adjust for years being counted since 1900 m->mon++; // Adjust for months being counted 0-11
6513612000-03-14Per Hedbor  if(m->mon < 10) m->mon = "0"+m->mon; if(m->mday < 10) m->mday = "0"+m->mday; if(m->hour < 10) m->hour = "0"+m->hour; ff = replace(fname,({"%d","%m","%y","%h", "%H" }), ({ (string)m->mday, (string)(m->mon), (string)(m->year),(string)m->hour, cached_hostname, })); mkdirhier( ff ); fd = open( ff, "wac" ); if(!fd) { remove_call_out( do_open ); call_out( do_open, 120 );
49cd282000-08-11Andreas Lange  report_error(LOC_M(37, "Failed to open logfile")+" "+fname+" "
6513612000-03-14Per Hedbor #if constant(strerror) "(" + strerror(errno()) + ")" #endif "\n"); return; }
1c78232000-03-13Per Hedbor  opened = 1;
6513612000-03-14Per Hedbor  remove_call_out( do_open ); call_out( do_open, 1800 );
1c78232000-03-13Per Hedbor  } void do_close() { destruct( fd ); opened = 0; }
14179b1997-01-29Per Hedbor 
6513612000-03-14Per Hedbor  int write( string what )
1c78232000-03-13Per Hedbor  {
6513612000-03-14Per Hedbor  if( !opened ) do_open(); if( !opened ) return 0;
1c78232000-03-13Per Hedbor  remove_call_out( do_close ); call_out( do_close, 10.0 );
6513612000-03-14Per Hedbor  return fd->write( what );
1c78232000-03-13Per Hedbor  }
10c7e11999-12-28Martin Nilsson 
1c78232000-03-13Per Hedbor  static void create( string f )
b1fca01996-11-12Per Hedbor  {
6513612000-03-14Per Hedbor  fname = f;
1c78232000-03-13Per Hedbor  opened = 0; } } void init_log_file() { if(log_function) { // Free the old one. destruct(function_object(log_function)); log_function = 0; } // Only try to open the log file if logging is enabled!! if(query("Log")) { string logfile = query("LogFile");
f7d9811997-09-12Per Hedbor  if(strlen(logfile))
1c78232000-03-13Per Hedbor  log_function = LogFile( logfile )->write; }
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor // Parse the logging format strings. private inline string fix_logging(string s)
b1fca01996-11-12Per Hedbor {
14179b1997-01-29Per Hedbor  string pre, post, c; sscanf(s, "%*[\t ]", s); s = replace(s, ({"\\t", "\\n", "\\r" }), ({"\t", "\n", "\r" }));
62eac81997-10-03Henrik Grubbström (Grubba) 
1c78232000-03-13Per Hedbor  s = String.trim_whites( s );
14179b1997-01-29Per Hedbor  while(sscanf(s, "%s$char(%d)%s", pre, c, post)==3) s=sprintf("%s%c%s", pre, c, post); while(sscanf(s, "%s$wchar(%d)%s", pre, c, post)==3) s=sprintf("%s%2c%s", pre, c, post); while(sscanf(s, "%s$int(%d)%s", pre, c, post)==3) s=sprintf("%s%4c%s", pre, c, post); if(!sscanf(s, "%s$^%s", pre, post)) s+="\n"; else s=pre+post; return s;
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor private void parse_log_formats() { string b; array foo=query("LogFormat")/"\n"; foreach(foo, b) if(strlen(b) && b[0] != '#' && sizeof(b/":")>1)
62eac81997-10-03Henrik Grubbström (Grubba)  log_format[(b/":")[0]] = fix_logging((b/":")[1..]*":");
14179b1997-01-29Per Hedbor }
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor // Really write an entry to the log. private void write_to_log( string host, string rest, string oh, function fun )
b1fca01996-11-12Per Hedbor {
14179b1997-01-29Per Hedbor  int s; if(!host) host=oh; if(!stringp(host)) host = "error:no_host";
71c7b11998-03-02Henrik Grubbström (Grubba)  else host = (host/" ")[0]; // In case it's an IP we don't want the port.
14179b1997-01-29Per Hedbor  if(fun) fun(replace(rest, "$host", host));
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor // Logging format support functions. nomask private inline string host_ip_to_int(string s) { int a, b, c, d; sscanf(s, "%d.%d.%d.%d", a, b, c, d); return sprintf("%c%c%c%c",a, b, c, d); }
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor nomask private inline string unsigned_to_bin(int a) { return sprintf("%4c", a); } nomask private inline string unsigned_short_to_bin(int a) { return sprintf("%2c", a); } nomask private inline string extract_user(string from) { array tmp; if (!from || sizeof(tmp = from/":")<2) return "-";
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  return tmp[0]; // username only, no password }
f406ba1999-11-27Per Hedbor public void log(mapping file, RequestID request_id)
14179b1997-01-29Per Hedbor {
e5bad21998-02-10Per Hedbor // _debug(2);
14179b1997-01-29Per Hedbor  string a; string form; function f; foreach(logger_modules(request_id), f) // Call all logging functions if(f(request_id,file))return;
0976901998-11-26Henrik Grubbström (Grubba)  if(!log_function || !request_id) return;// No file is open for logging.
14179b1997-01-29Per Hedbor 
dfe0362000-03-19Martin Nilsson  if(QUERY(NoLog) && Roxen._match(request_id->remoteaddr, QUERY(NoLog)))
14179b1997-01-29Per Hedbor  return;
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(!(form=log_format[(string)file->error])) form = log_format["*"];
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(!form) return;
10c7e11999-12-28Martin Nilsson  form=replace(form, ({
14179b1997-01-29Per Hedbor  "$ip_number", "$bin-ip_number", "$cern_date",
dfb4ec1999-05-20Francesco Chemolli  "$bin-date", "$method", "$resource", "$full_resource", "$protocol",
14179b1997-01-29Per Hedbor  "$response", "$bin-response", "$length", "$bin-length", "$referer", "$user_agent", "$user", "$user_id",
d9624c1998-04-03Henrik Grubbström (Grubba)  "$request-time"
10c7e11999-12-28Martin Nilsson  }),
f406ba1999-11-27Per Hedbor  ({
14179b1997-01-29Per Hedbor  (string)request_id->remoteaddr,
71c7b11998-03-02Henrik Grubbström (Grubba)  host_ip_to_int(request_id->remoteaddr),
dfe0362000-03-19Martin Nilsson  Roxen.cern_http_date(time(1)),
71c7b11998-03-02Henrik Grubbström (Grubba)  unsigned_to_bin(time(1)), (string)request_id->method,
dfe0362000-03-19Martin Nilsson  Roxen.http_encode_string((string)request_id->not_query), Roxen.http_encode_string((string)request_id->raw_url),
71c7b11998-03-02Henrik Grubbström (Grubba)  (string)request_id->prot, (string)(file->error||200), unsigned_short_to_bin(file->error||200), (string)(file->len>=0?file->len:"?"), unsigned_to_bin(file->len), (string) (sizeof(request_id->referer||({}))?request_id->referer[0]:"-"),
dfe0362000-03-19Martin Nilsson  Roxen.http_encode_string(sizeof(request_id->client||({}))?request_id->client*" ":"-"),
71c7b11998-03-02Henrik Grubbström (Grubba)  extract_user(request_id->realauth),
f406ba1999-11-27Per Hedbor  request_id->cookies->RoxenUserID||"0",
d9624c1998-04-03Henrik Grubbström (Grubba)  (string)(time(1)-request_id->time)
71c7b11998-03-02Henrik Grubbström (Grubba)  }));
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(search(form, "host") != -1) roxen->ip_to_host(request_id->remoteaddr, write_to_log, form, request_id->remoteaddr, log_function); else log_function(form);
e5bad21998-02-10Per Hedbor // _debug(0);
14179b1997-01-29Per Hedbor } // These are here for statistics and debug reasons only. public string status()
b1fca01996-11-12Per Hedbor {
14179b1997-01-29Per Hedbor  float tmp;
b1fca01996-11-12Per Hedbor  string res="";
b461641998-10-11Henrik Grubbström (Grubba)  float dt = (float)(time(1) - roxen->start_time + 1);
14179b1997-01-29Per Hedbor 
67f60e2000-07-09Martin Nilsson  res = "<p><table>";
434bac2000-07-14Andreas Lange  res += sprintf("<tr align=\"right\"><td><b>%s:</b></td><td>%.2fMB" "</td><td>%.2f Kbit/%s</td>" "<td><b>%s:</b></td><td>%.2fMB</td></tr>\n" "<tr align=\"right\"><td><b>%s:</b></td>" "<td>%8d</td><td>%.2f/%s</td>" "<td><b>%s:</b></td><td>%.2fMB</td></tr>\n",
23414a2000-07-21Andreas Lange  LOC_C(2,"Sent data"),((float)sent/(1024.0*1024.0)), (((float)sent)/(1024.0*1024.0)/dt) * 8192.0, LOC_C(3,"sec"), LOC_C(4,"Sent headers"),((float)hsent)/(1024.0*1024.0), LOC_C(5,"Number of requests"), requests, (((float)requests * 60.0)/dt), LOC_C(6,"min"), LOC_C(7,"Received data"),((float)received)/(1024.0*1024.0));
dc54c41997-08-28Henrik Grubbström (Grubba)  if (!zero_type(misc->ftp_users)) {
434bac2000-07-14Andreas Lange  res += sprintf("<tr align=\"right\"><td><b>%s:</b></td><td>%8d</td>" "<td>%.2f/%s</td>" "<td><b>%s:</b></td><td>%d</td></tr>\n",
23414a2000-07-21Andreas Lange  LOC_C(8,"FTP users (total)"), misc->ftp_users, (((float)misc->ftp_users*(float)60.0)/dt), LOC_C(6,"min"), LOC_C(9,"FTP users (now)"), misc->ftp_users_now);
dc54c41997-08-28Henrik Grubbström (Grubba)  }
67f60e2000-07-09Martin Nilsson  res += "</table></p>\n\n";
12a9c51997-08-11Henrik Grubbström (Grubba) 
c5e0961999-10-04Per Hedbor  if ((extra_statistics->ftp) && (extra_statistics->ftp->commands)) {
12a9c51997-08-11Henrik Grubbström (Grubba)  // FTP statistics.
23414a2000-07-21Andreas Lange  res += "<b>"+LOC_C(10, "FTP statistics") + ":</b><br />\n"
12a9c51997-08-11Henrik Grubbström (Grubba)  "<ul><table>\n"; foreach(sort(indices(extra_statistics->ftp->commands)), string cmd) {
1c783c2000-07-15Andreas Lange  res += CALL("ftp_stat_line", "eng") (upper_case(cmd), extra_statistics->ftp->commands[cmd]);
12a9c51997-08-11Henrik Grubbström (Grubba)  } res += "</table></ul>\n"; }
10c7e11999-12-28Martin Nilsson 
12a9c51997-08-11Henrik Grubbström (Grubba)  return res;
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor public array(string) userinfo(string u, RequestID|void id)
14179b1997-01-29Per Hedbor { if(auth_module) return auth_module->userinfo(u);
b461641998-10-11Henrik Grubbström (Grubba)  else report_warning(sprintf("userinfo(): %s\n" "%s\n",
49cd282000-08-11Andreas Lange  LOC_M(38, "No authorization module"),
b461641998-10-11Henrik Grubbström (Grubba)  describe_backtrace(backtrace())));
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor public array(string) userlist(RequestID|void id)
14179b1997-01-29Per Hedbor { if(auth_module) return auth_module->userlist();
b461641998-10-11Henrik Grubbström (Grubba)  else report_warning(sprintf("userlist(): %s\n" "%s\n",
49cd282000-08-11Andreas Lange  LOC_M(38, "No authorization module"),
b461641998-10-11Henrik Grubbström (Grubba)  describe_backtrace(backtrace())));
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor public array(string) user_from_uid(int u, RequestID|void id)
14179b1997-01-29Per Hedbor { if(auth_module) return auth_module->user_from_uid(u);
b461641998-10-11Henrik Grubbström (Grubba)  else report_warning(sprintf("user_from_uid(): %s\n" "%s\n",
49cd282000-08-11Andreas Lange  LOC_M(38, "No authorization module"),
b461641998-10-11Henrik Grubbström (Grubba)  describe_backtrace(backtrace())));
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor public string last_modified_by(Stdio.File file, RequestID id)
6103bc1999-10-09Henrik Grubbström (Grubba) {
9f9fc32000-02-17Per Hedbor  array(int) s;
6103bc1999-10-09Henrik Grubbström (Grubba)  int uid;
9f9fc32000-02-17Per Hedbor  array u;
10c7e11999-12-28Martin Nilsson 
6103bc1999-10-09Henrik Grubbström (Grubba)  if(objectp(file)) s=file->stat(); if(!s || sizeof(s)<5) return "A. Nonymous"; uid=s[5]; u=user_from_uid(uid, id); if(u) return u[0]; return "A. Nonymous"; }
14179b1997-01-29Per Hedbor  // Some clients does _not_ handle the magic 'internal-gopher-...'. // So, lets do it here instead. private mapping internal_gopher_image(string from) { sscanf(from, "%s.gif", from); sscanf(from, "%s.jpg", from); from -= "."; // Disallow "internal-gopher-..", it won't really do much harm, but a list of // all files in '..' might be retrieved (that is, the actual directory // file was sent to the browser)
1c78232000-03-13Per Hedbor  Stdio.File f = lopen("roxen-images/dir/"+from+".gif","r"); if (f) {
06026c1999-10-19Henrik Grubbström (Grubba)  return (["file":f, "type":"image/gif"]); } else { // File not found. return 0; }
14179b1997-01-29Per Hedbor } private static int nest = 0;
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY private mapping misc_cache=([]);
2b86422000-06-29Martin Stjernholm int|mapping check_security(function|object a, RequestID id, void|int slevel)
14179b1997-01-29Per Hedbor { array level; array seclevels;
2028af1997-07-07Henrik Grubbström (Grubba)  int ip_ok = 0; // Unknown
12a9c51997-08-11Henrik Grubbström (Grubba)  int auth_ok = 0; // Unknown // NOTE: // ip_ok and auth_ok are three-state variables. // Valid contents for them are: // 0 Unknown state -- No such restriction encountered yet. // 1 May be bad -- Restriction encountered, and test failed. // ~0 OK -- Test passed.
1935351997-04-28Henrik Grubbström (Grubba) 
2b86422000-06-29Martin Stjernholm  if(!(seclevels = misc_cache[ a ])) {
1a89f42000-08-14Martin Stjernholm  object mod = Roxen.get_owning_module (a);
ab7c312000-08-12Martin Stjernholm  if(mod && mod->query_seclevels)
3b17831998-11-22Per Hedbor  misc_cache[ a ] = seclevels = ({
2b86422000-06-29Martin Stjernholm  mod->query_seclevels(), mod->query("_seclvl"), mod->query("_sec_group")
3b17831998-11-22Per Hedbor  }); else misc_cache[ a ] = seclevels = ({({}),0,"foo" });
2b86422000-06-29Martin Stjernholm  }
14179b1997-01-29Per Hedbor  if(slevel && (seclevels[1] > slevel)) // "Trustlevel" to low. return 1;
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(!sizeof(seclevels[0])) return 0; // Ok if there are no patterns.
18be211998-05-07Henrik Grubbström (Grubba)  mixed err; err = catch {
2028af1997-07-07Henrik Grubbström (Grubba)  foreach(seclevels[0], level) {
cc6d7c1997-07-22Henrik Grubbström (Grubba)  switch(level[0]) { case MOD_ALLOW: // allow ip=...
2028af1997-07-07Henrik Grubbström (Grubba)  if(level[1](id->remoteaddr)) {
cc6d7c1997-07-22Henrik Grubbström (Grubba)  ip_ok = ~0; // Match. It's ok.
2028af1997-07-07Henrik Grubbström (Grubba)  } else {
cc6d7c1997-07-22Henrik Grubbström (Grubba)  ip_ok |= 1; // IP may be bad.
2028af1997-07-07Henrik Grubbström (Grubba)  }
12a9c51997-08-11Henrik Grubbström (Grubba)  break;
a8f1b32000-01-31Per Hedbor 
cc6d7c1997-07-22Henrik Grubbström (Grubba)  case MOD_DENY: // deny ip=...
b461641998-10-11Henrik Grubbström (Grubba) 
a75a321997-05-14Henrik Grubbström (Grubba)  if(level[1](id->remoteaddr))
23414a2000-07-21Andreas Lange  return Roxen.http_low_answer(403, "<h2> Access forbidden </h2>");
12a9c51997-08-11Henrik Grubbström (Grubba)  break;
14179b1997-01-29Per Hedbor 
cc6d7c1997-07-22Henrik Grubbström (Grubba)  case MOD_USER: // allow user=...
12a9c51997-08-11Henrik Grubbström (Grubba)  if(id->auth && id->auth[0] && level[1](id->auth[1])) { auth_ok = ~0; // Match. It's ok. } else { auth_ok |= 1; // Auth may be bad. } break;
a8f1b32000-01-31Per Hedbor 
cc6d7c1997-07-22Henrik Grubbström (Grubba)  case MOD_PROXY_USER: // allow user=...
12a9c51997-08-11Henrik Grubbström (Grubba)  if (ip_ok != 1) { // IP is OK as of yet.
10c7e11999-12-28Martin Nilsson  if(id->misc->proxyauth && id->misc->proxyauth[0] &&
12a9c51997-08-11Henrik Grubbström (Grubba)  level[1](id->misc->proxyauth[1])) return 0;
dfe0362000-03-19Martin Nilsson  return Roxen.http_proxy_auth_required(seclevels[2]);
12a9c51997-08-11Henrik Grubbström (Grubba)  } else { // Bad IP.
c5e0961999-10-04Per Hedbor  return 1;
12a9c51997-08-11Henrik Grubbström (Grubba)  }
7be80e1998-06-29Henrik Grubbström (Grubba)  break; case MOD_ACCEPT: // accept ip=... // Short-circuit version on allow. if(level[1](id->remoteaddr)) { // Match. It's ok.
c5e0961999-10-04Per Hedbor  return 0;
7be80e1998-06-29Henrik Grubbström (Grubba)  } else { ip_ok |= 1; // IP may be bad. } break; case MOD_ACCEPT_USER: // accept user=... // Short-circuit version on allow. if(id->auth && id->auth[0] && level[1](id->auth[1])) { // Match. It's ok.
c5e0961999-10-04Per Hedbor  return 0;
7be80e1998-06-29Henrik Grubbström (Grubba)  } else { if (id->auth) { auth_ok |= 1; // Auth may be bad. } else { // No auth yet, get some.
dfe0362000-03-19Martin Nilsson  return Roxen.http_auth_required(seclevels[2]);
7be80e1998-06-29Henrik Grubbström (Grubba)  } } break;
14179b1997-01-29Per Hedbor  }
2028af1997-07-07Henrik Grubbström (Grubba)  }
14179b1997-01-29Per Hedbor  };
18be211998-05-07Henrik Grubbström (Grubba)  if (err) {
434bac2000-07-14Andreas Lange  report_error("check_security(): %s:\n%s\n",
49cd282000-08-11Andreas Lange  LOC_M(39, "Error during module security check"),
67f60e2000-07-09Martin Nilsson  describe_backtrace(err));
c5e0961999-10-04Per Hedbor  return 1;
18be211998-05-07Henrik Grubbström (Grubba)  }
12a9c51997-08-11Henrik Grubbström (Grubba)  if (ip_ok == 1) { // Bad IP.
c5e0961999-10-04Per Hedbor  return 1;
12a9c51997-08-11Henrik Grubbström (Grubba)  } else { // IP OK, or no IP restrictions. if (auth_ok == 1) { // Bad authentification. // Query for authentification.
dfe0362000-03-19Martin Nilsson  return Roxen.http_auth_required(seclevels[2]);
12a9c51997-08-11Henrik Grubbström (Grubba)  } else { // No auth required, or authentification OK.
c5e0961999-10-04Per Hedbor  return 0;
12a9c51997-08-11Henrik Grubbström (Grubba)  }
2028af1997-07-07Henrik Grubbström (Grubba)  }
14179b1997-01-29Per Hedbor } #endif // Empty all the caches above.
8cc31b1997-10-12Henrik Grubbström (Grubba) void invalidate_cache()
14179b1997-01-29Per Hedbor { last_module_cache = 0; filter_module_cache = 0; first_module_cache = 0; url_module_cache = 0; location_module_cache = 0; logger_module_cache = 0; file_extension_module_cache = ([]);
ae32d01998-03-23David Hedbor  provider_module_cache = ([]);
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY if(misc_cache) misc_cache = ([ ]); #endif }
ec058c1998-07-04Henrik Grubbström (Grubba) // Empty all the caches above AND the ones in the loaded modules. void clear_memory_caches() { invalidate_cache();
10c7e11999-12-28Martin Nilsson  foreach(indices(otomod), RoxenModule m) if (m && m->clear_memory_caches) if (mixed err = catch( m->clear_memory_caches() ))
434bac2000-07-14Andreas Lange  report_error("clear_memory_caches() "+
49cd282000-08-11Andreas Lange  LOC_M(40, "failed for module %O:\n%s\n"),
67f60e2000-07-09Martin Nilsson  otomod[m], describe_backtrace(err));
ec058c1998-07-04Henrik Grubbström (Grubba) }
fc94331997-10-25Per Hedbor string draw_saturation_bar(int hue,int brightness, int where) {
e351dd1999-11-29Per Hedbor  Image.Image bar=Image.Image(30,256);
fc94331997-10-25Per Hedbor  for(int i=0;i<128;i++) { int j = i*2; bar->line(0,j,29,j,@hsv_to_rgb(hue,255-j,brightness)); bar->line(0,j+1,29,j+1,@hsv_to_rgb(hue,255-j,brightness)); } where = 255-where; bar->line(0,where,29,where, 255,255,255);
4c6df91999-11-25Jonas Wallden  return Image.GIF.encode(bar);
fc94331997-10-25Per Hedbor }
14179b1997-01-29Per Hedbor // Inspired by the internal-gopher-... thingie, this is the images
a6ef1f2000-03-28Johan Sundström // from the administration interface. :-)
14179b1997-01-29Per Hedbor private mapping internal_roxen_image(string from) { sscanf(from, "%s.gif", from); sscanf(from, "%s.jpg", from);
2b658c2000-02-07Per Hedbor  sscanf(from, "%s.xcf", from); sscanf(from, "%s.png", from);
fc94331997-10-25Per Hedbor 
1c78232000-03-13Per Hedbor  // Automatically generated colorbar. Used by wizard code...
fc94331997-10-25Per Hedbor  int hue,bright,w; if(sscanf(from, "%*s:%d,%d,%d", hue, bright,w)==4)
dfe0362000-03-19Martin Nilsson  return Roxen.http_string_answer(draw_saturation_bar(hue,bright,w),"image/gif");
fc94331997-10-25Per Hedbor 
2b658c2000-02-07Per Hedbor  Stdio.File f;
1c78232000-03-13Per Hedbor  if(f = lopen("roxen-images/"+from+".gif", "r"))
06026c1999-10-19Henrik Grubbström (Grubba)  return (["file":f, "type":"image/gif"]);
1c78232000-03-13Per Hedbor  if(f = lopen("roxen-images/"+from+".jpg", "r"))
06026c1999-10-19Henrik Grubbström (Grubba)  return (["file":f, "type":"image/jpeg"]);
1c78232000-03-13Per Hedbor  if(f = lopen("roxen-images/"+from+".png", "r"))
2b658c2000-02-07Per Hedbor  return (["file":f, "type":"image/png"]);
1c78232000-03-13Per Hedbor  if(f = lopen("roxen-images/"+from+".xcf", "r"))
2b658c2000-02-07Per Hedbor  return (["file":f, "type":"image/x-gimp-image"]); // File not found. return 0;
14179b1997-01-29Per Hedbor } mapping (mixed:function|int) locks = ([]); #ifdef THREADS
e5bad21998-02-10Per Hedbor // import Thread;
e6aff01997-05-25Henrik Grubbström (Grubba) 
55a89e1997-09-14Per Hedbor mapping locked = ([]), thread_safe = ([]);
e351dd1999-11-29Per Hedbor mixed _lock(object|function f)
14179b1997-01-29Per Hedbor { object key;
1fab6f1997-09-03Henrik Grubbström (Grubba)  function|int l;
55a89e1997-09-14Per Hedbor 
1fab6f1997-09-03Henrik Grubbström (Grubba)  if (functionp(f)) { f = function_object(f); }
55a89e1997-09-14Per Hedbor  if (l = locks[f]) { if (l != -1) {
1fab6f1997-09-03Henrik Grubbström (Grubba)  // Allow recursive locks.
beb1f21998-05-23Mattias Wingstedt  catch{
10c7e11999-12-28Martin Nilsson  //werror("lock %O\n", f);
55a89e1997-09-14Per Hedbor  locked[f]++;
1fab6f1997-09-03Henrik Grubbström (Grubba)  key = l();
beb1f21998-05-23Mattias Wingstedt  };
55a89e1997-09-14Per Hedbor  } else thread_safe[f]++;
1fab6f1997-09-03Henrik Grubbström (Grubba)  } else if (f->thread_safe) { locks[f]=-1;
55a89e1997-09-14Per Hedbor  thread_safe[f]++;
14179b1997-01-29Per Hedbor  } else {
55a89e1997-09-14Per Hedbor  if (!locks[f]) {
1fab6f1997-09-03Henrik Grubbström (Grubba)  // Needed to avoid race-condition.
e5bad21998-02-10Per Hedbor  l = Thread.Mutex()->lock;
1fab6f1997-09-03Henrik Grubbström (Grubba)  if (!locks[f]) { locks[f]=l; }
14179b1997-01-29Per Hedbor  }
10c7e11999-12-28Martin Nilsson  //werror("lock %O\n", f);
55a89e1997-09-14Per Hedbor  locked[f]++;
1fab6f1997-09-03Henrik Grubbström (Grubba)  key = l();
b1fca01996-11-12Per Hedbor  }
14179b1997-01-29Per Hedbor  return key;
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor #define LOCK(X) key=_lock(X)
d7b0871997-08-31Per Hedbor #define UNLOCK() do{key=0;}while(0)
14179b1997-01-29Per Hedbor #else #define LOCK(X)
c95bd51998-01-30Henrik Grubbström (Grubba) #define UNLOCK()
14179b1997-01-29Per Hedbor #endif
a1334f1998-02-20Mirar (Pontus Hagland) string examine_return_mapping(mapping m) { string res; if (m->extra_heads) m->extra_heads=mkmapping(Array.map(indices(m->extra_heads), lower_case), values(m->extra_heads)); else m->extra_heads=([]); switch (m->error||200) { case 302: // redirect
10c7e11999-12-28Martin Nilsson  if (m->extra_heads &&
a1334f1998-02-20Mirar (Pontus Hagland)  (m->extra_heads->location))
1a89f42000-08-14Martin Stjernholm  res = sprintf("Returned redirect to %s ", m->extra_heads->location);
a1334f1998-02-20Mirar (Pontus Hagland)  else
1a89f42000-08-14Martin Stjernholm  res = "Returned redirect, but no location header. ";
a1334f1998-02-20Mirar (Pontus Hagland)  break; case 401: if (m->extra_heads["www-authenticate"])
1a89f42000-08-14Martin Stjernholm  res = sprintf("Returned authentication failed: %s ",
67f60e2000-07-09Martin Nilsson  m->extra_heads["www-authenticate"]);
a1334f1998-02-20Mirar (Pontus Hagland)  else
1a89f42000-08-14Martin Stjernholm  res = "Returned authentication failed. ";
a1334f1998-02-20Mirar (Pontus Hagland)  break; case 200:
1a89f42000-08-14Martin Stjernholm  res = "Returned ok. ";
a1334f1998-02-20Mirar (Pontus Hagland)  break;
a8f1b32000-01-31Per Hedbor 
a1334f1998-02-20Mirar (Pontus Hagland)  default:
1a89f42000-08-14Martin Stjernholm  res = sprintf("Returned %d. ", m->error);
a1334f1998-02-20Mirar (Pontus Hagland)  } if (!zero_type(m->len)) if (m->len<0)
434bac2000-07-14Andreas Lange  res += "No data ";
a1334f1998-02-20Mirar (Pontus Hagland)  else
434bac2000-07-14Andreas Lange  res += sprintf("%d bytes ", m->len);
a1334f1998-02-20Mirar (Pontus Hagland)  else if (stringp(m->data))
434bac2000-07-14Andreas Lange  res += sprintf("%d bytes ", strlen(m->data));
a1334f1998-02-20Mirar (Pontus Hagland)  else if (objectp(m->file)) if (catch { array a=m->file->stat();
434bac2000-07-14Andreas Lange  res += sprintf("%d bytes ", a[1]-m->file->tell());
b461641998-10-11Henrik Grubbström (Grubba)  })
1a89f42000-08-14Martin Stjernholm  res += "? bytes ";
a1334f1998-02-20Mirar (Pontus Hagland) 
1a89f42000-08-14Martin Stjernholm  if (m->data) res += "(static)";
434bac2000-07-14Andreas Lange  else if (m->file) res += "(open file)";
a1334f1998-02-20Mirar (Pontus Hagland) 
b461641998-10-11Henrik Grubbström (Grubba)  if (stringp(m->extra_heads["http-content-type"]) || stringp(m->type)) {
1a89f42000-08-14Martin Stjernholm  res += sprintf(" of %s", m->type);
b461641998-10-11Henrik Grubbström (Grubba)  }
a1334f1998-02-20Mirar (Pontus Hagland) 
67f60e2000-07-09Martin Nilsson  res+="<br />";
a1334f1998-02-20Mirar (Pontus Hagland)  return res; }
c5e0961999-10-04Per Hedbor 
cd92872000-08-15Johan Sundström mapping|int(-1..0) low_get_file(RequestID id, int|void no_magic) //! The function that actually tries to find the data requested. All //! modules except last and filter type modules are mapped, in order, //! and the first one that returns a suitable response is used. If //! `no_magic' is set to one, the internal magic roxen images and the //! <ref>find_internal()</ref> callbacks will be ignored. //! //! The return values 0 (no such file) and -1 (the data is a //! directory) are only returned when `no_magic' was set to 1; //! otherwise a result mapping is always generated.
14179b1997-01-29Per Hedbor { #ifdef MODULE_LEVEL_SECURITY int slevel; #endif #ifdef THREADS object key; #endif
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Request for %s", id->not_query), 0);
14179b1997-01-29Per Hedbor  string file=id->not_query; string loc; function funp; mixed tmp, tmp2;
cd92872000-08-15Johan Sundström  mapping|object(Stdio.File)|int fid;
14179b1997-01-29Per Hedbor  if(!no_magic) {
41b77c1999-07-15David Hedbor #ifndef NO_INTERNAL_HACK
fd93022000-05-05Martin Nilsson  // Find internal-foo-bar images
41b77c1999-07-15David Hedbor  // min length == 17 (/internal-roxen-?..) // This will save some time indeed.
fd93022000-05-05Martin Nilsson  string type;
67f60e2000-07-09Martin Nilsson  if(sizeof(file) > 17 && #ifdef OLD_RXML_COMPAT (file[0] == '/') &&
cd92872000-08-15Johan Sundström  sscanf(file, "%*s/internal-%s-%[^/]", type, loc) == 3
67f60e2000-07-09Martin Nilsson #else
cd92872000-08-15Johan Sundström  sscanf(file, "/internal-%s-%[^/]", type, loc) == 2
67f60e2000-07-09Martin Nilsson #endif
cd92872000-08-15Johan Sundström  ) {
41b77c1999-07-15David Hedbor  switch(type) {
fd93022000-05-05Martin Nilsson  case "roxen":
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Magic internal gopher image");
fd93022000-05-05Martin Nilsson  return internal_roxen_image(loc);
41b77c1999-07-15David Hedbor  case "gopher":
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Magic internal roxen image");
14179b1997-01-29Per Hedbor  return internal_gopher_image(loc);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  } #endif
10c7e11999-12-28Martin Nilsson 
fd93022000-05-05Martin Nilsson  // Locate internal location resources.
10c7e11999-12-28Martin Nilsson  if(!search(file, QUERY(InternalLoc)))
5839c31999-01-22Marcus Comstedt  {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Magic internal module location", 0);
e351dd1999-11-29Per Hedbor  RoxenModule module;
5839c31999-01-22Marcus Comstedt  string name, rest; function find_internal; if(2==sscanf(file[strlen(QUERY(InternalLoc))..], "%s/%s", name, rest) && (module = find_module(replace(name, "!", "#"))) && (find_internal = module->find_internal)) { #ifdef MODULE_LEVEL_SECURITY if(tmp2 = check_security(find_internal, id, slevel)) if(intp(tmp2)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission to access module denied.");
5839c31999-01-22Marcus Comstedt  find_internal = 0; } else { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Request denied.");
5839c31999-01-22Marcus Comstedt  return tmp2; } #endif
41b77c1999-07-15David Hedbor  if(find_internal)
5839c31999-01-22Marcus Comstedt  {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Calling find_internal()...", find_internal);
5839c31999-01-22Marcus Comstedt  LOCK(find_internal); fid=find_internal( rest, id ); UNLOCK();
434bac2000-07-14Andreas Lange  TRACE_LEAVE(sprintf("find_internal has returned %O", fid));
5839c31999-01-22Marcus Comstedt  if(fid) { if(mappingp(fid)) { TRACE_LEAVE(""); TRACE_LEAVE(examine_return_mapping(fid)); return fid; } else { #ifdef MODULE_LEVEL_SECURITY int oslevel = slevel; slevel = misc_cache[ find_internal ][1]; // misc_cache from // check_security id->misc->seclevel = slevel; #endif if(objectp(fid))
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned open filedescriptor. "
5839c31999-01-22Marcus Comstedt #ifdef MODULE_LEVEL_SECURITY +(slevel != oslevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
5839c31999-01-22Marcus Comstedt #endif
67f60e2000-07-09Martin Nilsson  );
5839c31999-01-22Marcus Comstedt  else
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned directory indicator."
5839c31999-01-22Marcus Comstedt #ifdef MODULE_LEVEL_SECURITY +(oslevel != slevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
5839c31999-01-22Marcus Comstedt #endif ); } } else TRACE_LEAVE(""); } else TRACE_LEAVE(""); } else TRACE_LEAVE(""); }
14179b1997-01-29Per Hedbor  } // Well, this just _might_ be somewhat over-optimized, since it is
10c7e11999-12-28Martin Nilsson  // quite unreadable, but, you cannot win them all..
5839c31999-01-22Marcus Comstedt  if(!fid) {
14179b1997-01-29Per Hedbor #ifdef URL_MODULES
f128901997-08-15Henrik Grubbström (Grubba)  // Map URL-modules
26f44e2000-08-13Per Hedbor  foreach(url_module_cache||url_modules(id), funp)
41d0f91998-02-20Per Hedbor  {
5839c31999-01-22Marcus Comstedt  LOCK(funp);
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
5839c31999-01-22Marcus Comstedt  tmp=funp( id, file ); UNLOCK();
10c7e11999-12-28Martin Nilsson  if(mappingp(tmp))
5839c31999-01-22Marcus Comstedt  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
5839c31999-01-22Marcus Comstedt  return tmp; } if(objectp( tmp )) { array err;
a8f1b32000-01-31Per Hedbor 
5839c31999-01-22Marcus Comstedt  nest ++; err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->low_get_file( tmp, no_magic ); else {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Too deep recursion");
5839c31999-01-22Marcus Comstedt  error("Too deep recursion in roxen::get_file() while mapping " +file+".\n"); } }; nest = 0; if(err) throw(err); TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
5839c31999-01-22Marcus Comstedt  return tmp; }
41d0f91998-02-20Per Hedbor  TRACE_LEAVE(""); }
14179b1997-01-29Per Hedbor #endif
c5e0961999-10-04Per Hedbor 
26f44e2000-08-13Per Hedbor  foreach(location_module_cache||location_modules(id), tmp)
14179b1997-01-29Per Hedbor  {
5839c31999-01-22Marcus Comstedt  loc = tmp[0];
41b77c1999-07-15David Hedbor  if(!search(file, loc))
5839c31999-01-22Marcus Comstedt  {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
df8d711998-02-27Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  if(tmp2 = check_security(tmp[1], id, slevel)) if(intp(tmp2)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission to access module denied.");
5839c31999-01-22Marcus Comstedt  continue; } else { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Request denied.");
5839c31999-01-22Marcus Comstedt  return tmp2; }
14179b1997-01-29Per Hedbor #endif
434bac2000-07-14Andreas Lange  TRACE_ENTER("Calling find_file()...", 0);
5839c31999-01-22Marcus Comstedt  LOCK(tmp[1]); fid=tmp[1]( file[ strlen(loc) .. ] + id->extra_extension, id); UNLOCK();
b8b1072000-03-24Per Hedbor  TRACE_LEAVE("");
5839c31999-01-22Marcus Comstedt  if(fid)
14179b1997-01-29Per Hedbor  {
5839c31999-01-22Marcus Comstedt  id->virtfile = loc;
a8f1b32000-01-31Per Hedbor 
5839c31999-01-22Marcus Comstedt  if(mappingp(fid)) { TRACE_LEAVE(""); TRACE_LEAVE(examine_return_mapping(fid)); return fid; } else {
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  int oslevel = slevel; slevel = misc_cache[ tmp[1] ][1]; // misc_cache from // check_security id->misc->seclevel = slevel;
14179b1997-01-29Per Hedbor #endif
5839c31999-01-22Marcus Comstedt  if(objectp(fid))
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned open filedescriptor."
41d0f91998-02-20Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  +(slevel != oslevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
41d0f91998-02-20Per Hedbor #endif
a8f1b32000-01-31Per Hedbor 
67f60e2000-07-09Martin Nilsson  );
5839c31999-01-22Marcus Comstedt  else
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned directory indicator."
41d0f91998-02-20Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  +(oslevel != slevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
41d0f91998-02-20Per Hedbor #endif
5839c31999-01-22Marcus Comstedt  ); break; } } else TRACE_LEAVE("");
41b77c1999-07-15David Hedbor  } else if(strlen(loc)-1==strlen(file) && file+"/" == loc) {
10c7e11999-12-28Martin Nilsson  // This one is here to allow accesses to /local, even if
5839c31999-01-22Marcus Comstedt  // the mountpoint is /local/. It will slow things down, but...
67f60e2000-07-09Martin Nilsson 
434bac2000-07-14Andreas Lange  TRACE_ENTER("Automatic redirect to location_module.", tmp[1]); TRACE_LEAVE("Returning data");
a8f1b32000-01-31Per Hedbor 
41b77c1999-07-15David Hedbor  // Keep query (if any).
fd93022000-05-05Martin Nilsson  // FIXME: Should probably keep config <foo>
dfe0362000-03-19Martin Nilsson  string new_query = Roxen.http_encode_string(id->not_query) + "/" +
41b77c1999-07-15David Hedbor  (id->query?("?"+id->query):"");
fd93022000-05-05Martin Nilsson  new_query=Roxen.add_pre_state(new_query, id->prestate);
a8f1b32000-01-31Per Hedbor 
dfe0362000-03-19Martin Nilsson  return Roxen.http_redirect(new_query, id);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  } }
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(fid == -1) {
41d0f91998-02-20Per Hedbor  if(no_magic) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("No magic requested. Returning -1.");
41d0f91998-02-20Per Hedbor  return -1; }
14179b1997-01-29Per Hedbor  if(dir_module) { LOCK(dir_module);
434bac2000-07-14Andreas Lange  TRACE_ENTER("Directory module", dir_module);
14179b1997-01-29Per Hedbor  fid = dir_module->parse_directory(id); UNLOCK(); } else
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("No directory module. Returning 'no such file'");
14179b1997-01-29Per Hedbor  return 0;
41d0f91998-02-20Per Hedbor  }
10c7e11999-12-28Martin Nilsson  if(mappingp(fid))
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
41d0f91998-02-20Per Hedbor  return (mapping)fid; }
14179b1997-01-29Per Hedbor  }
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  // Map the file extensions, but only if there is a file...
41b77c1999-07-15David Hedbor  if(objectp(fid) &&
dfe0362000-03-19Martin Nilsson  (tmp = file_extension_modules(loc = Roxen.extension(id->not_query, id), id))) {
14179b1997-01-29Per Hedbor  foreach(tmp, funp) {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Extension module [%s] ", loc), funp);
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY if(tmp=check_security(funp, id, slevel)) if(intp(tmp)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission to access module denied.");
14179b1997-01-29Per Hedbor  continue; } else
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission denied");
14179b1997-01-29Per Hedbor  return tmp;
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor #endif LOCK(funp); tmp=funp(fid, loc, id); UNLOCK(); if(tmp) { if(!objectp(tmp))
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
14179b1997-01-29Per Hedbor  return tmp;
41d0f91998-02-20Per Hedbor  }
cd92872000-08-15Johan Sundström  if(fid && tmp != fid)
41b77c1999-07-15David Hedbor  destruct(fid);
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned new open file");
14179b1997-01-29Per Hedbor  fid = tmp; break;
41d0f91998-02-20Per Hedbor  } else TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  }
41b77c1999-07-15David Hedbor  }
fd93022000-05-05Martin Nilsson 
14179b1997-01-29Per Hedbor  if(objectp(fid)) {
41b77c1999-07-15David Hedbor  if(stringp(id->extension)) {
14179b1997-01-29Per Hedbor  id->not_query += id->extension;
dfe0362000-03-19Martin Nilsson  loc = Roxen.extension(id->not_query, id);
41b77c1999-07-15David Hedbor  }
434bac2000-07-14Andreas Lange  TRACE_ENTER("Content-type mapping module", types_module);
41b77c1999-07-15David Hedbor  tmp=type_from_filename(id->not_query, 1, loc);
3d94582000-07-31Martin Nilsson  TRACE_LEAVE(tmp?sprintf("Returned type %s %s.", tmp[0], tmp[1]||"")
434bac2000-07-14Andreas Lange  : "Missing type.");
14179b1997-01-29Per Hedbor  if(tmp)
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  return ([ "file":fid, "type":tmp[0], "encoding":tmp[1] ]);
10c7e11999-12-28Martin Nilsson  }
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  return ([ "file":fid, ]); }
41d0f91998-02-20Per Hedbor  if(!fid)
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'no such file'.");
41d0f91998-02-20Per Hedbor  else
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
14179b1997-01-29Per Hedbor  return fid; }
e351dd1999-11-29Per Hedbor mixed handle_request( RequestID id )
c7a5f01999-02-16Per Hedbor { function funp; mixed file;
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request()");
26f44e2000-08-13Per Hedbor  foreach(first_module_cache||first_modules(id), funp)
c7a5f01999-02-16Per Hedbor  {
10c7e11999-12-28Martin Nilsson  if(file = funp( id ))
c7a5f01999-02-16Per Hedbor  break;
cfda381999-03-28Henrik Grubbström (Grubba)  if(id->conf != this_object()) {
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request(): Redirected (2)");
c7a5f01999-02-16Per Hedbor  return id->conf->handle_request(id);
cfda381999-03-28Henrik Grubbström (Grubba)  }
c7a5f01999-02-16Per Hedbor  }
fd8b151999-05-19David Hedbor  if(!mappingp(file) && !mappingp(file = get_file(id)))
c7a5f01999-02-16Per Hedbor  { mixed ret;
26f44e2000-08-13Per Hedbor  foreach(last_module_cache||last_modules(id), funp) if(ret = funp(id)) break;
cfda381999-03-28Henrik Grubbström (Grubba)  if (ret == 1) {
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request(): Recurse");
c7a5f01999-02-16Per Hedbor  return handle_request(id);
cfda381999-03-28Henrik Grubbström (Grubba)  }
c7a5f01999-02-16Per Hedbor  file = ret; }
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request(): Done");
c7a5f01999-02-16Per Hedbor  return file; }
fd93022000-05-05Martin Nilsson mapping get_file(RequestID id, int|void no_magic, int|void internal_get)
cd92872000-08-15Johan Sundström //! Return a result mapping for the id object at hand, mapping all //! modules, including the filter modules. This function is mostly a //! wrapper for <ref>low_get_file()</ref>.
14179b1997-01-29Per Hedbor {
576c112000-03-07Martin Stjernholm  int orig_internal_get = id->misc->internal_get; id->misc->internal_get = internal_get;
fd93022000-05-05Martin Nilsson  mapping|int res; mapping res2;
14179b1997-01-29Per Hedbor  function tmp; res = low_get_file(id, no_magic);
fd93022000-05-05Martin Nilsson 
14179b1997-01-29Per Hedbor  // finally map all filter type modules. // Filter modules are like TYPE_LAST modules, but they get called // for _all_ files.
26f44e2000-08-13Per Hedbor  foreach(filter_module_cache||filter_modules(id), tmp)
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Filter module", tmp);
14179b1997-01-29Per Hedbor  if(res2=tmp(res,id)) { if(res && res->file && (res2->file != res->file)) destruct(res->file);
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Rewrote result.");
14179b1997-01-29Per Hedbor  res=res2;
41d0f91998-02-20Per Hedbor  } else TRACE_LEAVE(""); }
576c112000-03-07Martin Stjernholm  id->misc->internal_get = orig_internal_get;
14179b1997-01-29Per Hedbor  return res; }
e927de2000-05-06Martin Nilsson public array(string) find_dir(string file, RequestID id, void|int(0..1) verbose)
14179b1997-01-29Per Hedbor {
fd93022000-05-05Martin Nilsson  array dir;
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("List directory %O.", file), 0);
10c7e11999-12-28Martin Nilsson 
1935351997-04-28Henrik Grubbström (Grubba)  if(file[0] != '/') file = "/" + file;
f128901997-08-15Henrik Grubbström (Grubba) #ifdef URL_MODULES
fc0e5d1997-08-26Henrik Grubbström (Grubba) #ifdef THREADS object key; #endif
f128901997-08-15Henrik Grubbström (Grubba)  // Map URL-modules foreach(url_modules(id), function funp) { string of = id->not_query; id->not_query = file; LOCK(funp);
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
fd93022000-05-05Martin Nilsson  void|mapping|object remap=funp( id, file );
f128901997-08-15Henrik Grubbström (Grubba)  UNLOCK();
fd93022000-05-05Martin Nilsson  if(mappingp( remap ))
f128901997-08-15Henrik Grubbström (Grubba)  { id->not_query=of;
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'No thanks'.");
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  return 0; }
fd93022000-05-05Martin Nilsson  if(objectp( remap ))
f128901997-08-15Henrik Grubbström (Grubba)  { array err; nest ++;
10c7e11999-12-28Martin Nilsson 
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Recursing");
f128901997-08-15Henrik Grubbström (Grubba)  file = id->not_query; err = catch { if( nest < 20 )
fd93022000-05-05Martin Nilsson  dir = (id->conf || this_object())->find_dir( file, id );
f128901997-08-15Henrik Grubbström (Grubba)  else error("Too deep recursion in roxen::find_dir() while mapping " +file+".\n"); }; nest = 0;
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  if(err) throw(err);
fd93022000-05-05Martin Nilsson  return dir;
f128901997-08-15Henrik Grubbström (Grubba)  } id->not_query=of; }
a86c6c1997-09-22Henrik Grubbström (Grubba) #endif /* URL_MODULES */
f128901997-08-15Henrik Grubbström (Grubba) 
e927de2000-05-06Martin Nilsson  array(string) | mapping d; array(string) locks=({}); object mod; string loc;
fd93022000-05-05Martin Nilsson  foreach(location_modules(id), array tmp)
14179b1997-01-29Per Hedbor  { loc = tmp[0];
a476711997-10-20Henrik Grubbström (Grubba)  if(!search(file, loc)) { /* file == loc + subpath */
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
a78a591997-04-28Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY
41d0f91998-02-20Per Hedbor  if(check_security(tmp[1], id)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission denied");
41d0f91998-02-20Per Hedbor  continue; }
a78a591997-04-28Henrik Grubbström (Grubba) #endif
e927de2000-05-06Martin Nilsson  mod=function_object(tmp[1]); if(d=mod->find_dir(file[strlen(loc)..], id))
41d0f91998-02-20Per Hedbor  {
29a8071998-08-21David Hedbor  if(mappingp(d)) {
10c7e11999-12-28Martin Nilsson  if(d->files) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Got exclusive directory."); TRACE_LEAVE(sprintf("Returning list of %d files.", sizeof(d->files)));
fd93022000-05-05Martin Nilsson  return d->files;
29a8071998-08-21David Hedbor  } else TRACE_LEAVE(""); } else {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Got files.");
e927de2000-05-06Martin Nilsson  if(!dir) dir=({ });
29a8071998-08-21David Hedbor  dir |= d; }
e927de2000-05-06Martin Nilsson  } else { if(verbose && mod->list_lock_files) locks |= mod->list_lock_files();
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
e927de2000-05-06Martin Nilsson  }
a476711997-10-20Henrik Grubbström (Grubba)  } else if((search(loc, file)==0) && (loc[strlen(file)-1]=='/') && (loc[0]==loc[-1]) && (loc[-1]=='/') &&
6c67c81998-02-28Johan Schön  (function_object(tmp[1])->stat_file(".", id))) {
a476711997-10-20Henrik Grubbström (Grubba)  /* loc == file + "/" + subpath + "/"
24fa081998-02-28Henrik Grubbström (Grubba)  * and stat_file(".") returns non-zero.
a476711997-10-20Henrik Grubbström (Grubba)  */
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
a476711997-10-20Henrik Grubbström (Grubba)  loc=loc[strlen(file)..]; sscanf(loc, "%s/", loc);
df40452000-06-19Henrik Grubbström (Grubba)  if (dir) { dir |= ({ loc }); } else { dir = ({ loc }); }
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Added module mountpoint.");
14179b1997-01-29Per Hedbor  } }
e927de2000-05-06Martin Nilsson  if(!dir) return verbose ? ({0})+locks : ([])[0];
14179b1997-01-29Per Hedbor  if(sizeof(dir))
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_LEAVE(sprintf("Returning list of %d files.", sizeof(dir)));
14179b1997-01-29Per Hedbor  return dir;
10c7e11999-12-28Martin Nilsson  }
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning 'No such directory'.");
fd93022000-05-05Martin Nilsson  return 0;
14179b1997-01-29Per Hedbor }
10c7e11999-12-28Martin Nilsson // Stat a virtual file.
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor public array(int) stat_file(string file, RequestID id)
14179b1997-01-29Per Hedbor { string loc; array s, tmp;
c5e0961999-10-04Per Hedbor #ifdef THREADS object key; #endif
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Stat file %O.", file), 0);
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  file=replace(file, "//", "/"); // "//" is really "/" here...
f128901997-08-15Henrik Grubbström (Grubba)  #ifdef URL_MODULES // Map URL-modules foreach(url_modules(id), function funp) { string of = id->not_query; id->not_query = file;
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
f128901997-08-15Henrik Grubbström (Grubba)  LOCK(funp); tmp=funp( id, file ); UNLOCK(); if(mappingp( tmp )) { id->not_query = of;
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'No thanks'.");
f128901997-08-15Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) { file = id->not_query; array err; nest ++;
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Recursing");
f128901997-08-15Henrik Grubbström (Grubba)  err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->stat_file( file, id ); else error("Too deep recursion in roxen::stat_file() while mapping " +file+".\n"); }; nest = 0; if(err) throw(err);
8fd51f1998-03-01Per Hedbor  TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
f128901997-08-15Henrik Grubbström (Grubba)  return tmp; }
8fd51f1998-03-01Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  id->not_query = of; } #endif
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  // Map location-modules. foreach(location_modules(id), tmp) { loc = tmp[0]; if((file == loc) || ((file+"/")==loc))
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]); TRACE_LEAVE("Exact match.");
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
223fd12000-01-27Johan Sundström  return ({ 0775, -3, 0, 0, 0, 0, 0 });
41d0f91998-02-20Per Hedbor  }
10c7e11999-12-28Martin Nilsson  if(!search(file, loc))
14179b1997-01-29Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
a78a591997-04-28Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY
41d0f91998-02-20Per Hedbor  if(check_security(tmp[1], id)) {
8fd51f1998-03-01Per Hedbor  TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission denied");
41d0f91998-02-20Per Hedbor  continue; }
a78a591997-04-28Henrik Grubbström (Grubba) #endif
14179b1997-01-29Per Hedbor  if(s=function_object(tmp[1])->stat_file(file[strlen(loc)..], id))
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Stat ok.");
14179b1997-01-29Per Hedbor  return s;
41d0f91998-02-20Per Hedbor  } TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  } }
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'no such file'.");
14179b1997-01-29Per Hedbor }
e8790b1998-02-19Per Hedbor class StringFile { string data; int offset;
ec91501999-11-23Per Hedbor  string _sprintf() { return "StringFile("+strlen(data)+","+offset+")"; }
e8790b1998-02-19Per Hedbor  string read(int nbytes) {
6d93981998-11-30Per Hedbor  if(!nbytes) { offset = strlen(data); return data; }
41d0f91998-02-20Per Hedbor  string d = data[offset..offset+nbytes-1];
e8790b1998-02-19Per Hedbor  offset += strlen(d); return d; } void write(mixed ... args) {
3bb38c2000-01-20Martin Bähr  throw( ({ "File not open for write\n", backtrace() }) );
e8790b1998-02-19Per Hedbor  } void seek(int to) { offset = to; } void create(string d) { data = d; }
41d0f91998-02-20Per Hedbor 
e8790b1998-02-19Per Hedbor } // this is not as trivial as it sounds. Consider gtext. :-)
484ec92000-06-23Martin Stjernholm public array open_file(string fname, string mode, RequestID id, void|int internal_get)
e8790b1998-02-19Per Hedbor { object oc = id->conf; string oq = id->not_query; function funp;
3a4b9a1999-12-27Martin Nilsson  mapping|int(0..1) file;
cd7ea41998-12-14Peter Bortas  id->not_query = fname;
c7a5f01999-02-16Per Hedbor 
e8790b1998-02-19Per Hedbor  foreach(oc->first_modules(), funp)
10c7e11999-12-28Martin Nilsson  if(file = funp( id ))
e8790b1998-02-19Per Hedbor  break;
10c7e11999-12-28Martin Nilsson  else if(id->conf != oc)
e8790b1998-02-19Per Hedbor  {
484ec92000-06-23Martin Stjernholm  return open_file(fname, mode,id, internal_get);
e8790b1998-02-19Per Hedbor  } fname = id->not_query; if(search(mode, "R")!=-1) // raw (as in not parsed..) { string f; mode -= "R"; if(f = real_file(fname, id))
41d0f91998-02-20Per Hedbor  {
9bb8131998-09-12Per Hedbor  // werror("opening "+fname+" in raw mode.\n");
e8790b1998-02-19Per Hedbor  return ({ open(f, mode), ([]) });
41d0f91998-02-20Per Hedbor  }
2380831998-02-22Per Hedbor // return ({ 0, (["error":302]) });
e8790b1998-02-19Per Hedbor  } if(mode=="r") { if(!file) {
484ec92000-06-23Martin Stjernholm  file = oc->get_file( id, 0, internal_get );
f920ce1998-10-02Henrik Grubbström (Grubba)  if(!file) {
41d0f91998-02-20Per Hedbor  foreach(oc->last_modules(), funp) if(file = funp( id ))
e8790b1998-02-19Per Hedbor  break;
f920ce1998-10-02Henrik Grubbström (Grubba)  if (file == 1) { // Recurse.
484ec92000-06-23Martin Stjernholm  return open_file(id->not_query, mode, id, internal_get);
f920ce1998-10-02Henrik Grubbström (Grubba)  } }
e8790b1998-02-19Per Hedbor  } if(!mappingp(file)) { if(id->misc->error_code)
dfe0362000-03-19Martin Nilsson  file = Roxen.http_low_answer(id->misc->error_code, "Failed" );
2380831998-02-22Per Hedbor  else if(id->method!="GET"&&id->method != "HEAD"&&id->method!="POST")
dfe0362000-03-19Martin Nilsson  file = Roxen.http_low_answer(501, "Not implemented.");
576c112000-03-07Martin Stjernholm  else {
dfe0362000-03-19Martin Nilsson  file = Roxen.http_low_answer(404,
52e0822000-03-07Henrik Grubbström (Grubba)  parse_rxml(
576c112000-03-07Martin Stjernholm #ifdef OLD_RXML_COMPAT
52e0822000-03-07Henrik Grubbström (Grubba)  replace(query("ZNoSuchFile"), ({ "$File", "$Me" }), ({ "&page.virtfile;",
ee80572000-03-08Martin Nilsson  "&roxen.server;"
52e0822000-03-07Henrik Grubbström (Grubba)  })),
576c112000-03-07Martin Stjernholm #else
52e0822000-03-07Henrik Grubbström (Grubba)  query("ZNoSuchFile"),
576c112000-03-07Martin Stjernholm #endif
52e0822000-03-07Henrik Grubbström (Grubba)  id));
576c112000-03-07Martin Stjernholm  }
e8790b1998-02-19Per Hedbor  id->not_query = oq;
10c7e11999-12-28Martin Nilsson 
e8790b1998-02-19Per Hedbor  return ({ 0, file }); }
10c7e11999-12-28Martin Nilsson  if( file->data )
e8790b1998-02-19Per Hedbor  { file->file = StringFile(file->data); m_delete(file, "data");
10c7e11999-12-28Martin Nilsson  }
e8790b1998-02-19Per Hedbor  id->not_query = oq; return ({ file->file, file }); } id->not_query = oq;
23414a2000-07-21Andreas Lange  return ({ 0, (["error":501, "data":"Not implemented." ]) });
e8790b1998-02-19Per Hedbor }
e351dd1999-11-29Per Hedbor public mapping(string:array(mixed)) find_dir_stat(string file, RequestID id)
a86c6c1997-09-22Henrik Grubbström (Grubba) { string loc;
a476711997-10-20Henrik Grubbström (Grubba)  mapping(string:array(mixed)) dir = ([]); mixed d, tmp;
a86c6c1997-09-22Henrik Grubbström (Grubba) 
c7a5f01999-02-16Per Hedbor 
a86c6c1997-09-22Henrik Grubbström (Grubba)  file=replace(file, "//", "/");
10c7e11999-12-28Martin Nilsson 
a86c6c1997-09-22Henrik Grubbström (Grubba)  if(file[0] != '/') file = "/" + file;
ae60b61998-05-23Henrik Grubbström (Grubba)  // FIXME: Should I append a "/" to file if missing?
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Request for directory and stat's \"%s\".", file), 0);
ae60b61998-05-23Henrik Grubbström (Grubba) 
a86c6c1997-09-22Henrik Grubbström (Grubba) #ifdef URL_MODULES #ifdef THREADS object key; #endif // Map URL-modules foreach(url_modules(id), function funp) { string of = id->not_query; id->not_query = file; LOCK(funp);
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
a86c6c1997-09-22Henrik Grubbström (Grubba)  tmp=funp( id, file ); UNLOCK(); if(mappingp( tmp )) { id->not_query=of;
3510fb1997-11-09Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
10c7e11999-12-28Martin Nilsson  werror("conf->find_dir_stat(\"%s\"): url_module returned mapping:%O\n", file, tmp);
3510fb1997-11-09Henrik Grubbström (Grubba) #endif /* MODULE_DEBUG */
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned mapping."+sprintf("%O", tmp));
07014c1999-05-24Per Hedbor  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) { array err; nest ++;
10c7e11999-12-28Martin Nilsson 
a86c6c1997-09-22Henrik Grubbström (Grubba)  file = id->not_query; err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->find_dir_stat( file, id );
ae60b61998-05-23Henrik Grubbström (Grubba)  else {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Too deep recursion");
a86c6c1997-09-22Henrik Grubbström (Grubba)  error("Too deep recursion in roxen::find_dir_stat() while mapping " +file+".\n");
ae60b61998-05-23Henrik Grubbström (Grubba)  }
a86c6c1997-09-22Henrik Grubbström (Grubba)  }; nest = 0; if(err) throw(err);
3510fb1997-11-09Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
10c7e11999-12-28Martin Nilsson  werror("conf->find_dir_stat(\"%s\"): url_module returned object:\n", file);
3510fb1997-11-09Henrik Grubbström (Grubba) #endif /* MODULE_DEBUG */
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned object."); TRACE_LEAVE("Returning it.");
ae60b61998-05-23Henrik Grubbström (Grubba)  return tmp; // FIXME: Return 0 instead?
a86c6c1997-09-22Henrik Grubbström (Grubba)  } id->not_query=of;
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  } #endif /* URL_MODULES */ foreach(location_modules(id), tmp) { loc = tmp[0];
a476711997-10-20Henrik Grubbström (Grubba) 
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), 0);
a476711997-10-20Henrik Grubbström (Grubba)  /* Note that only new entries are added. */
a86c6c1997-09-22Henrik Grubbström (Grubba)  if(!search(file, loc)) {
a476711997-10-20Henrik Grubbström (Grubba)  /* file == loc + subpath */
a86c6c1997-09-22Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY if(check_security(tmp[1], id)) continue; #endif
e351dd1999-11-29Per Hedbor  RoxenModule c = function_object(tmp[1]);
a86c6c1997-09-22Henrik Grubbström (Grubba)  string f = file[strlen(loc)..]; if (c->find_dir_stat) {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Has find_dir_stat().", 0);
a86c6c1997-09-22Henrik Grubbström (Grubba)  if (d = c->find_dir_stat(f, id)) {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Returned mapping."+sprintf("%O", d), c);
a476711997-10-20Henrik Grubbström (Grubba)  dir = d | dir;
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  } else if(d = c->find_dir(f, id)) {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Returned array.", 0);
10c7e11999-12-28Martin Nilsson  dir = mkmapping(d, Array.map(d, lambda(string fn)
e351dd1999-11-29Per Hedbor  { return c->stat_file(f + fn, id); })) | dir;
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
a476711997-10-20Henrik Grubbström (Grubba)  } else if(search(loc, file)==0 && loc[strlen(file)-1]=='/' && (loc[0]==loc[-1]) && loc[-1]=='/' &&
8935ad1998-03-30Johan Schön  (function_object(tmp[1])->stat_file(".", id))) {
a476711997-10-20Henrik Grubbström (Grubba)  /* loc == file + "/" + subpath + "/"
8935ad1998-03-30Johan Schön  * and stat_file(".") returns non-zero.
a476711997-10-20Henrik Grubbström (Grubba)  */
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("The file %O is on the path to the mountpoint %O.",
67f60e2000-07-09Martin Nilsson  file, loc), 0);
a476711997-10-20Henrik Grubbström (Grubba)  loc=loc[strlen(file)..]; sscanf(loc, "%s/", loc); if (!dir[loc]) {
cd92872000-08-15Johan Sundström  dir[loc] = ({ 0775, -3, 0, 0, 0, 0, 0 });
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  } if(sizeof(dir)) return dir; }
14179b1997-01-29Per Hedbor  // Access a virtual file?
e351dd1999-11-29Per Hedbor public array access(string file, RequestID id)
14179b1997-01-29Per Hedbor { string loc; array s, tmp;
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  file=replace(file, "//", "/"); // "//" is really "/" here...
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  // Map location-modules. foreach(location_modules(id), tmp) { loc = tmp[0];
4770421999-11-22Henrik Grubbström (Grubba)  if((file+"/")==loc) { #ifdef MODULE_LEVEL_SECURITY if(check_security(tmp[1], id)) continue; #endif if(s=function_object(tmp[1])->access("", id)) return s; } else if(!search(file, loc)) {
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY if(check_security(tmp[1], id)) continue; #endif if(s=function_object(tmp[1])->access(file[strlen(loc)..], id)) return s; } }
4770421999-11-22Henrik Grubbström (Grubba)  return 0;
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor public string real_file(string file, RequestID id)
9fd8092000-08-08Johan Sundström //! Return the _real_ filename of a virtual file, if any.
14179b1997-01-29Per Hedbor { string loc; string s; array tmp; file=replace(file, "//", "/"); // "//" is really "/" here...
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(!id) error("No id passed to real_file"); // Map location-modules. foreach(location_modules(id), tmp) { loc = tmp[0];
10c7e11999-12-28Martin Nilsson  if(!search(file, loc))
14179b1997-01-29Per Hedbor  { #ifdef MODULE_LEVEL_SECURITY if(check_security(tmp[1], id)) continue; #endif
c5e0961999-10-04Per Hedbor  if(s=function_object(tmp[1])->real_file(file[strlen(loc)..], id))
14179b1997-01-29Per Hedbor  return s; } } }
10c7e11999-12-28Martin Nilsson int|string try_get_file(string s, RequestID id,
646f722000-03-07Martin Stjernholm  int|void status, int|void nocache, int|void not_internal)
2688e22000-07-26Johan Sundström //! Convenience function used in quite a lot of modules. Tries to read //! a file into memory, and then returns the resulting string. //! //! NOTE: A 'file' can be a cgi script, which will be executed, //! resulting in a horrible delay. //! //! Unless the not_internal flag is set, this tries to get an external //! or internal file. Here "internal" means a file that never should be //! sent directly as a request response. E.g. an internal redirect to a //! different file is still considered "external" since its contents is //! sent directly to the client. Internal requests are recognized by //! the id->misc->internal_get flag being non-zero.
14179b1997-01-29Per Hedbor {
646f722000-03-07Martin Stjernholm  string res, q, cache_key;
e351dd1999-11-29Per Hedbor  RequestID fake_id;
14179b1997-01-29Per Hedbor  mapping m;
10c7e11999-12-28Martin Nilsson  if(!objectp(id))
14179b1997-01-29Per Hedbor  error("No ID passed to 'try_get_file'\n");
e351dd1999-11-29Per Hedbor  // id->misc->common makes it possible to pass information to // the originating request. if ( !id->misc ) id->misc = ([]); if ( !id->misc->common ) id->misc->common = ([]);
10c7e11999-12-28Martin Nilsson 
e351dd1999-11-29Per Hedbor  fake_id = id->clone_me();
10c7e11999-12-28Martin Nilsson 
e351dd1999-11-29Per Hedbor  fake_id->misc->common = id->misc->common;
484ec92000-06-23Martin Stjernholm  fake_id->misc->internal_get = !not_internal;
e351dd1999-11-29Per Hedbor 
646da22000-03-20Martin Stjernholm  s = Roxen.fix_relative (s, id);
a59fc92000-08-16Per Hedbor // if(!id->pragma["no-cache"] && !nocache && (!id->auth || !id->auth[0])) { // cache_key = // s + "\0" + // id->request_headers->cookie + "\0" + // id->request_headers["user-agent"]; // if(res = cache_lookup("file:"+name, cache_key)) // return res; // }
14179b1997-01-29Per Hedbor 
4e0a532000-03-20Martin Stjernholm  if (fake_id->scan_for_query) // FIXME: If we're using e.g. ftp this doesn't exist. But the // right solution might be that clone_me() in an ftp id object // returns a vanilla (i.e. http) id instead when this function is // used. s = fake_id->scan_for_query (s);
14179b1997-01-29Per Hedbor  fake_id->raw_url=s; fake_id->not_query=s;
c927a02000-03-18Martin Stjernholm  if(!(m = get_file(fake_id,0,!not_internal))) {
4cd5e82000-03-20Martin Stjernholm  // Might be a PATH_INFO type URL. m_delete (fake_id->misc, "path_info");
484ec92000-06-23Martin Stjernholm  array a = open_file( s, "r", fake_id, !not_internal );
e1e86d2000-03-20Martin Stjernholm  if(a && a[0]) { m = a[1]; m->file = a[0]; } else { destruct (fake_id); return 0; }
c927a02000-03-18Martin Stjernholm  }
a59fc92000-08-16Per Hedbor  CACHE( fake_id->misc->cacheable );
c927a02000-03-18Martin Stjernholm  destruct (fake_id);
889d031999-10-04Per Hedbor 
3bb38c2000-01-20Martin Bähr  if (!mappingp(m) && !objectp(m)) { report_error("try_get_file(%O, %O, %O, %O): m = %O is not a mapping.\n", s, id, status, nocache, m); return 0; }
3510fb1997-11-09Henrik Grubbström (Grubba)  if (!(< 0, 200, 201, 202, 203 >)[m->error]) return 0;
10c7e11999-12-28Martin Nilsson 
3510fb1997-11-09Henrik Grubbström (Grubba)  if(status) return 1;
10c7e11999-12-28Martin Nilsson  if(m->data)
a22f6f1999-05-12Per Hedbor  res = m->data;
10c7e11999-12-28Martin Nilsson  else
a22f6f1999-05-12Per Hedbor  res="";
14179b1997-01-29Per Hedbor  m->data = 0;
10c7e11999-12-28Martin Nilsson 
4cb2212000-05-22Per Hedbor  if( objectp(m->file) )
14179b1997-01-29Per Hedbor  {
3a4d7e1997-09-03Per Hedbor  res += m->file->read();
14179b1997-01-29Per Hedbor  destruct(m->file); m->file = 0; }
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(m->raw) { res -= "\r"; if(!sscanf(res, "%*s\n\n%s", res)) sscanf(res, "%*s\n%s", res); }
a59fc92000-08-16Per Hedbor // if (cache_key) // cache_set("file:"+name, cache_key, res);
14179b1997-01-29Per Hedbor  return res; }
9fd8092000-08-08Johan Sundström int(0..1) is_file(string virt_path, RequestID id) //! Is `virt_path' a file in our virtual filesystem?
14179b1997-01-29Per Hedbor {
9fd8092000-08-08Johan Sundström  return !!stat_file(virt_path, id);
14179b1997-01-29Per Hedbor }
c5e0961999-10-04Per Hedbor array registered_urls = ({});
14179b1997-01-29Per Hedbor void start(int num) {
c5e0961999-10-04Per Hedbor  // Note: This is run as root if roxen is started as root foreach( query( "URLs" )-registered_urls, string url ) { registered_urls += ({ url }); roxenp()->register_url( url, this_object() );
14179b1997-01-29Per Hedbor  }
c5e0961999-10-04Per Hedbor  foreach( registered_urls-query("URLs"), string url ) { registered_urls -= ({ url }); roxenp()->unregister_url( url );
14179b1997-01-29Per Hedbor  }
5f6dae2000-08-13Per Hedbor  if( !datacache ) datacache = DataCache( ); else datacache->init_from_variables();
14179b1997-01-29Per Hedbor }
e7e6031999-11-05Per Hedbor void save_me() { save_one( 0 ); }
14179b1997-01-29Per Hedbor void save(int|void all)
2688e22000-07-26Johan Sundström //! Save this configuration. If all is included, save all configuration //! global variables as well, otherwise only all module variables.
14179b1997-01-29Per Hedbor { if(all) {
3f628a1999-12-09Martin Stjernholm  store("spider#0", variables, 0, this_object());
14179b1997-01-29Per Hedbor  start(2); }
10c7e11999-12-28Martin Nilsson 
3f628a1999-12-09Martin Stjernholm  foreach(indices(modules), string modname)
14179b1997-01-29Per Hedbor  {
3f628a1999-12-09Martin Stjernholm  foreach(indices(modules[modname]->copies), int i)
14179b1997-01-29Per Hedbor  {
3f628a1999-12-09Martin Stjernholm  store(modname+"#"+i, modules[modname]->copies[i]->query(), 0, this_object()); modules[modname]->copies[i]->start(2, this_object());
14179b1997-01-29Per Hedbor  } }
8cc31b1997-10-12Henrik Grubbström (Grubba)  invalidate_cache();
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor int save_one( RoxenModule o )
2688e22000-07-26Johan Sundström //! Save all variables in a given module.
14179b1997-01-29Per Hedbor { mapping mod;
10c7e11999-12-28Martin Nilsson  if(!o)
14179b1997-01-29Per Hedbor  {
c5e0961999-10-04Per Hedbor  store("spider#0", variables, 0, this_object());
14179b1997-01-29Per Hedbor  start(2); return 1; }
2c13a81999-11-10Per Hedbor  string q = otomod[ o ]; if( !q ) error("Invalid module");
10c7e11999-12-28Martin Nilsson 
2c13a81999-11-10Per Hedbor  store(q, o->query(), 0, this_object()); invalidate_cache(); o->start(2, this_object()); invalidate_cache(); return 1;
14179b1997-01-29Per Hedbor }
2f79202000-03-27Per Hedbor RoxenModule reload_module( string modname )
5964251999-11-19Per Hedbor {
e351dd1999-11-29Per Hedbor  RoxenModule old_module = find_module( modname );
2f79202000-03-27Per Hedbor  ModuleInfo mi = roxen->find_module( (modname/"#")[0] ); if( !old_module ) return 0;
f569581999-11-23Per Hedbor 
2f79202000-03-27Per Hedbor  save_one( old_module );
1f56521999-11-23Per Hedbor 
9a1d472000-01-12Martin Stjernholm  master()->refresh_inherit( object_program( old_module ) );
2f79202000-03-27Per Hedbor  master()->refresh( object_program( old_module ), 1 ); catch( disable_module( modname, 1 ) );
f569581999-11-23Per Hedbor 
2f79202000-03-27Per Hedbor  RoxenModule nm;
bcf5662000-04-05Per Hedbor  if( catch( nm = enable_module( modname, 0, 0, 1 ) ) || (nm == 0) ) enable_module( modname, (nm=old_module), mi, 1 );
ee3ff02000-04-06Per Hedbor  else {
2e597a2000-04-06Martin Stjernholm  foreach ((array) old_module->error_log, [string msg, array(int) times]) nm->error_log[msg] += times;
ee3ff02000-04-06Per Hedbor  catch( mi->update_with( nm,0 ) ); // This is sort of nessesary...
23414a2000-07-21Andreas Lange  nm->report_notice(LOC_C(11, "Reloaded %s.\n"), mi->get_name());
ab7c312000-08-12Martin Stjernholm  // It's possible e.g. in the config interface that the module // being reloaded is in use for the current request, so delay it a // little. call_out (destruct, 2, old_module);
2e597a2000-04-06Martin Stjernholm  }
bcf5662000-04-05Per Hedbor  call_start_callbacks( nm, mi, modules[ (modname/"#")[0] ] );
f569581999-11-23Per Hedbor 
2f79202000-03-27Per Hedbor  return nm;
5964251999-11-19Per Hedbor }
7e446c1999-11-24Per Hedbor class ModuleCopies { mapping copies = ([]);
0b7d2b1999-12-22Per Hedbor  mixed `[](mixed q ) { return copies[q]; } mixed `[]=(mixed q,mixed w ) { return copies[q]=w; } mixed _indices() { return(indices(copies)); } mixed _values() { return(values(copies)); }
7e446c1999-11-24Per Hedbor  string _sprintf( ) { return "ModuleCopies()"; } }
beba572000-03-20Martin Stjernholm #ifdef THREADS Thread.Mutex enable_modules_mutex = Thread.Mutex(); #define MODULE_LOCK \ Thread.MutexKey enable_modules_lock = enable_modules_mutex->lock (2) #else #define MODULE_LOCK #endif
9a1d472000-01-12Martin Stjernholm static int enable_module_batch_msgs;
2f79202000-03-27Per Hedbor RoxenModule enable_module( string modname, RoxenModule|void me,
bcf5662000-04-05Per Hedbor  ModuleInfo|void moduleinfo, int|void nostart )
14179b1997-01-29Per Hedbor {
beba572000-03-20Martin Stjernholm  MODULE_LOCK;
c5e0961999-10-04Per Hedbor  int id;
e351dd1999-11-29Per Hedbor  ModuleCopies module;
c5e0961999-10-04Per Hedbor  int pr; mixed err; int module_type;
e7e6031999-11-05Per Hedbor  if( sscanf(modname, "%s#%d", modname, id ) != 2 )
2f79202000-03-27Per Hedbor  while( modules[ modname ] && modules[ modname ][ id ] )
4f43eb1999-11-05Per Hedbor  id++;
c5e0961999-10-04Per Hedbor 
7f00081998-03-20Per Hedbor  int start_time = gethrtime();
2f79202000-03-27Per Hedbor  mixed err;
25171c1999-11-06Per Hedbor 
2f79202000-03-27Per Hedbor  if( !moduleinfo )
ad683e1998-05-09Henrik Grubbström (Grubba)  {
2f79202000-03-27Per Hedbor  moduleinfo = roxen->find_module( modname ); if (!moduleinfo) { report_warning("Failed to load %s. The module probably " "doesn't exist in the module path.\n", modname); return 0; }
c5e0961999-10-04Per Hedbor  }
9a1d472000-01-12Martin Stjernholm  string descr = moduleinfo->get_name() + (id ? " copy " + (id + 1) : "");
3bbda81997-06-11Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug(" %-43s... \b", descr );
c5e0961999-10-04Per Hedbor  else
9a1d472000-01-12Martin Stjernholm  report_debug("Enabling " + descr + "\n");
3bbda81997-06-11Henrik Grubbström (Grubba) #endif
c5e0961999-10-04Per Hedbor 
0b7d2b1999-12-22Per Hedbor  module = modules[ modname ];
c5e0961999-10-04Per Hedbor  if(!module)
7e446c1999-11-24Per Hedbor  modules[ modname ] = module = ModuleCopies();
c5e0961999-10-04Per Hedbor 
f569581999-11-23Per Hedbor  if( !me )
c5e0961999-10-04Per Hedbor  {
f569581999-11-23Per Hedbor  if(err = catch(me = moduleinfo->instance(this_object()))) {
c45b2a1999-12-09Martin Stjernholm #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
67f60e2000-07-09Martin Nilsson  if (err != "") { #endif string bt=describe_backtrace(err);
434bac2000-07-14Andreas Lange  report_error("enable_module(): " +
49cd282000-08-11Andreas Lange  LOC_M(41, "Error while initiating module copy of %s%s"),
434bac2000-07-14Andreas Lange  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
67f60e2000-07-09Martin Nilsson #ifdef MODULE_DEBUG }
c45b2a1999-12-09Martin Stjernholm #endif
0b7d2b1999-12-22Per Hedbor  return module[id];
f569581999-11-23Per Hedbor  }
c5e0961999-10-04Per Hedbor  }
0b7d2b1999-12-22Per Hedbor  if(module[id] && module[id] != me)
c5e0961999-10-04Per Hedbor  {
c45e3f2000-02-16Per Hedbor  if( module[id]->stop ) module[id]->stop();
f569581999-11-23Per Hedbor // if( err = catch( disable_module( modname+"#"+id ) ) ) // report_error(LOCALE->error_disabling_module(moduleinfo->get_name(), // describe_backtrace(err)));
ad683e1998-05-09Henrik Grubbström (Grubba)  }
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  me->set_configuration( this_object() ); module_type = moduleinfo->type; if (module_type & (MODULE_LOCATION|MODULE_EXTENSION| MODULE_CONFIG|MODULE_FILE_EXTENSION|MODULE_LOGGER| MODULE_URL|MODULE_LAST|MODULE_PROVIDER| MODULE_FILTER|MODULE_PARSER|MODULE_FIRST))
ad683e1998-05-09Henrik Grubbström (Grubba)  {
c5e0961999-10-04Per Hedbor  if(module_type != MODULE_CONFIG)
3b17831998-11-22Per Hedbor  {
4770421999-11-22Henrik Grubbström (Grubba)  if (err = catch {
23414a2000-07-21Andreas Lange  me->defvar("_priority", 5, DLOCALE(12, "Priority"), TYPE_INT_LIST, DLOCALE(13, "The priority of the module. 9 is highest and 0 is lowest."
4770421999-11-22Henrik Grubbström (Grubba)  " Modules with the same priority can be assumed to be "
f498ed2000-07-11Martin Nilsson  "called in random order"),
4770421999-11-22Henrik Grubbström (Grubba)  ({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); }) { throw(err); }
3b17831998-11-22Per Hedbor  }
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(module_type != MODULE_LOGGER && module_type != MODULE_PROVIDER)
ad683e1998-05-09Henrik Grubbström (Grubba)  {
23414a2000-07-21Andreas Lange  me->defvar("_sec_group", "user", DLOCALE(14, "Security: Realm"), TYPE_STRING, DLOCALE(15, "The realm to use when requesting password from the " "client. Usually used as an informative message to the " "user.")); me->defvar("_seclevels", "", DLOCALE(16, "Security: Patterns"), TYPE_TEXT_FIELD, DLOCALE(17, "This is the 'security level=value' list.<br />" "Each security level can be any or more from this list:" "<hr noshade=\"noshade\" />" "allow ip=<i>IP</i>/<i>bits</i><br />" "allow ip=<i>IP</i>:<i>mask</i><br />" "allow ip=<i>pattern</i><br />" "allow user=<i>username</i>,...<br />" "deny ip=<i>IP</i>/<i>bits</i><br />" "deny ip=<i>IP</i>:<i>mask</i><br />" "deny ip=<i>pattern</i><br />" "<hr noshade=\"noshade\" />" "In patterns: * matches one or more characters, " "and ? matches one character." "<p>In username: 'any' stands for any valid account " "(from .htaccess" " or an auth module. The default (used when _no_ " "entries are present) is 'allow ip=*', allowing" " everyone to access the module.</p>"));
c5e0961999-10-04Per Hedbor  if(!(module_type & MODULE_PROXY))
14179b1997-01-29Per Hedbor  {
23414a2000-07-21Andreas Lange  me->defvar("_seclvl", 0, DLOCALE(18, "Security: Security level"), TYPE_INT, DLOCALE(19, "The modules security level is used to determine if a "
3bf3451998-10-01Peter Bortas  " request should be handled by the module." "\n<p><h2>Security level vs Trust level</h2>" " Each module has a configurable <i>security level</i>." " Each request has an assigned trust level. Higher" " <i>trust levels</i> grants access to modules with higher" " <i>security levels</i>." "\n<p><h2>Definitions</h2><ul>"
f498ed2000-07-11Martin Nilsson  " <li>A requests initial Trust level is infinitely high.</li>"
3bf3451998-10-01Peter Bortas  " <li> A request will only be handled by a module if its" " <i>trust level</i> is higher or equal to the"
f498ed2000-07-11Martin Nilsson  " <i>security level</i> of the module.</li>"
3bf3451998-10-01Peter Bortas  " <li> Each time the request is handled by a module the" " <i>trust level</i> of the module will be set to the" " lower of its <i>trust level</i> and the modules"
f498ed2000-07-11Martin Nilsson  " <i>security level</i>.</li>" " </ul></p>"
3bf3451998-10-01Peter Bortas  "\n<p><h2>Example</h2>" " Modules:<ul>"
f498ed2000-07-11Martin Nilsson  " <li> User filesystem, <i>security level</i> 1</li>" " <li> Filesystem module, <i>security level</i> 3</li>" " <li> CGI module, <i>security level</i> 2</li>" " </ul></p>"
3bf3451998-10-01Peter Bortas  "\n<p>A request handled by \"User filesystem\" is assigned" " a <i>trust level</i> of one after the <i>security" " level</i> of that module. That request can then not be" " handled by the \"CGI module\" since that module has a" " higher <i>security level</i> than the requests trust"
f498ed2000-07-11Martin Nilsson  " level.</p>"
3bf3451998-10-01Peter Bortas  "\n<p>On the other hand, a request handled by the the" " \"Filsystem module\" could later be handled by the"
f498ed2000-07-11Martin Nilsson  " \"CGI module\".</p>"));
ad683e1998-05-09Henrik Grubbström (Grubba)  } else { me->definvisvar("_seclvl", -10, TYPE_INT); /* A very low one */
14179b1997-01-29Per Hedbor  }
3bbda81997-06-11Henrik Grubbström (Grubba)  }
ad683e1998-05-09Henrik Grubbström (Grubba)  } else { me->defvar("_priority", 0, "", TYPE_INT, "", 0, 1); }
14179b1997-01-29Per Hedbor 
a0fbcc2000-04-05Martin Stjernholm  mapping(string:mixed) stored_vars = retrieve(modname + "#" + id, this_object()); int has_stored_vars = sizeof (stored_vars); // A little ugly, but it suffices. me->setvars(stored_vars);
33e6351998-02-28Martin Stjernholm 
0b7d2b1999-12-22Per Hedbor  module[ id ] = me;
37c1b31999-10-12Per Hedbor  otomod[ me ] = modname+"#"+id;
10c7e11999-12-28Martin Nilsson 
bcf5662000-04-05Per Hedbor  mixed err; if(!nostart) call_start_callbacks( me, moduleinfo, module ); #ifdef MODULE_DEBUG if (enable_module_batch_msgs) report_debug("\bOK %6.1fms\n", (gethrtime()-start_time)/1000.0); #endif
2e597a2000-04-06Martin Stjernholm  if( me->no_delayed_load ) {
bcf5662000-04-05Per Hedbor  set( "no_delayed_load", 1 );
2e597a2000-04-06Martin Stjernholm  save_me(); }
bcf5662000-04-05Per Hedbor  if(!enabled_modules[ modname+"#"+id ]) { enabled_modules[modname+"#"+id] = 1; store( "EnabledModules", enabled_modules, 1, this_object()); } if (!has_stored_vars) store (modname + "#" + id, me->query(), 0, this_object()); return me; } void call_start_callbacks( RoxenModule me, ModuleInfo moduleinfo, ModuleCopies module ) { int module_type = moduleinfo->type, pr;
ad683e1998-05-09Henrik Grubbström (Grubba)  mixed err;
c5e0961999-10-04Per Hedbor  if((me->start) && (err = catch( me->start(0, this_object()) ) ) ) { #ifdef MODULE_DEBUG
bcf5662000-04-05Per Hedbor  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c5e0961999-10-04Per Hedbor #endif
67f60e2000-07-09Martin Nilsson  string bt=describe_backtrace(err);
49cd282000-08-11Andreas Lange  report_error(LOC_M(41, "Error while initiating module copy of %s%s"),
67f60e2000-07-09Martin Nilsson  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
bcf5662000-04-05Per Hedbor 
ad683e1998-05-09Henrik Grubbström (Grubba)  /* Clean up some broken references to this module. */
bcf5662000-04-05Per Hedbor // m_delete(otomod, me); // m_delete(module->copies, search( module->copies, me )); // destruct(me); // return 0;
ad683e1998-05-09Henrik Grubbström (Grubba)  }
5ffa542000-02-16Per Hedbor  if( inited && me->ready_to_receive_requests )
bcf5662000-04-05Per Hedbor  if( mixed q = catch( me->ready_to_receive_requests( this_object() ) ) ) {
c2fdff2000-03-21Martin Stjernholm #ifdef MODULE_DEBUG if (enable_module_batch_msgs) report_debug("\bERROR\n"); #endif report_error( "While calling ready_to_receive_requests:\n"+ describe_backtrace( q ) ); }
10c7e11999-12-28Martin Nilsson  if (err = catch(pr = me->query("_priority")))
c5e0961999-10-04Per Hedbor  {
c45b2a1999-12-09Martin Stjernholm #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c45b2a1999-12-09Martin Stjernholm #endif
67f60e2000-07-09Martin Nilsson  string bt=describe_backtrace(err);
49cd282000-08-11Andreas Lange  report_error(LOC_M(41, "Error while initiating module copy of %s%s"),
67f60e2000-07-09Martin Nilsson  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
ad683e1998-05-09Henrik Grubbström (Grubba)  pr = 3; } api_module_cache |= me->api_functions();
10c7e11999-12-28Martin Nilsson  if(module_type & MODULE_EXTENSION)
c5e0961999-10-04Per Hedbor  {
434bac2000-07-14Andreas Lange  report_error("%s is an MODULE_EXTENSION, that type is no " "longer available.\nPlease notify the modules writer.\n" "Suitable replacement types include MODULE_FIRST and " " MODULE_LAST.\n", moduleinfo->get_name());
c5e0961999-10-04Per Hedbor  }
ad683e1998-05-09Henrik Grubbström (Grubba) 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_FILE_EXTENSION)
ad683e1998-05-09Henrik Grubbström (Grubba)  if (err = catch { array arr = me->query_file_extensions();
10c7e11999-12-28Martin Nilsson  if (arrayp(arr))
c5e0961999-10-04Per Hedbor  {
ad683e1998-05-09Henrik Grubbström (Grubba)  string foo; foreach( me->query_file_extensions(), foo )
10c7e11999-12-28Martin Nilsson  if(pri[pr]->file_extension_modules[foo] )
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->file_extension_modules[foo]+=({me}); else pri[pr]->file_extension_modules[foo]=({me}); }
c45b2a1999-12-09Martin Stjernholm  }) { #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c45b2a1999-12-09Martin Stjernholm #endif
67f60e2000-07-09Martin Nilsson  string bt=describe_backtrace(err);
49cd282000-08-11Andreas Lange  report_error(LOC_M(41, "Error while initiating module copy of %s%s"),
67f60e2000-07-09Martin Nilsson  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
c45b2a1999-12-09Martin Stjernholm  }
14179b1997-01-29Per Hedbor 
10c7e11999-12-28Martin Nilsson  if(module_type & MODULE_PROVIDER) if (err = catch
c5e0961999-10-04Per Hedbor  {
ad683e1998-05-09Henrik Grubbström (Grubba)  mixed provs = me->query_provides(); if(stringp(provs)) provs = (< provs >); if(arrayp(provs)) provs = mkmultiset(provs); if (multisetp(provs)) { pri[pr]->provider_modules [ me ] = provs;
3bbda81997-06-11Henrik Grubbström (Grubba)  }
c45b2a1999-12-09Martin Stjernholm  }) { #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c45b2a1999-12-09Martin Stjernholm #endif
67f60e2000-07-09Martin Nilsson  string bt=describe_backtrace(err);
49cd282000-08-11Andreas Lange  report_error(LOC_M(41, "Error while initiating module copy of %s%s"),
67f60e2000-07-09Martin Nilsson  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
c45b2a1999-12-09Martin Stjernholm  }
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_TYPES)
ad683e1998-05-09Henrik Grubbström (Grubba)  { types_module = me; types_fun = me->type_from_extension; }
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_PARSER) add_parse_module( me );
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_AUTH)
ad683e1998-05-09Henrik Grubbström (Grubba)  { auth_module = me; auth_fun = me->auth; }
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_DIRECTORIES)
ad683e1998-05-09Henrik Grubbström (Grubba)  dir_module = me;
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_LOCATION)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->location_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_LOGGER)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->logger_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_URL)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->url_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_LAST)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->last_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_FILTER)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->filter_modules += ({ me });
14179b1997-01-29Per Hedbor 
10c7e11999-12-28Martin Nilsson  if(module_type & MODULE_FIRST)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->first_modules += ({ me });
14179b1997-01-29Per Hedbor 
ad683e1998-05-09Henrik Grubbström (Grubba)  invalidate_cache();
14179b1997-01-29Per Hedbor }
a6ef1f2000-03-28Johan Sundström // Called from the administration interface.
199d031999-09-05Francesco Chemolli string check_variable(string name, mixed value)
14179b1997-01-29Per Hedbor { switch(name) {
cffbaa2000-04-11Per Hedbor // case "MyWorldLocation": // if(strlen(value)<7 || value[-1] != '/' || // !(sscanf(value,"%*s://%*s/")==2)) // return LOCALE->url_format(); // return 0;
199d031999-09-05Francesco Chemolli  case "throttle": if (value) { THROTTLING_DEBUG("configuration: Starting throttler up"); throttler=.throttler(); throttler->throttle(query("throttle_fill_rate"), query("throttle_bucket_depth"), query("throttle_min_grant"), query("throttle_max_grant")); } else {
7e0f382000-05-06Francesco Chemolli  if (throttler) { //check, or get a backtrace the first time it's set THROTTLING_DEBUG("configuration: Stopping throttler"); destruct(throttler); throttler=0; }
199d031999-09-05Francesco Chemolli  } return 0; case "throttle_fill_rate": case "throttle_bucket_depth": case "throttle_min_grant": case "throttle_max_grant": THROTTLING_DEBUG("configuration: setting throttling parameter: "+ name+"="+value); throttler->throttle(query("throttle_fill_rate"), query("throttle_bucket_depth"), query("throttle_min_grant"), query("throttle_max_grant")); return 0;
14179b1997-01-29Per Hedbor  } }
2f79202000-03-27Per Hedbor int disable_module( string modname, int|void nodest )
14179b1997-01-29Per Hedbor {
beba572000-03-20Martin Stjernholm  MODULE_LOCK;
e351dd1999-11-29Per Hedbor  RoxenModule me;
c5e0961999-10-04Per Hedbor  int id, pr;
14179b1997-01-29Per Hedbor  sscanf(modname, "%s#%d", modname, id );
e351dd1999-11-29Per Hedbor  ModuleInfo moduleinfo = roxen->find_module( modname );
c5e0961999-10-04Per Hedbor  mapping module = modules[ modname ];
9a1d472000-01-12Martin Stjernholm  string descr = moduleinfo->get_name() + (id ? " copy " + (id + 1) : "");
14179b1997-01-29Per Hedbor 
10c7e11999-12-28Martin Nilsson  if(!module)
14179b1997-01-29Per Hedbor  {
434bac2000-07-14Andreas Lange  report_error("disable_module(): " +
49cd282000-08-11Andreas Lange  LOC_M(42, "Failed to disable module:\n"
67f60e2000-07-09Martin Nilsson  "No module by that name: \"%s\".\n"), modname);
14179b1997-01-29Per Hedbor  return 0; }
0b7d2b1999-12-22Per Hedbor  me = module[id];
c5e0961999-10-04Per Hedbor  m_delete(module->copies, id);
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(!sizeof(module->copies)) m_delete( modules, modname );
14179b1997-01-29Per Hedbor 
8cc31b1997-10-12Henrik Grubbström (Grubba)  invalidate_cache();
14179b1997-01-29Per Hedbor  if(!me) {
434bac2000-07-14Andreas Lange  report_error("disable_module(): " +
49cd282000-08-11Andreas Lange  LOC_M(43, "Failed to disable module \"%s\".\n"),
67f60e2000-07-09Martin Nilsson  descr);
14179b1997-01-29Per Hedbor  return 0; }
9a1d472000-01-12Martin Stjernholm  if(me->stop)
67f60e2000-07-09Martin Nilsson  if (mixed err = catch (me->stop())) { string bt=describe_backtrace(err);
434bac2000-07-14Andreas Lange  report_error("disable_module(): " +
49cd282000-08-11Andreas Lange  LOC_M(44, "Error while disabling module %s%s"),
434bac2000-07-14Andreas Lange  descr, (bt ? ":\n"+bt : "\n"));
67f60e2000-07-09Martin Nilsson  }
14179b1997-01-29Per Hedbor  #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  report_debug("Disabling "+descr+"\n");
14179b1997-01-29Per Hedbor #endif
c5e0961999-10-04Per Hedbor  if(moduleinfo->type & MODULE_FILE_EXTENSION)
14179b1997-01-29Per Hedbor  { string foo;
d54d061999-06-10Martin Stjernholm  for(pr=0; pr<10; pr++) foreach( indices (pri[pr]->file_extension_modules), foo ) pri[pr]->file_extension_modules[foo]-=({me});
14179b1997-01-29Per Hedbor  }
c5e0961999-10-04Per Hedbor  if(moduleinfo->type & MODULE_PROVIDER) {
ae32d01998-03-23David Hedbor  for(pr=0; pr<10; pr++) m_delete(pri[pr]->provider_modules, me); }
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(moduleinfo->type & MODULE_TYPES)
14179b1997-01-29Per Hedbor  { types_module = 0; types_fun = 0; }
c5e0961999-10-04Per Hedbor  if(moduleinfo->type & MODULE_PARSER)
b796b51998-11-18Per Hedbor  remove_parse_module( me );
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_AUTH )
14179b1997-01-29Per Hedbor  { auth_module = 0; auth_fun = 0; }
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_DIRECTORIES )
14179b1997-01-29Per Hedbor  dir_module = 0;
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_LOCATION )
14179b1997-01-29Per Hedbor  for(pr=0; pr<10; pr++) pri[pr]->location_modules -= ({ me });
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_URL )
14179b1997-01-29Per Hedbor  for(pr=0; pr<10; pr++) pri[pr]->url_modules -= ({ me });
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_LAST )
14179b1997-01-29Per Hedbor  for(pr=0; pr<10; pr++) pri[pr]->last_modules -= ({ me });
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_FILTER )
14179b1997-01-29Per Hedbor  for(pr=0; pr<10; pr++) pri[pr]->filter_modules -= ({ me });
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_FIRST ) {
14179b1997-01-29Per Hedbor  for(pr=0; pr<10; pr++) pri[pr]->first_modules -= ({ me });
f128901997-08-15Henrik Grubbström (Grubba)  }
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if( moduleinfo->type & MODULE_LOGGER )
14179b1997-01-29Per Hedbor  for(pr=0; pr<10; pr++) pri[pr]->logger_modules -= ({ me });
c5e0961999-10-04Per Hedbor  if( enabled_modules[modname+"#"+id] )
14179b1997-01-29Per Hedbor  { m_delete( enabled_modules, modname + "#" + id );
9745382000-08-01Johan Sundström  forcibly_added[ modname + "#" + id ] = 0;
c5e0961999-10-04Per Hedbor  store( "EnabledModules",enabled_modules, 1, this_object());
14179b1997-01-29Per Hedbor  }
2f79202000-03-27Per Hedbor  if(!nodest) destruct(me);
14179b1997-01-29Per Hedbor  return 1; }
e351dd1999-11-29Per Hedbor RoxenModule|string find_module(string name)
9fd8092000-08-08Johan Sundström //! Return the module corresponding to the name (eg "rxmlparse", //! "rxmlparse#0" or "filesystem#1") or zero, if there was no such //! module.
14179b1997-01-29Per Hedbor { int id; sscanf(name, "%s#%d", name, id); if(modules[name])
c5e0961999-10-04Per Hedbor  return modules[name]->copies[id];
14179b1997-01-29Per Hedbor  return 0; }
f5a2741999-10-18Per Hedbor multiset forcibly_added = (<>); int add_modules( array(string) mods, int|void now )
14179b1997-01-29Per Hedbor {
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  int wr;
ba18d71999-11-27Per Hedbor #endif
c5e0961999-10-04Per Hedbor  foreach (mods, string mod)
8f061b1999-11-19Per Hedbor  { sscanf( mod, "%s#", mod );
10c7e11999-12-28Martin Nilsson  if( ((now && !modules[ mod ]) ||
0ce25d1999-11-15Per Hedbor  !enabled_modules[ mod+"#0" ] ) && !forcibly_added[ mod+"#0" ])
14179b1997-01-29Per Hedbor  {
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  if( !wr++ )
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\b[ adding req module" + (sizeof (mods) > 1 ? "s" : "") + "\n"); else report_debug("Adding required module" + (sizeof (mods) > 1 ? "s" : "") + "\n");
14179b1997-01-29Per Hedbor #endif
9a1d472000-01-12Martin Stjernholm  forcibly_added[ mod+"#0" ] = 1; enable_module( mod+"#0" );
14179b1997-01-29Per Hedbor  }
8f061b1999-11-19Per Hedbor  }
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if( wr && enable_module_batch_msgs )
ed8d261999-12-30Martin Stjernholm  report_debug("] \b");
c79b261998-02-05Johan Schön #endif
14179b1997-01-29Per Hedbor }
279a0c1997-11-26Henrik Grubbström (Grubba) // BEGIN SQL
14179b1997-01-29Per Hedbor 
279a0c1997-11-26Henrik Grubbström (Grubba) mapping(string:string) sql_urls = ([]);
ed93131998-07-09Johan Schön mapping sql_cache = ([]);
e351dd1999-11-29Per Hedbor Sql.sql sql_cache_get(string what)
ed93131998-07-09Johan Schön { #ifdef THREADS if(sql_cache[what] && sql_cache[what][this_thread()]) return sql_cache[what][this_thread()]; if(!sql_cache[what]) sql_cache[what] = ([ this_thread():Sql.sql( what ) ]); else sql_cache[what][ this_thread() ] = Sql.sql( what ); return sql_cache[what][ this_thread() ]; #else /* !THREADS */ if(!sql_cache[what]) sql_cache[what] = Sql.sql( what ); return sql_cache[what]; #endif }
e351dd1999-11-29Per Hedbor Sql.sql sql_connect(string db)
279a0c1997-11-26Henrik Grubbström (Grubba) {
c5e0961999-10-04Per Hedbor  if (sql_urls[db]) return sql_cache_get(sql_urls[db]); else return sql_cache_get(db);
279a0c1997-11-26Henrik Grubbström (Grubba) } // END SQL
14179b1997-01-29Per Hedbor 
1e5ee81997-08-21Per Hedbor // This is the most likely URL for a virtual server.
14179b1997-01-29Per Hedbor private string get_my_url() { string s;
c79b261998-02-05Johan Schön #if efun(gethostname)
14179b1997-01-29Per Hedbor  s = (gethostname()/".")[0] + "." + query("Domain"); s -= "\n";
c79b261998-02-05Johan Schön #else s = "localhost"; #endif
14179b1997-01-29Per Hedbor  return "http://" + s + "/"; }
5ffa542000-02-16Per Hedbor array after_init_hooks = ({}); mixed add_init_hook( mixed what ) { if( inited ) call_out( what, 0, this_object() ); else after_init_hooks |= ({ what }); }
0f28da1997-08-13Per Hedbor void enable_all_modules()
14179b1997-01-29Per Hedbor {
beba572000-03-20Martin Stjernholm  MODULE_LOCK;
c45e3f2000-02-16Per Hedbor  int q = query( "no_delayed_load" ); set( "no_delayed_load", 0 ); low_init( ); if( q != query( "no_delayed_load" ) ) save_one( 0 );
5ffa542000-02-16Per Hedbor }
c45e3f2000-02-16Per Hedbor void low_init()
5ffa542000-02-16Per Hedbor { if( inited ) return; // already done
8516a71999-12-22Per Hedbor 
24c06c2000-02-16Per Hedbor  int start_time = gethrtime(); report_debug("\nEnabling all modules for "+query_name()+"... \n");
1d7d6d2000-02-16Per Hedbor  add_parse_module( (object)this_object() ); enabled_modules = retrieve("EnabledModules", this_object());
6958011999-12-28Martin Stjernholm  object ec = roxenloader.LowErrorContainer(); roxenloader.push_compile_error_handler( ec );
c5e0961999-10-04Per Hedbor  array modules_to_process = indices( enabled_modules );
14179b1997-01-29Per Hedbor  string tmp_string;
44f2431999-06-07Martin Stjernholm  parse_log_formats(); init_log_file();
0f28da1997-08-13Per Hedbor  // Always enable the user database module first. if(search(modules_to_process, "userdb#0")>-1) modules_to_process = (({"userdb#0"})+(modules_to_process-({"userdb#0"}))); array err;
f5a2741999-10-18Per Hedbor  forcibly_added = (<>);
9a1d472000-01-12Martin Stjernholm  enable_module_batch_msgs = 1;
0f28da1997-08-13Per Hedbor  foreach( modules_to_process, tmp_string )
f5a2741999-10-18Per Hedbor  {
6958011999-12-28Martin Stjernholm  if( !forcibly_added[ tmp_string ] )
f5a2741999-10-18Per Hedbor  if(err = catch( enable_module( tmp_string )))
49cd282000-08-11Andreas Lange  report_error(LOC_M(45, "Failed to enable the module %s. Skipping.\n%s"),
67f60e2000-07-09Martin Nilsson  tmp_string, describe_backtrace(err));
f5a2741999-10-18Per Hedbor  }
9a1d472000-01-12Martin Stjernholm  enable_module_batch_msgs = 0;
6958011999-12-28Martin Stjernholm  roxenloader.pop_compile_error_handler(); if( strlen( ec->get() ) ) report_error( "While enabling modules in "+name+":\n"+ec->get() );
17d6d12000-03-30Per Hedbor  if( strlen( ec->get_warnings() ) ) report_warning( "While enabling modules in "+name+":\n"+ec->get_warnings());
5ffa542000-02-16Per Hedbor  foreach( ({this_object()})+indices( otomod ), object mod ) if( mod->ready_to_receive_requests ) if( mixed q = catch( mod->ready_to_receive_requests( this_object() ) ) )
c2fdff2000-03-21Martin Stjernholm  report_error( "While calling ready_to_receive_requests in "+
5ffa542000-02-16Per Hedbor  otomod[mod]+":\n"+ describe_backtrace( q ) ); foreach( after_init_hooks, function q ) if( mixed w = catch( q ) )
c2fdff2000-03-21Martin Stjernholm  report_error( "While calling after_init_hook %O:\n%s",
5ffa542000-02-16Per Hedbor  q, describe_backtrace( w ) ); after_init_hooks = ({}); inited = 1;
23414a2000-07-21Andreas Lange  report_notice(LOC_S(4, "All modules for %s enabled in %3.1f seconds") + "\n\n", query_name(), (gethrtime()-start_time)/1000000.0);
0f28da1997-08-13Per Hedbor }
5f6dae2000-08-13Per Hedbor  // Trivial cache (actually, it's more or less identical to the 200+ // lines of C in HTTPLoop. But it does not have to bother with the // fact that more than one thread can be active in it at once. Also, // it does not have to delay free until all current connections using // the cache entry is done...) class DataCache { mapping(string:array(string|mapping(string:mixed))) cache = ([]); int current_size; int max_size; int max_file_size; int hits, misses; static void clear_some_cache() { array q = indices( cache ); for( int i = 0; i<sizeof( cache)/10; i++ ) { string ent = q[random(sizeof(q))]; current_size -= strlen( cache[ent][0] ); m_delete( cache, q[random(sizeof(q))] ); } } void expire_entry( string url ) { if( cache[ url ] ) { current_size -= strlen(cache[url][0]); m_delete( cache, url ); } } void set( string url, string data, mapping meta, int expire ) { // if( strlen( data ) > max_file_size ) // checked in conf // return 0; call_out( expire_entry, expire, url ); while( (strlen( data ) + current_size) > max_size ) clear_some_cache(); current_size += strlen( data ); cache[url] = ({ data, meta }); } array(string|mapping(string:mixed)) get( string url ) { mixed res; if( res = cache[ url ] ) hits++; else misses++; return res; } void init_from_variables( ) { max_size = query( "data_cache_size" ) * 1024; max_file_size = query( "data_cache_file_max_size" ) * 1024; while( current_size > max_size ) clear_some_cache(); } static void create() { init_from_variables(); } }; DataCache datacache;
0f28da1997-08-13Per Hedbor void create(string config) {
14179b1997-01-29Per Hedbor  name=config;
001ae71998-10-11Henrik Grubbström (Grubba) 
5f6dae2000-08-13Per Hedbor  // for now only theese two. In the future there might be more variables. defvar( "data_cache_size", 2048, DLOCALE("", "Data Cache:Cache size"), TYPE_INT, DLOCALE("", "The size of the data cache used to speed up requests " "for commonly requested files, in KBytes")); defvar( "data_cache_file_max_size", 50, DLOCALE("", "Data Cache:Max file size"), TYPE_INT, DLOCALE("", "The maximum size of a file that is to be considered for " "the cache"));
23414a2000-07-21Andreas Lange  defvar("default_server", 0, DLOCALE(20, "Default site"),
40e24c2000-05-27Per Hedbor  TYPE_FLAG,
23414a2000-07-21Andreas Lange  DLOCALE(21, "If true, this site will be selected in preference of "
40e24c2000-05-27Per Hedbor  "other sites when virtual hosting is used and no host " "header is supplied, or the supplied host header does not "
f498ed2000-07-11Martin Nilsson  "match the address of any of the other servers.") );
40e24c2000-05-27Per Hedbor 
23414a2000-07-21Andreas Lange  defvar("comment", "", DLOCALE(22, "Virtual server comment"),
9b9f701997-08-12Per Hedbor  TYPE_TEXT_FIELD|VAR_MORE,
23414a2000-07-21Andreas Lange  DLOCALE(23, "This text will be visible in the administration "
434bac2000-07-14Andreas Lange  "interface, it can be quite useful to use as a memory helper."));
b796b51998-11-18Per Hedbor 
23414a2000-07-21Andreas Lange  defvar("name", "", DLOCALE(24, "Virtual server name"),
9b9f701997-08-12Per Hedbor  TYPE_STRING|VAR_MORE,
23414a2000-07-21Andreas Lange  DLOCALE(25, "This is the name that will be used in the configuration "
14179b1997-01-29Per Hedbor  "interface. If this is left empty, the actual name of the "
f498ed2000-07-11Martin Nilsson  "virtual server will be used."));
10c7e11999-12-28Martin Nilsson  defvar("LogFormat",
f498ed2000-07-11Martin Nilsson  "404: $host $referer - [$cern_date] \"$method $resource $protocol\" 404 -\n" "500: $host $referer ERROR [$cern_date] \"$method $resource $protocol\" 500 -\n" "*: $host - - [$cern_date] \"$method $resource $protocol\" $response $length",
23414a2000-07-21Andreas Lange  DLOCALE(26, "Logging: Format"),
9b9f701997-08-12Per Hedbor  TYPE_TEXT_FIELD|VAR_MORE,
23414a2000-07-21Andreas Lange  DLOCALE(27, "What format to use for logging. The syntax is:\n"
14179b1997-01-29Per Hedbor  "<pre>"
434bac2000-07-14Andreas Lange  "response-code or *: Log format for that response code\n\n"
14179b1997-01-29Per Hedbor  "Log format is normal characters, or one or more of the " "variables below:\n" "\n" "\\n \\t \\r -- As in C, newline, tab and linefeed\n" "$char(int) -- Insert the (1 byte) character specified by the integer.\n" "$wchar(int) -- Insert the (2 byte) word specified by the integer.\n" "$int(int) -- Insert the (4 byte) word specified by the integer.\n" "$^ -- Supress newline at the end of the logentry\n" "$host -- The remote host name, or ip number.\n" "$ip_number -- The remote ip number.\n" "$bin-ip_number -- The remote host id as a binary integer number.\n" "\n" "$cern_date -- Cern Common Log file format date.\n"
434bac2000-07-14Andreas Lange  "$bin-date -- Time, but as an 32 bit integer in network byteorder\n"
14179b1997-01-29Per Hedbor  "\n" "$method -- Request method\n" "$resource -- Resource identifier\n"
dfb4ec1999-05-20Francesco Chemolli  "$full_resource -- Full requested resource, including any query fields\n"
14179b1997-01-29Per Hedbor  "$protocol -- The protocol used (normally HTTP/1.0)\n" "$response -- The response code sent\n" "$bin-response -- The response code sent as a binary short number\n" "$length -- The length of the data section of the reply\n"
434bac2000-07-14Andreas Lange  "$bin-length -- Same, but as an 32 bit integer in network byteorder\n"
0bf5a11998-04-03Henrik Grubbström (Grubba)  "$request-time -- The time the request took (seconds)\n"
14179b1997-01-29Per Hedbor  "$referer -- the header 'referer' from the request, or '-'.\n"
f498ed2000-07-11Martin Nilsson  "$user_agent -- the header 'User-Agent' from the request, or '-'.\n\n"
14179b1997-01-29Per Hedbor  "$user -- the name of the auth user used, if any\n" "$user_id -- A unique user ID, if cookies are supported,\n" " by the client, otherwise '0'\n"
f498ed2000-07-11Martin Nilsson  "</pre>"), 0, lambda(){ return !query("Log");});
b796b51998-11-18Per Hedbor 
23414a2000-07-21Andreas Lange  defvar("Log", 1, DLOCALE(28, "Logging: Enabled"), TYPE_FLAG, DLOCALE(29, "Log requests"));
14179b1997-01-29Per Hedbor 
f498ed2000-07-11Martin Nilsson  // FIXME: Mention it is relative to getcwd(). Can not be localized in pike 7.0. defvar("LogFile", "$LOGDIR/"+Roxen.short_name(name)+"/Log",
23414a2000-07-21Andreas Lange  DLOCALE(30, "Logging: Log file"), TYPE_FILE, DLOCALE(31, "The log file. "
f7d9811997-09-12Per Hedbor  ""
f498ed2000-07-11Martin Nilsson  "A file name. Some substitutions will be done:"
f7d9811997-09-12Per Hedbor  "<pre>"
b796b51998-11-18Per Hedbor  "%y Year (e.g. '1997')\n" "%m Month (e.g. '08')\n" "%d Date (e.g. '10' for the tenth)\n"
3bb38c2000-01-20Martin Bähr  "%h Hour (e.g. '00')\n" "%H Hostname\n"
f498ed2000-07-11Martin Nilsson  "</pre>")
c5e0961999-10-04Per Hedbor  ,0, lambda(){ return !query("Log");});
10c7e11999-12-28Martin Nilsson  defvar("NoLog", ({ }),
23414a2000-07-21Andreas Lange  DLOCALE(32, "Logging: No Logging for"), TYPE_STRING_LIST|VAR_MORE, DLOCALE(33, "Don't log requests from hosts with an IP number which "
434bac2000-07-14Andreas Lange  "matches any of the patterns in this list. This also affects " "the access counter log."), 0, lambda(){ return !query("Log");});
a8f1b32000-01-31Per Hedbor 
23414a2000-07-21Andreas Lange  defvar("Domain", roxen->get_domain(), DLOCALE(34, "Domain"), TYPE_STRING, DLOCALE(35, "The domainname of the server. The domainname is used "
434bac2000-07-14Andreas Lange  "to generate default URLs, and to generate email addresses."));
14179b1997-01-29Per Hedbor 
1acaeb2000-04-06Per Hedbor  defvar("MyWorldLocation", "http://"+gethostname()+"/",
23414a2000-07-21Andreas Lange  DLOCALE(36, "Primary Server URL"), TYPE_URL, DLOCALE(37, "This is the main server URL, where your start page is "
434bac2000-07-14Andreas Lange  "located. Please note that you also have to configure the " "'URLs' variable."));
c551f22000-07-04Per Hedbor  defvar("URLs", Variable.PortList( ({"http://*/"}), VAR_INITIAL,
23414a2000-07-21Andreas Lange  DLOCALE(38, "URLs"), DLOCALE(39, "Bind to these URLs. You can use '*' and '?' to perform"
434bac2000-07-14Andreas Lange  " globbing (using any of these will default to binding to " "all IP-numbers on your machine). The possible protocols " "are http, fhttp (a faster version of the normal HTTP " "protocol, but not 100% compatible with all modules) " "https, ftp, ftps, gopher and tetris.")));
c5e0961999-10-04Per Hedbor 
199d031999-09-05Francesco Chemolli  defvar("InternalLoc", "/_internal/",
23414a2000-07-21Andreas Lange  DLOCALE(40, "Internal module resource mountpoint"),
f406ba1999-11-27Per Hedbor  TYPE_LOCATION|VAR_MORE|VAR_DEVELOPER,
23414a2000-07-21Andreas Lange  DLOCALE(41, "Some modules may want to create links to internal "
434bac2000-07-14Andreas Lange  "resources. This setting configures an internally handled " "location that can be used for such purposes. Simply select " "a location that you are not likely to use for regular " "resources."));
f498ed2000-07-11Martin Nilsson  // Throttling-related variables defvar("throttle", 0,
23414a2000-07-21Andreas Lange  DLOCALE(42, "Bandwidth Throttling: Server: Enabled"),TYPE_FLAG, DLOCALE(43, "If set, per-server bandwidth throttling will be enabled. "
434bac2000-07-14Andreas Lange  "It will allow you to limit the total available bandwidth for "
f498ed2000-07-11Martin Nilsson  "this Virtual Server.<br />Bandwidth is assigned using a Token Bucket. " "The principle under which it works is: for each byte we send we use a token. " "Tokens are added to a repository at a constant rate. When there's not enough, " "we can't transmit. When there's too many, they \"spill\" and are lost."));
199d031999-09-05Francesco Chemolli  //TODO: move this explanation somewhere on the website and just put a link.
f498ed2000-07-11Martin Nilsson  defvar("throttle_fill_rate", 102400,
23414a2000-07-21Andreas Lange  DLOCALE(44, "Bandwidth Throttling: Server: Average available bandwidth"),
199d031999-09-05Francesco Chemolli  TYPE_INT,
23414a2000-07-21Andreas Lange  DLOCALE(45, "This is the average bandwidth available to this Virtual Server in "
f498ed2000-07-11Martin Nilsson  "bytes/sec (the bucket \"fill rate\")."), 0, arent_we_throttling_server); defvar("throttle_bucket_depth", 1024000,
23414a2000-07-21Andreas Lange  DLOCALE(46, "Bandwidth Throttling: Server: Bucket Depth"), TYPE_INT, DLOCALE(47, "This is the maximum depth of the bucket. After a long enough period "
f498ed2000-07-11Martin Nilsson  "of inactivity, a request will get this many unthrottled bytes of data, before " "throttling kicks back in.<br>Set equal to the Fill Rate in order not to allow " "any data bursts. This value determines the length of the time over which the " "bandwidth is averaged."), 0, arent_we_throttling_server); defvar("throttle_min_grant", 1300,
23414a2000-07-21Andreas Lange  DLOCALE(48, "Bandwidth Throttling: Server: Minimum Grant"), TYPE_INT, DLOCALE(49, "When the bandwidth availability is below this value, connections will "
f498ed2000-07-11Martin Nilsson  "be delayed rather than granted minimal amounts of bandwidth. The purpose " "is to avoid sending too small packets (which would increase the IP overhead)."), 0, arent_we_throttling_server); defvar("throttle_max_grant", 14900,
23414a2000-07-21Andreas Lange  DLOCALE(50, "Bandwidth Throttling: Server: Maximum Grant"), TYPE_INT, DLOCALE(51, "This is the maximum number of bytes assigned in a single request "
f498ed2000-07-11Martin Nilsson  "to a connection. Keeping this number low will share bandwidth more evenly " "among the pending connections, but keeping it too low will increase IP " "overhead and (marginally) CPU usage. You'll want to set it just a tiny " "bit lower than any integer multiple of your network's MTU (typically 1500 " "for ethernet)."), 0, arent_we_throttling_server);
199d031999-09-05Francesco Chemolli  defvar("req_throttle", 0,
23414a2000-07-21Andreas Lange  DLOCALE(52, "Bandwidth Throttling: Request: Enabled"), TYPE_FLAG, DLOCALE(53, "If set, per-request bandwidth throttling will be enabled.")
199d031999-09-05Francesco Chemolli  );
4d16831999-11-17Per Hedbor 
199d031999-09-05Francesco Chemolli  defvar("req_throttle_min", 1024,
23414a2000-07-21Andreas Lange  DLOCALE(54, "Bandwidth Throttling: Request: Minimum guarranteed bandwidth"),
199d031999-09-05Francesco Chemolli  TYPE_INT,
23414a2000-07-21Andreas Lange  DLOCALE(55, "The maximum bandwidth each connection (in bytes/sec) can use is determined "
f498ed2000-07-11Martin Nilsson  "combining a number of modules. But doing so can lead to too small " "or even negative bandwidths for particularly unlucky requests. This variable " "guarantees a minimum bandwidth for each request."), 0, arent_we_throttling_request);
4d16831999-11-17Per Hedbor 
199d031999-09-05Francesco Chemolli  defvar("req_throttle_depth_mult", 60.0,
23414a2000-07-21Andreas Lange  DLOCALE(56, "Bandwidth Throttling: Request: Bucket Depth Multiplier"),
199d031999-09-05Francesco Chemolli  TYPE_FLOAT,
23414a2000-07-21Andreas Lange  DLOCALE(57, "The average bandwidth available for each request will be determined by "
f498ed2000-07-11Martin Nilsson  "the modules combination. The bucket depth will be determined multiplying " "the rate by this factor."), 0, arent_we_throttling_request);
4d16831999-11-17Per Hedbor 
94d4752000-04-05Martin Nilsson  defvar("ZNoSuchFile", #" <html><head> <title>404 - Page not found</title> </head> <body alink=\"#000000\" bgcolor=\"#ffffff\" bottommargin=\"0\" leftmargin=\"0\" link=\"#ce5c00\" marginheight=\"2\" marginwidth=\"0\" rightmargin=\"0\" text=\"#333333\" topmargin=\"2\" vlink=\"#ce5c00\"> <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\"> <tr> <td><img src=\"/internal-roxen-page-not-found\" border=\"0\" alt=\"Page not found\" hspace=\"2\" /></td> <td>&nbsp;</td> <td align=\"right\"><b>&roxen.version;</b></td> </tr> <tr> <td width=\"100%\" height=\"21\" colspan=\"3\" background=\"/internal-roxen-tile\"><img src=\"/internal-roxen-unit\" alt=\"\" /></td> </tr> </table> <font face=\"lucida,helvetica,arial\"> <h2>&nbsp;Unable to retrieve &page.virtfile;.</h2> <br /><br /> <blockquote> If you feel that this is a configuration error, please contact the administrators or the author of the <if referrer> <a href=\"&client.referrer;\">referring</a> </if><else> referring </else> page. </blockquote> </font> </body> ",
23414a2000-07-21Andreas Lange  DLOCALE(58, "Messages: No such file"),TYPE_TEXT_FIELD, DLOCALE(59, "What to return when there is no resource or file "
434bac2000-07-14Andreas Lange  "available at a certain location."));
a7e39f2000-02-04Per Hedbor 
c45e3f2000-02-16Per Hedbor  definvisvar( "no_delayed_load", 0, TYPE_FLAG );
a7e39f2000-02-04Per Hedbor 
a59d252000-07-04Per Hedbor  setvars( retrieve("spider#0", this_object()) );
199d031999-09-05Francesco Chemolli 
07c9921999-11-23Per Hedbor  if (query("throttle"))
c5e0961999-10-04Per Hedbor  {
199d031999-09-05Francesco Chemolli  throttler=.throttler(); throttler->throttle(query("throttle_fill_rate"), query("throttle_bucket_depth"), query("throttle_min_grant"), query("throttle_max_grant")); } } int arent_we_throttling_server () { return !query("throttle"); } int arent_we_throttling_request() { return !query("req_throttle");
14179b1997-01-29Per Hedbor }
b6fb051999-11-02Per Hedbor  string _sprintf( ) { return "Configuration("+name+")"; }