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()
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
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
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)
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
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))
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()
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 ''
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)
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)
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))
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 ''
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
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)
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)
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)
def close(): if get_platform() == 'Darwin' and params.ipc_ws_server: params.ipc_ws_server.close() close_ipc()
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)