a hU@sddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z ddlmZmZmZmZmZmZmZmZmZmZmZmZddlmZddlmZddlm Z ddl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,e-e.Z/e0e1ee1d d d Z2e1e1d d dZ3e0e1dddZ4ede#e$Z5e5e5dddZ6GdddeZ7GdddZ8Gddde9e#Z:GdddZ;Gddde9e#ZGd$d%d%ej?d&d'Z@dS)(N)Path) BinaryIOCallableClassVarDictIterableList NamedTupleOptionalPatternSequenceTupleTypeVar)bus)config) __version__) JsonError JsonObject JsonValueget_boolget_dictget_intget_objvget_strget_strvjson_merge_patch typechecked)accept_languagereturnc Cstd|g}|dD]}|}td||d\}}}zt|pPd}WntylYqYn0|rtd|||||f| d\}}}qnq|j dd d d td |g}|D]&\}} |d krq||vr||qtd|t |S)aLParse the Accept-Language header, if it exists. Returns an ordered list of languages, with fallbacks inserted, and truncated to the position where 'en' would have otherwise appeared, if applicable. https://tools.ietf.org/html/rfc7231#section-5.3.5 https://datatracker.ietf.org/doc/html/rfc4647#section-3.4 zparse_accept_language(%r),z entry %rz;q=g?z adding %r q=%r-cSs|dS)Nr)Zpairr"r"4/usr/lib/python3.9/site-packages/cockpit/packages.pycz'parse_accept_language..Tkeyreversez sorted list is %renz results list is %r) loggerdebugsplitstriplower partitionfloat ValueErrorappend rpartitionsorttuple) rZlocales_with_qentrylocale_ZqstrqZ_regionresultsZ_qr"r"r#parse_accept_languageEs0         r;)versionrcCsddd|dDS)z7Convert a version string to a form that can be compared.css|]}|dVqdS)N)zfill).0partr"r"r# yr%z"sortify_version..)joinr,)r<r"r"r#sortify_versionvsrDrcCs6dD]"}tjtj|dr|SqtddS)zkDetect libexecdir on current machine This only works for systems which have cockpit-ws installed. )z/usr/local/libexecz /usr/libexecz/usr/local/lib/cockpitz/usr/lib/cockpitcockpit-askpasszCould not detect libexecdirz/nonexistent/libexecN)ospathexistsrCr*warning) candidater"r"r#get_libexecdir|s   rLJ)objrcCszt|tr>d|vr0td}|dur0|d|S|dtSt|trZdd|DSt|trrdd|DS|SdS)Nz${libexecdir}/cockpit-askpassrFz ${libexecdir}cSsi|]\}}|t|qSr"patch_libexecdir)r@r'valuer"r"r# r%z$patch_libexecdir..cSsg|] }t|qSr"rO)r@itemr"r"r# r%z$patch_libexecdir..) isinstancestrshutilwhichreplacerLdictitemslist)rNZ abs_askpassr"r"r#rPs     rPc@s>eZdZUeed<eed<dZeeed<dZeeed<dS)Documentdata content_typeNcontent_encodingcontent_security_policy) __name__ __module__ __qualname__r__annotations__rVr`r rar"r"r"r#r]s r]c@seZdZddddZdS)PackagesListenerNrEcCsdS)z+Called when the packages have been reloadedNr"selfr"r"r#packages_loadedsz PackagesListener.packages_loaded)rbrcrdrir"r"r"r#rfsrfcs"eZdZedfdd ZZS) BridgeConfigrQcst|t|dd|_t|ddd|_t|di|_|jsN|jsNt|dt |dd|_ t |d |_ |j sxt|d |jp|j d |_ dS) Nlabel privilegedF)defaultmatchz&must have match rules or be privilegedenvironr"spawnzspawn vector must be non-emptyr) super__init__rrlrrmrrorrrprqname)rhrQ __class__r"r#rss     zBridgeConfig.__init__)rbrcrdrrs __classcell__r"r"rur#rjsrjc@seZdZedddZdS) Conditionrkc CsLz|\\|_|_Wn0tyF}zt|d|WYd}~n d}~00dS)Nz'must contain exactly one key/value pair)r[rtrQr1r)rhrQexcr"r"r#rsszCondition.__init__N)rbrcrdrrsr"r"r"r#rxsrxcs0eZdZeoeeZeedfdd ZZ S)Manifest)rHrQcst|||_t|d|jj|_t|dt|_t|dd|_ t|dd|_ t|dt |_ |j durt|di}|D]@\}}|d krt|d tt|t|j krzt|d |d qzdS) Nrtbridgespriorityrzcontent-security-policy conditionsrequiresZcockpitznon-cockpit requirement listedzrequired cockpit version (z ) not met)rrrsrHrrtrrjr{rr|csprxr~COCKPIT_VERSIONrr[rrDrrV)rhrHrQrrtr<rur"r#rss    zManifest.__init__) rbrcrdrrDrrrrsrwr"r"rur#rzs rzc@seZdZUedZeeed<e ed<e ed<e ed<e ed<dZ eee ee e ffed<dZeee e fed <e d d d Zdd ddZe d ddZe edddZe ee edddZe eedddZdS)Packagez%(po|po\.manifest)\.([^.]+)\.js(\.gz)?PO_JS_REmanifestrtrHr|N translationsfilesrcCs"||_|j|_|j|_|j|_dSN)rrtrHr|)rhrr"r"r#rsszPackage.__init__rEcCs|jdurdSi|_iid|_|jdD]}t||j}|dvrJq,tj|}|r| d}| d}| dd}t d |||||j|d |<q,td d |}t d ||||j|<|j| dd|q,|jds|jd|jd<dS)zEnsure that the package has been scanned. This allows us to defer scanning the files of the package until we know that we'll actually use it. N)po.jspo.manifest.js*)r=z..z manifest.jsonrr8r!zAdding translation %r %r -> %rz.jsz.gz$r}zAdding content %r -> %rz.min.r=rr)rrrHrglobrV relative_torr fullmatchgroupr.rYr*r+resub setdefault)rhfilertZpo_matchbasenamer7Z lower_localer"r"r#ensure_scanneds*       zPackage.ensure_scannedcCsldddddddd}|jjdD],}|}|r"|d\}}}|||<q"ddd|Dd S) Nz'self'z'none'z 'self' data:)z default-srcz connect-srcz form-actionzbase-uriz object-srczfont-srczimg-src; css"|]\}}|d|dVqdS)rrNr")r@kvr"r"r#rB3r%z6Package.get_content_security_policy..z block-all-mixed-content)rrr,r-r/rCr[)rhZpolicyrSr'r8rQr"r"r#get_content_security_policy"s  z#Package.get_content_security_policy)filenamercCs\t|\}}d}|dur d}n|dr2|}|j|}td|t|d|||S)Nz text/plainz text/htmlz loading data from %srb) mimetypesZ guess_type startswithrrHr*r+r]open)rhrr_r`rarHr"r"r# load_file5s   zPackage.load_file)rHlocalesrc Csp||jdusJ|D]F}tt(||j||WdS1sV0YqttdS)Ntext/javascript) rr contextlibsuppressKeyErrorrr]ioBytesIO)rhrHrr7r"r"r#load_translationCs  8zPackage.load_translationrHheadersrcCs^||jdusJ|jdus$J||jvrJtt|dd}|||S||j|SdS)NAccept-Languager})rrrr;rrr)rhrHrrr"r"r# load_pathPs  zPackage.load_path)rbrcrdrcompilerrr rerzrVrintrr rrrsrrr]rr rrrr"r"r"r#rs  - rc@seZdZUejjdddZeee e e ge ffe d<e ee dddZe eeedd d Ze eedd d Ze ee d ddZee dddZeee efdddZdS)PackagesLoadercCstj| Sr)rGrHrI)pr"r"r#r$_r%zPackagesLoader.)z path-existszpath-not-exists CONDITIONSrEccsnztjdVWn ty0tjdVYn0ztjddEdHWntyhdEdHYn0dS)NZ XDG_DATA_HOMEz~/.local/shareZ XDG_DATA_DIRS:)z/usr/local/sharez /usr/share)rGrprrH expanduserr,)clsr"r"r#get_xdg_data_dirsbs  z PackagesLoader.get_xdg_data_dirs)rparentrc Cs|dt|jdtj|jdg}|D]}zt|}WnHtyZYq.Yn4tjy}zt d||WYd}~n d}~00t |t st d|q.t ||}q.t|S)Nz override.jsonz.override.json%s: %sz%%s: override file is not a dictionary)rZ lookup_configrtZDOT_CONFIG_COCKPITjsonloads read_bytesFileNotFoundErrorJSONDecodeErrorr*rJrUrZrrP)rrrZoverride_filesZ override_fileoverrideryr"r"r#patch_manifestns  $   zPackagesLoader.patch_manifestc cs|D]}td|t|dD]}td|zt|}Wn@tjy}z&t d||WYd}~q&WYd}~n d}~00t |t st d|q&|j }| ||}zt||VWq&ty}ztd||WYd}~q&d}~00q&qdS)Nz$Scanning for manifest files under %szcockpit/*/manifest.jsonzConsidering file %srz!%s: json document isn't an objectz%s %s)rr*r+rglobrr read_textrerrorrUrZrrrzrrJ)rZdatadirrrryrr"r"r#load_manifestss$   "   zPackagesLoader.load_manifests) conditionrQrcCs |j|}t|tsdS||SNF)rrUrV)rhrrQZcheck_fnr"r"r#check_conditions  zPackagesLoader.check_condition)rrc Csh|jD]\}z||j|j}Wn(tyFtd|j|jYqYn0|std|j|dSqdS)Nz0 %s: ignoring unknown predicate in manifest: %sz2 hiding package %s as its %s condition is not metFT) r~rrtrQrr*rJrHr+)rhrrZokayr"r"r#check_conditionss   zPackagesLoader.check_conditionsc cstdtt}|D]"}td|j||j|qtdtd| D]\}}t |ddddD]f}z2| |rtd ||j|t |fVWq\Wn t ytd |jYn0td |jqvq\tddS) Nz)Scanning for available package manifests:z %s/manifest.jsonzdone.zSelecting packages to serve:cSs|jSrr|rr"r"r#r$r%z.PackagesLoader.load_packages..Tr&z creating package %s -> %sz1 %s: ignoring package with invalid manifest filez ignoring %s: unmet conditions)r*r+ collections defaultdictr\rrHrtr2r[sortedrrrrJ)rhnamesrrtZ candidatesrKr"r"r# load_packagess$        zPackagesLoader.load_packagesN)rbrcrdrGrHrIrrrrVrboolre classmethodrrrrrrzrobjectrrr rrr"r"r"r#r\s $  rc@seZdZUeed<eeed<eee fed<e ed<d eeeedddZ dd d d Z dd d d Z eed ddZejjdddZejdd ddZejdd ddZee edddZed ddZedZeeedddZdS)!Packagesloaderlistenerpackagessaw_first_reload_hintN)rrcCs$||_|pt|_|d|_dSr)rrrloadr)rhrrr"r"r#rss zPackages.__init__rEcCsBt|j|_tdd|jD|_t dt |jdS)NcSsi|]\}}|t|jqSr")rZr)r@rtpackager"r"r#rRr%z!Packages.load..zPackages loaded: %s) rZrrrrdumpsr[ manifestsr*r+r\rgr"r"r#rsz Packages.loadc Cst|jD]}|j|}g}t|jdi|jdiD]<}tt | |dWdqD1sv0YqDt |ddd |dd|j q dS)NZmenuZtoolsrlZ20rz, Z40)rr itertoolschainrgetvaluesrrrr2printrCrH)rhrtrZ menuitemsr6r"r"r#shows  .z Packages.showcsfdd}t|S)Nc3s.tjdddD]}|jjEdHqdS)NcSs|j Srrrr"r"r#r$r%zDPackages.get_bridge_configs..yield_configs..)r')rrrrr{rrgr"r# yield_configssz2Packages.get_bridge_configs..yield_configs)r5)rhrr"rgr#get_bridge_configss zPackages.get_bridge_configssz{}rkcCs ||jdur|jdSr)rrrirgr"r"r#reloads zPackages.reloadcCs|jr|d|_dS)NT)rrrgr"r"r# reload_hintszPackages.reload_hint)ri18nrc Cstdg}|rtt|dd}|jD]t\}}|dvr>q,|d|}|j6|jdkrnt |j }n |j }Wdn1s0Y| |q,| d|j dttd |d S) NzServing /manifests.jsrr})ZstaticZbase1rgzipsh (function (root, data) { if (typeof define === 'function' && define.amd) { define(data); } if (typeof cockpit === 'object') { cockpit.manifests = data; } else { root.manifests = data; } }(this, s)) r)r*r+r;rrr[rr^r`r decompressreadr2rencoder]rrrC) rhrrchunksrrtr translationr^r"r"r#load_manifests_jss&   (    zPackages.load_manifests_jscCs tdtt|jdS)NzServing /manifests.jsonzapplication/json)r*r+r]rrrrrgr"r"r#load_manifests_json,s zPackages.load_manifests_jsonz /(?:([^/]+)/)?((?:[^/]+/)*[^/]+)rcCstd||j|}|dur.td||\}}|durT|j|||S|dkrj|j|ddS|dkr|j|ddS|dkr| St dS) Nzpackages: serving %szInvalid HTTP path z manifests.jsF)rzmanifests-i18n.jsTzmanifests.json) r*r+PATH_RErr1groupsrrrrr)rhrHrroZ packagenamerr"r"r#r6s   zPackages.load_path)NN) rbrcrdrrer rfrrVrrrsrrr rjrrZ InterfaceZPropertyrZMethodrrrr]rrrrrrr"r"r"r#rs&    %rzcockpit.Packages)Z interface)Arr functoolsrrrrZloggingrrGrrWpathlibrtypingrrrrrrr r r r r rZcockpit._vendor.systemd_ctypesrr}r_versionrZjsonutilrrrrrrrrrrrZ getLoggerrbr* lru_cacherVr;rDrLrMrPr]rfrZrjrxrzrrZObjectrr"r"r"r#sB 8   4 0 {s