root/tags/release-0.6.2/lib/installer.py

Revision 1, 14.2 kB (checked in by mjoc, 2 years ago)

Initial import.

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