Example #1
0
    def _stop_service(self):
        try:
            remove_file(self._port_file)
        except Exception as e:
            logger.warning("Removing port file exception: %s", e)

        platform = get_platform()
        logger.debug("Stopping service process. Platform: %s", platform)
        result = 0
        try:
            while True:
                if self._service_process is None or platform == 'Windows':
                    kill_all_services()
                    logger.debug("All services killed")
                    result = 1
                else:
                    self._service_process.terminate()
                    if self._service_process.wait(timeout=10) in (0, -15):
                        result = 1
                if result != 0:
                    break
                else:
                    logger.debug("Service killing: result == 0!")
                    self._service_process = None
                time.sleep(0.5)
        except OSError as e:
            if e.errno == errno.ESRCH:
                pass
            else:
                logger.warning("Stopping service exception: %s", e)
        except Exception as e:
            logger.warning("Stopping service exception: %s", e)
        logger.debug("Stopping service returned %s", result)
        self._close_stderr_log()
Example #2
0
def get_user_agent():
    """
    Returns platform-specific user agent string (to be used for statistics
    reporting

    @return User agent info [str]
    """

    params = []
    # Add program name and version
    params.append(('Pvtbox', __version__))

    os_name = get_platform()
    os_version = get_os_version()
    if not os_version:
        os_version = 'unknown'

    # Add OS name and version
    params.append((os_name, os_version))

    if os_name == 'Linux':
        # Add linux distribution name and version
        params.append(get_linux_distro_name_version())
        # Add desktop enviroment info (if any)
        de_info = os.getenv('DESKTOP_SESSION')
        if de_info:
            params.append(('DE', de_info))

    # Add node type and machine info
    params.append(('desktop', platform.machine()))

    ua = ' '.join(map(lambda p: '/'.join(p), params))
    logger.debug("Node's UA is '%s'", ua)

    return ua
Example #3
0
def qt_reveal_file_in_file_manager(path):
    if not exists(path) and exists(path + FILE_LINK_SUFFIX):
        path += FILE_LINK_SUFFIX
    try:
        while not exists(path):
            path = dirname(path)
    except Exception:
        return

    system = get_platform()
    if system == 'Darwin':
        args = [
            "-e", 'tell application "Finder"', "-e", "activate", "-e",
            'select POSIX file "{}"'.format(path), "-e", "end tell", "-e",
            "return"
        ]
        process = QProcess()
        if not process.execute("/usr/bin/osascript", args):
            return

    elif system == 'Windows':
        args = [QDir.toNativeSeparators(path)]
        if not isdir(path):
            args.insert(0, "/select,")
        process = QProcess()
        if process.startDetached("explorer", args):
            return

    qt_open_path(path if isdir(path) else dirname(path))
    def _login(self, login, password, user_hash):
        data = {
            'node_devicetype': 'desktop',
            'node_ostype': get_platform(),
            'node_osname': self._os_name,
            'node_name': get_device_name(),
            'user_email': login,
            'user_password': password,
            'user_hash': user_hash,
            'is_server': self._is_server,
        }

        # Signalize login attempt started (for statistics)
        if self._tracker:
            self._tracker.session_login_start()

        logged_in = False
        _res = self.create_request(action='login', data=data)
        if _res is None:
            if self._tracker:
                self._tracker.session_login_failed("response is None")
            return logged_in, _res
        if 'user_hash' not in _res:
            if self._tracker:
                self._tracker.session_login_failed("missing user_hash")
            logger.error("Server not returned user_hash")
            return logged_in, _res
        # Registered successfully
        if "success" in _res['result']:
            logged_in = True
            self.cfg.set_settings({'user_hash': _res['user_hash']})
            logger.info("Logged in successfully")

        return logged_in, _res
Example #5
0
 def onOpen(self):
     logger.debug("Incoming WebSocket connection opened")
     clients = getattr(self.factory, 'client_connections', set())
     first_client = not clients and get_platform() == 'Windows'
     clients.add(self)
     self.factory.client_connections = clients
     self.factory.loop.call_soon_threadsafe(
        self._on_connected, first_client)
Example #6
0
    def install_update(self):
        if not self._update_ready or self._status == UPDATER_STATUS_INSTALLING:
            return False
        self._status = UPDATER_STATUS_INSTALLING
        self.emit_status()
        logger.info('Installing update')
        try:
            assert self._update_file_path and isfile(self._update_file_path)
            logger.debug("self._update_file_path %s", self._update_file_path)
            path, name = split(self._update_file_path)
            old_cwd = os.getcwd()
            os.chdir(path)
            system = get_platform()
            if system == 'Windows':
                from common.config import load_config

                config = load_config()
                root = config.sync_directory
                log_basename = time.strftime('%Y%m%d_%H%M%S.log')
                log_filename = get_bases_filename(root, log_basename)
                if not self._is_ascii(log_filename):
                    log_filename = log_basename
                args = [name, '/verysilent', '/Log={}'.format(log_filename)]
                if is_portable():
                    args.append('/PATH={}'.format(get_application_path()))
                subprocess.Popen(
                    args,
                    creationflags=0x00000200  # CREATE_NEW_PROCESS_GROUP
                    | 0x00000008,  # DETACHED_PROCESS
                    close_fds=True)
            elif system == 'Darwin':
                bundle_path = normpath(
                    join(get_application_path(), '..', '..', '..', '..'))
                logger.debug("bundle_path: %s", bundle_path)
                subprocess.call(
                    ['ditto', '-xk', self._update_file_path, bundle_path])
                subprocess.call(
                    ['xattr', '-d', '-r', 'com.apple.quarantine', bundle_path])
                logger.debug("Update completed, restart")
                remove_file(get_cfg_filename('lock'))
                if is_portable():
                    launcher_path = normpath(
                        join(bundle_path, "..", "Pvtbox-Mac.command"))
                else:
                    launcher_path = bundle_path
                subprocess.call(['open', launcher_path])
            os.chdir(old_cwd)
            Application.exit()
        except Exception as e:
            logger.warning("Can't install update. Reason: %s", e)
            self._status = UPDATER_STATUS_INSTALL_ERROR
            self.emit_status()
            return False

        self._status = UPDATER_STATUS_INSTALLED
        self.emit_status()
        return True
Example #7
0
    def impl():
        # code below was added to resolve issue on Linux
        # 'kde-open5: /opt/pvtbox/libQt5Core.so.5:
        #  version `Qt_5.9.7_PRIVATE_API' not found
        #  (required by /usr/lib64/libQt5Xml.so.5)'
        if get_platform() == "Linux" and \
                os.environ.get("XDG_CURRENT_DESKTOP", None) == "KDE":
            os.environ["XDG_CURRENT_DESKTOP"] = "X-Generic"

        QDesktopServices.openUrl(QUrl(uri))
Example #8
0
    def start(self):
        self._loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self._loop)
        self._factory = WebSocketServerFactory(
            "ws://127.0.0.1", loop=self._loop)
        self._factory.protocol = IPCWebSocketProtocol
        coro = self._factory.loop.create_server(self._factory, '127.0.0.1', 0)
        self._server = self._factory.loop.run_until_complete(coro)

        _, port = self._server.sockets[0].getsockname()
        self._factory.setSessionParameters(url="ws://127.0.0.1:{}".format(port))

        if get_platform() == 'Darwin':
            port_path = join(
                HOME_DIR,
                'Library',
                'Containers',
                'net.pvtbox.Pvtbox.PvtboxFinderSync',
                'Data',
                'pvtbox.port')
        else:
            port_path = join(
                get_cfg_dir(),
                'pvtbox.port')
        port_path = ensure_unicode(port_path)
        self._loop.call_soon_threadsafe(
            self._write_opened_port_to_accessible_file, port, port_path)

        if get_platform() == 'Darwin':
            port_path = join(
                HOME_DIR,
                'Library',
                'Containers',
                'net.pvtbox.Pvtbox.PvtboxShareExtension',
                'Data',
                'pvtbox.port')
            port_path = ensure_unicode(port_path)
            self._loop.call_soon_threadsafe(
                self._write_opened_port_to_accessible_file, port, port_path)

        self._factory.loop.run_forever()
Example #9
0
 def _get_version_file_uri(self):
     os = get_platform()
     if os == 'Windows':
         return '{}/{}/win/version'.format(
             self._updates_server_addr,
             self._update_branch,
         )
     elif os == 'Darwin':
         return '{}/{}/osx/version'.format(
             self._updates_server_addr,
             self._update_branch,
         )
     else:
         return ''
Example #10
0
    def request_to_user(
            self, dialog_id, text, buttons=("Yes", "No"), title="",
            close_button_index=-1, close_button_off=False, parent=None,
            on_clicked_cb=None,
            details=''):

        msg_box = QMessageBox(parent)
        # msg_box = QMessageBox()
        if not title:
            title = tr('Pvtbox')
        msg_box.setWindowTitle(title)
        msg_box.setText(str(text))

        pvtboxIcon = QIcon(':/images/icon.png')
        msg_box.setWindowIcon(pvtboxIcon)

        if details:
            msg_box.setDetailedText(details)

        if close_button_off:
            if get_platform() == 'Darwin':
                msg_box.setWindowFlags(Qt.Tool)
            else:
                msg_box.setWindowFlags(Qt.Dialog |
                                       Qt.CustomizeWindowHint |
                                       Qt.WindowTitleHint)
        msg_box.setAttribute(Qt.WA_MacFrameworkScaled)
        msg_box.setModal(True)

        buttons = list(buttons)
        for button in buttons:
            msg_box.addButton(button, QMessageBox.ActionRole)
        msg_box.show()
        msg_box.raise_()
        msg_box.exec_()
        try:
            button_index = buttons.index(msg_box.clickedButton().text())
        except (ValueError, AttributeError):
            button_index = -1
           # message box was closed with close button
            if len(buttons) == 1 and close_button_index == -1:
                # if only one button then call callback
                close_button_index = 0

            if len(buttons) > close_button_index >= 0:
                button_index = close_button_index

        if button_index >= 0 and callable(on_clicked_cb):
            on_clicked_cb(dialog_id, button_index)
Example #11
0
def qt_open_path(path):
    system = get_platform()
    if system == 'Windows':
        from common.file_path import FilePath
        path = FilePath(path).shortpath

    # code below was added to resolve issue on Linux
    # 'kde-open5: /opt/pvtbox/libQt5Core.so.5:
    #  version `Qt_5.9.7_PRIVATE_API' not found
    #  (required by /usr/lib64/libQt5Xml.so.5)'
    if system == "Linux" and \
            os.environ.get("XDG_CURRENT_DESKTOP", None) == "KDE":
        os.environ["XDG_CURRENT_DESKTOP"] = "X-Generic"

    QDesktopServices.openUrl(QUrl.fromLocalFile(path))
    def __init__(self, sync, cfg):
        self._sync = sync
        self._cfg = cfg
        self._status = "syncing"
        self._sync_resuming = True
        self._files_in_indexing = set()
        self._files_in_downloading = dict()
        self._files_ignored = set()
        self._files_disk_error = set()
        self._subscriptions = dict()
        self._not_synced_paths = set()
        self._pc = PathConverter(self._cfg.sync_directory)
        QObject.__init__(self)

        self._check_not_synced.connect(
            self._on_check_not_synced, Qt.QueuedConnection)
        if get_platform() in ("Windows", "Linux"):
            self._path_removed.connect(
                self._on_path_removed, Qt.QueuedConnection)
Example #13
0
    def __init__(self, disk_usage, node_status, node_substatus):
        """
        Constructor
        """

        super(TableModel, self).__init__()
        self._data = []
        self._node_id_vs_row_number = {}
        self._icons = {}

        # Initialize icons
        for icon_id, icon_path in list(self._icon_paths.items()):
            if not icon_path:
                continue
            self._icons[icon_id] = QIcon(icon_path)

        # set font for arrow symbols
        font_id = QFontDatabase.addApplicationFont(":/fonts/symbol-signs.otf")
        font_family = QFontDatabase.applicationFontFamilies(font_id)[0]
        self._arrow_font = QFont(font_family, QFont().pointSize()+5)

        # Add the node itself
        node_ostype = get_platform()
        node_osname, is_server = get_os_name_and_is_server()
        # show "Downloading share" instead of "Syncing" if share is downlosded
        status = 30 if node_status == 3 and node_substatus == SUBSTATUS_SHARE \
            else node_status

        self_info = {
            'id': 'itself',
            'node_ostype': node_ostype,
            'node_osname': node_osname,
            'node_devicetype': 'desktop',
            'node_name': get_device_name(),
            'is_online': node_status not in self.OFFLINE_STATUSES,
            'is_itself': True,
            'disk_usage': disk_usage,
            'download_speed': 0.,
            'node_status': status,
            'upload_speed': 0.,
        }
        QTimer.singleShot(10, lambda: self._add_row(self_info))
Example #14
0
 def _get_update_file_uri(self):
     os = get_platform()
     if os == 'Windows':
         machine = 'x64' if is_os_64bit() else 'x86'
         return '{}/{}/win/PvtboxSetup-offline_{}.exe'.format(
             self._updates_server_addr,
             self._update_branch,
             machine,
         )
     elif os == 'Darwin':
         if is_portable():
             return '{}/{}/osx/Pvtbox-portable.app.zip'.format(
                 self._updates_server_addr,
                 self._update_branch,
             )
         else:
             return '{}/{}/osx/Pvtbox.app.zip'.format(
                 self._updates_server_addr,
                 self._update_branch,
             )
     else:
         return ''
Example #15
0
    def _signup(self, fullname, email, password):
        if self._tracker:
            self._tracker.session_signup_start()

        data = {
            'node_devicetype': 'desktop',
            'node_ostype': get_platform(),
            'node_osname': self._os_name,
            'node_name': get_device_name(),
            'fullname': fullname,
            'user_email': email,
            'user_password': password,
        }
        signed = False

        _res = self.create_request(action='signup', data=data)

        if _res and "success" in _res['result'] and 'user_hash' in _res:
            self.cfg.set_settings({'user_hash': _res['user_hash']})
            signed = True
            logger.info("Registered successfully")

        return signed, _res
Example #16
0
 def _clean_old_updates(self):
     logger.debug("Cleaning old updates...")
     os = get_platform()
     if os == 'Windows':
         suffix = '.exe'
     elif os == 'Darwin':
         suffix = '.zip'
     else:
         suffix = ''
     prefix = 'Pvtbox_'
     update_file = NamedTemporaryFile(prefix=prefix,
                                      suffix=suffix,
                                      delete=False)
     prefix_len = update_file.name.rfind(prefix) + len(prefix)
     update_file_template = "{}*{}".format(update_file.name[:prefix_len],
                                           suffix)
     update_file.file.close()
     old_updates = glob.glob(update_file_template)
     try:
         list(map(remove_file, old_updates))
         self._old_updates_cleaned = True
     except Exception as e:
         logger.warning("Can't clean old updates. Reason %s", e)
Example #17
0
    def _start_service(self):
        if not self._starting_service:
            self._starting_service = True
            self._stop_service()
            logger.debug("Starting service...")
            options = dict(shell=True) \
                if is_launched_from_code() else dict(shell=False)
            platform = get_platform()
            if platform == 'Darwin':
                options['close_fds'] = True

            from_code = is_launched_from_code()
            if not from_code:
                self._args = map(lambda a: a.strip('"'), self._args)
            args = get_service_start_command() + \
                   list(map(lambda a: ensure_unicode(a),
                            self._args))
            cmd = ' '.join(args) if from_code else \
                list(args)
            if "--logging-disabled" not in self._args:
                self._reopen_stderr_log()
            else:
                self._stderr_log = None

            logger.debug("Service start command: %s", cmd)
            self._service_process = subprocess.Popen(
                cmd, stderr=self._stderr_log, **options)
            if not self._start_only:
                self._loop.call_later(
                    self.start_service_timeout, self._drop_starting_service)
            if self._starting_service_signal:
                self._starting_service_signal.emit()

        if not self._start_only:
            self._loop.call_later(
                self.connect_to_service_interval, self._connect_to_service)
Example #18
0
        type=str,
    )
    parser.add_argument(
        '--logging-disabled',
        type=str,
    )

    # Parse command line args and return as dict
    args = vars(parser.parse_args(argv))

    return args


if __name__ == "__main__":
    # Get process ID
    if get_platform() == "Windows":
        pid = os.getpid()
    else:
        if getattr(sys, "frozen", False):
            pid = os.getppid()
        else:
            pid = os.getpid()
    #fh.set_process_id(pid)

    # for multiprocessing under build pyinstaller
    multiprocessing.freeze_support()

    args = sys.argv[1:]
    # Parse command line arguments
    args = parseArgs(args)
Example #19
0
def close():
    if get_platform() == 'Darwin' and params.ipc_ws_server:
        params.ipc_ws_server.close()
    close_ipc()
Example #20
0
    def _download_update_job(self, req):
        if self._stopped:
            return

        logger.debug("Update download")
        os = get_platform()
        if os == 'Windows':
            suffix = '.exe'
        elif os == 'Darwin':
            suffix = '.zip'
        else:
            suffix = ''
        update_file = NamedTemporaryFile(prefix='Pvtbox_',
                                         suffix=suffix,
                                         delete=False)

        size = \
            int(float(req.headers.get('content-length', 0)) / 1024 / 1024) + 1
        downloaded = 0
        checksum = hashlib.md5()
        self.downloading_update.emit(downloaded, size)
        logger.debug("Downloading update, %s of %s", downloaded, size)
        try:
            for chunk in req.iter_content(chunk_size=1024 * 1024):
                if self._stopped:
                    break

                if chunk:  # filter out keep-alive new chunks
                    update_file.write(chunk)
                    checksum.update(chunk)
                    downloaded += 1
                    if not self._stopped:
                        self.downloading_update.emit(downloaded, size)
                        logger.debug("Downloading update, %s of %s",
                                     downloaded, size)

        except Exception as e:
            logger.error("Error downloading update %s", e)
            self._status = UPDATER_STATUS_DOWNLOAD_ERROR
            if not self._stopped:
                self.emit_status()
        finally:
            update_file.close()
            if self._stopped:
                return

            success = checksum.hexdigest() == self._md5
            if success:
                logger.debug("Update downloaded successfully, hashsum matches")
                self._update_file_path = update_file.name
                self._status = UPDATER_STATUS_READY
            else:
                logger.warning(
                    "Update download failed: hashsum mismatch, expected: %s, actual: %s",
                    checksum.hexdigest(), self._md5)
                self._status = UPDATER_STATUS_DOWNLOAD_ERROR
                remove_file(update_file.name)
            self.emit_status()
            self._downloading_update = False
            self._update_ready = success
            self.update_ready.emit(success)