199d031999-09-05Francesco Chemolli /* * A vitual server's main configuration * (C) 1996, 1999 Idonex AB. */
8516a71999-12-22Per Hedbor constant cvs_version = "$Id: configuration.pike,v 1.242 1999/12/21 23:51:33 per Exp $";
4d16831999-11-17Per Hedbor constant is_configuration = 1;
b1fca01996-11-12Per Hedbor #include <module.h>
14179b1997-01-29Per Hedbor #include <roxen.h>
c5e0961999-10-04Per Hedbor #include <request_trace.h>
8afc811998-02-04Per Hedbor 
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) 
b461641998-10-11Henrik Grubbström (Grubba) // Locale support...
b87aa71998-10-15Henrik Grubbström (Grubba) #define LOCALE LOW_LOCALE->base_server
18be211998-05-07Henrik Grubbström (Grubba) 
199d031999-09-05Francesco Chemolli #ifdef THROTTLING_DEBUG #undef THROTTLING_DEBUG #define THROTTLING_DEBUG(X) perror("Throttling: "+X+"\n") #else #define THROTTLING_DEBUG(X) #endif
b1fca01996-11-12Per Hedbor /* A configuration.. */
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; mapping variables = ([]);
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]) return module->variables[variable][VAR_NAME]+ "\n"+module->variables[ variable ][ VAR_DOC_STR ]; } if(variables[ variable ]) return variables[variable][VAR_NAME]+ "\n"+variables[ variable ][ VAR_DOC_STR ]; }
14179b1997-01-29Per Hedbor public mixed query(string var) { if(var && variables[var]) return variables[var][ VAR_VALUE ]; if(!var) return variables;
383fa91997-01-29Per Hedbor  error("query("+var+"): Unknown variable.\n");
14179b1997-01-29Per Hedbor } mixed set(string var, mixed val) { if(variables[var]) return variables[var][VAR_VALUE] = val; error("set("+var+"). Unknown variable.\n"); } int setvars( mapping (string:mixed) vars ) { string v; foreach( indices( vars ), v ) if(variables[v]) variables[v][ VAR_VALUE ] = vars[ v ]; return 1; } void killvar(string name) { m_delete(variables, name); }
4d16831999-11-17Per Hedbor constant ConfigurableWrapper = roxen.ConfigurableWrapper;
7acb8e1998-07-07Henrik Grubbström (Grubba) 
c856841998-01-21Henrik Grubbström (Grubba) int defvar(string var, mixed value, string name, int type, string|void doc_str, mixed|void misc, int|function|void not_in_config)
14179b1997-01-29Per Hedbor {
c5e0961999-10-04Per Hedbor  variables[var] = allocate( VAR_SIZE );
14179b1997-01-29Per Hedbor  variables[var][ VAR_VALUE ] = value;
13ff621997-08-12Per Hedbor  variables[var][ VAR_TYPE ] = type & VAR_TYPE_MASK;
14179b1997-01-29Per Hedbor  variables[var][ VAR_DOC_STR ] = doc_str; variables[var][ VAR_NAME ] = name; variables[var][ VAR_MISC ] = misc;
9b9f701997-08-12Per Hedbor 
df6cd11998-10-13Per Hedbor  Locale.Roxen.standard ->register_module_doc( this_object(), var, name, doc_str );
7acb8e1998-07-07Henrik Grubbström (Grubba)  type &= (VAR_EXPERT | VAR_MORE);
c5e0961999-10-04Per Hedbor  if (functionp(not_in_config)) if (type)
7acb8e1998-07-07Henrik Grubbström (Grubba)  variables[var][ VAR_CONFIGURABLE ] = ConfigurableWrapper(type, not_in_config)->check;
c5e0961999-10-04Per Hedbor  else
7acb8e1998-07-07Henrik Grubbström (Grubba)  variables[var][ VAR_CONFIGURABLE ] = not_in_config;
c5e0961999-10-04Per Hedbor  else if (type)
7acb8e1998-07-07Henrik Grubbström (Grubba)  variables[var][ VAR_CONFIGURABLE ] = type;
c5e0961999-10-04Per Hedbor  else if(intp(not_in_config))
7acb8e1998-07-07Henrik Grubbström (Grubba)  variables[var][ VAR_CONFIGURABLE ] = !not_in_config;
14179b1997-01-29Per Hedbor  variables[var][ VAR_SHORTNAME ] = var; }
df6cd11998-10-13Per Hedbor void deflocaledoc( string locale, string variable,
b796b51998-11-18Per Hedbor  string name, string doc, mapping|void translate )
df6cd11998-10-13Per Hedbor { if( !Locale.Roxen[locale] )
07c9921999-11-23Per Hedbor  report_warning("Invalid locale: "+locale+". Ignoring.\n");
df6cd11998-10-13Per Hedbor  else Locale.Roxen[locale]
b796b51998-11-18Per Hedbor  ->register_module_doc( this_object(), variable, name, doc, translate );
df6cd11998-10-13Per Hedbor }
14179b1997-01-29Per Hedbor int definvisvar(string var, mixed value, int type) { return defvar(var, value, "", type, "", 0, 1); }
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() {
c5e0961999-10-04Per Hedbor  if(strlen(QUERY(name))) return QUERY(name);
b1fca01996-11-12Per Hedbor  return name; } string comment() { return QUERY(comment); }
38dca81996-12-10Per Hedbor 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() {
e351dd1999-11-29Per Hedbor  foreach(url_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping url modules",m->stop && m->stop());
e351dd1999-11-29Per Hedbor  foreach(logger_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping logging modules",m->stop && m->stop());
e351dd1999-11-29Per Hedbor  foreach(filter_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping filter modules",m->stop && m->stop());
e351dd1999-11-29Per Hedbor  foreach(location_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping location modules",m->stop && m->stop());
e351dd1999-11-29Per Hedbor  foreach(last_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping last modules",m->stop && m->stop());
e351dd1999-11-29Per Hedbor  foreach(first_modules, RoxenModule m)
c7a5f01999-02-16Per Hedbor  CATCH("stopping first modules",m->stop && m->stop());
e351dd1999-11-29Per Hedbor  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 /* For debug and statistics info only */ int requests;
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 
48315a1999-11-23Per Hedbor int sent; // Sent data int hsent; // Sent headers int received; // Received data
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  // The logging format used. This will probably move the the above // 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  // All enabled modules in this virtual server.
f569581999-11-23Per Hedbor // The format is "module":{ "copies":([ num:instance, ... ]) } public mapping modules = ([]);
b1fca01996-11-12Per Hedbor  // A mapping from objects to module names
e351dd1999-11-29Per Hedbor public mapping (RoxenModule:string) otomod = ([]);
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()); for(int i=0; i<10; i++) CATCH("stopping priority group",
e351dd1999-11-29Per Hedbor  (pri[i],pri[i]->stop,pri[i]->stop()));
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 {
14179b1997-01-29Per Hedbor  mixed tmp; if(!types_fun) return to?({ "application/octet-stream", 0 }):"application/octet-stream";
41b77c1999-07-15David Hedbor  string ext=myext || extension(file);
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 }
ae32d01998-03-23David Hedbor // Return an array with all provider modules that provides "provides".
e351dd1999-11-29Per Hedbor array (RoxenModule) get_providers(string provides)
ae32d01998-03-23David Hedbor {
d8b7721998-05-28Henrik Grubbström (Grubba)  // FIXME: Is there any way to clear this cache? // /grubba 1998-05-28
9336a81998-07-09Henrik Grubbström (Grubba)  // - Yes, it is zapped together with the rest in invalidate_cache().
ae32d01998-03-23David Hedbor  if(!provider_module_cache[provides]) { int i; provider_module_cache[provides] = ({ }); for(i = 9; i >= 0; i--) {
e351dd1999-11-29Per Hedbor  foreach(indices(pri[i]->provider_modules), RoxenModule d)
ae32d01998-03-23David Hedbor  if(pri[i]->provider_modules[ d ][ provides ]) provider_module_cache[provides] += ({ d }); } } return provider_module_cache[provides]; }
14179b1997-01-29Per Hedbor 
ae32d01998-03-23David Hedbor // Return the first provider module that provides "provides".
e351dd1999-11-29Per Hedbor RoxenModule get_provider(string 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; } // map the function "fun" over all matching provider modules.
bdb8da1998-09-02Johan Schön array(mixed) map_providers(string provides, string fun, mixed ... args)
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;
e351dd1999-11-29Per Hedbor  foreach(prov, RoxenModule mod)
9bb8131998-09-12Per Hedbor  {
ae32d01998-03-23David Hedbor  if(!objectp(mod)) continue; 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]; roxen_perror(describe_backtrace(error)); }
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 } // map the function "fun" over all matching provider modules and // return the first positive response. mixed call_provider(string provides, string fun, mixed ... args) {
e351dd1999-11-29Per Hedbor  foreach(get_providers(provides), RoxenModule mod) {
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]) { 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)
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--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; 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; }
e351dd1999-11-29Per Hedbor array filter_modules(RequestID id)
b1fca01996-11-12Per Hedbor { if(!filter_module_cache) { int i; filter_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]->filter_modules) foreach(d, p) if(p->filter) filter_module_cache+=({ p->filter }); } } return filter_module_cache; }
14179b1997-01-29Per Hedbor void init_log_file()
b1fca01996-11-12Per Hedbor {
14179b1997-01-29Per Hedbor  remove_call_out(init_log_file); if(log_function) destruct(function_object(log_function)); // Free the old one.
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  if(query("Log")) // Only try to open the log file if logging is enabled!!
b1fca01996-11-12Per Hedbor  {
f7d9811997-09-12Per Hedbor  mapping m = localtime(time());
119e241997-05-24Henrik Grubbström (Grubba)  string logfile = query("LogFile");
0a21221998-01-08Henrik Grubbström (Grubba)  m->year += 1900; /* Adjust for years being counted since 1900 */ m->mon++; /* Adjust for months being counted 0-11 */
f7d9811997-09-12Per Hedbor  if(m->mon < 10) m->mon = "0"+m->mon;
0a21221998-01-08Henrik Grubbström (Grubba)  if(m->mday < 10) m->mday = "0"+m->mday;
f7d9811997-09-12Per Hedbor  if(m->hour < 10) m->hour = "0"+m->hour; logfile = replace(logfile,({"%d","%m","%y","%h" }),
0a21221998-01-08Henrik Grubbström (Grubba)  ({ (string)m->mday, (string)(m->mon), (string)(m->year),(string)m->hour,}));
f7d9811997-09-12Per Hedbor  if(strlen(logfile))
b1fca01996-11-12Per Hedbor  {
f7d9811997-09-12Per Hedbor  do {
e351dd1999-11-29Per Hedbor  Stdio.File lf=open( logfile, "wac");
f7d9811997-09-12Per Hedbor  if(!lf) { mkdirhier(logfile); if(!(lf=open( logfile, "wac"))) {
b461641998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->failed_to_open_logfile(logfile));
f7d9811997-09-12Per Hedbor  log_function=0; break;
119e241997-05-24Henrik Grubbström (Grubba)  }
f7d9811997-09-12Per Hedbor  } log_function=lf->write; // Function pointer, speeds everything up (a little..). lf=0; } while(0); } else log_function=0;
14179b1997-01-29Per Hedbor  call_out(init_log_file, 60); } else log_function=0;
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)  // FIXME: This looks like a bug. // Is it supposed to strip all initial whitespace, or do what it does? // /grubba 1997-10-03 while(s[0] == ' ') s = s[1..]; while(s[0] == '\t') s = s[1..];
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 "-"; 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  if(QUERY(NoLog) && _match(request_id->remoteaddr, QUERY(NoLog))) return; if(!(form=log_format[(string)file->error])) form = log_format["*"]; if(!form) return; form=replace(form, ({ "$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"
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), cern_http_date(time(1)), unsigned_to_bin(time(1)), (string)request_id->method,
dfb4ec1999-05-20Francesco Chemolli  http_encode_string((string)request_id->not_query), 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]:"-"), http_encode_string(sizeof(request_id->client||({}))?request_id->client*" ":"-"), 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)  }));
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 
b461641998-10-11Henrik Grubbström (Grubba)  res = "<table>";
8f5abe1999-12-11Per Hedbor  res += LOCALE->config_status(((float)sent/(1024.0*1024.0)), (((float)sent)/(1024.0*1024.0)/dt) * 8192.0, ((float)hsent)/(1024.0*1024.0), requests, (((float)requests * 60.0)/dt), ((float)received)/(1024.0*1024.0));
dc54c41997-08-28Henrik Grubbström (Grubba)  if (!zero_type(misc->ftp_users)) {
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->ftp_status(misc->ftp_users, (((float)misc->ftp_users*(float)60.0)/dt), misc->ftp_users_now);
dc54c41997-08-28Henrik Grubbström (Grubba)  }
926d1a1997-08-31Henrik Grubbström (Grubba)  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.
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->ftp_statistics() + "<br>\n"
12a9c51997-08-11Henrik Grubbström (Grubba)  "<ul><table>\n"; foreach(sort(indices(extra_statistics->ftp->commands)), string cmd) {
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->ftp_stat_line(upper_case(cmd), extra_statistics->ftp->commands[cmd]);
12a9c51997-08-11Henrik Grubbström (Grubba)  } res += "</table></ul>\n"; }
14179b1997-01-29Per Hedbor 
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", LOCALE->no_auth_module(), 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", LOCALE->no_auth_module(), 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", LOCALE->no_auth_module(), 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) { int *s; int uid; mixed *u; 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)
e351dd1999-11-29Per Hedbor  Stdio.File f = open("roxen-images/dir/"+from+".gif","r");
06026c1999-10-19Henrik Grubbström (Grubba)  if (f) { return (["file":f, "type":"image/gif"]); } else { // File not found. return 0; }
14179b1997-01-29Per Hedbor } private static int nest = 0; #ifdef MODULE_LEVEL_SECURITY private mapping misc_cache=([]);
e351dd1999-11-29Per Hedbor int|mapping check_security(function 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) 
14179b1997-01-29Per Hedbor  if(!(seclevels = misc_cache[ a ]))
3b17831998-11-22Per Hedbor  if(function_object(a)->query_seclevels) misc_cache[ a ] = seclevels = ({ function_object(a)->query_seclevels(), function_object(a)->query("_seclvl"), function_object(a)->query("_sec_group") }); else misc_cache[ a ] = seclevels = ({({}),0,"foo" });
14179b1997-01-29Per Hedbor  if(slevel && (seclevels[1] > slevel)) // "Trustlevel" to low. return 1; 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;
14179b1997-01-29Per Hedbor 
cc6d7c1997-07-22Henrik Grubbström (Grubba)  case MOD_DENY: // deny ip=...
b461641998-10-11Henrik Grubbström (Grubba)  // FIXME: LOCALE?
a75a321997-05-14Henrik Grubbström (Grubba)  if(level[1](id->remoteaddr)) return 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;
14179b1997-01-29Per 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. if(id->misc->proxyauth && id->misc->proxyauth[0] && level[1](id->misc->proxyauth[1])) return 0; return http_proxy_auth_required(seclevels[2]); } 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.
c5e0961999-10-04Per Hedbor  return http_auth_failed(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) {
b461641998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->module_security_error(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.
c5e0961999-10-04Per Hedbor  return http_auth_failed(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();
e351dd1999-11-29Per Hedbor  foreach(indices(otomod), RoxenModule m)
c5e0961999-10-04Per Hedbor  if (m && m->clear_memory_caches) if (mixed err = catch( m->clear_memory_caches() ))
b461641998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE-> clear_memory_cache_error(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 // from the configuration interface. :-) private mapping internal_roxen_image(string from) {
c5e0961999-10-04Per Hedbor  // changed 970820 by js to allow for jpeg images
14179b1997-01-29Per Hedbor  sscanf(from, "%s.gif", from); sscanf(from, "%s.jpg", from);
fc94331997-10-25Per Hedbor 
14179b1997-01-29Per Hedbor  // Disallow "internal-roxen-..", 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) // /internal-roxen-../.. was never possible, since that would be remapped to // /..
fc94331997-10-25Per Hedbor  from -= ".";
4154e61997-08-20Johan Schön 
fc94331997-10-25Per Hedbor  // New idea: Automatically generated colorbar. Used by wizard code... int hue,bright,w; if(sscanf(from, "%*s:%d,%d,%d", hue, bright,w)==4) return http_string_answer(draw_saturation_bar(hue,bright,w),"image/gif");
c5e0961999-10-04Per Hedbor  if(Stdio.File f=open("roxen-images/"+from+".gif", "r"))
06026c1999-10-19Henrik Grubbström (Grubba)  return (["file":f, "type":"image/gif"]); else if (f = open("roxen-images/"+from+".jpg", "r")) { return (["file":f, "type":"image/jpeg"]); } else { // 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{
1fab6f1997-09-03Henrik Grubbström (Grubba)  //perror("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  }
1fab6f1997-09-03Henrik Grubbström (Grubba)  //perror("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 if (m->extra_heads && (m->extra_heads->location))
b461641998-10-11Henrik Grubbström (Grubba)  res = LOCALE->returned_redirect_to(m->extra_heads->location);
a1334f1998-02-20Mirar (Pontus Hagland)  else
b461641998-10-11Henrik Grubbström (Grubba)  res = LOCALE->returned_redirect_no_location();
a1334f1998-02-20Mirar (Pontus Hagland)  break; case 401: if (m->extra_heads["www-authenticate"])
b461641998-10-11Henrik Grubbström (Grubba)  res = LOCALE-> returned_authenticate(m->extra_heads["www-authenticate"]);
a1334f1998-02-20Mirar (Pontus Hagland)  else
b461641998-10-11Henrik Grubbström (Grubba)  res = LOCALE->returned_auth_failed();
a1334f1998-02-20Mirar (Pontus Hagland)  break; case 200:
b461641998-10-11Henrik Grubbström (Grubba)  res = LOCALE->returned_ok();
a1334f1998-02-20Mirar (Pontus Hagland)  break; default:
b461641998-10-11Henrik Grubbström (Grubba)  res = LOCALE->returned_error(m->error);
a1334f1998-02-20Mirar (Pontus Hagland)  } if (!zero_type(m->len)) if (m->len<0)
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->returned_no_data();
a1334f1998-02-20Mirar (Pontus Hagland)  else
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->returned_bytes(m->len);
a1334f1998-02-20Mirar (Pontus Hagland)  else if (stringp(m->data))
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->returned_bytes(strlen(m->data));
a1334f1998-02-20Mirar (Pontus Hagland)  else if (objectp(m->file)) if (catch { array a=m->file->stat();
b461641998-10-11Henrik Grubbström (Grubba)  res += LOCALE->returned_bytes(a[1]-m->file->tell()); }) res += LOCALE->returned_unknown_bytes();
a1334f1998-02-20Mirar (Pontus Hagland) 
b461641998-10-11Henrik Grubbström (Grubba)  if (m->data) res += LOCALE->returned_static_data();
7b80781999-02-15Marcus Comstedt  else if (m->file) res += LOCALE->returned_open_file();
a1334f1998-02-20Mirar (Pontus Hagland) 
b461641998-10-11Henrik Grubbström (Grubba)  if (stringp(m->extra_heads["http-content-type"]) || stringp(m->type)) { res += LOCALE->returned_type(m->type); }
a1334f1998-02-20Mirar (Pontus Hagland)  res+="<br>"; return res; }
c5e0961999-10-04Per Hedbor  // The function that actually tries to find the data requested. All // modules are mapped, in order, and the first one that returns a // suitable responce is used.
e351dd1999-11-29Per Hedbor mapping|int low_get_file(RequestID id, int|void no_magic)
14179b1997-01-29Per Hedbor { #ifdef MODULE_LEVEL_SECURITY int slevel; #endif #ifdef THREADS object key; #endif
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->request_for(id->not_query), 0);
14179b1997-01-29Per Hedbor  string file=id->not_query; string loc; function funp; mixed tmp, tmp2; mapping|object fid; if(!no_magic) {
41b77c1999-07-15David Hedbor #ifndef NO_INTERNAL_HACK string type;
14179b1997-01-29Per Hedbor  // No, this is not beautiful... :)
41b77c1999-07-15David Hedbor  // min length == 17 (/internal-roxen-?..) // This will save some time indeed. if(sizeof(file) > 17 && (file[0] == '/') && sscanf(file, "%*s/internal-%s-%[^/]", type, loc) == 3)
14179b1997-01-29Per Hedbor  {
41b77c1999-07-15David Hedbor  switch(type) { case "gopher":
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->magic_internal_gopher());
14179b1997-01-29Per Hedbor  return internal_gopher_image(loc);
41b77c1999-07-15David Hedbor  case "spinner": case "roxen":
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->magic_internal_roxen());
14179b1997-01-29Per Hedbor  return internal_roxen_image(loc);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  } #endif
41b77c1999-07-15David Hedbor 
14179b1997-01-29Per Hedbor  if(id->prestate->diract && dir_module) { LOCK(dir_module);
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->directory_module(), dir_module);
14179b1997-01-29Per Hedbor  tmp = dir_module->parse_directory(id); UNLOCK();
41d0f91998-02-20Per Hedbor  if(mappingp(tmp)) { TRACE_LEAVE("");
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returning_data());
41d0f91998-02-20Per Hedbor  return tmp; } TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  }
5839c31999-01-22Marcus Comstedt  if(!search(file, QUERY(InternalLoc))) { TRACE_ENTER(LOCALE->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)) { TRACE_LEAVE(LOCALE->module_access_denied()); find_internal = 0; } else { TRACE_LEAVE(""); TRACE_LEAVE(LOCALE->request_denied()); return tmp2; } #endif
41b77c1999-07-15David Hedbor  if(find_internal)
5839c31999-01-22Marcus Comstedt  {
8f46d91999-01-22Marcus Comstedt  TRACE_ENTER(LOCALE->calling_find_internal(), find_internal);
5839c31999-01-22Marcus Comstedt  LOCK(find_internal); fid=find_internal( rest, id ); UNLOCK(); TRACE_LEAVE(LOCALE->find_internal_returned(fid)); 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)) TRACE_LEAVE(LOCALE->returned_fd() #ifdef MODULE_LEVEL_SECURITY +(slevel != oslevel? LOCALE->seclevel_is_now(slevel):"") #endif +"."); else TRACE_LEAVE(LOCALE->returned_directory_indicator() #ifdef MODULE_LEVEL_SECURITY +(oslevel != slevel? LOCALE->seclevel_is_now(slevel):"") #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 // 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
5839c31999-01-22Marcus Comstedt  foreach(url_modules(id), funp)
41d0f91998-02-20Per Hedbor  {
5839c31999-01-22Marcus Comstedt  LOCK(funp); TRACE_ENTER(LOCALE->url_module(), funp); tmp=funp( id, file ); UNLOCK(); if(mappingp(tmp)) { TRACE_LEAVE(""); TRACE_LEAVE(LOCALE->returning_data()); return tmp; } if(objectp( tmp )) { array err; nest ++; err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->low_get_file( tmp, no_magic ); else { TRACE_LEAVE(LOCALE->too_deep_recursion()); error("Too deep recursion in roxen::get_file() while mapping " +file+".\n"); } }; nest = 0; if(err) throw(err); TRACE_LEAVE(""); TRACE_LEAVE(LOCALE->returning_data()); return tmp; }
41d0f91998-02-20Per Hedbor  TRACE_LEAVE(""); }
14179b1997-01-29Per Hedbor #endif
c5e0961999-10-04Per Hedbor 
5839c31999-01-22Marcus Comstedt  foreach(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  { TRACE_ENTER(LOCALE->location_module(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)) { TRACE_LEAVE(LOCALE->module_access_denied()); continue; } else { TRACE_LEAVE(""); TRACE_LEAVE(LOCALE->request_denied()); return tmp2; }
14179b1997-01-29Per Hedbor #endif
5839c31999-01-22Marcus Comstedt  TRACE_ENTER(LOCALE->calling_find_file(), 0); LOCK(tmp[1]); fid=tmp[1]( file[ strlen(loc) .. ] + id->extra_extension, id); UNLOCK(); TRACE_LEAVE(LOCALE->find_file_returned(fid)); if(fid)
14179b1997-01-29Per Hedbor  {
5839c31999-01-22Marcus Comstedt  id->virtfile = loc; 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)) TRACE_LEAVE(LOCALE->returned_fd()
41d0f91998-02-20Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  +(slevel != oslevel? LOCALE->seclevel_is_now(slevel):"")
41d0f91998-02-20Per Hedbor #endif
5839c31999-01-22Marcus Comstedt  +"."); else TRACE_LEAVE(LOCALE->returned_directory_indicator()
41d0f91998-02-20Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  +(oslevel != slevel? LOCALE->seclevel_is_now(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) {
5839c31999-01-22Marcus Comstedt  // This one is here to allow accesses to /local, even if // the mountpoint is /local/. It will slow things down, but...
41b77c1999-07-15David Hedbor  TRACE_ENTER(LOCALE->automatic_redirect_to_location(), tmp[1]); TRACE_LEAVE(LOCALE->returning_data());
5839c31999-01-22Marcus Comstedt 
41b77c1999-07-15David Hedbor  // Keep query (if any). /* FIXME: Should probably keep prestate etc. * /grubba 1999-01-14 */ string new_query = http_encode_string(id->not_query) + "/" + (id->query?("?"+id->query):""); return http_redirect(new_query, id);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  } }
41b77c1999-07-15David Hedbor 
14179b1997-01-29Per Hedbor  if(fid == -1) {
41d0f91998-02-20Per Hedbor  if(no_magic) {
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->no_magic());
41d0f91998-02-20Per Hedbor  return -1; }
14179b1997-01-29Per Hedbor  if(dir_module) { LOCK(dir_module);
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->directory_module(), dir_module);
14179b1997-01-29Per Hedbor  fid = dir_module->parse_directory(id); UNLOCK(); } else
41d0f91998-02-20Per Hedbor  {
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->no_directory_module());
14179b1997-01-29Per Hedbor  return 0;
41d0f91998-02-20Per Hedbor  } if(mappingp(fid)) {
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returning_data());
41d0f91998-02-20Per Hedbor  return (mapping)fid; }
14179b1997-01-29Per Hedbor  } // Map the file extensions, but only if there is a file...
41b77c1999-07-15David Hedbor  if(objectp(fid) && (tmp = file_extension_modules(loc = extension(id->not_query, id), id))) {
14179b1997-01-29Per Hedbor  foreach(tmp, funp) {
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->extension_module(loc), funp);
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY if(tmp=check_security(funp, id, slevel)) if(intp(tmp)) {
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->module_access_denied());
14179b1997-01-29Per Hedbor  continue; } else
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->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("");
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returning_data());
14179b1997-01-29Per Hedbor  return tmp;
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  if(fid)
41b77c1999-07-15David Hedbor  destruct(fid);
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->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  }
14179b1997-01-29Per Hedbor  if(objectp(fid)) {
41b77c1999-07-15David Hedbor  if(stringp(id->extension)) {
14179b1997-01-29Per Hedbor  id->not_query += id->extension;
41b77c1999-07-15David Hedbor  loc = extension(id->not_query, id); }
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->content_type_module(), types_module);
41b77c1999-07-15David Hedbor  tmp=type_from_filename(id->not_query, 1, loc);
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(tmp?LOCALE->returned_mime_type(tmp[0],tmp[1]): LOCALE->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] ]);
41d0f91998-02-20Per Hedbor  } TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  return ([ "file":fid, ]); }
41d0f91998-02-20Per Hedbor  if(!fid)
c7a5f01999-02-16Per Hedbor  {
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returned_not_found());
c7a5f01999-02-16Per Hedbor  }
41d0f91998-02-20Per Hedbor  else
b461641998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returning_data());
14179b1997-01-29Per Hedbor  return fid; }
c7a5f01999-02-16Per Hedbor 
e351dd1999-11-29Per Hedbor mixed handle_request( RequestID id )
c7a5f01999-02-16Per Hedbor { function funp; mixed file;
cfda381999-03-28Henrik Grubbström (Grubba) #ifdef REQUEST_DEBUG werror("CONFIG: handle_request()\n"); #endif /* REQUEST_DEBUG */
c7a5f01999-02-16Per Hedbor  foreach(first_modules(id), funp) { if(file = funp( id )) break;
cfda381999-03-28Henrik Grubbström (Grubba)  if(id->conf != this_object()) { #ifdef REQUEST_DEBUG werror("CONFIG: handle_request(): Redirected (2)\n"); #endif /* REQUEST_DEBUG */
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; foreach(last_modules(id), funp) if(ret = funp(id)) break;
cfda381999-03-28Henrik Grubbström (Grubba)  if (ret == 1) { #ifdef REQUEST_DEBUG werror("CONFIG: handle_request(): Recurse\n"); #endif /* REQUEST_DEBUG */
c7a5f01999-02-16Per Hedbor  return handle_request(id);
cfda381999-03-28Henrik Grubbström (Grubba)  }
c7a5f01999-02-16Per Hedbor  file = ret; }
cfda381999-03-28Henrik Grubbström (Grubba) #ifdef REQUEST_DEBUG werror("CONFIG: handle_request(): Done\n"); #endif /* REQUEST_DEBUG */
c7a5f01999-02-16Per Hedbor  return file; }
e351dd1999-11-29Per Hedbor mixed get_file(RequestID id, int|void no_magic)
14179b1997-01-29Per Hedbor { mixed res, res2; function tmp; res = low_get_file(id, no_magic); // finally map all filter type modules. // Filter modules are like TYPE_LAST modules, but they get called // for _all_ files. foreach(filter_modules(id), tmp)
41d0f91998-02-20Per Hedbor  {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->filter_module(), tmp);
14179b1997-01-29Per Hedbor  if(res2=tmp(res,id)) { if(res && res->file && (res2->file != res->file)) destruct(res->file);
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->rewrote_result());
14179b1997-01-29Per Hedbor  res=res2;
41d0f91998-02-20Per Hedbor  } else TRACE_LEAVE(""); }
14179b1997-01-29Per Hedbor  return res; }
e351dd1999-11-29Per Hedbor public array find_dir(string file, RequestID id)
14179b1997-01-29Per Hedbor { string loc;
29a8071998-08-21David Hedbor  array dir = ({ }), tmp; array | mapping d;
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->list_directory(file), 0);
c7a5f01999-02-16Per Hedbor // file=replace(file, "//", "/");
14179b1997-01-29Per Hedbor 
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);
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->url_module(), funp);
f128901997-08-15Henrik Grubbström (Grubba)  tmp=funp( id, file ); UNLOCK(); if(mappingp( tmp )) { id->not_query=of;
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returned_no_thanks());
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) { array err; nest ++;
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->recursing());
f128901997-08-15Henrik Grubbström (Grubba)  file = id->not_query; err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->find_dir( file, id ); 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); return tmp; } id->not_query=of; }
a86c6c1997-09-22Henrik Grubbström (Grubba) #endif /* URL_MODULES */
f128901997-08-15Henrik Grubbström (Grubba) 
14179b1997-01-29Per Hedbor  foreach(location_modules(id), tmp) { loc = tmp[0];
a476711997-10-20Henrik Grubbström (Grubba)  if(!search(file, loc)) { /* file == loc + subpath */
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->location_module(loc), tmp[1]);
a78a591997-04-28Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY
41d0f91998-02-20Per Hedbor  if(check_security(tmp[1], id)) {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->permission_denied());
41d0f91998-02-20Per Hedbor  continue; }
a78a591997-04-28Henrik Grubbström (Grubba) #endif
8dbe2d1997-05-26Henrik Grubbström (Grubba)  if(d=function_object(tmp[1])->find_dir(file[strlen(loc)..], id))
41d0f91998-02-20Per Hedbor  {
29a8071998-08-21David Hedbor  if(mappingp(d)) { if(d->files) { dir |= d->files;
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->got_exclusive_dir()); TRACE_LEAVE(LOCALE->returning_file_list(sizeof(dir)));
29a8071998-08-21David Hedbor  return dir; } else TRACE_LEAVE(""); } else {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->got_files());
29a8071998-08-21David Hedbor  dir |= d; }
41d0f91998-02-20Per Hedbor  } else TRACE_LEAVE("");
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)  */
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->location_module(loc), tmp[1]);
a476711997-10-20Henrik Grubbström (Grubba)  loc=loc[strlen(file)..]; sscanf(loc, "%s/", loc); dir += ({ loc });
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->added_module_mountpoint());
14179b1997-01-29Per Hedbor  } } if(sizeof(dir))
41d0f91998-02-20Per Hedbor  {
cfda381999-03-28Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returning_file_list(sizeof(dir)));
14179b1997-01-29Per Hedbor  return dir;
41d0f91998-02-20Per Hedbor  }
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returning_no_dir());
14179b1997-01-29Per Hedbor } // Stat a virtual file.
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
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->stat_file(file), 0);
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;
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->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("");
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returned_no_thanks());
f128901997-08-15Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) { file = id->not_query; array err; nest ++;
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->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("");
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->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
14179b1997-01-29Per Hedbor  // Map location-modules. foreach(location_modules(id), tmp) { loc = tmp[0]; if((file == loc) || ((file+"/")==loc))
41d0f91998-02-20Per Hedbor  {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->location_module(loc), tmp[1]); TRACE_LEAVE(LOCALE->exact_match());
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
d0a47d1997-04-29Henrik Grubbström (Grubba)  return ({ 0775, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  if(!search(file, loc)) {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->location_module(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("");
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->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("");
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->stat_ok());
14179b1997-01-29Per Hedbor  return s;
41d0f91998-02-20Per Hedbor  } TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  } }
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returned_not_found());
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) { throw( ({ "File not open for write", backtrace() }) ); } 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. :-)
e351dd1999-11-29Per Hedbor public array open_file(string fname, string mode, RequestID id)
e8790b1998-02-19Per Hedbor { object oc = id->conf; string oq = id->not_query; function funp; mapping file;
cd7ea41998-12-14Peter Bortas  id->not_query = fname;
c7a5f01999-02-16Per Hedbor 
e8790b1998-02-19Per Hedbor  foreach(oc->first_modules(), funp) if(file = funp( id )) break; else if(id->conf != oc) { return open_file(fname, mode,id); } 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) { file = oc->get_file( id );
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. return open_file(id->not_query, mode, id); } }
e8790b1998-02-19Per Hedbor  } if(!mappingp(file)) { if(id->misc->error_code)
001ae71998-10-11Henrik Grubbström (Grubba)  file = http_low_answer(id->misc->error_code, "Failed" );
2380831998-02-22Per Hedbor  else if(id->method!="GET"&&id->method != "HEAD"&&id->method!="POST")
e8790b1998-02-19Per Hedbor  file = http_low_answer(501, "Not implemented."); else file=http_low_answer(404,replace(parse_rxml(query("ZNoSuchFile"),id), ({"$File", "$Me"}), ({fname,query("MyWorldLocation")}))); id->not_query = oq;
c7a5f01999-02-16Per Hedbor 
e8790b1998-02-19Per Hedbor  return ({ 0, file }); }
d08a251999-06-25Per Hedbor  if( file->data )
e8790b1998-02-19Per Hedbor  { file->file = StringFile(file->data); m_delete(file, "data");
2380831998-02-22Per Hedbor  }
e8790b1998-02-19Per Hedbor  id->not_query = oq; return ({ file->file, file }); } id->not_query = oq;
001ae71998-10-11Henrik Grubbström (Grubba)  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, "//", "/"); if(file[0] != '/') file = "/" + file;
ae60b61998-05-23Henrik Grubbström (Grubba)  // FIXME: Should I append a "/" to file if missing?
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->find_dir_stat(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);
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->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 roxen_perror(sprintf("conf->find_dir_stat(\"%s\"): url_module returned mapping:%O\n", file, tmp)); #endif /* MODULE_DEBUG */
07014c1999-05-24Per Hedbor  TRACE_LEAVE(LOCALE->returned_mapping()+sprintf("%O", tmp)); TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) { array err; nest ++; 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 {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->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 roxen_perror(sprintf("conf->find_dir_stat(\"%s\"): url_module returned object:\n", file)); #endif /* MODULE_DEBUG */
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_LEAVE(LOCALE->returned_object()); TRACE_LEAVE(LOCALE->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) 
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->location_module(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) {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->has_find_dir_stat(), 0);
a86c6c1997-09-22Henrik Grubbström (Grubba)  if (d = c->find_dir_stat(f, id)) {
07014c1999-05-24Per Hedbor  TRACE_ENTER(LOCALE->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)) {
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->returned_array(), 0);
e351dd1999-11-29Per Hedbor  dir = mkmapping(d, Array.map(d, lambda(string fn) { 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)  */
001ae71998-10-11Henrik Grubbström (Grubba)  TRACE_ENTER(LOCALE->file_on_mountpoint_path(file, loc), 0);
a476711997-10-20Henrik Grubbström (Grubba)  loc=loc[strlen(file)..]; sscanf(loc, "%s/", loc); if (!dir[loc]) { dir[loc] = ({ 0775, -3, 0, 0, 0, 0, 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; file=replace(file, "//", "/"); // "//" is really "/" here... // 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 } // Return the _real_ filename of a virtual file, if any.
e351dd1999-11-29Per Hedbor public string real_file(string file, RequestID id)
14179b1997-01-29Per Hedbor { string loc; string s; array tmp; file=replace(file, "//", "/"); // "//" is really "/" here... if(!id) error("No id passed to real_file"); // Map location-modules. foreach(location_modules(id), tmp) { loc = tmp[0]; if(!search(file, loc)) { #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; } } } // Convenience functions 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.
e351dd1999-11-29Per Hedbor int|string try_get_file(string s, RequestID id, int|void status, int|void nocache)
14179b1997-01-29Per Hedbor { string res, q;
e351dd1999-11-29Per Hedbor  RequestID fake_id;
14179b1997-01-29Per Hedbor  mapping m;
e351dd1999-11-29Per Hedbor  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 = ([]); fake_id = id->clone_me(); fake_id->misc->common = id->misc->common;
ead2a11999-04-14Henrik Grubbström (Grubba)  if(!id->pragma["no-cache"] && !nocache && (!id->auth || !id->auth[0]))
14179b1997-01-29Per Hedbor  if(res = cache_lookup("file:"+id->conf->name, s)) return res; if(sscanf(s, "%s?%s", s, q)) { string v, name, value; foreach(q/"&", v)
4bf5f91997-03-13David KÃ¥gedal  if(sscanf(v, "%s=%s", name, value))
c5e0961999-10-04Per Hedbor  fake_id->variables[http_decode_string(name)]= http_decode_string(value);
14179b1997-01-29Per Hedbor  fake_id->query=q; } fake_id->raw_url=s; fake_id->not_query=s; fake_id->misc->internal_get=1; if(!(m = get_file(fake_id))) return 0;
889d031999-10-04Per Hedbor 
3510fb1997-11-09Henrik Grubbström (Grubba)  if (!(< 0, 200, 201, 202, 203 >)[m->error]) return 0;
14179b1997-01-29Per Hedbor 
3510fb1997-11-09Henrik Grubbström (Grubba)  if(status) return 1;
a22f6f1999-05-12Per Hedbor  if(m->data) res = m->data; else res="";
14179b1997-01-29Per Hedbor  m->data = 0; if(m->file) {
3a4d7e1997-09-03Per Hedbor  res += m->file->read();
14179b1997-01-29Per Hedbor  destruct(m->file); m->file = 0; } if(m->raw) { res -= "\r"; if(!sscanf(res, "%*s\n\n%s", res)) sscanf(res, "%*s\n%s", res); }
c5e0961999-10-04Per Hedbor  if (!id->auth || !id->auth[0])
ead2a11999-04-14Henrik Grubbström (Grubba)  cache_set("file:"+id->conf->name, s, res);
14179b1997-01-29Per Hedbor  return res; } // Is 'what' a file in our virtual filesystem?
e351dd1999-11-29Per Hedbor int(0..1) is_file(string what, RequestID id)
14179b1997-01-29Per Hedbor { return !!stat_file(what, id); }
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  } } // Save this configuration. If all is included, save all configuration // global variables as well, otherwise only all module variables.
e7e6031999-11-05Per Hedbor void save_me() { save_one( 0 ); }
14179b1997-01-29Per Hedbor void save(int|void all) { if(all) {
3f628a1999-12-09Martin Stjernholm  store("spider#0", variables, 0, this_object());
14179b1997-01-29Per Hedbor  start(2); }
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 } // Save all variables in _one_ module.
e351dd1999-11-29Per Hedbor int save_one( RoxenModule o )
14179b1997-01-29Per Hedbor { mapping mod; if(!o) {
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"); store(q, o->query(), 0, this_object()); invalidate_cache(); o->start(2, this_object()); invalidate_cache(); return 1;
14179b1997-01-29Per Hedbor }
f569581999-11-23Per Hedbor void reload_module( string modname )
5964251999-11-19Per Hedbor {
e351dd1999-11-29Per Hedbor  RoxenModule old_module = find_module( modname );
1f56521999-11-23Per Hedbor  int do_delete_doto;
f569581999-11-23Per Hedbor  if( !old_module ) return;
c63f771999-11-24Per Hedbor  master()->refresh_inherit( object_program( old_module ) );
1f56521999-11-23Per Hedbor 
f569581999-11-23Per Hedbor  if( enable_module( modname ) == old_module ) return; catch( disable_module( modname ) ); if( enable_module( modname ) == 0 ) enable_module( modname, old_module );
5964251999-11-19Per Hedbor }
7e446c1999-11-24Per Hedbor class ModuleCopies { mapping copies = ([]); string _sprintf( ) { return "ModuleCopies()"; } }
e351dd1999-11-29Per Hedbor RoxenModule enable_module( string modname, RoxenModule|void me )
14179b1997-01-29Per Hedbor {
c5e0961999-10-04Per Hedbor  int id;
e351dd1999-11-29Per Hedbor  ModuleInfo moduleinfo; 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 )
4f43eb1999-11-05Per Hedbor  while( modules[modname] && modules[modname]->copies[id] ) id++;
c5e0961999-10-04Per Hedbor 
7f00081998-03-20Per Hedbor  int start_time = gethrtime();
25171c1999-11-06Per Hedbor 
c5e0961999-10-04Per Hedbor  moduleinfo = roxen->find_module( modname );
ad683e1998-05-09Henrik Grubbström (Grubba) 
c5e0961999-10-04Per Hedbor  if (!moduleinfo)
ad683e1998-05-09Henrik Grubbström (Grubba)  {
3bbda81997-06-11Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
f569581999-11-23Per Hedbor  report_warning("Failed to load %s\n", modname);
3bbda81997-06-11Henrik Grubbström (Grubba) #endif
c5e0961999-10-04Per Hedbor  return 0; }
3bbda81997-06-11Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  if( id )
c45b2a1999-12-09Martin Stjernholm  report_debug(" %-33s ... \b", moduleinfo->get_name()+" copy "+(id+1));
c5e0961999-10-04Per Hedbor  else
c45b2a1999-12-09Martin Stjernholm  report_debug(" %-33s ... \b", moduleinfo->get_name() );
3bbda81997-06-11Henrik Grubbström (Grubba) #endif
c5e0961999-10-04Per Hedbor  module = modules[ module ]; 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 report_debug("\b ERROR\n"); #endif
f569581999-11-23Per Hedbor  report_error(LOCALE-> error_initializing_module_copy(moduleinfo->get_name(), describe_backtrace(err))); return module->copies[id]; }
c5e0961999-10-04Per Hedbor  }
f569581999-11-23Per Hedbor  if(module->copies[id] && module->copies[id] != me)
c5e0961999-10-04Per Hedbor  {
f569581999-11-23Per Hedbor  module->copies[id]->stop(); // 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 { me->defvar("_priority", 5, "Priority", TYPE_INT_LIST, "The priority of the module. 9 is highest and 0 is lowest." " Modules with the same priority can be assumed to be " "called in random order", ({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); me->deflocaledoc("svenska", "_priority", "Prioritet", "Modulens prioritet, 9 är högst och 0 är" " lägst. Moduler med samma prioritet anropas i " "mer eller mindre slumpmässig ordning."); }) { throw(err); }
3b17831998-11-22Per Hedbor  }
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type != MODULE_LOGGER && module_type != MODULE_PROVIDER)
ad683e1998-05-09Henrik Grubbström (Grubba)  {
c5e0961999-10-04Per Hedbor  if(!(module_type & MODULE_PROXY))
14179b1997-01-29Per Hedbor  {
ad683e1998-05-09Henrik Grubbström (Grubba)  me->defvar("_sec_group", "user", "Security: Realm", TYPE_STRING, "The realm to use when requesting password from the " "client. Usually used as an informative message to the " "user.");
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_sec_group", "Säkerhet: Grupp", "Gruppnamnet som används när klienten bes" " ange lösenord. I de flesta klienter visas den " " här informationen för användaren i"
3b17831998-11-22Per Hedbor  " lösenordsdialogen.");
df6cd11998-10-13Per Hedbor 
3bf3451998-10-01Peter Bortas  me->defvar("_seclvl", 0, "Security: Security level", TYPE_INT, "The modules security level is used to determine if a " " 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>" " <li>A requests initial Trust level is infinitely high." " <li> A request will only be handled by a module if its" " <i>trust level</i> is higher or equal to the" " <i>security level</i> of the module." " <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" " <i>security level</i>." " </ul>" "\n<p><h2>Example</h2>" " Modules:<ul>" " <li> User filesystem, <i>security level</i> 1" " <li> Filesystem module, <i>security level</i> 3" " <li> CGI module, <i>security level</i> 2" " </ul>" "\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" " level." "\n<p>On the other hand, a request handled by the the" " \"Filsystem module\" could later be handled by the" " \"CGI module\".");
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_seclvl", "Säkerhet: Säkerhetsnivå", "Modulens säkerhetsnivå används för att avgöra om " " en specifik request ska få hanteras av modulen. " "\n<p><h2>Säkerhetsnivå och pålitlighetsnivå</h2>" " Varje modul har en konfigurerbar " "<i>säkerhtesnivå</i>. " "Varje request har en <i>pålitlighetsnivå</i>.<p>" "Högre <i>pålitlighetsnivåer</i> ger " " requesten tillgång till moduler med högre " "<i>säkerhetsnivå</i>. <p>\n" "\n<p><h2>Defenitioner</h2><ul>" " <li>En requests initialpålitlighetsnivå är " " oändligt hög." " <li> En request hanteras bara av moduler om " "dess <i>pålitlighetsnivå</i> är högre eller " " lika hög som modulens <i>säkerhetsnivå</i>" " <li> Varje gång en request hanteras av en" " modul så sätts dess <i>pålitlighetsnivå</i> " "till modulens <i>säkerhetsnivå</i> om " " modulen har en <i>säkerhetsnivå</i> som är " "skiljd from noll. " " </ul>" "\n<p><h2>Ett exempel</h2>" " Moduler:<ul>" " <li> Användarfilsystem, <i>säkerhetsnivå</i> 1" " <li> Filesystem, <i>säkerhetsnivå</i> 3" " <li> CGI modul, <i>säkerhetsnivå</i> 2" " </ul>" "\n<p>En request hanterad av " " <i>Användarfilsystemet</i> får ett " "som <i>pålitlighetsnivå</i>. Den här" " requesten kan därför inte skickas vidare " "till <i>CGI modulen</i> eftersom den har" " en <i>säkerhetsnivå</i> som är högre än" " requestens <i>pålitlighetsnivå</i>.<p>" " Å andra sidan så kan en request som " " hanteras av <i>Filsystem</i> modulen " " skickas vidare till <i>CGI modulen</i>.");
ad683e1998-05-09Henrik Grubbström (Grubba)  me->defvar("_seclevels", "", "Security: Patterns", TYPE_TEXT_FIELD, "This is the 'security level=value' list.<br>" "Each security level can be any or more from this list:" "<hr 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>" "In patterns: * matches one or more characters, " "and ? matches one character.<p>" "In username: 'any' stands for any valid account " "(from .htaccess"
0026281999-06-07Martin Stjernholm  " or an auth module. The default (used when _no_ "
ad683e1998-05-09Henrik Grubbström (Grubba)  "entries are present) is 'allow ip=*', allowing" " everyone to access the module");
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_seclevels", "Säkerhet: Behörighetsregler", "Det här är en lista av behörighetsregler.<p>" "Varje behörighetsregler måste följa någon av de " " här mönstren: " "<hr noshade>" "allow ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" "allow ip=<i>IP-nummer</i>:<i>nätmask</i><br>" "allow ip=<i>globmönster</i><br>" "allow user=<i>användarnamn</i>,...<br>" "deny ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" "deny ip=<i>IP-nummer</i>:<i>nätmask</i><br>" "deny ip=<i>globmönster</i><br>" "<hr noshade>" "I globmänster betyer '*' ett eller flera " "godtyckliga tecken, och '?' betyder exekt " "ett godtyckligt tecken.<p> " "Användnamnet 'any' kan användas för att ange " "att vilken giltig användare som helst ska " " kunna få använda modulen.");
ad683e1998-05-09Henrik Grubbström (Grubba)  } else { me->definvisvar("_seclvl", -10, TYPE_INT); /* A very low one */
14179b1997-01-29Per Hedbor 
ad683e1998-05-09Henrik Grubbström (Grubba)  me->defvar("_sec_group", "user", "Proxy Security: Realm", TYPE_STRING, "The realm to use when requesting password from the " "client. Usually used as an informative message to the " "user.");
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_sec_group", "Säkerhet: Grupp", "Gruppnamnet som används när klienten bes" " ange lösenord. I de flesta klienter visas den " " här informationen för användaren i" "lösenordsdialogen.");
ad683e1998-05-09Henrik Grubbström (Grubba)  me->defvar("_seclevels", "", "Proxy security: Patterns", TYPE_TEXT_FIELD, "This is the 'security level=value' list.<br>" "Each security level can be any or more from " "this list:<br>" "<hr noshade>" "allow ip=pattern<br>" "allow user=username,...<br>" "deny ip=pattern<br>" "<hr noshade>" "In patterns: * is on or more characters, ? is one " " character.<p>" "In username: 'any' stands for any valid account" " (from .htaccess"
0026281999-06-07Martin Stjernholm  " or an auth module. The default is 'deny ip=*'");
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_seclevels", "Säkerhet: Behörighetsregler", "Det här är en lista av behörighetsregler.<p>" "Varje behörighetsregler måste följa någon av de " " här mönstren: " "<hr noshade>" "allow ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" "allow ip=<i>IP-nummer</i>:<i>nätmask</i><br>" "allow ip=<i>globmönster</i><br>" "allow user=<i>användarnamn</i>,...<br>" "deny ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" "deny ip=<i>IP-nummer</i>:<i>nätmask</i><br>" "deny ip=<i>globmönster</i><br>" "<hr noshade>" "I globmänster betyer '*' ett eller flera " "godtyckliga tecken, och '?' betyder exekt " "ett godtyckligt tecken.<p> " "Användnamnet 'any' kan användas för att ange " "att vilken giltig användare som helst ska " " kunna få använda modulen.");
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 
ad683e1998-05-09Henrik Grubbström (Grubba)  me->defvar("_comment", "", " Comment", TYPE_TEXT_FIELD|VAR_MORE, "An optional comment. This has no effect on the module, it " "is only a text field for comments that the administrator " "might have (why the module are here, etc.)");
14179b1997-01-29Per Hedbor 
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_comment", "Kommentar", "En kommentar. Den här kommentaren påverkar inte " " funktionaliteten hos modulen på något sätt, den " " syns bara i konfigurationsinterfacet.");
ad683e1998-05-09Henrik Grubbström (Grubba)  me->defvar("_name", "", " Module name", TYPE_STRING|VAR_MORE,
3b17831998-11-22Per Hedbor  "An optional name. You can set it to something to remaind you what "
ad683e1998-05-09Henrik Grubbström (Grubba)  "the module really does.");
14179b1997-01-29Per Hedbor 
df6cd11998-10-13Per Hedbor  me->deflocaledoc("svenska", "_name", "Namn", "Modulens namn. Om den här variablen är satt så " "används dess värde istället för modulens riktiga namn " "i konfigurationsinterfacet.");
c5e0961999-10-04Per Hedbor  me->setvars(retrieve(modname + "#" + id, this_object()));
33e6351998-02-28Martin Stjernholm 
c5e0961999-10-04Per Hedbor  module->copies[ id ] = me;
37c1b31999-10-12Per Hedbor  otomod[ me ] = modname+"#"+id;
14179b1997-01-29Per Hedbor 
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
c45b2a1999-12-09Martin Stjernholm  report_debug("\b ERROR\n");
c5e0961999-10-04Per Hedbor #endif
001ae71998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->
c5e0961999-10-04Per Hedbor  error_initializing_module_copy(moduleinfo->get_name(),
001ae71998-10-11Henrik Grubbström (Grubba)  describe_backtrace(err)));
ad683e1998-05-09Henrik Grubbström (Grubba) 
c5e0961999-10-04Per Hedbor 
ad683e1998-05-09Henrik Grubbström (Grubba)  /* Clean up some broken references to this module. */ m_delete(otomod, me);
0ca08a1999-10-04Marcus Comstedt  if(module->copies) m_delete(module->copies, id);
ad683e1998-05-09Henrik Grubbström (Grubba)  destruct(me); return 0; }
c5e0961999-10-04Per Hedbor  if (err = catch(pr = me->query("_priority"))) {
c45b2a1999-12-09Martin Stjernholm #ifdef MODULE_DEBUG report_debug("\b ERROR\n"); #endif
001ae71998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->
c5e0961999-10-04Per Hedbor  error_initializing_module_copy(moduleinfo->get_name(),
001ae71998-10-11Henrik Grubbström (Grubba)  describe_backtrace(err)));
ad683e1998-05-09Henrik Grubbström (Grubba)  pr = 3; } api_module_cache |= me->api_functions();
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_EXTENSION) { report_error( moduleinfo->get_name()+ " 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"); }
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();
c5e0961999-10-04Per Hedbor  if (arrayp(arr)) {
ad683e1998-05-09Henrik Grubbström (Grubba)  string foo; foreach( me->query_file_extensions(), foo ) if(pri[pr]->file_extension_modules[foo] ) pri[pr]->file_extension_modules[foo]+=({me}); else pri[pr]->file_extension_modules[foo]=({me}); }
c45b2a1999-12-09Martin Stjernholm  }) { #ifdef MODULE_DEBUG report_debug("\b ERROR\n"); #endif
001ae71998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->
c5e0961999-10-04Per Hedbor  error_initializing_module_copy(moduleinfo->get_name(),
001ae71998-10-11Henrik Grubbström (Grubba)  describe_backtrace(err)));
c45b2a1999-12-09Martin Stjernholm  }
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_PROVIDER) if (err = catch {
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 report_debug("\b ERROR\n"); #endif
001ae71998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->
c5e0961999-10-04Per Hedbor  error_initializing_module_copy(moduleinfo->get_name(), describe_backtrace(err)));
c45b2a1999-12-09Martin Stjernholm  }
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_TYPES)
ad683e1998-05-09Henrik Grubbström (Grubba)  { types_module = me; types_fun = me->type_from_extension; }
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 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_FIRST)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->first_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(!enabled_modules[ modname+"#"+id ])
ad683e1998-05-09Henrik Grubbström (Grubba)  { enabled_modules[modname+"#"+id] = 1;
c5e0961999-10-04Per Hedbor  store( "EnabledModules", enabled_modules, 1, this_object());
ad683e1998-05-09Henrik Grubbström (Grubba)  } invalidate_cache();
c45b2a1999-12-09Martin Stjernholm #ifdef MODULE_DEBUG report_debug("\b OK %5.1fms.\n", (gethrtime()-start_time)/1000.0); #endif
ad683e1998-05-09Henrik Grubbström (Grubba)  return me;
14179b1997-01-29Per Hedbor } // Called from the configuration interface.
199d031999-09-05Francesco Chemolli string check_variable(string name, mixed value)
14179b1997-01-29Per Hedbor { switch(name) { case "MyWorldLocation": if(strlen(value)<7 || value[-1] != '/' || !(sscanf(value,"%*s://%*s/")==2))
001ae71998-10-11Henrik Grubbström (Grubba)  return LOCALE->url_format();
4f4bc11998-02-04Per Hedbor  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 { THROTTLING_DEBUG("configuration: Stopping throttler"); destruct(throttler); throttler=0; } 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  } } int disable_module( string modname ) {
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 ];
14179b1997-01-29Per Hedbor  if(!module) {
001ae71998-10-11Henrik Grubbström (Grubba)  report_error(LOCALE->disable_nonexistant_module(modname));
14179b1997-01-29Per Hedbor  return 0; }
c5e0961999-10-04Per Hedbor  me = module->copies[id]; m_delete(module->copies, id); 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) {
c5e0961999-10-04Per Hedbor  if( id ) report_error(LOCALE->disable_module_failed(moduleinfo->get_name() +" # "+id)); else report_error(LOCALE->disable_module_failed(moduleinfo->get_name()));
14179b1997-01-29Per Hedbor  return 0; } if(me->stop) me->stop(); #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  if( id ) report_debug("Disabling "+moduleinfo->get_name()+" # "+id+"\n"); else report_debug("Disabling "+moduleinfo->get_name()+"\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); }
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 );
c5e0961999-10-04Per Hedbor  store( "EnabledModules",enabled_modules, 1, this_object());
14179b1997-01-29Per Hedbor  } destruct(me); return 1; }
e351dd1999-11-29Per Hedbor RoxenModule|string find_module(string name)
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 );
0ce25d1999-11-15Per Hedbor  if( ((now && !modules[ mod ]) || !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++ )
c45b2a1999-12-09Martin Stjernholm  report_debug("\b[ adding required modules\n");
14179b1997-01-29Per Hedbor #endif
0ce25d1999-11-15Per Hedbor  forcibly_added[ mod+"#0" ] = 1; enable_module( mod+"#0" );
14179b1997-01-29Per Hedbor  }
8f061b1999-11-19Per Hedbor  }
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  if( wr ) report_debug("]\n");
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 + "/"; }
0f28da1997-08-13Per Hedbor void enable_all_modules()
14179b1997-01-29Per Hedbor {
c5e0961999-10-04Per Hedbor  enabled_modules = retrieve("EnabledModules", this_object());
8516a71999-12-22Per Hedbor  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();
c5e0961999-10-04Per Hedbor  int start_time = gethrtime();
25171c1999-11-06Per Hedbor 
c5e0961999-10-04Per Hedbor  report_debug("\nEnabling all modules for "+query_name()+"... \n");
acfd171998-04-21Henrik Grubbström (Grubba) 
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 = (<>);
0f28da1997-08-13Per Hedbor  foreach( modules_to_process, tmp_string )
f5a2741999-10-18Per Hedbor  { if( !forcibly_added[ tmp_string ] ) if(err = catch( enable_module( tmp_string ))) report_error(LOCALE->enable_module_failed(tmp_string, describe_backtrace(err))); }
8516a71999-12-22Per Hedbor  roxenloader.pop_compile_error_handler(); if( strlen( ec->get() ) ) report_error( "While enabling modules in "+name+":\n"+ec->get() );
07c9921999-11-23Per Hedbor  report_notice("All modules for %s enabled in %3.1f seconds\n\n", query_name(),(gethrtime()-start_time)/1000000.0);
0f28da1997-08-13Per Hedbor } void create(string config) {
69161e1999-12-13Per Hedbor  add_parse_module( (object)this_object() );
14179b1997-01-29Per Hedbor  name=config;
001ae71998-10-11Henrik Grubbström (Grubba) 
5d87801997-11-29Henrik Grubbström (Grubba)  defvar("ZNoSuchFile", "<title>Sorry. I cannot find this resource</title>\n" "<body bgcolor='#ffffff' text='#000000' alink='#ff0000' " "vlink='#00007f' link='#0000ff'>\n" "<h2 align=center><configimage src=roxen.gif alt=\"File not found\">\n"
14179b1997-01-29Per Hedbor  "<p><hr noshade>" "\n<i>Sorry</i></h2>\n"
45165f1997-08-13Peter Bortas  "<br clear>\n<font size=\"+2\">The resource requested "
14179b1997-01-29Per Hedbor  "<i>$File</i>\ncannot be found.<p>\n\nIf you feel that this is a " "configuration error, please contact "
5d87801997-11-29Henrik Grubbström (Grubba)  "the administrators or the author of the\n" "<if referrer>" "<a href=\"<referrer>\">referring</a>" "</if>\n" "<else>referring</else>\n" "page."
14179b1997-01-29Per Hedbor  "<p>\n</font>\n" "<hr noshade>"
5d87801997-11-29Henrik Grubbström (Grubba)  "<version>, at <a href=\"$Me\">$Me</a>.\n" "</body>\n",
14179b1997-01-29Per Hedbor  "Messages: No such file", TYPE_TEXT_FIELD, "What to return when there is no resource or file available " "at a certain location. $File will be replaced with the name " "of the resource requested, and $Me with the URL of this server ");
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "ZNoSuchFile", "Meddelanden: Filen finns inte", #"Det här meddelandet returneras om en användare frågar efter en resurs som inte finns. '$File' byts ut mot den efterfrågade
c5e0961999-10-04Per Hedbor  resursen, och '$Me' med serverns URL");
b796b51998-11-18Per Hedbor 
9b9f701997-08-12Per Hedbor  defvar("comment", "", "Virtual server comment", TYPE_TEXT_FIELD|VAR_MORE,
14179b1997-01-29Per Hedbor  "This text will be visible in the configuration interface, it " " can be quite useful to use as a memory helper.");
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "comment", "Kommentar", "En kommentar som syns i konfigurationsinterfacet");
9b9f701997-08-12Per Hedbor  defvar("name", "", "Virtual server name", TYPE_STRING|VAR_MORE,
14179b1997-01-29Per Hedbor  "This is the name that will be used in the configuration " "interface. If this is left empty, the actual name of the " "virtual server will be used");
c5e0961999-10-04Per Hedbor 
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "name", "Serverns namn", #"Det här är namnet som kommer att synas i konfigurationsgränssnittet. Om du lämnar det här fältet tomt kommer serverns ursprungliga namn (det du skrev in när du skapade servern) att användas.");
14179b1997-01-29Per Hedbor  defvar("LogFormat", "404: $host $referer - [$cern_date] \"$method $resource $protocol\" 404 -\n"
2d4d4f1997-08-01Fredrik Noring  "500: $host $referer ERROR [$cern_date] \"$method $resource $protocol\" 500 -\n"
14179b1997-01-29Per Hedbor  "*: $host - - [$cern_date] \"$method $resource $protocol\" $response $length" , "Logging: Format",
9b9f701997-08-12Per Hedbor  TYPE_TEXT_FIELD|VAR_MORE,
14179b1997-01-29Per Hedbor  "What format to use for logging. The syntax is:\n" "<pre>" "response-code or *: Log format for that response acode\n\n" "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" "$bin-date -- Time, but as an 32 bit iteger in network byteorder\n" "\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" "$bin-length -- Same, but as an 32 bit iteger 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" "$user_agent -- the header 'User-Agent' from the request, or '-'.\n\n" "$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"
c5e0961999-10-04Per Hedbor  "</pre>", 0, lambda(){ return !query("Log");});
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "LogFormat", "Loggning: Loggningsformat", #"Vilket format som ska användas för att logga <pre> svarskod eller *: Loggformat för svarskoden (eller alla koder som inte har något annat format specifierat om du använder '*') loggformatet är normala tecken, och en eller flera av koderna nedan. \\n \\t \\r -- Precis som i C, ny rad, tab och carriage return $char(int) -- Stoppa in det tecken vars teckenkod är det angivna nummret. $wchar(int) -- Stoppa in det tvåocktetstecken vars teckenkod är det angivna nummret. $int(int) -- Stoppa in det fyraocktetstecken vars teckenkod är det angivna nummret. $^ -- Stoppa <b>inte</b> in en vagnretur på slutet av varje loggrad $host -- DNS namnet för datorn som gjorde förfrågan $ip_number -- IP-nummret för datorn som gjorde förfrågan $bin-ip_number -- IP-nummret för datorn som gjorde förfrågan som binärdata i nätverksoktettordning $cern_date -- Ett datum som det ska vara enligt Cern Common Log file specifikationen $bin-date -- Tiden för requesten som sekunder sedan 1970, binärt i nätverksoktettordning. $method -- Förfrågningsmetoden (GET, POST etc) $resource -- Resursidentifieraren (filnamnet) $protocol -- Protokollet som användes för att fråga efter filen $response -- Den skickade svarskoden $bin-response -- Den skickade svarskoden som ett binärt ord (2 oktetter) i nätverksoktettordning $length -- Längden av datan som skickades som svar till klienten $bin-length -- Samma sak, men som ett 4 oktetters ord i nätverksoktettordning. $request-time -- Tiden som requeten tog i sekunder $referer -- Headern 'referer' från förfrågan eller '-'. $user_agent -- Headern 'User-Agent' från förfrågan eller '-'. $user -- Den autentifierade användarens namn, eller '-' $user_id -- Ett unikt användarid. Tas från kakan RoxenUserID, du måste slå på kaksättningsfunktionaliteten i de globala inställningarna. '0' används för de förfrågningar som inte har kakan. </pre>");
14179b1997-01-29Per Hedbor  defvar("Log", 1, "Logging: Enabled", TYPE_FLAG, "Log requests");
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "Log", "Loggning: På", "Ska roxen logga alla förfrågningar till en logfil?");
14179b1997-01-29Per Hedbor  defvar("LogFile", roxen->QUERY(logdirprefix)+ short_name(name)+"/Log", "Logging: Log file", TYPE_FILE, "The log file. "
f7d9811997-09-12Per Hedbor  "" "A file name. May be relative to "+getcwd()+"." " Some substitutions will be done:" "<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" "%h Hour (e.g. '00')\n</pre>"
c5e0961999-10-04Per Hedbor  ,0, lambda(){ return !query("Log");});
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "LogFile",
3b17831998-11-22Per Hedbor  "Loggning: Loggfil",
b796b51998-11-18Per Hedbor  "Filen som roxen loggar i. Filnamnet kan vara relativt " +getcwd()+ #". Du kan använda några kontrollkoder för att få flera loggfiler och automatisk loggrotation: <pre> %y År (t.ex. '1997') %m Månad (t.ex. '08') %d Datum (t.ex. '10') %h Timme (t.ex. '00') </pre>");
14179b1997-01-29Per Hedbor  defvar("NoLog", ({ }),
9b9f701997-08-12Per Hedbor  "Logging: No Logging for", TYPE_STRING_LIST|VAR_MORE,
14179b1997-01-29Per Hedbor  "Don't log requests from hosts with an IP number which matches any " "of the patterns in this list. This also affects the access counter "
c5e0961999-10-04Per Hedbor  "log.\n",0, lambda(){ return !query("Log");});
b796b51998-11-18Per Hedbor  deflocaledoc("svenska", "NoLog",
3b17831998-11-22Per Hedbor  "Loggning: Logga inte för",
b796b51998-11-18Per Hedbor #"Logga inte några förfrågningar vars IP-nummer matchar något av de mönster som står i den här listan. Den här variabeln påverkar även &lt;accessed&gt; RXML-styrkoden.");
14179b1997-01-29Per Hedbor 
b653f51999-05-18Martin Stjernholm  defvar("Domain", roxen->get_domain(), "Domain", TYPE_STRING,
b796b51998-11-18Per Hedbor  "The domainname of the server. The domainname is used " " to generate default URLs, and to gererate email addresses"); deflocaledoc( "svenska", "Domain", "DNS Domän", #"Serverns domännamn. Det av en del RXML styrkoder för att generara epostadresser, samt för att generera skönskvärdet för serverurl variablen.");
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  defvar("MyWorldLocation", "", "Server URL", TYPE_STRING, "This is the main server URL, where your start page is located.");
b796b51998-11-18Per Hedbor  deflocaledoc( "svenska", "MyWorldLocation", "Serverns URL",
c5e0961999-10-04Per Hedbor #"Det här är huvudURLen till din startsida. Den används av många
b796b51998-11-18Per Hedbor  moduler för att bygga upp absoluta URLer från en relativ URL.");
c5e0961999-10-04Per Hedbor 
f406ba1999-11-27Per Hedbor  defvar("URLs", ({"http://*:80/"}), "URLs", TYPE_STRING_LIST|VAR_INITIAL,
c5e0961999-10-04Per Hedbor  "Bind to these URLs" );
199d031999-09-05Francesco Chemolli  defvar("InternalLoc", "/_internal/",
f406ba1999-11-27Per Hedbor  "Internal module resource mountpoint", TYPE_LOCATION|VAR_MORE|VAR_DEVELOPER,
5839c31999-01-22Marcus Comstedt  "Some modules may want to create links to internal 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.");
f406ba1999-11-27Per Hedbor 
5839c31999-01-22Marcus Comstedt  deflocaledoc("svenska", "InternalLoc", "Intern modulresursmountpoint", #"Somliga moduler kan vilja skapa länkar till interna resurser. Denna inställning konfigurerar en internt hanterad location som kan användas för sådana ändamål. Välj bara en location som du förmodligen inte kommer behöva för vanliga resurser.");
199d031999-09-05Francesco Chemolli  // throttling-related variables defvar("throttle",0,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Server: Enabled",TYPE_FLAG,
199d031999-09-05Francesco Chemolli #"If set, per-server bandwidth throttling will be enabled. It will allow you to limit the total available bandwidth for 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."); //TODO: move this explanation somewhere on the website and just put a link.
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "throttle", "Bandviddsbegränsning: Servernivå: På", #"Om den här variablen är på så kommer bandvisddsbegränsning på servernivå att ske. Det gör det möjligt för dig att begränsa den totala bandvidden som den här virtuella servern använder. <p> Bandvidden räknas ut genom att använda en poletthink. Principen som den arbetar efter är: För varje byte som sänds så används en polett, poletter stoppas i hinken i en konstant hastighet. När det inte finns några poletter så avstännar dataskickande tills en polett blir tillgänglig. När det är för många poletter i hinken så kommer de nya som kommer in att \"ramla ut\".");
199d031999-09-05Francesco Chemolli  defvar("throttle_fill_rate",102400,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Server: Average available bandwidth",
199d031999-09-05Francesco Chemolli  TYPE_INT, #"This is the average bandwidth available to this Virtual Server in bytes/sec (the bucket \"fill rate\").", 0,arent_we_throttling_server);
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "throttle_fill_rate", "Bandviddsbegränsning: Servernivå:" " Genomsnittlig tillgänglig bandvidd", "Det här är den genomsnittliga bandvidden som är tillgänglig " "för servern (hastigheten med vilken hinken fylls)");
199d031999-09-05Francesco Chemolli  defvar("throttle_bucket_depth",1024000,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Server: Bucket Depth", TYPE_INT,
199d031999-09-05Francesco Chemolli #"This is the maximum depth of the bucket. After a long enough period 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);
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "throttle_bucket_depth", "Bandviddsbegränsning: Servernivå:" " Hinkstorlek", "Det här är det maximala antalet poletter som får plats " "i hinken. Om det här värdet är lika stort som den " "genomsnittliga tillgängliga bandvidden så tillåts inga " "tillfälliga datapulser när servern har varit inaktiv ett tag" " utan data skickas alltid med max den bandvidden");
199d031999-09-05Francesco Chemolli  defvar("throttle_min_grant",1300,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Server: Minimum Grant", TYPE_INT,
199d031999-09-05Francesco Chemolli #"When the bandwidth availability is below this value, connections will 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);
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "throttle_min_grant", "Bandviddsbegränsning: Servernivå:" " Minimalt antal bytes", #"När det tillgängliga antalet poletter (alltså bytes) är mindre än det här värdet så fördröjs förbindelser, alternativet är att skicka små paket, vilket öker overheaden som kommer till från IP och TCP paketheadrar." );
199d031999-09-05Francesco Chemolli  defvar("throttle_max_grant",14900,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Server: Maximum Grant", TYPE_INT,
199d031999-09-05Francesco Chemolli #"This is the maximum number of bytes assigned in a single request 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);
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "throttle_max_grant", "Bandviddsbegränsning: Servernivå:" " Maximalt antal bytes", #"Det här är det maximala antalet bytes som en förbindelse kan få. Om det här värdet är lågt så fördelas bandvidden mer jämnt mellan olika förbindelser, men om det är för lågt så ökar overeden från IP och TCP. <p> Sätt det till ett värde som är aningens lägre än en jämn multipel av ditt nätverks MTU (normala ethernetförbindelser har en MTU på 1500) " );
199d031999-09-05Francesco Chemolli  defvar("req_throttle", 0,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Request: Enabled", TYPE_FLAG,
199d031999-09-05Francesco Chemolli #"If set, per-request bandwidth throttling will be enabled." );
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "req_throttle", "Bandviddsbegränsning: Förbindelsenivå: På", "Om på så begränsas bandvidden individuellt på förbindelser" );
199d031999-09-05Francesco Chemolli  defvar("req_throttle_min", 1024,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Request: Minimum guarranteed bandwidth",
199d031999-09-05Francesco Chemolli  TYPE_INT, #"The maximum bandwidth each connection (in bytes/sec) can use is determined 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  deflocaledoc( "svenska", "req_throttle_min", "Bandviddsbegränsning: Förbindelsenivå: Minimal bandvidd", #"Den maximala bandvidden som varje förbindelse får bestäms av en kombination av de bandviddsbegränsningsmoduler som är adderade i servern. Men ibland så blir det framräknade värdet väldigt lågt, och en del riktigt otursamma förbindelser kan råka hamna på 0 eller mindre bytes per sekund. <p>Den här variablen garanterar en vis minimal bandvidd för alla requests" );
199d031999-09-05Francesco Chemolli  defvar("req_throttle_depth_mult", 60.0,
4d16831999-11-17Per Hedbor  "Bandwidth Throttling: Request: Bucket Depth Multiplier",
199d031999-09-05Francesco Chemolli  TYPE_FLOAT, #"The average bandwidth available for each request will be determined by the modules combination. The bucket depth will be determined multiplying the rate by this factor.", 0,arent_we_throttling_request);
4d16831999-11-17Per Hedbor  deflocaledoc( "svenska", "req_throttle_depth_mult", "Bandviddsbegränsning: Förbindelsenivå: Hinkstorlek", #"Den genomsnittliga bandvidden som varje förbindelse bestäms av de adderade bandvidsbegränsningsmodulerna. Hinkstorleken bestäms genom att multiplicera detta värde med den här faktorn.");
c5e0961999-10-04Per Hedbor  setvars(retrieve("spider#0", this_object()));
199d031999-09-05Francesco Chemolli 
07c9921999-11-23Per Hedbor  report_notice("Creating virtual server '"+query_name()+"'\n"); 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+")"; }