Ejemplo n.º 1
0
def chmod(path, ch_mod, su=False, silent=False):
    """
    Cambia los permisos de un archivo o carpeta en sistemas Linux y derivados
    @param path: ruta
    @type path: str
    @param ch_mod: permisos
    @type ch_mod: str
    @param su: super-user, con diferentes variantes según plataforma
    @type su: bool
    @rtype: str
    @return: File-Info de un archivo o carpeta
    """
    path = encode(path)
    res = False
    error_cmd = True

    if KODI and xbmc.getCondVisibility("system.platform.windows"):
        if not silent:
            logger.info('Command ERROR: CHMOD no soportado en esta plataforma',
                        force=True)
    else:
        try:
            import subprocess
            from platformcode import config
            if not su:
                command = ['chmod', ch_mod, path]
                if not silent:
                    logger.info('Command: %s' % str(command), force=True)
                p = subprocess.Popen(command,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
                output_cmd, error_cmd = p.communicate()
            elif su and config.is_rooted(silent=True) == 'rooted':
                for subcmd in ['-c', '-0']:
                    for cmdtype in [['chmod', ch_mod, path],
                                    ['chmod %s %s' % (ch_mod, path)]]:
                        command = ['su', subcmd] + cmdtype
                        output_cmd, error_cmd = config.su_command(
                            command, silent=silent)
                        if not error_cmd:
                            break
                    if not error_cmd:
                        break
                else:
                    raise

            if not silent and error_cmd:
                logger.error('Command ERROR: %s, %s' %
                             (str(command), str(error_cmd)))
        except:
            if not silent:
                logger.error(traceback.format_exc())

    # Pedir file_info del archivo o carpeta
    res = file_info(path, silent=silent)
    if not silent:
        logger.info('File-stat: %s' % str(res), force=True)

    return res
Ejemplo n.º 2
0
def remove(path, silent=False, vfs=True, su=False):
    """
    Elimina un archivo, con alternativa de usar SU
    @param path: ruta del fichero a eliminar
    @type path: str
    @rtype: bool
    @return: devuelve False en caso de error
    """
    path = encode(path)
    try:
        if xbmc_vfs and vfs:
            result = bool(xbmcvfs.delete(path))

            # Si el borrado no ha funcionado y se especificado su=True, se intenta el comando RM vía SU del sistema
            from platformcode import config
            if not result and su and config.is_rooted(silent=True) == 'rooted':
                error_cmd = True
                for subcmd in ['-c', '-0']:
                    for cmdtype in [['rm', path], ['rm %s' % path]]:
                        command = ['su', subcmd] + cmdtype
                        output_cmd, error_cmd = config.su_command(
                            command, silent=silent)
                        if not error_cmd:
                            break
                    if not error_cmd:
                        result = True
                        break
                else:
                    logger.error('Sin PERMISOS ROOT: %s' % str(command))
                    result = False
            return result

        elif path.lower().startswith("smb://"):
            samba.remove(path)
        else:
            os.remove(path)
    except:
        logger.error("ERROR al eliminar el archivo: %s" % path)
        if not silent:
            logger.error(traceback.format_exc())
        return False
    else:
        return True
Ejemplo n.º 3
0
def get_environment():
    """
    Devuelve las variables de entorno del OS, de Kodi y de Alfa más habituales,
    necesarias para el diagnóstico de fallos 
    """

    try:
        import base64
        import ast

        environment = config.get_platform(full_version=True)
        environment['num_version'] = str(environment['num_version'])
        environment['python_version'] = '%s (%s, %s)' % (str(platform.python_version()), \
                    str(sys.api_version), str(platform.python_implementation()))
        environment['os_release'] = str(platform.release())
        environment['prod_model'] = ''
        try:
            import multiprocessing
            environment['proc_num'] = ' (%sx)' % str(
                multiprocessing.cpu_count())
        except:
            environment['proc_num'] = ''

        if xbmc.getCondVisibility("system.platform.Windows"):
            try:
                if platform.platform():
                    environment['os_release'] = str(
                        platform.platform()).replace('Windows-', '')
                elif platform._syscmd_ver()[2]:
                    environment['os_release'] = str(platform._syscmd_ver()[2])

                command = ["wmic", "cpu", "get", "name"]
                p = subprocess.Popen(command,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     creationflags=0x08000000)
                output_cmd, error_cmd = p.communicate()
                if PY3 and isinstance(output_cmd, bytes):
                    output_cmd = output_cmd.decode()
                output_cmd = re.sub(r'\n|\r|\s{2}', '', output_cmd)
                environment['prod_model'] = str(scrapertools.find_single_match(output_cmd, \
                                '\w+.*?(?i)(?:Intel\(R\))?(?:\s*Core\(TM\))\s*(.*?CPU.*?)\s*(?:\@|$)'))
            except:
                pass

        if xbmc.getCondVisibility("system.platform.Android"):
            environment['os_name'] = 'Android'
            try:
                for label_a in subprocess.check_output('getprop').split(FF):
                    if PY3 and isinstance(label_a, bytes):
                        label_a = label_a.decode()
                    if 'build.version.release' in label_a:
                        environment['os_release'] = str(
                            scrapertools.find_single_match(
                                label_a, ':\s*\[(.*?)\]$'))
                    if 'product.model' in label_a:
                        environment['prod_model'] = str(
                            scrapertools.find_single_match(
                                label_a, ':\s*\[(.*?)\]$'))
            except:
                try:
                    for label_a in filetools.read(os.environ['ANDROID_ROOT'] +
                                                  '/build.prop').split():
                        if 'build.version.release' in label_a:
                            environment['os_release'] = str(
                                scrapertools.find_single_match(
                                    label_a, '=(.*?)$'))
                        if 'product.model' in label_a:
                            environment['prod_model'] = str(
                                scrapertools.find_single_match(
                                    label_a, '=(.*?)$'))
                except:
                    pass
            environment['prod_model'] += ' (%s)' % config.is_rooted(
                silent=True)

        elif xbmc.getCondVisibility("system.platform.Linux"):
            environment['os_name'] = 'Linux'
            try:
                for label_a in subprocess.check_output('hostnamectl').split(
                        FF):
                    if PY3 and isinstance(label_a, bytes):
                        label_a = label_a.decode()
                    if 'Operating' in label_a:
                        environment['os_release'] = str(
                            scrapertools.find_single_match(
                                label_a, 'Operating\s*S\w+:\s*(.*?)\s*$'))
                        break

                for label_a in subprocess.check_output(
                    ['cat', '/proc/cpuinfo']).split(FF):
                    if PY3 and isinstance(label_a, bytes):
                        label_a = label_a.decode()
                    if 'model name' in label_a:
                        environment['prod_model'] = str(scrapertools.find_single_match(label_a, \
                                'model.*?:\s*(?i)(?:Intel\(R\))?(?:\s*Core\(TM\))\s*(.*?CPU.*?)\s*(?:\@|$)'))
                        break
            except:
                pass

        elif xbmc.getCondVisibility("system.platform.Linux.RaspberryPi"):
            environment['os_name'] = 'RaspberryPi'

        else:
            environment['os_name'] = str(platform.system())

        if not environment['os_release']:
            environment['os_release'] = str(platform.release())
        if environment['proc_num'] and environment['prod_model']:
            environment['prod_model'] += environment['proc_num']
        environment['machine'] = str(platform.machine())
        environment['architecture'] = str(sys.maxsize > 2**32 and "64-bit"
                                          or "32-bit")
        environment['language'] = str(xbmc.getInfoLabel('System.Language'))

        environment['cpu_usage'] = str(xbmc.getInfoLabel('System.CpuUsage'))

        environment['mem_total'] = str(
            xbmc.getInfoLabel('System.Memory(total)')).replace('MB',
                                                               '').replace(
                                                                   'KB', '')
        environment['mem_free'] = str(
            xbmc.getInfoLabel('System.Memory(free)')).replace('MB',
                                                              '').replace(
                                                                  'KB', '')
        if not environment['mem_total'] or not environment['mem_free']:
            try:
                if environment['os_name'].lower() == 'windows':
                    kernel32 = ctypes.windll.kernel32
                    c_ulong = ctypes.c_ulong
                    c_ulonglong = ctypes.c_ulonglong

                    class MEMORYSTATUS(ctypes.Structure):
                        _fields_ = [('dwLength', c_ulong),
                                    ('dwMemoryLoad', c_ulong),
                                    ('dwTotalPhys', c_ulonglong),
                                    ('dwAvailPhys', c_ulonglong),
                                    ('dwTotalPageFile', c_ulonglong),
                                    ('dwAvailPageFile', c_ulonglong),
                                    ('dwTotalVirtual', c_ulonglong),
                                    ('dwAvailVirtual', c_ulonglong),
                                    ('availExtendedVirtual', c_ulonglong)]

                    memoryStatus = MEMORYSTATUS()
                    memoryStatus.dwLength = ctypes.sizeof(MEMORYSTATUS)
                    kernel32.GlobalMemoryStatus(ctypes.byref(memoryStatus))
                    environment['mem_total'] = str(
                        old_div(int(memoryStatus.dwTotalPhys), (1024**2)))
                    environment['mem_free'] = str(
                        old_div(int(memoryStatus.dwAvailPhys), (1024**2)))

                else:
                    with open('/proc/meminfo') as f:
                        meminfo = f.read()
                    environment['mem_total'] = str(
                        old_div(
                            int(
                                re.search(r'MemTotal:\s+(\d+)',
                                          meminfo).groups()[0]), 1024))
                    environment['mem_free'] = str(
                        old_div(
                            int(
                                re.search(r'MemAvailable:\s+(\d+)',
                                          meminfo).groups()[0]), 1024))
            except:
                environment['mem_total'] = ''
                environment['mem_free'] = ''

        try:
            environment['kodi_buffer'] = '20'
            environment['kodi_bmode'] = '0'
            environment['kodi_rfactor'] = '4.0'
            if filetools.exists(
                    filetools.join("special://userdata",
                                   "advancedsettings.xml")):
                advancedsettings = filetools.read(
                    filetools.join("special://userdata",
                                   "advancedsettings.xml")).split('\n')
                for label_a in advancedsettings:
                    if 'memorysize' in label_a:
                        environment['kodi_buffer'] = str(
                            old_div(
                                int(
                                    scrapertools.find_single_match(
                                        label_a, '>(\d+)<\/')), 1024**2))
                    if 'buffermode' in label_a:
                        environment['kodi_bmode'] = str(
                            scrapertools.find_single_match(
                                label_a, '>(\d+)<\/'))
                    if 'readfactor' in label_a:
                        environment['kodi_rfactor'] = str(
                            scrapertools.find_single_match(
                                label_a, '>(.*?)<\/'))
        except:
            pass

        environment['userdata_path'] = str(config.get_data_path())
        environment['userdata_path_perm'] = filetools.file_info(
            environment['userdata_path'])
        if not environment['userdata_path_perm']:
            del environment['userdata_path_perm']
        try:
            if environment['os_name'].lower() == 'windows':
                free_bytes = ctypes.c_ulonglong(0)
                ctypes.windll.kernel32.GetDiskFreeSpaceExW(
                    ctypes.c_wchar_p(environment['userdata_path']), None, None,
                    ctypes.pointer(free_bytes))
                environment['userdata_free'] = str(
                    round(float(free_bytes.value) / (1024**3), 3))
            else:
                disk_space = os.statvfs(environment['userdata_path'])
                if not disk_space.f_frsize:
                    disk_space.f_frsize = disk_space.f_frsize.f_bsize
                environment['userdata_free'] = str(round((float(disk_space.f_bavail) / \
                                (1024**3)) * float(disk_space.f_frsize), 3))
        except:
            environment['userdata_free'] = '?'

        if environment['userdata_path_perm']:
            environment['userdata_path'] = environment['userdata_path_perm']
            del environment['userdata_path_perm']
        environment['torrent_lang'] = '%s/%s' % (config.get_setting("channel_language", default="").upper(), \
                                config.get_setting("second_language", default="").upper())

        try:
            environment['videolab_series'] = '?'
            environment['videolab_episodios'] = '?'
            environment['videolab_pelis'] = '?'
            environment['videolab_path'] = str(config.get_videolibrary_path())
            environment['videolab_path_perm'] = filetools.file_info(
                environment['videolab_path'])
            if not environment['videolab_path_perm']:
                environment['videolab_path_perm'] = environment[
                    'videolab_path']
            if filetools.exists(filetools.join(environment['videolab_path'], \
                                config.get_setting("folder_tvshows"))):
                environment['videolab_series'] = str(len(filetools.listdir(filetools.join(environment['videolab_path'], \
                                config.get_setting("folder_tvshows")))))
                counter = 0
                for root, folders, files in filetools.walk(filetools.join(environment['videolab_path'], \
                                    config.get_setting("folder_tvshows"))):
                    for file in files:
                        if file.endswith('.strm'): counter += 1
                environment['videolab_episodios'] = str(counter)
            if filetools.exists(filetools.join(environment['videolab_path'], \
                                config.get_setting("folder_movies"))):
                environment['videolab_pelis'] = str(len(filetools.listdir(filetools.join(environment['videolab_path'], \
                                config.get_setting("folder_movies")))))
        except:
            pass
        try:
            video_updates = [
                'No', 'Inicio', 'Una vez', 'Inicio+Una vez', 'Dos veces al día'
            ]
            environment['videolab_update'] = str(
                video_updates[config.get_setting("update", "videolibrary")])
        except:
            environment['videolab_update'] = '?'
        try:
            if environment['os_name'].lower() == 'windows':
                free_bytes = ctypes.c_ulonglong(0)
                ctypes.windll.kernel32.GetDiskFreeSpaceExW(
                    ctypes.c_wchar_p(environment['videolab_path']), None, None,
                    ctypes.pointer(free_bytes))
                environment['videolab_free'] = str(
                    round(float(free_bytes.value) / (1024**3), 3))
            else:
                disk_space = os.statvfs(environment['videolab_path'])
                if not disk_space.f_frsize:
                    disk_space.f_frsize = disk_space.f_frsize.f_bsize
                environment['videolab_free'] = str(round((float(disk_space.f_bavail) / \
                                (1024**3)) * float(disk_space.f_frsize), 3))
        except:
            environment['videolab_free'] = '?'

        environment['torrent_list'] = []
        environment['torrentcli_option'] = ''
        environment['torrent_error'] = ''
        environment['torrentcli_rar'] = config.get_setting("mct_rar_unpack",
                                                           server="torrent",
                                                           default=True)
        environment['torrentcli_backgr'] = config.get_setting(
            "mct_background_download", server="torrent", default=True)
        environment['torrentcli_lib_path'] = config.get_setting(
            "libtorrent_path", server="torrent", default="")

        if environment['torrentcli_lib_path']:
            lib_path = 'Activo'
        else:
            lib_path = 'Inactivo'
        if config.get_setting("libtorrent_version",
                              server="torrent",
                              default=""):
            lib_path += '-%s' % config.get_setting(
                "libtorrent_version", server="torrent", default="")
        environment['torrentcli_unrar'] = config.get_setting("unrar_path",
                                                             server="torrent",
                                                             default="")
        if environment['torrentcli_unrar']:
            if xbmc.getCondVisibility("system.platform.Android"):
                unrar = 'Android'
            else:
                unrar = filetools.dirname(environment['torrentcli_unrar'])
                unrar = filetools.basename(unrar).capitalize()
        else:
            unrar = 'Inactivo'
        torrent_id = config.get_setting("torrent_client",
                                        server="torrent",
                                        default=0)
        environment['torrentcli_option'] = str(torrent_id)
        torrent_options = platformtools.torrent_client_installed()
        if lib_path != 'Inactivo':
            torrent_options = ['MCT'] + torrent_options
            torrent_options = ['BT'] + torrent_options
        environment['torrent_list'].append({'Torrent_opt': str(torrent_id), 'Libtorrent': lib_path, \
                                            'RAR_Auto': str(environment['torrentcli_rar']), \
                                            'RAR_backgr': str(environment['torrentcli_backgr']), \
                                            'UnRAR': unrar})
        environment['torrent_error'] = config.get_setting("libtorrent_error",
                                                          server="torrent",
                                                          default="")
        if environment['torrent_error']:
            environment['torrent_list'].append(
                {'Libtorrent_error': environment['torrent_error']})

        for torrent_option in torrent_options:
            cliente = dict()
            cliente['D_load_Path'] = ''
            cliente['Libre'] = '?'
            cliente['Plug_in'] = torrent_option.replace('Plugin externo: ', '')
            if cliente['Plug_in'] == 'BT':
                cliente['D_load_Path'] = str(
                    config.get_setting("bt_download_path",
                                       server="torrent",
                                       default=''))
                if not cliente['D_load_Path']: continue
                cliente['D_load_Path'] = filetools.join(
                    cliente['D_load_Path'], 'BT-torrents')
                cliente['D_load_Path_perm'] = filetools.file_info(
                    cliente['D_load_Path'])
                if not cliente['D_load_Path_perm']:
                    del cliente['D_load_Path_perm']
                cliente['Buffer'] = str(
                    config.get_setting("bt_buffer",
                                       server="torrent",
                                       default=50))
            elif cliente['Plug_in'] == 'MCT':
                cliente['D_load_Path'] = str(
                    config.get_setting("mct_download_path",
                                       server="torrent",
                                       default=''))
                if not cliente['D_load_Path']: continue
                cliente['D_load_Path'] = filetools.join(
                    cliente['D_load_Path'], 'MCT-torrent-videos')
                cliente['D_load_Path_perm'] = filetools.file_info(
                    cliente['D_load_Path'])
                if not cliente['D_load_Path_perm']:
                    del cliente['D_load_Path_perm']
                cliente['Buffer'] = str(
                    config.get_setting("mct_buffer",
                                       server="torrent",
                                       default=50))
            elif xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' %
                                        cliente['Plug_in']):
                try:
                    __settings__ = xbmcaddon.Addon(id="plugin.video.%s" %
                                                   cliente['Plug_in'])
                except:
                    continue
                cliente['Plug_in'] = cliente['Plug_in'].capitalize()
                if cliente['Plug_in'] == 'Torrenter':
                    cliente['D_load_Path'] = str(
                        filetools.translatePath(
                            __settings__.getSetting('storage')))
                    if not cliente['D_load_Path']:
                        cliente['D_load_Path'] = str(filetools.join("special://home/", \
                                                     "cache", "xbmcup", "plugin.video.torrenter", "Torrenter"))
                    cliente['D_load_Path_perm'] = filetools.file_info(
                        cliente['D_load_Path'])
                    if not cliente['D_load_Path_perm']:
                        del cliente['D_load_Path_perm']
                    cliente['Buffer'] = str(
                        __settings__.getSetting('pre_buffer_bytes'))
                else:
                    cliente['D_load_Path'] = str(
                        filetools.translatePath(
                            __settings__.getSetting('download_path')))
                    cliente['D_load_Path_perm'] = filetools.file_info(
                        cliente['D_load_Path'])
                    if not cliente['D_load_Path_perm']:
                        del cliente['D_load_Path_perm']
                    cliente['Buffer'] = str(
                        __settings__.getSetting('buffer_size'))
                    if __settings__.getSetting(
                            'download_storage'
                    ) == '1' and __settings__.getSetting('memory_size'):
                        cliente['Memoria'] = str(
                            __settings__.getSetting('memory_size'))

            if cliente['D_load_Path']:
                try:
                    if environment['os_name'].lower() == 'windows':
                        free_bytes = ctypes.c_ulonglong(0)
                        ctypes.windll.kernel32.GetDiskFreeSpaceExW(
                            ctypes.c_wchar_p(cliente['D_load_Path']), None,
                            None, ctypes.pointer(free_bytes))
                        cliente['Libre'] = str(round(float(free_bytes.value) / \
                                    (1024**3), 3)).replace('.', ',')
                    else:
                        disk_space = os.statvfs(cliente['D_load_Path'])
                        if not disk_space.f_frsize:
                            disk_space.f_frsize = disk_space.f_frsize.f_bsize
                        cliente['Libre'] = str(round((float(disk_space.f_bavail) / \
                                    (1024**3)) * float(disk_space.f_frsize), 3)).replace('.', ',')
                except:
                    pass
                if cliente['D_load_Path_perm']:
                    cliente['D_load_Path'] = cliente['D_load_Path_perm']
                    del cliente['D_load_Path_perm']
            environment['torrent_list'].append(cliente)

        environment['proxy_active'] = ''
        try:
            proxy_channel_bloqued_str = base64.b64decode(
                config.get_setting('proxy_channel_bloqued')).decode('utf-8')
            proxy_channel_bloqued = dict()
            proxy_channel_bloqued = ast.literal_eval(proxy_channel_bloqued_str)
            for channel_bloqued, proxy_active in list(
                    proxy_channel_bloqued.items()):
                if proxy_active != 'OFF':
                    environment['proxy_active'] += channel_bloqued + ', '
        except:
            pass
        if not environment['proxy_active']: environment['proxy_active'] = 'OFF'
        environment['proxy_active'] = environment['proxy_active'].rstrip(', ')

        for root, folders, files in filetools.walk("special://logpath/"):
            for file in files:
                if file.lower() in ['kodi.log', 'jarvis.log', 'spmc.log', 'cemc.log', \
                                    'mygica.log', 'wonderbox.log', 'leiapp,log', \
                                    'leianmc.log', 'kodiapp.log', 'anmc.log', \
                                    'latin-anmc.log']:
                    environment['log_path'] = str(filetools.join(root, file))
                    break
            else:
                environment['log_path'] = ''
            break

        if environment['log_path']:
            environment['log_size_bytes'] = str(
                filetools.getsize(environment['log_path']))
            environment['log_size'] = str(round(float(environment['log_size_bytes']) / \
                                (1024*1024), 3))
        else:
            environment['log_size_bytes'] = ''
            environment['log_size'] = ''

        environment['debug'] = str(config.get_setting('debug'))
        environment['addon_version'] = '%s (Upd: %s h.)' % (str(config.get_addon_version()), \
                                str(config.get_setting("addon_update_timer", default=12)).replace('0', 'No'))

        environment['assistant_version'] = str(None)
        if filetools.exists(
                filetools.join(config.get_data_path(),
                               'alfa-mobile-assistant.version')):
            environment['assistant_version'] = filetools.read(
                filetools.join(config.get_data_path(),
                               'alfa-mobile-assistant.version'))
        environment['assistant_cf_ua'] = str(
            config.get_setting('cf_assistant_ua', None))

    except:
        logger.error(traceback.format_exc())
        environment = {}
        environment['log_size'] = ''
        environment['cpu_usage'] = ''
        environment['python_version'] = ''
        environment['log_path'] = ''
        environment['userdata_free'] = ''
        environment['mem_total'] = ''
        environment['machine'] = ''
        environment['platform'] = ''
        environment['videolab_path'] = ''
        environment['num_version'] = ''
        environment['os_name'] = ''
        environment['video_db'] = ''
        environment['userdata_path'] = ''
        environment['log_size_bytes'] = ''
        environment['name_version'] = ''
        environment['language'] = ''
        environment['mem_free'] = ''
        environment['prod_model'] = ''
        environment['proxy_active'] = ''
        environment['architecture'] = ''
        environment['os_release'] = ''
        environment['videolab_free'] = ''
        environment['kodi_buffer'] = ''
        environment['kodi_bmode'] = ''
        environment['kodi_rfactor'] = ''
        environment['videolab_series'] = ''
        environment['videolab_episodios'] = ''
        environment['videolab_pelis'] = ''
        environment['videolab_update'] = ''
        environment['videolab_path_perm'] = ''
        environment['debug'] = ''
        environment['addon_version'] = ''
        environment['torrent_list'] = []
        environment['torrent_lang'] = ''
        environment['torrentcli_option'] = ''
        environment['torrentcli_rar'] = ''
        environment['torrentcli_lib_path'] = ''
        environment['torrentcli_unrar'] = ''
        environment['torrent_error'] = ''
        environment['assistant_version'] = ''
        environment['assistant_cf_ua'] = ''

    return environment
Ejemplo n.º 4
0
def copy(path, dest, silent=False, vfs=True, ch_mod='', su=False):
    """
    Copia un archivo
    @param path: ruta del fichero a copiar
    @type path: str
    @param dest: ruta donde copiar
    @type dest: str
    @param silent: se muestra o no el cuadro de dialogo
    @type silent: bool
    @rtype: bool
    @return: devuelve False en caso de error
    """
    try:
        if xbmc_vfs and vfs:
            path = encode(path)
            dest = encode(dest)
            if not silent:
                logger.info("Copiando archivo %s a %s" % (path, dest),
                            force=True)
            result = bool(xbmcvfs.copy(path, dest))

            # Si la copia no ha funcionado y se ha especificado su=True, se intenta el comando CP vía SU del sistema
            from platformcode import config
            if not result and su and config.is_rooted(silent=True) == 'rooted':
                error_cmd = True
                for subcmd in ['-c', '-0']:
                    for cmdtype in [['cp', path, dest],
                                    ['cp %s %s' % (path, dest)]]:
                        command = ['su', subcmd] + cmdtype
                        output_cmd, error_cmd = config.su_command(
                            command, silent=silent)
                        if not error_cmd:
                            break
                    if not error_cmd:
                        result = True
                        break
                else:
                    logger.error('Sin PERMISOS ROOT: %s' % str(command))
                    result = False
            elif result:
                su = ''

            if result and ch_mod:
                result = chmod(dest, ch_mod, silent=silent, su=su)
            return result

        fo = file_open(path, "rb")
        fd = file_open(dest, "wb")
        if fo and fd:
            if not silent:
                dialogo = platformtools.dialog_progress("Copiando archivo", "")
            size = getsize(path)
            copiado = 0
            while True:
                if not silent:
                    dialogo.update(old_div(copiado * 100, size),
                                   basename(path))
                buf = fo.read(1024 * 1024)
                if not buf:
                    break
                if not silent and dialogo.iscanceled():
                    dialogo.close()
                    return False
                fd.write(buf)
                copiado += len(buf)
            if not silent:
                dialogo.close()
    except:
        logger.error("ERROR al copiar el archivo: %s" % path)
        if not silent:
            logger.error(traceback.format_exc())
        return False
    else:
        return True
Ejemplo n.º 5
0
def install_alfa_assistant(update=False, remote='', verbose=False):
    if update:
        logger.info('update=%s' % str(update))
    # Si ya está instalada, devolvemos el control
    app_name = 'com.alfa.alfamobileassistant'
    if not verbose: verbose = config.get_setting('addon_update_message')        # Verbose en la actualización/instalación
    assistant_flag_install = config.get_setting('assistant_flag_install', default=True)
    addonid = 'alfa-mobile-assistant'
    download = addonid + '.apk'
    package = addonid + '.apk'
    version = addonid + '.version'
    forced_menu = False
    respuesta = False
    alfa_s = True
    addons_path = config.get_runtime_path()
    if filetools.exists(filetools.join(addons_path, 'channels', 'custom.py')):
        alfa_s = False

    if not remote:
        ANDROID_STORAGE = os.getenv('ANDROID_STORAGE')
        if not ANDROID_STORAGE: ANDROID_STORAGE = '/storage'
    else:
        # Remote es la url de un servidor FTP o SMB activo que apunta a la ruta "/storage" del dispositivo Android
        ANDROID_STORAGE = remote
        if ANDROID_STORAGE.endswith('/'):
            ANDROID_STORAGE = ANDROID_STORAGE[:-1]
    apk_files = '%s/%s/%s/%s/%s/%s' % (ANDROID_STORAGE, 'emulated', '0', 'Android', 'data', app_name)
    if ASSISTANT_MODE == 'este' and not filetools.exists(filetools.dirname(apk_files)):
        apk_files_alt = scrapertools.find_single_match(os.getenv('HOME'), '(.*?)\/\w*.\w*.\w*\/files')
        logger.info('HOME: ' + apk_files_alt)
        if apk_files_alt and filetools.exists(apk_files_alt):
            apk_files = '%s/%s' % (apk_files_alt, app_name)

    version_path = filetools.join(config.get_data_path(), version)
    version_act = filetools.read(version_path, silent=True)
    if not version_act: version_act = '0.0.0'
    
    # Averiguamos si es instalacción, update, o forzado desde el Menú de Ajustes
    if not update and ASSISTANT_MODE == 'este' and filetools.exists(apk_files):
        return version_act, app_name
    if ASSISTANT_MODE == 'este' and not update:
        check_permissions_alfa_assistant()                                      # activamos la app por si no se ha inicializado
        time.sleep(1)
        if filetools.exists(apk_files):
            return version_act, app_name
    # Mirarmos si la app está activa y obtenemos el nº de versión
    version_dict = get_generic_call('getWebViewInfo', timeout=2-EXTRA_TIMEOUT, alfa_s=True)
    if isinstance(version_dict, dict):
        version_app = version_dict.get('assistantVersion', '')
        try:
            android_version = int(scrapertools.find_single_match(version_dict.get('userAgent', ''), r"Android\s*(\d+)"))
        except:
            android_version = 8
    else:
        version_app = version_dict
        android_version = 8
    if version_app and not update:
        return version_app, app_name
    
    if version_app:
        app_active = True
    else:
        app_active = False
        if ASSISTANT_MODE == "este":
            execute_in_alfa_assistant_with_cmd('open')                          # activamos la app por si no se ha inicializado
            time.sleep(5)
            version_dict = get_generic_call('getWebViewInfo', timeout=2-EXTRA_TIMEOUT, alfa_s=True)
            if isinstance(version_dict, dict):
                version_app = version_dict.get('assistantVersion', '')
                try:
                    android_version = int(scrapertools.find_single_match(version_dict.get('userAgent', ''), r"Android\s*(\d+)"))
                except:
                    android_version = 8
            else:
                version_app = version_dict
                android_version = 8
    version_actual = filetools.read(version_path, silent=True)
    if not version_actual and version_app:
        version_actual = version_app
        filetools.write(version_path, version_actual, mode='wb', silent=True)
    elif not version_actual:
        version_actual = '0.0.0'

    if ASSISTANT_MODE != 'este':
        if not version_app:
            if verbose or (update and not isinstance(update, bool)):
                platformtools.dialog_notification("Active Alfa Assistant", 
                            "o Instale manualmente desde [COLOR yellow]https://bit.ly/2Zwpfzq[/COLOR]")
            logger.info("Active Alfa Assistant, o Instale manualmente desde [COLOR yellow]https://bit.ly/2Zwpfzq[/COLOR]", force=True)
            config.set_setting('assistant_flag_install', False)
            return version_app, app_name
        else:
            config.set_setting('assistant_flag_install', True)
            if not update:
                return version_app, app_name
    elif not update and not assistant_flag_install and not filetools.exists(apk_files):
        logger.info('NO está instalada. El usuario no quiere instalaciñon automática: %s' % app_name)
        return False, app_name
    elif update and isinstance(update, bool) and not filetools.exists(apk_files):
        logger.info('NO está instalada. No se va a actualizar: %s' % app_name)
        return False, app_name
    elif update and not isinstance(update, bool) and not filetools.exists(apk_files):
        logger.info('NO está instalada. Viene del Menú y se va a instalar: %s' % app_name)
        update = False
        forced_menu = True
    elif not remote and not xbmc.getCondVisibility("system.platform.android"):
        logger.info('El sistema local no es Android: %s' % app_name)
        return False, app_name

    logger.info('assistant_mode=%s, update=%s, forced_menu=%s, assistant_flag_install=%s, version_actual=%s, version_app=%s, android=%s, app_active=%s' \
            % (ASSISTANT_MODE, str(update), str(forced_menu), str(assistant_flag_install), version_actual, \
            version_app, str(android_version), str(app_active)))
    
    # Si no está instalada, o se quiere actualizar, empezamos el proceso
    alfa_assistant_pwd = ''
    assistant_urls = ['https://github.com/alfa-addon/alfa-repo/raw/master/downloads/assistant/%s' % version, \
            'https://bitbucket.org/alfa_addon/alfa-repo/raw/master/downloads/assistant/%s' % version]
    
    apk_updated = filetools.join(addons_path, 'tools')
    apk_path = filetools.join(apk_updated, download)
    apk_apk = filetools.join(apk_updated, package)
    upk_install_path = filetools.join('special://xbmc/', 'files').replace('/cache/apk/assets', '')
    if not remote:
        apk_install = filetools.join(ANDROID_STORAGE, 'emulated', '0', 'Download')
        apk_install_SD = filetools.join(apk_install, package)
    else:
        apk_install = '%s/%s/%s/%s' % (ANDROID_STORAGE, 'emulated', '0', 'Download')
        apk_install_SD = '%s/%s' % (apk_install, package)

    if not update and not remote and not forced_menu:
        # Probamos a iniciar por si se ha instalado manualmente y no se ha iniciado la estrucutra de archivos
        check_permissions_alfa_assistant()
        try:
            command = ['pm', 'list', 'packages']
            p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            PM_LIST, error_cmd = p.communicate()
            if PY3 and isinstance(label_a, bytes):
                PM_LIST = PM_LIST.decode()
            if app_name in PM_LIST:
                logger.info('Ya instalada. Volvemos: %s' % app_name)
                return version_actual, app_name
        except:
            logger.error(traceback.format_exc(1))
    
    if not update and not forced_menu and not platformtools.dialog_yesno("Instalación Alfa Assistant", \
                    "¿Desea instalar la App [COLOR yellow][B]%s[/B][/COLOR]\n" % app_name +
                    " como ayuda para acceder a ciertos canales y servidores?"):
        config.set_setting('assistant_flag_install', False)
        return respuesta, app_name
    elif update and not isinstance(update, bool):
        platformtools.dialog_notification("Instalación Alfa Assistant", "Comienza la actualización")
    elif forced_menu:
        platformtools.dialog_notification("Instalación Alfa Assistant", "Comienza la instalación")

    # Comprobamos si el dispositivo está rooteado
    is_rooted = config.is_rooted(silent=True)                                   # ¡OJO! puede pedir permisos root en algunos dispositivos
    if is_rooted == 'rooted' and ASSISTANT_MODE == 'este':                      # El dispositivo esta rooteado?
        update_install = 'py'                                                   # Se actualiza desde esta función
    else:
        update_install = 'app'                                                  # Se actualiza desde la app
    cmd = 'update'                                                              # Comando de la app para auto actualizarse
    dataURI = 'Version:%s'                                                      # Versión a actualizar
    
    # Comprobamos si hay acceso a Github o BitBucket
    for assistant_rar in assistant_urls:
        response = httptools.downloadpage(assistant_rar, timeout=5, ignore_response_code=True, alfa_s=alfa_s, json_to_utf8=False)
        if response.sucess:
            break
    
    # Descargamos el archivo de version.  Si hay error avisamos, pero continuamos
    if not response.sucess:
        if update and isinstance(update, bool):
            logger.error("Error en la descarga de control de versión. No se puede actualizar: %s" % str(response.code))
            return respuesta, app_name
        platformtools.dialog_notification("Instalación Alfa Assistant", "Error en la descarga de control de versión. Seguimos")
        logger.error("Error en la descarga de control de versión. Seguimos...: %s" % str(response.code))

    #Si es una actualización programada, comprobamos las versiones de Github y de lo instalado
    if update and isinstance(update, bool):
        if version_actual != response.data:
            if version_app:
                version_actual = version_app
                filetools.write(version_path, version_actual, mode='wb', silent=True)
        if version_actual == response.data:
            if verbose: platformtools.dialog_notification("Instalación Alfa Assistant", "Ya está actualizado a version %s" % response.data)
            logger.info("Alfa Assistant ya actualizado a versión: %s" % response.data)
            if not app_active and ASSISTANT_MODE == "este":
                execute_in_alfa_assistant_with_cmd('quit')                      # desactivamos la app si no estaba iniciada
            return version_actual, app_name

    # Guardamos archivo de versión
    if remote:
        version_path = '%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s' % (ANDROID_STORAGE, 'emulated', '0', 'Android', 
                        'data', 'org.xbmc.kodi', 'files', '.kodi', 'addons', 'plugin.video.alfa', 
                        'tools', version)
        if not filetools.exists(filetools.dirname(version_path)):
            logger.error("Ruta a carpeta remota de versión no es estándar: %s" % version_path)
            version_path = ''
    version_old = version_actual
    version_actual = response.data
    if version_path:
        res = filetools.write(version_path, response.data, mode='wb', silent=True)
        if not res:
            if not update: platformtools.dialog_notification("Instalación Alfa Assistant", \
                            "Error en la escritura de control de versión. Seguimos...")
            logger.error("Error en la escritura de control de versión. Seguimos...: %s" % assistant_rar)

    # Descargamos y guardamos el .APK
    assistant_rar = assistant_rar.replace(version, download)                    # Sustituir en la url la versión por el apk
    res = False
    if not update: platformtools.dialog_notification("Instalación Alfa Assistant", "Descargando APK")
    logger.info('Descargando de_ %s' % assistant_rar)
    response = httptools.downloadpage(assistant_rar, timeout=5, ignore_response_code=True, alfa_s=alfa_s, json_to_utf8=False)
    if not response.sucess:
        if not update or verbose: platformtools.dialog_notification("Instalación Alfa Assistant", "Error en la descarga del .apk")
        response.data = ''
        logger.error("Error en la descarga del .apk: %s" % str(response.code))
    else:
        # Guardamos archivo descargado de APK
        res = filetools.write(apk_path, response.data, mode='wb', silent=True)
        if not res:
            if not update or verbose: platformtools.dialog_notification("Instalación Alfa Assistant", "Error en la escritura del APK")
            logger.error("Error en la escritura del APK: %s" % apk_path)
        
        else:
            if '.rar' in download:
                # Empezando la extracción del .rar del APK
                try:
                    import rarfile
                    archive = rarfile.RarFile(apk_path)
                    if alfa_assistant_pwd: archive.setpassword(alfa_assistant_pwd)
                    archive.extractall(apk_updated)
                except:
                    logger.error(traceback.format_exc(1))
            elif '.zip' in download:
                # Empezando la extracción del .rar del APK
                try:
                    import ziptools
                    archive = ziptools.ziptools()
                    #if alfa_assistant_pwd: archive.setpassword(alfa_assistant_pwd)      # No hay password en .zip
                    archive.extract(filetools.basename(apk_updated), filetools.dirname(apk_updated))
                except:
                    xbmc.executebuiltin('Extract("%s","%s")' % (filetools.basename(apk_updated), filetools.dirname(apk_updated)))
                    time.sleep(1)

            # Verificado si está el APK, y si está y es LOCAL lo instalamos
            if ASSISTANT_MODE == "este":
                res = filetools.copy(apk_apk, apk_install_SD, silent=True)
                if not res or not filetools.exists(apk_install_SD):
                    if not update or verbose: platformtools.dialog_notification("Instalación Alfa Assistant", "Error de Extracción o Copia %s" % package)
                    logger.error("Error de Extracción o copia %s" % package)
                
                # Si está rooteado se instala/actualiza directamente
                elif update_install == 'py' and res and filetools.exists(apk_install_SD):

                    # Instalamos: nueva o actualización. 
                    if not update: platformtools.dialog_notification("Instalación Alfa Assistant", "Installando %s" % package)
                    logger.info("Installing %s" % package)
                    
                    # Instalación Remota
                    if remote:
                        filetools.remove(apk_apk, silent=True)
                        platformtools.dialog_notification("Alfa Assistant: Descarga Remota terminada", "Instale manualmente desde: %s" % apk_install_SD)
                        logger.info("Alfa Assistant: Descarga Remota terminada. Instale manualmente desde: %s" % apk_install_SD)
                        return version_actual, app_name

                    # Instalación Local
                    if not filetools.exists(upk_install_path):
                        filetools.mkdir(upk_install_path)
                    upk_install_path = filetools.join(upk_install_path, package)
                    res = filetools.copy(apk_install_SD, upk_install_path, ch_mod='777')    # Copiamos APK a la partición del Sistema, y cambiamos permisos
                    if not res:
                        if not update or verbose: platformtools.dialog_notification("Instalación Alfa Assistant", "Error de Copia %s" % package)
                        logger.error(str(filetools.listdir(apk_install)))
                        logger.error(filetools.file_info(filetools.dirname(upk_install_path)))
                        logger.error(str(filetools.listdir(filetools.dirname(upk_install_path), file_inf=True)))
                    else:

                        # Intenta la instalación vía ROOT y si no funciona como NO ROOT
                        
                        # Marcamos la opción de instalación, -r si es actualización, -g (todos los permisos granted) si es instalación
                        if filetools.exists(apk_files):
                            pm_opt = '-r'
                        else:
                            pm_opt = '-g'
                        
                        # Listamos todas las opciones de comandos, según las variantes de Android
                        command_list = [
                                        ['adb', 'install', '%s' % upk_install_path],
                                        ['su', '-c', 'pm install %s %s' % (pm_opt, upk_install_path)],
                                        ['su', '-c', 'pm', 'install', pm_opt, '%s' % upk_install_path],
                                        ['su', '-0', 'pm install %s %s' % (pm_opt, upk_install_path)],
                                        ['su', '-0', 'pm', 'install', pm_opt, '%s' % upk_install_path]
                                       ]
                        
                        for command in command_list:
                            try:
                                logger.info(command, force=True)
                                p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                output_cmd, error_cmd = p.communicate()
                                if error_cmd:
                                    if error_cmd.startswith('su:'): continue
                                    if update:
                                        ver_upd = get_generic_call('ping', timeout=2-EXTRA_TIMEOUT, alfa_s=True)
                                        if not ver_upd:
                                            execute_in_alfa_assistant_with_cmd('open')  # activamos la app por si no se ha inicializado
                                            time.sleep(5)
                                            ver_upd = get_generic_call('ping', timeout=2-EXTRA_TIMEOUT, alfa_s=True)
                                            execute_in_alfa_assistant_with_cmd('quit')
                                        if ver_upd == version_actual:
                                            logger.debug(str(error_cmd), force=True)
                                            error_cmd = ''
                                    else:
                                        check_permissions_alfa_assistant()
                                        time.sleep(1)
                                        if filetools.exists(apk_files):
                                            logger.debug(str(error_cmd), force=True)
                                            error_cmd = ''
                                    if error_cmd:
                                        logger.error(str(error_cmd))
                                    else:
                                        respuesta = version_actual
                                        break
                                else:
                                    respuesta = version_actual
                                    break
                            except Exception as e:
                                if not PY3:
                                    e = unicode(str(e), "utf8", errors="replace").encode("utf8")
                                logger.error('Command ERROR: %s, %s' % (str(command), str(e)))
                                continue
      
    # Ùltimo resorte: instalación manual desde GitHub o actualización desde la app
    if not respuesta and update:
        
        # Si hay que actualizar se verifica el vehículo de instalación
        logger.info("Instalación Alfa Assistant. Actualización desde la app de %s a %s" % (version_old, version_actual))
        version_mod = version_actual
        if not isinstance(update, bool):
            version_mod = '9.9.999'                                             # Intenta forzar la actualización si viene desde el Menú
        if ASSISTANT_MODE == "este":
            if android_version >= 10:
                app_active = False
                respuesta = execute_in_alfa_assistant_with_cmd(cmd, dataURI=dataURI % version_mod)
            else:
                if not app_active:
                    execute_in_alfa_assistant_with_cmd('openAndQuit')           # activamos la app por si no se ha inicializado
                    time.sleep(5)
                app_active = False
                respuesta = get_generic_call(cmd, version=version_mod, alfa_s=alfa_s)
        else:
            if app_active:
                respuesta = get_generic_call(cmd, version=version_mod, alfa_s=alfa_s)

        if not respuesta and ASSISTANT_MODE != "este":
            if verbose or not isinstance(update, bool):
                platformtools.dialog_notification("Instalación Alfa Assistant", "Intente la actualización manualmente %s" % version_actual)
            logger.info("Instalación Alfa Assistant. Intente la actualización manualmente %s" % version_actual)
            return False, app_name
        elif not respuesta:
            # Update local
            #respuesta = execute_in_alfa_assistant_with_cmd(cmd, dataURI=dataURI % version_mod)
            if not respuesta:
                if verbose or not isinstance(update, bool):
                    platformtools.dialog_notification("Instalación Alfa Assistant", "Actualización en error %s. REINTENTANDO" % version_actual)
                logger.info("Instalación Alfa Assistant. Actualización en error %s. REINTENTANDO" % version_actual)
        else:
            respuesta = version_actual
        
    if not respuesta:
        config.set_setting('assistant_flag_install', False)                     # No vuelve a intentar la instalación
        try:
            #xbmc.executebuiltin('StartAndroidActivity("","android.intent.action.VIEW","application/vnd.android.package-archive","file:%s")' % apk_install_SD)
            
            if ASSISTANT_MODE == "este":
                from lib import generictools
                assistant_rar = assistant_rar.replace('/raw/', '/tree/')            # Apuntar a la web de descargas
                browser, res = generictools.call_browser(assistant_rar, lookup=True)
                if browser:
                    filetools.remove(apk_install_SD, silent=True)
                    platformtools.dialog_ok("Alfa Assistant: Instale desde [COLOR yellow]%s[/COLOR]" % browser.capitalize(), 
                                    "O Instale manualmente desde: [COLOR yellow]%s[/COLOR]" % apk_install_SD)
                    logger.info('Browser: %s, Ruta: %s' % (browser.capitalize(), apk_install_SD))
                    time.sleep(5)
                    browser, res = generictools.call_browser(assistant_rar, dataType='application/vnd.android.package-archive')
                    filetools.remove(apk_path, silent=True)
                    filetools.remove(upk_install_path, silent=True)
                else:
                    logger.error('Error de Instalación: NO Browser, Ruta: %s' % apk_install_SD)
                    raise
            else:
                logger.error('Error de Instalación: no se puede instalar en remoto: %s' % ASSISTANT_SERVER)
                raise
        except:
            if ASSISTANT_MODE == "este":
                platformtools.dialog_ok("Alfa Assistant: Error", "Instale manualmente desde: [COLOR yellow]%s[/COLOR]" % apk_install_SD)
                logger.error("Alfa Assistant: Error. Instale manualmente desde: [COLOR yellow]%s[/COLOR]" % apk_install_SD)
                filetools.remove(apk_path, silent=True)
                filetools.remove(upk_install_path, silent=True)
            else:
                platformtools.dialog_ok("Alfa Assistant: Error", "Copie a Android manualmente desde: [COLOR yellow]%s[/COLOR]" % apk_apk)
                logger.error("Alfa Assistant: Error. Copie a Android manualmente desde: [COLOR yellow]%s[/COLOR]" % apk_apk)
            logger.error(traceback.format_exc(1))

    if respuesta:
        if update:
            if verbose or not isinstance(update, bool): platformtools.dialog_notification("Alfa Assistant", \
                                "Actualización con exito: %s" % respuesta)
            logger.info("Actualización terminada con éxito: %s" % respuesta)
        else:
            platformtools.dialog_notification("Alfa Assistant", "Instalación con exito: %s" % respuesta)
            logger.info("Instalación terminada con éxito: %s" % respuesta)
        filetools.remove(apk_path, silent=True)
        filetools.remove(apk_install_SD, silent=True)
        filetools.remove(upk_install_path, silent=True)
        if not update and not forced_menu:
            time.sleep(1)
            check_permissions_alfa_assistant()
            time.sleep(1)
        if app_active and ASSISTANT_MODE == "este":
            execute_in_alfa_assistant_with_cmd('open')                          # re-activamos la app para dejarla como estaba
        
    return respuesta, app_name