def _decompressIOSSlot(self):
        """
        Slot to decompress an IOS image.
        """

        item = self.uiIOSRoutersTreeWidget.currentItem()
        if item:
            key = item.data(0, QtCore.Qt.UserRole)
            ios_router = self._ios_routers[key]
            path = ios_router["image"]
            if not os.path.isfile(path):
                QtGui.QMessageBox.critical(self, "IOS image", "IOS image file {} is does not exist".format(path))
                return
            if not isIOSCompressed(path):
                QtGui.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
                return

            decompressed_image_path = os.path.splitext(path)[0] + ".image"
            if os.path.isfile(decompressed_image_path):
                QtGui.QMessageBox.critical(self, "IOS image", "Decompressed IOS image {} already exist".format(os.path.basename(decompressed_image_path)))
                return

            thread = DecompressIOSThread(path, decompressed_image_path)
            progress_dialog = ProgressDialog(thread,
                                             "IOS image",
                                             "Decompressing IOS image {}...".format(path),
                                             "Cancel", busy=True, parent=self)
            progress_dialog.show()
            if progress_dialog.exec_() is not False:
                ios_router["image"] = decompressed_image_path
                self._refreshInfo(ios_router)
            thread.wait()
    def _decompressIOSSlot(self):
        """
        Slot to decompress an IOS image.
        """

        item = self.uiIOSRoutersTreeWidget.currentItem()
        if item:
            key = item.data(0, QtCore.Qt.UserRole)
            ios_router = self._ios_routers[key]
            path = ios_router["path"]
            if not os.path.isfile(path):
                QtGui.QMessageBox.critical(self, "IOS image", "IOS image file {} is does not exist".format(path))
                return
            if not isIOSCompressed(path):
                QtGui.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
                return

            decompressed_image_path = os.path.splitext(path)[0] + ".image"
            if os.path.isfile(decompressed_image_path):
                QtGui.QMessageBox.critical(self, "IOS image", "Decompressed IOS image {} already exist".format(os.path.basename(decompressed_image_path)))
                return

            thread = DecompressIOSThread(path, decompressed_image_path)
            progress_dialog = ProgressDialog(thread,
                                             "IOS image",
                                             "Decompressing IOS image {}...".format(path),
                                             "Cancel", busy=True, parent=self)
            progress_dialog.show()
            if progress_dialog.exec_() is not False:
                ios_router["path"] = decompressed_image_path
                ios_router["image"] = os.path.basename(decompressed_image_path)
                self._refreshInfo(ios_router)
            thread.wait()
    def _uncompressIOSSlot(self):
        """
        Slot to uncompress an IOS image.
        """

        item = self.uiIOSImagesTreeWidget.currentItem()
        if item:
            image = item.text(0)
            server = item.text(2)
            key = "{server}:{image}".format(server=server, image=image)
            ios_image = self._ios_images[key]
            path = ios_image["path"]
            if not os.path.isfile(path):
                QtGui.QMessageBox.critical(self, "IOS image", "IOS image file {} is does not exist".format(path))
                return
            if not isIOSCompressed(path):
                QtGui.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
                return

            uncompressed_image_path = os.path.splitext(path)[0] + ".image"
            if os.path.isfile(uncompressed_image_path):
                QtGui.QMessageBox.critical(self, "IOS image", "Uncompressed IOS image {} already exist".format(os.path.basename(uncompressed_image_path)))
                return

            thread = UncompressIOSThread(path, uncompressed_image_path)
            progress_dialog = ProgressDialog(thread,
                                             "IOS image",
                                             "Uncompressing IOS image {}...".format(path),
                                             "Cancel", busy=True, parent=self)
            progress_dialog.show()
            if progress_dialog.exec_() is not False:
                self.uiIOSPathLineEdit.setText(uncompressed_image_path)
                self._iosImageSaveSlot()
            thread.wait()
Example #4
0
    def localServerAutoStartIfRequire(self):
        """
        Try to start the embed gns3 server.
        """

        if not self.shouldLocalServerAutoStart():
            self._http_client = HTTPClient(self._settings)
            Controller.instance().setHttpClient(self._http_client)
            return

        if self.isLocalServerRunning() and self._server_started_by_me:
            return True

        # We check if two gui are not launched at the same time
        # to avoid killing the server of the other GUI
        if not LocalConfig.isMainGui():
            log.info("Not the main GUI, will not auto start the server")
            self._http_client = HTTPClient(self._settings)
            Controller.instance().setHttpClient(self._http_client)
            return True

        if self.isLocalServerRunning():
            log.debug("A local server already running on this host")
            # Try to kill the server. The server can be still running after
            # if the server was started by hand
            self._killAlreadyRunningServer()

        if not self.isLocalServerRunning():
            if not self.initLocalServer():
                QtWidgets.QMessageBox.critical(
                    self.parent(), "Local server",
                    "Could not start the local server process: {}".format(
                        self._settings["path"]))
                return False
            if not self.startLocalServer():
                QtWidgets.QMessageBox.critical(
                    self.parent(), "Local server",
                    "Could not start the local server process: {}".format(
                        self._settings["path"]))
                return False

        if self.parent():
            worker = WaitForConnectionWorker(self._settings["host"],
                                             self._port)
            progress_dialog = ProgressDialog(
                worker,
                "Local server",
                "Connecting to server {} on port {}...".format(
                    self._settings["host"], self._port),
                "Cancel",
                busy=True,
                parent=self.parent())
            progress_dialog.show()
            if not progress_dialog.exec_():
                return False
        self._server_started_by_me = True
        self._http_client = HTTPClient(self._settings)
        Controller.instance().setHttpClient(self._http_client)

        return True
Example #5
0
    def localServerAutoStartIfRequire(self):
        """
        Try to start the embed gns3 server.
        """

        if not self.shouldLocalServerAutoStart():
            self._http_client = HTTPClient(self._settings)
            Controller.instance().setHttpClient(self._http_client)
            return

        if self.isLocalServerRunning() and self._server_started_by_me:
            return True

        # We check if two gui are not launched at the same time
        # to avoid killing the server of the other GUI
        if not LocalConfig.isMainGui():
            log.info("Not the main GUI, will not auto start the server")
            self._http_client = HTTPClient(self._settings)
            Controller.instance().setHttpClient(self._http_client)
            return True

        if self.isLocalServerRunning():
            log.info("A local server already running on this host")
            # Try to kill the server. The server can be still running after
            # if the server was started by hand
            self._killAlreadyRunningServer()

        if not self.isLocalServerRunning():
            if not self.initLocalServer():
                QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not start the local server process: {}".format(self._settings["path"]))
                return False
            if not self.startLocalServer():
                QtWidgets.QMessageBox.critical(self.parent(), "Local server", "Could not start the local server process: {}".format(self._settings["path"]))
                return False

        if self.parent():
            worker = WaitForConnectionWorker(self._settings["host"], self._port)
            progress_dialog = ProgressDialog(worker,
                                             "Local server",
                                             "Connecting to server {} on port {}...".format(self._settings["host"], self._port),
                                             "Cancel", busy=True, parent=self.parent())
            progress_dialog.show()
            if not progress_dialog.exec_():
                return False
        self._server_started_by_me = True
        self._http_client = HTTPClient(self._settings)
        Controller.instance().setHttpClient(self._http_client)

        return True
    def _decompressIOSSlot(self):
        """
        Slot to decompress an IOS image.
        """

        item = self.uiIOSRoutersTreeWidget.currentItem()
        if item:
            key = item.data(0, QtCore.Qt.UserRole)
            ios_router = self._ios_routers[key]
            path = ios_router["image"]
            if not os.path.isabs(path):
                path = os.path.join(self.getImageDirectory(), path)
            if not os.path.isfile(path):
                QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image file {} does not exist".format(path))
                return
            try:
                if not isIOSCompressed(path):
                    QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
                    return
            except OSError as e:
                # errno 22, invalid argument means the file system where the IOS image is located doesn't support mmap
                if e.errno == 22:
                    QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image {} cannot be memory mapped, most likely because the file system doesn't support it".format(os.path.basename(path)))
                else:
                    QtWidgets.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
                return
            except ValueError as e:
                QtWidgets.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
                return

            decompressed_image_path = os.path.splitext(path)[0] + ".image"
            if os.path.isfile(decompressed_image_path):
                QtWidgets.QMessageBox.critical(self, "IOS image", "Decompressed IOS image {} already exist".format(os.path.basename(decompressed_image_path)))
                return

            worker = DecompressIOSWorker(path, decompressed_image_path)
            progress_dialog = ProgressDialog(worker,
                                             "IOS image",
                                             "Decompressing IOS image {}...".format(path),
                                             "Cancel", busy=True, parent=self)
            progress_dialog.show()
            if progress_dialog.exec_() is not False:
                ios_router["image"] = decompressed_image_path
                self._refreshInfo(ios_router)
Example #7
0
    def askCopyUploadImage(self, parent, source_path, server, node_type):
        """
        Ask user for copying the image to the default directory or upload
        it to remote server.

        :param parent: Parent window
        :param path: File path on computer
        :param server: The server where the images should be located
        :param node_type: Remote upload endpoint
        :returns path: Final path
        """

        if (server and server != "local") or Controller.instance().isRemote():
            return self._uploadImageToRemoteServer(source_path, server, node_type)
        else:
            destination_directory = self.getDirectoryForType(node_type)
            destination_path = os.path.join(destination_directory, os.path.basename(source_path))
            source_filename = os.path.basename(source_path)
            destination_filename = os.path.basename(destination_path)
            if os.path.normpath(os.path.dirname(source_path)) != destination_directory:
                # the image is not in the default images directory
                if source_filename == destination_filename:
                    # the filename already exists in the default images directory
                    source_image = Image(node_type, source_path, filename=source_filename)
                    destination_image = Image(node_type, destination_path, filename=destination_filename)
                    try:
                        if source_image.md5sum == destination_image.md5sum:
                            # the source and destination images are identical
                            return source_path
                    except OSError as e:
                        QtWidgets.QMessageBox.critical(parent, 'Image', 'Cannot compare image file {} with {}: {}.'.format(source_path, destination_path, str(e)))
                        return source_path
                    # find a new unique path to avoid overwriting existing destination file
                    destination_path = self._getUniqueDestinationPath(source_image, node_type, destination_path)

                reply = QtWidgets.QMessageBox.question(parent,
                                                       'Image',
                                                       'Would you like to copy {} to the default images directory'.format(source_filename),
                                                       QtWidgets.QMessageBox.Yes,
                                                       QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    try:
                        os.makedirs(destination_directory, exist_ok=True)
                    except OSError as e:
                        QtWidgets.QMessageBox.critical(parent, 'Image', 'Could not create destination directory {}: {}'.format(destination_directory, str(e)))
                        return source_path

                    worker = FileCopyWorker(source_path, destination_path)
                    progress_dialog = ProgressDialog(worker, 'Image', 'Copying {}'.format(source_filename), 'Cancel', busy=True, parent=parent)
                    progress_dialog.show()
                    progress_dialog.exec_()
                    errors = progress_dialog.errors()
                    if errors:
                        QtWidgets.QMessageBox.critical(parent, 'Image', '{}'.format(''.join(errors)))
                        return source_path
                    else:
                        source_path = destination_path
            return source_path
    def _decompressIOSSlot(self):
        """
        Slot to decompress an IOS image.
        """

        item = self.uiIOSRoutersTreeWidget.currentItem()
        if item:
            key = item.data(0, QtCore.Qt.UserRole)
            ios_router = self._ios_routers[key]
            path = ios_router["image"]
            if not os.path.isfile(path):
                QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image file {} is does not exist".format(path))
                return
            try:
                if not isIOSCompressed(path):
                    QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image {} is not compressed".format(os.path.basename(path)))
                    return
            except OSError as e:
                # errno 22, invalid argument means the file system where the IOS image is located doesn't support mmap
                if e.errno == 22:
                    QtWidgets.QMessageBox.critical(self, "IOS image", "IOS image {} cannot be memory mapped, most likely because the file system doesn't support it".format(os.path.basename(path)))
                else:
                    QtWidgets.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
                return
            except ValueError as e:
                QtWidgets.QMessageBox.critical(self, "IOS image", "Could not determine if the IOS image is compressed: {}".format(e))
                return

            decompressed_image_path = os.path.splitext(path)[0] + ".image"
            if os.path.isfile(decompressed_image_path):
                QtWidgets.QMessageBox.critical(self, "IOS image", "Decompressed IOS image {} already exist".format(os.path.basename(decompressed_image_path)))
                return

            worker = DecompressIOSWorker(path, decompressed_image_path)
            progress_dialog = ProgressDialog(worker,
                                             "IOS image",
                                             "Decompressing IOS image {}...".format(path),
                                             "Cancel", busy=True, parent=self)
            progress_dialog.show()
            if progress_dialog.exec_() is not False:
                ios_router["image"] = decompressed_image_path
                self._refreshInfo(ios_router)
Example #9
0
    def stopLocalServer(self, wait=False):
        """
        Stops the local server.

        :param wait: wait for the server to stop
        """

        if self.localServerProcessIsRunning():
            self._stopping = True
            log.info("Stopping local server (PID={})".format(self._local_server_process.pid))
            # local server is running, let's stop it
            if self._http_client:
                self._http_client.shutdown()
            if wait:
                worker = StopLocalServerWorker(self._local_server_process)
                progress_dialog = ProgressDialog(worker, "Local server", "Waiting for the local server to stop...", None, busy=True, parent=self.parent())
                progress_dialog.show()
                progress_dialog.exec_()
                if self._local_server_process.returncode is None:
                    self._killLocalServer()
            self._server_started_by_me = False
Example #10
0
    def stopLocalServer(self, wait=False):
        """
        Stops the local server.

        :param wait: wait for the server to stop
        """

        if self.localServerProcessIsRunning():
            self._stopping = True
            log.debug("Stopping local server (PID={})".format(
                self._local_server_process.pid))
            # local server is running, let's stop it
            if self._http_client:
                self._http_client.shutdown()
            if wait:
                worker = StopLocalServerWorker(self._local_server_process)
                progress_dialog = ProgressDialog(
                    worker,
                    "Local server",
                    "Waiting for the local server to stop...",
                    None,
                    busy=True,
                    parent=self.parent())
                progress_dialog.show()
                progress_dialog.exec_()
                if self._local_server_process.returncode is None:
                    self._killLocalServer()
            self._server_started_by_me = False
Example #11
0
    def getDiskImage(parent):

        destination_directory = os.path.join(
            MainWindow.instance().imagesDirPath(), "QEMU")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(
            parent, "Select a QEMU disk image", destination_directory)
        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "QEMU disk image",
                                       "Cannot read {}".format(path))
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(
                parent, "QEMU disk images directory",
                "Could not create the QEMU disk images directory {}: {}".
                format(destination_directory, e))
            return

        if os.path.normpath(os.path.dirname(path)) != destination_directory:
            # the QEMU disk image is not in the default images directory
            reply = QtGui.QMessageBox.question(
                parent, "QEMU disk image",
                "Would you like to copy {} to the default images directory".
                format(os.path.basename(path)), QtGui.QMessageBox.Yes,
                QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                destination_path = os.path.join(destination_directory,
                                                os.path.basename(path))
                thread = FileCopyThread(path, destination_path)
                progress_dialog = ProgressDialog(thread,
                                                 "QEMU disk image",
                                                 "Copying {}".format(
                                                     os.path.basename(path)),
                                                 "Cancel",
                                                 busy=True,
                                                 parent=parent)
                thread.deleteLater()
                progress_dialog.show()
                progress_dialog.exec_()
                errors = progress_dialog.errors()
                if errors:
                    QtGui.QMessageBox.critical(parent, "QEMU disk image",
                                               "{}".format("".join(errors)))
                else:
                    path = destination_path

        return path
Example #12
0
    def askCopyUploadImage(self, parent, path, server, node_type):
        """
        Ask user for copying the image to the default directory or upload
        it to remote server.

        :param parent: Parent window
        :param path: File path on computer
        :param server: The server where the images should be located
        :param node_type: Remote upload endpoint
        :returns path: Final path
        """

        if (server and server != "local") or Controller.instance().isRemote():
            return self._uploadImageToRemoteServer(path, server, node_type)
        else:
            destination_directory = self.getDirectoryForType(node_type)
            if os.path.normpath(
                    os.path.dirname(path)) != destination_directory:
                # the IOS image is not in the default images directory
                reply = QtWidgets.QMessageBox.question(
                    parent, 'Image',
                    'Would you like to copy {} to the default images directory'
                    .format(os.path.basename(path)), QtWidgets.QMessageBox.Yes,
                    QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    destination_path = os.path.join(destination_directory,
                                                    os.path.basename(path))
                    try:
                        os.makedirs(destination_directory, exist_ok=True)
                    except OSError as e:
                        QtWidgets.QMessageBox.critical(
                            parent, 'Image',
                            'Could not create destination directory {}: {}'.
                            format(destination_directory, str(e)))
                        return path
                    worker = FileCopyWorker(path, destination_path)
                    progress_dialog = ProgressDialog(
                        worker,
                        'Image',
                        'Copying {}'.format(os.path.basename(path)),
                        'Cancel',
                        busy=True,
                        parent=parent)
                    progress_dialog.show()
                    progress_dialog.exec_()
                    errors = progress_dialog.errors()
                    if errors:
                        QtWidgets.QMessageBox.critical(
                            parent, 'Image', '{}'.format(''.join(errors)))
                        return path
                    else:
                        path = destination_path
            return path
Example #13
0
    def askCopyUploadImage(self, parent, source_path, server, node_type):
        """
        Ask user for copying the image to the default directory or upload
        it to remote server.

        :param parent: Parent window
        :param path: File path on computer
        :param server: The server where the images should be located
        :param node_type: Remote upload endpoint
        :returns path: Final path
        """

        if (server and server != "local") or Controller.instance().isRemote():
            return self._uploadImageToRemoteServer(source_path, server, node_type)
        else:
            destination_directory = self.getDirectoryForType(node_type)
            destination_path = os.path.join(destination_directory, os.path.basename(source_path))
            source_filename = os.path.basename(source_path)
            destination_filename = os.path.basename(destination_path)
            if os.path.normpath(os.path.dirname(source_path)) != destination_directory:
                # the image is not in the default images directory
                if source_filename == destination_filename:
                    # the filename already exists in the default images directory
                    source_image = Image(node_type, source_path, filename=source_filename)
                    destination_image = Image(node_type, destination_path, filename=destination_filename)
                    try:
                        if source_image.md5sum == destination_image.md5sum:
                            # the source and destination images are identical
                            return source_path
                    except OSError as e:
                        QtWidgets.QMessageBox.critical(parent, 'Image', 'Cannot compare image file {} with {}: {}.'.format(source_path, destination_path, str(e)))
                        return source_path
                    # find a new unique path to avoid overwriting existing destination file
                    destination_path = self._getUniqueDestinationPath(source_image, node_type, destination_path)

                reply = QtWidgets.QMessageBox.question(parent,
                                                       'Image',
                                                       'Would you like to copy {} to the default images directory'.format(source_filename),
                                                       QtWidgets.QMessageBox.Yes,
                                                       QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    try:
                        os.makedirs(destination_directory, exist_ok=True)
                    except OSError as e:
                        QtWidgets.QMessageBox.critical(parent, 'Image', 'Could not create destination directory {}: {}'.format(destination_directory, str(e)))
                        return source_path

                    worker = FileCopyWorker(source_path, destination_path)
                    progress_dialog = ProgressDialog(worker, 'Image', 'Copying {}'.format(source_filename), 'Cancel', busy=True, parent=parent)
                    progress_dialog.show()
                    progress_dialog.exec_()
                    errors = progress_dialog.errors()
                    if errors:
                        QtWidgets.QMessageBox.critical(parent, 'Image', '{}'.format(''.join(errors)))
                        return source_path
                    else:
                        source_path = destination_path
            return source_path
Example #14
0
    def askCopyUploadImage(self, parent, path, server, vm_type):
        """
        Ask user for copying the image to the default directory or upload
        it to remote server.

        :param parent: Parent window
        :param path: File path on computer
        :param server: The server where the images should be located
        :param vm_type: Remote upload endpoint
        :returns path: Final path
        """

        if server and not server.isLocal():
            return self._uploadImageToRemoteServer(path, server, vm_type)
        else:
            destination_directory = self.getDirectoryForType(vm_type)
            if os.path.normpath(os.path.dirname(path)) != destination_directory:
                # the IOS image is not in the default images directory
                reply = QtWidgets.QMessageBox.question(parent,
                                                       'Image',
                                                       'Would you like to copy {} to the default images directory'.format(os.path.basename(path)),
                                                       QtWidgets.QMessageBox.Yes,
                                                       QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    destination_path = os.path.join(destination_directory, os.path.basename(path))
                    try:
                        os.makedirs(destination_directory, exist_ok=True)
                    except OSError as e:
                        QtWidgets.QMessageBox.critical(parent, 'Image', 'Could not create destination directory {}: {}'.format(destination_directory, str(e)))
                        return path
                    worker = FileCopyWorker(path, destination_path)
                    progress_dialog = ProgressDialog(worker, 'Image', 'Copying {}'.format(os.path.basename(path)), 'Cancel', busy=True, parent=parent)
                    progress_dialog.show()
                    progress_dialog.exec_()
                    errors = progress_dialog.errors()
                    if errors:
                        QtWidgets.QMessageBox.critical(parent, 'Image', '{}'.format(''.join(errors)))
                        return path
                    else:
                        path = destination_path
            return path
    def getDiskImage(parent):

        destination_directory = os.path.join(MainWindow.instance().imagesDirPath(), "QEMU")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(parent,
                                                             "Select a QEMU disk image",
                                                             destination_directory)
        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "QEMU disk image", "Cannot read {}".format(path))
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "QEMU disk images directory", "Could not create the QEMU disk images directory {}: {}".format(destination_directory, e))
            return

        if os.path.normpath(os.path.dirname(path)) != destination_directory:
            # the QEMU disk image is not in the default images directory
            reply = QtGui.QMessageBox.question(parent,
                                               "QEMU disk image",
                                               "Would you like to copy {} to the default images directory".format(os.path.basename(path)),
                                               QtGui.QMessageBox.Yes,
                                               QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                destination_path = os.path.join(destination_directory, os.path.basename(path))
                worker = FileCopyWorker(path, destination_path)
                progress_dialog = ProgressDialog(worker, "QEMU disk image", "Copying {}".format(os.path.basename(path)), "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                progress_dialog.exec_()
                errors = progress_dialog.errors()
                if errors:
                    QtGui.QMessageBox.critical(parent, "QEMU disk image", "{}".format("".join(errors)))
                else:
                    path = destination_path

        return path
Example #16
0
def sudo(*commands, parent=None, shell=False):
    """
    Run a command  as an administrator.
    """

    if parent is None:
        from ..main_window import MainWindow
        parent = MainWindow.instance()

    while True:
        if sys.platform.startswith("win32"):
            for command in commands:
                worker = WaitForRunAsWorker(command)
                progress_dialog = ProgressDialog(worker,
                                                 "Run as administrator",
                                                 "Executing command...",
                                                 "Cancel",
                                                 busy=True,
                                                 parent=parent)
                progress_dialog.show()
                if not progress_dialog.exec_():
                    return False
        elif sys.platform.startswith("darwin"):
            cmd = []
            for command in commands:
                command = [shlex.quote(c) for c in command]
                cmd.append(' '.join(command))
            command = [
                "osascript", "-e",
                "do shell script \"{}\" with administrator privileges".format(
                    ' && '.join(cmd))
            ]
            log.info("Execute as admin: {}".format(' '.join(command)))
            worker = WaitForCommandWorker(command, shell=shell)

            for line in worker.output().decode("utf-8",
                                               errors="ignore").splitlines():
                log.info(line)
            progress_dialog = ProgressDialog(worker,
                                             "Run as administrator",
                                             "Executing command...",
                                             "Cancel",
                                             busy=True,
                                             parent=parent)
            progress_dialog.show()
            if not progress_dialog.exec_():
                return False

        else:
            command_detail = []
            for command in commands:
                command = [shlex.quote(c) for c in command]
                command_detail.append(' '.join(command))

            password, ok = QtWidgets.QInputDialog.getText(
                parent, "Run as administrator",
                "Please enter your password to proceed.\nCommand:\n{}".format(
                    '\n'.join(command_detail)), QtWidgets.QLineEdit.Password,
                "")
            if not ok:
                return False

            try:
                # check the password is valid
                subprocess.check_output(["sudo", "-S", "id"],
                                        input=(password + "\n").encode(),
                                        timeout=30)
            except subprocess.CalledProcessError:
                continue
            except (OSError, subprocess.SubprocessError) as e:
                QtWidgets.QMessageBox.critical(
                    parent, "Run as administrator",
                    "Could not execute sudo: {}".format(e))
                return False

            # sudo shouldn't need the password again.
            for command in commands:
                waited_command = ["sudo"]
                waited_command.extend(command)
                worker = WaitForCommandWorker(waited_command, shell=shell)

                for line in worker.output().decode(
                        "utf-8", errors="ignore").splitlines():
                    log.info(line)
                progress_dialog = ProgressDialog(worker,
                                                 "Run as administrator",
                                                 "Executing command...",
                                                 "Cancel",
                                                 busy=True,
                                                 parent=parent)
                progress_dialog.show()
                if not progress_dialog.exec_():
                    return False
        return True
    def getIOSImage(cls, parent, server):
        """

        :param parent: parent widget
        :param server: The server where the image is located

        :return: path to the IOS image or None
        """

        if not cls._default_images_dir:
            cls._default_images_dir = cls.getImageDirectory()

        path, _ = QtWidgets.QFileDialog.getOpenFileName(parent,
                                                        "Select an IOS image",
                                                        cls._default_images_dir,
                                                        "All files (*.*);;IOS image (*.bin *.image)",
                                                        "IOS image (*.bin *.image)")

        if not path:
            return
        cls._default_images_dir = os.path.dirname(path)

        if not os.access(path, os.R_OK):
            QtWidgets.QMessageBox.critical(parent, "IOS image", "Cannot read {}".format(path))
            return

        if sys.platform.startswith('win'):
            # Dynamips (Cygwin actually) doesn't like non ascii paths on Windows
            try:
                path.encode('ascii')
            except UnicodeEncodeError:
                QtWidgets.QMessageBox.warning(parent, "IOS image", "The IOS image filename should contains only ascii (English) characters.")

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtWidgets.QMessageBox.critical(parent, "IOS image", "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
        if elf_header_start != b'\x7fELF\x01\x02\x01':
            QtWidgets.QMessageBox.critical(parent, "IOS image", "Sorry, this is not a valid IOS image!")
            return

        try:
            os.makedirs(cls.getImageDirectory(), exist_ok=True)
        except OSError as e:
            QtWidgets.QMessageBox.critical(parent, "IOS images directory", "Could not create the IOS images directory {}: {}".format(cls.getImageDirectory(), e))
            return

        compressed = False
        try:
            compressed = isIOSCompressed(path)
        except (OSError, ValueError):
            pass  # ignore errors if we cannot find out the IOS image is compressed.
        if compressed:
            reply = QtWidgets.QMessageBox.question(parent, "IOS image", "Would you like to decompress this IOS image?", QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
            if reply == QtWidgets.QMessageBox.Yes:
                decompressed_image_path = os.path.join(cls.getImageDirectory(), os.path.basename(os.path.splitext(path)[0] + ".image"))
                worker = DecompressIOSWorker(path, decompressed_image_path)
                progress_dialog = ProgressDialog(worker,
                                                 "IOS image",
                                                 "Decompressing IOS image {}...".format(os.path.basename(path)),
                                                 "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                if progress_dialog.exec_() is not False:
                    path = decompressed_image_path

        path = ImageManager.instance().askCopyUploadImage(parent, path, server, "DYNAMIPS")

        return path
    def getIOSImage(parent):
        """

        :param parent: parent widget

        :return: path to the IOS image or None
        """

        destination_directory = os.path.join(MainWindow.instance().settings()["images_path"], "IOS")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(parent,
                                                             "Select an IOS image",
                                                             destination_directory,
                                                             "All files (*.*);;IOS image (*.bin *.image)",
                                                             "IOS image (*.bin *.image)")
        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "IOS image", "Cannot read {}".format(path))
            return

        if sys.platform.startswith('win'):
            # Dynamips (Cygwin acutally) doesn't like non ascii paths on Windows
            try:
                path.encode('ascii')
            except UnicodeEncodeError:
                QtGui.QMessageBox.warning(parent, "IOS image", "The IOS image filename should contains only ascii (English) characters.")

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "IOS image", "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
        if elf_header_start != b'\x7fELF\x01\x02\x01':
            QtGui.QMessageBox.critical(parent, "IOS image", "Sorry, this is not a valid IOS image!")
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "IOS images directory", "Could not create the IOS images directory {}: {}".format(destination_directory, str(e)))
            return

        if isIOSCompressed(path):
            reply = QtGui.QMessageBox.question(parent, "IOS image", "Would you like to uncompress this IOS image?",
                                               QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                uncompressed_image_path = os.path.join(destination_directory, os.path.basename(os.path.splitext(path)[0] + ".image"))
                thread = UncompressIOSThread(path, uncompressed_image_path)
                progress_dialog = ProgressDialog(thread,
                                                 "IOS image",
                                                 "Uncompressing IOS image {}...".format(os.path.basename(path)),
                                                 "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                if progress_dialog.exec_() is not False:
                    path = uncompressed_image_path
                thread.wait()

        if os.path.dirname(path) != destination_directory:
            # the IOS image is not in the default images directory
            new_destination_path = os.path.join(destination_directory, os.path.basename(path))
            try:
                # try to create a symbolic link to it
                symlink_path = new_destination_path
                os.symlink(path, symlink_path)
                path = symlink_path
            except (OSError, NotImplementedError):
                # if unsuccessful, then copy the IOS image itself
                try:
                    shutil.copyfile(path, new_destination_path)
                    path = new_destination_path
                except OSError:
                    pass

        return path
    def _iosImageBrowserSlot(self):
        """
        Slot to open a file browser and select an IOS image.
        """

        destination_directory = os.path.join(self._main_window.settings()["images_path"], "IOS")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(self,
                                                             "Select an IOS image",
                                                             destination_directory,
                                                             "All files (*.*);;IOS image (*.bin *.image)",
                                                             "IOS image (*.bin *.image)")
        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(self, "IOS image", "Cannot read {}".format(path))
            return

        if sys.platform.startswith('win'):
            # Dynamips (Cygwin acutally) doesn't like non ascii paths on Windows
            try:
                path.encode('ascii')
            except UnicodeEncodeError:
                QtGui.QMessageBox.warning(self, "IOS image", "The IOS image filename should contains only ascii (English) characters.")

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtGui.QMessageBox.critical(self, "IOS image", "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
        if elf_header_start != b'\x7fELF\x01\x02\x01':
            QtGui.QMessageBox.critical(self, "IOS image", "Sorry, this is not a valid IOS image!")
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(self, "IOS images directory", "Could not create the IOS images directory {}: {}".format(destination_directory, str(e)))
            return

        if isIOSCompressed(path):
            reply = QtGui.QMessageBox.question(self, "IOS image", "Would you like to uncompress this IOS image?",
                                               QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                uncompressed_image_path = os.path.join(destination_directory, os.path.basename(os.path.splitext(path)[0] + ".image"))
                thread = UncompressIOSThread(path, uncompressed_image_path)
                progress_dialog = ProgressDialog(thread,
                                                 "IOS image",
                                                 "Uncompressing IOS image {}...".format(path),
                                                 "Cancel", busy=True, parent=self)
                progress_dialog.show()
                if progress_dialog.exec_() is not False:
                    path = uncompressed_image_path
                thread.wait()

        if os.path.dirname(path) != destination_directory:
            # the IOS image is not in the default images directory
            new_destination_path = os.path.join(destination_directory, os.path.basename(path))
            try:
                # try to create a symbolic link to it
                symlink_path = new_destination_path
                os.symlink(path, symlink_path)
                path = symlink_path
            except (OSError, NotImplementedError):
                # if unsuccessful, then copy the IOS image itself
                try:
                    shutil.copyfile(path, new_destination_path)
                    path = new_destination_path
                except OSError:
                    pass

        self.uiIOSPathLineEdit.clear()
        self.uiIOSPathLineEdit.setText(path)

        # try to guess the platform
        image = os.path.basename(path)
        match = re.match("^(c[0-9]+)\\-\w+", image)
        if not match:
            QtGui.QMessageBox.warning(self, "IOS image", "Could not detect the platform, make sure this is a valid IOS image!")
            return

        detected_platform = match.group(1)
        detected_chassis = ""
        # IOS images for the 3600 platform start with the chassis name (c3620 etc.)
        for platform, chassis in CHASSIS.items():
            if detected_platform[1:] in chassis:
                detected_chassis = detected_platform[1:]
                detected_platform = platform
                break

        if detected_platform not in PLATFORMS_DEFAULT_RAM:
            QtGui.QMessageBox.warning(self, "IOS image", "This IOS image is for the {} platform/chassis and is not supported by this application!".format(detected_platform))
            return

        index = self.uiPlatformComboBox.findText(detected_platform)
        if index != -1:
            self.uiPlatformComboBox.setCurrentIndex(index)

        index = self.uiChassisComboBox.findText(detected_chassis)
        if index != -1:
            self.uiChassisComboBox.setCurrentIndex(index)

        self.uiRAMSpinBox.setValue(PLATFORMS_DEFAULT_RAM[detected_platform])
    def getIOUImage(parent):
        """

        :param parent: parent widget

        :return: path to the IOU image or None
        """

        destination_directory = os.path.join(MainWindow.instance().imagesDirPath(), "IOU")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(parent,
                                                             "Select an IOU image",
                                                             destination_directory,
                                                             "All files (*)",
                                                             "IOU image (*.bin *.image)")

        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "IOU image", "Cannot read {}".format(path))
            return

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "IOU image", "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, little endian and have an ELF version of 1
        # normal IOS image are big endian!
        if elf_header_start != b'\x7fELF\x01\x01\x01':
            QtGui.QMessageBox.critical(parent, "IOU image", "Sorry, this is not a valid IOU image!")
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "IOU images directory", "Could not create the IOU images directory {}: {}".format(destination_directory, e))
            return

        if os.path.normpath(os.path.dirname(path)) != destination_directory:
            # the IOU image is not in the default images directory
            reply = QtGui.QMessageBox.question(parent,
                                               "IOU image",
                                               "Would you like to copy {} to the default images directory".format(os.path.basename(path)),
                                               QtGui.QMessageBox.Yes,
                                               QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                destination_path = os.path.join(destination_directory, os.path.basename(path))
                thread = FileCopyThread(path, destination_path)
                progress_dialog = ProgressDialog(thread, "Project", "Copying {}".format(os.path.basename(path)), "Cancel", busy=True, parent=parent)
                thread.deleteLater()
                progress_dialog.show()
                progress_dialog.exec_()
                errors = progress_dialog.errors()
                if errors:
                    QtGui.QMessageBox.critical(parent, "IOS image", "{}".format("".join(errors)))
                else:
                    path = destination_path
                    mode = os.stat(path).st_mode
                    os.chmod(path, mode | stat.S_IXUSR)

        if not os.access(path, os.X_OK):
            QtGui.QMessageBox.warning(parent, "IOU image", "{} is not executable".format(path))

        return path
    def getIOSImage(parent):
        """

        :param parent: parent widget

        :return: path to the IOS image or None
        """

        destination_directory = os.path.join(MainWindow.instance().imagesDirPath(), "IOS")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(parent,
                                                             "Select an IOS image",
                                                             destination_directory,
                                                             "All files (*.*);;IOS image (*.bin *.image)",
                                                             "IOS image (*.bin *.image)")
        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "IOS image", "Cannot read {}".format(path))
            return

        if sys.platform.startswith('win'):
            # Dynamips (Cygwin acutally) doesn't like non ascii paths on Windows
            try:
                path.encode('ascii')
            except UnicodeEncodeError:
                QtGui.QMessageBox.warning(parent, "IOS image", "The IOS image filename should contains only ascii (English) characters.")

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "IOS image", "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
        if elf_header_start != b'\x7fELF\x01\x02\x01':
            QtGui.QMessageBox.critical(parent, "IOS image", "Sorry, this is not a valid IOS image!")
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(parent, "IOS images directory", "Could not create the IOS images directory {}: {}".format(destination_directory, e))
            return

        compressed = False
        try:
            compressed = isIOSCompressed(path)
        except (OSError, ValueError):
            pass  # ignore errors if we cannot find out the IOS image is compressed.
        if compressed:
            reply = QtGui.QMessageBox.question(parent, "IOS image", "Would you like to decompress this IOS image?",
                                               QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                decompressed_image_path = os.path.join(destination_directory, os.path.basename(os.path.splitext(path)[0] + ".image"))
                worker = DecompressIOSWorker(path, decompressed_image_path)
                progress_dialog = ProgressDialog(worker,
                                                 "IOS image",
                                                 "Decompressing IOS image {}...".format(os.path.basename(path)),
                                                 "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                if progress_dialog.exec_() is not False:
                    path = decompressed_image_path

        if os.path.normpath(os.path.dirname(path)) != destination_directory:
            # the IOS image is not in the default images directory
            reply = QtGui.QMessageBox.question(parent,
                                               "IOS image",
                                               "Would you like to copy {} to the default images directory".format(os.path.basename(path)),
                                               QtGui.QMessageBox.Yes,
                                               QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                destination_path = os.path.join(destination_directory, os.path.basename(path))
                worker = FileCopyWorker(path, destination_path)
                progress_dialog = ProgressDialog(worker, "IOS image", "Copying {}".format(os.path.basename(path)), "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                progress_dialog.exec_()
                errors = progress_dialog.errors()
                if errors:
                    QtGui.QMessageBox.critical(parent, "IOS image", "{}".format("".join(errors)))
                else:
                    path = destination_path

        return path
Example #22
0
def sudo(*commands, parent=None, shell=False):
    """
    Run a command  as an administrator.
    """

    if parent is None:
        from ..main_window import MainWindow
        parent = MainWindow.instance()

    while True:
        if sys.platform.startswith("win32"):
            for command in commands:
                worker = WaitForRunAsWorker(command)
                progress_dialog = ProgressDialog(worker, "Run as administrator", "Executing command...", "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                if not progress_dialog.exec_():
                    return False
        elif sys.platform.startswith("darwin"):
            cmd = []
            for command in commands:
                command = [shlex.quote(c) for c in command]
                cmd.append(' '.join(command))
            command = ["osascript", "-e", "do shell script \"{}\" with administrator privileges".format(' && '.join(cmd))]
            log.info("Execute as admin: {}".format(' '.join(command)))
            worker = WaitForCommandWorker(command, shell=shell)

            for line in worker.output().decode("utf-8", errors="ignore").splitlines():
                log.info(line)
            progress_dialog = ProgressDialog(worker, "Run as administrator", "Executing command...", "Cancel", busy=True, parent=parent)
            progress_dialog.show()
            if not progress_dialog.exec_():
                return False

        else:
            command_detail = []
            for command in commands:
                command = [shlex.quote(c) for c in command]
                command_detail.append(' '.join(command))

            password, ok = QtWidgets.QInputDialog.getText(parent,
                                                          "Run as administrator",
                                                          "Please enter your password to proceed.\nCommand:\n{}".format('\n'.join(command_detail)),
                                                          QtWidgets.QLineEdit.Password, "")
            if not ok:
                return False

            try:
                # check the password is valid
                subprocess.check_output(["sudo", "-S", "id"], input=(password + "\n").encode(), timeout=30)
            except subprocess.CalledProcessError:
                continue
            except (OSError, subprocess.SubprocessError) as e:
                QtWidgets.QMessageBox.critical(parent, "Run as administrator", "Could not execute sudo: {}".format(e))
                return False

            # sudo shouldn't need the password again.
            for command in commands:
                waited_command = ["sudo"]
                waited_command.extend(command)
                worker = WaitForCommandWorker(waited_command, shell=shell)

                for line in worker.output().decode("utf-8", errors="ignore").splitlines():
                    log.info(line)
                progress_dialog = ProgressDialog(worker, "Run as administrator", "Executing command...", "Cancel", busy=True, parent=parent)
                progress_dialog.show()
                if not progress_dialog.exec_():
                    return False
        return True
Example #23
0
    def getIOUImage(parent):
        """

        :param parent: parent widget

        :return: path to the IOU image or None
        """

        destination_directory = os.path.join(
            MainWindow.instance().imagesDirPath(), "IOU")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(
            parent, "Select an IOU image", destination_directory,
            "All files (*)", "IOU image (*.bin *.image)")

        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "IOU image",
                                       "Cannot read {}".format(path))
            return

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtGui.QMessageBox.critical(
                parent, "IOU image",
                "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, little endian and have an ELF version of 1
        # normal IOS image are big endian!
        if elf_header_start != b'\x7fELF\x01\x01\x01':
            QtGui.QMessageBox.critical(
                parent, "IOU image", "Sorry, this is not a valid IOU image!")
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(
                parent, "IOU images directory",
                "Could not create the IOU images directory {}: {}".format(
                    destination_directory, e))
            return

        if os.path.normpath(os.path.dirname(path)) != destination_directory:
            # the IOU image is not in the default images directory
            reply = QtGui.QMessageBox.question(
                parent, "IOU image",
                "Would you like to copy {} to the default images directory".
                format(os.path.basename(path)), QtGui.QMessageBox.Yes,
                QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                destination_path = os.path.join(destination_directory,
                                                os.path.basename(path))
                thread = FileCopyThread(path, destination_path)
                progress_dialog = ProgressDialog(thread,
                                                 "Project",
                                                 "Copying {}".format(
                                                     os.path.basename(path)),
                                                 "Cancel",
                                                 busy=True,
                                                 parent=parent)
                thread.deleteLater()
                progress_dialog.show()
                progress_dialog.exec_()
                errors = progress_dialog.errors()
                if errors:
                    QtGui.QMessageBox.critical(parent, "IOS image",
                                               "{}".format("".join(errors)))
                else:
                    path = destination_path
                    mode = os.stat(path).st_mode
                    os.chmod(path, mode | stat.S_IXUSR)

        if not os.access(path, os.X_OK):
            QtGui.QMessageBox.warning(parent, "IOU image",
                                      "{} is not executable".format(path))

        return path
    def getIOSImage(parent):
        """

        :param parent: parent widget

        :return: path to the IOS image or None
        """

        destination_directory = os.path.join(
            MainWindow.instance().imagesDirPath(), "IOS")
        path, _ = QtGui.QFileDialog.getOpenFileNameAndFilter(
            parent, "Select an IOS image", destination_directory,
            "All files (*.*);;IOS image (*.bin *.image)",
            "IOS image (*.bin *.image)")
        if not path:
            return

        if not os.access(path, os.R_OK):
            QtGui.QMessageBox.critical(parent, "IOS image",
                                       "Cannot read {}".format(path))
            return

        if sys.platform.startswith('win'):
            # Dynamips (Cygwin acutally) doesn't like non ascii paths on Windows
            try:
                path.encode('ascii')
            except UnicodeEncodeError:
                QtGui.QMessageBox.warning(
                    parent, "IOS image",
                    "The IOS image filename should contains only ascii (English) characters."
                )

        try:
            with open(path, "rb") as f:
                # read the first 7 bytes of the file.
                elf_header_start = f.read(7)
        except OSError as e:
            QtGui.QMessageBox.critical(
                parent, "IOS image",
                "Cannot read ELF magic number: {}".format(e))
            return

        # file must start with the ELF magic number, be 32-bit, big endian and have an ELF version of 1
        if elf_header_start != b'\x7fELF\x01\x02\x01':
            QtGui.QMessageBox.critical(
                parent, "IOS image", "Sorry, this is not a valid IOS image!")
            return

        try:
            os.makedirs(destination_directory)
        except FileExistsError:
            pass
        except OSError as e:
            QtGui.QMessageBox.critical(
                parent, "IOS images directory",
                "Could not create the IOS images directory {}: {}".format(
                    destination_directory, e))
            return

        if isIOSCompressed(path):
            reply = QtGui.QMessageBox.question(
                parent, "IOS image",
                "Would you like to decompress this IOS image?",
                QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                decompressed_image_path = os.path.join(
                    destination_directory,
                    os.path.basename(os.path.splitext(path)[0] + ".image"))
                thread = DecompressIOSThread(path, decompressed_image_path)
                progress_dialog = ProgressDialog(
                    thread,
                    "IOS image",
                    "Decompressing IOS image {}...".format(
                        os.path.basename(path)),
                    "Cancel",
                    busy=True,
                    parent=parent)
                progress_dialog.show()
                if progress_dialog.exec_() is not False:
                    path = decompressed_image_path
                thread.wait()

        if os.path.normpath(os.path.dirname(path)) != destination_directory:
            # the IOS image is not in the default images directory
            reply = QtGui.QMessageBox.question(
                parent, "IOS image",
                "Would you like to copy {} to the default images directory".
                format(os.path.basename(path)), QtGui.QMessageBox.Yes,
                QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                destination_path = os.path.join(destination_directory,
                                                os.path.basename(path))
                thread = FileCopyThread(path, destination_path)
                progress_dialog = ProgressDialog(thread,
                                                 "IOS image",
                                                 "Copying {}".format(
                                                     os.path.basename(path)),
                                                 "Cancel",
                                                 busy=True,
                                                 parent=parent)
                thread.deleteLater()
                progress_dialog.show()
                progress_dialog.exec_()
                errors = progress_dialog.errors()
                if errors:
                    QtGui.QMessageBox.critical(parent, "IOS image",
                                               "{}".format("".join(errors)))
                else:
                    path = destination_path

        return path