f41b982009-05-07Martin Stjernholm // This is a roxen module. Copyright © 1998 - 2009, Roxen IS.
1430c02000-03-16Martin Nilsson 
980d532007-05-16Stefan Wallström #include <module.h>
5a31bd1998-10-02Henrik Grubbström (Grubba) inherit "module";
f41b982009-05-07Martin Stjernholm constant cvs_version = "$Id: pathinfo.pike,v 1.22 2009/05/07 14:15:55 mast Exp $";
5a31bd1998-10-02Henrik Grubbström (Grubba) constant thread_safe = 1;
29c8dd1999-12-28Martin Nilsson #ifdef PATHINFO_DEBUG # define PATHINFO_WERR(X) werror("PATHINFO: "+X+"\n"); #else # define PATHINFO_WERR(X) #endif
28bb742000-02-10Martin Nilsson constant module_type = MODULE_LAST;
17013c2001-05-16Per Hedbor constant module_name = "Scripting: Path info support";
4025092000-03-20Martin Stjernholm constant module_doc = #"\ Support for \"path info\" style URLs, e.g. URLs that got a path like <tt>/index.html/a/b</tt>, where <tt>/index.html</tt> is an existing file, but <tt>/index.html/a</tt> and <tt>/index.html/a/b</tt> aren't. In this case <tt>/index.html</tt> will be fetched, and the rest, <tt>/a/b</tt> is made available in the RXML variable page.pathinfo.";
5a31bd1998-10-02Henrik Grubbström (Grubba) 
1231522000-06-19Henrik Grubbström (Grubba) /* #define PATHINFO_LINEAR */
980d532007-05-16Stefan Wallström array pathlimit = ({ }); void create(Configuration c) { defvar("pathlimit", ({ }), "Limit to paths", TYPE_STRING_LIST,
ce64c82007-05-16Jonas Wallden  "If specified, path info support will only be active for paths matching globs provided in this list.");
980d532007-05-16Stefan Wallström } void start() { pathlimit = query("pathlimit"); }
5a31bd1998-10-02Henrik Grubbström (Grubba) mapping|int last_resort(object id) {
980d532007-05-16Stefan Wallström  if(sizeof(pathlimit)) { int found_match = 0; foreach(pathlimit, string s) { if(glob(s, id->not_query)) { found_match = 1; break; } } if(!found_match) return 0; }
29c8dd1999-12-28Martin Nilsson  PATHINFO_WERR(sprintf("Checking %O...", id->not_query));
3b78432004-04-19Martin Stjernholm  #if 0 // This kind of recursion detection doesn't work with internal // redirects. We leave it to the generic loop prevention in // handle_request et al.
5a31bd1998-10-02Henrik Grubbström (Grubba)  if (id->misc->path_info) { // Already been here...
29c8dd1999-12-28Martin Nilsson  PATHINFO_WERR(sprintf("Been here, done that."));
5a31bd1998-10-02Henrik Grubbström (Grubba)  return 0; }
3b78432004-04-19Martin Stjernholm #endif
b5019b1999-03-25Kadlecsik Jozsi  string query = id->not_query;
1231522000-06-19Henrik Grubbström (Grubba) #ifndef PATHINFO_LINEAR array(int) offsets = Array.map(query/"/", sizeof); int sum = 0; int i; for (i=0; i < sizeof(offsets); i++) { sum = (offsets[i] += sum) + 1; } int lo = (offsets[0] == 0); // Skip testing the empty string. int hi = sizeof(offsets) - 1; while(lo <= hi) { // Don't let the beams cross. int probe = (lo + hi + 1)/2; string file = query[..offsets[probe]-1]; PATHINFO_WERR(sprintf("Trying %O...", file)); /* Note: Zapps id->not_query. */ array st = id->conf->stat_file(file, id); if (st) { if (st[1] >= 0) { // Found a file! id->misc->path_info = query[offsets[probe]..]; id->not_query = file; PATHINFO_WERR(sprintf("Found: %O:%O", id->not_query, id->misc->path_info)); return 1; // Go through id->handle_request() one more time... } PATHINFO_WERR(sprintf("Directory: %O", file)); lo = probe + 1; } else { hi = probe - 1; } } #else /* PATHINFO_LINEAR */
7ae17d1999-10-04Per Hedbor  string pi = "";
e793be1999-10-10Per Hedbor  while( (search( query[1..], "/" ) != -1) && strlen( query ) > 0 )
7ae17d1999-10-04Per Hedbor  { query = reverse(query); string add_path_info; sscanf( query, "%[^/]/%s", add_path_info, query ); query = reverse( query );
4025092000-03-20Martin Stjernholm  pi = "/"+reverse( add_path_info )+pi;
7ae17d1999-10-04Per Hedbor  id->misc->path_info = pi;
29c8dd1999-12-28Martin Nilsson  PATHINFO_WERR(sprintf("Trying: %O (%O)", query, pi));
7ae17d1999-10-04Per Hedbor  array st = id->conf->stat_file( query, id );
e793be1999-10-10Per Hedbor  if( st && (st[ ST_SIZE ] > 0))
7ae17d1999-10-04Per Hedbor  { id->not_query = query;
29c8dd1999-12-28Martin Nilsson  PATHINFO_WERR(sprintf("Found: %O:%O", id->not_query, id->misc->path_info));
7ae17d1999-10-04Per Hedbor  return 1; } }
1231522000-06-19Henrik Grubbström (Grubba) #endif /* !PATHINFO_LINEAR */
5a31bd1998-10-02Henrik Grubbström (Grubba)  return 0; }