
    g5d                        d dl Z d dlZd dlZd dlZd dlZd dlmZmZ d dlm	Z	 d dl
Z
d dl
mZ d dl
mZ d ZdZi ded	d fd
ed	dfdeddfdeddfdeddfdedd fdedd fdeddfdeddfdeddfdeddfdeddfdeddfdeddfdedd fdeddfdeddfi d edd fd!edd fd"eddfd#ed$d%fd&edd fd'eddfd(eddfd)edd*fd+eddfd,eddfd-ed$d.fd/edd0fd1ed	d2fd3ed	dfd4ed	d5fd6ed	d5fd7ed	dfi d8ed	d fd9ed:d;fd<ed:d=fd>ed	d?fd@ed	dfdAed	dBfdCed	dfdDed	d5fdEed$dFfdGed$d5fdHed	d5fdIed	dBfdJed	d5fdKed$dLfdMed	d fdNedOdfdPedOdfi dQedOdfdRed$d fdSed	d fdTed	d fdUed	dfdVed$dWfdXed	d fdYed	d fdZed	d fd[ed	g g d\fd]ed	d^fd_ed	dfd`ed	dafdbed	dfdced	ddfdeed	ddfdfed	d5fi dged	d5fdhed	g difdjed	g fdked	g dlfdmed	d;fdned	d5fdoed	dfdped	dfdqed	dfdred	dsfdted	dfdued$dvfdwed	d fdxed	dyfdzed	d5fd{ed	d5fd|ed	d}fi d~ed	dfded	dfded	d fded	dfded	dfded	d fded	dfded	d;fded	dfded	dfded	d;fded	dfded:dfded$dfded	d5fded	d5fded	d5fi ded	d5fded	dfded:dfded$dfded:dfded:dfded	d fded:d fded:dfdedd fdeddfdeddfdedd5fdeddfdeddfdedd fded$dfi ded:d5fded:d%fded:d5fded:d5fded:d fded:dfded:d fded:d fded:dfded:d fded:dfded:dfded:d5fded:dfded:d fded:d fded$d fi ded	d fded:dfded:d5fded:dfded:d5fded$dfded	d fded$dfded	dfded	d fded	d fded:dfded	d.fded	d5fded$d fded$d5fded$d5fed:d?fed$d fed$dfed$dfed	d fed$dfed$d fed$d5fed	d5fdҜ	Zg dӢZdqgZg dԢZg dբZddgZdadag dآZg d٢Zdڄ ZddۄZdd܄Zdd݄Z  G dބ de!      Z"y)    N)	ConfigObj
ParseError)	make_hash)helpers)loggerc                 r    t        | t              r| j                         dv rd} t        t	        |             S )z,
    Casts a config value into a 0 or 1
    ) 0falsefnonoffr   )
isinstancestrlowerintboolvalues    /opt/Tautulli/plexpy/config.pybool_intr      s1     %;;=EEEtE{    z
config.iniALLOW_GUEST_ACCESSGeneralDATE_FORMATz
YYYY-MM-DDPMS_CLIENT_IDPMSr	   PMS_IDENTIFIERPMS_IPz	127.0.0.1PMS_IS_CLOUDPMS_IS_REMOTEPMS_LANGUAGEPMS_LOGS_FOLDERPMS_LOGS_LINE_CAPi  PMS_NAMEPMS_NAME_OVERRIDEPMS_PORTi~  	PMS_TOKENPMS_SSLPMS_URLPMS_URL_OVERRIDEPMS_URL_MANUALPMS_USE_BIFPMS_UUIDPMS_TIMEOUTAdvanced   PMS_PLEXPASSPMS_PLATFORMPMS_VERSIONPMS_UPDATE_CHANNELplexPMS_UPDATE_DISTROPMS_UPDATE_DISTRO_BUILDPMS_UPDATE_CHECK_INTERVAL   PMS_WEB_URLzhttps://app.plex.tv/desktopTIME_FORMATzHH:mmANON_REDIRECTANON_REDIRECT_DYNAMIC   API_ENABLEDAPI_KEYAPI_SQLBUFFER_THRESHOLD
Monitoring
   BUFFER_WAITi  BACKUP_DAYS   
BACKUP_DIRBACKUP_INTERVAL   	CACHE_DIRCACHE_IMAGESCACHE_SIZEMB    CHECK_DOCKER_MOUNTCHECK_GITHUBCHECK_GITHUB_INTERVALCHECK_GITHUB_ON_STARTUPCHECK_GITHUB_CACHE_SECONDSi  CLEANUP_FILESCLOUDINARY_CLOUD_NAME
CloudinaryCLOUDINARY_API_KEYCLOUDINARY_API_SECRETCONFIG_VERSIONDO_NOT_OVERRIDE_GIT_BRANCHENABLE_HTTPS
EXPORT_DIREXPORT_THREADS   FIRST_RUN_COMPLETE	FREEZE_DBGET_FILE_SIZESGET_FILE_SIZES_HOLD)section_idsrating_keys
GIT_BRANCHmasterGIT_PATH
GIT_REMOTEorigin	GIT_TOKENGIT_USERTautulliGIT_REPOGROUP_HISTORY_TABLESHISTORY_TABLE_ACTIVITYHOME_SECTIONS)current_activitywatch_statslibrary_statsrecently_addedHOME_LIBRARY_CARDSHOME_STATS_CARDS)
top_moviespopular_moviestop_tv
popular_tv	top_musicpopular_musiclast_watchedtop_libraries	top_userstop_platformsmost_concurrentHOME_REFRESH_INTERVALHTTPS_CREATE_CERT
HTTPS_CERTHTTPS_CERT_CHAIN	HTTPS_KEYHTTPS_DOMAIN	localhostHTTPS_IPHTTPS_MIN_TLS_VERSIONzTLSv1.2HTTP_BASIC_AUTHHTTP_ENVIRONMENT
productionHTTP_HASH_PASSWORDHTTP_HASHED_PASSWORD	HTTP_HOSTz0.0.0.0HTTP_PASSWORD	HTTP_PORTi  
HTTP_PROXY	HTTP_ROOTHTTP_USERNAMEHTTP_PLEX_ADMINHTTP_BASE_URLHTTP_RATE_LIMIT_ATTEMPTS!HTTP_RATE_LIMIT_ATTEMPTS_INTERVALi,  HTTP_RATE_LIMIT_LOCKOUT_TIMEHTTP_THREAD_POOL	INTERFACEdefaultIMGUR_CLIENT_IDJOURNAL_MODEWALLAUNCH_BROWSERLAUNCH_STARTUPLOG_BLACKLISTLOG_BLACKLIST_USERNAMESLOG_DIRLOGGING_IGNORE_INTERVALx   METADATA_CACHE_SECONDSi  MOVIE_WATCHED_PERCENTU   MUSIC_WATCHED_PERCENTMUSICBRAINZ_LOOKUPMONITOR_PMS_UPDATESMONITORING_INTERVAL<   NEWSLETTER_AUTH
NewsletterNEWSLETTER_PASSWORDNEWSLETTER_CUSTOM_DIRNEWSLETTER_INLINE_STYLESNEWSLETTER_TEMPLATESnewslettersNEWSLETTER_DIRNEWSLETTER_SELF_HOSTEDNOTIFICATION_THREADS   NOTIFY_CONSECUTIVE"NOTIFY_CONTINUED_SESSION_THRESHOLD'NOTIFY_GROUP_RECENTLY_ADDED_GRANDPARENT"NOTIFY_GROUP_RECENTLY_ADDED_PARENTNOTIFY_UPLOAD_POSTERSNOTIFY_RECENTLY_ADDED_DELAY!NOTIFY_RECENTLY_ADDED_GRANDPARENTNOTIFY_RECENTLY_ADDED_UPGRADENOTIFY_REMOTE_ACCESS_THRESHOLDNOTIFY_CONCURRENT_BY_IPNOTIFY_CONCURRENT_IPV6_CIDRz/64NOTIFY_CONCURRENT_THRESHOLDNOTIFY_NEW_DEVICE_INITIAL_ONLY"NOTIFY_SERVER_CONNECTION_THRESHOLDNOTIFY_SERVER_UPDATE_REPEATNOTIFY_PLEXPY_UPDATE_REPEATNOTIFY_TEXT_EVALPLEXPY_AUTO_UPDATEREFRESH_LIBRARIES_INTERVAL   REFRESH_LIBRARIES_ON_STARTUPREFRESH_USERS_INTERVALREFRESH_USERS_ON_STARTUPSESSION_DB_WRITE_ATTEMPTS   SHOW_ADVANCED_SETTINGSSYNCHRONOUS_MODENORMALTHEMOVIEDB_APIKEY e9a6655bae34bf694a0f3e33338dc28eTHEMOVIEDB_LOOKUPTVMAZE_LOOKUPTV_WATCHED_PERCENTUPDATE_DB_INTERVALUPDATE_SHOW_CHANGELOGUPGRADE_FLAGVERBOSE_LOGSVERIFY_SSL_CERT)	WATCHED_MARKERWEBSOCKET_MONITOR_PING_PONGWEBSOCKET_CONNECTION_ATTEMPTSWEBSOCKET_CONNECTION_TIMEOUTWEEK_START_MONDAY
JWT_SECRETJWT_UPDATE_SECRETSYSTEM_ANALYTICSSYS_TRAY_ICON)	_APITOKEN_TOKEN_KEY_SECRET	_PASSWORD_APIKEY_ID_HOOK)ra   rd   ri   r$   rJ   rM   r^   r   r   r   r   r   r   r   r   r   r   r]   r   r   r   r   r)   r   )r   rj   rg   r   F)Er>   rB   rH   rJ   rK   rD   rG   rM   rS   rY   rZ   rW   r   r^   rg   ri   rj   rl   rw   r   rr   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r$   r&   r(   r*   r6   r:   r8   r9   r+   r5   r<   r   r   r   r=   r   r   )$r   r?   rA   rN   rR   r]   rc   rp   rq   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r-   r   r   r   r   r   r   c                     | a y N)IS_IMPORTINGr   s    r   set_is_importingr   U  s    Lr   c                 X    | r&t         ry t        j                  t        | |d      a y d a y )Nconfigbackup)targetkwargs)IMPORT_THREAD	threadingThreadimport_tautulli_configr   s     r   set_import_threadr  Z  s.    !((0F;AV0TV r   c                    t         rt        j                  d       y|r5t        j                  d       t	               st        j
                  d       y	 t        | d      }t        j                  d|        t        d       t        D ]  }t        ||        t        j                  st        j                  rt        D ]  }t        ||        t        j                  j                  j!                  |j                         t        j                  j#                          t        j                  d	       t%        d        t        d       d
t        _        y #  t        j
                  d       Y yxY w)NzTautulli Config :: Another Tautulli config is currently being imported. Please wait until it is complete before importing another config.Fz=Tautulli Config :: Creating a config backup before importing.zSTautulli Config :: Failed to import Tautulli config: failed to create config backupT)	is_importzWTautulli Config :: Failed to import Tautulli config: error reading imported config filez4Tautulli Config :: Importing Tautulli config '%s'...z3Tautulli Config :: Tautulli config import complete.restart)r   r   warninfomake_backuperrorConfigr   _DO_NOT_IMPORT_KEYSdelattrplexpyDOCKERSNAP_DO_NOT_IMPORT_KEYS_DOCKERCONFIG_configmergewriter  SIGNAL)r   r   imported_configkeys       r   r  r  e  s    X 	YST}LLno 48
 KKFOT # &%&}}- 	*COS)	* MM 7 78
MM
KKEFdU FM/nos   E E2c           	         |r$dj                  t        j                               }n#dj                  t        j                               }t        j                  j
                  }t        j                  j                  ||      }t        j                  j                  |      st        j                  |       t        j                  j                          t        j                  t        j                  |       | rt        j                         }t        j                   |      D ]  \  }}}|D 	cg c]4  }	|	j#                  d      st        j                  j                  ||	      6 }
}	|
D ]Y  }t        j$                  |      j&                  |t        j                  j(                  dz  z
  k  sD	 t        j*                  |       [  |t        j2                  |      v r*t/        j4                  dt        j                  d	|       y
t/        j0                  dt        j                  d	|       yc c}	w # t,        $ r%}t/        j0                  d|d|       Y d}~d}~ww xY w)zC Makes a backup of config file, removes all but the last 5 backups zconfig.backup-{}.sched.inizconfig.backup-{}.iniz
.sched.iniiQ z$Tautulli Config :: Failed to delete z from the backup folder: Nz*Tautulli Config :: Successfully backed up z to Tz$Tautulli Config :: Failed to backup F)formatr   nowr  r  rJ   ospathjoinexistsmakedirsr  shutilcopyfileCONFIG_FILEtimewalkendswithstatst_mtimerH   removeOSErrorr   r	  listdirdebug)cleanup	schedulerbackup_filebackup_folderbackup_file_fpr  rootdirsfilesr   	ini_filesfile_es                r   r  r    s    299'++-H,33GKKMBMM,,MWW\\-=N 77>>-(
M"
MM
OOF&&7iik!#!7 	wD$8=Z1LAYdA.ZIZ" w775>**S6==3L3Lu3T-TTw		%(w	w bjj//VM_M_almnvGYGY[fgh [
 # wlqst%uvvws$   0H6"H62H;;	I)I$$I)c                   h     e Zd ZdZddZd Zd Zd Zd Zd Z	 fdZ
 fd	Z fd
Zd Zd Z xZS )r
  z4 Wraps access to particular values in a config file c                    || _         	 t        | j                   d      | _        t        D ]  }| j                  |        |s!| j                          | j                          yy# t        $ r}t	        j
                  d|        d}~ww xY w)z/ Initialize the config with values from a file zutf-8encodingz7Tautulli Config :: Error reading configuration file: %sN)
_config_filer   r  r   r   r	  _CONFIG_DEFINITIONScheck_setting_upgrade
_blacklist)selfconfig_filer  r6  r  s        r   __init__zConfig.__init__  s    '	$T%6%6IDL
 ' 	$Cs#	$MMOOO   	LLRTUV	s   A% %	B
.BB
c                    t               }| j                  j                         D ]  \  }}|j                         D ]  \  }t        |t              st        |j                               dkD  s4j                         t        vsKt        fdt        D              sd|j                  |j                                  t        j                  j                  |       y)z9 Add tokens and passwords to blacklisted words in logger r   c              3   B   K   | ]  }|j                         v   y wr   )upper).0bksubkeys     r   	<genexpr>z$Config._blacklist.<locals>.<genexpr>  s     Aq[]"BVAqs   N)setr  itemsr   r   lenstriprE  _WHITELIST_KEYSany_BLACKLIST_KEYSaddr   _BLACKLIST_WORDSupdate)r@  	blacklistr  subkeysr   rH  s        @r   r?  zConfig._blacklist  s    E	 LL..0 	1LC!( 1eS)c%++-.@1.DLLN/9cAqapAq>qMM%++-01	1 	&&y1r   c                     |j                         }|j                         }t        |   }t        |      dk(  r|\  }}}n|\  }}}}|||||fS )NrI   )rE  r   r<  rL  )	r@  namer  ini_key
definitiondefinition_typesectionr   _s	            r   _definezConfig._define  sY    jjl**,(-
z?a0:-OWg3=0OWaOWgw>>r   c                 @    || j                   vri | j                   |<   yy)z/ Check if INI section exists, if not create it TF)r  )r@  r[  s     r   check_sectionzConfig.check_section  s"    $,,&$&DLL!r   c                     | j                  |      \  }}}}}| j                  |       	  || j                  |   |         }|S # t        $ r  ||      }|| j                  |   |<   Y |S w xY w)zC Cast any value in the config to the right type or use the default )r]  r_  r  	Exception)r@  r  rZ  r[  rX  r   my_vals          r   r=  zConfig.check_setting  s    :>,,s:K7_gw7#	4$T\\'%:7%CDF   	4$W-F-3DLL!'*	4s   A #A+*A+c                 @   t        d      }| j                  |_        | j                  j	                         D ].  \  }}||vri ||<   |j	                         D ]  \  }}|||   |<    0 t
        D ]K  }| j                  |      \  }}}}}	| j                  |       ||vri ||<   | j                  |   |   ||   |<   M t        j                  d       	 |j                          | j                          y# t        $ r }
t        j                  d|
       Y d}
~
5d}
~
ww xY w)zF Make a copy of the stored config and write it to the configured file zUTF-8r9  z0Tautulli Config :: Writing configuration to filez7Tautulli Config :: Error writing configuration file: %sN)r   r;  filenamer  rK  r<  r]  r=  r   r  r  IOErrorr	  r?  )r@  
new_configr  rU  rH  r   rZ  r[  rX  r   r6  s              r   r  zConfig.write  s1   0
"//
 !LL..0 	0LC*$"$
3!( 0*/
3'0	0 ' 	JC>Bll3>O;C'7Gs#j(&(
7#+/<<+@+IJw(	J 	FG	W 	  	WLLRTUVV	Ws   C4 4	D=DDc                 x    t        j                  d|      st        t        |   |      S | j                  |      S )z
        Returns something from the ini unless it is a real property
        of the configuration object or is not all caps.
        z[A-Z0-9_]+$)rematchsuperr
  __getattr__r=  )r@  rW  	__class__s     r   rk  zConfig.__getattr__  s6    
 xx-2488%%d++r   c                     t        j                  d|      st        t        |   ||       |S | j                  |      \  }}}}} ||      | j                  |   |<   | j                  |   |   S )zo
        Maps all-caps properties to ini values unless they exist on the
        configuration object.
        [A-Z_]+$)rh  ri  rj  r
  __setattr__r]  r  )	r@  rW  r   r  rZ  r[  rX  r   rl  s	           r   ro  zConfig.__setattr__  sn    
 xxT*&$+D%8L>Bll4>P;C'7G-<U-CDLL!'*<<(11r   c                     t        j                  d|      st        t        |   |      S | j                  |      \  }}}}}| j                  |   |= y)z>
        Deletes a key from the configuration object.
        rn  N)rh  ri  rj  r
  __delattr__r]  r  )r@  rW  r  rZ  r[  rX  r   rl  s          r   rq  zConfig.__delattr__'  sO     xxT*2488>Bll4>P;C'7GW%g.r   c                     |j                         D ]4  \  }}| j                  |      \  }}}}} ||      | j                  |   |<   6 y)zN
        Given a big bunch of key value pairs, apply them to the ini.
        N)rK  r]  r  )	r@  r   rW  r   r  rZ  r[  rX  r   s	            r   process_kwargszConfig.process_kwargs1  sP     "<<> 	DKD%>Bll4>P;C'7G-<U-CDLL!'*	Dr   c                    | j                   dk(  rd| _         | j                   dk(  r| j                  rFdj                  | j                        j                  d      }d|v r|j	                  d       || _        | j
                  rFdj                  | j
                        j                  d      }d|v r|j	                  d       || _        d| _         | j                   dk(  rd| _         | j                   dk(  r| j                  d	k(  rd| _        d
| _         | j                   d
k(  rd| _         | j                   dk(  rd| _        d| _         | j                   dk(  r+| j                  j                         dk(  rd| _        d| _         | j                   dk(  rd| _         | j                   dk(  rd| _         | j                   dk(  r| j                  dk(  rd| _
        d| _         | j                   dk(  rd| _        d| _        d| _         | j                   dk(  r(| j                  j                  dd      | _        d| _         | j                   dk(  r"t        | j                  d      | _        d| _         | j                   dk(  rd| _         | j                   dk(  rt         j"                  rd| _        d| _         | j                   dk(  r)| j                  r| j                  d	k7  rd| _        d| _         | j                   dk(  rt         j(                  rd| _        d| _         | j                   dk(  rS| j                  }d |v r$|j+                  d       }|j-                  |d!       n|j/                  d!       || _        d"| _         | j                   d"k(  rF| j0                  d#kD  r0t3        | j0                  d$z        | j0                  d$z  dkD  z   | _        d%| _         | j                   d%k(  rG| j4                  r&| j6                  st9        | j4                        | _        d| _        d| _        d&| _         | j                   d&k(  r| j<                  rd| _        d'| _         | j                   d'k(  r'| j@                  s| j                  sd| _         d(| _         y)y))*zZ
        Upgrades config file from previous verisions and bumps up config version
        r   r@   r	   z, watch_statisticslibrary_statisticsr   rI   /   r   rL   drzoidberg33JonnyWong16   r`   	   plexpassbetarF   rn      zhttp://www.nullrefer.com/?zhttps://www.nullrefer.com/?r         r2   T      r   r      r;   r               N)!r[   rx   r  splitr(  rw   r   r   rm   r   r6   ro   r>   replacemaxrD   r  r  r   r   r  indexinsertappendrS   r   r   r   r   r   r/   ra   r?   )r@  home_stats_cardshome_library_cardstop_users_indexs       r   r>  zConfig._upgrade9  s2    !#"#D!#$$#%774+@+@#A#G#G#M %)99$++,>?,<D)&&%'WWT-D-D%E%K%KD%Q"'+==&--.BC.@D+"#D!#"#D!#~~$!#"#D!#"#D!#'(D$"#D!#}}""$6 -"#D!#"#D!#"#D!#&&*4*0'"$D"$&DM&DM"$D"$!%!3!3!;!;<X<Y"[D"$D"$$'(=(=r$BD!"$D"$"$D"$}}*+'"$D"$~~$..C"7)-&"$D"${{*+'"$D"$#44.."2"8"8"E ''I ''8$4D!"$D"$))B.D66"<=55:Q>@ *
 #%D"$!!$*C*C%.t/A/A%B"&'D#()D%"$D"$}}*+'"$D"$--d6H6H-.*"$D	 %r   )F)__name__
__module____qualname____doc__rB  r?  r]  r_  r=  r  rk  ro  rq  rs  r>  __classcell__)rl  s   @r   r
  r
    s?    >
2?	>,2/DF%r   r
  )NF)FF)#r  rh  r   r#  r   	configobjr   r   hashing_passwordsr   r  r   r   r   FILENAMEr   r   dictlistr<  rP  rN  r  r  _DO_NOT_DOWNLOAD_KEYSr   r   SETTINGSCHECKED_SETTINGSr   r  r  r  objectr
   r   r   <module>r     s    
 	    + '    d3	1-dCL1d c5"%d sE2&	d
 sE;'d S%Od c5!_d S%$d UB'd #ud+d eR d #ub)d eU#d #ub!d UAd  UB!d" eR(#d$ sE1o%d& C?'d( eR )d* CR(+d, S%O-d. S%$/d0 C#1d2 3v.3d4 #ub)5d6 UB/7d8  #z2!69d: C =>;d< CG,=d> c9b)?d@ c9a0AdB CA&CdD Y#EdF Y"GdH lB/IdJ Cs+KdL CA&MdN 3	2&OdP Y*QdR #y"%SdT S)Q'UdV S*b)WdX 3
A.YdZ S)Q'[d\ c9a0]d^ Y2_d` !3
D"9adb c9a(cdd c<4edf 3b1gdh c<4idj sJ*kdl !3	1"5mdn S)Q'odp 3	2&qdr sJ*sdt 3	1-udv #y!$wdx sIq)ydz D)RPR-ST{d| 3	8,}d~ i$d@ 3	8,AdB #y"%CdD i,EdF i,GdH S)Q/IdJ sIq1KdL dI'mnMdN 4B/OdP y +k lQdT c9b1UdV #y!,WdX 3	2&YdZ i,[d\ #y"%]d^ S)[1_d` i-adb c:y9cdd Y*edf i6gdh 3	1-idj S)Q/kdl #y),mdn c9b)odp #y$'qdr 3	1%sdt #y"%udv c9b)wdx Y*ydz c9b){d| i 4}d~ (#y#)>d@ #S)S$9AdB i,CdD #y),EdF \2.GdH S*e,IdJ sIq)KdL sIq)MdN c9a(OdP Y2QdR Y#SdT \37UdV sJ5WdX c<4YdZ c<4[d\ 3	1-]d^ Cq1_d` Cr2adb \1-cdd Cr2edf c<4gdh lA 6idj S,>kdl sL"-mdn sL!4odp S*a0qdr 3a0sdt )3b*Audv .\1/Ewdx )3a*@ydz c<3{d| "Cs#;}d~ (#|Q)?d@ $c<%;AdB %sL"&=CdD \15EdF "Cu#=GdH "Cq#9IdJ %sL!&<KdL )3b*AMdN "Cq#9OdP "Cq#9QdR j!,SdT 3	1-UdV !3b"9WdX #S,$:YdZ sL"5[d\ lA 6]d^  #z1!5_d` sIq1adb j(3cdd #y*LMedf #y!,gdh c9a(idj 3b1kdl 3	2.mdn c9a0odp S*a(qdr S*a(sdt *a0udv L!,$'Q#7&):q%9%(*a$8y!,
B'"J2j!,9a(Gd L e-     FP% P
'T"NI%V I%r   