diff -Nru mythbuntu-common-0.76.1/build/lib/mythbuntu_common/d3des.py mythbuntu-common-0.77/build/lib/mythbuntu_common/d3des.py --- mythbuntu-common-0.76.1/build/lib/mythbuntu_common/d3des.py 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/build/lib/mythbuntu_common/d3des.py 2016-04-01 15:14:55.000000000 +0000 @@ -0,0 +1,387 @@ +#!/usr/bin/env python +## +## d3des.py - DES implementation +## +## Copyright (c) 2009 by Yusuke Shinyama +## Ported to python3: (c) 2013 by Nikita Kovaliov +## + +# This is a Python rewrite of d3des.c by Richard Outerbridge. +# +# I referred to the original VNC viewer code for the changes that +# is necessary to maintain the exact behavior of the VNC protocol. +# Two constants and two functions were added to the original d3des +# code. These added parts were written in Python and marked +# below. I believe that the added parts do not make this program +# a "derivative work" of the VNC viewer (which is GPL'ed and +# written in C), but if there's any problem, let me know. +# +# Yusuke Shinyama (yusuke at cs dot nyu dot edu) + + +# D3DES (V5.09) - +# +# A portable, public domain, version of the Data Encryption Standard. +# +# Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. +# Thanks to: Dan Hoey for his excellent Initial and Inverse permutation +# code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis +# Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, +# for humouring me on. +# +# Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. +# (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. +# + +from struct import pack, unpack + + +################################################### +### +### start: changes made for VNC. +### + +# This constant was taken from vncviewer/rfb/vncauth.c: +vnckey = [23, 82, 107, 6, 35, 78, 88, 7] + +# This is a departure from the original code. +#bytebit = [ 0200, 0100, 040, 020, 010, 04, 02, 01 ] # original +bytebit = [0o01, 0o02, 0o04, 0o010, 0o020, 0o040, 0o0100, 0o0200] # VNC version + + +# two password functions for VNC protocol. +def decrypt_passwd(data): + dk = deskey(pack('8B', *vnckey), True) + return desfunc(data, dk) + + +def generate_response(passwd, challange): + ek = deskey((passwd + b'\x00' * 8)[:8], False) + return desfunc(challange[:8], ek) + desfunc(challange[8:], ek) + + +### +### end: changes made for VNC. +### +################################################### + + +bigbyte = [0x800000, 0x400000, 0x200000, 0x100000, + 0x80000, 0x40000, 0x20000, 0x10000, + 0x8000, 0x4000, 0x2000, 0x1000, + 0x800, 0x400, 0x200, 0x100, + 0x80, 0x40, 0x20, 0x10, + 0x8, 0x4, 0x2, 0x1] + +# Use the key schedule specified in the Standard (ANSI X3.92-1981). + +pc1 = [ + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 + ] + +totrot = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28] + +pc2 = [ + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 + ] + + +def deskey(key, decrypt): # Thanks to James Gillogly & Phil Karn! + key = unpack('8B', key) + + pc1m = [0] * 56 + pcr = [0] * 56 + kn = [0] * 32 + + for j in range(56): + l = pc1[j] + m = l & 0o07 + if key[l >> 3] & bytebit[m]: + pc1m[j] = 1 + else: + pc1m[j] = 0 + + for i in range(16): + if decrypt: + m = (15 - i) << 1 + else: + m = i << 1 + n = m + 1 + kn[m] = kn[n] = 0 + for j in range(28): + l = j + totrot[i] + if l < 28: + pcr[j] = pc1m[l] + else: + pcr[j] = pc1m[l - 28] + for j in range(28, 56): + l = j + totrot[i] + if l < 56: + pcr[j] = pc1m[l] + else: + pcr[j] = pc1m[l - 28] + for j in range(24): + if pcr[pc2[j]]: + kn[m] |= bigbyte[j] + if pcr[pc2[j + 24]]: + kn[n] |= bigbyte[j] + + return cookey(kn) + + +def cookey(raw): + key = [] + for i in range(0, 32, 2): + (raw0, raw1) = (raw[i], raw[i + 1]) + k = (raw0 & 0x00fc0000) << 6 + k |= (raw0 & 0x00000fc0) << 10 + k |= (raw1 & 0x00fc0000) >> 10 + k |= (raw1 & 0x00000fc0) >> 6 + key.append(k) + k = (raw0 & 0x0003f000) << 12 + k |= (raw0 & 0x0000003f) << 16 + k |= (raw1 & 0x0003f000) >> 4 + k |= (raw1 & 0x0000003f) + key.append(k) + return key + +SP1 = [ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 + ] + +SP2 = [ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 + ] + +SP3 = [ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 + ] + +SP4 = [ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 + ] + +SP5 = [ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 + ] + +SP6 = [ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 + ] + +SP7 = [ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 + ] + +SP8 = [ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 + ] + + +def desfunc(block, keys): + (leftt, right) = unpack('>II', block) + + work = ((leftt >> 4) ^ right) & 0x0f0f0f0f + right ^= work + leftt ^= (work << 4) + work = ((leftt >> 16) ^ right) & 0x0000ffff + right ^= work + leftt ^= (work << 16) + work = ((right >> 2) ^ leftt) & 0x33333333 + leftt ^= work + right ^= (work << 2) + work = ((right >> 8) ^ leftt) & 0x00ff00ff + leftt ^= work + right ^= (work << 8) + right = ((right << 1) | ((right >> 31) & 1)) & 0xffffffff + work = (leftt ^ right) & 0xaaaaaaaa + leftt ^= work + right ^= work + leftt = ((leftt << 1) | ((leftt >> 31) & 1)) & 0xffffffff + + for i in range(0, 32, 4): + work = (right << 28) | (right >> 4) + work ^= keys[i] + fval = SP7[work & 0x3f] + fval |= SP5[(work >> 8) & 0x3f] + fval |= SP3[(work >> 16) & 0x3f] + fval |= SP1[(work >> 24) & 0x3f] + work = right ^ keys[i + 1] + fval |= SP8[work & 0x3f] + fval |= SP6[(work >> 8) & 0x3f] + fval |= SP4[(work >> 16) & 0x3f] + fval |= SP2[(work >> 24) & 0x3f] + leftt ^= fval + work = (leftt << 28) | (leftt >> 4) + work ^= keys[i + 2] + fval = SP7[work & 0x3f] + fval |= SP5[(work >> 8) & 0x3f] + fval |= SP3[(work >> 16) & 0x3f] + fval |= SP1[(work >> 24) & 0x3f] + work = leftt ^ keys[i + 3] + fval |= SP8[work & 0x3f] + fval |= SP6[(work >> 8) & 0x3f] + fval |= SP4[(work >> 16) & 0x3f] + fval |= SP2[(work >> 24) & 0x3f] + right ^= fval + + right = (right << 31) | (right >> 1) + work = (leftt ^ right) & 0xaaaaaaaa + leftt ^= work + right ^= work + leftt = (leftt << 31) | (leftt >> 1) + work = ((leftt >> 8) ^ right) & 0x00ff00ff + right ^= work + leftt ^= (work << 8) + work = ((leftt >> 2) ^ right) & 0x33333333 + right ^= work + leftt ^= (work << 2) + work = ((right >> 16) ^ leftt) & 0x0000ffff + leftt ^= work + right ^= (work << 16) + work = ((right >> 4) ^ leftt) & 0x0f0f0f0f + leftt ^= work + right ^= (work << 4) + + leftt &= 0xffffffff + right &= 0xffffffff + return pack('>II', right, leftt) + + +# test +if __name__ == '__main__': + key = bytes.fromhex('0123456789abcdef') + plain = bytes.fromhex('0123456789abcdef') + cipher = bytes.fromhex('6e09a37726dd560c') + ek = deskey(key, decrypt=False) + dk = deskey(key, decrypt=True) + assert desfunc(plain, ek) == cipher + assert desfunc(desfunc(plain, ek), dk) == plain + assert desfunc(desfunc(plain, dk), ek) == plain + print('ok') diff -Nru mythbuntu-common-0.76.1/build/lib/mythbuntu_common/dictionaries.py mythbuntu-common-0.77/build/lib/mythbuntu_common/dictionaries.py --- mythbuntu-common-0.76.1/build/lib/mythbuntu_common/dictionaries.py 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/build/lib/mythbuntu_common/dictionaries.py 2016-04-01 15:14:55.000000000 +0000 @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +# +# «dictionaries» - Manage list of all widget -> package matching +# +# This script: +# Copyright (C) 2008, Mario Limonciello, for Mythbuntu +# +# +# Mythbuntu is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3 of the License, or at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this application; if not, write to the Free Software Foundation, Inc., 51 +# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import string +import subprocess + +#################### +# Type dictionaries: different installation types possible +def get_install_type_dictionary(self): + list= { + "Master Backend/Frontend" : self.master_be_fe, \ + "Slave Backend/Frontend" : self.slave_be_fe, \ + "Master Backend" : self.master_be, \ + "Slave Backend" : self.slave_be, \ + "Frontend" : self.fe, \ + "Set Top Box" : self.stb } + return list + +#################### +#Plugin dictionaries: these are for managing a list of all possible plugins +#################### +def get_frontend_plugin_dictionary(self): + list = { + "mytharchive": self.mytharchive_checkbox, \ + "mythbrowser": self.mythbrowser_checkbox, \ + "mythgame": self.mythgame_checkbox, \ + "mythgallery": self.mythgallery_checkbox, \ + "mythmusic": self.mythmusic_checkbox, \ + "mythnews": self.mythnews_checkbox, \ + "mythnetvision": self.mythnetvision_checkbox, \ + "mythweather": self.mythweather_checkbox } + return list + +def get_backend_plugin_dictionary(self): + return { "mythweb": self.mythweb_checkbox } + +#################### +#Other dictionaries: these are for managing a list of all other apps +#################### +def get_role_dictionary(self): + list = { + "mythtv-backend-master": self.primary_backend_radio, \ + "mythtv-backend": self.secondary_backend_radio, \ + "mythtv-frontend": self.frontend_radio } + return list + +def get_desktop_dictionary(self): + list = { + "ubuntu-desktop": self.ubuntu_desk_check, \ + "xubuntu-desktop": self.xubuntu_desk_check, \ + "kubuntu-desktop": self.kubuntu_desk_check } + return list + +def get_media_app_dictionary(self): + list = { + "mplayer": self.mplayer_checkbox, \ + "xine-ui": self.xine_checkbox, \ + "vlc": self.vlc_checkbox } + return list + +def get_nonfree_dictionary(self): + list = { +# "medibuntu-keyring": self.medibuntu_keyring, \ + "libdvdcss2": self.enable_libdvdcss2 } + return list + +def get_services_dictionary(self,sql_object=None): + list = { + "x11vnc": self.enablevnc, \ + "samba": self.enablesamba, \ + "nfs-kernel-server": self.enablenfs, \ + "openssh-server": self.enablessh, \ + "mysql-server": sql_object } + return list + +def get_diskless_dictionary(self): + list = { + "mythbuntu-diskless-server": self.diskless_server_install, \ + "dhcp3-server": self.diskless_server_dhcp } + return list + +def get_graphics_dictionary(): + list = {} + ##AMD graphics detection + #output=string.split(subprocess.Popen(['lspci'],stdout=subprocess.PIPE).communicate()[0],'\n') + #for line in output: + # if line and 'VGA' in line and ('AMD' in line or 'ATI' in line): + # list["AMD Graphics"]="fglrx" + # break + + #NVIDIA Graphics detection + try: + from NvidiaDetector.nvidiadetector import NvidiaDetection + except ImportError: + return list + + nv = NvidiaDetection().selectDriver() + if nv is not None: + list["NVIDIA Graphics"]=nv + return list + +def get_tweak_dictionary(self): + list = { + "/etc/mysql/conf.d/mythtv-tweaks.cnf": self.enable_mysql_tweaks, \ +# "/etc/cron.daily/mythtv-xfs-defrag": self.enable_nightly_defrag, \ + "/etc/cron.daily/optimize_mythdb": self.enable_mysql_repair} + return list diff -Nru mythbuntu-common-0.76.1/build/lib/mythbuntu_common/installer.py mythbuntu-common-0.77/build/lib/mythbuntu_common/installer.py --- mythbuntu-common-0.76.1/build/lib/mythbuntu_common/installer.py 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/build/lib/mythbuntu_common/installer.py 2016-04-01 15:14:55.000000000 +0000 @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +# +# installer - Functions for use in Mythbuntu ubiquity plugins +# +# Copyright (C) 2010, Mario Limonciello, for Mythbuntu +# +# Mythbuntu is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3 of the License, or at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this application; if not, write to the Free Software Foundation, Inc., 51 +# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +from ubiquity.plugin import * +from ubiquity.misc import create_bool +from gi.repository import Gtk + +class MythPageGtk(PluginUI): + def __init__(self, controller, *args, **kwargs): + def add_widget(plugin, widget): + """Make a widget callable by a plugin.""" + if not isinstance(widget, Gtk.Widget): + return + widget.set_name(Gtk.Buildable.get_name(widget)) + setattr(plugin, widget.get_name(), widget) + if isinstance(widget, Gtk.Label): + widget.set_property('can-focus', False) + + self.controller=controller + try: + builder = Gtk.Builder() + builder.add_from_file('/usr/share/ubiquity/gtk/%s.ui' % self.ui_file) + builder.connect_signals(self) + for widget in builder.get_objects(): + add_widget(self, widget) + self.plugin_widgets = builder.get_object(self.ui_file) + self.controller.add_builder(builder) + except Exception as e: + self.debug('Could not create mythbuntu page: %s', e) + self.plugin_widgets = None + +def preseed_list(lists,names,value): + """Helper function for preseeding dictionary based lists""" + new_value = create_bool(value) + for list in lists: + for item in list: + for name in names.split(): + if item == name: + #be careful what type of item we are dealing with + if type(list[item]) == Gtk.CheckButton: + list[item].set_active(new_value) + elif type(list[item]) == Gtk.Entry: + list[item].set_text(new_value) + elif type(list[item]) == Gtk.ComboBox: + model = list[item].get_model() + for iteration in range(len(list[item]),0): + list[item].set_active(iteration) + iterator = list[item].get_active_iter() + active = model.get_value(iterator, 0) + if active == new_value: + break + else: + list[item].set_active_text(new_value) + +def build_static_list(lists): + """Creates a flat list""" + total_list= {} + for list in lists: + for item in list: + if type(list[item]) == str: + total_list[item]=list[item] + elif type(list[item]) == Gtk.CheckButton: + total_list[item]=list[item].get_active() + elif type(list[item]) == Gtk.Entry: + total_list[item]=list[item].get_text() + else: + model = list[item].get_model() + iterator = model.get_iter_first() + active = model.get_value(iterator, 0) + total_list[item]=active + return total_list diff -Nru mythbuntu-common-0.76.1/build/lib/mythbuntu_common/lirc.py mythbuntu-common-0.77/build/lib/mythbuntu_common/lirc.py --- mythbuntu-common-0.76.1/build/lib/mythbuntu_common/lirc.py 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/build/lib/mythbuntu_common/lirc.py 2016-04-01 15:14:55.000000000 +0000 @@ -0,0 +1,352 @@ +# -*- coding: utf-8 -*- +# +# «lirc» - libmythbuntu class for lirc modifications +# +# This script: +# Copyright (C) 2010, John Baab, for Mythbuntu +# Copyright (C) 2007-2008, Mario Limonciello, for Mythbuntu +# +# +# Mythbuntu is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3 of the License, or at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this application; if not, write to the Free Software Foundation, Inc., 51 +# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import re +import subprocess +import os +import shutil + +#default remote hwdb +REMOTE_HWDB="/usr/share/lirc/lirc.hwdb" +EXTRA_REMOTE_HWDB="/usr/share/lirc/extras/more_remotes.hwdb" +TRANSMITTER_HWDB="/usr/share/lirc/extras/transmitter.hwdb" + +#path to hardware.conf +HARDWARE_CONF="/etc/lirc/hardware.conf" + +#Path to remotes +REMOTE_PATH="/usr/share/lirc/remotes/" + +#path to main lircd.conf +LIRCD_CONF="/etc/lirc/lircd.conf" + +class LircHandler: + + def __init__(self,hw_conf=HARDWARE_CONF): + #initialize all lists + self.remote_list=[] + self.remote="None" + self.remote_modules="" + self.remote_device="" + self.remote_driver="" + self.remote_lircd_conf="" + self.remote_count=0 + self.transmitter_list=[] + self.transmitter="None" + self.transmitter_modules="" + self.transmitter_device="" + self.transmitter_driver="" + self.transmitter_lircd_conf="" + self.transmitter_count=0 + self.populate_devices("remote",REMOTE_HWDB) + self.populate_devices("remote",EXTRA_REMOTE_HWDB) + self.populate_devices("transmitter",TRANSMITTER_HWDB) + self.sort_devices() + #load our current data + self.read_hardware_conf(hw_conf) + + def sort_devices(self): + """Sorts the device list for a type""" + self.remote_list.sort(reverse=True) + self.transmitter_list.sort(reverse=True) + self.remote_list.insert(0,"None") + self.transmitter_list.insert(0,"None") + + def populate_devices(self,type,file): + """Populates all possible remotes from a hwdb. Accepts either 'remote' or 'transmitter' for possible types""" + try: + hwdb = open(file).readlines() + hwdb.sort() + #Filter out uncessary lines + filter = "^\#|^\[" + #Filter out the /dev/input/eventX remote + filter += "|http" + #Filter blaster if we are in remote + if type == 'remote': + filter += "|Blaster" + pattern = re.compile(filter) + for line in hwdb: + if pattern.search(line) is None: + list = line.split(';') + if len(list) > 1: + #Make sure we have a config file before including + if list[4] != "": + if type == "remote": +# self.remote_list.append(list[0].translate(bytes.maketrans('',''),',')) + self.remote_list.append(list[0]) + self.remote_count = self.remote_count + 1 + elif type == "transmitter": + self.transmitter_list.append(list[0]) +# self.transmitter_list.append(list[0].translate(bytes.maketrans('',''),',')) + self.transmitter_count = self.transmitter_count + 1 + except IOError: + print("Error reading " + file + " to parse remote listing.") + #if type == "remote": + # self.remote_list.append("Custom") + # self.remote_count = self.remote_count + 1 + #elif type == "transmitter": + # self.transmitter_list.append("Custom") + # self.transmitter_count = self.transmitter_count + 1 + + def set_device(self,device,type): + """Sets an active remote control or transmitter""" + if type == "remote": + count=self.remote_count + list=self.remote_list + elif type == "transmitter": + count=self.transmitter_count + list=self.transmitter_list + else: + print("Invalid device type: " + type) + return + + found = False + for item in range(count): + if list[item] == device[type]: + if type == "remote": + self.remote = list[item] + elif type == "transmitter": + self.transmitter = list[item] + found = True + break + if device[type] == "Custom": + if type == "remote": + self.remote=device[type] + self.remote_modules=device["remote_modules"] + self.remote_driver=device["remote_driver"] + self.remote_device=device["remote_device"] + self.remote_lircd_conf=device["remote_lircd_conf"] + elif type == "transmitter": + self.transmitter=device[type] + self.transmitter_modules=device["transmitter_modules"] + self.transmitter_driver=device["transmitter_driver"] + self.transmitter_device=device["transmitter_device"] + self.transmitter_lircd_conf=device["transmitter_lircd_conf"] + + def get_device_dictionary(self,type): + """Returns a dictionary of all the info for a given device type""" + if type == "remote": + return {"remote":self.remote, "remote_modules":self.remote_modules, "remote_device": self.remote_device, "remote_driver":self.remote_driver, "remote_lircd_conf":self.remote_lircd_conf} + elif type == "transmitter": + return {"transmitter":self.transmitter, "transmitter_modules":self.transmitter_modules, "transmitter_device": self.transmitter_device, "transmitter_driver":self.transmitter_driver, "transmitter_lircd_conf":self.transmitter_lircd_conf} + + def get_possible_devices(self,type): + """Returns all the possible remotes or transmitters""" + if type == "remote": + return self.remote_list + elif type == "transmitter": + return self.transmitter_list + else: + print("Invalid type: " + type) + return None + + def read_hardware_conf(self,file=HARDWARE_CONF): + """Reads in a lirc hardware configuration""" + try: + in_f=open(file) + remote_pattern=re.compile("^REMOTE=") + found_remote=False + remote_modules_pattern=re.compile("^REMOTE_MODULES=") + remote_device_pattern=re.compile("^REMOTE_DEVICE=") + remote_driver_pattern=re.compile("^REMOTE_DRIVER=") + remote_lircd_conf_pattern=re.compile("^REMOTE_LIRCD_CONF=") + transmitter_pattern=re.compile("^TRANSMITTER=") + found_transmitter=False + transmitter_modules_pattern=re.compile("^TRANSMITTER_MODULES=") + transmitter_device_pattern=re.compile("^TRANSMITTER_DEVICE=") + transmitter_driver_pattern=re.compile("^TRANSMITTER_DRIVER=") + transmitter_lircd_conf_pattern=re.compile("^TRANSMITTER_LIRCD_CONF=") + + for line in in_f: + if remote_pattern.search(line) and not found_remote: + for item in range(self.remote_count): + if (not found_remote) and (self.remote_list[item] == line.split('"')[1]): + found_remote = True + self.remote = line.split('"')[1] + elif remote_modules_pattern.search(line): + self.remote_modules = line.split('"')[1] + elif remote_device_pattern.search(line): + self.remote_device = line.split('"')[1] + elif remote_driver_pattern.search(line): + self.remote_driver = line.split('"')[1] + elif remote_lircd_conf_pattern.search(line): + self.remote_lircd_conf = line.split('"')[1] + elif transmitter_pattern.search(line) and not found_transmitter: + for item in range(self.transmitter_count): + if (not found_transmitter) and (self.transmitter_list[item] == line.split('"')[1]): + found_transmitter = True + self.transmitter = line.split('"')[1] + elif transmitter_modules_pattern.search(line): + self.transmitter_modules = line.split('"')[1] + elif transmitter_device_pattern.search(line): + self.transmitter_device = line.split('"')[1] + elif transmitter_driver_pattern.search(line): + self.transmitter_driver = line.split('"')[1] + elif transmitter_lircd_conf_pattern.search(line): + self.transmitter_lircd_conf = line.split('"')[1] + if not found_remote: + self.remote="" + if not found_transmitter: + self.transmitter="" + in_f.close() + except IOError: + print("Error opening " + file) + + def write_hardware_conf(self,file=HARDWARE_CONF): + """Writes out a hardware.conf""" + patternline="^REMOTE=" + patternline+="|^TRANSMITTER=" + patternline+="|^FORCE_NONINTERACTIVE_RECONFIGURATION=" + #If we are known to be a custom remote, then write out other stuff too + if self.remote == "Custom": + custom_remote = True + patternline+="|^REMOTE_MODULES=" + patternline+="|^REMOTE_DRIVER=" + patternline+="|^REMOTE_LIRCD_CONF=" + else: + custom_remote = False + if self.transmitter == "Custom": + custom_transmitter = True + patternline+="|^TRANSMITTER_MODULES=" + patternline+="|^TRANSMITTER_DRIVER=" + patternline+="|^TRANSMITTER_LIRCD_CONF=" + else: + custom_transmitter = False + pattern=re.compile(patternline) + found_remote=False + found_transmitter=False + lines = None + try: + in_f = open(file) + lines = in_f.readlines() + in_f.close() + except IOError: + print("Unable to find " + file) + out_f = open(file, 'w') + for line in lines: + if pattern.search(line) is None: + out_f.write(line) + continue + else: + if not found_remote and re.compile("^REMOTE=").search(line): + out_f.write("REMOTE=\"" + self.remote + "\"\n") + found_remote = True + continue + elif not found_transmitter and re.compile("^TRANSMITTER=").search(line): + out_f.write("TRANSMITTER=\"" + self.transmitter + "\"\n") + found_transmitter = True + continue + if re.compile("^FORCE_NONINTERACTIVE_RECONFIGURATION=").search(line): + #a reconfigure of lirc will be necessary after writing this hardware conf + out_f.write("FORCE_NONINTERACTIVE_RECONFIGURATION=\"" + "true" + "\"\n") + if custom_remote: + if re.compile("^REMOTE_MODULES=").search(line): + out_f.write("REMOTE_MODULES=\"" + self.remote_modules + "\"\n") + continue + elif re.compile("^REMOTE_DRIVER=").search(line): + out_f.write("REMOTE_DRIVER=\"" + self.remote_driver + "\"\n") + continue + elif re.compile("^REMOTE_DEVICE=").search(line): + out_f.write("REMOTE_DEVICE=\"" + self.remote_device + "\"\n") + continue + elif re.compile("^REMOTE_LIRCD_CONF=").search(line): + out_f.write("REMOTE_LIRCD_CONF=\"" + self.remote_lircd_conf + "\"\n") + continue + if custom_transmitter: + if re.compile("^TRANSMITTER_MODULES=").search(line): + out_f.write("TRANSMITTER_MODULES=\"" + self.transmitter_modules + "\"\n") + continue + elif re.compile("^TRANSMITTER_DRIVER=").search(line): + out_f.write("TRANSMITTER_DRIVER=\"" + self.transmitter_driver + "\"\n") + continue + elif re.compile("^TRANSMITTER_DEVICE=").search(line): + out_f.write("TRANSMITTER_DEVICE=\"" + self.transmitter_device + "\"\n") + continue + elif re.compile("^TRANSMITTER_LIRCD_CONF=").search(line): + out_f.write("TRANSMITTER_LIRCD_CONF=\"" + self.transmitter_lircd_conf + "\"\n") + continue + if not found_remote: + out_f.write("REMOTE=\"" + self.remote + "\"\n") + if not found_transmitter: + out_f.write("TRANSMITTER=\"" + self.transmitter + "\"\n") + out_f.close() + + def reconfigure_lirc(self,interactive=False): + """Restarts & Reconfigures LIRC""" + if interactive: + os.putenv('DEBIAN_FRONTEND','gnome') + else: + os.putenv('DEBIAN_FRONTEND','noninteractive') + lirc_command = subprocess.Popen(["/usr/sbin/dpkg-reconfigure", "lirc"],stdout=subprocess.PIPE).communicate()[0] + print(lirc_command) + + def query_advanced(self,remote_hwdb_file=REMOTE_HWDB,transmitter_hwdb_file=TRANSMITTER_HWDB): + """Determine if this remote requires interactive configuration""" + + advanced_driver_pattern=re.compile("devinput") + advanced_modules_pattern=re.compile("serial") + + remote_hwdb = open(remote_hwdb_file).readlines() + transmitter_hwdb = open(transmitter_hwdb_file).readlines() + + #Filter out uncessary lines + filter = "^\#|^\[" + pattern = re.compile(filter) + #search advanced remotes + for line in remote_hwdb: + if pattern.search(line) is None: + list = line.split(";") + if len(list) > 1 and list[0].translate(bytes.maketrans('',''),',') == self.remote: + if advanced_driver_pattern.search(list[1]) or advanced_modules_pattern.search(list[2]): + return True + #search advanced transmitters + for line in transmitter_hwdb: + if pattern.search(line) is None: + list = line.split(";") + if len(list) > 1 and list[0].translate(bytes.maketrans('',''),',') == self.remote: + if advanced_driver_pattern.search(list[1]) or advanced_modules_pattern.search(list[2]): + return True + return False + def create_lircrc(self,file=LIRCD_CONF,change_permissions=True,irexec=False,irexec_only=False): + """Generates lircrc files for all possible applications""" + + command = "mythbuntu-lircrc-generator" + + if file != LIRCD_CONF: + command = command + " -L " + file + + if irexec == True: + command = command + " --irexec 1" + + if irexec_only == True: + command = command + " --mythtv 0 --mplayer 0 --totem 0 --elisa 0 --xine 0 --vlc 0 --xmame 0 --xmess 0" + + if change_permissions: + uid = os.getenv('SUDO_UID') + if uid != None: + in_f=open("/etc/passwd") + for line in in_f: + fields = line.split(":") + if fields[2] == uid: + command = "su " + fields[0] + " -c " + command + os.system(command) diff -Nru mythbuntu-common-0.76.1/build/lib/mythbuntu_common/mysql.py mythbuntu-common-0.77/build/lib/mythbuntu_common/mysql.py --- mythbuntu-common-0.76.1/build/lib/mythbuntu_common/mysql.py 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/build/lib/mythbuntu_common/mysql.py 2016-04-01 15:14:55.000000000 +0000 @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +# +# «mysql» - mythbuntu class for mysql mangling +# +# This script: +# Copyright (C) 2007-2010, Mario Limonciello, for Mythbuntu +# +# +# Mythbuntu is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3 of the License, or at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this application; if not, write to the Free Software Foundation, Inc., 51 +# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import shutil +import os +import subprocess +import re +import string +import xml.dom.minidom + + +#pymysql isn't available yet. +#for now don't fail on import +try: + import pymysql +except: + pass + +class MySQLHandler: + """MySQL configuration, mangling, and activation class""" + + def __init__(self,config={"user":"mythtv","password":"mythtv","server":"localhost","database":"mythconverg","securitypin":"0000"}): + self.user=config["user"] + self.password=config["password"] + self.server=config["server"] + self.database=config["database"] + self.securitypin=config["securitypin"] + + def _config_xml(self, file=None): + """Reads in and parses and writes a config.xml from a number of places: + 1) /etc/mythtv/config.xml + 2) /usr/share/mythtv/config.xml + Returns a dictionary filled with references that can be parsed or processed + """ + dictionary={"doc": None, 'DBHostName': None, 'DBUserName': None, 'DBPassword': None, 'DBName': None, 'SecurityPin' : None} + for file in [file, '/etc/mythtv/config.xml', '/usr/share/mythtv/config.xml' ]: + if file and os.path.exists(file): + dictionary["doc"]=xml.dom.minidom.parse(file) + for tag in dictionary: + elements=dictionary["doc"].getElementsByTagName(tag) + if elements: + dictionary[tag]=elements[0] + elif tag != "doc": + dictionary[tag]=dictionary["doc"].createElement(tag) + break + return dictionary + + def write_xml(self,file): + """Writes XML to a file""" + dict=self._config_xml(file) + if dict['DBHostName'].hasChildNodes(): + dict['DBHostName'].childNodes[0].replaceWholeText(self.server) + else: + node = dom.xml.minidom.createTextNode(self.server) + dict['DBHostName'].appendChild(node) + if dict['DBUserName'].hasChildNodes(): + dict['DBUserName'].childNodes[0].replaceWholeText(self.user) + else: + node = dom.xml.minidom.createTextNode(self.user) + dict['DBUserName'].appendChild(node) + if dict['DBPassword'].hasChildNodes(): + dict['DBPassword'].childNodes[0].replaceWholeText(self.password) + else: + node = dom.xml.minidom.createTextNode(self.password) + dict['DBPassword'].appendChild(node) + if dict['DBName'].hasChildNodes(): + dict['DBName'].childNodes[0].replaceWholeText(self.database) + else: + node = dom.xml.minidom.createTextNode(self.database) + dict['DBName'].appendChild(node) + if dict['SecurityPin'].hasChildNodes(): + dict['SecurityPin'].childNodes[0].replaceWholeText(self.securitypin) + else: + node = dom.xml.minidom.createTextNode(self.securitypin) + dict['SecurityPin'].appendChild(node) + + dict["doc"].writexml(open(file, 'w')) + + def read_xml(self,file): + dict=self._config_xml(file) + if dict['DBHostName'].hasChildNodes(): + self.server = dict['DBHostName'].childNodes[0].data + if dict['DBUserName'].hasChildNodes(): + self.user = dict['DBUserName'].childNodes[0].data + if dict['DBPassword'].hasChildNodes(): + self.password = dict['DBPassword'].childNodes[0].data + if dict['DBName'].hasChildNodes(): + self.database = dict['DBName'].childNodes[0].data + if dict['SecurityPin'].hasChildNodes(): + self.securitypin = dict['SecurityPin'].childNodes[0].data + + def toggle_mysql_service_config(self,enable): + """Enables and disables the mysql service on all interfaces""" + if not os.path.exists("/etc/mysql/conf.d"): + os.mkdir("/etc/mysql/conf.d") + lines = None + out_f = None + found = False + pattern = re.compile("^bind-address|^#bind-address") + try: + in_f = open("/etc/mysql/conf.d/mythtv.cnf") + lines = in_f.readlines() + in_f.close() + out_f=open("/etc/mysql/conf.d/mythtv.cnf","w") + for line in lines: + if pattern.search(line) is None: + out_f.write(line) + elif not found: + if enable: + out_f.write("bind-address=::\n") + else: + out_f.write("#bind-address=::\n") + found = True + if not found: + if enable: + out_f.write("bind-address=::\n") + else: + out_f.write("#bind-address=::\n") + except IOError: + print("/etc/mysql/conf.d/mythtv.cnf not found") + out_f=open("/etc/mysql/conf.d/mythtv.cnf","w") + out_f.write("[mysqld]\n") + if enable: + out_f.write("bind-address=::\n") + else: + out_f.write("#bind-address=::\n") + out_f.close() + + def restart_mysql_service(self): + """Restarts MySQL service""" + start_mysql = subprocess.Popen(["/usr/sbin/invoke-rc.d", "mysql", "restart"],stdout=subprocess.PIPE).communicate()[0] + print(start_mysql) + + def update_config(self,config): + """Sets up a new configuration based on the dict {user,pass,server,db,securitypin}""" + self.user=config["user"] + self.password=config["password"] + self.server=config["server"] + self.database=config["database"] + self.securitypin=config["securitypin"] + + def get_config(self): + """Returns our currently stored configuration""" + return {"user":self.user,"password":self.password,"server":self.server,"database":self.database,"securitypin":self.securitypin} + + def reset_user_password(self,admin_pass,password): + """Resets a user's password if it was forgotten""" + commands = ["UPDATE user SET Password=PASSWORD('"+password+"') WHERE user=mythtv')", + "FLUSH PRIVILEGES"] + if self.run_mysql_commands(commands,mysql_user="root"): + return "Successful" + else: + return "Failure" + + def run_mysql_commands(self,commands,mysql_user=None): + """Runs mysql command(s) and returns the response""" + if mysql_user is None: + mysql_user = self.user + try: + db = pymysql.Connect(host=self.server, user=mysql_user, passwd=self.password,database=self.database) + cursor = db.cursor() + if type(commands) is list: + for command in commands: + cursor.execute(command) + result = cursor.fetchone() + elif type(commands) is str: + result = cursor.execute(commands) + else: + print("Unknown type") + cursor.close() + db.close() + except: + result = False + return result + + def do_connection_test(self, pin): + """Tests to make sure that the backend is accessible""" + try: + import MythTV + except ImportError: + return False + args = { 'SecurityPin' : pin } + #figure out whether 0.24+ or 0.23 + try: + method = getattr(MythTV, "MythDBBase") + except AttributeError: + method = getattr(MythTV, "MythDB") + try: + db_base = method(args=args) + except Exception as e: + return str(e) diff -Nru mythbuntu-common-0.76.1/build/lib/mythbuntu_common/vnc.py mythbuntu-common-0.77/build/lib/mythbuntu_common/vnc.py --- mythbuntu-common-0.76.1/build/lib/mythbuntu_common/vnc.py 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/build/lib/mythbuntu_common/vnc.py 2016-04-01 15:14:55.000000000 +0000 @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# +# «vnc» - libmythbuntu class for adding/removing VNC from configuration +# +# This script: +# Copyright (C) 2007-2008, Mario Limonciello, for Mythbuntu +# +# +# Mythbuntu is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3 of the License, or at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this application; if not, write to the Free Software Foundation, Inc., 51 +# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import sys +import shutil +from mythbuntu_common import d3des + +#import xorgconfig +import xkit +from xkit import xutils + +#Script Directory +SCRIPTDIR = '/usr/share/mythbuntu-common/scripts' + +class VNCHandler: + """Used to properly enable VNC in a target configuration""" + + def __init__(self,root=''): + self.add_modules = ["vnc"] + self.add_screen = [ ['SecurityTypes', 'VncAuth'], ['UserPasswdVerifier', 'VncAuth'], ['PasswordFile', '/root/.vnc/passwd']] + self.root = root + + self.xorg_conf_path = '/etc/X11/xorg.conf' + + try: + self.xorg_conf = xutils.XUtils(self.xorg_conf_path) + except(IOError, xkit.xorgparser.ParseException):#if xorg.conf is missing or broken + self.xorg_conf = xutils.XUtils() + + def create_password(self,password): + home = os.environ['HOME'] + if not os.path.exists(home + "/.vnc"): + os.mkdir(home + "/.vnc") + elif os.path.exists(home + "/.vnc/passwd"): + print("Copying ~/.vnc/passwd to ~/.vnc/passwd.old") + shutil.copy(home + "/.vnc/passwd",home + "/.vnc/passwd.old") + + if not isinstance(password, bytes): + raise ValueError('Password should be passed as bytes') + passpadd = (password + b'\x00' * 8)[:8] + strkey = bytes(d3des.vnckey) + ekey = d3des.deskey(strkey, False) + ctext = d3des.desfunc(passpadd, ekey) + with open(home + "/.vnc/passwd", 'wb') as f: + f.write(ctext) + + def toggle_xorg(self,enable): + """Adds necessary lines for enabling VNC upon the next boot""" + + # backup the current xorg.conf + open(os.path.join(self.root + self.xorg_conf_path + ".old"), "w").write(open(self.root + self.xorg_conf_path).read()) + + + #Revert any existing settings first + have_modules = len(self.xorg_conf.globaldict["Module"]) > 0 + have_screens = len(self.xorg_conf.globaldict["Screen"]) > 0 + + if have_modules: + for m in self.add_modules: + self.xorg_conf.removeOption("Module", "Load", value=m, position=0) + + if have_screens: + for item in self.add_screen: + self.xorg_conf.removeOption("Screen", item[0], position=0) + + + #Now re-enable if we want to + if enable: + if self.add_modules: + if not have_modules: + self.xorg_conf.makeSection("Module") + for m in self.add_modules: + self.xorg_conf.addOption("Module", "Load", m, position=0) + + if not have_screens: + self.xorg_conf.makeSection("Screen", identifier="Default Screen") + for item in self.add_screen: + self.xorg_conf.addOption("Screen", item[0], item[1], optiontype="Option", position=0) + + self.xorg_conf.writeFile(self.root + self.xorg_conf_path) + diff -Nru mythbuntu-common-0.76.1/.bzr/branch/branch.conf mythbuntu-common-0.77/.bzr/branch/branch.conf --- mythbuntu-common-0.76.1/.bzr/branch/branch.conf 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/branch/branch.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -parent_location = http://bazaar.launchpad.net/~mythbuntu-dev/mythbuntu/mythbuntu-common/ diff -Nru mythbuntu-common-0.76.1/.bzr/branch/format mythbuntu-common-0.77/.bzr/branch/format --- mythbuntu-common-0.76.1/.bzr/branch/format 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/branch/format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Bazaar Branch Format 7 (needs bzr 1.6) diff -Nru mythbuntu-common-0.76.1/.bzr/branch/last-revision mythbuntu-common-0.77/.bzr/branch/last-revision --- mythbuntu-common-0.76.1/.bzr/branch/last-revision 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/branch/last-revision 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -338 thomas@mashos.com-20160218005613-y3qx2lzjq0tva5m1 diff -Nru mythbuntu-common-0.76.1/.bzr/branch/tags mythbuntu-common-0.77/.bzr/branch/tags --- mythbuntu-common-0.76.1/.bzr/branch/tags 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/branch/tags 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -d13:0.41-0ubuntu150:superm1@ubuntu.com-20100126092921-rsm40bti9oxzg7oa13:0.42-0ubuntu150:superm1@ubuntu.com-20100204083207-3ejcipjddtgogndn13:0.43-0ubuntu150:superm1@ubuntu.com-20100216065158-jj9byth1tfdsif6113:0.44-0ubuntu150:superm1@ubuntu.com-20100218005902-foxkwd6z3nwelgca13:0.45-0ubuntu150:superm1@ubuntu.com-20100218062643-eawfxbq0de61svh613:0.46-0ubuntu150:superm1@ubuntu.com-20100222022623-ftt06mfgft2gfawh13:0.47-0ubuntu150:superm1@ubuntu.com-20100306231942-8rvyupo2db5uf5gd13:0.48-0ubuntu158:mario_limonciello@dell.com-20100328055752-aa2y3rck1od5ly5913:0.48-0ubuntu250:superm1@ubuntu.com-20100403223617-k352ng5z76820xnp13:0.49-0ubuntu150:superm1@ubuntu.com-20100403224157-naavu5hlsw3fl2qx13:0.49-0ubuntu250:superm1@ubuntu.com-20100404002305-k615l06yshybl3zl13:0.50-0ubuntu158:mario_limonciello@dell.com-20100419060954-s442m3cd32hbbksy13:0.51-0ubuntu158:mario_limonciello@dell.com-20100812181503-vucahbr2xzvz5dd313:0.51-0ubuntu258:mario_limonciello@dell.com-20100814073516-ra34gjrx9j9ivs8z13:0.52-0ubuntu158:mario_limonciello@dell.com-20100831153030-sd6m22remn4a2u1f13:0.53-0ubuntu158:mario_limonciello@dell.com-20100909013521-ncsesok2ewkwhzc313:0.54-0ubuntu158:mario_limonciello@dell.com-20100916040228-nsg63kmjp9gz0wqn13:0.55-0ubuntu158:mario_limonciello@dell.com-20110202235536-gsqg6uxvc9germwd13:0.56-0ubuntu150:superm1@ubuntu.com-20110208083130-zt2l22gv1gkyhvyr13:0.57-0ubuntu153:davewalker@ubuntu.com-20110224030158-ske7wz68rctrf0t013:0.58-0ubuntu158:mario_limonciello@dell.com-20110318072258-97bs1bq903fks1ji13:0.59-0ubuntu158:mario_limonciello@dell.com-20110417212505-i46auz2jc00xsh8x13:0.60-0ubuntu158:mario_limonciello@dell.com-20110808171529-78eb3sfa1irh0e6a4:0.6158:mario_limonciello@dell.com-20110829030222-o6abu37jbd2yd0gd4:0.6258:mario_limonciello@dell.com-20110909210920-ogyn0odlskna6h6k4:0.6358:mario_limonciello@dell.com-20111005051143-gdwv281n55mpu45i4:0.6458:mario_limonciello@dell.com-20111207162422-iiv19j9nvlzrv0yo4:0.6558:mario_limonciello@dell.com-20111209053505-9ffk6e42zt332ehf4:0.6658:mario_limonciello@dell.com-20120117171245-5w95dub4ylcjlpwa4:0.6758:mario_limonciello@dell.com-20120410195751-w77x4le2evyzlxl54:0.6958:mario_limonciello@dell.com-20131112071650-vrertz5bir508riq4:0.7058:mario_limonciello@dell.com-20131113040528-rxdkp120iz41qmxk4:0.7158:mario_limonciello@dell.com-20140410161648-htey957e1kpgi0o84:0.7258:mario_limonciello@dell.com-20140410162716-a4s20afrpuyfw2x04:0.7358:mario_limonciello@dell.com-20140417184307-dludpf26r44z1g414:0.7449:thomas@mashos.com-20140508210712-ggonxdeuy44j02dhe \ No newline at end of file diff -Nru mythbuntu-common-0.76.1/.bzr/branch-format mythbuntu-common-0.77/.bzr/branch-format --- mythbuntu-common-0.76.1/.bzr/branch-format 2016-02-27 15:52:34.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/branch-format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Bazaar-NG meta directory, format 1 diff -Nru mythbuntu-common-0.76.1/.bzr/checkout/conflicts mythbuntu-common-0.77/.bzr/checkout/conflicts --- mythbuntu-common-0.76.1/.bzr/checkout/conflicts 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/checkout/conflicts 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -BZR conflict list format 1 Binary files /tmp/tmpFAL3f3/mzwG_32jmH/mythbuntu-common-0.76.1/.bzr/checkout/dirstate and /tmp/tmpFAL3f3/yrnMrbI6iI/mythbuntu-common-0.77/.bzr/checkout/dirstate differ diff -Nru mythbuntu-common-0.76.1/.bzr/checkout/format mythbuntu-common-0.77/.bzr/checkout/format --- mythbuntu-common-0.76.1/.bzr/checkout/format 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/checkout/format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Bazaar Working Tree Format 6 (bzr 1.14) diff -Nru mythbuntu-common-0.76.1/.bzr/README mythbuntu-common-0.77/.bzr/README --- mythbuntu-common-0.76.1/.bzr/README 2016-02-27 15:52:34.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -This is a Bazaar control directory. -Do not change any files in this directory. -See http://bazaar.canonical.com/ for more information about Bazaar. diff -Nru mythbuntu-common-0.76.1/.bzr/repository/format mythbuntu-common-0.77/.bzr/repository/format --- mythbuntu-common-0.76.1/.bzr/repository/format 2016-02-27 15:52:34.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/repository/format 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Bazaar repository format 2a (needs bzr 1.16 or later) Binary files /tmp/tmpFAL3f3/mzwG_32jmH/mythbuntu-common-0.76.1/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.cix and /tmp/tmpFAL3f3/yrnMrbI6iI/mythbuntu-common-0.77/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.cix differ Binary files /tmp/tmpFAL3f3/mzwG_32jmH/mythbuntu-common-0.76.1/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.iix and /tmp/tmpFAL3f3/yrnMrbI6iI/mythbuntu-common-0.77/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.iix differ Binary files /tmp/tmpFAL3f3/mzwG_32jmH/mythbuntu-common-0.76.1/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.rix and /tmp/tmpFAL3f3/yrnMrbI6iI/mythbuntu-common-0.77/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.rix differ diff -Nru mythbuntu-common-0.76.1/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.six mythbuntu-common-0.77/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.six --- mythbuntu-common-0.76.1/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.six 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.six 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -B+Tree Graph Index 2 -node_ref_lists=0 -key_elements=1 -len=0 -row_lengths= Binary files /tmp/tmpFAL3f3/mzwG_32jmH/mythbuntu-common-0.76.1/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.tix and /tmp/tmpFAL3f3/yrnMrbI6iI/mythbuntu-common-0.77/.bzr/repository/indices/48350aa3b825783bb9736f16798a0af6.tix differ diff -Nru mythbuntu-common-0.76.1/.bzr/repository/pack-names mythbuntu-common-0.77/.bzr/repository/pack-names --- mythbuntu-common-0.76.1/.bzr/repository/pack-names 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/.bzr/repository/pack-names 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -B+Tree Graph Index 2 -node_ref_lists=0 -key_elements=1 -len=1 -row_lengths=1 -x DZ Pk`oaN)dؼ~ϺvqNty $RL2vv -9# \ No newline at end of file Binary files /tmp/tmpFAL3f3/mzwG_32jmH/mythbuntu-common-0.76.1/.bzr/repository/packs/48350aa3b825783bb9736f16798a0af6.pack and /tmp/tmpFAL3f3/yrnMrbI6iI/mythbuntu-common-0.77/.bzr/repository/packs/48350aa3b825783bb9736f16798a0af6.pack differ diff -Nru mythbuntu-common-0.76.1/Changelog mythbuntu-common-0.77/Changelog --- mythbuntu-common-0.76.1/Changelog 2016-02-27 16:02:39.000000000 +0000 +++ mythbuntu-common-0.77/Changelog 2016-04-03 20:51:43.000000000 +0000 @@ -1,4 +1,13 @@ -mythbuntu-common (0.76.1) xenial; urgency=medium +mythbuntu-common (0.77) xenial; urgency=medium + + * Disable mythexport plugin. It will be removed in this release. + * Update repos.db to match releases in xenial. + * Include a .desktop file pointing to setup instructions. + * Update postinst for mythtv 0.28 version + + -- Mario Limonciello Sun, 03 Apr 2016 15:51:36 -0500 + +mythbuntu-common (0.76) trusty; urgency=medium * Ask and enable update repo during install diff -Nru mythbuntu-common-0.76.1/debian/changelog mythbuntu-common-0.77/debian/changelog --- mythbuntu-common-0.76.1/debian/changelog 2016-02-27 16:02:39.000000000 +0000 +++ mythbuntu-common-0.77/debian/changelog 2016-04-03 20:51:43.000000000 +0000 @@ -1,4 +1,13 @@ -mythbuntu-common (0.76.1) xenial; urgency=medium +mythbuntu-common (0.77) xenial; urgency=medium + + * Disable mythexport plugin. It will be removed in this release. + * Update repos.db to match releases in xenial. + * Include a .desktop file pointing to setup instructions. + * Update postinst for mythtv 0.28 version + + -- Mario Limonciello Sun, 03 Apr 2016 15:51:36 -0500 + +mythbuntu-common (0.76) trusty; urgency=medium * Ask and enable update repo during install diff -Nru mythbuntu-common-0.76.1/debian/install mythbuntu-common-0.77/debian/install --- mythbuntu-common-0.76.1/debian/install 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/debian/install 2016-04-03 20:24:42.000000000 +0000 @@ -1 +1,2 @@ debian/mythbuntu.make usr/share/mythbuntu +debian/setup-instructions.desktop /usr/share/mythbuntu diff -Nru mythbuntu-common-0.76.1/debian/postinst mythbuntu-common-0.77/debian/postinst --- mythbuntu-common-0.76.1/debian/postinst 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/debian/postinst 2016-04-03 20:10:02.000000000 +0000 @@ -6,7 +6,7 @@ db_get mythbuntu/repos if [ "$RET" = "true" ]; then - /usr/bin/apt-add-repository -y ppa:mythbuntu/0.27 + /usr/bin/apt-add-repository -y ppa:mythbuntu/0.28 fi ;; diff -Nru mythbuntu-common-0.76.1/debian/setup-instructions.desktop mythbuntu-common-0.77/debian/setup-instructions.desktop --- mythbuntu-common-0.76.1/debian/setup-instructions.desktop 1970-01-01 00:00:00.000000000 +0000 +++ mythbuntu-common-0.77/debian/setup-instructions.desktop 2016-04-03 19:51:44.000000000 +0000 @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=MythTV Setup Instructions +Comment=instructions for setting up +GenericName=Setup Instructions +Exec=xdg-open https://www.mythtv.org/wiki/Configuring_MythTV +Type=Application +Icon=chromium-browser +Categories=GTK;System;Settings; +NoDisplay=true diff -Nru mythbuntu-common-0.76.1/plugins/python/mythexport.py mythbuntu-common-0.77/plugins/python/mythexport.py --- mythbuntu-common-0.76.1/plugins/python/mythexport.py 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/plugins/python/mythexport.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -## -*- coding: utf-8 -*- -# -# «MythExport» - A MythExport Plugin for MCC -# -# Copyright (C) 2009, John Baab, for Mythbuntu -# -# -# Mythbuntu is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this application; if not, write to the Free Software Foundation, Inc., 51 -# Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -################################################################################## - -from MythbuntuControlCentre.plugin import MCCPlugin -from gi.repository import Gtk -import os - -class MythExportPlugin(MCCPlugin): - """A plugin to enable or disable mythexport""" - # - #Load GUI & Calculate Changes - # - CONFIGFILE = "/etc/default/mythexport-install" - - def __init__(self): - #Initialize parent class - information = {} - information["name"] = "MythExport" - information["icon"] = "gtk-leave-fullscreen" - information["ui"] = "tab_mythexport" - MCCPlugin.__init__(self,information) - import configparser - self.config = configparser.ConfigParser() - - def captureState(self): - """Determines the state of the items on managed by this plugin - and stores it into the plugin's own internal structures""" - import os - self.changes = {} - self.changes['mythexport'] = self.query_installed('mythexport') - - if os.path.exists(self.CONFIGFILE): - self.config.read(self.CONFIGFILE) - self.changes['dir'] = self.config.get("cfg", "dir") - else: - self.changes['dir'] = "/var/lib/mythtv/" - - def applyStateToGUI(self): - """Takes the current state information and sets the GUI - for this plugin""" - self.mythexport_checkbox.set_active(self.changes['mythexport']) - self.export_dir.set_current_folder(self.changes['dir']) - if self.changes['mythexport']: - self.configuration_linkbutton.show() - self.export_dir.set_sensitive(True); - else: - self.configuration_linkbutton.hide() - self.export_dir.set_sensitive(False); - - def compareState(self): - """Determines what items have been modified on this plugin""" - MCCPlugin.clearParentState(self) - if self.mythexport_checkbox.get_active() != self.changes['mythexport']: - if self.mythexport_checkbox.get_active(): - self._markInstall('mythexport') - self._markReconfigureRoot('dir',self.export_dir.get_filename()) - else: - self._markRemove('mythexport') - elif self.mythexport_checkbox.get_active() == True and self.export_dir.get_filename() != self.changes['dir']: - self._markReconfigureRoot('dir',self.export_dir.get_filename()) - - # - # Process selected activities - # - - def root_scripted_changes(self,reconfigure): - """System-wide changes that need root access to be applied. - This function is ran by the dbus backend""" - if os.path.exists(self.CONFIGFILE): - self.config.read(self.CONFIGFILE) - else: - self.config.add_section("cfg") - for item in reconfigure: - self.config.set("cfg", item, reconfigure[item]) - - with open(self.CONFIGFILE, 'w', encoding='utf8') as configfile: - self.config.write(configfile) - os.system("DEBIAN_FRONTEND=noninteractive dpkg-reconfigure mythexport") - - diff -Nru mythbuntu-common-0.76.1/plugins/ui/tab_mythexport.ui mythbuntu-common-0.77/plugins/ui/tab_mythexport.ui --- mythbuntu-common-0.76.1/plugins/ui/tab_mythexport.ui 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/plugins/ui/tab_mythexport.ui 1970-01-01 00:00:00.000000000 +0000 @@ -1,190 +0,0 @@ - - - - - - True - 6 - vertical - - - True - True - 0 - <big><b>MythExport</b></big> - True - True - - - False - False - 0 - - - - - True - - - False - False - 6 - 1 - - - - - True - vertical - 10 - - - 525 - True - 0 - MythExport is a Perl daemon that can be used with MythTV to export recordings into a format playable on portable devices such as iPod Video, iPod Touch, PSP, and other devices. For more information, or to see a full feature list, please use the 'Help / More Information' link below. - True - - - 0 - - - - - True - 0 - <b>Available Actions</b> - True - - - 1 - - - - - True - 0 - 0 - 25 - - - Enable MythExport - True - True - False - True - - - - - 2 - - - - - True - 0 - <b>Required Installation Inputs</b> - True - - - 3 - - - - - True - 0 - 0 - 25 - - - True - 13 - Choose a directory where you would like MythExport to store files: - - - - - 4 - - - - - True - 0 - 0 - 25 - - - True - select-folder - True - - - - - 5 - - - - - True - 0 - <b>Additional Information</b> - True - - - 6 - - - - - True - 0 - 0 - 25 - - - Launch Configuration Site - True - True - none - http://localhost/mythexport - - - - - 7 - - - - - True - 0 - 0 - 25 - - - Help / More Informtion - True - True - True - none - https://help.ubuntu.com/community/MythExport - - - - - 8 - - - - - False - 6 - 2 - - - - diff -Nru mythbuntu-common-0.76.1/po/POTFILES.in mythbuntu-common-0.77/po/POTFILES.in --- mythbuntu-common-0.76.1/po/POTFILES.in 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/po/POTFILES.in 2016-04-01 15:14:55.000000000 +0000 @@ -1,16 +1,16 @@ -./plugins/ui/tab_system_roles.ui -./plugins/ui/tab_proprietary_codecs.ui +./plugins/ui/tab_plugins.ui +./plugins/ui/tab_mysql_configuration.ui ./plugins/ui/tab_remote_control.ui +./plugins/ui/tab_repos.ui ./plugins/ui/tab_startup_behavior.ui -./plugins/ui/tab_mythexport.ui -./plugins/ui/tab_mysql_configuration.ui -./plugins/ui/tab_plugins.ui ./plugins/ui/tab_services.ui -./plugins/python/mythexport.py -./plugins/python/mysql_configuration.py -./plugins/python/remote.py +./plugins/ui/tab_proprietary_codecs.ui +./plugins/ui/tab_system_roles.ui +./plugins/python/mythbuntu_repos.py ./plugins/python/services.py ./plugins/python/plugins.py +./plugins/python/mysql_configuration.py +./plugins/python/system_roles.py ./plugins/python/startup_behavior.py +./plugins/python/remote.py ./plugins/python/proprietary_codecs.py -./plugins/python/system_roles.py diff -Nru mythbuntu-common-0.76.1/repos.db mythbuntu-common-0.77/repos.db --- mythbuntu-common-0.76.1/repos.db 2016-02-27 15:53:00.000000000 +0000 +++ mythbuntu-common-0.77/repos.db 2016-04-03 14:44:06.000000000 +0000 @@ -1,4 +1,4 @@ -MYTHTV_RELEASE 0.27 +MYTHTV_RELEASE 0.28 TRUNKPASS YouMustBeThisTallToRide karmic fixes-0.21 @@ -31,6 +31,9 @@ nadia 0.26 precise 0.26 maya 0.26 +wily 0.27 +vivid 0.27 +utopic 0.27 trusty 0.27 saucy 0.27 petra 0.27 @@ -38,6 +41,10 @@ olivia 0.27 precise 0.27 maya 0.27 +xenial 0.28 +wily 0.28 +vivid 0.28 +utopic 0.28 trusty 0.28 saucy 0.28 petra 0.28 @@ -45,3 +52,4 @@ olivia 0.28 precise 0.28 maya 0.28 +xenial 0.29