Roxen.git / server / base_server / prototypes.pike

version» Context lines:

Roxen.git/server/base_server/prototypes.pike:1:   // This file is part of Roxen WebServer.   // Copyright © 2001 - 2009, Roxen IS.      #include <stat.h>   #include <config.h>   #include <module.h>   #include <module_constants.h> - constant cvs_version="$Id: prototypes.pike,v 1.288 2012/05/10 16:25:57 grubba Exp $"; + constant cvs_version="$Id$";      #ifdef DAV_DEBUG   #define DAV_WERROR(X...) werror(X)   #else /* !DAV_DEBUG */   #define DAV_WERROR(X...)   #endif /* DAV_DEBUG */      #ifdef VARY_DEBUG   #define VARY_WERROR(X...) werror("VARY: " + X)   #else
Roxen.git/server/base_server/prototypes.pike:36:       string get_warnings();    int get_flags();    void set_flags( int flags );    int check_visibility( RequestID id,    int more_mode,    int expert_mode,    int devel_mode,    int initial,    int|void variable_in_cfif ); -  void set_invisibility_check_callback( function(RequestID,Variable:int) cb ); +  this_program set_invisibility_check_callback( function(RequestID,Variable:int) cb );    function(Variable:void) get_changed_callback( ); -  void set_changed_callback( function(Variable:void) cb ); -  void add_changed_callback( function(Variable:void) cb ); +  this_program set_changed_callback( function(Variable:void) cb ); +  this_program add_changed_callback( function(Variable:void) cb );    function(RequestID,Variable:int) get_invisibility_check_callback() ;    string doc( );    string name( );    string type_hint( );    mixed default_value();    void set_warning( string to );    int set( mixed to );    int low_set( mixed to );    mixed query();    int is_defaulted();
Roxen.git/server/base_server/prototypes.pike:319:   //! Configuration information for a site.   //! @seealso   //! @[configuration]   class Configuration   {    inherit BasicDefvar;    constant is_configuration = 1;    mapping(string:int(1..1)) enabled_modules = ([]);    mapping(string:array(int)) error_log=([]);    +  // The Configration logger class - allows overrides of the SocketLogger if needed. +  class ConfigurationLogger { +  inherit Logger.SocketLogger; +  } +  +  // Logger instance for this configuration. +  object json_logger; +    #ifdef PROFILE    mapping(string:array(int)) profile_map = ([]);   #endif    -  class Priority -  { -  string _sprintf (int flag) -  { -  return flag == 'O' && "Priority()"; -  } -  -  array (RoxenModule) url_modules = ({ }); -  array (RoxenModule) logger_modules = ({ }); -  array (RoxenModule) location_modules = ({ }); -  array (RoxenModule) filter_modules = ({ }); -  array (RoxenModule) last_modules = ({ }); -  array (RoxenModule) first_modules = ({ }); -  mapping (string:array(RoxenModule)) file_extension_modules = ([ ]); -  mapping (RoxenModule:multiset(string)) provider_modules = ([ ]); -  } -  +     class DataCache    { -  int current_size, max_size, max_file_size; -  int hits, misses; +     void flush();    void expire_entry(string url, RequestID id);    void set(string url, string data, mapping meta, int expire, RequestID id);    array(string|mapping(string:mixed)) get(string url, RequestID id);    void init_from_variables( );    };    -  array(Priority) allocate_pris(); -  +     object throttler;    RoxenModule types_module;    RoxenModule dir_module;    function types_fun;       string name;    int inited;       // Protocol specific statistics.    int requests, sent, hsent, received;
Roxen.git/server/base_server/prototypes.pike:463:    array(function) logger_modules();    array(function) last_modules();    array(function) first_modules();    array location_modules();    array(function) filter_modules();    void init_log_file();    int|mapping check_security(function|object a, RequestID id, void|int slevel);    void invalidate_cache();    void clear_memory_caches();    string examine_return_mapping(mapping m); -  multiset(DAVLock) find_locks(string path, int(0..1) recursive, +  multiset(DAVLock) find_locks(string path, int(-1..1) recursive,    int(0..1) exclude_shared, RequestID id);    DAVLock|LockFlag check_locks(string path, int(0..1) recursive, RequestID id);    mapping(string:mixed) unlock_file(string path, DAVLock lock, RequestID|int(0..0) id);    int expire_locks(RequestID id);    void refresh_lock(DAVLock lock);    mapping(string:mixed)|DAVLock lock_file(string path,    int(0..1) recursive,    string lockscope,    string locktype,    int(0..) expiry_delta,
Roxen.git/server/base_server/prototypes.pike:1169:   //! @appears ProtocolCacheKey   //!   //! The cache key used by the protocol cache.   {    inherit TristateCacheKey;   }      // Kludge for resolver problems   protected function _charset_decoder_func;    - string browser_supports_vary(string ignored, RequestID id) - { -  return (string)!has_value(id->client||"", "MSIE"); - } -  +    // This is a somewhat simplistic regexp that doesn't handle   // quoted-string parameter values correctly. It's only used on content   // types so we know wide strings aren't a problem.   protected Regexp ct_charset_search = Regexp (";[ \t\n\r]*charset=");    -  + // Logger class for requests. Intended to have a parent logger in + // the parent request or its configuration. + class RequestJSONLogger { +  inherit Logger.BaseJSONLogger; +  string request_uuid; +  +  mapping merge_defaults(mapping msg) { +  // We always want the hrtime from the request as well as the thread id. +  msg = msg + ([ +  // We want the current hrtime, not the start of the request... +  "hrtime" : gethrtime(), +  ]); +  +  msg->rid = request_uuid; +  +  return ::merge_defaults(msg); +  } +  +  //! Default parameter mapping and a parent logger object. +  //! +  //! The @[parent_logger] object is used to pass any log messages +  //! injected into this logger up the chain. By default, this logger +  //! does not log at it's own level if a parent logger is given. Instead, +  //! it will simply add its defaults and pass the complete log entry up +  //! to the parent which is then responsible for handling the actual logging. +  void create(void|string logger_name, void|mapping|function defaults, +  void|object parent_logger, void|string request_uuid) { +  ::create (logger_name, defaults, parent_logger); +  this_program::request_uuid = request_uuid; +  } + } +    class RequestID   //! @appears RequestID   //! The request information object contains all request-local information and   //! server as the vessel for most forms of intercommunication between modules,   //! scripts, RXML and so on. It gets passed round to almost all API callbacks   //! worth mentioning. A RequestID object is born when an incoming request is   //! encountered, and its life expectancy is short, as it dies again when the   //! request has passed through all levels of the module type calling sequence.   {   #ifdef ID_OBJ_DEBUG    RoxenDebug.ObjectMarker __marker = RoxenDebug.ObjectMarker (this);   #else    //! @ignore    DECLARE_OBJ_COUNT;    //! @endignore   #endif    -  Configuration conf; +  // Generator for unique request UUIDs on the fly. +  protected string _request_uuid; +  string `request_uuid() { +  return _request_uuid || (_request_uuid = Standards.UUID.make_version4()->str()); +  }; +  void `request_uuid=(mixed v) { +  _request_uuid = (string)v; +  };    -  +  protected Configuration _conf; +  Configuration `conf() { +  return _conf; +  } +  +  void `conf=(Configuration c) { +  if (!json_logger->parent_logger && c) +  json_logger->parent_logger = c->json_logger; +  _conf = c; +  } +  +  RequestJSONLogger json_logger = RequestJSONLogger("server/handler", UNDEFINED, +  UNDEFINED, request_uuid); +     Protocol port_obj;    //! The port object this request came from.       int time;    //! Time of the request, standard unix time (seconds since the epoch; 1970).       int hrtime;    //! Time of the start of the request, as returned by @[gethrtime].       string raw_url;
Roxen.git/server/base_server/prototypes.pike:1375:    //! names should follow the capitalization forms used in RFC    //! 2616 (c.f. @[Roxen.canonicalize_http_header]). See    //! @[add_response_header()] for more details.    //! @member int(1..1) "no_proto_cache"    //! Flag indicating that the result should not be cached in    //! the protocol cache.    //! @member RequestID "orig"    //! Originating @[RequestID] for recursive requests.    //! @member int "port"    //! Port number from the canonicalized host header. +  //! +  //! Note that this may differ from the actual port number +  //! (available in @[port_obj->port]) if eg the server is +  //! found behind a load balancing proxy. cf [bug 7385]. +  //! @member array(array(string|int)) forwarded +  //! Parsed @expr{"Forwarded"@} header (@rfc{7239@}). +  //! If the client sent no forwarded headers, any @expr{"x-forwarded-*"@} +  //! headers that it sent are used instead. +  //! +  //! Each entry is on the format returned by @[MIME.tokenize()], and +  //! corresponds to one @b{Forwarded@} field.    //! @member PrefLanguages "pref_languages"    //! Language preferences for the request.    //! @member mapping(string:array(string)) "post_variables"    //! For POST requests, these are the variables parsed from the    //! request body. It is undefined otherwise.    //! @member mapping(string:array(MIME.Message)) "post_parts"    //! For multipart/form-data POST requests, this holds the MIME    //! message object for each part. It is undefined otherwise.    //! @member array "proxyauth"    //! Decoded proxy authentication information.
Roxen.git/server/base_server/prototypes.pike:1437:    //! to a cloned @[RequestID]. This is a feature.    //!    //! @seealso    //! @[cookies], @[register_vary_callback()], @[Roxen.get_cookie_callback()]    class CookieJar    {    //! Contains the set of cookies that have been zapped in some way.    protected mapping(string:string) eaten = ([]);       -  // cf RFC 2109. +  // cf RFC 6265.    protected void create(string|array(string)|mapping(string:string)|void    contents)    {    VARY_WERROR("Initiating cookie jar.\n");    real_cookies = ([]);       if(!contents)    return;       if (mappingp(contents)) {    real_cookies = contents;    return;    }       array tmp = arrayp(contents) ? contents : ({ contents});       foreach(tmp, string cookieheader) { -  array(int|string) tokens = MIME.tokenize(cookieheader); -  foreach(tokens/({';'}), array(int|string) c) +  foreach(cookieheader/";", string c)    { -  array(array(int|string)) pair = c/({'='}); +  array(string) pair = c/"=";    if (sizeof(pair) < 2) continue; -  string name = MIME.quote(pair[0]); -  string value = MIME.quote(pair[1..]*({'='})); -  // FIXME: What about cookie-attributes? +  string name = String.trim_whites(pair[0]); +  string value = String.trim_whites(pair[1..]*"="); +  if (has_prefix(value, "\"") && has_suffix(value, "\"")) +  value = value[1..sizeof(value)-2];    catch {    value=_Roxen.http_decode_string(value);    };    catch {    name=_Roxen.http_decode_string(name);    };    real_cookies[ name ]=value;      #ifdef OLD_RXML_CONFIG    // FIXME: Really ought to register this one...
Roxen.git/server/base_server/prototypes.pike:1484:    config = mkmultiset( value/"," );   #endif    }    }    }    protected string `->(string cookie)    {    if (supports && zero_type(eaten[cookie])) {    VARY_WERROR("Looking at cookie %O from %s\n",    cookie, describe_backtrace(({backtrace()[-2]}))); -  /* Workaround for MSIE 6's refusal to cache anything with -  * a Vary:Cookie header. -  */ -  register_vary_callback("user-agent", browser_supports_vary); -  if (supports->vary) { +     register_vary_callback("cookie", Roxen->get_cookie_callback(cookie)); -  } else { -  register_vary_callback("user-agent", -  Roxen->get_cookie_callback(cookie)); +     } -  } +     return real_cookies[cookie];    }    protected string `[](mixed cookie)    {    if (stringp(cookie)) {    return `->(cookie);    }    return UNDEFINED;    }    protected string `->=(string cookie, string value)
Roxen.git/server/base_server/prototypes.pike:1567:       //! @ignore    DECLARE_OBJ_COUNT;    //! @endignore       protected string _sprintf(int fmt)    {    return fmt == 'O' && sprintf("CookieJar(%O)" + OBJ_COUNT,    RequestID::this && real_cookies);    } +  +  string encode_json(int flags) { +  return Standards.JSON.encode(real_cookies);    } -  +  }       CookieJar|mapping(string:string) cookies;    //! The indices and values map to the names and values of the cookies sent    //! by the client for the requested page. All data (names and values) are    //! decoded from their possible transport encoding.    //!    //! @note    //! Used to be a plain mapping in Roxen 4.0 and earlier. It now    //! has a wrapper that registers dependencies on the various cookies.    //! @note
Roxen.git/server/base_server/prototypes.pike:1814:    if (xml_data) return xml_data;    // FIXME: Probably ought to check that the content-type for    // the request is text/xml.    DAV_WERROR("Parsing XML data: %O\n", data);    return xml_data =    Parser.XML.Tree.simple_parse_input(data,    0,    Parser.XML.Tree.PARSE_ENABLE_NAMESPACES);    }    +  //! Get a string describing the link layer protocol for the request. +  //! +  //! @returns +  //! Currently returns one of +  //! @string +  //! @value "-" +  //! Unknown. Typically an internal request or the connection has +  //! been closed. +  //! @value "TCP/IP" +  //! Standard TCP/IP connection. +  //! @value "SSL/3.0" +  //! Secure Socket Layer version 3.0. +  //! @value "TLS/1.0" +  //! Transport Layer Security version 1.0. +  //! @value "TLS/1.1" +  //! Transport Layer Security version 1.1. +  //! @value "TLS/1.2" +  //! Transport Layer Security version 1.2. +  //! @endstring +  //! +  //! @note +  //! This is the value logged by the log-format @tt{$link-layer@}. +  //! +  //! @note +  //! More versions of TLS may become supported, in which case they +  //! will get corresponding results from this function. +  //! +  //! @seealso +  //! @[query_cipher_suite()] +  string query_link_layer() +  { +  if (!my_fd) return "-"; +  if (!my_fd->query_version) return "TCP/IP"; +  return replace(SSL.Constants.fmt_version(my_fd->query_version()), " ", "/"); +  } +  +  //! Get a string describing the TLS cipher suite used for the request. +  //! +  //! @returns +  //! Returns either +  //! @string +  //! @value "-" +  //! None. Either the connection doesn't use SSL/TLS, or the +  //! handshaking hasn't completed yet. +  //! @value "TLS_*" +  //! @value "SSL_*" +  //! A symbol from the table of cipher suites in @[SSL.Constants]. +  //! These are typically the same as the symbols in the corresponding +  //! RFCs, but with only the "TLS_"/"SSL_" prefix being upper case. +  //! @endstring +  //! +  //! @note +  //! This is the value logged by the log-format @tt{$cipher-suite@}. +  //! +  //! @seealso +  //! @[query_link_layer()] +  string query_cipher_suite() +  { +  if (!my_fd || !my_fd->query_suite) return "-"; +  int suite = my_fd->query_suite(); +  if (!suite) return "-"; +  return SSL.Constants.fmt_cipher_suite(suite); +  } +     // Parsed if-header for the request.    protected mapping(string:array(array(array(string)))) if_data;      #ifdef IF_HEADER_DEBUG   #define IF_HDR_MSG(X...) werror (X)   #else   #define IF_HDR_MSG(X...)   #endif       //! Parse an RFC 2518 9.4 "If Header".
Roxen.git/server/base_server/prototypes.pike:2338:    if (mixed err = catch {    if (obj)    // Relying on the interpreter lock here.    destruct (obj);    })    master()->handle_error (err);    }    }    }    +  protected variant string find_in_misc_forwarded(string key, +  bool|void case_insensitive) +  //! Wrapper for +  //! find_in_misc_forwarded(multiset(string) keys, bool|void case_insensitive) +  { +  return find_in_misc_forwarded((<key>), case_insensitive)[key]; +  } +  +  protected variant mapping(string:string) +  find_in_misc_forwarded(multiset(string) keys, bool|void case_insensitive) +  //! If @[case_insensitive] is true, indeces in arg @[keys] will be converted +  //! to lower case. Indeces in returned mapping will also be only in lower +  //! case. +  { +  keys += (<>); // Shallow copy is ok since keys are strings. +  if (case_insensitive) { +  for (keys; string key;) { +  keys[key] = 0; +  keys[lower_case(key)] = 1; +  } +  } +  mapping(string:string) map_ = ([]); +  foreach(misc->forwarded || ({}), array(int|string) entry) { +  foreach(entry/ ({ ';' }), array(int|string) forwarded_pair) { +  if ((sizeof(forwarded_pair) != 3) || +  (forwarded_pair[1] != '=') || +  !stringp(forwarded_pair[0]) || +  !stringp(forwarded_pair[2])) { +  continue; +  } +  string key = lower_case(forwarded_pair[0]); +  if (case_insensitive) { +  key = lower_case(key); +  } +  if (keys[key]) { +  // If keys contained key add key and value to map_. +  map_[key] = forwarded_pair[2]; +  // Do not try to find another value for this key. +  keys[key] = 0; +  } +  if (!sizeof(keys)) { +  return map_; +  } +  } +  } +  return map_; +  } +  +  string client_scheme() +  //! The scheme used by the client. Typically http or https. If the client +  //! talks https with a proxy and the proxy talkes http with the server, this +  //! function returns the string "https". +  //! Returns 0 if client scheme cannot be found. +  { +  string scheme = find_in_misc_forwarded("proto", true); +  if (!scheme) { +  scheme = port_obj?->prot_name; +  } +  if (scheme) { +  scheme = lower_case(scheme); +  } +  return scheme; +  } +     protected string cached_url_base;       string url_base()    //! Returns the base part of the URL, i.e. what should be added in    //! front of a path in the virtual filesystem to get the absolute    //! URL to the page. The returned string ends with a "/", or is ""    //! if no server base could be found.    //!    //! This function gets the correct host for protocols that handles    //! IP-less hosts.    {    if (!cached_url_base) { -  string tmp; +  string host; +  string scheme;    -  +  // We're looking at the forwarded header... +  register_vary_callback("forwarded"); +  +  // First look at the forwarded header. +  if (misc->forwarded) { +  mapping(string:string) forwarded = +  find_in_misc_forwarded((<"proto", "host">), true); +  scheme = forwarded->proto ? lower_case(forwarded->proto) : 0; +  host = forwarded->host ? forwarded->host : 0; +  } +  +  // Second look at the host header in the request. +  if (!host) {    // We're looking at the host header...    register_vary_callback("host"); -  +  host = misc->host; +  }    -  // First look at the host header in the request. -  if (tmp = misc->host) { -  string scheme = port_obj->prot_name; -  if (has_prefix(tmp, "[")) { +  // Then try the port object. +  if (!scheme) { +  scheme = port_obj->prot_name; +  } +  if (!host) { +  mapping(string:mixed) conf_data = port_obj->conf_data[conf]; +  if (conf_data) { +  host = conf_data->hostname; +  if (host == "*") +  // Use the hostname in the configuration url. +  // Fall back to the numeric ip. +  host = conf->get_host() || port_obj->ip; +  if (port_obj->port != port_obj->default_port) { +  host += ":" + port_obj->port; +  } +  } +  } else { +  string host_no_port; +  int port; +  +  if (has_prefix(host, "[")) {    // IPv6 -  sscanf(tmp, "[%s]:%d", string host, int port); -  if (!port || port == port_obj->default_port) -  cached_url_base = scheme + "://[" + host + "]"; -  else -  cached_url_base = scheme + "://" + tmp; +  sscanf(host, "[%s]:%d", host_no_port, port);    } else { -  int scanres = sscanf(tmp, "%[^:]:%d", string host, int port); -  if ((scanres < 2) || (port == port_obj->default_port)) { -  // Some clients don't send the port in the host header -  // if they've connected to the default port. -  // NOTE: We want the (probable) port number that the client -  // used here; NOT the actual port number, since there -  // may be port remappers in the way. -  // Remove redundant port number. -  cached_url_base = scheme + "://" + host; -  } else { -  cached_url_base = scheme + "://" + tmp; +  sscanf(host, "%[^:]:%d", host_no_port, port);    } -  +  if (port == ([ "http":80, "https":443 ])[scheme]) { +  // Default port. +  port = 0; +  host = host_no_port;    }    }    -  // Then use the port object. -  else if (mapping(string:mixed) conf_data = -  port_obj && port_obj->conf_data[conf]) { -  string host = conf_data->hostname; -  if (host == "*") -  // Use the hostname in the configuration url. -  // Fall back to the numeric ip. -  host = conf->get_host() || port_obj->ip; -  cached_url_base = port_obj->prot_name + "://" + host; -  if (port_obj->port != port_obj->default_port) -  cached_url_base += ":" + port_obj->port; +  if (host) { +  cached_url_base = scheme + "://" + host;    }       // Then try the configuration url. -  else if (conf && sizeof (tmp = conf->get_url())) -  cached_url_base = tmp[..sizeof (tmp) - 2]; // Remove trailing '/'. +  else if (conf && sizeof (host = conf->get_url())) +  cached_url_base = host[..sizeof(host) - 2]; // Remove trailing '/'.       // Lastly use a pathetic fallback. With this the produced urls    // will still be relative, which has some chance of working.    else return cached_url_base = "";       if (string p = misc->site_prefix_path) cached_url_base += p;    cached_url_base += "/";    }    return cached_url_base;    }
Roxen.git/server/base_server/prototypes.pike:2710:       // Charset handling       array(string) output_charset = ({});       void set_output_charset( string|function to, int|void mode )    {   #ifdef DEBUG    if (stringp (to))    // This will throw an error if the charset is invalid. -  Locale.Charset.encoder (to); +  Charset.encoder (to);   #endif       if (object/*(RXML.Context)*/ ctx = RXML_CONTEXT)    ctx->add_p_code_callback ("set_output_charset", to, mode);       if( has_value (output_charset, to) ) // Already done.    return;       switch( mode )    {
Roxen.git/server/base_server/prototypes.pike:2751:    {    string charset;    function(string:string) encoder;    foreach( output_charset, string|function f )    [charset,encoder] = join_charset(charset, f, encoder, 0);    return charset || encoder;    }       protected string charset_name(function|string what)    { -  switch (what) { -  case string_to_unicode: return "ISO10646-1"; -  case string_to_utf8: return "UTF-8"; -  default: return upper_case((string) what); +  if (what == string_to_unicode) return "ISO10646-1"; +  if (what == string_to_utf8) return "UTF-8"; +  return upper_case((string) what);    } -  } +        protected function charset_function(function|string what, int allow_entities)    { -  switch (what) { +  if (functionp(what)) return what; +  switch (upper_case(what)) {    case "ISO-10646-1":    case "ISO10646-1": -  case string_to_unicode: +  case "ISO-10646": +  case "ISO10646":    return string_to_unicode;       case "UTF-8": -  case string_to_utf8: +  case "UTF8":    return string_to_utf8;       default:    // Use entity fallback if content type allows it    function fallback_func =    allow_entities &&    lambda(string char) {    return sprintf("&#x%x;", char[0]);    };       _charset_decoder_func =    _charset_decoder_func || Roxen->_charset_decoder;    return -  _charset_decoder_func(Locale.Charset.encoder((string) what, "", -  fallback_func)) +  _charset_decoder_func(Charset.encoder((string) what, "", fallback_func))    ->decode;    }    }       protected array(string) join_charset(string old,    function|string add,    function oldcodec,    int allow_entities)    {    switch (old && upper_case(old)) {
Roxen.git/server/base_server/prototypes.pike:2853:    if (String.width(what) > 8) {    charset = "UTF-8";    encoder = string_to_utf8;    }    if (encoder)    what = encoder(what);    return replace_charset_placeholder( charset, what, allow_entities );    } else    return ({    0, -  Locale.Charset.encoder((force_charset / "=")[-1])->feed(what)->drain() +  Charset.encoder((force_charset / "=")[-1])->feed(what)->drain()    });    }       void split_query_vars (string query_vars, mapping(string:array(string)) vars)    {    array(string) rests = ({});       foreach (query_vars / "&", string v) {    if(sscanf(v, "%s=%s", string a, string b) == 2)    { -  a = _Roxen.http_decode_string(replace(a, "+", " ")); -  b = _Roxen.http_decode_string(replace(b, "+", " ")); +  // NB: Assume invalidly %-encoded values are unencoded. +  // Fixes [bug 7818]. +  catch { +  a = replace(a, "+", " "); +  a = _Roxen.http_decode_string(a); +  }; +  catch { +  b = replace(b, "+", " "); +  b = _Roxen.http_decode_string(b); +  };    vars[ a ] += ({ b }); -  } else -  rests += ({_Roxen.http_decode_string( v )}); +  } else { +  catch { +  v = _Roxen.http_decode_string( v ); +  }; +  rests += ({ v });    } -  +  }       if (sizeof (rests)) {    string rest = rests * "&";   #ifdef ENABLE_IDIOTIC_STUPID_STANDARD    // This comes from http.pike with the illustrious comment "IDIOTIC    // STUPID STANDARD". I fail to find any standard that says    // anything about this, so nowadays it's disabled by default.    // /mast    rest=replace(rest, "+", "\000");   #endif
Roxen.git/server/base_server/prototypes.pike:3122:    }       // Only declare charset if we have exact knowledge of it. We cannot    // provide a default for other requests since e.g. Firefox will    // complain if it receives a charset=ISO-8859-1 header for text data    // that starts with a UTF-8 BOM.    if (charset)    type += "; charset=" + charset;    }    -  heads["Content-Type"] = type; -  -  if (stringp (file->data)) +  if (stringp (file->data)) { +  if (String.width(file->data) > 8) { +  // Invalid charset header! +  // DWIM! +  eval_status["bad-charset"] = 1; +  file->data = string_to_utf8(file->data); +  type = (type/";")[0] + "; charset=utf-8"; +  }    file->len = sizeof (file->data); -  +  }    -  +  heads["Content-Type"] = type; +    #ifndef DISABLE_BYTE_RANGES    heads["Accept-Ranges"] = "bytes";   #endif    heads["Server"] = replace(roxenp()->version(), " ", "_");    if (file->error == 500) {    // Internal server error.    // Make sure the connection is closed to resync.    heads["Connection"] = "close";    misc->connection = "close";    } else if( misc->connection )
Roxen.git/server/base_server/prototypes.pike:3155:    //if( file->len > 0 || (file->error != 200) )    heads["Content-Length"] = (string)file->len;       if (misc->etag)    heads->ETag = misc->etag;      #ifdef RAM_CACHE    if (!misc->etag && file->len &&    (file->data || file->file) &&    file->error == 200 && (<"HEAD", "GET">)[method] && -  (file->len < conf->datacache->max_file_size)) { +  (file->len < conf->datacache->get_cache_stats()->max_file_size)) {    string data = "";    if (file->file) {    data = file->file->read(file->len);    if (file->data && (sizeof(data) < file->len)) {    data += file->data[..file->len - (sizeof(data)+1)];    }    m_delete(file, "file");    } else if (file->data) {    data = file->data[..file->len - 1];    }
Roxen.git/server/base_server/prototypes.pike:3275:    c->rest_query = rest_query;    c->raw = raw;    c->query = query;    c->not_query = not_query;    c->data = data;    c->extra_extension = extra_extension;       c->realauth = realauth;    c->rawauth = rawauth;    c->since = since; +  +  c->json_logger = json_logger->child();    return c;    }       Stdio.File connection( )    //! Returns the file descriptor used for the connection to the client.    {    return my_fd;    }       Configuration configuration()
Roxen.git/server/base_server/prototypes.pike:3843:    RequestID id);    mapping(string:mixed) set_property (string path, string prop_name,    string|array(SimpleNode) value,    RequestID id);    mapping(string:mixed) remove_property (string path, string prop_name,    RequestID id);       string resource_id (string path, RequestID id);    string|int authenticated_user_id (string path, RequestID id);    multiset(DAVLock) find_locks(string path, -  int(0..1) recursive, +  int(-1..1) recursive,    int(0..1) exclude_shared,    RequestID id);    DAVLock|LockFlag check_locks(string path,    int(0..1) recursive,    RequestID id);    mapping(string:mixed) lock_file(string path,    DAVLock lock,    RequestID id);    mapping(string:mixed) unlock_file (string path,    DAVLock lock,
Roxen.git/server/base_server/prototypes.pike:4000:    //! The user (short) name       string real_name();    //! The real name of the user       int password_authenticate(string password)    //! Return 1 if the password is correct, 0 otherwise. The default    //! implementation uses the crypted_password() method.    {    string c = crypted_password(); -  return !sizeof(c) || crypt(password, c); +  return !sizeof(c) || verify_password(password, c);    }       int uid();    //! A numerical UID, or -1 if not applicable       int gid();    //! A numerical GID, or -1 if not applicable       string shell();    //! The shell, or 0 if not applicable