
    gjb                        d Z ddlZddlZddlZ	 eej
                  fZddlZ G d de	      Z
d Z	 ddlZd Z G d d	e
      Zej                   d
k  r4 ej"                  ej$                  d eej$                        z        Zd Zn2ej#                  ej$                  d eej$                        z        Zd Z G d de	      Z G d de      Z G d de	      Z e       fdZ e       dfdZy# e$ r eZY w xY w# e$ r d ZY w xY w)a  CherryPy dispatchers.

A 'dispatcher' is the object which looks up the 'page handler' callable
and collects config for the current request based on the path_info,
other request attributes, and the application architecture. The core
calls the dispatcher as early as possible, passing it a 'path_info'
argument.

The default dispatcher discovers the page handler by matching path_info
to a hierarchical arrangement of objects, starting at request.app.root.
    Nc                       e Zd ZdZd Zed        Zej                  d        Zed        Zej                  d        Zd Z	y)	PageHandlerz"Callable which sets response.body.c                 .    || _         || _        || _        y Ncallableargskwargs)selfr   r	   r
   s       )/opt/Tautulli/lib/cherrypy/_cpdispatch.py__init__zPageHandler.__init__   s     	    c                 J    t         j                  j                  j                  S )z?The ordered args should be accessible from post dispatch hooks.cherrypyservingrequestr	   r   s    r   r	   zPageHandler.args    s     '',,,r   c                     |t         j                  j                  _        t         j                  j                  j                  S r   r   )r   r	   s     r   r	   zPageHandler.args%   s.    (,  %'',,,r   c                 J    t         j                  j                  j                  S )z?The named kwargs should be accessible from post dispatch hooks.r   r   r   r
   r   s    r   r
   zPageHandler.kwargs*   s     ''...r   c                     |t         j                  j                  _        t         j                  j                  j                  S r   r   r   r
   s     r   r
   zPageHandler.kwargs/   s.    *0  '''...r   c                 b   	  | j                   | j                  i | j                  S # t        $ r} t	        j
                         d   }	 t        | j                   | j                  | j                          # t        j                  $ r t	        j
                         d   t        $ r |w xY ww xY w)N   )
r   r	   r
   	TypeErrorsysexc_infotest_callable_specr   	HTTPError	Exception)r   xs     r   __call__zPageHandler.__call__4   s    
	 4==$));t{{;; 	q!A"4==$))T[[I
 	 %% (llnQ'' 	s!   %(  B.	+A54B.55B**B.N)
__name__
__module____qualname____doc__r   propertyr	   setterr
   r#    r   r   r   r      sg    ,
 - - 
[[- - / / ]]/ /r   r   c                    t        t        j                  j                  dd      }	 t	        |       \  }}}}|r&t        | d      st        j                  |       r|dd }t        |D cg c]  }|df c}      }	d}
d}t               }t        |      D ]  \  }}	 |	||   xx   dz  cc<    |j!                         D ]  }	 |	|xx   dz  cc<    |t'        |xs g        d }t        |xs g       D ]!  \  }}|	||      dk(  s|	||   xx   dz  cc<   # g }g }|	j)                         D ]3  \  }}|dk(  r|j+                  |       |dkD  s#|j+                  |       5 |r/d}|rddj-                  |      z  }t        j.                  d	|
      |s|
dkD  rt        j.                  d	      t        j                  j                  j0                  j2                  xs i }t        |j!                               }t        |j!                               |z
  }|rN|j5                  t        |            rd	}nd}d}|rddj-                  |      z  }t        j.                  ||
      |s|dkD  rt        |      j5                  |      }|r/d}|rddj-                  |      z  }t        j.                  d	|
      t        |      j5                  |      }|r/d}|rddj-                  |      z  }t        j.                  d|
      yyy# t
        $ r< t        | t              r't        | d      rt	        | j                        \  }}}}n Y w xY wc c}w # t        $ r	 |
dz  }
Y w xY w# t"        $ r |dz  }|j%                  |       Y w xY w)ai  Inspect callable and test to see if the given args are suitable for it.

    When an error occurs during the handler's invoking stage there are 2
    erroneous cases:
    1.  Too many parameters passed to a function which doesn't define
        one of *args or **kwargs.
    2.  Too little parameters are passed to the function.

    There are 3 sources of parameters to a cherrypy handler.
    1.  query string parameters are passed as keyword parameters to the
        handler.
    2.  body parameters are also passed as keyword parameters.
    3.  when partial matching occurs, the final path atoms are passed as
        positional args.
    Both the query string and path atoms are part of the URI.  If they are
    incorrect, then a 404 Not Found should be raised. Conversely the body
    parameters are part of the request; if they are invalid a 400 Bad Request.
    show_mismatched_paramsFr#   r   Nr   zMissing parameters: %s,i  )messagei  z"Multiple values for parameters: %sz&Unexpected query string parameters: %s, zUnexpected body parameters: %s)getattrr   r   r   
getargspecr   
isinstanceobjecthasattrr#   inspectismethoddictset	enumerate
IndexErrorkeysKeyErroraddlenitemsappendjoinr    bodyparamsintersection)r   callable_argscallable_kwargsr,   r	   varargsvarkwdefaultsarg	arg_usagevararg_usagevarkw_usageextra_kwargsivaluekeyargs_with_defaultsvalmissing_argsmultiple_argsusager.   body_params	qs_paramserrorextra_qs_paramsextra_body_paramss                              r   r   r   B   s   & %  ":EC	+5h+?(wx Hj)X& ABx40CsAi01ILK5Lm, 5	d1g!# ##% "	"cNaN" s8>r2234HN+ 23'*+q0(+,1,2
 LMoo' &
UA:$QY  %	&  !.,1GGG  g66 |a'  %%""**//66<"Kk&&()KO((*+k9I!!#m"45 E E!xx./G  88[1_ i.55lCG%%'+yy'AB$$S'::  ,99,GG%99%678$$S'::  %5y  h'GHj,I#H$5$56T7E 	 $ 1  	AL	  	"1KS!	"s<   L (MM M%AMMM"!M"%NNc                 2    t        j                  |       d d S )N   )r5   getfullargspec)r   s    r   r1   r1      s    %%h/33r   c                      y r   r*   r   s      r   r   r      s    r   c                   D    e Zd ZdZed        Zej                  d        Zy)LateParamPageHandlera  When passing cherrypy.request.params to the page handler, we do not
    want to capture that dict too early; we want to give tools like the
    decoding tool a chance to modify the params dict in-between the lookup
    of the handler and the actual calling of the handler. This subclass
    takes that into account, and allows request.params to be 'bound late'
    (it's more complicated than that, but that's the effect).
    c                     t         j                  j                  j                  j	                         }| j
                  r|j                  | j
                         |S )z=Page handler kwargs (with cherrypy.request.params copied in).)r   r   r   rC   copy_kwargsupdater   s     r   r
   zLateParamPageHandler.kwargs   s@     !!))00557<<MM$,,'r   c                 P    |t         j                  j                  _        || _        y r   )r   r   r   r
   rd   r   s     r   r
   zLateParamPageHandler.kwargs   s    *0  'r   N)r$   r%   r&   r'   r(   r
   r)   r*   r   r   ra   ra      s3       ]] r   ra   )   r   _c                 V    t        | t              rt        |       dk7  rt        d      y )N   z0The translate argument must be a str of len 256.)r2   strr>   
ValueErrorts    r   validate_translatorro      s-    !S!SVs]BD D &3r   c                 :    t        | t              st        d      y )Nz&The translate argument must be a dict.)r2   r7   rl   rm   s    r   ro   ro      s    !T"EFF #r   c                   .    e Zd ZdZdZ	 defdZd Zd Zy)
Dispatchera  CherryPy Dispatcher which walks a tree of objects to find a handler.

    The tree is rooted at cherrypy.request.app.root, and each
    hierarchical component in the path_info argument is matched to a
    corresponding nested attribute of the root object. Matching handlers
    must have an 'exposed' attribute which evaluates to True. The
    special method name "index" matches a URI which ends in a slash
    ("/"). The special method name "default" may match a portion of the
    path_info (but only when no longer substring of the path_info
    matches some other object).

    This is the default, built-in dispatcher for CherryPy.
    _cp_dispatchNc                 <    t        |       || _        |r|| _        y y r   )ro   	translatedispatch_method_name)r   rv   ru   s      r   r   zDispatcher.__init__  s!    I&"(<D%  r   c                    t         j                  j                  }| j                  |      \  }}|r1|D cg c]  }|j	                  dd       }}t        |g| |_        yt        j                         |_        yc c}w )/Set handler and config for the current request.%2F/N)r   r   r   find_handlerreplacera   handlerNotFound)r   	path_infor   funcvpathr"   s         r   r#   zDispatcher.__call__  sn    ""**''	2e49:qQYYuc*:E:24@%@GO&//1GO ;s   A<c                 6   t         j                  j                  }|j                  }|j                  }| j
                  }|j                  d      j                  d      D cg c]  }|s|	 c}dgz   t              }i }t        |d      r|j                  |j                         d|j                  v r|j                  |j                  d          d|||gg|}	dd }
|
r|
d   }|j                  | j                        }i }t        |	|d      }t        |
      }|jt        |	|d      }|rIt        |d      r=t        |dd	      s0|d
kD  r+|
j                         } ||
      }|
j!                  |       n#|
j                  d       n|
j                  d       t        |
      }||kD  r%t        j"                  dj%                  |            ||k(  r|
j                  d       |d
z  }|}	|	't        |	d      r|j                  |	j                         |z
  }|dk7  rddj'                  d|       z   }nd}|z
  |z
   }|D ]7  }|d|z   z  }||j                  v s|j                  |j                  |          9 j!                  ||	||g       |
rfd}t              d
z
  }t)        |dd      D ]  }|   \  }}}}|t        |d      rm|j*                  }t        |dd	      rTt        |di       }j-                  |d
z   d|||g        |       |_        |j/                  d      |_        ||z
  d fc S t        |dd	      s |       |_        ||k(  rd|_        nd	|_        ||z
  d fc S   |       |_        dg fS c c}w )ak  Return the appropriate page handler, plus any virtual path.

        This will return two objects. The first will be a callable,
        which can be used to generate page output. Any parameters from
        the query string or request body will be sent to that callable
        as keyword arguments.

        The callable is found by traversing the application's tree,
        starting from cherrypy.request.app.root, and matching path
        components to successive objects in the tree. For example, the
        URL "/path/to/handler" might return root.path.to.handler.

        The second object returned will be a list of names which are
        'virtual path' components: parts of the URL which are dynamic,
        and were not used when looking up the handler. These virtual
        path components are passed to the handler as positional
        arguments.
        rz   index
_cp_configrootNr   r#   exposedFr   )r   zlA vpath segment was added.  Custom dispatchers may only remove elements.  While trying to process {0} in {1} c                      t         j                  j                         } D ]:  \  }}}}| j                  |       d|v sddj	                  d|z
         z   | d<   < | S )zKCollapse all object_trail config into cherrypy.request.config.
            tools.staticdir.dirrz   r   tools.staticdir.section)r   configrc   re   rA   )basenameobjconfsegleftfullpathfullpath_lenobject_trails        r   set_confz)Dispatcher.find_handler.<locals>.set_conf  sw     ??'')D -9 E(c4D!(D069!L7,B!CD7ED23E
 Kr   defaultT)r   r   r   appr   rv   stripsplitr>   r4   re   r   r   ru   r0   popr@   CherryPyExceptionformatrA   ranger   insertendswithis_index)r   pathr   r   r   dispatch_namer"   r   nodeconfnode	iternamesr   objnamesubnodepre_lendispatch
index_nameexisting_lencurpathnew_segssegr   num_candidatesrO   	candidate
defhandlerr   r   r   r   s                              @@@r   r{   zDispatcher.find_handler%  s   & ""**kkxx11  $zz#44S9?!QA?7)K8}4&OODOO,#**OOCJJsO,x9:QK	Q<DnnT^^4GHdGT2G)nG"4=* =)U;! "+J&Y7G$$Z0 MM!$ a )nG 00!!'h!7 
 G# a 1D4.OODOO4 ('1Lq !L)A BBw 6|g7MNH 939$cjj(OOCJJw$789
 tXw ?@w z	 \*Q.~r2. $	FA1=a.D)Xw  y),&..
:y%8":|R@D ''A	:tWEG%-ZGN'+}}S'9G$%xw0Fr'JJJ y)U3!)& (,G$ (-G$ (<'+A""EEEI$	FN "RxA @s   $N,N)	r$   r%   r&   r'   rv   punctuation_to_underscoresr   r#   r{   r*   r   r   rr   rr      s,     *
 -15=
2Yr   rr   c                       e Zd ZdZd Zy)MethodDispatcherac  Additional dispatch based on cherrypy.request.method.upper().

    Methods named GET, POST, etc will be called on an exposed class. The
    method names must be all caps; the appropriate Allow header will be
    output showing all capitalized method names as allowable HTTP verbs.

    Note that the containing class must be exposed, not the methods.
    c                 0   t         j                  j                  }| j                  |      \  }}|rBt	        |      D cg c]  }|j                         s| }}d|v rd|vr|j                  d       |j                          dj                  |      t         j                  j                  j                  d<   |j                  j                         }t        ||d      }||dk(  rt        |dd      }|rbt        |d      r%|j                  j!                  |j"                         |D 	cg c]  }	|	j%                  dd       }}	t'        |g| |_        yt        j*                  d	      |_        yt        j,                         |_        yc c}w c c}	w )
rx   GETHEADr/   AllowNr   ry   rz   i  )r   r   r   r{   dirisupperr@   sortrA   responseheadersmethodupperr0   r4   r   re   r   r|   ra   r}   r    r~   )
r   r   r   resourcer   mavailmethr   r"   s
             r   r#   zMethodDispatcher.__call__  sL   ""**++I6% #H=1Q=E=~&"5V$JJL9=59IH%%--g6 >>'')D8T40D|x54.NN))$//: 9>>15#.>>"6t"De"D"*"4"4S"9&//1GO- >" ?s   FF,FN)r$   r%   r&   r'   r#   r*   r   r   r   r     s    2r   r   c                   0    e Zd ZdZddZd Zd Zd Zd Zy)	RoutesDispatcherz'A Routes based dispatcher for CherryPy.c                     ddl }|| _        i | _         |j                  di || _        | j                  j
                  | j                  _        y)zRoutes dispatcher.

        Set full_result to True if you wish the controller and the
        action to be passed on to the page handler parameters. By
        default they won't be.
        r   Nr*   )routesfull_resultcontrollersMappermapperr;   controller_scan)r   r   mapper_optionsr   s       r   r   zRoutesDispatcher.__init__  sD     	&#fmm5n5&*&6&6&;&;#r   c                 b    || j                   |<    | j                  j                  ||fd|i| y )N
controller)r   r   connect)r   r   router   r
   s        r   r   zRoutesDispatcher.connect  s2    !+D%CDCFCr   c                 ,    t        j                  |      r   )r   HTTPRedirect)r   urls     r   redirectzRoutesDispatcher.redirect  s    ##C((r   c                     | j                  |      }|r)t        |      t        j                  j                  _        yt        j                         t        j                  j                  _        y)rx   N)r{   ra   r   r   r   r}   r~   )r   r   r   s      r   r#   zRoutesDispatcher.__call__  sK      +/CD/IH$$,/7/@/@/BH$$,r   c                 
   ddl }t        j                  j                  }|j	                         }| j
                  |_        t        |d      r|j                  |_        |j                  j                  dd      |_        |j                  |_        | j                  |_        | j
                  j                  |      }||_        i }|r|j#                         }| j$                  s$|j'                  dd       |j'                  dd       |j(                  j+                  |       t        j,                  j#                         x|_        dfd}|j.                  }|j0                  }	t        |	d	      r ||	j2                         d
|j,                  v r ||j,                  d
          |j5                  d
      D 
cg c]  }
|
s|
	 }}
|r|j'                         }nd}|D ]9  }d
j7                  |f      |j,                  v s% ||j,                            ; d}|r|j                  d      }| j8                  j                  ||      }|r5t;        |t<              r |       }t        |d	      r ||j2                         |j                  d      }|,t?        ||d      }t        |d	      r ||j2                         n|}|r6d
j7                  |f      |j,                  v r ||j,                            |S c c}
w )z4Find the right page handler, and set request.config.r   Nwsgi_environHostr   actionr   c                 B    d| v r	xs d| d<   j                  |        y )Nr   rz   r   )re   )r   r   r   s    r   mergez,RoutesDispatcher.find_handler.<locals>.merge'  s&    $06=n23KK!r   r   rz   ) r   r   r   r   request_configr   r4   r   environr   gethostschemeprotocolr   matchmapper_dictrc   r   r   rC   re   r   r   r   r   r   rA   r   r2   	classtyper0   )r   r   r   r   r   resultrC   r   r   r   r"   atomslastatomr}   r   r   r   r   s                    @@r   r{   zRoutesDispatcher.find_handler
  s   ""**&&(7N+$11FNoo))&$7!..--""9-#[[]FJJ|T*JJx&f% !) 4 4 66	"
 kkxx4&$//"#**#**S/" &OOC06qA6699;DD 	+Dhh/G#**$cjj)*	+
 L1J))--j*EJj)4!+J:|4*//0ZZ)F!!*fd;7L1',,-$ hh/G#**$cjj)*K 7s   <L L N)F)	r$   r%   r&   r'   r   r   r   r#   r{   r*   r   r   r   r     s!    1<D)COr   r   c                 "     ddl m  fd}|S )Nr   )
xmlrpcutilc                 6    j                  |       }  |       S r   )patched_path)r   next_dispatcherr   s    r   xmlrpc_dispatchz)XMLRPCDispatcher.<locals>.xmlrpc_dispatch_  s    ++I6	y))r   )cherrypy.libr   )r   r   r   s   ` @r   XMLRPCDispatcherr   \  s    '* r   Tc                 *     ddl m  fd}|S )a  Select a different handler based on the Host header.

    This can be useful when running multiple sites within one CP server.
    It allows several domains to point to different parts of a single
    website structure. For example::

        http://www.domain.example  ->  root
        http://www.domain2.example  ->  root/domain2/
        http://www.domain2.example:443  ->  root/secure

    can be accomplished via the following config::

        [/]
        request.dispatch = cherrypy.dispatch.VirtualHost(
            **{'www.domain2.example': '/domain2',
               'www.domain2.example:443': '/secure',
              })

    next_dispatcher
        The next dispatcher object in the dispatch chain.
        The VirtualHost dispatcher adds a prefix to the URL and calls
        another dispatcher. Defaults to cherrypy.dispatch.Dispatcher().

    use_x_forwarded_host
        If True (the default), any "X-Forwarded-Host"
        request header will be used instead of the "Host" header. This
        is commonly added by HTTP servers (such as Apache) when proxying.

    ``**domains``
        A dict of {host header value: virtual prefix} pairs.
        The incoming "Host" request header is looked up in this dict,
        and, if a match is found, the corresponding "virtual prefix"
        value will be prepended to the URL path before calling the
        next dispatcher. Note that you often need separate entries
        for "example.com" and "www.example.com". In addition, "Host"
        headers may contain the port number.
    r   )httputilc                 `   t         j                  j                  }|j                  j                  } |dd      }
r	 |d|      }j	                  |d      }|rj                  ||       }  	|       }|j                  j	                  d      }|r|t        |      d  }||j                  d<   |S )Nr   r   zX-Forwarded-Hostr   )r   r   r   r   r   urljoinr   r>   )r   r   headerdomainprefixr   sectiondomainsr   r   use_x_forwarded_hosts          r   vhost_dispatchz#VirtualHost.<locals>.vhost_dispatch  s    ""**$$#.7FVR( ((;I + ..$$%>?c&kl+G8?GNN45r   )r   r   )r   r   r   r   r   s   ``` @r   VirtualHostr   e  s    N &, r   )r'   stringr   typestype	ClassTyper   AttributeErrorr   r3   r   r   r5   r1   ImportErrorra   version_info	maketranspunctuationr>   r   ro   rk   rr   r   r   r   r   r*   r   r   <module>r     sB  
  
 u'I '& 'TE;P4
4; 0 f!1!1!1C#f&8&8"99";D
 "%C#f&8&8"99";G
A AH'2z '2Tnv nb &0\  !+4 ?g  It  s"   C/ C< /C98C9<DD