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(Other
, 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
))
80 rox
.alert('Sorry, MIME-Editor does not support editing fields of this type')
86 rox
.alert("Sorry, can't create fields of this type yet")
90 lang
, data
= self
.item
92 lang
= '[' + lang
+ '] '
99 return "Match '%s'" % self
.item
103 prio
, match
= self
.item
104 return "Match with priority %s" % prio
106 def add_subtree(self
, model
, parent
):
107 def build(match
, parent
):
108 for m
in match
.matches
:
109 text
= '%s at %s = %s' % (m
.type, m
.offset
, m
.value
)
111 text
+= ' masked with ' + m
.mask
112 iter = model
.append(parent
)
113 model
.set(iter, 0, text
, 1, m
)
115 build(self
.item
[1], parent
)
117 def __cmp__(self
, b
):
118 ret
= cmp(str(self
), str(b
))
120 return cmp(self
.item
[1], b
.item
[1])
124 return "<%s> with namespace '%s'" % (self
.item
[1], self
.item
[0])
126 class Other(Field
): pass
129 def __init__(self
, type, attrs
):
132 def start(self
, element
, attrs
): pass
133 def data(self
, data
): pass
136 class CommentParser(FieldParser
):
137 def __init__(self
, type, attrs
):
138 FieldParser
.__init
__(self
, type, attrs
)
139 self
.lang
= attrs
.get(XML_NAMESPACE
+ ' lang', None)
142 def data(self
, data
):
146 self
.type.add_comment(self
.lang
, self
.comment
)
149 def __init__(self
, parent
):
153 def __cmp__(self
, b
):
155 for x
, y
in zip(self
.matches
, b
.matches
):
163 return cmp(self
.type, b
.type) or cmp(self
.offset
, b
.offset
) or \
164 cmp(self
.value
, b
.value
) or cmp(self
.mask
, b
.mask
) or \
168 rox
.alert("Editing of matches isn't currently supported")
170 class MagicParser(FieldParser
):
171 def __init__(self
, type, attrs
):
172 FieldParser
.__init
__(self
, type, attrs
)
173 self
.prio
= attrs
.get('priority', 50)
174 self
.match
= Match(None)
176 def start(self
, element
, attrs
):
177 new
= Match(self
.match
)
178 new
.offset
= attrs
.get('offset', '?')
179 new
.type = attrs
.get('type', '?')
180 new
.value
= attrs
.get('value', '?')
181 new
.mask
= attrs
.get('mask', None)
182 self
.match
.matches
.append(new
)
185 if self
.match
.parent
:
186 self
.match
= self
.match
.parent
188 self
.type.add_magic(self
.prio
, self
.match
)
196 def parse(self
, path
):
197 parser
= expat
.ParserCreate(namespace_separator
= ' ')
198 parser
.StartElementHandler
= self
.start
199 parser
.EndElementHandler
= self
.end
200 parser
.CharacterDataHandler
= self
.data
201 parser
.ParseFile(file(path
))
203 def start(self
, element
, attrs
):
206 assert element
== FREE_NS
+ ' mime-info'
207 elif self
.level
== 2:
208 assert element
== FREE_NS
+ ' mime-type'
209 self
.type = get_type(attrs
['type'])
210 elif self
.level
== 3:
211 if element
== FREE_NS
+ ' comment':
212 self
.handler
= CommentParser(self
.type, attrs
)
213 elif element
== FREE_NS
+ ' glob':
214 self
.type.add_glob(attrs
['pattern'])
215 elif element
== FREE_NS
+ ' magic':
216 self
.handler
= MagicParser(self
.type, attrs
)
217 elif element
== FREE_NS
+ ' root-XML':
218 self
.type.add_xml(attrs
['namespaceURI'], attrs
['localName'])
220 self
.type.add_other(element
)
223 self
.handler
.start(element
, attrs
)
225 def end(self
, element
):
231 elif self
.level
== 2:
234 def data(self
, data
):
236 self
.handler
.data(data
)
239 if not path
.endswith('.xml'): return
240 if not os
.path
.exists(path
):
246 rox
.report_exception()
249 from xml
.dom
import minidom
250 if os
.path
.exists(user_override
):
251 doc
= minidom
.parse(user_override
)
253 doc
= minidom
.Document()
254 node
= doc
.createElementNS(FREE_NS
, 'mime-info')
255 doc
.appendChild(node
)
256 node
.setAttributeNS(XMLNS_NAMESPACE
, 'xmlns', FREE_NS
)
259 def write_override(doc
):
260 home_packages
= os
.path
.join(home_mime
, 'packages')
261 if not os
.path
.isdir(home_packages
):
262 os
.makedirs(home_packages
)
263 path
= os
.path
.join(home_packages
, 'Override.xml.new')
264 doc
.writexml(file(path
, 'w'))
265 os
.rename(path
, path
[:-4])
274 os
.execlp('update-mime-database', 'update-mime-database', home_mime
)
278 rox
.info(os
.fdopen(r
, 'r').read())
282 __main__
.box
.update()
287 root
= doc
.documentElement
288 type_node
= doc
.createElementNS(FREE_NS
, 'mime-type')
289 root
.appendChild(type_node
)
291 type_node
.setAttributeNS(None, 'type', name
)
295 def delete_type(name
):
296 from xml
.dom
import Node
299 for c
in doc
.documentElement
.childNodes
:
300 if c
.nodeType
!= Node
.ELEMENT_NODE
: continue
301 if c
.nodeName
!= 'mime-type': continue
302 if c
.namespaceURI
!= FREE_NS
: continue
303 if c
.getAttributeNS(None, 'type') != name
: continue
304 doc
.documentElement
.removeChild(c
)
307 rox
.alert("No user-provided information about this type -- can't remove anything")
309 if not rox
.confirm("Really remove all user-specified information about type %s?" % name
,
315 "(Re)read the database."
318 for mime_dir
in ['/usr/share/mime', '/usr/local/share/mime', home_mime
]:
319 packages_dir
= os
.path
.join(mime_dir
, 'packages')
320 if not os
.path
.isdir(packages_dir
):
322 packages
= os
.listdir(packages_dir
)
324 for package
in packages
:
325 if package
== 'Override.xml' and mime_dir
is home_mime
: continue
326 scan_file(os
.path
.join(packages_dir
, package
))
327 scan_file(user_override
)