source: air-manager/trunk/fuentes/python3-air-manager/airmanager/airmanager.py @ 7336

Last change on this file since 7336 was 7336, checked in by Juanma, 17 months ago

fix css font properties

File size: 17.5 KB
Line 
1#!/usr/bin/env python3
2import os
3import stat
4import datetime
5import subprocess
6import sys
7import shutil
8import tempfile
9import zipfile
10import urllib.request as url
11import glob
12from gi.repository import GdkPixbuf
13
14LOG='/tmp/air_manager.log'
15
16class AirManager():
17        def __init__(self):
18                self.dbg=True
19                self.default_icon="/usr/share/air-installer/rsrc/air-installer_icon.png"
20                self.adobeair_folder="/opt/AdobeAirApp/"
21                self.adobeairsdk_folder="/opt/adobe-air-sdk/"
22                self.adobeair_pkgname="adobeair"
23        #def __init__
24
25        def _debug(self,msg):
26                if self.dbg:
27                        print("airinstaller: %s"%msg)
28                        self._log(msg)
29        #def _debug
30
31        def _log(self,msg):
32                f=open(LOG,'a')
33                f.write("%s"%msg)
34                f.close()
35        #def _log
36
37        def set_default_icon(self,icon):
38                self.default_icon=icon
39
40        def install(self,air_file,icon=None):
41                sw_err=0
42                sw_install_sdk=False
43                self._check_adobeair()
44                if not icon:
45                        icon=self.default_icon
46                self._debug("Procced with file: %s"%air_file)
47                file_name=os.path.basename(air_file)
48                if self._check_file_is_air(air_file):
49                        basedir_name=file_name.replace(".air","")
50                        self._debug("Installing %s"%air_file)
51                        sw_err=self._install_air_package(air_file)
52                        if sw_err:
53                                self._debug("Trying rebuild...")
54                                modified_air_file=self._recompile_for_certificate_issue(air_file)
55                                self._debug("Installing %s"%modified_air_file)
56                                sw_err=self._install_air_package(modified_air_file)
57                        if sw_err:
58                                self._debug("Failed to install code: %s"%sw_err)
59                                self._debug("Going with sdk installation")
60                                sw_err=self._install_air_package_sdk(air_file,icon)
61                                sw_install_sdk=True
62
63                        if not sw_err and sw_install_sdk:
64                                #Copy icon to hicolor
65                                sw_installed=self._generate_desktop(file_name)
66                                if sw_installed:
67                                        hicolor_icon='/usr/share/icons/hicolor/48x48/apps/%s.png'%basedir_name
68                                        shutil.copyfile (icon,hicolor_icon)
69                                        self._debug("Installed in %s"%(basedir_name))
70                                else:
71                                        self._debug("%s Not Installed!!!"%(basedir_name))
72                        elif not sw_err and icon!=self.default_icon:
73                                #Modify desktop with icon
74                                hicolor_icon='/usr/share/icons/hicolor/48x48/apps/%s.png'%basedir_name
75                                shutil.copyfile (icon,hicolor_icon)
76                                icon_new=os.path.basename(hicolor_icon)
77                                self._modify_desktop(air_file,icon_name=icon_new)
78        #def install
79
80        def _modify_desktop(self,air_file,icon_name=None):
81                self._debug("Modify desktop %s"%air_file)
82                air_info=self.get_air_info(air_file)
83                sw_modify_icon=False
84                if 'name' in air_info.keys():
85                        cwd=os.getcwd()
86                        os.chdir('/usr/share/applications')
87                        desktop_list=glob.glob(air_info['name']+"*desktop")
88                        if desktop_list==[]:
89                                desktop_list=glob.glob(air_info['name'].lower()+"*desktop")
90                        if desktop_list:
91                                #First file must be the desktop but for sure...
92                                sw_modify_icon=False
93                                for desktop_file in desktop_list:
94                                        self._debug("Testing file %s"%desktop_file)
95                                        f=open(desktop_file,'r')
96                                        flines=f.readlines()
97                                        self._debug("Looking for %s"%self.adobeair_folder)
98                                        for fline in flines:
99                                                self._debug(fline)
100                                                self._debug(type(fline))
101                                                if '/opt/AdobeAirApp' in fline:
102                                                        self._debug("Match")
103                                                        sw_modify_icon=True
104                                        f.close()
105                        if sw_modify_icon:
106                                self._debug("Setting icon")
107                                new_desktop=[]
108                                for fline in flines:
109                                        if fline.startswith('Icon'):
110                                                self._debug("Before: %s"%fline)
111                                                nline='Icon=%s\n'%icon_name
112                                                self._debug("After: %s"%nline)
113                                                new_desktop.append(nline)
114                                        else:
115                                                new_desktop.append(fline)
116                                self._debug("Writing desktop %s"%desktop_file)
117                                f=open(desktop_file,'w')
118                                f.writelines(new_desktop)
119                                f.close()
120                        os.chdir(cwd)
121        #def _modify_desktop
122
123        def _check_adobeair(self):
124                sw_install_adobe=False
125                sw_download=False
126                try:
127                        res=subprocess.check_output(["dpkg-query","-W","-f='${Status}'",self.adobeair_pkgname])
128                        if "not" in str(res):
129                                self._debug("adobeair not installed")
130                                sw_install_adobe=True
131                except Exception as e:
132                        self._debug("dpkg-query failed: %s"%e)
133                        sw_install_adobe=True
134                finally:
135                        if sw_install_adobe:
136                                sw_download=self._install_adobeair()
137
138                if sw_download==False:
139                        self._debug("Adobeair failed to install")
140                #Now install the sdk
141                if not os.path.isdir(self.adobeair_folder):
142                        os.makedirs(self.adobeair_folder)
143                self._install_adobeair_sdk()
144
145        def _install_air_package(self,air_file):
146                sw_err=1
147                my_env=os.environ.copy()
148                my_env["DISPLAY"]=":0"
149                try:
150                        subprocess.check_output(["/usr/bin/Adobe AIR Application Installer","-silent","-eulaAccepted","-location","/opt/AdobeAirApp",air_file],env=my_env)
151                        sw_err=0
152                except Exception as e:
153                        self._debug("Install Error: %s"%e)
154                return sw_err
155        #def _install_air_package
156
157        def _install_air_package_sdk(self,air_file,icon=None):
158                sw_err=0
159                if not icon:
160                        icon=self.default_icon
161                file_name=os.path.basename(air_file)
162                basedir_name=file_name.replace('.air','')
163                wrkdir=self.adobeair_folder+basedir_name
164                if os.path.isdir(wrkdir):
165                        try:
166                                shutil.rmtree(wrkdir)
167                        except Exception as e:
168                                sw_err=3
169                                self._debug(e)
170                try:
171                        os.makedirs(wrkdir)
172                except Exception as e:
173                        sw_err=4
174                        self._debug(e)
175                if sw_err==0:
176                        try:
177                                shutil.copyfile (air_file,wrkdir+"/"+file_name)
178                        except:
179                                sw_err=1
180                #Copy icon to hicolor
181                if sw_err==0:
182                        hicolor_icon='/usr/share/icons/hicolor/48x48/apps/%s.png'%basedir_name
183                        try:
184                                shutil.copyfile (icon,hicolor_icon)
185                        except:
186                                sw_err=2
187
188                self._generate_desktop_sdk(file_name)
189                self._debug("Installed in %s/%s"%(wrkdir,air_file))
190                return sw_err
191        #def _install_air_package_sdk
192
193        def _generate_desktop(self,file_name):
194                basedir_name=file_name.replace('.air','')
195                desktop="/usr/share/applications/%s.desktop"%basedir_name
196                exec_file=self._get_air_bin_file(basedir_name)
197                self._debug("Exec: %s"%exec_file)
198                if exec_file:
199                        f=open(desktop,'w')
200                        f.write("[Desktop Entry]\n\
201Encoding=UTF-8\n\
202Version=1.0\n\
203Type=Application\n\
204Exec=\""+exec_file+"\"\n\
205Icon="+basedir_name+".png\n\
206Terminal=false\n\
207Name="+basedir_name+"\n\
208Comment=Application from AdobeAir "+basedir_name+"\n\
209MimeType=application/x-scratch-project\n\
210Categories=Application;Education;Development;ComputerScience;\n\
211")
212                        f.close()
213                        return True
214                else:
215                        return False
216#chmod +x $NEW_ICON_FILE
217        #def _generate_desktop
218
219        def _get_air_bin_file(self,basedir_name):
220                target_bin=''
221                for folder in os.listdir(self.adobeair_folder):
222                        target_folder=''
223                        if basedir_name.lower() in folder.lower() or basedir_name.lower==folder.lower():
224                                target_folder=os.listdir(self.adobeair_folder+folder)
225                        else:
226                                split_name=''
227                                if '-' in basedir_name.lower():
228                                        split_name=basedir_name.lower().split('-')[0]
229                                elif ' ' in basedir_name.lower():
230                                        split_name=basedir_name.lower().split(' ')[0]
231                                elif '.' in basedir_name.lower():
232                                        split_name=basedir_name.lower().split('.')[0]
233                                if split_name!='' and split_name in folder.lower():
234                                        target_folder=os.listdir(self.adobeair_folder+folder)
235                        if target_folder:
236                                if 'bin' in target_folder:
237                                        candidate_list=os.listdir(self.adobeair_folder+folder+'/bin')
238                                        for candidate_file in candidate_list:
239                                                test_file=self.adobeair_folder+folder+'/bin/'+candidate_file
240                                                self._debug("Testing %s"%test_file)
241                                                if os.access(test_file,os.X_OK):
242                                                        target_bin=test_file
243                                                        self._debug("Test OK for %s"%target_bin)
244                                                        break
245                return(target_bin)
246
247        def _generate_desktop_sdk(self,file_name):
248                basedir_name=file_name.replace('.air','')
249                desktop="/usr/share/applications/%s.desktop"%basedir_name
250                f=open(desktop,'w')
251                f.write("[Desktop Entry]\n\
252Encoding=UTF-8\n\
253Version=1.0\n\
254Type=Application\n\
255Exec=/opt/adobe-air-sdk/adobe-air/adobe-air "+self.adobeair_folder+basedir_name+"/"+file_name+"\n\
256Icon="+basedir_name+".png\n\
257Terminal=false\n\
258Name="+basedir_name+"\n\
259Comment=Application from AdobeAir "+basedir_name+"\n\
260MimeType=application/x-scratch-project\n\
261Categories=Application;Education;Development;ComputerScience;\n\
262")
263                f.close()
264        #def _generate_desktop_sdk
265
266        def _install_adobeair_sdk(self):
267                        #               if os.path.isfile(self.adobeairsdk_folder+'adobe-air/adobe-air'):
268#                       return
269                self._install_adobeair_depends()
270                self._debug("Installing Adobe Air SDK")
271                adobeair_url="http://lliurex.net/recursos-edu/misc/AdobeAIRSDK.tbz2"
272#               adobeair_url="http://lliurex.net/recursos-edu/misc/adobe-air.tar.gz"
273                req=url.Request(adobeair_url,headers={'User-Agent':'Mozilla/5.0'})
274                try:
275                        adobeair_file=url.urlopen(req)
276                except Exception as e:
277                        self._debug(e)
278                        return False
279                (tmpfile,tmpfile_name)=tempfile.mkstemp()
280                os.close(tmpfile)
281                self._debug("Download %s"%tmpfile_name)
282                with open(tmpfile_name,'wb') as output:
283                        output.write(adobeair_file.read())
284                try:
285                        os.makedirs ("/opt/adobe-air-sdk")
286                except:
287                        pass
288                subprocess.call(["tar","jxf",tmpfile_name,"-C","/opt/adobe-air-sdk"])
289                st=os.stat("/opt/adobe-air-sdk/adobe-air/adobe-air")
290                os.chmod("/opt/adobe-air-sdk/adobe-air/adobe-air",st.st_mode | 0o111)
291
292#               self._debug("Downloading Air Runtime SDK from Archlinux")
293#       subprocess.call(["zero-lliurex-wget","http://lliurex.net/recursos-edu/misc/adobe-air.tar.gz","/tmp"])
294#       subprocess.call(["tar","xvf","/tmp/adobe-air.tar.gz","-C","/opt/adobe-air-sdk"])
295#       subprocess.call(["chmod","+x","/opt/adobe-air-sdk/adobe-air/adobe-air"])
296        #def _install_adobeair_sdk
297
298        def _install_adobeair(self):
299                        self._install_adobeair_depends()
300                        self._debug("Installing Adobe Air")
301                        adobeair_url="http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRInstaller.bin"
302                        req=url.Request(adobeair_url,headers={'User-Agent':'Mozilla/5.0'})
303                        try:
304                                adobeair_file=url.urlopen(req)
305                        except Exception as e:
306                                self._debug('Donwload err: %s'%e)
307                                return False
308                        (tmpfile,tmpfile_name)=tempfile.mkstemp()
309                        os.close(tmpfile)
310                        with open(tmpfile_name,'wb') as output:
311                                output.write(adobeair_file.read())
312                        st=os.stat(tmpfile_name)
313                        os.chmod(tmpfile_name,st.st_mode | 0o111)
314#                       subprocess.call([tmpfile_name,"-silent","-eulaAccepted","-pingbackAllowed"])
315                        os.system("DISPLAY=:0 " + tmpfile_name + " -silent -eulaAccepted -pingbackAllowed")
316                        os.remove(tmpfile_name)
317                        #Remove symlinks
318                        if os.path.isfile("/usr/lib/libgnome-keyring.so.0"):
319                                os.remove("/usr/lib/libgnome-keyring.so.0")
320                        if os.path.isfile("/usr/lib/libgnome-keyring.so.0.2.0"):
321                                os.remove("/usr/lib/libgnome-keyring.so.0.2.0")
322                        return True
323        #def _install_adobeair
324
325        def _install_adobeair_depends(self):
326                subprocess.call(["apt-get","-q","update"])
327                lib_folder='x86_64-linux-gnu'
328                if os.uname().machine=='x86_64':
329                        self._debug("Installing i386 libs")
330                        subprocess.call(["apt-get","-q","-y","install","libgtk2.0-0:i386","libstdc++6:i386","libxml2:i386","libxslt1.1:i386","libcanberra-gtk-module:i386","gtk2-engines-murrine:i386","libqt4-qt3support:i386","libgnome-keyring0:i386","libnss-mdns:i386","libnss3:i386","libatk-adaptor:i386","libgail-common:i386"])
331                else:
332                        lib_folder='i386-linux-gnu'
333                        subprocess.call(["apt-get","-q","-y","install","libgtk2.0-0","libxslt1.1","libxml2","libnss3","libxaw7","libgnome-keyring0","libatk-adaptor","libgail-common"])
334                self._debug("Linking libs")
335                try:
336                        if os.path.isfile("/usr/lib/libgnome-keyring.so.0"):
337                                os.remove("/usr/lib/libgnome-keyring.so.0")
338                        if os.path.isfile("/usr/lib/libgnome-keyring.so.0.2.0"):
339                                os.remove("/usr/lib/libgnome-keyring.so.0.2.0")
340                        os.symlink("/usr/lib/"+lib_folder+"/libgnome-keyring.so.0","/usr/lib/libgnome-keyring.so.0")
341                        os.symlink("/usr/lib/"+lib_folder+"/libgnome-keyring.so.0.2.0","/usr/lib/libgnome-keyring.so.0.2.0")
342                except Exception as e:
343                        self._debug(e)
344        #def _install_adobeair_depends
345
346        def _recompile_for_certificate_issue(self,air_file):
347                self._debug("Rebuilding package %s"%air_file)
348                new_air_file=''
349                tmpdir=self._unzip_air_file(air_file)
350                cwd=os.getcwd()
351                os.chdir(tmpdir)
352                air_xml=''
353                for xml_file in os.listdir("META-INF/AIR"):
354                        if xml_file.endswith(".xml"):
355                                air_xml=xml_file
356                                break
357                if air_xml:
358                        shutil.move("META-INF/AIR/"+air_xml,air_xml)
359                        shutil.rmtree("META-INF/",ignore_errors=True)
360                        os.remove("mimetype")
361                        self._debug("Generating new cert")
362                        subprocess.call(["/opt/adobe-air-sdk/bin/adt","-certificate","-cn","lliurex","2048-RSA","lliurex.p12","lliurex"])
363                        new_air_file=os.path.basename(air_file)
364                        my_env=os.environ.copy()
365                        my_env["DISPLAY"]=":0"
366                        try:
367                                subprocess.check_output(["/opt/adobe-air-sdk/bin/adt","-package","-tsa","none","-storetype","pkcs12","-keystore","lliurex.p12",new_air_file,air_xml,"."],input=b"lliurex",env=my_env)
368                        except Exception as e:
369                                self._debug(e)
370                os.chdir(cwd)
371                return tmpdir+'/'+new_air_file
372        #def _recompile_for_certificate_issue
373
374        def _unzip_air_file(self,air_file):
375                cwd=os.getcwd()
376                tmpdir=tempfile.mkdtemp()
377                self._debug("Extracting to %s"%tmpdir)
378                os.chdir(tmpdir)
379                air_pkg=zipfile.ZipFile(air_file,'r')
380                for file_to_unzip in air_pkg.infolist():
381                        try:
382                                air_pkg.extract(file_to_unzip)
383                        except:
384                                pass
385                air_pkg.close()
386                os.chdir(cwd)
387                return (tmpdir)
388
389        def get_installed_apps(self):
390                installed_apps={}
391                if os.path.isdir(self.adobeair_folder):
392                        for app_dir in os.listdir(self.adobeair_folder):
393                                self._debug("Testing %s"%app_dir)
394                                app_desktop=''
395                                if os.path.isdir(self.adobeair_folder+app_dir+'/bin') or os.path.isfile(self.adobeair_folder+app_dir+'/'+app_dir+'.air'):
396                                        #Search the desktop of the app
397                                        self._debug("Searching desktop %s"%'/usr/share/applications/'+app_dir+'.desktop')
398                                        sw_desktop=False
399                                        if os.path.isdir(self.adobeair_folder+app_dir+'/share/META-INF/AIR'):
400                                                for pkg_file in os.listdir(self.adobeair_folder+app_dir+'/share/META-INF/AIR'):
401                                                        if pkg_file.endswith('.desktop'):
402                                                                app_desktop='/usr/share/applications/'+pkg_file
403                                                                sw_desktop=True
404                                                                break
405                                        if sw_desktop==False:
406                                                if os.path.isfile('/usr/share/applications/'+app_dir+'.desktop'):
407                                                        app_desktop='/usr/share/applications/'+app_dir+'.desktop'
408                                                elif os.path.isfile('/usr/share/applications/'+app_dir.lower()+'.desktop'):
409                                                        app_desktop='/usr/share/applications/'+app_dir.lower()+'.desktop'
410                                        #Get the app_id
411                                        self._debug("Searching id %s"%self.adobeair_folder+app_dir+'/share/application.xml')
412                                        if os.path.isfile(self.adobeair_folder+app_dir+'/share/application.xml'):
413                                                f=open(self.adobeair_folder+app_dir+'/share/application.xml','r')
414                                                flines=f.readlines()
415                                                app_id=''
416                                                for fline in flines:
417                                                        fline=fline.strip()
418                                                        if fline.startswith('<id>'):
419                                                                app_id=fline
420                                                                app_id=app_id.replace('<id>','')
421                                                                app_id=app_id.replace('</id>','')
422                                                                break
423                                                f.close()
424                                        elif os.path.isfile(self.adobeair_folder+app_dir+'/'+app_dir+'.air'):
425                                                app_id=app_dir+'.air'
426                                        installed_apps[app_dir]={'desktop':app_desktop,'air_id':app_id}
427                return installed_apps
428        #def get_installed_apps
429
430        def remove_air_app(self,*kwarg):
431                sw_err=1
432                my_env=os.environ.copy()
433                my_env["DISPLAY"]=":0"
434                air_dict=kwarg[0]
435                sw_uninstall_err=False
436                if 'air_id' in air_dict.keys():
437                        self._debug("Removing %s"%air_dict['air_id'])
438                        if air_dict['air_id'].endswith('.air'):
439                                air_file=self.adobeair_folder+air_dict['air_id'].replace('.air','')+'/'+air_dict['air_id']
440                                self._debug("SDK app detected %s"%air_file)
441                                if os.path.isfile(air_file):
442                                        try:
443                                                shutil.rmtree(os.path.dirname(air_file))
444                                                sw_err=0
445                                        except Exception as e:
446                                                self._debug(e)
447                        else:
448                                try:
449                                        #Let's try with supercow's power
450                                        pkgname=subprocess.check_output(["apt-cache","search",air_dict['air_id']],env=my_env,universal_newlines=True)
451                                        pkglist=pkgname.split(' ')
452                                        for pkg in pkglist:
453                                                self._debug("Testing %s"%pkg)
454                                                if air_dict['air_id'].lower() in pkg.lower():
455                                                        try:
456                                                                self._debug("Uninstalling %s"%pkg)
457                                                                sw_uninstall_err=subprocess.check_output(["apt-get","-y","remove",pkg],universal_newlines=True)
458                                                                self._debug("Uninstalled OK %s"%pkg)
459                                                                sw_err=0
460                                                        except Exception as e:
461                                                                self._debug(e)
462                                                        break
463                                except Exception as e:
464                                                sw_uninstall_err=True
465                               
466                                if sw_err:
467                                        try:
468                                                sw_uninstall_err=subprocess.check_output(["/usr/bin/Adobe AIR Application Installer","-silent","-uninstall","-location",self.adobeair_folder,air_dict['air_id']],env=my_env)
469                                                sw_err=0
470                                        except Exception as e:
471                                                self._debug(e)
472
473                if 'desktop' in air_dict.keys():
474                        if os.path.isfile(air_dict['desktop']):
475                                try:
476                                        os.remove(air_dict['desktop'])
477                                except Exception as e:
478                                        self._debug(e)
479                return sw_err
480
481        def get_air_info(self,air_file):
482                air_info={}
483                tmpdir=self._unzip_air_file(air_file)
484                cwd=os.getcwd()
485                os.chdir(tmpdir+'/META-INF/AIR')
486                icon_line=''
487                name_line=''
488                if os.path.isfile('application.xml'):
489                        f=open('application.xml','r')
490                        flines=f.readlines()
491                        for fline in flines:
492                                fline=fline.strip()
493                                if fline.startswith('<filename>'):
494                                        name_line=fline
495                                if fline.startswith('<image48x48>'):
496                                        if fline!='<image48x48></image48x48>' and icon_line=='':
497                                                icon_line=fline
498                                                self._debug(fline)
499                        if icon_line:
500                                self._debug("ICON: %s"%icon_line)
501                                icon=icon_line.replace('<image48x48>','')
502                                icon=icon.replace('</image48x48>','')
503                                if icon!='':
504                                        icon=tmpdir+'/'+icon
505                                        air_info['pb']=GdkPixbuf.Pixbuf.new_from_file_at_scale(icon,64,-1,True)
506                        if name_line:
507                                name=name_line.replace('<filename>','')
508                                air_info['name']=name.replace('</filename>','')
509                else:
510                        air_info['name']=os.path.basename(air_file)
511                        air_info['name']=air_info['name'].replace('.air','')
512                        os.chdir(tmpdir)
513                        icon_files=glob("*/*48*png")
514                        if not icon_files:
515                                icon_files=glob("*48*png")
516                        if icon_files:
517                                air_info['pb']=GdkPixbuf.Pixbuf.new_from_file_at_scale(icon_files[0],64,-1,True)
518
519                return air_info
520        #def _get_air_info
521
522        def _check_file_is_air(self,air_file):
523                retval=False
524                if air_file.endswith(".air"):
525                        retval=True
526                return retval
527        #def _check_file_is_air
528               
Note: See TracBrowser for help on using the repository browser.