#line 57 "/home/travis/build/felix-lang/felix/src/packages/web.fdoc"
  include "web/__init__";
  
  publish """ Implements Basic HTTP Authentication
  """
  class HTTPBasicAuth {
    open HTTPConnection;
    open HTTPRequest;
    open Assoc_list;
    open HTTPResponse;
    open Base64;
    open ServerConfig;
    open HTTPHandler;
  
    publish """
    A default app_handler for implementing Basic Auth. You must supply a function that
    takes a user name and password and returns fru or fals if authenticated. You must
    also supply a realm string which appears in the Authentication Prompt of the browser.
    This app_handler uses a route that applies to all pages
    """
    fun app_handlers(auth_source:(string*string->bool),realm:string) =>
      (Cons (http_handler(http_basic_auth_route,(http_basic_auth(auth_source,realm))),
       Empty[http_handler]));
  
    publish """
    A default route for http auth applies to all pages
    """
    fun http_basic_auth_route(config:server_config,request:http_request) =>
      true;
  
    private fun basic(s:string) =>ltrim s "Basic ";
  
    publish """
    Handler for http_basic_auth if Authorization header supplied by browser attemps to authenticate against auth source.
    If Authorization header not supplied send WWW-Authenticate header
    """
  
  
  
    gen http_basic_auth (auth_source:(string*string->bool),realm:string) (conn:http_connection, request:http_request) =  {
      http_basic_auth (auth_source,realm,"Unauthorized") (conn, request);
  }
  
    gen http_basic_auth (auth_source:(string*string->bool),realm:string,unauth_content:string) (conn:http_connection, request:http_request) =  {
      if match (find (fun(x:string)=>x=="Authorization") request.headers) with
        |Some a => match split(decode(basic(a)),":") with
                        |Cons(n,Cons(p,Empty)) => auth_source(n,p)
                        |_ => false
                      endmatch
         |_       => false
        endmatch do
          set_dirty(conn,false);
          return ;
      else
        val hdrs:assoc_list[string,string] = Cons (("WWW-Authenticate","Basic realm=\""+realm+"\""), Empty[string*string]);
        var us = make_unauthorized(hdrs,unauth_content);
        write(conn,us);
      done
      set_dirty(conn,true);
      return ;
    }
  
  publish """Authentication wrapper for a http_handler function, prcesses HTTP Authentication
  and passes control to handler if Authentication succedes otherwise returns Unauthorized response
  to the browser"""
    proc requires_auth (auth_source:(string*string->bool),realm:string,
                       handler_fn:(http_connection*http_request) -> void)
                      (conn:http_connection, request:http_request ) = {
      http_basic_auth (auth_source,realm) (conn, request);
      if not *conn.dirty do
        handler_fn(conn,request);
      done
    }
  
     proc requires_auth (auth_source:(string*string->bool),realm:string,
                       handler_fn:(http_connection*http_request) -> void,
                       unauthorized_content:string)
                      (conn:http_connection, request:http_request ) = {
      http_basic_auth (auth_source,realm,unauthorized_content) (conn, request);
      if not *conn.dirty do
        handler_fn(conn,request);
      done
    }
  
  
  
  
    gen authorized_user (conn:http_connection, request:http_request) =>
       match (find (fun(x:string)=>x=="Authorization") request.headers) with
        |Some a => match split(decode(basic(a)),":") with
                        |Cons(n,Cons(p,Empty)) => Some n
                        |_ => None[string]
                      endmatch
         |_       => None[string]
        endmatch ;
  
  
  }