dfc05d2002-06-14Johan Sundström // This file is part of Internet Server.
835c6c2001-06-17Martin Nilsson // Copyright © 1996 - 2001, Roxen IS. //
6b67fe2001-08-24Martin Nilsson // @appears Configuration //! A site's main configuration
2b7ca32002-07-03Martin Nilsson constant cvs_version = "$Id: configuration.pike,v 1.531 2002/07/03 20:20:32 nilsson Exp $";
b1fca01996-11-12Per Hedbor #include <module.h>
a59d252000-07-04Per Hedbor #include <module_constants.h>
14179b1997-01-29Per Hedbor #include <roxen.h>
c5e0961999-10-04Per Hedbor #include <request_trace.h>
9c19002001-02-27Per Hedbor #include <timers.h>
8afc811998-02-04Per Hedbor 
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) 
199d031999-09-05Francesco Chemolli #ifdef THROTTLING_DEBUG #undef THROTTLING_DEBUG
91d3c32001-03-12Martin Nilsson #define THROTTLING_DEBUG(X) report_debug("Throttling: "+X+"\n")
199d031999-09-05Francesco Chemolli #else #define THROTTLING_DEBUG(X) #endif
10c7e11999-12-28Martin Nilsson #ifdef REQUEST_DEBUG
91d3c32001-03-12Martin Nilsson # define REQUEST_WERR(X) report_debug("CONFIG: "+X+"\n")
10c7e11999-12-28Martin Nilsson #else # define REQUEST_WERR(X) #endif
4717052001-05-07Per Hedbor  #ifdef AVERAGE_PROFILING
7e16102001-11-01Henrik Grubbström (Grubba)  #if !constant(gethrvtime) #define gethrvtime() gethrtime() #endif /* !constant(gethrvtime) */
4717052001-05-07Per Hedbor class ProfStack { array current_stack = ({}); void enter( string k, RequestID id ) { current_stack += ({ ({ k, gethrtime(), gethrvtime() }) }); } void leave( string k, RequestID id ) { int t0 = gethrtime(); int t1 = gethrvtime(); if( !sizeof(current_stack ) ) {
7937df2001-05-16Per Hedbor // report_error("Popping out of profiling stack\n");
4717052001-05-07Per Hedbor  return; } int i = sizeof( current_stack )-1; while( current_stack[ i ][0] != k && i >= 0 ) i--; if(i < 0 ) { return; }
7937df2001-05-16Per Hedbor  void low_leave( int i ) { int tt = t0-current_stack[i][1]; int ttv = t1-current_stack[i][2]; if( i > 0 ) // Do not count child time in parent. { current_stack[i-1][1]+=tt+gethrtime()-t0; current_stack[i-1][2]+=ttv+gethrvtime()-t1; } current_stack = current_stack[..i-1]; add_prof_entry( id, k, tt, ttv ); };
4717052001-05-07Per Hedbor 
7937df2001-05-16Per Hedbor  if( i != sizeof( current_stack )-1 )
4717052001-05-07Per Hedbor  {
7937df2001-05-16Per Hedbor  for( int j = sizeof( current_stack )-1; j>=i; j-- ) low_leave( j ); return;
4717052001-05-07Per Hedbor  }
7937df2001-05-16Per Hedbor  low_leave( i );
4717052001-05-07Per Hedbor  } } class ProfInfo( string url ) { mapping data = ([]); void add( string k, int h, int hrv ) { if( !data[k] ) data[k] = ({ h, hrv, 1 }); else { data[k][0]+=h; data[k][1]+=hrv; data[k][2]++; } } array summarize_table( ) { array table = ({}); int n, t, v;
dfa0f92002-06-18Martin Nilsson  foreach(data; string k; array value )
4717052001-05-07Per Hedbor  table += ({ ({ k,
dfa0f92002-06-18Martin Nilsson  sprintf( "%d", (n=value[2]) ), sprintf("%5.2f",(t=value[0])/1000000.0), sprintf("%5.2f", (v=value[1])/1000000.0),
4717052001-05-07Per Hedbor  sprintf("%8.2f", t/n/1000.0), sprintf("%8.2f",v/n/1000.0), }) }); sort( (array(float))column(table,2), table ); return reverse(table); } void dump( ) { write( "\n"+url+": \n" );
ab1e022002-03-06Henrik Grubbström (Grubba)  ADT.Table.table t = ADT.Table.table( summarize_table(), ({ "What", "Calls", "Time", "CPU", "t/call(ms)", "cpu/call(ms)" }));
4717052001-05-07Per Hedbor  write( ADT.Table.ASCII.encode( t )+"\n" ); } } mapping profiling_info = ([]); void debug_write_prof( ) { foreach( sort( indices( profiling_info ) ), string p ) profiling_info[p]->dump(); } void add_prof_entry( RequestID id, string k, int hr, int hrv ) {
e8dffa2001-05-14Per Hedbor  string l = id->not_query;
7937df2001-05-16Per Hedbor // if( has_prefix( k, "find_internal" ) ) l = dirname(l); if( has_prefix( l, query_internal_location() ) ) l = dirname( l ); // enough, really. if( !profiling_info[l] ) profiling_info[l] = ProfInfo(l);
e8dffa2001-05-14Per Hedbor  profiling_info[l]->add( k, hr, hrv );
4717052001-05-07Per Hedbor } void avg_prof_enter( string name, string type, RequestID id ) { if( !id->misc->prof_stack ) id->misc->prof_stack = ProfStack(); id->misc->prof_stack->enter( name+":"+type,id ); } void avg_prof_leave( string name, string type, RequestID id ) { if( !id->misc->prof_stack ) id->misc->prof_stack = ProfStack(); id->misc->prof_stack->leave( name+":"+type,id ); } #endif
b1fca01996-11-12Per Hedbor /* A configuration.. */
9a8a152000-09-25Per Hedbor inherit Configuration; inherit "basic_defvar";
dfe0362000-03-19Martin Nilsson 
b9c3872002-03-27Per Hedbor static mapping(RequestID:mapping) current_connections = set_weak_flag( ([ ]), 1 ); void connection_add( RequestID id, mapping data ) //! Add a connection. The data mapping can contain things such as //! currently sent bytes. //! //! See protocols/http.pike and slowpipe.pike for more information. //! //! You are not in any way forced to use this method from your //! protocol module. The information is only used for debug purposes
0fa67e2002-06-15Martin Nilsson //! in the administration interface.
b9c3872002-03-27Per Hedbor //! //! You have to keep a reference to the mapping on your own, none is //! kept by the configuration object. { current_connections[id] = data; } mapping connection_drop( RequestID id ) //! Remove a connection from the list of currently active connections. //! Returns the mapping previously added with connection_add, if any. { m_delete( current_connections, id ); } mapping(RequestID:mapping) connection_get( ) //! Return all currently active connections. { return current_connections; }
3557f52001-06-30Martin Stjernholm // It's nice to have the name when the rest of __INIT executes. string name = roxen->bootstrap_info->get();
d093992000-09-25Per Hedbor // Trivial cache (actually, it's more or less identical to the 200+ // lines of C in HTTPLoop. But it does not have to bother with the // fact that more than one thread can be active in it at once. Also, // it does not have to delay free until all current connections using // the cache entry is done...) class DataCache { mapping(string:array(string|mapping(string:mixed))) cache = ([]); int current_size; int max_size; int max_file_size; int hits, misses; void flush() { current_size = 0; cache = ([]); } static void clear_some_cache() { array q = indices( cache ); if(!sizeof(q)) { current_size=0; return; } for( int i = 0; i<sizeof( q )/10; i++ ) expire_entry( q[random(sizeof(q))] ); } void expire_entry( string url ) { if( cache[ url ] ) { current_size -= strlen(cache[url][0]); m_delete( cache, url ); } } void set( string url, string data, mapping meta, int expire ) {
c42ab32002-04-15Jonas Wallden  if( strlen( data ) > max_file_size ) return;
d093992000-09-25Per Hedbor  call_out( expire_entry, expire, url ); current_size += strlen( data ); cache[url] = ({ data, meta }); int n; while( (current_size > max_size) && (n++<10)) clear_some_cache(); } array(string|mapping(string:mixed)) get( string url ) { mixed res; if( res = cache[ url ] ) hits++; else misses++; return res; } void init_from_variables( ) { max_size = query( "data_cache_size" ) * 1024; max_file_size = query( "data_cache_file_max_size" ) * 1024; if( max_size < max_file_size ) max_size += max_file_size; int n; while( (current_size > max_size) && (n++<10)) clear_some_cache(); } static void create() { init_from_variables(); } }
3b17831998-11-22Per Hedbor #include "rxml.pike";
9a8a152000-09-25Per Hedbor constant store = roxen.store; constant retrieve = roxen.retrieve; constant remove = roxen.remove;
14179b1997-01-29Per Hedbor 
65c6d22000-03-10Martin Nilsson int config_id;
9a8a152000-09-25Per Hedbor int get_config_id() {
65c6d22000-03-10Martin Nilsson  if(config_id) return config_id; for(int i=sizeof(roxen->configurations); i;) if(roxen->configurations[--i]->name==name) return config_id=i; }
c7a5f01999-02-16Per Hedbor string get_doc_for( string region, string variable ) {
e351dd1999-11-29Per Hedbor  RoxenModule module;
c7a5f01999-02-16Per Hedbor  if(variable[0] == '_') return 0; if((int)reverse(region)) return 0; if(module = find_module( region )) { if(module->variables[variable])
b2c49b2000-07-09Per Hedbor  return module->variables[variable]->name()+ "\n"+module->variables[ variable ]->doc();
c7a5f01999-02-16Per Hedbor  } if(variables[ variable ])
b2c49b2000-07-09Per Hedbor  return variables[variable]->name()+ "\n"+variables[ variable ]->doc();
c7a5f01999-02-16Per Hedbor }
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor string query_internal_location(RoxenModule|void mod)
5839c31999-01-22Marcus Comstedt {
8552d92001-01-13Martin Nilsson  return query("InternalLoc")+(mod?replace(otomod[mod]||"", "#", "!")+"/":"");
5839c31999-01-22Marcus Comstedt }
b1fca01996-11-12Per Hedbor  string query_name() {
8552d92001-01-13Martin Nilsson  if(strlen(query("name"))) return query("name");
b1fca01996-11-12Per Hedbor  return name; } string comment() {
8552d92001-01-13Martin Nilsson  return query("comment");
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 }
2f1e892000-08-15Martin Nilsson // The logging format used. This will probably move to the above
b1fca01996-11-12Per Hedbor // mentioned module in the future.
7a243b2000-08-19Per Hedbor private mapping (int:string) log_format = ([]);
b1fca01996-11-12Per Hedbor 
c5e0961999-10-04Per Hedbor // A list of priority objects
053a552000-10-04Per Hedbor array (Priority) pri = allocate_pris();
b1fca01996-11-12Per Hedbor 
9c19002001-02-27Per Hedbor mapping modules = ([]);
1dd64a2000-09-19Mattias Wingstedt //! All enabled modules in this site.
e75fd12000-07-26Johan Sundström //! The format is "module":{ "copies":([ num:instance, ... ]) }
b1fca01996-11-12Per Hedbor 
9c19002001-02-27Per Hedbor mapping (RoxenModule:string) otomod = ([]);
e75fd12000-07-26Johan Sundström //! A mapping from the module objects to module names
b1fca01996-11-12Per Hedbor  // Caches to speed up the handling of the module search. // They are all sorted in priority order, and created by the functions // below. private array (function) url_module_cache, last_module_cache; private array (function) logger_module_cache, first_module_cache; private array (function) filter_module_cache; private array (array (string|function)) location_module_cache; private mapping (string:array (function)) file_extension_module_cache=([]);
e351dd1999-11-29Per Hedbor private mapping (string:array (RoxenModule)) provider_module_cache=([]);
3342dd2001-01-19Per Hedbor private array (RoxenModule) auth_module_cache, userdb_module_cache;
b1fca01996-11-12Per Hedbor 
38dca81996-12-10Per Hedbor 
0e15572001-02-23Martin Stjernholm void unregister_urls()
38dca81996-12-10Per Hedbor {
9c3c6c2001-11-09Henrik Grubbström (Grubba)  foreach( registered_urls + failed_urls, string url ) roxen.unregister_url(url, this_object());
dffa222000-12-10Per Hedbor  registered_urls = ({});
38dca81996-12-10Per Hedbor }
0e15572001-02-23Martin Stjernholm private int num_modules = 0; #ifdef THREADS private Thread.Condition modules_stopped = Thread.Condition(); #endif private void safe_stop_module (RoxenModule mod, string desc) { if (mixed err = catch (mod && mod->stop && mod->stop())) report_error ("While stopping " + desc + ": " + describe_backtrace (err));
a5249e2001-03-05Per Hedbor  if (!--num_modules) #ifdef THREADS modules_stopped->signal() #endif ;
0e15572001-02-23Martin Stjernholm } void stop (void|int asynch) //! Unregisters the urls and calls stop in all modules. Uses the //! handler threads to lessen the impact if a module hangs. Doesn't //! wait for all modules to finish if @[asynch] is nonzero. {
79b7c32001-09-13Honza Petrous  #ifdef SNMP_AGENT if(query("snmp_process") && objectp(roxen->snmpagent)) { roxen->snmpagent->vs_stop_trap(get_config_id()); roxen->snmpagent->del_virtserv(get_config_id()); } #endif
0e15572001-02-23Martin Stjernholm  unregister_urls(); multiset allmods = mkmultiset (indices (otomod)); num_modules = 17; if (types_module) { num_modules++; roxen.handle (safe_stop_module, types_module, "type module"); allmods[types_module] = 0; } if (dir_module) { num_modules++; roxen.handle (safe_stop_module, dir_module, "directory module"); allmods[dir_module] = 0; } for(int i=0; i<10; i++) if (Priority p = pri[i]) { #define STOP_MODULES(MODS, DESC) \ foreach(MODS, RoxenModule m) \ if (allmods[m]) { \ num_modules++; \ roxen.handle (safe_stop_module, m, DESC); \ allmods[m] = 0; \ } STOP_MODULES (p->url_modules, "url module"); STOP_MODULES (p->logger_modules, "logging module"); STOP_MODULES (p->filter_modules, "filter module"); STOP_MODULES (p->location_modules, "location module"); STOP_MODULES (p->last_modules, "last module"); STOP_MODULES (p->first_modules, "first module"); STOP_MODULES (indices (p->provider_modules), "provider module"); } if (mixed err = catch { if (object m = log_function && function_object (log_function)) { destruct (m); allmods[m] = 0; } }) report_error ("While stopping the logger: " + describe_backtrace (err)); STOP_MODULES(indices (allmods), "unclassified module"); #undef STOP_MODULES if (!asynch) { num_modules -= 17; if (num_modules) { #ifdef THREADS // Relying on the interpreter lock here. modules_stopped->wait(); #else error ("num_modules shouldn't be nonzero here when running nonthreaded.\n"); #endif } } }
9a8a152000-09-25Per Hedbor string type_from_filename( string file, int|void to, string|void myext )
b1fca01996-11-12Per Hedbor {
f28c112000-03-06Martin Nilsson  array(string)|string tmp;
14179b1997-01-29Per Hedbor  if(!types_fun) return to?({ "application/octet-stream", 0 }):"application/octet-stream";
0ba0382001-08-28Henrik Grubbström (Grubba)  string ext = lower_case(myext || Roxen.extension(file));
41b77c1999-07-15David Hedbor 
14179b1997-01-29Per Hedbor  if(tmp = types_fun(ext)) { mixed tmp2,nx;
0ba0382001-08-28Henrik Grubbström (Grubba)  // FIXME: Ought to support several levels of "strip". if (tmp[0] == "strip")
14179b1997-01-29Per Hedbor  { tmp2=file/".";
0ba0382001-08-28Henrik Grubbström (Grubba)  if (sizeof(tmp2) > 2)
14179b1997-01-29Per Hedbor  nx=tmp2[-2];
0ba0382001-08-28Henrik Grubbström (Grubba)  if (nx && (tmp2 = types_fun(nx)))
14179b1997-01-29Per Hedbor  tmp[0] = tmp2[0];
0ba0382001-08-28Henrik Grubbström (Grubba)  else if (tmp2 = types_fun("default"))
9be5aa1998-07-03Henrik Grubbström (Grubba)  tmp[0] = tmp2[0];
14179b1997-01-29Per Hedbor  else
0ba0382001-08-28Henrik Grubbström (Grubba)  tmp[0] = "application/octet-stream";
14179b1997-01-29Per Hedbor  }
0ba0382001-08-28Henrik Grubbström (Grubba)  } else if (!(tmp = types_fun("default"))) {
9be5aa1998-07-03Henrik Grubbström (Grubba)  tmp = ({ "application/octet-stream", 0 });
14179b1997-01-29Per Hedbor  }
9be5aa1998-07-03Henrik Grubbström (Grubba)  return to?tmp:tmp[0];
b1fca01996-11-12Per Hedbor }
e351dd1999-11-29Per Hedbor array (RoxenModule) get_providers(string provides)
2f1e892000-08-15Martin Nilsson //! Returns an array with all provider modules that provides "provides".
ae32d01998-03-23David Hedbor {
2f1e892000-08-15Martin Nilsson  // This cache is cleared in the invalidate_cache() call.
ae32d01998-03-23David Hedbor  if(!provider_module_cache[provides])
10c7e11999-12-28Martin Nilsson  {
ae32d01998-03-23David Hedbor  int i; provider_module_cache[provides] = ({ }); for(i = 9; i >= 0; i--) {
2b7ca32002-07-03Martin Nilsson  foreach(pri[i]->provider_modules; RoxenModule d; multiset(string) p) if( p[ provides ] )
ae32d01998-03-23David Hedbor  provider_module_cache[provides] += ({ d }); } } return provider_module_cache[provides]; }
14179b1997-01-29Per Hedbor 
e351dd1999-11-29Per Hedbor RoxenModule get_provider(string provides)
2f1e892000-08-15Martin Nilsson //! Returns the first provider module that provides "provides".
ae32d01998-03-23David Hedbor {
e351dd1999-11-29Per Hedbor  array (RoxenModule) prov = get_providers(provides);
ae32d01998-03-23David Hedbor  if(sizeof(prov)) return prov[0]; return 0; }
bdb8da1998-09-02Johan Schön array(mixed) map_providers(string provides, string fun, mixed ... args)
2f1e892000-08-15Martin Nilsson //! Maps the function "fun" over all matching provider modules.
ae32d01998-03-23David Hedbor {
e351dd1999-11-29Per Hedbor  array (RoxenModule) prov = get_providers(provides);
0e1f262002-01-29Martin Stjernholm  mixed error;
bdb8da1998-09-02Johan Schön  array a=({ }); mixed m;
10c7e11999-12-28Martin Nilsson  foreach(prov, RoxenModule mod)
9bb8131998-09-12Per Hedbor  {
ae32d01998-03-23David Hedbor  if(!objectp(mod)) continue;
10c7e11999-12-28Martin Nilsson  if(functionp(mod[fun]))
bdb8da1998-09-02Johan Schön  error = catch(m=mod[fun](@args));
0e1f262002-01-29Martin Stjernholm  if(error) { report_debug("Error in map_providers(): " + describe_backtrace(error));
24fbd41999-04-21David Hedbor  }
bdb8da1998-09-02Johan Schön  else
9bb8131998-09-12Per Hedbor  a += ({ m });
18be211998-05-07Henrik Grubbström (Grubba)  error = 0;
ae32d01998-03-23David Hedbor  }
9bb8131998-09-12Per Hedbor  return a;
ae32d01998-03-23David Hedbor } mixed call_provider(string provides, string fun, mixed ... args)
2f1e892000-08-15Martin Nilsson //! Maps the function "fun" over all matching provider modules and //! returns the first positive response.
ae32d01998-03-23David Hedbor {
10c7e11999-12-28Martin Nilsson  foreach(get_providers(provides), RoxenModule mod)
e351dd1999-11-29Per Hedbor  {
d8b7721998-05-28Henrik Grubbström (Grubba)  function f; if(objectp(mod) && functionp(f = mod[fun])) {
a51a902001-11-12Martin Stjernholm  mixed ret; if (ret = f(@args)) { return ret;
d8b7721998-05-28Henrik Grubbström (Grubba)  } }
ae32d01998-03-23David Hedbor  } }
14179b1997-01-29Per Hedbor 
517c7e2000-09-30Per Hedbor array (function) file_extension_modules(string ext)
b1fca01996-11-12Per Hedbor {
0ba0382001-08-28Henrik Grubbström (Grubba)  if(!file_extension_module_cache[ext = lower_case(ext)])
10c7e11999-12-28Martin Nilsson  {
b1fca01996-11-12Per Hedbor  int i; file_extension_module_cache[ext] = ({ }); for(i=9; i>=0; i--) {
e351dd1999-11-29Per Hedbor  array(RoxenModule) d; RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d = pri[i]->file_extension_modules[ext]) foreach(d, p) file_extension_module_cache[ext] += ({ p->handle_file_extension }); } } return file_extension_module_cache[ext]; }
517c7e2000-09-30Per Hedbor array (function) url_modules()
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; }
9a8a152000-09-25Per Hedbor static mapping api_module_cache = ([]);
e351dd1999-11-29Per Hedbor mapping api_functions(void|RequestID id)
4f4bc11998-02-04Per Hedbor {
fc9d8e2000-08-28Per Hedbor  return api_module_cache+([]);
4f4bc11998-02-04Per Hedbor }
517c7e2000-09-30Per Hedbor array (function) logger_modules()
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; }
517c7e2000-09-30Per Hedbor array (function) last_modules()
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/"::";
9934d62001-09-05Jonas Wallden  // FIX: Must not subtract ":" chars since it breaks proper URL:s, // e.g. "/internal-roxen-colorbar:x,y,z" and several others. // id->not_query = a[0]-":"; id->not_query = a[0];
ca44e51998-07-02Henrik Grubbström (Grubba)  id->misc->fork_information = a[1..];
c5e0961999-10-04Per Hedbor  return 0;
ca44e51998-07-02Henrik Grubbström (Grubba) } #endif /* __NT__ */
517c7e2000-09-30Per Hedbor array (function) first_modules()
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; }
4d10232001-06-26Per Hedbor void set_userdb_module_cache( array to ) // Used by the config_filesystem.pike module to enforce the usage of // the config userdb module, for now. { userdb_module_cache = to; }
3342dd2001-01-19Per Hedbor array(UserDB) user_databases() { if( userdb_module_cache ) return userdb_module_cache; array tmp = ({}); foreach( values( modules ), mapping m ) foreach( values(m->copies), RoxenModule mo ) if( mo->module_type & MODULE_USERDB ) tmp += ({ ({ mo->query( "_priority" ), mo }) }); sort( tmp );
b765aa2002-06-20Martin Nilsson // tmp += ({ ({ 0, roxen->admin_userdb_module }) });
3342dd2001-01-19Per Hedbor  return userdb_module_cache = reverse(column(tmp,1)); } array(AuthModule) auth_modules() { if( auth_module_cache ) return auth_module_cache; array tmp = ({}); foreach( values( modules ), mapping m ) foreach( values(m->copies), RoxenModule mo ) if( mo->module_type & MODULE_AUTH ) tmp += ({ ({ mo->query( "_priority" ), mo }) }); sort( tmp ); return auth_module_cache = reverse(column(tmp,1)); }
b1fca01996-11-12Per Hedbor 
517c7e2000-09-30Per Hedbor array location_modules()
3342dd2001-01-19Per Hedbor //! Return an array of all location modules the request should be
cd92872000-08-15Johan Sundström //! mapped through, by order of priority.
b1fca01996-11-12Per Hedbor { if(!location_module_cache) { int i;
8cc31b1997-10-12Henrik Grubbström (Grubba)  array new_location_module_cache=({ });
b1fca01996-11-12Per Hedbor  for(i=9; i>=0; i--) {
10c7e11999-12-28Martin Nilsson  array(RoxenModule) d;
e351dd1999-11-29Per Hedbor  RoxenModule p;
8cc31b1997-10-12Henrik Grubbström (Grubba)  if(d=pri[i]->location_modules) { array level_find_files = ({}); array level_locations = ({}); foreach(d, p) { string location; // FIXME: Should there be a catch() here? if(p->find_file && (location = p->query_location())) { level_find_files += ({ p->find_file }); level_locations += ({ location }); } }
dffddc2000-10-10Johan Sundström  sort(map(level_locations, sizeof), level_locations, level_find_files);
8cc31b1997-10-12Henrik Grubbström (Grubba)  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; }
517c7e2000-09-30Per Hedbor array(function) filter_modules()
b1fca01996-11-12Per Hedbor { if(!filter_module_cache) { int i; filter_module_cache=({ }); for(i=9; i>=0; i--) {
10c7e11999-12-28Martin Nilsson  array(RoxenModule) d;
e351dd1999-11-29Per Hedbor  RoxenModule p;
b1fca01996-11-12Per Hedbor  if(d=pri[i]->filter_modules) foreach(d, p) if(p->filter) filter_module_cache+=({ p->filter }); } } return filter_module_cache; }
1c78232000-03-13Per Hedbor void init_log_file() { if(log_function) { // Free the old one. destruct(function_object(log_function)); log_function = 0; } // Only try to open the log file if logging is enabled!! if(query("Log")) { string logfile = query("LogFile");
f7d9811997-09-12Per Hedbor  if(strlen(logfile))
f3ca762000-08-19Per Hedbor  log_function = roxen.LogFile( logfile )->write;
1c78232000-03-13Per Hedbor  }
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor // Parse the logging format strings. private inline string fix_logging(string s)
b1fca01996-11-12Per Hedbor {
f3ca762000-08-19Per Hedbor  sscanf(s, "%*[\t ]%s", s);
14179b1997-01-29Per Hedbor  return s;
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor private void parse_log_formats() {
2b7ca32002-07-03Martin Nilsson  foreach(String.SplitIterator(query("LogFormat"), '\n'); int x; string b)
14179b1997-01-29Per Hedbor  if(strlen(b) && b[0] != '#' && sizeof(b/":")>1)
7a243b2000-08-19Per Hedbor  log_format[(int)(b/":")[0]] = fix_logging((b/":")[1..]*":");
14179b1997-01-29Per Hedbor }
b1fca01996-11-12Per Hedbor 
9c19002001-02-27Per Hedbor void log(mapping file, RequestID request_id)
14179b1997-01-29Per Hedbor {
6533f22001-08-23Martin Nilsson  // Call all logging functions foreach(logger_module_cache||logger_modules(), function f)
f3ca762000-08-19Per Hedbor  if( f( request_id, file ) ) return;
14179b1997-01-29Per Hedbor 
7a243b2000-08-19Per Hedbor  if( !log_function )
6533f22001-08-23Martin Nilsson  return; // No file is open for logging.
14179b1997-01-29Per Hedbor 
7a243b2000-08-19Per Hedbor  if(do_not_log_patterns && Roxen._match(request_id->remoteaddr, do_not_log_patterns))
14179b1997-01-29Per Hedbor  return;
10c7e11999-12-28Martin Nilsson 
7a243b2000-08-19Per Hedbor  string form; if(!(form=log_format[file->error])) form = log_format[0];
14179b1997-01-29Per Hedbor  if(!form) return;
7a243b2000-08-19Per Hedbor  roxen.run_log_format( form, log_function, request_id, file );
14179b1997-01-29Per Hedbor }
9c19002001-02-27Per Hedbor array(string) userinfo(string u, RequestID|void id)
6533f22001-08-23Martin Nilsson //! @note //! DEPRECATED COMPATIBILITY FUNCTION
3342dd2001-01-19Per Hedbor //!
cd81922000-09-19Johan Sundström //! Fetches user information from the authentication module by calling //! its userinfo() method. Returns zero if no auth module was present.
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
14179b1997-01-29Per Hedbor {
3342dd2001-01-19Per Hedbor  User uid; foreach( user_databases(), UserDB m ) if( uid = m->find_user( u ) )
ac77452001-06-13Per Hedbor  return uid->compat_userinfo(id);
14179b1997-01-29Per Hedbor }
9c19002001-02-27Per Hedbor array(string) userlist(RequestID|void id)
6533f22001-08-23Martin Nilsson //! @note //! DEPRECATED COMPATIBILITY FUNCTION
3342dd2001-01-19Per Hedbor //!
cd81922000-09-19Johan Sundström //! Fetches the full list of valid usernames from the authentication //! module by calling its userlist() method. Returns zero if no auth //! module was present.
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
14179b1997-01-29Per Hedbor {
3342dd2001-01-19Per Hedbor  array(string) list = ({}); foreach( user_databases(), UserDB m )
ac77452001-06-13Per Hedbor  list |= m->list_users(id);
3342dd2001-01-19Per Hedbor  return list;
14179b1997-01-29Per Hedbor }
9c19002001-02-27Per Hedbor array(string) user_from_uid(int u, RequestID|void id)
6533f22001-08-23Martin Nilsson //! @note //! DEPRECATED COMPATIBILITY FUNCTION
3342dd2001-01-19Per Hedbor //!
cd81922000-09-19Johan Sundström //! Return the user data for id u from the authentication module. The //! id parameter might be left out if FTP. Returns zero if no auth //! module was present.
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
14179b1997-01-29Per Hedbor {
3342dd2001-01-19Per Hedbor  User uid; foreach( user_databases(), UserDB m )
ac77452001-06-13Per Hedbor  if( uid = m->find_user_from_uid( u,id ) )
3342dd2001-01-19Per Hedbor  return uid->compat_userinfo();
14179b1997-01-29Per Hedbor }
e3f4662001-01-19Per Hedbor UserDB find_user_database( string name )
96d86e2001-01-29Per Hedbor //! Given a user database name, returns it if it exists in this //! configuration, otherwise returns 0.
e3f4662001-01-19Per Hedbor { foreach( user_databases(), UserDB m ) if( m->name == name ) return m; } AuthModule find_auth_module( string name )
96d86e2001-01-29Per Hedbor //! Given a authentication method name, returns it if it exists in //! this configuration, otherwise returns 0.
e3f4662001-01-19Per Hedbor { foreach( auth_modules(), AuthModule m ) if( m->name == name ) return m; }
3342dd2001-01-19Per Hedbor 
96d86e2001-01-29Per Hedbor User authenticate( RequestID id, UserDB|void database)
3342dd2001-01-19Per Hedbor //! Try to authenticate the request with users from the specified user //! database. If no @[database] is specified, all datbases in the
96d86e2001-01-29Per Hedbor //! current configuration are searched in priority order.
3342dd2001-01-19Per Hedbor //! //! The return value is the autenticated user.
0cde962001-01-21Per Hedbor //! id->misc->authenticated_user is always set to the return value.
3342dd2001-01-19Per Hedbor { User u;
9a4c052001-01-28Per Hedbor  foreach( auth_modules(), AuthModule method ) if( u = method->authenticate( id, database ) ) return id->misc->authenticated_user = u;
3342dd2001-01-19Per Hedbor }
96d86e2001-01-29Per Hedbor mapping authenticate_throw( RequestID id, string realm, UserDB|void database)
3342dd2001-01-19Per Hedbor //! Returns a reply mapping, similar to @[Roxen.http_rxml_reply] with //! friends. If no @[database] is specified, all datbases in the
96d86e2001-01-29Per Hedbor //! current configuration are searched in priority order.
3342dd2001-01-19Per Hedbor { mapping m;
9a4c052001-01-28Per Hedbor  foreach( auth_modules(), AuthModule method ) if( m = method->authenticate_throw( id, realm, database ) ) return m;
96d86e2001-01-29Per Hedbor } User find_user( string user, RequestID|void id ) //! Tries to find the specified user in the currently available user //! databases. If id is specified, this function defaults to the //! database that the currently authenticated user came from, if any. //! //! The other user databases are processed in priority order
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
96d86e2001-01-29Per Hedbor { User uid;
d2fcaf2001-01-30Per Hedbor  if( id && id->misc->authenticated_user
ac77452001-06-13Per Hedbor  && ( uid = id->misc->authenticated_user->database->find_user(user,id)))
96d86e2001-01-29Per Hedbor  return uid; foreach( user_databases(), UserDB m )
ac77452001-06-13Per Hedbor  if( uid = m->find_user( user,id ) )
96d86e2001-01-29Per Hedbor  return uid; }
ac77452001-06-13Per Hedbor array(string) list_users(RequestID|void id)
d2fcaf2001-01-30Per Hedbor //! Fetches the full list of valid usernames from the authentication //! modules by calling the list-users() methods.
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
d2fcaf2001-01-30Per Hedbor { array(string) list = ({}); foreach( user_databases(), UserDB m )
ac77452001-06-13Per Hedbor  list |= m->list_users(id);
d2fcaf2001-01-30Per Hedbor  return list; }
ac77452001-06-13Per Hedbor array(string) list_groups(RequestID|void id)
d2fcaf2001-01-30Per Hedbor //! Fetches the full list of valid groupnames from the authentication //! modules by calling the list-users() methods.
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
d2fcaf2001-01-30Per Hedbor { array(string) list = ({}); foreach( user_databases(), UserDB m )
ac77452001-06-13Per Hedbor  list |= m->list_groups(id);
d2fcaf2001-01-30Per Hedbor  return list; }
96d86e2001-01-29Per Hedbor Group find_group( string group, RequestID|void id ) //! Tries to find the specified group in the currently available user //! databases. If id is specified, this function defaults to the //! database that the currently authenticated user came from, if any. //! //! The other user databases are processed in priority order
ac77452001-06-13Per Hedbor //! //! Note that you should always supply id if it's possible, some user //! databases require it (such as the htaccess database)
96d86e2001-01-29Per Hedbor { Group uid;
d2fcaf2001-01-30Per Hedbor  if( id && id->misc->authenticated_user
96d86e2001-01-29Per Hedbor  && ( uid = id->misc->authenticated_user->database->find_group( group ) )) return uid; foreach( user_databases(), UserDB m )
ac77452001-06-13Per Hedbor  if( uid = m->find_group( group,id ) )
96d86e2001-01-29Per Hedbor  return uid;
3342dd2001-01-19Per Hedbor }
9c19002001-02-27Per Hedbor string last_modified_by(Stdio.File file, RequestID id)
6103bc1999-10-09Henrik Grubbström (Grubba) {
1f4a6c2000-08-28Per Hedbor  Stat s;
6103bc1999-10-09Henrik Grubbström (Grubba)  int uid;
9f9fc32000-02-17Per Hedbor  array u;
10c7e11999-12-28Martin Nilsson 
6103bc1999-10-09Henrik Grubbström (Grubba)  if(objectp(file)) s=file->stat(); if(!s || sizeof(s)<5) return "A. Nonymous"; uid=s[5]; u=user_from_uid(uid, id); if(u) return u[0]; return "A. Nonymous"; }
14179b1997-01-29Per Hedbor  // Some clients does _not_ handle the magic 'internal-gopher-...'. // So, lets do it here instead. private mapping internal_gopher_image(string from) { sscanf(from, "%s.gif", from); sscanf(from, "%s.jpg", from); from -= "."; // Disallow "internal-gopher-..", it won't really do much harm, but a list of // all files in '..' might be retrieved (that is, the actual directory // file was sent to the browser)
dacef22002-06-05Martin Nilsson  Stdio.File f = lopen("data/images/dir/"+from+".gif","r");
1c78232000-03-13Per Hedbor  if (f)
5848842000-08-28Per Hedbor  return (["file":f, "type":"image/gif", "stat":f->stat(),]); else
06026c1999-10-19Henrik Grubbström (Grubba)  return 0;
5848842000-08-28Per Hedbor  // File not found.
14179b1997-01-29Per Hedbor } private static int nest = 0;
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY
c658172002-06-11Martin Nilsson private mapping misc_cache = set_weak_flag( ([]), 1 );
14179b1997-01-29Per Hedbor 
3e3bab2001-01-19Per Hedbor int|mapping check_security(function|RoxenModule a, RequestID id, void|int slevel)
14179b1997-01-29Per Hedbor { array seclevels;
12a9c51997-08-11Henrik Grubbström (Grubba)  // 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) 
bc0fa02001-03-08Per Hedbor  if(!(seclevels = misc_cache[ a ])) {
3e3bab2001-01-19Per Hedbor  RoxenModule mod = Roxen.get_owning_module (a);
ab7c312000-08-12Martin Stjernholm  if(mod && mod->query_seclevels)
3b17831998-11-22Per Hedbor  misc_cache[ a ] = seclevels = ({
2b86422000-06-29Martin Stjernholm  mod->query_seclevels(), mod->query("_seclvl"),
3b17831998-11-22Per Hedbor  }); else
bc0fa02001-03-08Per Hedbor  misc_cache[ a ] = seclevels = ({0,0});
2b86422000-06-29Martin Stjernholm  }
14179b1997-01-29Per Hedbor 
bc0fa02001-03-08Per Hedbor  if(slevel && (seclevels[1] > slevel)) // "Trustlevel" to low.
5a42932001-08-30Per Hedbor  // Regarding memory cache: This won't have any impact, since it's // always the same, regardless of the client requesting the file.
14179b1997-01-29Per Hedbor  return 1;
10c7e11999-12-28Martin Nilsson 
18be211998-05-07Henrik Grubbström (Grubba)  mixed err;
bc0fa02001-03-08Per Hedbor  if( function(RequestID:int|mapping) f = seclevels[0] )
5a42932001-08-30Per Hedbor  // And here we don't have to take notice of the RAM-cache either, // since the security patterns themselves does that. // // All patterns that varies depending on the client must use // NOCACHE(), to force the request to be uncached. //
bc0fa02001-03-08Per Hedbor  err=catch { return f( id ); }; else return 0; // Ok if there are no patterns.
18be211998-05-07Henrik Grubbström (Grubba) 
e40eb52002-06-13Martin Nilsson  report_error("check_security(): Error during module security check:\n%s\n",
bc0fa02001-03-08Per Hedbor  describe_backtrace(err));
18be211998-05-07Henrik Grubbström (Grubba) 
bc0fa02001-03-08Per Hedbor  return 1;
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;
3342dd2001-01-19Per Hedbor  userdb_module_cache = 0; auth_module_cache = 0;
14179b1997-01-29Per Hedbor  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
bc0fa02001-03-08Per Hedbor  misc_cache = ([ ]);
14179b1997-01-29Per Hedbor #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();
dfa0f92002-06-18Martin Nilsson  foreach(otomod; RoxenModule m; string name)
10c7e11999-12-28Martin Nilsson  if (m && m->clear_memory_caches) if (mixed err = catch( m->clear_memory_caches() ))
e40eb52002-06-13Martin Nilsson  report_error("clear_memory_caches() failed for module %O:\n%s\n",
dfa0f92002-06-18Martin Nilsson  name, describe_backtrace(err));
ec058c1998-07-04Henrik Grubbström (Grubba) }
7de44b2000-09-13Jonas Wallden // Returns tuple < image, mime-type >
9a8a152000-09-25Per Hedbor static array(string) draw_saturation_bar(int hue,int brightness, int where)
fc94331997-10-25Per Hedbor {
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);
2a346d2000-09-19Per Hedbor #if constant(Image.JPEG) && constant(Image.JPEG.encode)
7de44b2000-09-13Jonas Wallden  return ({ Image.JPEG.encode(bar), "image/jpeg" });
2a346d2000-09-19Per Hedbor #else return ({ Image.PNG.encode(bar), "image/png" });
7de44b2000-09-13Jonas Wallden #endif
fc94331997-10-25Per Hedbor }
14179b1997-01-29Per Hedbor // Inspired by the internal-gopher-... thingie, this is the images
a6ef1f2000-03-28Johan Sundström // from the administration interface. :-)
2a346d2000-09-19Per Hedbor private mapping internal_roxen_image( string from, RequestID id )
14179b1997-01-29Per Hedbor { sscanf(from, "%s.gif", from); sscanf(from, "%s.jpg", from);
2b658c2000-02-07Per Hedbor  sscanf(from, "%s.xcf", from); sscanf(from, "%s.png", from);
fc94331997-10-25Per Hedbor 
1c78232000-03-13Per Hedbor  // Automatically generated colorbar. Used by wizard code...
fc94331997-10-25Per Hedbor  int hue,bright,w;
7de44b2000-09-13Jonas Wallden  if(sscanf(from, "%*s:%d,%d,%d", hue, bright,w)==4) { array bar = draw_saturation_bar(hue, bright, w); return Roxen.http_string_answer(bar[0], bar[1]); }
fc94331997-10-25Per Hedbor 
2b658c2000-02-07Per Hedbor  Stdio.File f;
7310762000-09-19Per Hedbor  if( !id->misc->internal_get )
dacef22002-06-05Martin Nilsson  if(f = lopen("data/images/"+from+".gif", "r"))
7310762000-09-19Per Hedbor  return (["file":f, "type":"image/gif", "stat":f->stat()]);
dacef22002-06-05Martin Nilsson  if(f = lopen("data/images/"+from+".png", "r"))
5848842000-08-28Per Hedbor  return (["file":f, "type":"image/png", "stat":f->stat()]);
7310762000-09-19Per Hedbor 
dacef22002-06-05Martin Nilsson  if(f = lopen("data/images/"+from+".jpg", "r"))
7310762000-09-19Per Hedbor  return (["file":f, "type":"image/jpeg", "stat":f->stat()]);
dacef22002-06-05Martin Nilsson  if(f = lopen("data/images/"+from+".xcf", "r"))
5848842000-08-28Per Hedbor  return (["file":f, "type":"image/x-gimp-image", "stat":f->stat()]);
7310762000-09-19Per Hedbor 
dacef22002-06-05Martin Nilsson  if(f = lopen("data/images/"+from+".gif", "r"))
7310762000-09-19Per Hedbor  return (["file":f, "type":"image/gif", "stat":f->stat()]);
2b658c2000-02-07Per Hedbor  // 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 {
3e3bab2001-01-19Per Hedbor  Thread.MutexKey key;
1fab6f1997-09-03Henrik Grubbström (Grubba)  function|int l;
9c19002001-02-27Per Hedbor  TIMER_START(module_lock);
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{
91d3c32001-03-12Martin Nilsson  // report_debug("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  }
91d3c32001-03-12Martin Nilsson  // report_debug("lock %O\n", f);
55a89e1997-09-14Per Hedbor  locked[f]++;
1fab6f1997-09-03Henrik Grubbström (Grubba)  key = l();
b1fca01996-11-12Per Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(module_lock);
14179b1997-01-29Per Hedbor  return key;
b1fca01996-11-12Per Hedbor }
14179b1997-01-29Per Hedbor #define LOCK(X) key=_lock(X)
d7b0871997-08-31Per Hedbor #define UNLOCK() do{key=0;}while(0)
14179b1997-01-29Per Hedbor #else #define LOCK(X)
c95bd51998-01-30Henrik Grubbström (Grubba) #define UNLOCK()
14179b1997-01-29Per Hedbor #endif
a1334f1998-02-20Mirar (Pontus Hagland) string examine_return_mapping(mapping m) { string res; if (m->extra_heads) m->extra_heads=mkmapping(Array.map(indices(m->extra_heads), lower_case), values(m->extra_heads)); else m->extra_heads=([]); switch (m->error||200) { case 302: // redirect
10c7e11999-12-28Martin Nilsson  if (m->extra_heads &&
a1334f1998-02-20Mirar (Pontus Hagland)  (m->extra_heads->location))
1a89f42000-08-14Martin Stjernholm  res = sprintf("Returned redirect to %s ", m->extra_heads->location);
a1334f1998-02-20Mirar (Pontus Hagland)  else
1a89f42000-08-14Martin Stjernholm  res = "Returned redirect, but no location header. ";
a1334f1998-02-20Mirar (Pontus Hagland)  break; case 401: if (m->extra_heads["www-authenticate"])
1a89f42000-08-14Martin Stjernholm  res = sprintf("Returned authentication failed: %s ",
67f60e2000-07-09Martin Nilsson  m->extra_heads["www-authenticate"]);
a1334f1998-02-20Mirar (Pontus Hagland)  else
1a89f42000-08-14Martin Stjernholm  res = "Returned authentication failed. ";
a1334f1998-02-20Mirar (Pontus Hagland)  break; case 200:
1a89f42000-08-14Martin Stjernholm  res = "Returned ok. ";
a1334f1998-02-20Mirar (Pontus Hagland)  break;
a8f1b32000-01-31Per Hedbor 
a1334f1998-02-20Mirar (Pontus Hagland)  default:
1a89f42000-08-14Martin Stjernholm  res = sprintf("Returned %d. ", m->error);
a1334f1998-02-20Mirar (Pontus Hagland)  } if (!zero_type(m->len)) if (m->len<0)
434bac2000-07-14Andreas Lange  res += "No data ";
a1334f1998-02-20Mirar (Pontus Hagland)  else
434bac2000-07-14Andreas Lange  res += sprintf("%d bytes ", m->len);
a1334f1998-02-20Mirar (Pontus Hagland)  else if (stringp(m->data))
434bac2000-07-14Andreas Lange  res += sprintf("%d bytes ", strlen(m->data));
a1334f1998-02-20Mirar (Pontus Hagland)  else if (objectp(m->file)) if (catch {
1f4a6c2000-08-28Per Hedbor  Stat a=m->file->stat();
434bac2000-07-14Andreas Lange  res += sprintf("%d bytes ", a[1]-m->file->tell());
b461641998-10-11Henrik Grubbström (Grubba)  })
1a89f42000-08-14Martin Stjernholm  res += "? bytes ";
a1334f1998-02-20Mirar (Pontus Hagland) 
1a89f42000-08-14Martin Stjernholm  if (m->data) res += "(static)";
434bac2000-07-14Andreas Lange  else if (m->file) res += "(open file)";
a1334f1998-02-20Mirar (Pontus Hagland) 
dffa222000-12-10Per Hedbor  if (stringp(m->extra_heads["content-type"]) ||
b461641998-10-11Henrik Grubbström (Grubba)  stringp(m->type)) {
dffa222000-12-10Per Hedbor  res += sprintf(" of %s", m->type||m->extra_heads["content-type"]);
b461641998-10-11Henrik Grubbström (Grubba)  }
a1334f1998-02-20Mirar (Pontus Hagland)  return res; }
c5e0961999-10-04Per Hedbor 
cd92872000-08-15Johan Sundström mapping|int(-1..0) low_get_file(RequestID id, int|void no_magic) //! The function that actually tries to find the data requested. All //! modules except last and filter type modules are mapped, in order, //! and the first one that returns a suitable response is used. If //! `no_magic' is set to one, the internal magic roxen images and the //! <ref>find_internal()</ref> callbacks will be ignored. //! //! The return values 0 (no such file) and -1 (the data is a //! directory) are only returned when `no_magic' was set to 1; //! otherwise a result mapping is always generated.
14179b1997-01-29Per Hedbor { #ifdef MODULE_LEVEL_SECURITY int slevel; #endif #ifdef THREADS
3e3bab2001-01-19Per Hedbor  Thread.MutexKey key;
14179b1997-01-29Per Hedbor #endif
db5f6b2001-07-31Per Hedbor  id->not_query = VFS.normalize_path( id->not_query );
5655dc2001-06-06Per Hedbor 
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Request for %s", id->not_query), 0);
14179b1997-01-29Per Hedbor  string file=id->not_query; string loc; function funp; mixed tmp, tmp2;
cd92872000-08-15Johan Sundström  mapping|object(Stdio.File)|int fid;
14179b1997-01-29Per Hedbor  if(!no_magic) {
9c19002001-02-27Per Hedbor  TIMER_START(internal_magic);
41b77c1999-07-15David Hedbor #ifndef NO_INTERNAL_HACK
fd93022000-05-05Martin Nilsson  // Find internal-foo-bar images
41b77c1999-07-15David Hedbor  // min length == 17 (/internal-roxen-?..) // This will save some time indeed.
fd93022000-05-05Martin Nilsson  string type;
67f60e2000-07-09Martin Nilsson  if(sizeof(file) > 17 &&
51d4d22001-01-04Martin Nilsson #if ROXEN_COMPAT <= 2.1
67f60e2000-07-09Martin Nilsson  (file[0] == '/') &&
cd92872000-08-15Johan Sundström  sscanf(file, "%*s/internal-%s-%[^/]", type, loc) == 3
67f60e2000-07-09Martin Nilsson #else
cd92872000-08-15Johan Sundström  sscanf(file, "/internal-%s-%[^/]", type, loc) == 2
67f60e2000-07-09Martin Nilsson #endif
cd92872000-08-15Johan Sundström  ) {
41b77c1999-07-15David Hedbor  switch(type) {
fd93022000-05-05Martin Nilsson  case "roxen":
d738ba2002-04-10Jonas Wallden  // Mark all /internal-roxen-* as cacheable even though the user might be // authenticated (which normally disables protocol-level caching). id->misc->cacheable = 9999;
a7d0342000-11-13Martin Nilsson  TRACE_LEAVE("Magic internal roxen image");
5eb2832001-01-03Martin Nilsson  if(loc=="unit" || loc=="pixel-of-destiny")
9c19002001-02-27Per Hedbor  { TIMER_END(internal_magic); return (["data":"GIF89a\1\0\1\0\200ÿ\0ÀÀÀ\0\0\0!ù\4\1\0\0\0\0," "\0\0\0\0\1\0\1\0\0\1\1""2\0;",
2f51ba2002-03-22Martin Stjernholm  "type":"image/gif", "stat": ({0, 0, 0, 900000000, 0, 0, 0})]);
9c19002001-02-27Per Hedbor  }
5eb2832001-01-03Martin Nilsson  if(has_prefix(loc, "pixel-"))
9c19002001-02-27Per Hedbor  { TIMER_END(internal_magic); return (["data":sprintf("GIF89a\1\0\1\0\200\0\0\0\0\0%c%c%c,\0\0\0" "\0\1\0\1\0\0\2\2L\1\0;",
5eb2832001-01-03Martin Nilsson  @parse_color(loc[6..])),
2f51ba2002-03-22Martin Stjernholm  "type":"image/gif", "stat": ({0, 0, 0, 900000000, 0, 0, 0})]);
9c19002001-02-27Per Hedbor  } TIMER_END(internal_magic);
2a346d2000-09-19Per Hedbor  return internal_roxen_image(loc, id);
fd93022000-05-05Martin Nilsson 
41b77c1999-07-15David Hedbor  case "gopher":
a7d0342000-11-13Martin Nilsson  TRACE_LEAVE("Magic internal gopher image");
9c19002001-02-27Per Hedbor  TIMER_END(internal_magic);
14179b1997-01-29Per Hedbor  return internal_gopher_image(loc);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  } #endif
10c7e11999-12-28Martin Nilsson 
fd93022000-05-05Martin Nilsson  // Locate internal location resources.
8552d92001-01-13Martin Nilsson  if(!search(file, query("InternalLoc")))
5839c31999-01-22Marcus Comstedt  {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Magic internal module location", 0);
e351dd1999-11-29Per Hedbor  RoxenModule module;
5839c31999-01-22Marcus Comstedt  string name, rest; function find_internal;
8552d92001-01-13Martin Nilsson  if(2==sscanf(file[strlen(query("InternalLoc"))..], "%s/%s", name, rest) &&
5839c31999-01-22Marcus Comstedt  (module = find_module(replace(name, "!", "#"))) && (find_internal = module->find_internal)) { #ifdef MODULE_LEVEL_SECURITY if(tmp2 = check_security(find_internal, id, slevel)) if(intp(tmp2)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission to access module denied.");
5839c31999-01-22Marcus Comstedt  find_internal = 0; } else { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Request denied.");
9c19002001-02-27Per Hedbor  TIMER_END(internal_magic);
5839c31999-01-22Marcus Comstedt  return tmp2; } #endif
41b77c1999-07-15David Hedbor  if(find_internal)
5839c31999-01-22Marcus Comstedt  {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Calling find_internal()...", find_internal);
4717052001-05-07Per Hedbor  PROF_ENTER("find_internal","location");
5839c31999-01-22Marcus Comstedt  LOCK(find_internal); fid=find_internal( rest, id ); UNLOCK();
02c6642001-08-22Martin Stjernholm  //TRACE_LEAVE(sprintf("find_internal has returned %O", fid)); TRACE_LEAVE("");
4717052001-05-07Per Hedbor  PROF_LEAVE("find_internal","location");
5839c31999-01-22Marcus Comstedt  if(fid) { if(mappingp(fid)) { TRACE_LEAVE(""); TRACE_LEAVE(examine_return_mapping(fid));
9c19002001-02-27Per Hedbor  TIMER_END(internal_magic);
5839c31999-01-22Marcus Comstedt  return fid; } else { #ifdef MODULE_LEVEL_SECURITY int oslevel = slevel; slevel = misc_cache[ find_internal ][1]; // misc_cache from // check_security id->misc->seclevel = slevel; #endif if(objectp(fid))
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned open filedescriptor. "
5839c31999-01-22Marcus Comstedt #ifdef MODULE_LEVEL_SECURITY +(slevel != oslevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
5839c31999-01-22Marcus Comstedt #endif
67f60e2000-07-09Martin Nilsson  );
5839c31999-01-22Marcus Comstedt  else
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned directory indicator."
5839c31999-01-22Marcus Comstedt #ifdef MODULE_LEVEL_SECURITY +(oslevel != slevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
5839c31999-01-22Marcus Comstedt #endif ); } } else TRACE_LEAVE(""); } else TRACE_LEAVE(""); } else TRACE_LEAVE(""); }
9c19002001-02-27Per Hedbor  TIMER_END(internal_magic);
14179b1997-01-29Per Hedbor  } // Well, this just _might_ be somewhat over-optimized, since it is
10c7e11999-12-28Martin Nilsson  // quite unreadable, but, you cannot win them all..
5839c31999-01-22Marcus Comstedt  if(!fid) {
14179b1997-01-29Per Hedbor #ifdef URL_MODULES
f128901997-08-15Henrik Grubbström (Grubba)  // Map URL-modules
9c19002001-02-27Per Hedbor  TIMER_START(url_modules);
517c7e2000-09-30Per Hedbor  foreach(url_module_cache||url_modules(), funp)
41d0f91998-02-20Per Hedbor  {
4717052001-05-07Per Hedbor  PROF_ENTER(Roxen.get_owning_module(funp)->module_name,"url module");
5839c31999-01-22Marcus Comstedt  LOCK(funp);
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
5839c31999-01-22Marcus Comstedt  tmp=funp( id, file ); UNLOCK();
4717052001-05-07Per Hedbor  PROF_LEAVE(Roxen.get_owning_module(funp)->module_name,"url module");
10c7e11999-12-28Martin Nilsson  if(mappingp(tmp))
5839c31999-01-22Marcus Comstedt  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
9c19002001-02-27Per Hedbor  TIMER_END(url_modules);
5839c31999-01-22Marcus Comstedt  return tmp; } if(objectp( tmp )) {
a51a902001-11-12Martin Stjernholm  mixed err;
a8f1b32000-01-31Per Hedbor 
5839c31999-01-22Marcus Comstedt  nest ++; err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->low_get_file( tmp, no_magic ); else {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Too deep recursion");
5839c31999-01-22Marcus Comstedt  error("Too deep recursion in roxen::get_file() while mapping " +file+".\n"); } }; nest = 0; if(err) throw(err); TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
9c19002001-02-27Per Hedbor  TIMER_END(url_modules);
5839c31999-01-22Marcus Comstedt  return tmp; }
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
9c19002001-02-27Per Hedbor  TIMER_END(url_modules);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor #endif
c5e0961999-10-04Per Hedbor 
9c19002001-02-27Per Hedbor  TIMER_START(location_modules);
517c7e2000-09-30Per Hedbor  foreach(location_module_cache||location_modules(), tmp)
14179b1997-01-29Per Hedbor  {
5839c31999-01-22Marcus Comstedt  loc = tmp[0];
41b77c1999-07-15David Hedbor  if(!search(file, loc))
5839c31999-01-22Marcus Comstedt  {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
df8d711998-02-27Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  if(tmp2 = check_security(tmp[1], id, slevel)) if(intp(tmp2)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission to access module denied.");
5839c31999-01-22Marcus Comstedt  continue; } else { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Request denied.");
9c19002001-02-27Per Hedbor  TIMER_END(location_modules);
5839c31999-01-22Marcus Comstedt  return tmp2; }
14179b1997-01-29Per Hedbor #endif
7937df2001-05-16Per Hedbor  PROF_ENTER(Roxen.get_owning_module(tmp[1])->module_name,"location");
434bac2000-07-14Andreas Lange  TRACE_ENTER("Calling find_file()...", 0);
5839c31999-01-22Marcus Comstedt  LOCK(tmp[1]); fid=tmp[1]( file[ strlen(loc) .. ] + id->extra_extension, id); UNLOCK();
b8b1072000-03-24Per Hedbor  TRACE_LEAVE("");
7937df2001-05-16Per Hedbor  PROF_LEAVE(Roxen.get_owning_module(tmp[1])->module_name,"location");
5839c31999-01-22Marcus Comstedt  if(fid)
14179b1997-01-29Per Hedbor  {
5839c31999-01-22Marcus Comstedt  id->virtfile = loc;
a8f1b32000-01-31Per Hedbor 
5839c31999-01-22Marcus Comstedt  if(mappingp(fid)) { TRACE_LEAVE(""); TRACE_LEAVE(examine_return_mapping(fid));
9c19002001-02-27Per Hedbor  TIMER_END(location_modules);
5839c31999-01-22Marcus Comstedt  return fid; } else {
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  int oslevel = slevel; slevel = misc_cache[ tmp[1] ][1]; // misc_cache from // check_security id->misc->seclevel = slevel;
14179b1997-01-29Per Hedbor #endif
5839c31999-01-22Marcus Comstedt  if(objectp(fid))
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned open filedescriptor."
41d0f91998-02-20Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  +(slevel != oslevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
41d0f91998-02-20Per Hedbor #endif
a8f1b32000-01-31Per Hedbor 
67f60e2000-07-09Martin Nilsson  );
5839c31999-01-22Marcus Comstedt  else
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned directory indicator."
41d0f91998-02-20Per Hedbor #ifdef MODULE_LEVEL_SECURITY
5839c31999-01-22Marcus Comstedt  +(oslevel != slevel?
434bac2000-07-14Andreas Lange  sprintf(" The security level is now %d.", slevel):"")
41d0f91998-02-20Per Hedbor #endif
5839c31999-01-22Marcus Comstedt  ); break; } } else TRACE_LEAVE("");
41b77c1999-07-15David Hedbor  } else if(strlen(loc)-1==strlen(file) && file+"/" == loc) {
10c7e11999-12-28Martin Nilsson  // This one is here to allow accesses to /local, even if
5839c31999-01-22Marcus Comstedt  // the mountpoint is /local/. It will slow things down, but...
67f60e2000-07-09Martin Nilsson 
434bac2000-07-14Andreas Lange  TRACE_ENTER("Automatic redirect to location_module.", tmp[1]); TRACE_LEAVE("Returning data");
a8f1b32000-01-31Per Hedbor 
41b77c1999-07-15David Hedbor  // Keep query (if any).
fd93022000-05-05Martin Nilsson  // FIXME: Should probably keep config <foo>
dfe0362000-03-19Martin Nilsson  string new_query = Roxen.http_encode_string(id->not_query) + "/" +
41b77c1999-07-15David Hedbor  (id->query?("?"+id->query):"");
fd93022000-05-05Martin Nilsson  new_query=Roxen.add_pre_state(new_query, id->prestate);
a8f1b32000-01-31Per Hedbor 
9c19002001-02-27Per Hedbor  TIMER_END(location_modules);
dfe0362000-03-19Martin Nilsson  return Roxen.http_redirect(new_query, id);
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(location_modules);
14179b1997-01-29Per Hedbor  }
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(fid == -1) {
41d0f91998-02-20Per Hedbor  if(no_magic) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("No magic requested. Returning -1.");
41d0f91998-02-20Per Hedbor  return -1; }
9c19002001-02-27Per Hedbor  TIMER_START(directory_module);
14179b1997-01-29Per Hedbor  if(dir_module) {
7937df2001-05-16Per Hedbor  PROF_ENTER(dir_module->module_name,"directory");
14179b1997-01-29Per Hedbor  LOCK(dir_module);
434bac2000-07-14Andreas Lange  TRACE_ENTER("Directory module", dir_module);
14179b1997-01-29Per Hedbor  fid = dir_module->parse_directory(id); UNLOCK();
7937df2001-05-16Per Hedbor  PROF_LEAVE(dir_module->module_name,"directory");
14179b1997-01-29Per Hedbor  } else
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("No directory module. Returning 'no such file'");
14179b1997-01-29Per Hedbor  return 0;
41d0f91998-02-20Per Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(directory_module);
10c7e11999-12-28Martin Nilsson  if(mappingp(fid))
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
41d0f91998-02-20Per Hedbor  return (mapping)fid; }
14179b1997-01-29Per Hedbor  }
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  // Map the file extensions, but only if there is a file...
9c19002001-02-27Per Hedbor  TIMER_START(extension_module);
41b77c1999-07-15David Hedbor  if(objectp(fid) &&
f511c52001-08-31Per Hedbor  (tmp = file_extension_modules(loc = lower_case(Roxen.extension(id->not_query, id)))))
517c7e2000-09-30Per Hedbor  {
14179b1997-01-29Per Hedbor  foreach(tmp, funp) {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Extension module [%s] ", loc), funp);
14179b1997-01-29Per Hedbor #ifdef MODULE_LEVEL_SECURITY if(tmp=check_security(funp, id, slevel)) if(intp(tmp)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission to access module denied.");
14179b1997-01-29Per Hedbor  continue; } else
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission denied");
9c19002001-02-27Per Hedbor  TIMER_END(extension_module);
14179b1997-01-29Per Hedbor  return tmp;
41d0f91998-02-20Per Hedbor  }
14179b1997-01-29Per Hedbor #endif
7937df2001-05-16Per Hedbor  PROF_ENTER(Roxen.get_owning_module(funp)->module_name,"ext");
14179b1997-01-29Per Hedbor  LOCK(funp); tmp=funp(fid, loc, id); UNLOCK();
7937df2001-05-16Per Hedbor  PROF_LEAVE(Roxen.get_owning_module(funp)->module_name,"ext");
14179b1997-01-29Per Hedbor  if(tmp) { if(!objectp(tmp))
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
9c19002001-02-27Per Hedbor  TIMER_END(extension_module);
14179b1997-01-29Per Hedbor  return tmp;
41d0f91998-02-20Per Hedbor  }
cd92872000-08-15Johan Sundström  if(fid && tmp != fid)
41b77c1999-07-15David Hedbor  destruct(fid);
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned new open file");
14179b1997-01-29Per Hedbor  fid = tmp; break;
41d0f91998-02-20Per Hedbor  } else TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  }
41b77c1999-07-15David Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(extension_module);
fd93022000-05-05Martin Nilsson 
14179b1997-01-29Per Hedbor  if(objectp(fid)) {
9c19002001-02-27Per Hedbor  TIMER_START(content_type_module);
41b77c1999-07-15David Hedbor  if(stringp(id->extension)) {
14179b1997-01-29Per Hedbor  id->not_query += id->extension;
f511c52001-08-31Per Hedbor  loc = lower_case(Roxen.extension(id->not_query, id));
41b77c1999-07-15David Hedbor  }
434bac2000-07-14Andreas Lange  TRACE_ENTER("Content-type mapping module", types_module);
41b77c1999-07-15David Hedbor  tmp=type_from_filename(id->not_query, 1, loc);
3d94582000-07-31Martin Nilsson  TRACE_LEAVE(tmp?sprintf("Returned type %s %s.", tmp[0], tmp[1]||"")
434bac2000-07-14Andreas Lange  : "Missing type.");
14179b1997-01-29Per Hedbor  if(tmp)
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
9c19002001-02-27Per Hedbor  TIMER_END(content_type_module);
14179b1997-01-29Per Hedbor  return ([ "file":fid, "type":tmp[0], "encoding":tmp[1] ]);
10c7e11999-12-28Martin Nilsson  }
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
9c19002001-02-27Per Hedbor  TIMER_END(content_type_module);
14179b1997-01-29Per Hedbor  return ([ "file":fid, ]); }
9c19002001-02-27Per Hedbor 
41d0f91998-02-20Per Hedbor  if(!fid)
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'no such file'.");
41d0f91998-02-20Per Hedbor  else
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
14179b1997-01-29Per Hedbor  return fid; }
e351dd1999-11-29Per Hedbor mixed handle_request( RequestID id )
c7a5f01999-02-16Per Hedbor { function funp; mixed file;
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request()");
9c19002001-02-27Per Hedbor  TIMER_START(handle_request); TIMER_START(first_modules);
517c7e2000-09-30Per Hedbor  foreach(first_module_cache||first_modules(), funp)
c7a5f01999-02-16Per Hedbor  {
10c7e11999-12-28Martin Nilsson  if(file = funp( id ))
c7a5f01999-02-16Per Hedbor  break;
cfda381999-03-28Henrik Grubbström (Grubba)  if(id->conf != this_object()) {
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request(): Redirected (2)");
c7a5f01999-02-16Per Hedbor  return id->conf->handle_request(id);
cfda381999-03-28Henrik Grubbström (Grubba)  }
c7a5f01999-02-16Per Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(first_modules);
fd8b151999-05-19David Hedbor  if(!mappingp(file) && !mappingp(file = get_file(id)))
c7a5f01999-02-16Per Hedbor  { mixed ret;
9c19002001-02-27Per Hedbor  TIMER_START(last_modules);
517c7e2000-09-30Per Hedbor  foreach(last_module_cache||last_modules(), funp) if(ret = funp(id)) break;
cfda381999-03-28Henrik Grubbström (Grubba)  if (ret == 1) {
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request(): Recurse");
9c19002001-02-27Per Hedbor  TIMER_END(last_modules); TIMER_END(handle_request);
c7a5f01999-02-16Per Hedbor  return handle_request(id);
cfda381999-03-28Henrik Grubbström (Grubba)  }
c7a5f01999-02-16Per Hedbor  file = ret;
9c19002001-02-27Per Hedbor  TIMER_END(last_modules);
c7a5f01999-02-16Per Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(handle_request);
10c7e11999-12-28Martin Nilsson  REQUEST_WERR("handle_request(): Done");
9c19002001-02-27Per Hedbor  MERGE_TIMERS(roxen);
c7a5f01999-02-16Per Hedbor  return file; }
fd93022000-05-05Martin Nilsson mapping get_file(RequestID id, int|void no_magic, int|void internal_get)
cd92872000-08-15Johan Sundström //! Return a result mapping for the id object at hand, mapping all //! modules, including the filter modules. This function is mostly a //! wrapper for <ref>low_get_file()</ref>.
14179b1997-01-29Per Hedbor {
9c19002001-02-27Per Hedbor  TIMER_START(get_file);
576c112000-03-07Martin Stjernholm  int orig_internal_get = id->misc->internal_get; id->misc->internal_get = internal_get;
483b062002-05-16Stefan Wallström  RequestID root_id = id->root_id || id; int sub_req_limit = query("SubRequestLimit"); root_id->misc->_request_depth++; if(sub_req_limit && root_id->misc->_request_depth > sub_req_limit)
98501d2002-07-03Martin Nilsson  error( "Subrequest limit reached. (Possibly an insertion loop.)" );
576c112000-03-07Martin Stjernholm 
fd93022000-05-05Martin Nilsson  mapping|int res; mapping res2;
14179b1997-01-29Per Hedbor  function tmp; res = low_get_file(id, no_magic);
9c19002001-02-27Per Hedbor  TIMER_END(get_file);
fd93022000-05-05Martin Nilsson 
14179b1997-01-29Per Hedbor  // finally map all filter type modules. // Filter modules are like TYPE_LAST modules, but they get called // for _all_ files.
9c19002001-02-27Per Hedbor  TIMER_START(filter_modules);
517c7e2000-09-30Per Hedbor  foreach(filter_module_cache||filter_modules(), tmp)
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Filter module", tmp);
4717052001-05-07Per Hedbor  PROF_ENTER(Roxen.get_owning_module(tmp)->module_name,"filter");
14179b1997-01-29Per Hedbor  if(res2=tmp(res,id)) { if(res && res->file && (res2->file != res->file)) destruct(res->file);
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Rewrote result.");
14179b1997-01-29Per Hedbor  res=res2;
41d0f91998-02-20Per Hedbor  } else TRACE_LEAVE("");
4717052001-05-07Per Hedbor  PROF_LEAVE(Roxen.get_owning_module(tmp)->module_name,"filter");
41d0f91998-02-20Per Hedbor  }
9c19002001-02-27Per Hedbor  TIMER_END(filter_modules);
576c112000-03-07Martin Stjernholm 
483b062002-05-16Stefan Wallström  root_id->misc->_request_depth--;
576c112000-03-07Martin Stjernholm  id->misc->internal_get = orig_internal_get;
14179b1997-01-29Per Hedbor  return res; }
9a8a152000-09-25Per Hedbor array(string) find_dir(string file, RequestID id, void|int(0..1) verbose)
14179b1997-01-29Per Hedbor {
fd93022000-05-05Martin Nilsson  array dir;
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("List directory %O.", file), 0);
10c7e11999-12-28Martin Nilsson 
db43d12000-11-24Martin Stjernholm  if(!sizeof (file) || file[0] != '/')
1935351997-04-28Henrik Grubbström (Grubba)  file = "/" + file;
f128901997-08-15Henrik Grubbström (Grubba) #ifdef URL_MODULES
fc0e5d1997-08-26Henrik Grubbström (Grubba) #ifdef THREADS
3e3bab2001-01-19Per Hedbor  Thread.MutexKey key;
fc0e5d1997-08-26Henrik Grubbström (Grubba) #endif
f128901997-08-15Henrik Grubbström (Grubba)  // Map URL-modules
517c7e2000-09-30Per Hedbor  foreach(url_modules(), function funp)
f128901997-08-15Henrik Grubbström (Grubba)  { string of = id->not_query; id->not_query = file; LOCK(funp);
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
3e3bab2001-01-19Per Hedbor  mixed remap=funp( id, file );
f128901997-08-15Henrik Grubbström (Grubba)  UNLOCK();
fd93022000-05-05Martin Nilsson  if(mappingp( remap ))
f128901997-08-15Henrik Grubbström (Grubba)  { id->not_query=of;
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'No thanks'.");
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  return 0; }
fd93022000-05-05Martin Nilsson  if(objectp( remap ))
f128901997-08-15Henrik Grubbström (Grubba)  {
a51a902001-11-12Martin Stjernholm  mixed err;
f128901997-08-15Henrik Grubbström (Grubba)  nest ++;
10c7e11999-12-28Martin Nilsson 
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Recursing");
f128901997-08-15Henrik Grubbström (Grubba)  file = id->not_query; err = catch { if( nest < 20 )
fd93022000-05-05Martin Nilsson  dir = (id->conf || this_object())->find_dir( file, id );
f128901997-08-15Henrik Grubbström (Grubba)  else error("Too deep recursion in roxen::find_dir() while mapping " +file+".\n"); }; nest = 0;
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  if(err) throw(err);
fd93022000-05-05Martin Nilsson  return dir;
f128901997-08-15Henrik Grubbström (Grubba)  } id->not_query=of; }
a86c6c1997-09-22Henrik Grubbström (Grubba) #endif /* URL_MODULES */
f128901997-08-15Henrik Grubbström (Grubba) 
3e3bab2001-01-19Per Hedbor  array | mapping d;
e927de2000-05-06Martin Nilsson  array(string) locks=({});
3e3bab2001-01-19Per Hedbor  RoxenModule mod;
e927de2000-05-06Martin Nilsson  string loc;
517c7e2000-09-30Per Hedbor  foreach(location_modules(), array tmp)
14179b1997-01-29Per Hedbor  { loc = tmp[0];
a476711997-10-20Henrik Grubbström (Grubba)  if(!search(file, loc)) { /* file == loc + subpath */
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
a78a591997-04-28Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY
41d0f91998-02-20Per Hedbor  if(check_security(tmp[1], id)) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission denied");
41d0f91998-02-20Per Hedbor  continue; }
a78a591997-04-28Henrik Grubbström (Grubba) #endif
e927de2000-05-06Martin Nilsson  mod=function_object(tmp[1]); if(d=mod->find_dir(file[strlen(loc)..], id))
41d0f91998-02-20Per Hedbor  {
29a8071998-08-21David Hedbor  if(mappingp(d)) {
10c7e11999-12-28Martin Nilsson  if(d->files) {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Got exclusive directory."); TRACE_LEAVE(sprintf("Returning list of %d files.", sizeof(d->files)));
fd93022000-05-05Martin Nilsson  return d->files;
29a8071998-08-21David Hedbor  } else TRACE_LEAVE(""); } else {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Got files.");
e927de2000-05-06Martin Nilsson  if(!dir) dir=({ });
29a8071998-08-21David Hedbor  dir |= d; }
e927de2000-05-06Martin Nilsson  } else { if(verbose && mod->list_lock_files) locks |= mod->list_lock_files();
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
e927de2000-05-06Martin Nilsson  }
a476711997-10-20Henrik Grubbström (Grubba)  } else if((search(loc, file)==0) && (loc[strlen(file)-1]=='/') && (loc[0]==loc[-1]) && (loc[-1]=='/') &&
6c67c81998-02-28Johan Schön  (function_object(tmp[1])->stat_file(".", id))) {
a476711997-10-20Henrik Grubbström (Grubba)  /* loc == file + "/" + subpath + "/"
24fa081998-02-28Henrik Grubbström (Grubba)  * and stat_file(".") returns non-zero.
a476711997-10-20Henrik Grubbström (Grubba)  */
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
a476711997-10-20Henrik Grubbström (Grubba)  loc=loc[strlen(file)..]; sscanf(loc, "%s/", loc);
df40452000-06-19Henrik Grubbström (Grubba)  if (dir) { dir |= ({ loc }); } else { dir = ({ loc }); }
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Added module mountpoint.");
14179b1997-01-29Per Hedbor  } }
e927de2000-05-06Martin Nilsson  if(!dir) return verbose ? ({0})+locks : ([])[0];
14179b1997-01-29Per Hedbor  if(sizeof(dir))
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_LEAVE(sprintf("Returning list of %d files.", sizeof(dir)));
14179b1997-01-29Per Hedbor  return dir;
10c7e11999-12-28Martin Nilsson  }
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning 'No such directory'.");
fd93022000-05-05Martin Nilsson  return 0;
14179b1997-01-29Per Hedbor }
10c7e11999-12-28Martin Nilsson // Stat a virtual file.
14179b1997-01-29Per Hedbor 
9a8a152000-09-25Per Hedbor array(int)|Stat stat_file(string file, RequestID id)
14179b1997-01-29Per Hedbor { string loc;
1f4a6c2000-08-28Per Hedbor  mixed s, tmp;
c5e0961999-10-04Per Hedbor #ifdef THREADS
3e3bab2001-01-19Per Hedbor  Thread.MutexKey key;
c5e0961999-10-04Per Hedbor #endif
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Stat file %O.", file), 0);
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  file=replace(file, "//", "/"); // "//" is really "/" here...
f128901997-08-15Henrik Grubbström (Grubba)  #ifdef URL_MODULES // Map URL-modules
517c7e2000-09-30Per Hedbor  foreach(url_modules(), function funp)
f128901997-08-15Henrik Grubbström (Grubba)  { string of = id->not_query; id->not_query = file;
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
f128901997-08-15Henrik Grubbström (Grubba)  LOCK(funp); tmp=funp( id, file ); UNLOCK(); if(mappingp( tmp )) { id->not_query = of;
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'No thanks'.");
f128901997-08-15Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) { file = id->not_query;
a51a902001-11-12Martin Stjernholm  mixed err;
f128901997-08-15Henrik Grubbström (Grubba)  nest ++;
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Recursing");
f128901997-08-15Henrik Grubbström (Grubba)  err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->stat_file( file, id ); else error("Too deep recursion in roxen::stat_file() while mapping " +file+".\n"); }; nest = 0; if(err) throw(err);
8fd51f1998-03-01Per Hedbor  TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returning data");
f128901997-08-15Henrik Grubbström (Grubba)  return tmp; }
8fd51f1998-03-01Per Hedbor  TRACE_LEAVE("");
f128901997-08-15Henrik Grubbström (Grubba)  id->not_query = of; } #endif
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  // Map location-modules.
517c7e2000-09-30Per Hedbor  foreach(location_modules(), tmp)
14179b1997-01-29Per Hedbor  { loc = tmp[0]; if((file == loc) || ((file+"/")==loc))
41d0f91998-02-20Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]); TRACE_LEAVE("Exact match.");
41d0f91998-02-20Per Hedbor  TRACE_LEAVE("");
223fd12000-01-27Johan Sundström  return ({ 0775, -3, 0, 0, 0, 0, 0 });
41d0f91998-02-20Per Hedbor  }
10c7e11999-12-28Martin Nilsson  if(!search(file, loc))
14179b1997-01-29Per Hedbor  {
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), tmp[1]);
a78a591997-04-28Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY
41d0f91998-02-20Per Hedbor  if(check_security(tmp[1], id)) {
8fd51f1998-03-01Per Hedbor  TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Permission denied");
41d0f91998-02-20Per Hedbor  continue; }
a78a591997-04-28Henrik Grubbström (Grubba) #endif
14179b1997-01-29Per Hedbor  if(s=function_object(tmp[1])->stat_file(file[strlen(loc)..], id))
41d0f91998-02-20Per Hedbor  { TRACE_LEAVE("");
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Stat ok.");
14179b1997-01-29Per Hedbor  return s;
41d0f91998-02-20Per Hedbor  } TRACE_LEAVE("");
14179b1997-01-29Per Hedbor  } }
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned 'no such file'.");
14179b1997-01-29Per Hedbor }
73ce3d2000-12-11Per Hedbor mapping error_file( RequestID id ) { string data = query("ZNoSuchFile"); NOCACHE();
51d4d22001-01-04Martin Nilsson #if ROXEN_COMPAT <= 2.1
73ce3d2000-12-11Per Hedbor  data = replace(data,({"$File", "$Me"}),
1493442000-12-17Henrik Grubbström (Grubba)  ({"&page.virtfile;", "&roxen.server;"}));
73ce3d2000-12-11Per Hedbor #endif
1371e02001-06-22Martin Nilsson  mapping res = Roxen.http_rxml_answer( data, id, 0, "text/html" ); res->error = 404; return res;
73ce3d2000-12-11Per Hedbor }
e8790b1998-02-19Per Hedbor // this is not as trivial as it sounds. Consider gtext. :-)
9a8a152000-09-25Per Hedbor array open_file(string fname, string mode, RequestID id, void|int internal_get)
e8790b1998-02-19Per Hedbor {
517c7e2000-09-30Per Hedbor  if( id->conf && (id->conf != this_object()) ) return id->conf->open_file( fname, mode, id, internal_get );
3e3bab2001-01-19Per Hedbor  Configuration oc = id->conf;
e8790b1998-02-19Per Hedbor  string oq = id->not_query; function funp;
3a4b9a1999-12-27Martin Nilsson  mapping|int(0..1) file;
cd7ea41998-12-14Peter Bortas  id->not_query = fname;
c7a5f01999-02-16Per Hedbor 
517c7e2000-09-30Per Hedbor  foreach(first_modules(), funp)
10c7e11999-12-28Martin Nilsson  if(file = funp( id ))
e8790b1998-02-19Per Hedbor  break;
517c7e2000-09-30Per Hedbor  else if(id->conf && (id->conf != oc))
e8790b1998-02-19Per Hedbor  {
517c7e2000-09-30Per Hedbor  return id->conf->open_file(fname, mode,id, internal_get);
e8790b1998-02-19Per Hedbor  } fname = id->not_query; if(search(mode, "R")!=-1) // raw (as in not parsed..) { string f; mode -= "R"; if(f = real_file(fname, id))
41d0f91998-02-20Per Hedbor  {
91d3c32001-03-12Martin Nilsson  // report_debug("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) {
517c7e2000-09-30Per Hedbor  file = get_file( id, 0, internal_get );
f920ce1998-10-02Henrik Grubbström (Grubba)  if(!file) {
517c7e2000-09-30Per Hedbor  foreach(last_modules(), funp) if(file = funp( id ))
e8790b1998-02-19Per Hedbor  break;
f920ce1998-10-02Henrik Grubbström (Grubba)  if (file == 1) { // Recurse.
484ec92000-06-23Martin Stjernholm  return open_file(id->not_query, mode, id, internal_get);
f920ce1998-10-02Henrik Grubbström (Grubba)  } }
e8790b1998-02-19Per Hedbor  } if(!mappingp(file)) { if(id->misc->error_code)
dfe0362000-03-19Martin Nilsson  file = Roxen.http_low_answer(id->misc->error_code, "Failed" );
2380831998-02-22Per Hedbor  else if(id->method!="GET"&&id->method != "HEAD"&&id->method!="POST")
dfe0362000-03-19Martin Nilsson  file = Roxen.http_low_answer(501, "Not implemented.");
73ce3d2000-12-11Per Hedbor  else file = error_file( id );
e8790b1998-02-19Per Hedbor  id->not_query = oq;
10c7e11999-12-28Martin Nilsson 
e8790b1998-02-19Per Hedbor  return ({ 0, file }); }
10c7e11999-12-28Martin Nilsson  if( file->data )
e8790b1998-02-19Per Hedbor  { file->file = StringFile(file->data); m_delete(file, "data");
10c7e11999-12-28Martin Nilsson  }
e8790b1998-02-19Per Hedbor  id->not_query = oq; return ({ file->file, file }); } id->not_query = oq;
23414a2000-07-21Andreas Lange  return ({ 0, (["error":501, "data":"Not implemented." ]) });
e8790b1998-02-19Per Hedbor }
9a8a152000-09-25Per Hedbor mapping(string:array(mixed)) find_dir_stat(string file, RequestID id)
a86c6c1997-09-22Henrik Grubbström (Grubba) { string loc;
a476711997-10-20Henrik Grubbström (Grubba)  mapping(string:array(mixed)) dir = ([]); mixed d, tmp;
a86c6c1997-09-22Henrik Grubbström (Grubba) 
c7a5f01999-02-16Per Hedbor 
a86c6c1997-09-22Henrik Grubbström (Grubba)  file=replace(file, "//", "/");
10c7e11999-12-28Martin Nilsson 
db43d12000-11-24Martin Stjernholm  if(!sizeof (file) || file[0] != '/')
a86c6c1997-09-22Henrik Grubbström (Grubba)  file = "/" + file;
ae60b61998-05-23Henrik Grubbström (Grubba)  // FIXME: Should I append a "/" to file if missing?
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Request for directory and stat's \"%s\".", file), 0);
ae60b61998-05-23Henrik Grubbström (Grubba) 
a86c6c1997-09-22Henrik Grubbström (Grubba) #ifdef URL_MODULES #ifdef THREADS
3e3bab2001-01-19Per Hedbor  Thread.MutexKey key;
a86c6c1997-09-22Henrik Grubbström (Grubba) #endif // Map URL-modules
517c7e2000-09-30Per Hedbor  foreach(url_modules(), function funp)
a86c6c1997-09-22Henrik Grubbström (Grubba)  { string of = id->not_query; id->not_query = file; LOCK(funp);
434bac2000-07-14Andreas Lange  TRACE_ENTER("URL module", funp);
a86c6c1997-09-22Henrik Grubbström (Grubba)  tmp=funp( id, file ); UNLOCK(); if(mappingp( tmp )) { id->not_query=of;
3510fb1997-11-09Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
91d3c32001-03-12Martin Nilsson  report_debug("conf->find_dir_stat(\"%s\"): url_module returned mapping:%O\n", file, tmp);
3510fb1997-11-09Henrik Grubbström (Grubba) #endif /* MODULE_DEBUG */
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned mapping."+sprintf("%O", tmp));
07014c1999-05-24Per Hedbor  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  return 0; } if(objectp( tmp )) {
a51a902001-11-12Martin Stjernholm  mixed err;
a86c6c1997-09-22Henrik Grubbström (Grubba)  nest ++;
10c7e11999-12-28Martin Nilsson 
a86c6c1997-09-22Henrik Grubbström (Grubba)  file = id->not_query; err = catch { if( nest < 20 ) tmp = (id->conf || this_object())->find_dir_stat( file, id );
ae60b61998-05-23Henrik Grubbström (Grubba)  else {
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Too deep recursion");
a86c6c1997-09-22Henrik Grubbström (Grubba)  error("Too deep recursion in roxen::find_dir_stat() while mapping " +file+".\n");
ae60b61998-05-23Henrik Grubbström (Grubba)  }
a86c6c1997-09-22Henrik Grubbström (Grubba)  }; nest = 0; if(err) throw(err);
3510fb1997-11-09Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
91d3c32001-03-12Martin Nilsson  report_debug("conf->find_dir_stat(\"%s\"): url_module returned object:\n", file);
3510fb1997-11-09Henrik Grubbström (Grubba) #endif /* MODULE_DEBUG */
434bac2000-07-14Andreas Lange  TRACE_LEAVE("Returned object."); TRACE_LEAVE("Returning it.");
ae60b61998-05-23Henrik Grubbström (Grubba)  return tmp; // FIXME: Return 0 instead?
a86c6c1997-09-22Henrik Grubbström (Grubba)  } id->not_query=of;
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  } #endif /* URL_MODULES */
517c7e2000-09-30Per Hedbor  foreach(location_modules(), tmp)
a86c6c1997-09-22Henrik Grubbström (Grubba)  { loc = tmp[0];
a476711997-10-20Henrik Grubbström (Grubba) 
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("Location module [%s] ", loc), 0);
a476711997-10-20Henrik Grubbström (Grubba)  /* Note that only new entries are added. */
a86c6c1997-09-22Henrik Grubbström (Grubba)  if(!search(file, loc)) {
a476711997-10-20Henrik Grubbström (Grubba)  /* file == loc + subpath */
a86c6c1997-09-22Henrik Grubbström (Grubba) #ifdef MODULE_LEVEL_SECURITY if(check_security(tmp[1], id)) continue; #endif
e351dd1999-11-29Per Hedbor  RoxenModule c = function_object(tmp[1]);
a86c6c1997-09-22Henrik Grubbström (Grubba)  string f = file[strlen(loc)..]; if (c->find_dir_stat) {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Has find_dir_stat().", 0);
a86c6c1997-09-22Henrik Grubbström (Grubba)  if (d = c->find_dir_stat(f, id)) {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Returned mapping."+sprintf("%O", d), c);
a476711997-10-20Henrik Grubbström (Grubba)  dir = d | dir;
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  } else if(d = c->find_dir(f, id)) {
434bac2000-07-14Andreas Lange  TRACE_ENTER("Returned array.", 0);
10c7e11999-12-28Martin Nilsson  dir = mkmapping(d, Array.map(d, lambda(string fn)
e351dd1999-11-29Per Hedbor  { return c->stat_file(f + fn, id); })) | dir;
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
a476711997-10-20Henrik Grubbström (Grubba)  } else if(search(loc, file)==0 && loc[strlen(file)-1]=='/' && (loc[0]==loc[-1]) && loc[-1]=='/' &&
8935ad1998-03-30Johan Schön  (function_object(tmp[1])->stat_file(".", id))) {
a476711997-10-20Henrik Grubbström (Grubba)  /* loc == file + "/" + subpath + "/"
8935ad1998-03-30Johan Schön  * and stat_file(".") returns non-zero.
a476711997-10-20Henrik Grubbström (Grubba)  */
434bac2000-07-14Andreas Lange  TRACE_ENTER(sprintf("The file %O is on the path to the mountpoint %O.",
67f60e2000-07-09Martin Nilsson  file, loc), 0);
a476711997-10-20Henrik Grubbström (Grubba)  loc=loc[strlen(file)..]; sscanf(loc, "%s/", loc); if (!dir[loc]) {
cd92872000-08-15Johan Sundström  dir[loc] = ({ 0775, -3, 0, 0, 0, 0, 0 });
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  }
ae60b61998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a86c6c1997-09-22Henrik Grubbström (Grubba)  } if(sizeof(dir)) return dir; }
14179b1997-01-29Per Hedbor  // Access a virtual file?
9a8a152000-09-25Per Hedbor array access(string file, RequestID id)
14179b1997-01-29Per Hedbor { string loc; array s, tmp;
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  file=replace(file, "//", "/"); // "//" is really "/" here...
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  // Map location-modules.
517c7e2000-09-30Per Hedbor  foreach(location_modules(), tmp)
14179b1997-01-29Per Hedbor  { 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 }
9a8a152000-09-25Per Hedbor string real_file(string file, RequestID id)
9fd8092000-08-08Johan Sundström //! Return the _real_ filename of a virtual file, if any.
14179b1997-01-29Per Hedbor { string loc; string s; array tmp; file=replace(file, "//", "/"); // "//" is really "/" here...
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(!id) error("No id passed to real_file"); // Map location-modules.
517c7e2000-09-30Per Hedbor  foreach(location_modules(), tmp)
14179b1997-01-29Per Hedbor  { loc = tmp[0];
10c7e11999-12-28Martin Nilsson  if(!search(file, loc))
14179b1997-01-29Per Hedbor  { #ifdef MODULE_LEVEL_SECURITY if(check_security(tmp[1], id)) continue; #endif
c5e0961999-10-04Per Hedbor  if(s=function_object(tmp[1])->real_file(file[strlen(loc)..], id))
14179b1997-01-29Per Hedbor  return s; } } }
10c7e11999-12-28Martin Nilsson int|string try_get_file(string s, RequestID id,
646f722000-03-07Martin Stjernholm  int|void status, int|void nocache,
bbd61c2002-06-18Martin Nilsson  int|void not_internal, mapping|void result_mapping)
2688e22000-07-26Johan Sundström //! Convenience function used in quite a lot of modules. Tries to read //! a file into memory, and then returns the resulting string. //! //! NOTE: A 'file' can be a cgi script, which will be executed, //! resulting in a horrible delay. //! //! Unless the not_internal flag is set, this tries to get an external //! or internal file. Here "internal" means a file that never should be //! sent directly as a request response. E.g. an internal redirect to a //! different file is still considered "external" since its contents is //! sent directly to the client. Internal requests are recognized by //! the id->misc->internal_get flag being non-zero.
14179b1997-01-29Per Hedbor {
646f722000-03-07Martin Stjernholm  string res, q, cache_key;
e351dd1999-11-29Per Hedbor  RequestID fake_id;
14179b1997-01-29Per Hedbor  mapping m;
10c7e11999-12-28Martin Nilsson  if(!objectp(id))
14179b1997-01-29Per Hedbor  error("No ID passed to 'try_get_file'\n");
9644732001-11-27Martin Stjernholm  // id->misc->common is here for compatibility; it's better to use // id->root_id->misc. if ( !id->misc ) id->misc = ([]); if ( !id->misc->common ) id->misc->common = ([]);
e351dd1999-11-29Per Hedbor  fake_id = id->clone_me();
10c7e11999-12-28Martin Nilsson 
9644732001-11-27Martin Stjernholm  fake_id->misc->common = id->misc->common;
484ec92000-06-23Martin Stjernholm  fake_id->misc->internal_get = !not_internal;
e351dd1999-11-29Per Hedbor 
4e0a532000-03-20Martin Stjernholm  if (fake_id->scan_for_query)
c65dbe2001-05-03Per Hedbor  // FIXME: If we're using e.g. ftp this doesn't exist. But the // right solution might be that clone_me() in an ftp id object // returns a vanilla (i.e. http) id instead when this function is // used.
4e0a532000-03-20Martin Stjernholm  s = fake_id->scan_for_query (s);
c65dbe2001-05-03Per Hedbor  s = Roxen.fix_relative (s, id);
14179b1997-01-29Per Hedbor  fake_id->raw_url=s; fake_id->not_query=s;
7a41502001-08-30Henrik Grubbström (Grubba)  fake_id->method = "GET";
14179b1997-01-29Per Hedbor 
c927a02000-03-18Martin Stjernholm  if(!(m = get_file(fake_id,0,!not_internal))) {
4cd5e82000-03-20Martin Stjernholm  // Might be a PATH_INFO type URL. m_delete (fake_id->misc, "path_info");
484ec92000-06-23Martin Stjernholm  array a = open_file( s, "r", fake_id, !not_internal );
e1e86d2000-03-20Martin Stjernholm  if(a && a[0]) { m = a[1]; m->file = a[0]; } else { destruct (fake_id); return 0; }
c927a02000-03-18Martin Stjernholm  }
a59fc92000-08-16Per Hedbor  CACHE( fake_id->misc->cacheable );
c927a02000-03-18Martin Stjernholm  destruct (fake_id);
889d031999-10-04Per Hedbor 
3bb38c2000-01-20Martin Bähr  if (!mappingp(m) && !objectp(m)) { report_error("try_get_file(%O, %O, %O, %O): m = %O is not a mapping.\n", s, id, status, nocache, m); return 0; }
bbd61c2002-06-18Martin Nilsson  if (result_mapping)
dfa0f92002-06-18Martin Nilsson  foreach(m; string i; mixed v) result_mapping[i] = v;
bbd61c2002-06-18Martin Nilsson 
96d86e2001-01-29Per Hedbor  // Allow 2* and 3* error codes, not only a few specific ones. if (!(< 0,2,3 >)[m->error/100]) return 0;
10c7e11999-12-28Martin Nilsson 
3510fb1997-11-09Henrik Grubbström (Grubba)  if(status) return 1;
10c7e11999-12-28Martin Nilsson  if(m->data)
a22f6f1999-05-12Per Hedbor  res = m->data;
10c7e11999-12-28Martin Nilsson  else
a22f6f1999-05-12Per Hedbor  res="";
14179b1997-01-29Per Hedbor  m->data = 0;
10c7e11999-12-28Martin Nilsson 
4cb2212000-05-22Per Hedbor  if( objectp(m->file) )
14179b1997-01-29Per Hedbor  {
3a4d7e1997-09-03Per Hedbor  res += m->file->read();
2c66592001-09-06Henrik Grubbström (Grubba)  if (m->file) { // Some wrappers may destruct themselves in read()... destruct(m->file); }
14179b1997-01-29Per Hedbor  m->file = 0; }
10c7e11999-12-28Martin Nilsson 
14179b1997-01-29Per Hedbor  if(m->raw) { res -= "\r"; if(!sscanf(res, "%*s\n\n%s", res)) sscanf(res, "%*s\n%s", res); } return res; }
7345b02001-09-13Martin Nilsson int(0..1) is_file(string virt_path, RequestID id, int(0..1)|void internal) //! Is @[virt_path] a file in our virtual filesystem? If @[internal] is //! set, internal files is "visible" as well.
14179b1997-01-29Per Hedbor {
7345b02001-09-13Martin Nilsson  if(internal) { int(0..1) was_internal = id->misc->internal_get; id->misc->internal_get = 1; int(0..1) res = !!stat_file(virt_path, id); if(!was_internal) m_delete(id->misc, "internal_get"); return res; } if(stat_file(virt_path, id) || has_suffix(virt_path, "/internal-roxen-unit")) return 1; string f = (virt_path/"/")[-1]; if( sscanf(f, "internal-roxen-%s", f) ) { if(internal_roxen_image(f, id) || has_prefix(f, "pixel-")) return 1; return 0; } if( sscanf(f, "internal-gopher-%s", f) && internal_gopher_image(f) ) return 1; return 0;
14179b1997-01-29Per Hedbor }
03aa492000-08-23Per Hedbor array registered_urls = ({}), failed_urls = ({ });
7a243b2000-08-19Per Hedbor array do_not_log_patterns = 0;
14179b1997-01-29Per Hedbor void start(int num) {
c109fc2001-07-21Martin Stjernholm  fix_my_url();
55c0522001-11-07Henrik Grubbström (Grubba) #if 0
98501d2002-07-03Martin Nilsson  report_debug("configuration:start():\n" " registered_urls: ({ %{%O, %}})\n" " failed_urls: ({ %{%O, %}})\n" " URLs: ({ %{%O, %}})\n", registered_urls, failed_urls, query("URLs"));
55c0522001-11-07Henrik Grubbström (Grubba) #endif /* 0 */
c5e0961999-10-04Per Hedbor  // Note: This is run as root if roxen is started as root
5d6c8d2000-09-01Per Hedbor  foreach( (registered_urls-query("URLs"))+failed_urls, string url ) { registered_urls -= ({ url });
9c3c6c2001-11-09Henrik Grubbström (Grubba)  roxen.unregister_url(url, this_object());
5d6c8d2000-09-01Per Hedbor  }
ecd9ab2000-08-23Per Hedbor 
03aa492000-08-23Per Hedbor  failed_urls = ({ });
ecd9ab2000-08-23Per Hedbor 
5d6c8d2000-09-01Per Hedbor  foreach( (query( "URLs" )-registered_urls), string url )
55c0522001-11-07Henrik Grubbström (Grubba)  {
ecd9ab2000-08-23Per Hedbor  if( roxen.register_url( url, this_object() ) ) registered_urls += ({ url });
03aa492000-08-23Per Hedbor  else failed_urls += ({ url });
55c0522001-11-07Henrik Grubbström (Grubba)  }
5f6dae2000-08-13Per Hedbor  if( !datacache ) datacache = DataCache( ); else datacache->init_from_variables();
7a243b2000-08-19Per Hedbor  parse_log_formats(); init_log_file(); do_not_log_patterns = query("NoLog"); if(!sizeof(do_not_log_patterns)) do_not_log_patterns = 0;
6f669a2001-08-14Honza Petrous 
b9c3872002-03-27Per Hedbor  if( query("throttle") ) { if( !throttler )
9a5c4c2002-07-03Per Hedbor  throttler=.throttler(0);
b9c3872002-03-27Per Hedbor  throttler->throttle(query("throttle_fill_rate"), query("throttle_bucket_depth"), query("throttle_min_grant"), query("throttle_max_grant")); } else if( throttler ) { // This is done to give old connections more bandwidth. throttler->throttle( 1000000000, 1000000000, // 800Mbit. 1024, 65536 ); // and new connections does not even have to care. throttler = 0; }
6f669a2001-08-14Honza Petrous #ifdef SNMP_AGENT if(query("snmp_process") && objectp(roxen->snmpagent)) roxen->snmpagent->add_virtserv(get_config_id()); #endif
14179b1997-01-29Per Hedbor }
e7e6031999-11-05Per Hedbor void save_me() { save_one( 0 ); }
14179b1997-01-29Per Hedbor void save(int|void all)
2688e22000-07-26Johan Sundström //! Save this configuration. If all is included, save all configuration //! global variables as well, otherwise only all module variables.
14179b1997-01-29Per Hedbor { if(all) {
3f628a1999-12-09Martin Stjernholm  store("spider#0", variables, 0, this_object());
14179b1997-01-29Per Hedbor  start(2); }
10c7e11999-12-28Martin Nilsson 
a2d0792002-04-15Marcus Wellhardh  store( "EnabledModules", enabled_modules, 1, this_object());
dfa0f92002-06-18Martin Nilsson  foreach(modules; string modname; ModuleCopies mc)
14179b1997-01-29Per Hedbor  {
2b7ca32002-07-03Martin Nilsson  foreach(mc->copies; int i; mixed mod)
14179b1997-01-29Per Hedbor  {
2b7ca32002-07-03Martin Nilsson  store(modname+"#"+i, mod->query(), 0, this_object()); if (mixed err = catch(mod->start(2, this_object())))
49e3bc2001-03-12Anders Johansson  report_error("Error calling start in module.\n%s", describe_backtrace (err));
14179b1997-01-29Per Hedbor  } }
8cc31b1997-10-12Henrik Grubbström (Grubba)  invalidate_cache();
14179b1997-01-29Per Hedbor }
e351dd1999-11-29Per Hedbor int save_one( RoxenModule o )
2688e22000-07-26Johan Sundström //! Save all variables in a given module.
14179b1997-01-29Per Hedbor { mapping mod;
10c7e11999-12-28Martin Nilsson  if(!o)
14179b1997-01-29Per Hedbor  {
c5e0961999-10-04Per Hedbor  store("spider#0", variables, 0, this_object());
14179b1997-01-29Per Hedbor  start(2); return 1; }
2c13a81999-11-10Per Hedbor  string q = otomod[ o ]; if( !q ) error("Invalid module");
10c7e11999-12-28Martin Nilsson 
2c13a81999-11-10Per Hedbor  store(q, o->query(), 0, this_object()); invalidate_cache();
0d1e432000-11-02Per Hedbor  mixed error; if( error = catch( o->start(2, this_object()) ) ) { if( objectp(error ) ) error = (array)error; if( sizeof(error)>1 && arrayp( error[1] ) ) { int i; for( i = 0; i<sizeof( error[1] ); i++ ) if( error[1][i][2] == save_one ) break; error[1] = error[1][i+1..]; } if( o->report_error ) o->report_error( "Call to start failed.\n"+describe_backtrace( error ) ); else report_error( "Call to start failed.\n"+describe_backtrace( error )); }
2c13a81999-11-10Per Hedbor  invalidate_cache(); return 1;
14179b1997-01-29Per Hedbor }
2f79202000-03-27Per Hedbor RoxenModule reload_module( string modname )
5964251999-11-19Per Hedbor {
e351dd1999-11-29Per Hedbor  RoxenModule old_module = find_module( modname );
9a8a152000-09-25Per Hedbor  ModuleInfo mi = roxen.find_module( (modname/"#")[0] );
ffdab52001-08-24Per Hedbor 
f7c5742001-09-03Per Hedbor  roxen->bootstrap_info->set (({this_object(), modname }));
2f79202000-03-27Per Hedbor  if( !old_module ) return 0;
f569581999-11-23Per Hedbor 
b86de82000-11-13Per Hedbor  master()->clear_compilation_failures();
1f56521999-11-23Per Hedbor 
ffdab52001-08-24Per Hedbor  if( !old_module->not_a_module )
b86de82000-11-13Per Hedbor  { save_one( old_module ); master()->refresh_inherit( object_program( old_module ) ); master()->refresh( object_program( old_module ), 1 ); }
2f79202000-03-27Per Hedbor 
2141a12001-07-12Martin Stjernholm  array old_error_log = (array) old_module->error_log;
2f79202000-03-27Per Hedbor  RoxenModule nm;
2141a12001-07-12Martin Stjernholm 
ffdab52001-08-24Per Hedbor  // Load up a new instance.
7957982001-09-06Per Hedbor  nm = mi->instance( this_object() );
ffdab52001-08-24Per Hedbor  // If this is a faked module, let's call it a failure. if( nm->not_a_module ) {
198e272002-06-13Martin Nilsson  old_module->report_error("Reload failed\n");
ffdab52001-08-24Per Hedbor  return old_module; }
bd86bd2001-09-06Per Hedbor  disable_module( modname, 1 ); destruct( old_module );
ffdab52001-08-24Per Hedbor  mi->update_with( nm,0 ); // This is sort of nessesary... enable_module( modname, nm, mi );
2141a12001-07-12Martin Stjernholm  foreach (old_error_log, [string msg, array(int) times]) nm->error_log[msg] += times;
198e272002-06-13Martin Nilsson  nm->report_notice("Reloaded " + mi->get_name() + ".\n");
2f79202000-03-27Per Hedbor  return nm;
5964251999-11-19Per Hedbor }
beba572000-03-20Martin Stjernholm #ifdef THREADS Thread.Mutex enable_modules_mutex = Thread.Mutex();
c6bf402001-09-10Martin Stjernholm #define MODULE_LOCK(TYPE) \ Thread.MutexKey enable_modules_lock = enable_modules_mutex->lock (TYPE)
beba572000-03-20Martin Stjernholm #else
c6bf402001-09-10Martin Stjernholm #define MODULE_LOCK(TYPE)
beba572000-03-20Martin Stjernholm #endif
9a1d472000-01-12Martin Stjernholm static int enable_module_batch_msgs;
2f79202000-03-27Per Hedbor RoxenModule enable_module( string modname, RoxenModule|void me,
bcf5662000-04-05Per Hedbor  ModuleInfo|void moduleinfo,
e6cd832002-04-09Marcus Wellhardh  int|void nostart, int|void nosave )
14179b1997-01-29Per Hedbor {
c6bf402001-09-10Martin Stjernholm  MODULE_LOCK (2);
c5e0961999-10-04Per Hedbor  int id;
e351dd1999-11-29Per Hedbor  ModuleCopies module;
c5e0961999-10-04Per Hedbor  int pr; mixed err; int module_type;
acff932001-08-14Per Hedbor  if( forcibly_added[modname] == 2 )
747a7c2001-08-13Per Hedbor  return search(otomod, modname);
4867e92000-09-05Per Hedbor  if( datacache ) datacache->flush();
8b16fe2000-09-05Per Hedbor 
e7e6031999-11-05Per Hedbor  if( sscanf(modname, "%s#%d", modname, id ) != 2 )
2f79202000-03-27Per Hedbor  while( modules[ modname ] && modules[ modname ][ id ] )
4f43eb1999-11-05Per Hedbor  id++;
c5e0961999-10-04Per Hedbor 
1e79252001-07-11Martin Stjernholm  roxen->bootstrap_info->set (({this_object(), modname + "#" + id}));
a42fe42001-07-05Martin Nilsson #ifdef MODULE_DEBUG
7f00081998-03-20Per Hedbor  int start_time = gethrtime();
a42fe42001-07-05Martin Nilsson #endif
25171c1999-11-06Per Hedbor 
2f79202000-03-27Per Hedbor  if( !moduleinfo )
ad683e1998-05-09Henrik Grubbström (Grubba)  {
2e8d0f2001-06-28Martin Stjernholm  moduleinfo = roxen->find_module( modname );
2f79202000-03-27Per Hedbor  if (!moduleinfo) { report_warning("Failed to load %s. The module probably " "doesn't exist in the module path.\n", modname);
8b700e2000-09-19Martin Stjernholm  got_no_delayed_load = -1;
3557f52001-06-30Martin Stjernholm  roxen->bootstrap_info->set (0);
2f79202000-03-27Per Hedbor  return 0; }
c5e0961999-10-04Per Hedbor  }
9a1d472000-01-12Martin Stjernholm  string descr = moduleinfo->get_name() + (id ? " copy " + (id + 1) : "");
835c6c2001-06-17Martin Nilsson  // sscanf(descr, "%*s: %s", descr);
9a1d472000-01-12Martin Stjernholm 
3bbda81997-06-11Henrik Grubbström (Grubba) #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug(" %-43s... \b", descr );
c5e0961999-10-04Per Hedbor  else
9a1d472000-01-12Martin Stjernholm  report_debug("Enabling " + descr + "\n");
3bbda81997-06-11Henrik Grubbström (Grubba) #endif
c5e0961999-10-04Per Hedbor 
0b7d2b1999-12-22Per Hedbor  module = modules[ modname ];
c5e0961999-10-04Per Hedbor  if(!module)
7e446c1999-11-24Per Hedbor  modules[ modname ] = module = ModuleCopies();
c5e0961999-10-04Per Hedbor 
f569581999-11-23Per Hedbor  if( !me )
c5e0961999-10-04Per Hedbor  {
f569581999-11-23Per Hedbor  if(err = catch(me = moduleinfo->instance(this_object()))) {
c45b2a1999-12-09Martin Stjernholm #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
67f60e2000-07-09Martin Nilsson  if (err != "") { #endif string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("enable_module(): Error while initiating module copy of %s%s",
434bac2000-07-14Andreas Lange  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
67f60e2000-07-09Martin Nilsson #ifdef MODULE_DEBUG }
c45b2a1999-12-09Martin Stjernholm #endif
f63aca2000-09-08Martin Stjernholm  got_no_delayed_load = -1;
3557f52001-06-30Martin Stjernholm  roxen->bootstrap_info->set (0);
0b7d2b1999-12-22Per Hedbor  return module[id];
f569581999-11-23Per Hedbor  }
c5e0961999-10-04Per Hedbor  }
0b7d2b1999-12-22Per Hedbor  if(module[id] && module[id] != me)
c5e0961999-10-04Per Hedbor  {
0e1f262002-01-29Martin Stjernholm  if( module[id]->stop ) { if (err = catch( module[id]->stop() )) { string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("disable_module(): Error while disabling module %s%s",
0e1f262002-01-29Martin Stjernholm  descr, (bt ? ":\n"+bt : "\n")); } }
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|
4770952002-06-06Martin Nilsson  MODULE_FILTER|MODULE_TAG|MODULE_FIRST|MODULE_USERDB))
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 {
198e272002-06-13Martin Nilsson  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"),
4770421999-11-22Henrik Grubbström (Grubba)  ({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); }) {
3557f52001-06-30Martin Stjernholm  roxen->bootstrap_info->set (0);
4770421999-11-22Henrik Grubbström (Grubba)  throw(err); }
3b17831998-11-22Per Hedbor  }
10c7e11999-12-28Martin Nilsson 
21306c2000-11-02Per Hedbor #ifdef MODULE_LEVEL_SECURITY
4770952002-06-06Martin Nilsson  if( (module_type & ~(MODULE_LOGGER|MODULE_PROVIDER|MODULE_USERDB)) != 0 )
ad683e1998-05-09Henrik Grubbström (Grubba)  {
198e272002-06-13Martin Nilsson // me->defvar("_sec_group", "user", "Security: Realm",
bc0fa02001-03-08Per Hedbor // TYPE_STRING,
198e272002-06-13Martin Nilsson // ("The realm to use when requesting password from the " // "client. Usually used as an informative message to the " // "user."));
23414a2000-07-21Andreas Lange 
198e272002-06-13Martin Nilsson  me->defvar("_seclevels", "", "Security: Patterns",
23414a2000-07-21Andreas Lange  TYPE_TEXT_FIELD,
198e272002-06-13Martin Nilsson  #"The syntax is: <dl> <dt><b>userdb</b> <i>userdatabase module</i></dt> <dd> Select a non-default userdatabase module. The default is to
b765aa2002-06-20Martin Nilsson  search all modules. The userdatabase module admin_userdb is always present, and contains the administration interface users</dd>
198e272002-06-13Martin Nilsson  <dt><b>authmethod</b> <i>authentication module</i></dt> <dd>Select a non-default authentication method.</dd> <dt><b>realm</b> <i>realm name</i></dt> <dd>The realm is used when user authentication info is requested</dd> </dl> Below, CMD is one of 'allow' and 'deny' <dl> <dt>CMD <b>ip</b>=<i>ip/bits</i> [return]<br /> CMD <b>ip</b>=<i>ip:mask</i> [return] <br /> CMD <b>ip</b>=<i>pattern[,pattern,...]</i> [return] <br /></dt> <dd>Match the remote IP-address.</dd> <dt>CMD <b>user</b>=<i>name[,name,...]</i> [return]</dt> <dd>Requires a authenticated user. If the user name 'any' is used, any valid user will be OK. Otherwise, one of the listed users are required. </dd> <dt>CMD <b>group</b>=<i>name[,name,...]</i> [return]</dt> <dd>Requires a authenticated user with a group. If the group name 'any' is used, any valid group will be OK. Otherwise, one of the listed groups are required.</dd> <dt>CMD <b>dns</b>=<i>pattern[,pattern,...]</i> [return]</dt> <dd>Require one of the specified DNS domain-names</dd> <dt>CMD <b>time</b>=<i>HH:mm-HH:mm</i> [return]</dt> <dd>Only allow access to the module from the first time to the second each day. Both times should be specified in 24-hour HH:mm format.</dd> <dt>CMD <b>day</b>=<i>day[,day,...]</i> [return]</dt> <dd>Only allow access during certain days. Day is either a numerical value (monday=1, sunday=7) or a string (monday, thuesday etc)</dd> </dl> <p>pattern is always a glob pattern (* = any characters, ? = any character).</p> <p>return means that reaching this command results in immediate return, only useful for 'allow'.</p> <p>'deny' always implies a return, no futher testing is done if a 'deny' match.</p> ");
23414a2000-07-21Andreas Lange 
c5e0961999-10-04Per Hedbor  if(!(module_type & MODULE_PROXY))
14179b1997-01-29Per Hedbor  {
198e272002-06-13Martin Nilsson  me->defvar("_seclvl", 0, "Security: Security level",
23414a2000-07-21Andreas Lange  TYPE_INT,
198e272002-06-13Martin Nilsson  #"The modules security level is used to determine if a request should be handled by the module. <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>.</p> <p><h2>Definitions</h2><ul> <li>A requests initial Trust level is infinitely high.</li> <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> <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>, <i>unless</i> the security level of the module is 0, which is a special case and means that no change should be made.</li> </ul></p> <p><h2>Example</h2> Modules:<ul> <li> User filesystem, <i>security level</i> 1</li> <li> Filesystem module, <i>security level</i> 3</li> <li> CGI module, <i>security level</i> 2</li> </ul></p> <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.</p> <p>On the other hand, a request handled by the the \"Filsystem module\" could later be handled by the \"CGI module\".</p>");
f498ed2000-07-11Martin Nilsson 
14179b1997-01-29Per Hedbor  }
198e272002-06-13Martin Nilsson  else me->definvisvar("_seclvl", -10, TYPE_INT); // A very low one
3bbda81997-06-11Henrik Grubbström (Grubba)  }
21306c2000-11-02Per Hedbor #endif
ad683e1998-05-09Henrik Grubbström (Grubba)  }
198e272002-06-13Martin Nilsson  else me->defvar("_priority", 0, "", TYPE_INT, "", 0, 1);
14179b1997-01-29Per Hedbor 
a0fbcc2000-04-05Martin Stjernholm  mapping(string:mixed) stored_vars = retrieve(modname + "#" + id, this_object()); int has_stored_vars = sizeof (stored_vars); // A little ugly, but it suffices. me->setvars(stored_vars);
33e6351998-02-28Martin Stjernholm 
0b7d2b1999-12-22Per Hedbor  module[ id ] = me;
37c1b31999-10-12Per Hedbor  otomod[ me ] = modname+"#"+id;
10c7e11999-12-28Martin Nilsson 
bcf5662000-04-05Per Hedbor  if(!nostart) call_start_callbacks( me, moduleinfo, module ); #ifdef MODULE_DEBUG
be87a72002-04-17Marcus Wellhardh  if (enable_module_batch_msgs) { if(moduleinfo->config_locked[this_object()]) report_debug("\bLocked %6.1fms\n", (gethrtime()-start_time)/1000.0); else report_debug("\bOK %6.1fms\n", (gethrtime()-start_time)/1000.0); } #else if(moduleinfo->config_locked[this_object()]) report_error(" Error: \"%s\" not loaded (license restriction).\n", moduleinfo->get_name());
bcf5662000-04-05Per Hedbor #endif
fd24e22000-08-28Per Hedbor  if( !enabled_modules[modname+"#"+id] ) { enabled_modules[modname+"#"+id] = 1;
e6cd832002-04-09Marcus Wellhardh  if(!nosave) store( "EnabledModules", enabled_modules, 1, this_object());
fd24e22000-08-28Per Hedbor  }
6f595f2000-08-20Per Hedbor 
e6cd832002-04-09Marcus Wellhardh  if (!has_stored_vars && !nosave)
bcf5662000-04-05Per Hedbor  store (modname + "#" + id, me->query(), 0, this_object());
f63aca2000-09-08Martin Stjernholm  if( me->no_delayed_load && got_no_delayed_load >= 0 ) got_no_delayed_load = 1;
a8ba692000-08-29Marcus Wellhardh 
3557f52001-06-30Martin Stjernholm  roxen->bootstrap_info->set (0);
bcf5662000-04-05Per Hedbor  return me; } void call_start_callbacks( RoxenModule me, ModuleInfo moduleinfo, ModuleCopies module ) {
40f0642000-09-13Per Hedbor  if(!me) return; if(!moduleinfo) return; if(!module) return;
a8ba692000-08-29Marcus Wellhardh  call_low_start_callbacks( me, moduleinfo, module );
ad683e1998-05-09Henrik Grubbström (Grubba)  mixed err;
c5e0961999-10-04Per Hedbor  if((me->start) && (err = catch( me->start(0, this_object()) ) ) ) { #ifdef MODULE_DEBUG
bcf5662000-04-05Per Hedbor  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c5e0961999-10-04Per Hedbor #endif
67f60e2000-07-09Martin Nilsson  string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("Error while initiating module copy of %s%s", moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
f63aca2000-09-08Martin Stjernholm  got_no_delayed_load = -1;
ad683e1998-05-09Henrik Grubbström (Grubba)  }
5ffa542000-02-16Per Hedbor  if( inited && me->ready_to_receive_requests )
bcf5662000-04-05Per Hedbor  if( mixed q = catch( me->ready_to_receive_requests( this_object() ) ) ) {
c2fdff2000-03-21Martin Stjernholm #ifdef MODULE_DEBUG if (enable_module_batch_msgs) report_debug("\bERROR\n"); #endif report_error( "While calling ready_to_receive_requests:\n"+ describe_backtrace( q ) );
f63aca2000-09-08Martin Stjernholm  got_no_delayed_load = -1;
c2fdff2000-03-21Martin Stjernholm  }
a8ba692000-08-29Marcus Wellhardh } void call_low_start_callbacks( RoxenModule me, ModuleInfo moduleinfo, ModuleCopies module ) {
40f0642000-09-13Per Hedbor  if(!me) return; if(!moduleinfo) return; if(!module) return;
a8ba692000-08-29Marcus Wellhardh  int module_type = moduleinfo->type, pr; mixed err;
10c7e11999-12-28Martin Nilsson  if (err = catch(pr = me->query("_priority")))
c5e0961999-10-04Per Hedbor  {
c45b2a1999-12-09Martin Stjernholm #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c45b2a1999-12-09Martin Stjernholm #endif
67f60e2000-07-09Martin Nilsson  string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("Error while initiating module copy of %s%s", moduleinfo->get_name(), (bt ? ":\n"+bt : "\n"));
ad683e1998-05-09Henrik Grubbström (Grubba)  pr = 3; } api_module_cache |= me->api_functions();
10c7e11999-12-28Martin Nilsson  if(module_type & MODULE_EXTENSION)
c5e0961999-10-04Per Hedbor  {
434bac2000-07-14Andreas Lange  report_error("%s is an MODULE_EXTENSION, that type is no " "longer available.\nPlease notify the modules writer.\n" "Suitable replacement types include MODULE_FIRST and " " MODULE_LAST.\n", moduleinfo->get_name());
c5e0961999-10-04Per Hedbor  }
ad683e1998-05-09Henrik Grubbström (Grubba) 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_FILE_EXTENSION)
ad683e1998-05-09Henrik Grubbström (Grubba)  if (err = catch { array arr = me->query_file_extensions();
10c7e11999-12-28Martin Nilsson  if (arrayp(arr))
c5e0961999-10-04Per Hedbor  {
ad683e1998-05-09Henrik Grubbström (Grubba)  string foo; foreach( me->query_file_extensions(), foo )
0ba0382001-08-28Henrik Grubbström (Grubba)  if(pri[pr]->file_extension_modules[foo = lower_case(foo)] ) pri[pr]->file_extension_modules[foo] += ({me});
ad683e1998-05-09Henrik Grubbström (Grubba)  else
0ba0382001-08-28Henrik Grubbström (Grubba)  pri[pr]->file_extension_modules[foo] = ({me});
ad683e1998-05-09Henrik Grubbström (Grubba)  }
c45b2a1999-12-09Martin Stjernholm  }) { #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c45b2a1999-12-09Martin Stjernholm #endif
f63aca2000-09-08Martin Stjernholm  string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("Error while initiating module copy of %s%s",
f63aca2000-09-08Martin Stjernholm  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n")); got_no_delayed_load = -1;
c45b2a1999-12-09Martin Stjernholm  }
14179b1997-01-29Per Hedbor 
10c7e11999-12-28Martin Nilsson  if(module_type & MODULE_PROVIDER) if (err = catch
c5e0961999-10-04Per Hedbor  {
747a7c2001-08-13Per Hedbor  mixed provs = me->query_provides ? me->query_provides() : ({});
ad683e1998-05-09Henrik Grubbström (Grubba)  if(stringp(provs)) provs = (< provs >); if(arrayp(provs)) provs = mkmultiset(provs); if (multisetp(provs)) { pri[pr]->provider_modules [ me ] = provs;
3bbda81997-06-11Henrik Grubbström (Grubba)  }
c45b2a1999-12-09Martin Stjernholm  }) { #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\bERROR\n");
c45b2a1999-12-09Martin Stjernholm #endif
f63aca2000-09-08Martin Stjernholm  string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("Error while initiating module copy of %s%s",
f63aca2000-09-08Martin Stjernholm  moduleinfo->get_name(), (bt ? ":\n"+bt : "\n")); got_no_delayed_load = -1;
c45b2a1999-12-09Martin Stjernholm  }
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_TYPES)
ad683e1998-05-09Henrik Grubbström (Grubba)  { types_module = me; types_fun = me->type_from_extension; }
10c7e11999-12-28Martin Nilsson 
f590762000-09-10Martin Nilsson  if(module_type & MODULE_TAG)
c5e0961999-10-04Per Hedbor  add_parse_module( me );
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_DIRECTORIES)
aaf3912000-09-19Jonas Wallden  if (me->parse_directory) dir_module = me;
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_LOCATION)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->location_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_LOGGER)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->logger_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_URL)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->url_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_LAST)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->last_modules += ({ me });
14179b1997-01-29Per Hedbor 
c5e0961999-10-04Per Hedbor  if(module_type & MODULE_FILTER)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->filter_modules += ({ me });
14179b1997-01-29Per Hedbor 
10c7e11999-12-28Martin Nilsson  if(module_type & MODULE_FIRST)
ad683e1998-05-09Henrik Grubbström (Grubba)  pri[pr]->first_modules += ({ me });
14179b1997-01-29Per Hedbor 
ad683e1998-05-09Henrik Grubbström (Grubba)  invalidate_cache();
14179b1997-01-29Per Hedbor }
a6ef1f2000-03-28Johan Sundström // Called from the administration interface.
199d031999-09-05Francesco Chemolli string check_variable(string name, mixed value)
14179b1997-01-29Per Hedbor { switch(name) {
cffbaa2000-04-11Per Hedbor // case "MyWorldLocation": // if(strlen(value)<7 || value[-1] != '/' || // !(sscanf(value,"%*s://%*s/")==2)) // return LOCALE->url_format(); // return 0;
c109fc2001-07-21Martin Stjernholm  case "MyWorldLocation": case "URLs": fix_my_url(); return 0;
b9c3872002-03-27Per Hedbor // case "throttle": // // There was code here to sett the throttling. That's not a // // good idea. Moved to start. The code now also avoids // // creating new throttle objects each time a value is changed. // case "throttle_fill_rate": // case "throttle_bucket_depth": // case "throttle_min_grant": // case "throttle_max_grant": // return 0;
e427912001-06-30Honza Petrous #ifdef SNMP_AGENT case "snmp_process": if (objectp(roxen->snmpagent)) { int cid = get_config_id(); value ? roxen->snmpagent->add_virtserv(cid) : roxen->snmpagent->del_virtserv(cid); } return 0; #endif
14179b1997-01-29Per Hedbor  } }
2f4ac12000-11-02Per Hedbor void module_changed( ModuleInfo moduleinfo, RoxenModule me )
14179b1997-01-29Per Hedbor {
2f4ac12000-11-02Per Hedbor  clean_up_for_module( moduleinfo, me ); call_low_start_callbacks( me, moduleinfo, modules[ moduleinfo->sname ] ); }
14179b1997-01-29Per Hedbor 
2f4ac12000-11-02Per Hedbor void clean_up_for_module( ModuleInfo moduleinfo, RoxenModule me ) { int pr;
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++)
dfa0f92002-06-18Martin Nilsson  foreach( values (pri[pr]->file_extension_modules), array mods ) mods -= ({me});
14179b1997-01-29Per Hedbor  }
c5e0961999-10-04Per Hedbor  if(moduleinfo->type & MODULE_PROVIDER) {
ae32d01998-03-23David Hedbor  for(pr=0; pr<10; pr++) m_delete(pri[pr]->provider_modules, me); }
10c7e11999-12-28Martin Nilsson 
c5e0961999-10-04Per Hedbor  if(moduleinfo->type & MODULE_TYPES)
14179b1997-01-29Per Hedbor  { types_module = 0; types_fun = 0; }
f590762000-09-10Martin Nilsson  if(moduleinfo->type & MODULE_TAG)
b796b51998-11-18Per Hedbor  remove_parse_module( me );
14179b1997-01-29Per Hedbor 
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 });
2f4ac12000-11-02Per Hedbor } int disable_module( string modname, int|void nodest ) {
c6bf402001-09-10Martin Stjernholm  MODULE_LOCK (2);
2f4ac12000-11-02Per Hedbor  RoxenModule me; int id, pr; sscanf(modname, "%s#%d", modname, id ); if( datacache ) datacache->flush(); ModuleInfo moduleinfo = roxen.find_module( modname ); mapping module = modules[ modname ]; string descr = moduleinfo->get_name() + (id ? " copy " + (id + 1) : ""); if(!module) {
e40eb52002-06-13Martin Nilsson  report_error("disable_module(): Failed to disable module:\n" "No module by that name: %O.\n", modname);
2f4ac12000-11-02Per Hedbor  return 0; } me = module[id]; m_delete(module->copies, id); if(!sizeof(module->copies)) m_delete( modules, modname ); invalidate_cache(); if(!me) {
e40eb52002-06-13Martin Nilsson  report_error("disable_module(): Failed to disable module %O.\n", descr);
2f4ac12000-11-02Per Hedbor  return 0; } if(me->stop) if (mixed err = catch (me->stop())) { string bt=describe_backtrace(err);
e40eb52002-06-13Martin Nilsson  report_error("disable_module(): Error while disabling module %s%s",
2f4ac12000-11-02Per Hedbor  descr, (bt ? ":\n"+bt : "\n")); } #ifdef MODULE_DEBUG report_debug("Disabling "+descr+"\n"); #endif
14179b1997-01-29Per Hedbor 
2f4ac12000-11-02Per Hedbor  clean_up_for_module( moduleinfo, me );
14179b1997-01-29Per Hedbor 
5fbaec2001-04-11Per Hedbor  if( !nodest ) {
a42fe42001-07-05Martin Nilsson  m_delete( enabled_modules, modname + "#" + id );
acff932001-08-14Per Hedbor  m_delete( forcibly_added, modname + "#" + id );
5fbaec2001-04-11Per Hedbor  store( "EnabledModules",enabled_modules, 1, this_object());
2f79202000-03-27Per Hedbor  destruct(me);
5fbaec2001-04-11Per Hedbor  }
14179b1997-01-29Per Hedbor  return 1; }
9a8a152000-09-25Per Hedbor RoxenModule find_module(string name)
9fd8092000-08-08Johan Sundström //! Return the module corresponding to the name (eg "rxmlparse", //! "rxmlparse#0" or "filesystem#1") or zero, if there was no such
d5c8642001-08-23Martin Stjernholm //! module. The string is on the same format as the one returned by //! @[RoxenModule.module_local_id].
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; }
acff932001-08-14Per Hedbor mapping forcibly_added = ([]);
f5a2741999-10-18Per Hedbor int add_modules( array(string) mods, int|void now )
14179b1997-01-29Per Hedbor {
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  int wr;
ba18d71999-11-27Per Hedbor #endif
c5e0961999-10-04Per Hedbor  foreach (mods, string mod)
8f061b1999-11-19Per Hedbor  { sscanf( mod, "%s#", mod );
10c7e11999-12-28Martin Nilsson  if( ((now && !modules[ mod ]) ||
0ce25d1999-11-15Per Hedbor  !enabled_modules[ mod+"#0" ] ) && !forcibly_added[ mod+"#0" ])
14179b1997-01-29Per Hedbor  {
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
c5e0961999-10-04Per Hedbor  if( !wr++ )
9a1d472000-01-12Martin Stjernholm  if (enable_module_batch_msgs) report_debug("\b[ adding req module" + (sizeof (mods) > 1 ? "s" : "") + "\n"); else report_debug("Adding required module" + (sizeof (mods) > 1 ? "s" : "") + "\n");
14179b1997-01-29Per Hedbor #endif
747a7c2001-08-13Per Hedbor  forcibly_added[ mod+"#0" ] = 1;
acff932001-08-14Per Hedbor  enable_module( mod+"#0" ); forcibly_added[ mod+"#0" ] = 2;
14179b1997-01-29Per Hedbor  }
8f061b1999-11-19Per Hedbor  }
ba18d71999-11-27Per Hedbor #ifdef MODULE_DEBUG
9a1d472000-01-12Martin Stjernholm  if( wr && enable_module_batch_msgs )
ed8d261999-12-30Martin Stjernholm  report_debug("] \b");
c79b261998-02-05Johan Schön #endif
14179b1997-01-29Per Hedbor }
850c282001-01-10Per Hedbor #if ROXEN_COMPAT < 2.2
279a0c1997-11-26Henrik Grubbström (Grubba) // BEGIN SQL
14179b1997-01-29Per Hedbor 
279a0c1997-11-26Henrik Grubbström (Grubba) mapping(string:string) sql_urls = ([]);
3f059e2001-06-24Per Hedbor constant sql_cache_get = DBManager.sql_cache_get;
ed93131998-07-09Johan Schön 
850c282001-01-10Per 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
850c282001-01-10Per Hedbor #endif
14179b1997-01-29Per Hedbor 
c109fc2001-07-21Martin Stjernholm static string my_url; void fix_my_url()
14179b1997-01-29Per Hedbor {
c109fc2001-07-21Martin Stjernholm  my_url = query ("MyWorldLocation");
f418572001-07-21Martin Stjernholm  if (!sizeof (my_url) && !(my_url = Roxen.get_world (query ("URLs"))))
3ec7cf2001-07-21Martin Stjernholm  // Probably no port configured. The empty string is used as a // flag; there shouldn't be any bad fallback here. my_url = ""; else if (!has_suffix (my_url, "/")) my_url += "/";
14179b1997-01-29Per Hedbor }
6b67fe2001-08-24Martin Nilsson //! Returns some URL for accessing the configuration. (Should be //! used instead of querying MyWorldLocation directly.)
c109fc2001-07-21Martin Stjernholm string get_url() {return my_url;}
5ffa542000-02-16Per Hedbor array after_init_hooks = ({}); mixed add_init_hook( mixed what ) { if( inited ) call_out( what, 0, this_object() ); else after_init_hooks |= ({ what }); }
d53f0b2000-09-09Martin Stjernholm static int got_no_delayed_load = 0;
c6bf402001-09-10Martin Stjernholm // 0 -> enable delayed loading, 1 -> disable delayed loading,
f63aca2000-09-08Martin Stjernholm // -1 -> don't change.
d53f0b2000-09-09Martin Stjernholm void fix_no_delayed_load_flag()
14179b1997-01-29Per Hedbor {
d53f0b2000-09-09Martin Stjernholm  if( got_no_delayed_load >= 0 && query ("no_delayed_load") != got_no_delayed_load ) {
f63aca2000-09-08Martin Stjernholm  set( "no_delayed_load", got_no_delayed_load );
c45e3f2000-02-16Per Hedbor  save_one( 0 );
f63aca2000-09-08Martin Stjernholm  }
5ffa542000-02-16Per Hedbor }
d53f0b2000-09-09Martin Stjernholm void enable_all_modules() {
c6bf402001-09-10Martin Stjernholm  MODULE_LOCK (0);
d53f0b2000-09-09Martin Stjernholm  low_init( ); fix_no_delayed_load_flag(); } void low_init(void|int modules_already_enabled)
5ffa542000-02-16Per Hedbor { if( inited ) return; // already done
8516a71999-12-22Per Hedbor 
24c06c2000-02-16Per Hedbor  int start_time = gethrtime();
d53f0b2000-09-09Martin Stjernholm  if (!modules_already_enabled) report_debug("\nEnabling all modules for "+query_name()+"... \n");
24c06c2000-02-16Per Hedbor 
f7c5742001-09-03Per Hedbor  if (!modules_already_enabled) {
d53f0b2000-09-09Martin Stjernholm  enabled_modules = retrieve("EnabledModules", this_object());
747a7c2001-08-13Per Hedbor // roxenloader.LowErrorContainer ec = roxenloader.LowErrorContainer(); // roxenloader.push_compile_error_handler( ec );
d53f0b2000-09-09Martin Stjernholm  array modules_to_process = indices( enabled_modules ); string tmp_string;
0e1f262002-01-29Martin Stjernholm  mixed err;
acff932001-08-14Per Hedbor  forcibly_added = ([]);
d53f0b2000-09-09Martin Stjernholm  enable_module_batch_msgs = 1; foreach( modules_to_process, tmp_string ) { if( !forcibly_added[ tmp_string ] )
747a7c2001-08-13Per Hedbor  if(err = catch( enable_module( tmp_string ))) {
e40eb52002-06-13Martin Nilsson  report_error("Failed to enable the module %s. Skipping.\n%s\n", tmp_string, describe_backtrace(err));
d53f0b2000-09-09Martin Stjernholm  got_no_delayed_load = -1; } } enable_module_batch_msgs = 0; roxenloader.pop_compile_error_handler();
acff932001-08-14Per Hedbor  forcibly_added = ([]);
f5a2741999-10-18Per Hedbor  }
17d6d12000-03-30Per Hedbor 
3e3bab2001-01-19Per Hedbor  foreach( ({this_object()})+indices( otomod ), RoxenModule mod )
5ffa542000-02-16Per Hedbor  if( mod->ready_to_receive_requests )
f63aca2000-09-08Martin Stjernholm  if( mixed q = catch( mod->ready_to_receive_requests( this_object() ) ) ) {
c2fdff2000-03-21Martin Stjernholm  report_error( "While calling ready_to_receive_requests in "+
5ffa542000-02-16Per Hedbor  otomod[mod]+":\n"+ describe_backtrace( q ) );
f63aca2000-09-08Martin Stjernholm  got_no_delayed_load = -1; }
5ffa542000-02-16Per Hedbor  foreach( after_init_hooks, function q )
f63aca2000-09-08Martin Stjernholm  if( mixed w = catch( q(this_object()) ) ) {
c2fdff2000-03-21Martin Stjernholm  report_error( "While calling after_init_hook %O:\n%s",
5ffa542000-02-16Per Hedbor  q, describe_backtrace( w ) );
f63aca2000-09-08Martin Stjernholm  got_no_delayed_load = -1; }
5ffa542000-02-16Per Hedbor  after_init_hooks = ({}); inited = 1;
d53f0b2000-09-09Martin Stjernholm  if (!modules_already_enabled)
ac6bcd2002-06-13Martin Nilsson  report_notice("All modules for %s enabled in %3.1f seconds\n\n", query_name(), (gethrtime()-start_time)/1000000.0);
14cf2b2001-07-18Honza Petrous  #ifdef SNMP_AGENT
79b7c32001-09-13Honza Petrous  // Start trap after real virt.serv. loading if(query("snmp_process") && objectp(roxen->snmpagent)) roxen->snmpagent->vs_start_trap(get_config_id());
14cf2b2001-07-18Honza Petrous #endif
0f28da1997-08-13Per Hedbor }
5f6dae2000-08-13Per Hedbor DataCache datacache;
3557f52001-06-30Martin Stjernholm static void create()
0f28da1997-08-13Per Hedbor {
3557f52001-06-30Martin Stjernholm  if (!name) error ("Configuration name not set through bootstrap_info.\n");
8514832000-11-27Per Hedbor // int st = gethrtime();
198e272002-06-13Martin Nilsson  roxen.add_permission( "Site:"+name, "Site: "+name );
62e1bb2000-11-08Per Hedbor 
b0a9ea2001-04-18Martin Stjernholm  // for now only these two. In the future there might be more variables.
198e272002-06-13Martin Nilsson  defvar( "data_cache_size", 16384, "Cache:Cache size",
e4e6d32000-11-02Per Hedbor  TYPE_INT| VAR_PUBLIC,
198e272002-06-13Martin Nilsson  ("The size of the data cache used to speed up requests " "for commonly requested files, in KBytes"));
5f6dae2000-08-13Per Hedbor 
198e272002-06-13Martin Nilsson  defvar( "data_cache_file_max_size", 100, "Cache:Max file size",
e4e6d32000-11-02Per Hedbor  TYPE_INT | VAR_PUBLIC,
198e272002-06-13Martin Nilsson  "The maximum size of a file that is to be considered for the cache");
5f6dae2000-08-13Per Hedbor 
198e272002-06-13Martin Nilsson  defvar("default_server", 0, "Default site",
e4e6d32000-11-02Per Hedbor  TYPE_FLAG| VAR_PUBLIC,
198e272002-06-13Martin Nilsson  ("If true, this site will be selected in preference of " "other sites when virtual hosting is used and no host " "header is supplied, or the supplied host header does not " "match the address of any of the other servers.") );
40e24c2000-05-27Per Hedbor 
198e272002-06-13Martin Nilsson  defvar("comment", "", "Site comment",
9b9f701997-08-12Per Hedbor  TYPE_TEXT_FIELD|VAR_MORE,
198e272002-06-13Martin Nilsson  ("This text will be visible in the administration " "interface, it can be quite useful to use as a memory helper."));
b796b51998-11-18Per Hedbor 
198e272002-06-13Martin Nilsson  defvar("name", "", "Site name",
b98c022001-07-31Per Hedbor  TYPE_STRING|VAR_MORE| VAR_PUBLIC|VAR_NO_DEFAULT,
198e272002-06-13Martin Nilsson  ("This is the name that will be used in the administration " "interface. If this is left empty, the actual name of the " "site will be used."));
10c7e11999-12-28Martin Nilsson 
b0a9ea2001-04-18Martin Stjernholm  defvar("compat_level", Variable.StringChoice (
b98c022001-07-31Per Hedbor  "", roxen.compat_levels, VAR_NO_DEFAULT,
198e272002-06-13Martin Nilsson  "Compatibility level", ("<p>The compatibility level is used by different modules to select " "the right behavior to remain compatible with earlier Roxen " "versions. When a server configuration is created, this variable " "is set to the latest version. After that it's never changed " "automatically, thereby ensuring that server configurations " "migrated from earlier Roxen versions is kept at the right " "compatibility level.\n" "</p><p>\n" "This variable may be changed manually, but it's advisable to " "test the site carefully afterwards. A reload of the whole " "server configuration is required to propagate the change properly " "to all modules.</p>")));
b0a9ea2001-04-18Martin Stjernholm  set ("compat_level", roxen.__roxen_version__);
7848ae2001-06-15Martin Stjernholm  // Note to developers: This setting can be accessed through // id->conf->query("compat_level") or similar, but observe that that // call is not entirely cheap. It's therefore advisable to put it in // a local variable if the compatibility level is to be tested // frequently. It's perfectly all right to do that in e.g. the // module start function, since the documentation explicitly states // that a reload of all modules is necessary to propagate a change // the setting.
b0a9ea2001-04-18Martin Stjernholm 
198e272002-06-13Martin Nilsson  defvar("Log", 1, "Logging: Enabled", TYPE_FLAG, "Log requests");
5467e92001-10-05Per Hedbor 
10c7e11999-12-28Martin Nilsson  defvar("LogFormat",
f498ed2000-07-11Martin Nilsson  "404: $host $referer - [$cern_date] \"$method $resource $protocol\" 404 -\n" "500: $host $referer ERROR [$cern_date] \"$method $resource $protocol\" 500 -\n" "*: $host - - [$cern_date] \"$method $resource $protocol\" $response $length",
198e272002-06-13Martin Nilsson  "Logging: Format",
9b9f701997-08-12Per Hedbor  TYPE_TEXT_FIELD|VAR_MORE,
198e272002-06-13Martin Nilsson  #"What format to use for logging. The syntax is:
46d4cb2001-08-22Martin Stjernholm <pre>response-code or *: Log format for that response code Log format is normal characters, or one or more of the variables below:
0e20f32002-05-29Anders Johansson \\n \\t \\r -- As in C, newline, tab and linefeed $char(int) -- Insert the (1 byte) character specified by the integer. $wchar(int) -- Insert the (2 byte) word specified by the integer. $int(int) -- Insert the (4 byte) word specified by the integer. $^ -- Supress newline at the end of the logentry $host -- The remote host name, or ip number. $vhost -- The Host request-header sent by the client, or - if none $ip_number -- The remote ip number. $bin-ip_number -- The remote host id as a binary integer number. $cern_date -- Cern Common Log file format date. $bin-date -- Time, but as an 32 bit integer in network byteorder $method -- Request method $resource -- Resource identifier $full_resource -- Full requested resource, including any query fields $protocol -- The protocol used (normally HTTP/1.0) $response -- The response code sent $bin-response -- The response code sent as a binary short number $length -- The length of the data section of the reply $bin-length -- Same, but as an 32 bit integer in network byteorder $request-time -- The time the request took (seconds) $referer -- The header 'referer' from the request, or '-'. $user_agent -- The header 'User-Agent' from the request, or '-'.
f9ce962002-05-29Anders Johansson $user_agent_raw -- Same, but spaces in the name are not encoded to %20.
0e20f32002-05-29Anders Johansson $user -- the name of the auth user used, if any $user_id -- A unique user ID, if cookies are supported, by the client, otherwise '0' $cache-status -- A comma separated list of words (containing no whitespace) that describes which cache(s) the page was delivered from: protcache -- The low-level cache in the HTTP protocol module. xsltcache -- The XSLT cache. pcoderam -- RXML parse tree RAM cache. pcodedisk -- RXML parse tree persistent cache. cachetag -- No RXML &lt;cache&gt; tag misses. nocache -- No hit in any known cache.
198e272002-06-13Martin Nilsson </pre>", 0, lambda(){ return !query("Log");});
b796b51998-11-18Per Hedbor 
f498ed2000-07-11Martin Nilsson  // FIXME: Mention it is relative to getcwd(). Can not be localized in pike 7.0. defvar("LogFile", "$LOGDIR/"+Roxen.short_name(name)+"/Log",
198e272002-06-13Martin Nilsson  "Logging: Log file", TYPE_FILE, "The log file. "
f7d9811997-09-12Per Hedbor  ""
f498ed2000-07-11Martin Nilsson  "A file name. Some substitutions will be done:"
f7d9811997-09-12Per Hedbor  "<pre>"
b796b51998-11-18Per Hedbor  "%y Year (e.g. '1997')\n" "%m Month (e.g. '08')\n" "%d Date (e.g. '10' for the tenth)\n"
3bb38c2000-01-20Martin Bähr  "%h Hour (e.g. '00')\n" "%H Hostname\n"
198e272002-06-13Martin Nilsson  "</pre>"
c5e0961999-10-04Per Hedbor  ,0, lambda(){ return !query("Log");});
10c7e11999-12-28Martin Nilsson  defvar("NoLog", ({ }),
198e272002-06-13Martin Nilsson  "Logging: No Logging for", TYPE_STRING_LIST|VAR_MORE, ("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 log."),
434bac2000-07-14Andreas Lange  0, lambda(){ return !query("Log");});
a8f1b32000-01-31Per Hedbor 
198e272002-06-13Martin Nilsson  defvar("Domain", roxen.get_domain(), "Domain",
b98c022001-07-31Per Hedbor  TYPE_STRING|VAR_PUBLIC|VAR_NO_DEFAULT,
198e272002-06-13Martin Nilsson  ("The domain name of the server. The domain name is used " "to generate default URLs, and to generate email addresses."));
14179b1997-01-29Per Hedbor 
f418572001-07-21Martin Stjernholm  defvar("MyWorldLocation", "",
198e272002-06-13Martin Nilsson  "Ports: Primary Server URL", TYPE_URL|VAR_PUBLIC, #"\ <p>This is the main server URL, where your start page is located. This
f418572001-07-21Martin Stjernholm setting is for instance used as fallback to generate absolute URLs to the server, but in most circumstances the URLs sent by the clients are used. A URL is deduced from the first entry in 'URLs' if this is left
198e272002-06-13Martin Nilsson blank.</p>
f418572001-07-21Martin Stjernholm  <p>Note that setting this doesn't make the server accessible; you must
198e272002-06-13Martin Nilsson also set 'URLs'.</p>");
c551f22000-07-04Per Hedbor  defvar("URLs",
b98c022001-07-31Per Hedbor  Variable.PortList( ({"http://*/"}), VAR_INITIAL|VAR_NO_DEFAULT,
198e272002-06-13Martin Nilsson  "Ports: URLs", ("Bind to these URLs. You can use '*' and '?' to perform " "globbing (using any of these will default to binding to " "all IP-numbers on your machine). If you specify a IP# in " "the field it will take precedence over the hostname.")));
c5e0961999-10-04Per Hedbor 
199d031999-09-05Francesco Chemolli  defvar("InternalLoc", "/_internal/",
198e272002-06-13Martin Nilsson  "Internal module resource mountpoint",
f406ba1999-11-27Per Hedbor  TYPE_LOCATION|VAR_MORE|VAR_DEVELOPER,
198e272002-06-13Martin Nilsson  ("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."));
483b062002-05-16Stefan Wallström  defvar("SubRequestLimit", 30, "Subrequest depth limit", TYPE_INT | VAR_MORE, "A limit for the number of nested sub requests for each request. " "This is intented to catch unintended infinite loops when for example " "inserting files in RXML. 0 for no limit." );
f498ed2000-07-11Martin Nilsson  // Throttling-related variables defvar("throttle", 0,
198e272002-06-13Martin Nilsson  "Throttling: Server; Enabled", TYPE_FLAG, ("If set, per-server bandwidth throttling will be enabled. " "It will allow you to limit the total available bandwidth for " "this site.<br />Bandwidth is assigned using a Token Bucket. " "The principle under which it works is: for each byte we send we use a token. " "Tokens are added to a repository at a constant rate. When there's not enough, " "we can't transmit. When there's too many, they \"spill\" and are lost."));
199d031999-09-05Francesco Chemolli  //TODO: move this explanation somewhere on the website and just put a link.
f498ed2000-07-11Martin Nilsson  defvar("throttle_fill_rate", 102400,
198e272002-06-13Martin Nilsson  "Throttling: Server; Average available bandwidth",
199d031999-09-05Francesco Chemolli  TYPE_INT,
198e272002-06-13Martin Nilsson  ("This is the average bandwidth available to this site in " "bytes/sec (the bucket \"fill rate\")."),
f498ed2000-07-11Martin Nilsson  0, arent_we_throttling_server); defvar("throttle_bucket_depth", 1024000,
198e272002-06-13Martin Nilsson  "Throttling: Server; Bucket Depth", TYPE_INT, ("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);
f498ed2000-07-11Martin Nilsson  defvar("throttle_min_grant", 1300,
198e272002-06-13Martin Nilsson  "Throttling: Server; Minimum Grant", TYPE_INT, ("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)."),
f498ed2000-07-11Martin Nilsson  0, arent_we_throttling_server); defvar("throttle_max_grant", 14900,
198e272002-06-13Martin Nilsson  "Throttling: Server; Maximum Grant", TYPE_INT, ("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);
199d031999-09-05Francesco Chemolli  defvar("req_throttle", 0,
198e272002-06-13Martin Nilsson  "Throttling: Request; Enabled", TYPE_FLAG, "If set, per-request bandwidth throttling will be enabled.");
4d16831999-11-17Per Hedbor 
199d031999-09-05Francesco Chemolli  defvar("req_throttle_min", 1024,
198e272002-06-13Martin Nilsson  "Throttling: Request; Minimum guarranteed bandwidth",
199d031999-09-05Francesco Chemolli  TYPE_INT,
198e272002-06-13Martin Nilsson  ("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."),
f498ed2000-07-11Martin Nilsson  0, arent_we_throttling_request);
4d16831999-11-17Per Hedbor 
199d031999-09-05Francesco Chemolli  defvar("req_throttle_depth_mult", 60.0,
198e272002-06-13Martin Nilsson  "Throttling: Request; Bucket Depth Multiplier",
199d031999-09-05Francesco Chemolli  TYPE_FLOAT,
198e272002-06-13Martin Nilsson  ("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."),
f498ed2000-07-11Martin Nilsson  0, arent_we_throttling_request);
4d16831999-11-17Per Hedbor 
9fbde22000-11-06Per Hedbor  defvar("404-files", ({ "404.inc" }),
198e272002-06-13Martin Nilsson  "No such file message override files",
9fbde22000-11-06Per Hedbor  TYPE_STRING_LIST|VAR_PUBLIC,
198e272002-06-13Martin Nilsson  ("<p>If no file match a given resource all directories above the " "wanted file is searched for one of the files in this list.</p>" "\n" "<p>As an example, if the file /foo/bar/not_there.html is " "wanted, and this list contains the default value of 404.inc, " "these files will be searched for, in this order:</p><br /> " "/foo/bar/404.inc, /foo/404.inc and /404.inc." ) );
9fbde22000-11-06Per Hedbor 
be918b2002-02-26Marcus Wellhardh  defvar("license",
66e4c02002-02-27Marcus Wellhardh  License.
198e272002-06-13Martin Nilsson  LicenseVariable("../license/", VAR_NO_DEFAULT, "License file", "The license file for this configuration.",
66e4c02002-02-27Marcus Wellhardh  this_object()));
9fbde22000-11-06Per Hedbor  class NoSuchFileOverride { // compatibility with old config-files. inherit Variable.Variable; int check_visibility( RequestID id, int more_mode, int expert_mode, int devel_mode, int initial, int|void variable_in_cfif ) { return 0; } void set( string newval ) { if( search(newval,"emit source=values") == -1 ) variables[ "404-message" ]->set( newval ); } void create() { ::create( #"<nooutput><emit source=values scope=ef variable='modvar.site.404-files'> <set variable='var.base' value=''/> <emit source='path'> <append variable='var.base' value='/&_.name;'/> <set variable='var.404' value='&var.base;/&ef.value;'/> <if exists='&var.404;'> <set variable='var.errfile' from='var.404'/> </if> </emit> </emit> </nooutput><if variable='var.errfile'><eval><insert file='&var.errfile;'/></eval></if><else><eval>&modvar.site.404-message:none;</eval></else>", 0, 0, 0 ); } }; defvar("ZNoSuchFile", NoSuchFileOverride() );
b82d0f2001-08-01Per Hedbor  defvar("404-message", #"<html><head>
94d4752000-04-05Martin Nilsson <title>404 - Page not found</title> </head> <body alink=\"#000000\" bgcolor=\"#ffffff\" bottommargin=\"0\" leftmargin=\"0\" link=\"#ce5c00\" marginheight=\"2\" marginwidth=\"0\" rightmargin=\"0\" text=\"#333333\" topmargin=\"2\" vlink=\"#ce5c00\">
8cf9d82000-09-19Martin Nilsson <if nserious=''><set variable='var.404' value='-sorry' /></if>
94d4752000-04-05Martin Nilsson <table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\"> <tr>
8cf9d82000-09-19Martin Nilsson  <td><img src=\"/internal-roxen-page-not-found&var.404;\" border=\"0\" alt=\"Page not found\" width=\"404\" hspace=\"2\" /></td>
94d4752000-04-05Martin Nilsson  <td>&nbsp;</td>
8cf9d82000-09-19Martin Nilsson  <td align=\"right\"><font face=\"lucida,helvetica,arial\">
f997982002-05-29Jonas Wallden  <if variable='roxen.product-name is Roxen CMS'> <b>Roxen CMS&nbsp;</b> </if> <else>
dfc05d2002-06-14Johan Sundström  <b>Internet Server &roxen.base-version;&nbsp;</b>
f997982002-05-29Jonas Wallden  </else> </font></td>
94d4752000-04-05Martin Nilsson  </tr> <tr> <td width=\"100%\" height=\"21\" colspan=\"3\" background=\"/internal-roxen-tile\"><img src=\"/internal-roxen-unit\" alt=\"\" /></td> </tr> </table> <font face=\"lucida,helvetica,arial\"> <h2>&nbsp;Unable to retrieve &page.virtfile;.</h2> <br /><br /> <blockquote> If you feel that this is a configuration error,
8cf9d82000-09-19Martin Nilsson please contact the administrators of this webserver or the author of the <if referrer=''>
94d4752000-04-05Martin Nilsson <a href=\"&client.referrer;\">referring</a> </if><else> referring </else> page. </blockquote> </font> </body>
7146cf2002-03-13Henrik Grubbström (Grubba) </html>
94d4752000-04-05Martin Nilsson ",
198e272002-06-13Martin Nilsson  "No such file message",
9fbde22000-11-06Per Hedbor  TYPE_TEXT_FIELD|VAR_PUBLIC,
198e272002-06-13Martin Nilsson  ("What to return when there is no resource or file " "available at a certain location."));
a7e39f2000-02-04Per Hedbor 
e427912001-06-30Honza Petrous #ifdef SNMP_AGENT // SNMP stuffs defvar("snmp_process", 0, "SNMP: Enabled",TYPE_FLAG, "If set, per-server objects will be added to the SNMP agent database.", 0, snmp_global_disabled); defvar("snmp_community", "public:ro", "SNMP: Community string", TYPE_STRING, "The community string and access level for manipulation on server " " specific objects.", 0, snmp_disabled);
14cf2b2001-07-18Honza Petrous  defvar("snmp_traphosts", ({ }),
7e23ea2001-09-04Honza Petrous  "SNMP: Trap host URLs", TYPE_STRING_LIST, "The remote nodes, where should be sent traps." "<p>\n" "The URL syntax is: snmptrap://community@hostname:portnumber" "</p><br/>", 0, snmp_disabled);
e427912001-06-30Honza Petrous  if (query("snmp_process")) { if(objectp(roxen()->snmpagent)) { int servid;
12e6ea2001-07-19Honza Petrous  servid = roxen()->snmpagent->add_virtserv(get_config_id());
e427912001-06-30Honza Petrous  // todo: make invisible varibale and set it to this value for future reference
14cf2b2001-07-18Honza Petrous  // (support for per-reload persistence of server index?)
e427912001-06-30Honza Petrous  } else report_error("SNMPagent: something gets wrong! The main agent is disabled!\n"); } #endif
12e6ea2001-07-19Honza Petrous  definvisvar( "no_delayed_load", 0, TYPE_FLAG|VAR_PUBLIC ); // report_debug("[defvar: %.1fms] ", (gethrtime()-st)/1000.0 ); // st = gethrtime(); mapping(string:mixed) retrieved_vars = retrieve("spider#0", this_object()); if (sizeof (retrieved_vars) && !retrieved_vars->compat_level) // Upgrading an older configuration; default to 2.1 compatibility level. set ("compat_level", "2.1"); setvars( retrieved_vars ); // report_debug("[restore: %.1fms] ", (gethrtime()-st)/1000.0 );
199d031999-09-05Francesco Chemolli }
9a8a152000-09-25Per Hedbor static int arent_we_throttling_server () {
199d031999-09-05Francesco Chemolli  return !query("throttle"); }
9a8a152000-09-25Per Hedbor static int arent_we_throttling_request() {
199d031999-09-05Francesco Chemolli  return !query("req_throttle");
14179b1997-01-29Per Hedbor }
e427912001-06-30Honza Petrous  #ifdef SNMP_AGENT private static int(0..1) snmp_disabled() { return (!snmp_global_disabled() && !query("snmp_process")); }
14cf2b2001-07-18Honza Petrous private static int(0..1) snmp_global_disabled() { return (!objectp(roxen->snmpagent)); }
e427912001-06-30Honza Petrous #endif