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

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

Fix paths

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