Example #1
0
    def do_connect(self, dev_no):
        """Connect Polar device. Run 'list' to see available devices.
Usage: connect <device_no>
        """
        try:
            dev_no = int(dev_no)
        except ValueError:
            print '[!] You need to specify the device number. Run \'list\' to see available devices.'
            print
            return

        try:
            devs = Device.list()
            dev = devs[dev_no]
            serial = Device.get_info(dev)['serial_number']

            self.prompt = LoopholeCli.__PROMPT.format(serial)
            self.device = Device(dev)
            self.device.open()

            print '[+] Device connected.'
            print
        except IndexError:
            print '[!] Device not found or failed to open it. Run \'list\' to see available devices.'
            print
Example #2
0
    def do_connect(self, dev_no):
        """Connect Polar device. Run 'list' to see available devices.
Usage: connect <device_no>
        """
        try:
            dev_no = int(dev_no)
        except ValueError:
            print '[!] You need to specify the device number. Run \'list\' to see available devices.'
            print
            return

        try:
            devs = Device.list()
            dev = devs[dev_no]
            serial = Device.get_info(dev)['serial_number']

            self.prompt = LoopholeCli.__PROMPT.format(serial)
            self.device = Device(dev)
            self.device.open()

            print '[+] Device connected.'
            print
        except IndexError:
            print '[!] Device not found or failed to open it. Run \'list\' to see available devices.'
            print
Example #3
0
    def do_list(self, _):
        """List available Polar devices.
Usage: list
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                try:
                    info = Device.get_info(dev)
                except ValueError as err:
                    print "Device no: %i" % i
                    print "Device info:"
                    print dev
                    print "-" * 79
                    if 'langid' in err.message:
                        raise ValueError(
                            ("Can't get device info. Origin Error: %s\n"
                             "Maybe this is a permission issue.\n"
                             "Please read section 'permission' in README ;)") %
                            err)
                    raise  # raise origin error

                print '{} - {} ({})'.format(i, info['product_name'],
                                            info['serial_number'])
        else:
            print '[!] No Polar devices found!'

        print
Example #4
0
    def do_list(self, _):
        """List available Polar devices.
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                info = Device.get_info(dev)
                print '{} - {} ({})'.format(i, info['product_name'], info['serial_number'])
        else:
            print '[!] No Polar devices found!'

        print
Example #5
0
    def do_list(self, _):
        """List available Polar devices.
Usage: list
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                info = Device.get_info(dev)
                print '{} - {} ({})'.format(i, info['product_name'],
                                            info['serial_number'])
        else:
            print '[!] No Polar devices found!'

        print
Example #6
0
    def _scanDevices(self):
        self.scanning = True
        while self.scanning:
            devices = Device.list()
            scannedDevices = {}

            if len(devices) > 0:
                for i, dev in enumerate(devices):
                    try:
                        info = self._registerDevice(dev)
                        scannedDevices[info['serial_number']] = {
                            'vendorId': info['vendor_id'],
                            'productId': info['product_id'],
                            'name': info['product_name'],
                            'manufacturer': info['manufacturer'],
                            'device': dev
                        }
                    except ValueError as err:
                        if 'langid' in err.message:
                            print("Can't get device info. Origin Error: %s" %
                                  err)

            self._unregisterDevices({
                k: self.devices[k]
                for k in set(self.devices) - set(scannedDevices)
            })
            GLib.idle_add(self._toggleTray)
            time.sleep(1)
Example #7
0
    def do_info(self, _):
        """Print connected device info.
        """
        info = Device.get_info(self.device.usb_device)
        print '{:>20s} - {}'.format('Manufacturer', info['manufacturer'])
        print '{:>20s} - {}'.format('Product name', info['product_name'])
        print '{:>20s} - {}'.format('Vendor ID', info['vendor_id'])
        print '{:>20s} - {}'.format('Product ID', info['product_id'])
        print '{:>20s} - {}'.format('Serial number', info['serial_number'])

        try:
            data = self.device.read_file('/DEVICE.BPB')
            resp = ''.join(chr(c) for c in data)
            d = pb_device.PbDeviceInfo()
            d.ParseFromString(resp)
            bootloader_version = '{}.{}.{}'.format(d.bootloader_version.major, d.bootloader_version.minor, d.bootloader_version.patch)
            print '{:>20s} - {}'.format('Bootloader version', bootloader_version)
            platform_version = '{}.{}.{}'.format(d.platform_version.major, d.platform_version.minor, d.platform_version.patch)
            print '{:>20s} - {}'.format('Platform version', platform_version)
            device_version = '{}.{}.{}'.format(d.device_version.major, d.device_version.minor, d.device_version.patch)
            print '{:>20s} - {}'.format('Device version', device_version)
            print '{:>20s} - {}'.format('SVN revision', d.svn_rev)
            print '{:>20s} - {}'.format('Hardware code', d.hardware_code)
            print '{:>20s} - {}'.format('Color', d.product_color)
            print '{:>20s} - {}'.format('Product design', d.product_design)

        except:
            print '[!] Failed to get extended info.'

        print ' '
Example #8
0
    def do_connect(self, dev_no):
        """Connect Polar device. Run 'list' to see available devices.
        """
        try:
            dev_no = int(dev_no)
            devs = Device.list()
            dev = devs[dev_no]

            self.prompt = LoopholeCli.__PROMPT.format(dev.serial_number)
            self.device = Device(dev)

            print '[+] Device connected.'
            print
        except IndexError:
            print '[!] Device not found. Run \'list\' to see available devices.'
            print
Example #9
0
    def _syncDevice(self, serial):
        print('connecting device %s (%s)' %
              (self.devices[serial]['name'], serial))
        device = Device(self.devices[serial]['device'])
        device.open()
        syncing = True

        GLib.idle_add(self._changeIcon, True)

        devMap = device.walk(device.SEP)
        print('syncing device %s (%s)' %
              (self.devices[serial]['name'], serial))
        for directory in devMap.keys():
            osDirectory = directory.replace(device.SEP, os.sep)
            d = devMap[directory]
            files = [e for e in d.entries if not e.name.endswith(os.sep)]
            for file in files:
                parserFailed = False
                if '.BPB' in file.name:
                    data = device.read_file('%s%s' % (directory, file.name))

                    dataFileName = '%s%s%s' % (
                        serial, directory.replace(os.sep, '-').lower(),
                        os.path.splitext(file.name)[0].lower())

                    if file.name in self.FILE_MAPPINGS.keys():
                        parser = self.FILE_MAPPINGS[file.name]()

                        if file.name == 'SAMPLES.GZB':
                            data = zlib.decompress(data)

                        f = '%s/.local/polartray/%s.json' % (
                            os.environ['HOME'], dataFileName)
                        try:
                            parser.ParseFromString(bytes(bytearray(data)))
                            with open(f, 'w') as fh:
                                fh.write(MessageToJson(parser))
                        except Exception as err:
                            parserFailed = True
                            print('failed to decode %s' % (dataFileName))
                            print(err)

                    if file.name not in self.FILE_MAPPINGS.keys(
                    ) or parserFailed == True:
                        f = '%s/.local/polartray/%s%s' % (
                            os.environ['HOME'], dataFileName,
                            os.path.splitext(file.name)[1].lower())
                        with open(f, 'wb') as fh:
                            fh.write(bytearray(data))

        GLib.idle_add(self._changeIcon, False)

        print('disconnecting device %s (%s)' %
              (self.devices[serial]['name'], serial))
        device.close()
Example #10
0
    def do_disk_space(self, _):
        """Print connected device disk space info.
Usage: info
        """
        info = Device.get_disk_space(self.device.usb_device)
        resp = ''.join(chr(c) for c in info['disk_space'])
        d = pb_device.PbPFtpDiskSpaceResult()
        d.ParseFromString(resp)
        print d

        print ' '
Example #11
0
    def do_list(self, _):
        """List available Polar devices.
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                print '{} - {} ({})'.format(i, dev.product_name, dev.serial_number)
        else:
            print '[!] No Polar devices found!'

        print
Example #12
0
    def _registerDevice(self, dev):
        info = Device.get_info(dev)

        if info['serial_number'] not in self.devices:
            print('register device %s (%s)' %
                  (info['product_name'], info['serial_number']))
            self.devices[info['serial_number']] = {
                'vendorId': info['vendor_id'],
                'productId': info['product_id'],
                'name': info['product_name'],
                'manufacturer': info['manufacturer'],
                'device': dev
            }
            self.deviceCount += 1

            self.devices[info['serial_number']]['thread'] = threading.Thread(
                target=self._syncDevice, args=[info['serial_number']])
            self.devices[info['serial_number']]['thread'].start()

        return info
Example #13
0
    def do_info(self, _):
        """Print connected device info.
Usage: info
        """
        info = Device.get_info(self.device.usb_device)
        print '{:>20s} - {}'.format('Manufacturer', info['manufacturer'])
        print '{:>20s} - {}'.format('Product name', info['product_name'])
        print '{:>20s} - {}'.format('Vendor ID', info['vendor_id'])
        print '{:>20s} - {}'.format('Product ID', info['product_id'])
        print '{:>20s} - {}'.format('Serial number', info['serial_number'])

        try:
            data = self.device.read_file('/DEVICE.BPB')
            resp = ''.join(chr(c) for c in data)
            d = pb_device.PbDeviceInfo()
            d.ParseFromString(resp)
            bootloader_version = '{}.{}.{}'.format(d.bootloader_version.major,
                                                   d.bootloader_version.minor,
                                                   d.bootloader_version.patch)
            print '{:>20s} - {}'.format('Bootloader version',
                                        bootloader_version)
            platform_version = '{}.{}.{}'.format(d.platform_version.major,
                                                 d.platform_version.minor,
                                                 d.platform_version.patch)
            print '{:>20s} - {}'.format('Platform version', platform_version)
            device_version = '{}.{}.{}'.format(d.device_version.major,
                                               d.device_version.minor,
                                               d.device_version.patch)
            print '{:>20s} - {}'.format('Device version', device_version)
            print '{:>20s} - {}'.format('SVN revision', d.svn_rev)
            print '{:>20s} - {}'.format('Hardware code', d.hardware_code)
            print '{:>20s} - {}'.format('Color', d.product_color)
            print '{:>20s} - {}'.format('Product design', d.product_design)

        except:
            print '[!] Failed to get extended info.'

        print ' '
Example #14
0
class LoopholeCli(cmd.Cmd):
    """ Loophole command line interface class. """

    __PROMPT = 'loophole({})>'

    def __init__(self):
        """Constructor.
        """
        cmd.Cmd.__init__(self)
        self.prompt = LoopholeCli.__PROMPT.format('no device')
        self.device = None
    # end-of-method __init__

    def do_exit(self, _):
        """Quit.
        """
        if self.device is not None:
            self.device.close()
        sys.exit(0)
    # end-of-method do_exit

    def do_list(self, _):
        """List available Polar devices.
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                info = Device.get_info(dev)
                print '{} - {} ({})'.format(i, info['product_name'], info['serial_number'])
        else:
            print '[!] No Polar devices found!'

        print
    # end-of-method do_list

    def do_connect(self, dev_no):
        """Connect Polar device. Run 'list' to see available devices.
        """
        try:
            dev_no = int(dev_no)
            devs = Device.list()
            dev = devs[dev_no]
            serial = Device.get_info(dev)['serial_number']

            self.prompt = LoopholeCli.__PROMPT.format(serial)
            self.device = Device(dev)
            self.device.open()

            print '[+] Device connected.'
            print
        except IndexError:
            print '[!] Device not found or failed to open it. Run \'list\' to see available devices.'
            print
    # end-of-method do_connect

    @check_if_device_is_connected
    def do_disconnect(self, _):
        """Disconnect Polar device.
        """
        self.device.close()
        self.device = None
        self.prompt = LoopholeCli.__PROMPT.format('no device')
        print '[+] Device disconnected.'
        print
    # end-of-method do_disconnect

    @check_if_device_is_connected
    def do_get(self, line):
        """Read file from device.
Usage: get <src> <dest>
        """
        try:
            src, dest = line.strip().split()

            data = self.device.read_file(src)
            with open(dest, 'wb') as outfile:
                outfile.write(bytearray(data))

            print '[+] File \'{}\' saved to \'{}\''.format(src, dest)
            print
        except ValueError:
            print '[!] Invalid command usage.'
            print '[!] Usage: get <source> <destination>'
            print
    # end-of-method do_get

    def do_dump(self, path):
        """Dump device memory.
Usage: dump <path>
        """
        print '[+] Reading files tree...'
        dev_map = self.device.walk(self.device.SEP)

        for directory in dev_map.keys():
            fixed_directory = directory.replace(self.device.SEP, os.sep)
            full_path = os.path.abspath(os.path.join(path, fixed_directory[1:]))

            if not os.path.exists(full_path):
                os.makedirs(full_path)

            d = dev_map[directory]
            files = [e for e in d.entries if not e.name.endswith('/')]
            for file in files:
                with open(os.path.join(full_path, file.name), 'wb') as fh:
                    print '[+] Dumping {}{}'.format(directory, file.name)
                    data = self.device.read_file('{}{}'.format(directory, file.name))
                    fh.write(bytearray(data))

        print '[+] Device memory dumped.'
        print
    # end-of-method do_dump

    @check_if_device_is_connected
    def do_info(self, _):
        """Print connected device info.
        """
        info = Device.get_info(self.device.usb_device)
        print '{:>20s} - {}'.format('Manufacturer', info['manufacturer'])
        print '{:>20s} - {}'.format('Product name', info['product_name'])
        print '{:>20s} - {}'.format('Vendor ID', info['vendor_id'])
        print '{:>20s} - {}'.format('Product ID', info['product_id'])
        print '{:>20s} - {}'.format('Serial number', info['serial_number'])

        try:
            data = self.device.read_file('/DEVICE.BPB')
            resp = ''.join(chr(c) for c in data)
            d = pb_device.PbDeviceInfo()
            d.ParseFromString(resp)
            bootloader_version = '{}.{}.{}'.format(d.bootloader_version.major, d.bootloader_version.minor, d.bootloader_version.patch)
            print '{:>20s} - {}'.format('Bootloader version', bootloader_version)
            platform_version = '{}.{}.{}'.format(d.platform_version.major, d.platform_version.minor, d.platform_version.patch)
            print '{:>20s} - {}'.format('Platform version', platform_version)
            device_version = '{}.{}.{}'.format(d.device_version.major, d.device_version.minor, d.device_version.patch)
            print '{:>20s} - {}'.format('Device version', device_version)
            print '{:>20s} - {}'.format('SVN revision', d.svn_rev)
            print '{:>20s} - {}'.format('Hardware code', d.hardware_code)
            print '{:>20s} - {}'.format('Color', d.product_color)
            print '{:>20s} - {}'.format('Product design', d.product_design)

        except:
            print '[!] Failed to get extended info.'

        print ' '

    # end-of-method do_info

    @check_if_device_is_connected
    def do_walk(self, path):
        """Walk file system.
Usage: walk [path]
        """
        if not path.endswith('/'):
            path += '/'

        fs = self.device.walk(path)
        keyz = fs.keys()
        keyz.sort()

        for k in keyz:
            print k
            d = fs[k]
            files = [e for e in d.entries if not e.name.endswith('/')]
            files.sort()
            for f in files:
                print '{}{} ({} bytes)'.format(k, f.name, f.size)

        print
    # end-of-method do_walk

    pass
Example #15
0
class LoopholeCli(cmd.Cmd):
    """ Loophole command line interface class. """

    __PROMPT = 'loophole({})>'

    def __init__(self):
        """Constructor.
        """
        cmd.Cmd.__init__(self)
        self.prompt = LoopholeCli.__PROMPT.format('no device')
        self.device = None

    # end-of-method __init__

    def do_exit(self, _):
        """Quit.
Usage: exit
        """
        if self.device is not None:
            self.device.close()
        sys.exit(0)

    # end-of-method do_exit

    def do_list(self, _):
        """List available Polar devices.
Usage: list
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                try:
                    info = Device.get_info(dev)
                except ValueError as err:
                    print "Device no: %i" % i
                    print "Device info:"
                    print dev
                    print "-" * 79
                    if 'langid' in err.message:
                        raise ValueError(
                            ("Can't get device info. Origin Error: %s\n"
                             "Maybe this is a permission issue.\n"
                             "Please read section 'permission' in README ;)") %
                            err)
                    raise  # raise origin error

                print '{} - {} ({})'.format(i, info['product_name'],
                                            info['serial_number'])
        else:
            print '[!] No Polar devices found!'

        print

    # end-of-method do_list

    def do_connect(self, dev_no):
        """Connect Polar device. Run 'list' to see available devices.
Usage: connect <device_no>
        """
        try:
            dev_no = int(dev_no)
        except ValueError:
            print '[!] You need to specify the device number. Run \'list\' to see available devices.'
            print
            return

        try:
            devs = Device.list()
            dev = devs[dev_no]
            serial = Device.get_info(dev)['serial_number']

            self.prompt = LoopholeCli.__PROMPT.format(serial)
            self.device = Device(dev)
            self.device.open()

            print '[+] Device connected.'
            print
        except IndexError:
            print '[!] Device not found or failed to open it. Run \'list\' to see available devices.'
            print

    # end-of-method do_connect

    @check_if_device_is_connected
    def do_disconnect(self, _):
        """Disconnect Polar device.
        """
        self.device.close()
        self.device = None
        self.prompt = LoopholeCli.__PROMPT.format('no device')
        print '[+] Device disconnected.'
        print

    # end-of-method do_disconnect

    @check_if_device_is_connected
    def do_get(self, line):
        """Read file from device and store in under local_path.
Usage: get <device_path> <local_path>
        """
        try:
            src, dest = line.strip().split()

            data = self.device.read_file(src)
            with open(dest, 'wb') as outfile:
                outfile.write(bytearray(data))

            print '[+] File \'{}\' saved to \'{}\''.format(src, dest)
            print
        except ValueError:
            print '[!] Invalid command usage.'
            print '[!] Usage: get <source> <destination>'
            print

    # end-of-method do_get

    @check_if_device_is_connected
    def do_delete(self, line):
        """Delete file from device.
Usage: delete <device_path>
        """
        path = line.strip()
        _ = self.device.delete(path)

    # end-of-method do_delete

    @check_if_device_is_connected
    def do_dump(self, path):
        """Dump device memory. Path is local folder to store dump.
Usage: dump <local_path>
        """
        print '[+] Reading files tree...'
        dev_map = self.device.walk(self.device.SEP)

        for directory in dev_map.keys():
            fixed_directory = directory.replace(self.device.SEP, os.sep)
            full_path = os.path.abspath(os.path.join(path,
                                                     fixed_directory[1:]))

            if not os.path.exists(full_path):
                os.makedirs(full_path)

            d = dev_map[directory]
            files = [e for e in d.entries if not e.name.endswith('/')]
            for file in files:
                with open(os.path.join(full_path, file.name), 'wb') as fh:
                    print '[+] Dumping {}{}'.format(directory, file.name)
                    data = self.device.read_file('{}{}'.format(
                        directory, file.name))
                    fh.write(bytearray(data))

        print '[+] Device memory dumped.'
        print

    # end-of-method do_dump

    @check_if_device_is_connected
    def do_info(self, _):
        """Print connected device info.
Usage: info
        """
        info = Device.get_info(self.device.usb_device)
        print '{:>20s} - {}'.format('Manufacturer', info['manufacturer'])
        print '{:>20s} - {}'.format('Product name', info['product_name'])
        print '{:>20s} - {}'.format('Vendor ID', info['vendor_id'])
        print '{:>20s} - {}'.format('Product ID', info['product_id'])
        print '{:>20s} - {}'.format('Serial number', info['serial_number'])

        try:
            data = self.device.read_file('/DEVICE.BPB')
            resp = ''.join(chr(c) for c in data)
            d = pb_device.PbDeviceInfo()
            d.ParseFromString(resp)
            bootloader_version = '{}.{}.{}'.format(d.bootloader_version.major,
                                                   d.bootloader_version.minor,
                                                   d.bootloader_version.patch)
            print '{:>20s} - {}'.format('Bootloader version',
                                        bootloader_version)
            platform_version = '{}.{}.{}'.format(d.platform_version.major,
                                                 d.platform_version.minor,
                                                 d.platform_version.patch)
            print '{:>20s} - {}'.format('Platform version', platform_version)
            device_version = '{}.{}.{}'.format(d.device_version.major,
                                               d.device_version.minor,
                                               d.device_version.patch)
            print '{:>20s} - {}'.format('Device version', device_version)
            print '{:>20s} - {}'.format('SVN revision', d.svn_rev)
            print '{:>20s} - {}'.format('Hardware code', d.hardware_code)
            print '{:>20s} - {}'.format('Color', d.product_color)
            print '{:>20s} - {}'.format('Product design', d.product_design)

        except:
            print '[!] Failed to get extended info.'

        print ' '

    # end-of-method do_info

    @check_if_device_is_connected
    def do_fuzz(self, _):
        import polar
        num = _.strip()

        if len(num) > 0:
            num = int(num)
            resp = self.device.send_raw([0x01, num] + [0x00] * 62)
            print 'req: {} '.format(num),
            if resp:
                print 'err code: {}'.format(polar.PFTP_ERROR[resp[0]])

            return

        for i in xrange(256):
            #raw_input('Sending [{}]...<press enter>'.format(i))
            if (i & 0x03) == 2:
                continue

            if i in [3, 251, 252]:
                continue

            resp = self.device.send_raw([0x01, i] + [0x00] * 62)

            print 'resp: {} '.format(i),
            if resp:
                print 'err code: {}'.format(polar.PFTP_ERROR[resp[0]])
            else:
                print

    # end-of-method do_fuzz

    @check_if_device_is_connected
    def do_put_file(self, line):
        path, filename = line.split()
        self.device.put_file(path.strip(), filename.strip())

    # end-of-method do_put_file

    @check_if_device_is_connected
    def do_walk(self, path):
        """Walk file system. Default device_path is device root folder.
Usage: walk [device_path]
        """
        if not path.endswith('/'):
            path += '/'

        fs = self.device.walk(path)
        keyz = fs.keys()
        keyz.sort()

        for k in keyz:
            print k
            d = fs[k]
            files = [e for e in d.entries if not e.name.endswith('/')]
            files.sort()
            for f in files:
                print '{}{} ({} bytes)'.format(k, f.name, f.size)

        print

    # end-of-method do_walk

    pass
Example #16
0
class LoopholeCli(cmd.Cmd):
    """ Loophole command line interface class. """

    __PROMPT = 'loophole({})>'

    def __init__(self):
        """Constructor.
        """
        cmd.Cmd.__init__(self)
        self.prompt = LoopholeCli.__PROMPT.format('no device')
        self.device = None
    # end-of-method __init__

    def do_exit(self, _):
        """Quit.
        """
        if self.device is not None:
            self.device.close()
        sys.exit(0)
    # end-of-method do_exit

    def do_list(self, _):
        """List available Polar devices.
        """
        devs = Device.list()

        if len(devs) > 0:
            for i, dev in enumerate(devs):
                print '{} - {} ({})'.format(i, dev.product_name, dev.serial_number)
        else:
            print '[!] No Polar devices found!'

        print
    # end-of-method do_list

    def do_connect(self, dev_no):
        """Connect Polar device. Run 'list' to see available devices.
        """
        try:
            dev_no = int(dev_no)
            devs = Device.list()
            dev = devs[dev_no]

            self.prompt = LoopholeCli.__PROMPT.format(dev.serial_number)
            self.device = Device(dev)

            print '[+] Device connected.'
            print
        except IndexError:
            print '[!] Device not found. Run \'list\' to see available devices.'
            print
    # end-of-method do_connect

    def do_disconnect(self, _):
        """Disconnect Polar device.
        """
        if self.device is not None:
            self.device.close()
            self.device = None
            self.prompt = LoopholeCli.__PROMPT.format('no device')
            print '[+] Device disconnected.'
            print
    # end-of-method do_disconnect

    @check_if_device_is_connected
    def do_get(self, line):
        """Read file from device.
Usage: get <src> <dest>
        """
        try:
            src, dest = line.strip().split()

            data = self.device.read_file(src)
            with open(dest, 'wb') as outfile:
                outfile.write(bytearray(data))

            print '[+] File \'{}\' saved to \'{}\''.format(src, dest)
            print
        except ValueError:
            print '[!] Invalid command usage.'
            print '[!] Usage: get <source> <destination>'
            print
    # end-of-method do_get

    def do_dump(self, path):
        """Dump device memory.
Usage: dump <path>
        """
        print '[+] Reading files tree...'
        dev_map = self.device.walk(self.device.SEP)

        for directory in dev_map.keys():
            fixed_directory = directory.replace(self.device.SEP, os.sep)
            full_path = os.path.abspath(os.path.join(path, fixed_directory[1:]))

            if not os.path.exists(full_path):
                os.makedirs(full_path)

            d = dev_map[directory]
            files = [e for e in d.entries if not e.name.endswith('/')]
            for file in files:
                with open(os.path.join(full_path, file.name), 'wb') as fh:
                    print '[+] Dumping {}{}'.format(directory, file.name)
                    data = self.device.read_file('{}{}'.format(directory, file.name))
                    fh.write(bytearray(data))

        print '[+] Device memory dumped.'
        print
    # end-of-method do_dump

    @check_if_device_is_connected
    def do_info(self, _):
        """Print connected device info.
        """
        info = self.device.get_info()
        for k, v in info.items():
            print '{:>20s} - {}'.format(k, v)
        print
    # end-of-method do_info

    @check_if_device_is_connected
    def do_walk(self, path):
        """Walk file system.
Usage: walk [path]
        """
        if not path.endswith('/'):
            path += '/'

        fs = self.device.walk(path)
        keyz = fs.keys()
        keyz.sort()

        for k in keyz:
            print k
            d = fs[k]
            files = [e for e in d.entries if not e.name.endswith('/')]
            files.sort()
            for f in files:
                print '{}{} ({} bytes)'.format(k, f.name, f.size)

        print
    # end-of-method do_walk

    pass