
    g8                     >    d Z ddlZddlZddlZddlZ G d de      Zy)z,Checker for CherryPy sites and mounted apps.    Nc                       e Zd ZdZdZ	 d Zd ZddZdZd Z	d	 Z
d
 Zd Zd Zddddddddddd
Zi Zd Zd Zg Zd Zd Zi Zd Zd Zd Zd Zy)Checkera  A checker for CherryPy sites and their mounted applications.

    When this object is called at engine startup, it executes each
    of its own methods whose names start with ``check_``. If you wish
    to disable selected checks, simply add a line in your global
    config which sets the appropriate method to False::

        [global]
        checker.check_skipped_app_config = False

    You may also dynamically add or replace ``check_*`` methods in this way.
    Tc                 $    | j                          y)zInitialize Checker instance.N)_populate_known_types)selfs    (/opt/Tautulli/lib/cherrypy/_cpchecker.py__init__zChecker.__init__   s    ""$    c                 ,   | j                   rxt        j                  }| j                  t        _        	 t        |       D ]7  }|j	                  d      st        | |      }|s$t        |d      s1 |        9 	 |t        _        yy# |t        _        w xY w)zRun all check_* methods.check___call__N)onwarningsformatwarningdir
startswithgetattrhasattr)r   oldformatwarningnamemethods       r   r   zChecker.__call__   s    77'55%)%7%7H":I %Dx0!(t!4!gfj&A"H	% *:&  *:&s   B B "B /	B BNc                     d|z  S )zFormat a warning.zCherryPy Checker:
%s

 )r   messagecategoryfilenamelinenolines         r   r   zChecker.formatwarning,   s    *W44r
   Fc                    t         j                  j                  j                         D ]  \  }}t	        |t         j
                        s!|j                  s.|dk(  r4|j                  d      j                  d      }|j                  j                         D ]O  }|j                  d      j                  d      }|dt        |       |k(  s5t        j                  d|d|       Q  y)z;Check for App config with sections that repeat script_name. /NThe application mounted at z5 has config entries that start with its script name: )cherrypytreeappsitems
isinstanceApplicationconfigstripsplitkeyslenr   warn)r   snappsn_atomskey	key_atomss         r   4check_app_config_entries_dont_start_with_script_namez<Checker.check_app_config_entries_dont_start_with_script_name3   s    }}))//1 	OGBc8#7#78::Rxxx}**3/Hzz( OIIcN005	^c(m,8MMIKILNOO	Or
   c                 0   t         j                  j                  j                         D ]  \  }}t	        |t         j
                        s!g }|j                  j                         D ]b  \  }}|j                  d      s|j                         D ]8  \  }}dD ].  }|j                  |      s|j                  d|d|d|       0 : d |s|j                  dd|z         t        j                  t        j                  j                  |              y)	z<Check for mounted Applications that have site-scoped config.r!   )zengine.zserver.ztree.zchecker.[z] z = r   zThe application mounted at %r contains the following config entries, which are only allowed in site-wide config. Move them to a [global] section and pass them to cherrypy.config.update() instead of tree.mount().N)r#   r$   r%   r&   r'   r(   r)   r   appendinsertr   r.   oslinesepjoin)	r   r/   r0   msgsectionentriesr2   valuens	            r   'check_site_config_entries_in_app_configz/Checker.check_site_config_entries_in_app_configE   s    }}))//1 	4GBc8#7#78C$'JJ$4$4$6 B %%c*&-mmo B
U!L BA"~~a0 #

,3S%,A !BBBB 

16 9;	;< bjjooc23'	4r
   c                    t         j                  j                  j                         D ]Y  \  }}t	        |t         j
                        s!|j                  r.d|z  }| j                  r|dz  }t        j                  |        y y)z3Check for mounted Applications that have no config.z2The Application mounted at %r has an empty config.z It looks like the config you passed to cherrypy.config.update() contains application-specific sections. You must explicitly pass application config via cherrypy.tree.mount(..., config=app_config)N)
r#   r$   r%   r&   r'   r(   r)   global_config_contained_pathsr   r.   )r   r/   r0   r<   s       r   check_skipped_app_configz Checker.check_skipped_app_config\   sw    }}))//1 	GBc8#7#78::JRO55 J KC
 c"	r
   c           	      p   t         j                  j                  j                         D ]  \  }}t	        |t         j
                        s!|j                  s.|j                  j                         D ]A  }|j                  d      s|j                  d      s&t        j                  d|d|d       C  y)z?Check for App config with extraneous brackets in section names.r6   ]r"   z4 has config section names with extraneous brackets: zR. Config *files* need brackets; config *dicts* (e.g. passed to tree.mount) do not.N)r#   r$   r%   r&   r'   r(   r)   r,   r   endswithr   r.   )r   r/   r0   r2   s       r   check_app_config_bracketsz!Checker.check_app_config_bracketsl   s    }}))//1 	KGBc8#7#78::zz( K>>#&#,,s*;MM BDSJKK	Kr
   c                    t         j                  }t         j                  j                  j	                         D ]  \  }}t        |t         j                        s"||_        |j                  D ]^  }|j                  |dz          |j                  j                  } |dd      s8d} |d      } |d      }|d}nd}	t        j                  j                  |      rR|}	|rd	}t        j                  j                  ||d
d       }
t        j                  j                  |
      rS|d|
dz  }nI|sd}nDt        j                  j                  ||      }	t        j                  j                  |	      s|	d}|	r.t        j                  j                  |	      s|r|dz  }|d|	z  z  }|s?t!        j"                  |d|d|d|       a  y)z4Check Application config for incorrect static paths.z/dummy.htmlztools.staticdir.onFr    ztools.staticdir.rootztools.staticdir.dirNztools.staticdir.dir is not set.z8dir is an absolute path, even though a root is provided.   z0
If you meant to serve the filesystem folder at z$, remove the leading slash from dir.z,dir is a relative path and no root provided.z is not an absolute path.
z3%r (root + dir) is not an existing filesystem path.z
section: [z]
root: z
dir: )r#   requestr$   r%   r&   r'   r(   r0   r)   get_resourcegetr9   pathisabsr;   existsr   r.   )r   rL   r/   r0   r=   confr<   rootr   fulldirtestdirs              r   check_static_pathszChecker.check_static_paths{   s    ""}}))//1 /	CGBc8#7#78GK:: +C$$W}%<=~~)),e4C 67D45C{?"$77==-&)G#(D*,'',,tSW*E#%77>>'#:$' FM)O%PC
 $(%8 !$ +-'',,tS*A')ww}}W'=(/,2C #277>>'+B" #t %79@%A BC  ),gtS'B CU+C	/	Cr
   ztools.response_headers.headerszlog.access_filezlog.error_fileztools.log_headers.onz
log.screenzrequest.show_tracebackszrequest.throw_errorszDcherrypy.tree.mount(profiler.make_app(cherrypy.Application(Root()))))
zserver.default_content_typelog_access_filelog_config_optionslog_filelog_file_not_foundlog_request_headerslog_to_screenshow_tracebacksthrow_errorszprofiler.onc           
      ,   |j                         D ]   \  }}t        |t              r||D ]v  }|| j                  v r,t	        j
                  |d| j                  |   d|d       =|| j                  v sLt	        j
                  |d| j                  |   d|d       x || j                  v r)t	        j
                  |d| j                  |   d       || j                  v st	        j
                  |d| j                  |   d        y)=Process config and warn on each obsolete or deprecated entry.z is obsolete. Use  instead.
section: [rF   z is deprecated. Use z	 instead.N)r&   r'   dictobsoleter   r.   
deprecated)r   r)   r=   rR   ks        r   _compatzChecker._compat   s    #\\^ 	IMGT$% HADMM) '($--*:G'E F doo- '($//!*<g'G HH dmm+MM%,dmmG.D#F G/MM%,doog.F#H I!	Ir
   c                    | j                  t        j                         t        j                  j                  j                         D ];  \  }}t        |t        j                        s!| j                  |j                         = y)r`   N)rf   r#   r)   r$   r%   r&   r'   r(   r   r/   r0   s      r   check_compatibilityzChecker.check_compatibility   s[    X__%}}))//1 	%GBc8#7#78LL$	%r
   c           
      X   dg}|j                  |j                         |j                  |j                         |j                  |j                  j                         |j                  t        j
                  j                         || j                  z  }|j
                  j                         D ]  \  }}|j                  d      }|st        |t              s+|D ]  }|j                  d      }t        |      dkD  s#|d   |vrS|d   dk(  r&|d   |v rd|ddj                  |dd        d	|d
}nd|d|d   d|d
}t        j                  |       }|d   dk(  s|d   t!        t        j"                        vsd|d|d   d|d
}t        j                  |         y )Nwsgir!   .rJ   r   r#   zThe config entry z is invalid; try ra   rF   z is invalid, because the z( config namespace is unknown.
section: [toolsz may be invalid, because the z tool was not found.
section: [)extend	toolboxes
namespacesrequest_classr#   r)   extra_config_namespacesr&   r   r'   rb   r+   r-   r;   r   r.   r   rm   )	r   r0   nsr=   rR   is_path_sectionre   atomsr<   s	            r   	_known_nszChecker._known_ns   s   X
		#-- 
		#..!
		###../
		(//,,-
d*** ZZ--/ 	3MGT%005O:dD#9 3AGGCLE5zA~ 82-  %Qx:5%(b. ()#((59*=w%H !$ 89%(G%M !$
 %MM#."1X0$Qxs8>>/BB 89%(G%M !$ !)c 213	3r
   c                     t         j                  j                  j                         D ]1  \  }}t	        |t         j
                        s!| j                  |       3 y)z9Process config and warn on each unknown config namespace.N)r#   r$   r%   r&   r'   r(   rv   rh   s      r   check_config_namespaceszChecker.check_config_namespaces  sG    }}))//1 	 GBc8#7#78NN3	 r
   c                     t        t              j                         D cg c]  }t        |      t        t              u r|  c} fd} |t
        j                  d        |t
        j                  d        |t
        j                  d        |t
        j                  d        |t
        j                  d       y c c}w )Nc                     t        |       D ]8  }|dk(  r	t        t        | |d             }|v s$|j                  |dz   |z   <   : y )Nbody_paramsrl   )r   typer   known_config_types)obj	namespacer   vtypebr   s       r   traversez/Checker._populate_known_types.<locals>.traverse  sV    C L=(WS$56A:FKD++IOd,BCLr
   rL   responseserverenginelog)varsbuiltinsvaluesr|   strr#   rL   r   r   r   r   )r   xr   r   s   `  @r   r   zChecker._populate_known_types  s    X--/ &1Q49$  &	L 	!!9-""J/(+(+u%!&s   #Cc           	      V   d}|j                         D ]  \  }}t        |t              s||i}|j                         D ]h  \  }}|	| j                  j	                  |d       }t        |      }|s3||k7  s9t        j                  ||||j                  |j                  fz         j  y )Nz[The config entry %r in section %r is of type %r, which does not match the expected type %r.)	r&   r'   rb   r}   rN   r|   r   r.   __name__)	r   r)   r<   r=   rR   re   vexpected_typer   s	            r   _known_typeszChecker._known_types#  s    < $\\^ 		FMGTdD)

 F1=$($;$;$?$?4$HM GE$-)? cQ-:-C-C-E 'E FF		Fr
   c                    | j                  t        j                         t        j                  j                  j                         D ];  \  }}t        |t        j                        s!| j                  |j                         = y)zAAssert that config values are of the same type as default values.N)r   r#   r)   r$   r%   r&   r'   r(   rh   s      r   check_config_typeszChecker.check_config_types2  s_    (//*}}))//1 	*GBc8#7#78cjj)	*r
   c                     t         j                  j                         D ]&  \  }}|dk(  s|dk(  st        j                  d       ( y)zCWarn if any socket_host is 'localhost'.

        See #711.
        zserver.socket_host	localhostzThe use of 'localhost' as a socket host can cause problems on newer systems, since 'localhost' can map to either an IPv4 or an IPv6 address. You should use '127.0.0.1' or '[::1]' instead.N)r#   r)   r&   r   r.   )r   re   r   s      r   check_localhostzChecker.check_localhost;  sE    
 OO))+ 	5DAq((Q+-= 4 5	5r
   )N)r   
__module____qualname____doc__r   r	   r   r   rC   r4   rA   rD   rH   rV   rc   rd   rf   ri   rr   rv   rx   r}   r   r   r   r   r   r
   r   r   r   	   s     
BO%:5
 %*!O$4. K3Cn (H,"$"5%4.9H JI*% !#3J  &&F*5r
   r   )r   r9   r   r   r#   objectr   r   r
   r   <module>r      s"    2 	   }5f }5r
   