root/trunk/lib/installer.py

Revision 16, 14.2 kB (checked in by nerijusb, 1 year ago)

Transition to the wx namespace - opendict now works with wx 2.8

Line 
1 #
2 # OpenDict
3 # Copyright (c) 2003-2006 Martynas Jocius <martynas.jocius@idiles.com>
4 # Copyright (c) 2007 IDILES SYSTEMS, UAB <support@idiles.com>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your opinion) any later version.
10 #
11 # This program is distributed in the hope that will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more detals.
15 #
16 # You shoud have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 # 02111-1307 USA
20 #
21
22 import wx
23
24 import os
25 import zipfile
26 import shutil
27 import traceback
28
29 from lib.gui.dictaddwin import DictAddWindow
30 from lib.gui import errorwin
31 from lib import misc
32 from lib import info
33 from lib import dicttype
34 from lib import xmltools
35 from lib import util
36 from lib import enc
37 from lib import plaindict
38 from lib import newplugin
39
40 _ = wx.GetTranslation
41
42 class Installer:
43     """Default class used for installing plugins and registering
44        dictionaries."""
45
46     def __init__(self, mainWin, config):
47         self.mainWin = mainWin
48         self.config = config
49
50        
51     def showGUI(self):
52         """Show graphical window for selecting files and formats"""
53
54         wildCard = "All files (*.*)|*.*|" \
55                    "OpenDict plugins (*.zip)|*.zip|" \
56                    "Slowo dictionaries (*.dwa)|*.dwa|" \
57                    "Mova dictionaries (*.mova)|*.mova|" \
58                    "DICT dictionaries (*.dz)|*.dz"
59        
60         fileDialog = wx.FileDialog(self.mainWin,
61                                   message=_("Choose dictionary file"),
62                                   wildcard=wildCard,
63                                   style=wx.OPEN|wx.CHANGE_DIR)
64         fileDialog.CentreOnScreen()
65
66         if fileDialog.ShowModal() == wx.ID_OK:
67             filePath = fileDialog.GetPaths()[0]
68         else:
69             fileDialog.Destroy()
70             return
71
72         fileName = os.path.basename(filePath)
73         extention = os.path.splitext(fileName)[1][1:]
74
75         extMapping = {}
76         for t in dicttype.supportedTypes:
77             for ext in t.getFileExtentions():
78                 extMapping[ext.lower()] = t
79
80         if not extention.lower() in extMapping.keys():
81             title = _("Recognition Error")
82             msg = _("File %s is not supported by OpenDict") % fileName
83             errorwin.showErrorMessage(title, msg)
84             return
85         else:
86             self.install(filePath)
87
88            
89     def install(self, filePath):
90         """Install dictionary"""
91
92         extention = os.path.splitext(filePath)[1][1:]
93         succeeded = False
94  
95         try:
96             if extention.lower() in dicttype.PLUGIN.getFileExtentions():
97                 try:
98                     directory, dtype = installPlugin(filePath)
99                     if directory:
100                         if dtype.lower() == 'plugin':
101                             dictionary = newplugin._loadDictionaryPlugin(directory)
102                         else:
103                             dictionary = plaindict._loadPlainDictionary(directory)
104                         self.mainWin.addDictionary(dictionary)
105                         succeeded = True
106                        
107                 except Exception, e:
108                     errorwin.showErrorMessage(_("Installation failed"),
109                                               e.args[0] or '')
110                     self.mainWin.SetStatusText(_("Installation failed"))
111                     return
112
113             else:
114                 try:
115                     directory = installPlainDictionary(filePath)
116                     if directory:
117                         dictionary = plaindict._loadPlainDictionary(directory)
118                         self.mainWin.addDictionary(dictionary)
119                         succeeded = True
120                 except Exception, e:
121                     traceback.print_exc()
122                     errorwin.showErrorMessage(_("Installation Error"),
123                                               e.args[0] or '')
124                     self.mainWin.SetStatusText(_("Error: Installation failed"))
125                     return
126         except:
127             # Can this happen?
128             self.mainWin.SetStatusText(_("Error: Installation failed"))
129             traceback.print_exc()
130
131         if succeeded:
132             title = _("Dictionary installed")
133             msg = _("Dictionary successfully installed. You can choose it " \
134                     "from \"Dictionaries\" menu now.")
135             errorwin.showInfoMessage(title, msg)
136
137
138
139 def installPlainDictionary(filePath):
140     """Install plain dictionary and return directory path"""
141
142     if not os.path.exists(filePath):
143         raise Exception, _("File %s does not exist") % filePath
144
145     if not os.path.isfile(filePath):
146         raise Exception, _("%s is not a file") % filePath
147
148     util.makeDirectories()
149
150     fileName = os.path.basename(filePath)
151     dictionaryName = os.path.splitext(fileName)[0]
152
153     dictDir = os.path.join(info.LOCAL_HOME,
154                            info.__DICT_DIR,
155                            info.__PLAIN_DICT_DIR,
156                            fileName)
157
158     # Check existance
159     if os.path.exists(dictDir):
160         raise Exception, _("Dictionary \"%s\" is already installed") \
161             % dictionaryName
162    
163     extention = os.path.splitext(fileName)[1][1:]
164     dictType = None
165
166     # Determine type
167     for t in dicttype.supportedTypes:
168         for ext in t.getFileExtentions():
169             if ext.lower() == extention.lower():
170                 dictType = t
171                 break
172
173     if not dictType:
174         raise Exception, "Dictionary type for '%s' still unknown! " \
175               "This may be internal error." % fileName
176
177     # Create directories
178     try:
179         os.mkdir(dictDir)
180         os.mkdir(os.path.join(dictDir, info.__PLAIN_DICT_CONFIG_DIR))
181         os.mkdir(os.path.join(dictDir, info.__PLAIN_DICT_FILE_DIR))
182         os.mkdir(os.path.join(dictDir, info._PLAIN_DICT_DATA_DIR))
183     except Exception, e:
184         print "ERROR Unable to create dicrectories, aborted (%s)" % e
185         try:
186             shutil.rmtree(dictDir)
187         except Exception, e:
188             print "ERROR Unable to remove directories (%s)" % e
189
190
191     # Determine info
192     dictFormat = dictType.getIdName()
193     md5sum = util.getMD5Sum(filePath)
194
195     # Write configuration
196     doc = xmltools.generatePlainDictConfig(name=dictionaryName,
197                                            format=dictFormat,
198                                            version=None,
199                                            authors={},
200                                            path=filePath,
201                                            md5=md5sum,
202                                            encoding='UTF-8',
203                                            description=None)
204
205     xmltools.writePlainDictConfig(doc, os.path.join(dictDir,
206                                                     'conf',
207                                                     'config.xml'))
208
209
210     return dictDir
211
212
213 def installPlugin(filePath):
214     """Install dictionary plugin and return directory path"""
215
216     # Check if file exists
217     if not os.path.exists(filePath):
218         raise Exception, _("File %s does not exist") % filePath
219
220     # Check if it is file
221     if not os.path.isfile(filePath):
222         raise Exception, _("%s is not a file") % filePath
223
224     # Check if it is ZIP archive
225     if os.path.splitext(filePath)[1].lower()[1:] != "zip":
226         raise Exception, _("%s is not OpenDict dictionary plugin") % filePath
227
228     util.makeDirectories()
229
230     try:
231         zipFile = zipfile.ZipFile(filePath, 'r')
232     except Exception, e:
233         raise Exception, _("File \"%s\" is not valid ZIP file") % \
234               os.path.basename(filePath)
235
236     # Test CRC
237     if zipFile.testzip():
238         raise Exception, _("Dictionary plugin file is corrupted")
239
240     # Check if empty
241     try:
242         topDirectory = zipFile.namelist()[0]
243     except Exception, e:
244         raise Exception, _("Plugin file is empty (%s)") % e
245
246     configFileExists = False
247     pluginConfigExists = False
248     plainConfigExists = False
249     topLevelDirExists = False
250
251     # Check for validity
252     for fileInZip in zipFile.namelist():
253         dirName = os.path.dirname(fileInZip)
254         fileName = os.path.basename(fileInZip)
255
256         if fileName == "plugin.xml":
257             pluginConfigExists = True
258
259         if fileName == 'config.xml':
260             plainConfigExists = True
261
262         if len(fileName) == 0 \
263            and len(dirName.split('/')) == 1:
264             topLevelDirExists = True
265
266     if ((not plainConfigExists) and (not pluginConfigExists)) \
267        or (not topLevelDirExists):
268         raise Exception, _("Selected file is not valid OpenDict plugin")
269
270
271     dtype = None
272     if plainConfigExists:
273         directory = _installPlainPlugin(filePath)
274         dtype = 'plain'
275     elif pluginConfigExists:
276         directory = _installNormalPlugin(filePath)
277         dtype = 'plugin'
278
279     return (directory, dtype)
280        
281
282 def _installNormalPlugin(filePath):
283     """Install 'normal' OpenDict plugin"""
284
285     zipFile = zipfile.ZipFile(filePath, 'r')
286
287     topDirectory = zipFile.namelist()[0]
288     pluginsPath = os.path.join(info.LOCAL_HOME,
289                               info.PLUGIN_DICT_DIR)
290
291     # Check if already installed
292     if os.path.exists(os.path.join(info.LOCAL_HOME,
293                                    info.PLUGIN_DICT_DIR,
294                                    topDirectory)):
295         raise Exception, _("This dictionary already installed. " \
296                            "If you want to upgrade it, please remove " \
297                            "old version first.")
298
299     installFile = os.path.join(topDirectory, 'install.py')
300    
301     if installFile in zipFile.namelist():
302         data = zipFile.read(installFile)
303
304         try:
305             struct = {}
306             exec data in struct
307         except Exception, e:
308             title = _("Installation Error")
309             msg = _("Installation tool for this dictionary failed to start. " \
310                     "Please report this problem to developers.")
311             errorwin.showErrorMessage(title, msg)
312             return
313
314         install = struct.get('install')
315         if not install:
316             title = _("Installation Error")
317             msg = _("Installation tool for this dictionary failed to start. " \
318                     "Please report this problem to developers.")
319             errorwin.showErrorMessage(title, msg)
320             return
321
322         if not install(info.GLOBAL_HOME, info.LOCAL_HOME):
323             title = _("Installation Aborted")
324             msg = _("Dictionary installation has been aborted.")
325             errorwin.showErrorMessage(title, msg)
326             return
327        
328
329     # Install
330     try:
331         for fileInZip in zipFile.namelist():
332             dirName = os.path.dirname(fileInZip)
333             fileName = os.path.basename(fileInZip)
334
335             if len(fileName) == 0:
336                 dirToCreate = os.path.join(pluginsPath, dirName)
337                 if not os.path.exists(dirToCreate):
338                     os.mkdir(dirToCreate)
339             else:
340                 fileToWrite = os.path.join(pluginsPath, dirName, fileName)
341                 fd = open(fileToWrite, 'wb')
342                 fd.write(zipFile.read(fileInZip))
343                 fd.close()
344     except Exception, e:
345         try:
346             shutil.rmtree(os.path.join(pluginsPath, topLevelDir))
347         except Exception, e:
348             raise _("Error while removing created directories after " \
349                     "plugin installation failure. This may be " \
350                     "permission or disk space error.")
351
352         raise _("Unable to install plugin")
353
354
355     return os.path.join(info.LOCAL_HOME,
356                         info.PLUGIN_DICT_DIR,
357                         topDirectory)
358
359
360
361 def _installPlainPlugin(filePath):
362     """Install prepared plain dictionary and return directory path"""
363
364     zipFile = zipfile.ZipFile(filePath, 'r')
365     topDirectory = zipFile.namelist()[0]
366
367     # Test CRC
368     if zipFile.testzip():
369         raise Exception, _("Compressed dictionary file is corrupted")
370
371     plainDictsPath = os.path.join(info.LOCAL_HOME,
372                               info.PLAIN_DICT_DIR)
373
374     # Check if already installed
375     if os.path.exists(os.path.join(plainDictsPath,
376                                    topDirectory)):
377         raise Exception, _("This dictionary already installed. " \
378                            "If you want to upgrade it, please remove " \
379                            "old version first.")
380
381     # Install
382     try:
383         for fileInZip in zipFile.namelist():
384             dirName = os.path.dirname(fileInZip)
385             fileName = os.path.basename(fileInZip)
386
387             if len(fileName) == 0:
388                 dirToCreate = os.path.join(plainDictsPath, dirName)
389                 if not os.path.exists(dirToCreate):
390                     os.mkdir(dirToCreate)
391             else:
392                 fileToWrite = os.path.join(plainDictsPath, dirName, fileName)
393                 fd = open(fileToWrite, 'wb')
394                 fd.write(zipFile.read(fileInZip))
395                 fd.close()
396     except Exception, e:
397         try:
398             shutil.rmtree(os.path.join(plainDictsPath, topDirectory))
399         except Exception, e:
400             raise _("Error while removing created directories after " \
401                     "plugin installation failure. This may be " \
402                     "permission or disk space error.")
403
404         raise _("Unable to install dictionary")
405
406
407     return os.path.join(info.LOCAL_HOME,
408                         info.PLAIN_DICT_DIR,
409                         topDirectory)
410
411
412
413 def removePlainDictionary(dictInstance):
414     """Remove dictionary configuration"""
415
416     filePath = dictInstance.getPath()
417     fileName = os.path.basename(filePath)
418
419     dictDir = dictInstance.getConfigDir()
420
421     try:
422         shutil.rmtree(dictDir)
423     except Exception, e:
424         raise Exception, str(e)
425
426
427 def removePluginDictionary(dictInstance):
428     """Remove plugin dictionary"""
429
430     filePath = dictInstance.getPath()
431     fileName = os.path.basename(filePath)
432
433     dictDir = dictInstance.getPath()
434
435     try:
436         shutil.rmtree(dictDir)
437     except Exception, e:
438         raise Exception, str(e)
439    
Note: See TracBrowser for help on using the browser.