4 from xml
.parsers
import expat
5 from xml
.dom
import XML_NAMESPACE
9 home_mime
= os
.path
.join(os
.environ
['HOME'], '.mime')
10 user_override
= os
.path
.join(home_mime
, 'packages', 'Override.xml')
12 FREE_NS
='http://www.freedesktop.org/standards/shared-mime-info'
16 types
[name
] = MIME_Type(name
)
20 def __init__(self
, name
):
21 assert name
not in types
22 self
.media
, self
.subtype
= name
.split('/')
30 def add_from_node(self
, file):
31 self
.sources
.append(Source(file))
33 def add_comment(self
, lang
, comment
):
34 self
.comments
.append((lang
, comment
))
36 def add_xml(self
, uri
, name
):
37 self
.xml
.append((uri
, name
))
39 def add_magic(self
, prio
, root
):
40 self
.magic
.append((prio
, root
))
42 def add_other(self
, element
):
43 self
.others
.append(element
)
45 def add_glob(self
, pattern
):
46 self
.globs
.append(pattern
)
48 def get_comment(self
):
50 for lang
, comment
in self
.comments
:
54 return best
or self
.get_name()
57 return self
.media
+ '/' + self
.subtype
59 def get_comments(self
): return map(Comment
, self
.comments
)
60 def get_globs(self
): return map(Glob
, self
.globs
)
61 def get_magic(self
): return map(Magic
, self
.magic
)
62 def get_xml(self
): return map(XML
, self
.xml
)
63 def get_others(self
): return map(Others
, self
.others
)
66 "MIME_Type.get_* functions return a list of these."
67 def __init__(self
, item
):
71 return "<%s>" % self
.item
73 def add_subtree(self
, model
, iter):
77 return cmp(str(self
), str(b
))
81 lang
, data
= self
.item
83 lang
= '[' + lang
+ '] '
90 return "Match '%s'" % self
.item
94 prio
, match
= self
.item
95 return "Match with priority %s" % prio
97 def add_subtree(self
, model
, parent
):
98 def build(match
, parent
):
99 for m
in match
.matches
:
100 text
= '%s at %s = %s' % (m
.type, m
.offset
, m
.value
)
102 text
+= ' masked with ' + m
.mask
103 iter = model
.append(parent
)
104 model
.set(iter, 0, text
)
106 build(self
.item
[1], parent
)
108 def __cmp__(self
, b
):
109 ret
= cmp(str(self
), str(b
))
111 return cmp(self
.item
[1], b
.item
[1])
115 return "<%s> with namespace '%s'" % (self
.item
[1], self
.item
[0])
117 class Others(Field
): pass
120 def __init__(self
, type, attrs
):
123 def start(self
, element
, attrs
): pass
124 def data(self
, data
): pass
127 class CommentParser(FieldParser
):
128 def __init__(self
, type, attrs
):
129 FieldParser
.__init
__(self
, type, attrs
)
130 self
.lang
= attrs
.get(XML_NAMESPACE
+ ' lang', None)
133 def data(self
, data
):
137 self
.type.add_comment(self
.lang
, self
.comment
)
140 def __init__(self
, parent
):
144 def __cmp__(self
, b
):
146 for x
, y
in zip(self
.matches
, b
.matches
):
151 return cmp(self
.type, b
.type) or cmp(self
.offset
, b
.offset
) or \
152 cmp(self
.value
, b
.value
) or cmp(self
.mask
, b
.mask
) or \
155 class MagicParser(FieldParser
):
156 def __init__(self
, type, attrs
):
157 FieldParser
.__init
__(self
, type, attrs
)
158 self
.prio
= attrs
.get('priority', 50)
159 self
.match
= Match(None)
161 def start(self
, element
, attrs
):
162 new
= Match(self
.match
)
163 new
.offset
= attrs
.get('offset', '?')
164 new
.type = attrs
.get('type', '?')
165 new
.value
= attrs
.get('value', '?')
166 new
.mask
= attrs
.get('mask', None)
167 self
.match
.matches
.append(new
)
170 if self
.match
.parent
:
171 self
.match
= self
.match
.parent
173 self
.type.add_magic(self
.prio
, self
.match
)
181 def parse(self
, path
):
182 parser
= expat
.ParserCreate(namespace_separator
= ' ')
183 parser
.StartElementHandler
= self
.start
184 parser
.EndElementHandler
= self
.end
185 parser
.CharacterDataHandler
= self
.data
186 parser
.ParseFile(file(path
))
188 def start(self
, element
, attrs
):
191 assert element
== FREE_NS
+ ' mime-info'
192 elif self
.level
== 2:
193 assert element
== FREE_NS
+ ' mime-type'
194 self
.type = get_type(attrs
['type'])
195 elif self
.level
== 3:
196 if element
== FREE_NS
+ ' comment':
197 self
.handler
= CommentParser(self
.type, attrs
)
198 elif element
== FREE_NS
+ ' glob':
199 self
.type.add_glob(attrs
['pattern'])
200 elif element
== FREE_NS
+ ' magic':
201 self
.handler
= MagicParser(self
.type, attrs
)
202 elif element
== FREE_NS
+ ' root-XML':
203 self
.type.add_xml(attrs
['namespaceURI'], attrs
['localName'])
205 self
.type.add_other(element
)
208 self
.handler
.start(element
, attrs
)
210 def end(self
, element
):
216 elif self
.level
== 2:
219 def data(self
, data
):
221 self
.handler
.data(data
)
224 if not path
.endswith('.xml'): return
225 if not os
.path
.exists(path
):
231 rox
.report_exception()
234 from xml
.dom
import minidom
235 if os
.path
.exists(user_override
):
236 doc
= minidom
.parse(user_override
)
238 doc
= minidom
.Document()
239 node
= doc
.createElementNS(FREE_NS
, 'mime-info')
240 doc
.appendChild(node
)
241 node
.setAttributeNS(XMLNS_NAMESPACE
, 'xmlns', FREE_NS
)
244 def write_override(doc
):
245 home_packages
= os
.path
.join(home_mime
, 'packages')
246 if not os
.path
.isdir(home_packages
):
247 os
.makedirs(home_packages
)
248 path
= os
.path
.join(home_packages
, 'Override.xml.new')
249 doc
.writexml(file(path
, 'w'))
250 os
.rename(path
, path
[:-4])
259 os
.execlp('update-mime-database', 'update-mime-database', home_mime
)
263 rox
.info(os
.fdopen(r
, 'r').read())
267 __main__
.box
.update()
272 root
= doc
.documentElement
273 type_node
= doc
.createElementNS(FREE_NS
, 'mime-type')
274 root
.appendChild(type_node
)
276 type_node
.setAttributeNS(None, 'type', name
)
280 def delete_type(name
):
281 from xml
.dom
import Node
284 for c
in doc
.documentElement
.childNodes
:
285 if c
.nodeType
!= Node
.ELEMENT_NODE
: continue
286 if c
.nodeName
!= 'mime-type': continue
287 if c
.namespaceURI
!= FREE_NS
: continue
288 if c
.getAttributeNS(None, 'type') != name
: continue
289 doc
.documentElement
.removeChild(c
)
292 rox
.alert("No user-provided information about this type -- can't remove anything")
294 if not rox
.confirm("Really remove all user-specified information about type %s?" % name
,
300 "(Re)read the database."
303 for mime_dir
in ['/usr/share/mime', '/usr/local/share/mime', home_mime
]:
304 packages_dir
= os
.path
.join(mime_dir
, 'packages')
305 if not os
.path
.isdir(packages_dir
):
307 packages
= os
.listdir(packages_dir
)
309 for package
in packages
:
310 if package
== 'Override.xml' and mime_dir
is home_mime
: continue
311 scan_file(os
.path
.join(packages_dir
, package
))
312 scan_file(user_override
)