o '8_f@sdZddlZddlZddlZddlZddlZddlmZddlZddl m Z m Z ddl m Z dZiZdZdadZdaejddkZdd ZdCd d ZGd d d eZGdddeZGdddeZGdddZGdddeZGdddZ GdddeZ!eddZ"eddZ#eddZ$edd Z%edd!Z&edd"Z'edd#Z(edd$Z)edd%Z*edd&Z+d'a,d(d)Z-d*d+Z.d,d-Z/dDd/d0Z0dDd1d2Z1d3d4Z2dEd6d7Z3dFd8d9Z4d:d;Z5erdd=Z6da7d'a8d?d@Z9dAdBZ:dS)Ga This module is based on a rox module (LGPL): http://cvs.sourceforge.net/viewcvs.py/rox/ROX-Lib2/python/rox/mime.py?rev=1.21&view=log This module provides access to the shared MIME database. types is a dictionary of all known MIME types, indexed by the type name, e.g. types['application/x-python'] Applications can install information about MIME types by storing an XML file as /packages/.xml and running the update-mime-database command, which is provided by the freedesktop.org shared mime database package. See http://www.freedesktop.org/standards/shared-mime-info-spec/ for information about the format of these files. (based on version 0.13) N) BaseDirectory)minidom XML_NAMESPACE) defaultdictz5http://www.freedesktop.org/standards/shared-mime-infocCsddd|jDS)zGet text of XML nodecSsg|]}|jqS) nodeValue).0nrr*/usr/lib/python3/dist-packages/xdg/Mime.py /sz"_get_node_data..)join childNodesstrip)noderrr _get_node_data-srcCs t||S)zGet the MIMEtype object for the given type. This remains for backwards compatibility; calling MIMEtype now does the same thing. The name can either be passed as one part ('text/plain'), or as two ('text', 'plain'). )MIMEtypemediasubtyperrr lookup1s rcsbeZdZdZdfdd ZddZddZd d Zd d Zd dZ ddZ ddZ ddZ Z S)rzClass holding data about a MIME type. Calling the class will return a cached instance, so there is only one instance for each MIME type. The name can either be passed as one part ('text/plain'), or as two ('text', 'plain'). Ncs|durd|vr|dd\}}d|vsJ|}|}zt||fWStyDtt||}||||t||f<|YSw)N/)splitlowertypesKeyErrorsuperr__new___init)clsrrmtype __class__rr rCs    zMIMEtype.__new__cCs||_||_d|_dSN)rr_comment)selfrrrrr r Us zMIMEtype._initcCstjd|j|jd}t|D]<}t|}|durq|j t dD](}| t dp-d}d|tjjv}||jdkrD|t|f|_|d krLdSq$qdS) z>Loads comment for current language. Use get_comment() instead.mime.xmlNcommentlangenrr)ospathrrrrload_data_pathsrparsedocumentElementgetElementsByTagNameNSFREE_NSgetAttributeNSrxdgLocalelangsr&r)r'resourcer/docr*r+goodnessrrr _loadZs zMIMEtype._loadcCs*|jdurdt|f|_||jdS)z;Returns comment for current language, loading it if needed.Nrr)r&strr<r'rrr get_commentis  zMIMEtype.get_commentcCs&tt|}|tvrtt|S|S)z:Returns the canonical MimeType object if this is an alias.) update_cacher=aliasesr)r'srrr canonicalqs  zMIMEtype.canonicalcCs ttddtt|DS)z5Returns a set of Mime types which this inherits from.css|]}t|VqdSr%)r)r trrr |z)MIMEtype.inherits_from..)r@set inheritancer=r>rrr inherits_fromyszMIMEtype.inherits_fromcCs|jd|jS)Nrrr>rrr __str__~zMIMEtype.__str__cCsd|j|jfS)NzMIMEtype(%r, %r)rr>rrr __repr__rKzMIMEtype.__repr__cCst|jt|jASr%)hashrrr>rrr __hash__zMIMEtype.__hash__r%)__name__ __module__ __qualname____doc__rr r<r?rCrIrJrLrN __classcell__rrr#r r<src@s eZdZdS)UnknownMagicRuleFormatN)rPrQrRrrrr rUsrUc@seZdZdZdS)DiscardMagicRuleszGRaised when __NOMAGIC__ is found, and caught to discard previous rules.N)rPrQrRrSrrrr rVsrVc@sNeZdZdZddZedZeddZ ddZ d d Z d d Z d dZ dS) MagicRuleNcCs"||_||_||_||_||_dSr%startvaluemaskwordrange)r'rYrZr[r\r]rrr __init__s  zMagicRule.__init__s(?:~(\d+))?(?:\+(\d+))?\n$c Cs|}|dd\}}|rt|nd}|dd\}}t|}|dkr&ttjddkr9tj|ddd d }nt|dd >t|d}|dd}t||kr_||7}t||ksS|d|||d}}| d rt||kr||7}t||ksw|d|d||dd}}nd}|j |}|st t ||\} } | durt| nd} | durt| nd} |||||| | fS) zjRead a rule from the binary magics file. Returns a 2-tuple of the nesting depth and the MagicRule.>rr=s __NOMAGIC__ rNr-big) byteorder&)readlinerintrVsys version_info from_bytesordlen startswithrule_ending_rematchrUreprgroups) r!fline nest_depthrYlenvaluerZr[endingr\r]rrr from_files8        $   zMagicRule.from_filecCs0|jt|j|j}|jrt||jS|Sr%)rYrkrZr]alsomaxmaxlen)r'lrrr ryszMagicRule.maxlencCs$||r|jr|j|SdSdS)NT)match0rwrnr'bufferrrr rns  zMagicRule.matchc Cst|}t|j}t|jD]P}|j|}||}||kr dS|jrPd}t|D]%}tr9||||j|@} nt|||t|j|@} |t| 7}q)n|||}||jkr^dSqdS)NFrT)rkrZr]rYr[PY3rjchr) r'r}rzrtorBetesticrrr r{s(     zMagicRule.match0cCsd|j|j|j|j|jfS)Nz9MagicRule(start=%r, value=%r, mask=%r, word=%r, range=%r)rXr>rrr rLszMagicRule.__repr__)rPrQrRrwr^recompilerm classmethodrvryrnr{rLrrrr rWs  4 rWc@s@eZdZdZddZddZddZedd Zed d Z d S) MagicMatchAnyzMatch any of a set of magic rules. This has a similar interface to MagicRule objects (i.e. its match() and maxlen() methods), to allow for duck typing. cCs ||_dSr%)rules)r'rrrr r^s zMagicMatchAny.__init__cstfdd|jDS)Nc3s|]}|VqdSr%)rnr rr}rr rEsz&MagicMatchAny.match..)anyrr|rrr rnszMagicMatchAny.matchcCstdd|jDS)Ncss|]}|VqdSr%)ryrrrr rErFz'MagicMatchAny.maxlen..)rxrr>rrr ryrOzMagicMatchAny.maxlenc Cs|d}|ddg}|r:|dkr:z |t|Wn ty&Ynw|d}|r4|dd|r:|dksg}d|i}|D]\}}g}||||f|||d<qB||S)z/Read a set of rules from the binary magic file.r[r)readseekappendrWrvrUfrom_rule_tree) r!rqr depths_rulestree insert_pointsdepthrulesubrulesrrr rv s(          zMagicMatchAny.from_filecCsXg}|D]\}}|r|||_||qt|dkrdSt|dkr(|dS||S)aFrom a nested list of (rule, subrules) pairs, build a MagicMatchAny instance, recursing down the tree. Where there's only one top-level rule, this is returned directly, to simplify the nested structure. Returns None if no rules were read. rNr)rrwrrk)r!rrrrrrr r#s     zMagicMatchAny.from_rule_treeN) rPrQrRrSr^rnryrrvrrrrr rs rc@s@eZdZddZddZddZdd d Zdd d ZddZd S)MagicDBcCstt|_dSr%)rlistbytyper>rrr r^8zMagicDB.__init__c Cst|ds}|}|dkrtd |d}|snS|ddks+|dd d kr0td ||d dd \}}t|}t|}zt |}Wnt y_|j |d t |}Ynw|d ureq|j | ||fqWd d S1s{wYd S)zfz"MagicDB.finalise..TkeyreverseN)alltypesritemsrrxrysort)r'ryr"rrrrrr finaliseXs zMagicDB.finalisedrNc Cs|dur&g}|D]}|j|D] \}}||||fqq|jdddn|j}|D]\} } }| |kr5q+| |kr<dS||rE| Sq+dS)a]Do magic sniffing on some bytes. max_pri & min_pri can be used to specify the maximum & minimum priority rules to look for. possible can be a list of mimetypes to check, or None (the default) to check all mimetypes until one matches. Returns the MIMEtype found, or None if no entries match. NcSrrrrrrr rvrz$MagicDB.match_data..)r)rrrrrn) r'datamax_primin_pripossiblermtrrprioritymimetyperrr match_datahs"  zMagicDB.match_datacCsFt|d}||j}Wdn1swY|||||S)aRead data from the file and do magic sniffing on it. max_pri & min_pri can be used to specify the maximum & minimum priority rules to look for. possible can be a list of mimetypes to check, or None (the default) to check all mimetypes until one matches. Returns the MIMEtype found, or None if no entries match. Raises IOError if the file can't be opened. rN)rrryr)r'r/rrrrqbufrrr rns z MagicDB.matchcCsdt|jS)Nz)rkrr>rrr rLrzMagicDB.__repr__)rrN) rPrQrRr^rrrrnrLrrrr r7s   rc@s<eZdZddZddZddZddZd d Zd d Zd S)GlobDBcCstt|_dS)zPrepare the GlobDB. It can't actually be used until .finalise() is called, but merge_file() can be used to add data before that. N)rrGallglobsr>rrr r^szGlobDB.__init__c Cs|j}t|U}|D]I}|drq |ddd}|dd\}}}t|}t|} t|dkr:|dd} nd} |dkrG|| dq || ||t | fq WddS1s_wYdS) z3Loads name matching information from a globs2 file.#Nrrr,r __NOGLOBS__) rrrlrrfrrkraddtuple) r'r/rrqrrfieldsweight type_namepatternr"flagsrrr rs"    "zGlobDB.merge_filec CsHtt|_tt|_g|_i|_i|_|jD]\}}| }|D]t\}}}d|v}| dr\|dd}d|vs\d|vs\d|vs\|rO|j| ||fn |j|  ||fq"d|vshd|vshd|vr|rldnt j}t jt||d }|j |||fq"|r||f|j|<q"||f|j| <q"q|jjd d d d dS)zzPrepare the GlobDB for matching. This should be called after all files have been merged into it. csz*.r-N*r?r)rTcSs|dt|djfS)Nr-r)rkrrrrr rsz!GlobDB.finalise..)rr)rrexts cased_extsglobsliteralscased_literalsrrrCrlrrrIrfnmatch translater) r'r"rrrrcasedrestre_flagsrrr rs2    zGlobDB.finalisecCs*z t||dWStyYdSw)zTReturn the first match found for a given path, or None if no match is found.rN)next _match_path StopIterationr'r/rrr first_matchs  zGlobDB.first_matchcCst||S)z.TrrrNcSsg|]\}}|qSrr)r rwrrr r szget_type2..)rr)r@r.rrOSErrorr octet_streamrrrsortedrrrkrrnrrr is_text_filer) r/rrmtypes max_weightrrr rrDrrr get_type2sB          r'cCsZzt|d}Wn tyYdSw|t|dWdS1s&wYdS)zGuess whether a file contains text or binary data. Heuristic: binary if the first 32 bytes include ASCII control characters. This rule may change in future versions. .. versionadded:: 1.0 rF N)rr_is_textr)r/rqrrr r$s  $r$cCtdd|D S)Ncs8|]}|dkpd|kodknp|dkVqdS)rcr(Nrr brrr rEs6_is_text..rrrrr r)rOr)cCr*)Ncsr+) Nrr.rrr rEs0r0r1r2rrr r)s cCsNtts#ttatjD]\}}|D] \}}t||qqdat|S)aBRetrieve the set of filename extensions matching a given MIMEtype. Extensions are returned without a leading dot, e.g. 'py'. If no extensions are registered for the MIMEtype, returns an empty set. The extensions are stored in a cache the first time this is called. .. versionadded:: 1.0 T) r@_mime2ext_cache_uptodaterrG_mime2ext_cacherrrr)rrr%r"priorrr get_extensionss  r:c Cs4|d7}t| }|}Wdn1swYtjdd}tj||}t|D])}zt| }|}Wdn1sEwYWnYq/||krXdSq/datjt||}t|d }| |Wdn1szwYd} t tj | | tdrt |t d| dS) aCopy 'package_file' as ``~/.local/share/mime/packages/.xml.`` If package_file is None, install ``/.xml``. If already installed, does nothing. May overwrite an existing file with the same name (if the contents are different)r)Nr(packagesFr zupdate-mime-databasezThe '%s' command returned an error code! Make sure you have the freedesktop.org shared MIME package: http://standards.freedesktop.org/shared-mime-info/)rrr.r/rrr0rsave_data_pathwritespawnlpP_WAITunlink Exception) r package_filerqnew_data package_dirr9rold_datanew_filecommandrrr install_mime_infos:       rHr%)rr)Tr)T);rSr.rrrgrr6r xdg.Localexml.domrr collectionsrr4rrrrrrhr~rrobjectrrrUrArVrWrrrrr"r r r rrrrrrrr@rrrrrr'r$r)r8r7r:rHrrrr sj    Kl=^ y         "   %7