24c6c12000-02-20Martin Nilsson // This file is part of Roxen Webserver. // Copyright © 1996 - 2000, Roxen IS.
8b8ecf2000-08-28Johan Sundström // $Id: module.pike,v 1.96 2000/08/28 12:05:45 jhs Exp $
c20c872000-02-16Per Hedbor  #include <module_constants.h>
b1fca01996-11-12Per Hedbor #include <module.h>
c5e0961999-10-04Per Hedbor #include <request_trace.h>
b275871998-05-23Henrik Grubbström (Grubba) 
a59d252000-07-04Per Hedbor inherit "basic_defvar";
9d9b9b1999-11-17Per Hedbor mapping(string:array(int)) error_log=([]);
c5e0961999-10-04Per Hedbor 
9d9b9b1999-11-17Per Hedbor constant is_module = 1;
dd341c2000-01-10Martin Nilsson constant module_type = MODULE_ZERO;
c5e0961999-10-04Per Hedbor constant module_name = "Unnamed module"; constant module_doc = "Undocumented"; constant module_unique = 1;
a59d252000-07-04Per Hedbor  private string _module_identifier; private Configuration _my_configuration; static mapping _api_functions = ([]); string|array(string) module_creator; string module_url; RXML.TagSet module_tag_set;
c20c872000-02-16Per Hedbor /* These functions exists in here because otherwise the messages in * the event log does not always end up in the correct * module/configuration. And the reason for that is that if the * messages are logged from subclasses in the module, the DWIM in * roxenlib.pike cannot see that they are logged from a module. This * solution is not really all that beatiful, but it works. :-) */ void report_fatal( mixed ... args ) { predef::report_fatal( @args ); } void report_error( mixed ... args ) { predef::report_error( @args ); } void report_notice( mixed ... args ) { predef::report_notice( @args ); } void report_debug( mixed ... args ) { predef::report_debug( @args ); }
b9ec252000-01-05Martin Stjernholm string module_identifier() { if (!_module_identifier) { string|mapping name = register_module()[1]; if (mappingp (name)) name = name->standard;
8d49192000-03-18Martin Stjernholm  string cname = sprintf ("%O", my_configuration()); if (sscanf (cname, "Configuration(%s", cname) == 1 && sizeof (cname) && cname[-1] == ')') cname = cname[..sizeof (cname) - 2]; _module_identifier = sprintf ("%s,%s", name || module_name, cname);
b9ec252000-01-05Martin Stjernholm  } return _module_identifier; }
b6fb051999-11-02Per Hedbor string _sprintf() {
c2768e2000-08-22Martin Stjernholm  return "RoxenModule(" + (Roxen.get_modname (this_object()) || module_identifier()) + ")";
b6fb051999-11-02Per Hedbor }
c5e0961999-10-04Per Hedbor array register_module() { return ({ module_type, module_name, module_doc, 0, module_unique, }); }
2a2a5b1996-12-01Per Hedbor string fix_cvs(string from) {
fd0b6f1996-12-02Per Hedbor  from = replace(from, ({ "$", "Id: "," Exp $" }), ({"","",""}));
2a2a5b1996-12-01Per Hedbor  sscanf(from, "%*s,v %s", from);
00730e1999-11-18Per Hedbor  return replace(from,"/","-");
2a2a5b1996-12-01Per Hedbor }
72ac572000-01-31Per Hedbor int module_dependencies(Configuration configuration,
f5a2741999-10-18Per Hedbor  array (string) modules, int|void now)
facee72000-07-18Johan Sundström //! If your module depends on other modules present in the server, //! calling <pi>module_dependencies()</pi>, supplying an array of //! module identifiers (the filename minus extension, more or less).
edb5061997-08-25Peter Bortas {
a59d252000-07-04Per Hedbor  if(configuration || my_configuration() ) (configuration||my_configuration())->add_modules( modules, now );
edb5061997-08-25Peter Bortas  return 1; }
2a2a5b1996-12-01Per Hedbor string file_name_and_stuff() {
a59d252000-07-04Per Hedbor  return ("<b>Loaded from:</b> "+(roxen->filename(this_object()))+"<br>"+ (this_object()->cvs_version?
00730e1999-11-18Per Hedbor  "<b>CVS Version: </b>"+
a59d252000-07-04Per Hedbor  fix_cvs(this_object()->cvs_version)+"\n":""));
2a2a5b1996-12-01Per Hedbor }
5839c31999-01-22Marcus Comstedt 
9f2a971999-11-29Per Hedbor Configuration my_configuration()
facee72000-07-18Johan Sundström //! Returns the Configuration object of the virtual server the module //! belongs to.
b1fca01996-11-12Per Hedbor {
5839c31999-01-22Marcus Comstedt  if(_my_configuration) return _my_configuration;
7fb7f51999-11-29Per Hedbor  Configuration conf;
b1fca01996-11-12Per Hedbor  foreach(roxen->configurations, conf)
a59d252000-07-04Per Hedbor  if(conf->otomod[this_object()])
33266d1999-05-24Per Hedbor  return _my_configuration = conf;
b1fca01996-11-12Per Hedbor  return 0; }
7fb7f51999-11-29Per Hedbor nomask void set_configuration(Configuration c)
5839c31999-01-22Marcus Comstedt { if(_my_configuration && _my_configuration != c) error("set_configuration() called twice.\n"); _my_configuration = c; }
48679b2000-02-03Johan Sundström void set_module_creator(string|array(string) c)
facee72000-07-18Johan Sundström //! Set the name and optionally email address of the author of the //! module. Names on the format "author name <author_email>" will //! end up as links on the module's information page in the admin //! interface. In the case of multiple authors, an array of such //! strings can be passed.
b1fca01996-11-12Per Hedbor { module_creator = c; } void set_module_url(string to)
facee72000-07-18Johan Sundström //! A common way of referring to a location where you maintain //! information about your module or similar. The URL will turn up //! on the module's information page in the admin interface, //! referred to as the module's home page.
b1fca01996-11-12Per Hedbor { module_url = to; } void free_some_sockets_please(){}
7fb7f51999-11-29Per Hedbor void start(void|int num, void|Configuration conf) {}
b1fca01996-11-12Per Hedbor 
a59d252000-07-04Per Hedbor string status() {}
c5e0961999-10-04Per Hedbor 
7fb7f51999-11-29Per Hedbor string info(Configuration conf)
72ac572000-01-31Per Hedbor {
facee72000-07-18Johan Sundström  return (this_object()->register_module()[2]);
df6cd11998-10-13Per Hedbor }
b1fca01996-11-12Per Hedbor 
2c13a81999-11-10Per Hedbor void save_me()
e7e6031999-11-05Per Hedbor { my_configuration()->save_one( this_object() ); }
2c13a81999-11-10Per Hedbor void save() { save_me(); }
b1fca01996-11-12Per Hedbor string comment() { return ""; }
5839c31999-01-22Marcus Comstedt string query_internal_location()
facee72000-07-18Johan Sundström //! Returns the internal mountpoint, where <ref>find_internal()</ref> //! is mounted.
5839c31999-01-22Marcus Comstedt { if(!_my_configuration) error("Please do not call this function from create()!\n"); return _my_configuration->query_internal_location(this_object()); }
b7c45e1997-01-27Per Hedbor string query_location() { string s; catch{s = query("location");}; return s; }
162bd52000-02-20Martin Stjernholm array(string) location_urls()
facee72000-07-18Johan Sundström //! Returns an array of all locations where the module is mounted. //! The first is the canonical one built with MyWorldLocation.
162bd52000-02-20Martin Stjernholm { string loc = query_location(); if (!loc) return ({}); if(!_my_configuration) error("Please do not call this function from create()!\n"); string world_url = _my_configuration->query("MyWorldLocation"); if (world_url == "") world_url = 0;
3adf202000-03-06Jonas Wallden  array(string) urls = copy_value(_my_configuration->query("URLs"));
162bd52000-02-20Martin Stjernholm  string hostname = gethostname(); for (int i = 0; i < sizeof (urls); i++) { if (world_url && glob (urls[i], world_url)) urls[i] = 0; else if (sizeof (urls[i]/"*") == 2) urls[i] = replace(urls[i], "*", hostname); } if (world_url) urls = ({world_url}) | (urls - ({0})); return map (urls, `+, loc[1..]); }
ae32d01998-03-23David Hedbor /* By default, provide nothing. */
72ac572000-01-31Per Hedbor string query_provides() { return 0; }
b7c45e1997-01-27Per Hedbor 
b1fca01996-11-12Per Hedbor /* * Parse and return a parsed version of the security levels for this module * */
a59d252000-07-04Per Hedbor class IP_with_mask {
17d1731997-08-13Henrik Grubbström (Grubba)  int net; int mask; static private int ip_to_int(string ip) { int res;
eac26d1997-09-27Henrik Grubbström (Grubba)  foreach(((ip/".") + ({ "0", "0", "0" }))[..3], string num) {
17d1731997-08-13Henrik Grubbström (Grubba)  res = res*256 + (int)num; } return(res); }
4117501997-08-13Henrik Grubbström (Grubba)  void create(string _ip, string|int _mask)
17d1731997-08-13Henrik Grubbström (Grubba)  { net = ip_to_int(_ip);
4117501997-08-13Henrik Grubbström (Grubba)  if (intp(_mask)) { if (_mask > 32) { report_error(sprintf("Bad netmask: %s/%d\n" "Using %s/32\n", _ip, _mask, _ip)); _mask = 32; } mask = ~0<<(32-_mask); } else { mask = ip_to_int(_mask); }
17d1731997-08-13Henrik Grubbström (Grubba)  if (net & ~mask) {
4117501997-08-13Henrik Grubbström (Grubba)  report_error(sprintf("Bad netmask: %s for network %s\n" "Ignoring node-specific bits\n", _ip, _mask)); net &= mask;
17d1731997-08-13Henrik Grubbström (Grubba)  } } int `()(string ip) { return((ip_to_int(ip) & mask) == net); } };
b7c45e1997-01-27Per Hedbor 
b1fca01996-11-12Per Hedbor array query_seclevels() { array patterns=({ });
a59d252000-07-04Per Hedbor  if(catch(query("_seclevels")) || (query("_seclevels") == 0))
b1fca01996-11-12Per Hedbor  return patterns;
72ac572000-01-31Per Hedbor 
4117501997-08-13Henrik Grubbström (Grubba)  foreach(replace(query("_seclevels"), ({" ","\t","\\\n"}), ({"","",""}))/"\n", string sl) {
b1fca01996-11-12Per Hedbor  if(!strlen(sl) || sl[0]=='#') continue;
de493f1997-04-28Henrik Grubbström (Grubba) 
b1fca01996-11-12Per Hedbor  string type, value; if(sscanf(sl, "%s=%s", type, value)==2) {
de493f1997-04-28Henrik Grubbström (Grubba)  switch(lower_case(type))
b1fca01996-11-12Per Hedbor  { case "allowip":
4117501997-08-13Henrik Grubbström (Grubba)  array(string|int) arr; if (sizeof(arr = (value/"/")) == 2) { // IP/bits arr[1] = (int)arr[1]; patterns += ({ ({ MOD_ALLOW, IP_with_mask(@arr) }) }); } else if ((sizeof(arr = (value/":")) == 2) ||
8919711998-02-06Gerald Schupfner  (sizeof(arr = (value/",")) > 1)) {
4117501997-08-13Henrik Grubbström (Grubba)  // IP:mask or IP,mask patterns += ({ ({ MOD_ALLOW, IP_with_mask(@arr) }) }); } else { // Pattern
17d1731997-08-13Henrik Grubbström (Grubba)  value = replace(value, ({ "?", ".", "*" }), ({ ".", "\\.", ".*" })); patterns += ({ ({ MOD_ALLOW, Regexp(value)->match, }) }); }
b1fca01996-11-12Per Hedbor  break;
9579781998-06-29Henrik Grubbström (Grubba)  case "acceptip": // Short-circuit version of allow ip. array(string|int) arr; if (sizeof(arr = (value/"/")) == 2) { // IP/bits arr[1] = (int)arr[1]; patterns += ({ ({ MOD_ACCEPT, IP_with_mask(@arr) }) }); } else if ((sizeof(arr = (value/":")) == 2) || (sizeof(arr = (value/",")) > 1)) { // IP:mask or IP,mask patterns += ({ ({ MOD_ACCEPT, IP_with_mask(@arr) }) }); } else { // Pattern value = replace(value, ({ "?", ".", "*" }), ({ ".", "\\.", ".*" })); patterns += ({ ({ MOD_ACCEPT, Regexp(value)->match, }) }); } break;
b1fca01996-11-12Per Hedbor  case "denyip":
4117501997-08-13Henrik Grubbström (Grubba)  array(string|int) arr; if (sizeof(arr = (value/"/")) == 2) { // IP/bits arr[1] = (int)arr[1]; patterns += ({ ({ MOD_DENY, IP_with_mask(@arr) }) }); } else if ((sizeof(arr = (value/":")) == 2) ||
8919711998-02-06Gerald Schupfner  (sizeof(arr = (value/",")) > 1)) {
4117501997-08-13Henrik Grubbström (Grubba)  // IP:mask or IP,mask patterns += ({ ({ MOD_DENY, IP_with_mask(@arr) }) }); } else { // Pattern
17d1731997-08-13Henrik Grubbström (Grubba)  value = replace(value, ({ "?", ".", "*" }), ({ ".", "\\.", ".*" })); patterns += ({ ({ MOD_DENY, Regexp(value)->match, }) }); }
b1fca01996-11-12Per Hedbor  break;
f6d62d1997-03-26Per Hedbor  case "allowuser":
17d1731997-08-13Henrik Grubbström (Grubba)  value = replace(value, ({ "?", ".", "*" }), ({ ".", "\\.", ".*" }));
f6d62d1997-03-26Per Hedbor  array(string) users = (value/"," - ({""})); int i;
72ac572000-01-31Per Hedbor 
f6d62d1997-03-26Per Hedbor  for(i=0; i < sizeof(users); i++) {
de493f1997-04-28Henrik Grubbström (Grubba)  if (lower_case(users[i]) == "any") {
a59d252000-07-04Per Hedbor  if(this_object()->register_module()[0] & MODULE_PROXY)
f6d62d1997-03-26Per Hedbor  patterns += ({ ({ MOD_PROXY_USER, lambda(){ return 1; } }) }); else patterns += ({ ({ MOD_USER, lambda(){ return 1; } }) }); break; } else { users[i & 0x0f] = "(^"+users[i]+"$)"; } if ((i & 0x0f) == 0x0f) { value = users[0..0x0f]*"|";
a59d252000-07-04Per Hedbor  if(this_object()->register_module()[0] & MODULE_PROXY) {
f6d62d1997-03-26Per Hedbor  patterns += ({ ({ MOD_PROXY_USER, Regexp(value)->match, }) }); } else { patterns += ({ ({ MOD_USER, Regexp(value)->match, }) }); } } } if (i & 0x0f) { value = users[0..(i-1)&0x0f]*"|";
a59d252000-07-04Per Hedbor  if(this_object()->register_module()[0] & MODULE_PROXY) {
f6d62d1997-03-26Per Hedbor  patterns += ({ ({ MOD_PROXY_USER, Regexp(value)->match, }) }); } else { patterns += ({ ({ MOD_USER, Regexp(value)->match, }) }); }
a397fe1996-12-13David Hedbor  }
b1fca01996-11-12Per Hedbor  break;
9579781998-06-29Henrik Grubbström (Grubba)  case "acceptuser": // Short-circuit version of allow user. // NOTE: MOD_PROXY_USER is already short-circuit. value = replace(value, ({ "?", ".", "*" }), ({ ".", "\\.", ".*" })); array(string) users = (value/"," - ({""})); int i;
72ac572000-01-31Per Hedbor 
9579781998-06-29Henrik Grubbström (Grubba)  for(i=0; i < sizeof(users); i++) { if (lower_case(users[i]) == "any") {
a59d252000-07-04Per Hedbor  if(this_object()->register_module()[0] & MODULE_PROXY)
9579781998-06-29Henrik Grubbström (Grubba)  patterns += ({ ({ MOD_PROXY_USER, lambda(){ return 1; } }) }); else patterns += ({ ({ MOD_ACCEPT_USER, lambda(){ return 1; } }) }); break; } else { users[i & 0x0f] = "(^"+users[i]+"$)"; } if ((i & 0x0f) == 0x0f) { value = users[0..0x0f]*"|";
a59d252000-07-04Per Hedbor  if(this_object()->register_module()[0] & MODULE_PROXY) {
9579781998-06-29Henrik Grubbström (Grubba)  patterns += ({ ({ MOD_PROXY_USER, Regexp(value)->match, }) }); } else { patterns += ({ ({ MOD_ACCEPT_USER, Regexp(value)->match, }) }); } } } if (i & 0x0f) { value = users[0..(i-1)&0x0f]*"|";
a59d252000-07-04Per Hedbor  if(this_object()->register_module()[0] & MODULE_PROXY) {
9579781998-06-29Henrik Grubbström (Grubba)  patterns += ({ ({ MOD_PROXY_USER, Regexp(value)->match, }) }); } else { patterns += ({ ({ MOD_ACCEPT_USER, Regexp(value)->match, }) }); } } break;
de493f1997-04-28Henrik Grubbström (Grubba)  default:
4117501997-08-13Henrik Grubbström (Grubba)  report_error(sprintf("Unknown Security:Patterns directive: " "type=\"%s\"\n", type));
de493f1997-04-28Henrik Grubbström (Grubba)  break;
b1fca01996-11-12Per Hedbor  }
de493f1997-04-28Henrik Grubbström (Grubba)  } else {
4117501997-08-13Henrik Grubbström (Grubba)  report_error(sprintf("Syntax error in Security:Patterns directive: " "line=\"%s\"\n", sl));
b1fca01996-11-12Per Hedbor  } } return patterns; }
8b8ecf2000-08-28Johan Sundström Stat stat_file(string f, RequestID id){} array(string) find_dir(string f, RequestID id){} mapping(string:Stat) find_dir_stat(string f, RequestID id)
a476711997-10-20Henrik Grubbström (Grubba) {
b275871998-05-23Henrik Grubbström (Grubba)  TRACE_ENTER("find_dir_stat(): \""+f+"\"", 0);
a476711997-10-20Henrik Grubbström (Grubba)  array(string) files = find_dir(f, id);
8b8ecf2000-08-28Johan Sundström  mapping(string:Stat) res = ([]);
a476711997-10-20Henrik Grubbström (Grubba) 
0c8b9a1997-10-22Henrik Grubbström (Grubba)  foreach(files || ({}), string fname) {
b275871998-05-23Henrik Grubbström (Grubba)  TRACE_ENTER("stat()'ing "+ f + "/" + fname, 0);
8b8ecf2000-08-28Johan Sundström  Stat st = stat_file(f + "/" + fname, id);
a476711997-10-20Henrik Grubbström (Grubba)  if (st) {
0c8b9a1997-10-22Henrik Grubbström (Grubba)  res[fname] = st;
b275871998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("OK"); } else { TRACE_LEAVE("No stat info");
a476711997-10-20Henrik Grubbström (Grubba)  } }
b275871998-05-23Henrik Grubbström (Grubba)  TRACE_LEAVE("");
a476711997-10-20Henrik Grubbström (Grubba)  return(res); }
a59d252000-07-04Per Hedbor 
8b8ecf2000-08-28Johan Sundström string real_file(string f, RequestID id){}
b1fca01996-11-12Per Hedbor 
4f4bc11998-02-04Per Hedbor void add_api_function( string name, function f, void|array(string) types) { _api_functions[name] = ({ f, types }); } mapping api_functions() { return _api_functions; }
9ed3ea2000-08-06Martin Stjernholm mapping(string:function) query_tag_callers()
facee72000-07-18Johan Sundström //! Compat
48ca161999-05-18Per Hedbor {
9ed3ea2000-08-06Martin Stjernholm  mapping(string:function) m = ([]);
48ca161999-05-18Per Hedbor  foreach(glob("tag_*", indices( this_object())), string q) if(functionp( this_object()[q] )) m[replace(q[4..], "_", "-")] = this_object()[q]; return m; }
9ed3ea2000-08-06Martin Stjernholm mapping(string:function) query_container_callers() //! Compat
48ca161999-05-18Per Hedbor {
9ed3ea2000-08-06Martin Stjernholm  mapping(string:function) m = ([]);
48ca161999-05-18Per Hedbor  foreach(glob("container_*", indices( this_object())), string q) if(functionp( this_object()[q] )) m[replace(q[10..], "_", "-")] = this_object()[q]; return m; }
9ed3ea2000-08-06Martin Stjernholm mapping(string:array(int|function)) query_simpletag_callers()
7d2a5d2000-01-31Martin Nilsson {
9ed3ea2000-08-06Martin Stjernholm  mapping(string:array(int|function)) m = ([]);
7d2a5d2000-01-31Martin Nilsson  foreach(glob("simpletag_*", indices(this_object())), string q) if(functionp(this_object()[q]))
d6b20a2000-02-08Martin Stjernholm  m[replace(q[10..],"_","-")] = ({ intp (this_object()[q + "_flags"]) && this_object()[q + "_flags"], this_object()[q] });
7d2a5d2000-01-31Martin Nilsson  return m;
48ca161999-05-18Per Hedbor }
ea062e1999-11-21Martin Nilsson 
9ed3ea2000-08-06Martin Stjernholm mapping(string:array(int|function)) query_simple_pi_tag_callers() { mapping(string:array(int|function)) m = ([]); foreach (glob ("simple_pi_tag_*", indices (this_object())), string q) if (functionp (this_object()[q])) m[replace (q[sizeof ("simple_pi_tag_")..], "_", "-")] = ({(intp (this_object()[q + "_flags"]) && this_object()[q + "_flags"]) | RXML.FLAG_PROC_INSTR, this_object()[q]}); return m; }
1b2b752000-01-07Martin Stjernholm RXML.TagSet query_tag_set()
b9ec252000-01-05Martin Stjernholm {
395e462000-01-18Martin Stjernholm  if (!module_tag_set) { array(function|program|object) tags = filter (rows (this_object(), glob ("Tag*", indices (this_object()))), functionp); for (int i = 0; i < sizeof (tags); i++) if (programp (tags[i])) if (!tags[i]->is_RXML_Tag) tags[i] = 0; else tags[i] = tags[i](); else { tags[i] = tags[i](); // Bogosity: The check is really a little too late here.. if (!tags[i]->is_RXML_Tag) tags[i] = 0; } tags -= ({0}); module_tag_set = (this_object()->ModuleTagSet || RXML.TagSet) (module_identifier(), tags); } return module_tag_set;
b9ec252000-01-05Martin Stjernholm }
12e79e1999-12-07Martin Nilsson mixed get_value_from_file(string path, string index, void|string pre)
ea062e1999-11-21Martin Nilsson {
7fb7f51999-11-29Per Hedbor  Stdio.File file=Stdio.File();
ea062e1999-11-21Martin Nilsson  if(!file->open(path,"r")) return 0;
12e79e1999-12-07Martin Nilsson  if(index[sizeof(index)-2..sizeof(index)-1]=="()") { return compile_string((pre||"")+file->read())[index[..sizeof(index)-3]](); } return compile_string((pre||"")+file->read())[index];
ea062e1999-11-21Martin Nilsson }