#!/usr/bin/env python
import sys
import os
import json
import urllib
import urlparse
import tempfile
import mimetypes
import subprocess
import Tkinter
import tkMessageBox
class XdgUrl:
"""Core class of xdgurl"""
def __init__(self, xdg_url=''):
self.xdg_url = xdg_url
self.meta = self.parse()
self.temp_dir = tempfile.gettempdir()
self.home_dir = os.path.expanduser('~')
#self.config_dir = os.path.join(self.home_dir, '.config', 'xdgurl')
self.data_dir = os.path.join(self.home_dir, '.local', 'share')
self.kde_data_dir = os.path.join(self.home_dir, '.kde', 'share')
#self.config = {}
self.destinations = {
'downloads': os.path.join(self.home_dir, 'Downloads'),
'documents': os.path.join(self.home_dir, 'Documents'),
'pictures': os.path.join(self.home_dir, 'Pictures'),
'music': os.path.join(self.home_dir, 'Music'),
'videos': os.path.join(self.home_dir, 'Videos'),
'wallpapers': os.path.join(self.data_dir, 'wallpapers'),
'fonts': os.path.join(self.home_dir, '.fonts'),
'cursors': os.path.join(self.home_dir, '.icons'),
'icons': os.path.join(self.data_dir, 'icons'),
'emoticons': os.path.join(self.data_dir, 'emoticons'),
'themes': os.path.join(self.home_dir, '.themes'),
'emerald_themes': os.path.join(self.home_dir, '.emerald', 'themes'),
'enlightenment_themes': os.path.join(self.home_dir, '.e', 'e', 'themes'),
'enlightenment_backgrounds': os.path.join(self.home_dir, '.e', 'e', 'backgrounds'),
'fluxbox_styles': os.path.join(self.home_dir, '.fluxbox', 'styles'),
'pekwm_themes': os.path.join(self.home_dir, '.pekwm', 'themes'),
'icewm_themes': os.path.join(self.home_dir, '.icewm', 'themes'),
'plasma_plasmoids': os.path.join(self.data_dir, 'plasma', 'plasmoids'),
'plasma_look_and_feel': os.path.join(self.data_dir, 'plasma', 'look-and-feel'),
'plasma_desktopthemes': os.path.join(self.data_dir, 'plasma', 'desktoptheme'),
'kwin_effects': os.path.join(self.data_dir, 'kwin', 'effects'),
'kwin_scripts': os.path.join(self.data_dir, 'kwin', 'scripts'),
'kwin_tabbox': os.path.join(self.data_dir, 'kwin', 'tabbox'),
'aurorae_themes': os.path.join(self.data_dir, 'aurorae', 'themes'),
'dekorator_themes': os.path.join(self.data_dir, 'deKorator', 'themes'),
'qtcurve': os.path.join(self.data_dir, 'QtCurve'),
'color_schemes': os.path.join(self.data_dir, 'color-schemes'),
'gnome_shell_extensions': os.path.join(self.data_dir, 'gnome-shell', 'extensions'),
'cinnamon_applets': os.path.join(self.data_dir, 'cinnamon', 'applets'),
'cinnamon_desklets': os.path.join(self.data_dir, 'cinnamon', 'desklets'),
'cinnamon_extensions': os.path.join(self.data_dir, 'cinnamon', 'extensions'),
'nautilus_scripts': os.path.join(self.data_dir, 'nautilus', 'scripts'),
'amarok_scripts': os.path.join(self.kde_data_dir, 'apps', 'amarok', 'scripts'),
'yakuake_skins': os.path.join(self.kde_data_dir, 'apps', 'yakuake', 'skins'),
'cairo_clock_themes': os.path.join(self.home_dir, '.cairo-clock', 'themes')
}
self.destinations_alias = {
'gnome_shell_themes': self.destinations['themes'],
'cinnamon_themes': self.destinations['themes'],
'gtk2_themes': self.destinations['themes'],
'gtk3_themes': self.destinations['themes'],
'metacity_themes': self.destinations['themes'],
'xfwm4_themes': self.destinations['themes'],
'openbox_themes': self.destinations['themes'],
'kvantum_themes': self.destinations['themes'],
'compiz_themes': self.destinations['emerald_themes'],
'beryl_themes': self.destinations['emerald_themes'],
'plasma4_plasmoids': self.destinations['plasma_plasmoids'],
'plasma5_plasmoids': self.destinations['plasma_plasmoids'],
'plasma5_look_and_feel': self.destinations['plasma_look_and_feel'],
'plasma5_desktopthemes': self.destinations['plasma_desktopthemes'],
'plasma_color_schemes': self.destinations['color_schemes']
}
self.destinations.update(self.destinations_alias)
self.archive_types = {
'tar': [
'application/x-tar',
'application/x-gzip',
'application/gzip',
'application/x-bzip',
'application/x-bzip2',
'application/x-xz',
'application/x-lzma',
'application/x-lzip',
'application/x-compressed-tar',
'application/x-bzip-compressed-tar',
'application/x-bzip2-compressed-tar',
'application/x-xz-compressed-tar',
'application/x-lzma-compressed-tar',
'application/x-lzip-compressed-tar'
],
'zip': ['application/zip'],
'7z': ['application/x-7z-compressed'],
'rar': [
'application/x-rar',
'application/x-rar-compressed'
]
}
#self.config.update(self.read_config('config'))
#self.destinations.update(self.read_config('destinations'))
def read_config(self, name):
path = os.path.join(self.config_dir, name + '.json')
data = {}
if os.path.isfile(path):
f = open(path, 'r')
data = json.load(f)
f.close()
return data
def write_config(self, name, data):
if not os.path.isdir(self.config_dir):
os.makedirs(self.config_dir)
path = os.path.join(self.config_dir, name + '.json')
f = open(path, 'w')
json.dump(data, f)
f.close()
def parse(self):
meta = {
'command': 'download',
'url': '',
'type': 'downloads',
'filename': ''
}
parse_result = urlparse.urlparse(self.xdg_url)
query = urlparse.parse_qs(parse_result.query)
if parse_result.netloc:
meta['command'] = parse_result.netloc
if 'url' in query and query['url'][0]:
meta['url'] = urllib.unquote(query['url'][0])
if 'type' in query and query['type'][0]:
meta['type'] = urllib.unquote(query['type'][0])
if 'filename' in query and query['filename'][0]:
meta['filename'] = urllib.unquote(query['filename'][0]).split('?')[0]
if meta['url'] and not meta['filename']:
meta['filename'] = os.path.basename(meta['url']).split('?')[0]
return meta
"""
def detect_desktop_environment(self):
desktop_environment = 'unknown'
if os.environ.get('KDE_FULL_SESSION') == 'true':
desktop_environment = 'kde'
elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
desktop_environment = 'gnome'
return desktop_environment
"""
def install_plasmapkg(self, path, type='plasmoid'):
status = subprocess.call(['plasmapkg2', '-t', type, '-i', path])
if status == 0:
return True
return False
def uncompress_archive(self, path, target_dir):
(mimetype, encoding) = mimetypes.guess_type(path)
status = None
if mimetype in self.archive_types['tar']:
status = subprocess.call(['tar', '-xf', path, '-C', target_dir])
elif mimetype in self.archive_types['zip']:
status = subprocess.call(['unzip', '-o', path, '-d', target_dir])
elif mimetype in self.archive_types['7z']:
# No space between -o and directory
status = subprocess.call(['7z', 'x', path, '-o' + target_dir])
elif mimetype in self.archive_types['rar']:
status = subprocess.call(['unrar', 'e', path, target_dir])
if status == 0:
return True
return False
def download(self):
url = self.meta['url']
type = self.meta['type']
filename = self.meta['filename']
destination = self.destinations[type]
temp_path = os.path.join(self.temp_dir, filename)
path = os.path.join(destination, filename)
print('Retrieving a file from ' + url)
urllib.urlretrieve(url, temp_path)
print('Creating a directory ' + destination)
if not os.path.isdir(destination):
os.makedirs(destination)
print('Saving a file to ' + path)
os.rename(temp_path, path)
print('Done')
def install(self):
url = self.meta['url']
type = self.meta['type']
filename = self.meta['filename']
destination = self.destinations[type]
temp_path = os.path.join(self.temp_dir, filename)
path = os.path.join(destination, filename)
print('Retrieving a file from ' + url)
urllib.urlretrieve(url, temp_path)
print('Creating a directory ' + destination)
if not os.path.isdir(destination):
os.makedirs(destination)
print('Installing')
if (type in ['plasma_plasmoids', 'plasma4_plasmoids', 'plasma5_plasmoids']
and self.install_plasmapkg(temp_path, 'plasmoid')):
print('The plasmoid has been installed')
os.remove(temp_path)
elif (type in ['plasma_look_and_feel', 'plasma5_look_and_feel']
and self.install_plasmapkg(temp_path, 'lookandfeel')):
print('The plasma look and feel has been installed')
os.remove(temp_path)
elif (type in ['plasma_desktopthemes', 'plasma5_desktopthemes']
and self.install_plasmapkg(temp_path, 'theme')):
print('The plasma desktop theme has been installed')
os.remove(temp_path)
elif (type == 'kwin_effects'
and self.install_plasmapkg(temp_path, 'kwineffect')):
print('The KWin effect has been installed')
os.remove(temp_path)
elif (type == 'kwin_scripts'
and self.install_plasmapkg(temp_path, 'kwinscript')):
print('The KWin script has been installed')
os.remove(temp_path)
elif (type == 'kwin_tabbox'
and self.install_plasmapkg(temp_path, 'windowswitcher')):
print('The KWin window switcher has been installed')
os.remove(temp_path)
elif self.uncompress_archive(temp_path, destination):
print('The archive file has been uncompressed into ' + destination)
os.remove(temp_path)
else:
print('Saving a file to ' + path)
os.rename(temp_path, path)
print('Done')
def execute(self):
if (self.meta['command'] in ['download', 'install']
and self.meta['url']
and self.meta['type'] in self.destinations
and self.meta['filename']):
if self.meta['command'] == 'download':
self.download()
elif self.meta['command'] == 'install':
self.install()
else:
raise Exception('Incorrect XDG-URL ' + self.xdg_url)
'''
class XdgUrlApp(Tkinter.Frame):
"""Confirmation dialog for xdgurl"""
def __init__(self, master=None, core=None):
Tkinter.Frame.__init__(self, master)
self.pack()
self.core = core
self.master.title('xdgurl')
self.master.geometry('300x120')
self.create_widget()
def create_widget(self):
execute_text = 'Download'
if self.core.meta['command'] == 'install':
execute_text = 'Install'
info_label = Tkinter.Label(self, text=execute_text + ': ' + self.core.meta['filename'])
info_label.pack(padx=10, pady=5, anchor=Tkinter.W)
message_label = Tkinter.Label(self, text='Do you want to continue?')
message_label.pack(padx=10, pady=5, anchor=Tkinter.W)
execute_button = Tkinter.Button(self, text=execute_text, command=self.execute)
execute_button.pack(padx=5, pady=10, side=Tkinter.RIGHT)
quit_button = Tkinter.Button(self, text='Cancel', command=self.quit)
quit_button.pack(padx=5, pady=10, side=Tkinter.RIGHT)
def execute(self):
self.core.execute()
sys.exit()
def quit(self):
sys.exit()
'''
def main():
if len(sys.argv) > 1:
"""
window = Tkinter.Tk()
core = XdgUrl(sys.argv[1])
app = XdgUrlApp(window, core)
app.mainloop()
"""
core = XdgUrl(sys.argv[1])
execute_text = 'Download'
if core.meta['command'] == 'install':
execute_text = 'Install'
info_text = execute_text + ': ' + core.meta['filename'] + '\nFrom: ' + core.meta['url']
window = Tkinter.Tk()
window.withdraw()
if tkMessageBox.askyesno('xdgurl', info_text + '\n\nDo you want to continue?'):
try:
core.execute();
except Exception as e:
message = ''
if e.message:
message = e.message
else:
message = str(e)
tkMessageBox.showerror('xdgurl', info_text + '\n\n' + execute_text + ' failed\n' + message)
else:
tkMessageBox.showinfo('xdgurl', info_text + '\n\n' + execute_text + ' finished')
sys.exit()
else:
print('xdgurl "XDG-URL"')
sys.exit()
if __name__ == '__main__':
main()