def _on_part(self, data): msg.log('%s left the workspace' % data['username']) user_id = str(data['user_id']) try: del self.workspace_info['users'][user_id] except Exception: print('Unable to delete user %s from user list' % (data))
def floobits_check_credentials(): msg.debug('Print checking credentials.') if not (G.USERNAME and G.SECRET): if not utils.has_browser(): msg.log('You need a Floobits account to use the Floobits plugin. Go to https://floobits.com to sign up.') return floobits_setup_credentials()
def _on_part(self, data): msg.log(data['username'], ' left the workspace') user_id = str(data['user_id']) try: del self.workspace_info['users'][user_id] except Exception: msg.error('Unable to delete user %s from user list' % (data))
def connect(self, conn=None): utils.cancel_timeout(self._reconnect_timeout) self._reconnect_timeout = None self.cleanup() host = self._host port = self._port self._empty_selects = 0 # TODO: Horrible code here if self.proxy: if G.OUTBOUND_FILTERING: port = self.start_proxy(G.OUTBOUND_FILTER_PROXY_HOST, G.OUTBOUND_FILTER_PROXY_PORT) else: port = self.start_proxy(self.host, self.port) elif G.OUTBOUND_FILTERING: host = G.OUTBOUND_FILTER_PROXY_HOST port = G.OUTBOUND_FILTER_PROXY_PORT self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.setblocking(False) if self._secure: with open(self._cert_path, 'wb') as cert_fd: cert_fd.write(cert.CA_CERT.encode('utf-8')) conn_msg = 'Connecting to %s:%s' % (self.host, self.port) if self.port != self._port or self.host != self._host: conn_msg += ' (proxying through %s:%s)' % (self._host, self._port) if host != self._host: conn_msg += ' (proxying through %s:%s)' % (host, port) msg.log(conn_msg) editor.status_message(conn_msg) self._connect(host, port)
def floobits_part_workspace(self): if not G.AGENT: return msg.warn( 'Unable to leave workspace: You are not joined to a workspace.' ) floobits_stop_everything() msg.log('You left the workspace.')
def stop(self): self._retries = -1 utils.cancel_timeout(self._reconnect_timeout) self._reconnect_timeout = None self.cleanup() self.emit('stop') msg.log('Disconnected.')
def run(self, paths, current_file=False): if not self.is_enabled(): return if paths is None and current_file: active_view = self.window.active_view() if active_view is None: msg.log( 'RemoveFromWorkspace: No active view found. Perhaps active tab is an image?' ) return paths = [active_view.file_name()] if not hasattr(sublime, 'yes_no_cancel_dialog'): unlink = bool( sublime.ok_cancel_dialog( 'Delete? Select cancel to remove from the workspace without deleting.', 'Delete')) else: ret = sublime.yes_no_cancel_dialog( "What should I do with\n%s" % "\n".join(paths[:5]), "Delete!", "Just Remove from Workspace.") if ret == 0: return unlink = ret == 1 for path in paths: G.AGENT.delete_buf(path, unlink)
def run(self, paths, current_file=False): if not self.is_enabled(): return if paths is None and current_file: active_view = self.window.active_view() if active_view is None: msg.log( 'AddToWorkspace: No active view found. Perhaps active tab is an image?' ) return paths = [active_view.file_name()] notshared = [] for path in paths: if utils.is_shared(path): G.AGENT.upload(path) else: notshared.append(path) if notshared: limit = 5 sublime.error_message( "The following paths are not a child of\n\n%s\n\nand will not be shared for security reasons:\n\n%s%s." % (G.PROJECT_PATH, ",\n".join(notshared[:limit]), len(notshared) > limit and ",\n..." or ""))
def _uploader(self, paths_iter, cb, total_bytes, bytes_uploaded=0.0): reactor.tick() if len(self.proto) > 0: return utils.set_timeout(self._uploader, 10, paths_iter, cb, total_bytes, bytes_uploaded) bar_len = 20 try: p = next(paths_iter) size = self._upload(p) bytes_uploaded += size try: percent = (bytes_uploaded / total_bytes) except ZeroDivisionError: percent = 0.5 bar = ' |' + ('|' * int(bar_len * percent)) + (' ' * int( (1 - percent) * bar_len)) + '|' editor.status_message('Uploading... %2.2f%% %s' % (percent * 100, bar)) except StopIteration: editor.status_message('Uploading... 100% ' + ('|' * bar_len) + '| complete') msg.log('All done uploading') return cb and cb() return utils.set_timeout(self._uploader, 50, paths_iter, cb, total_bytes, bytes_uploaded)
def floobits_check_credentials(): msg.debug('Print checking credentials.') if utils.can_auth(): return if not utils.has_browser(): msg.log('You need a Floobits account to use the Floobits plugin. Go to https://floobits.com to sign up.') return yield VUI.create_or_link_account, None, G.DEFAULT_HOST, False
def floobits_toggle_highlights(): G.SHOW_HIGHLIGHTS = not G.SHOW_HIGHLIGHTS if G.SHOW_HIGHLIGHTS: floobits_buf_enter() msg.log('Highlights enabled') return floobits_clear() msg.log('Highlights disabled')
def stop(self): for _conn in self._protos: _conn.stop() self._protos = [] self._handlers = [] msg.log('Reactor shut down.') editor.status_message('Disconnected.')
def create_workspace(self, context, host, owner, name, api_args, dir_to_share): prompt = 'Workspace name: ' api_args['name'] = name api_args['owner'] = owner while True: new_name = yield self.user_charfield, context, prompt, name name = new_name or name try: api_args['name'] = name r = api.create_workspace(host, api_args) except Exception as e: msg.error('Unable to create workspace ', str_e(e)) editor.error_message('Unable to create workspace: %s' % str_e(e)) return if r.code < 400: workspace_url = 'https://%s/%s/%s' % (host, owner, name) msg.log('Created workspace ', workspace_url) self.remote_connect(context, host, owner, name, dir_to_share, utils.JOIN_ACTION.UPLOAD) return msg.error('Unable to create workspace: ', r.body) if r.code not in (400, 402, 409): try: r.body = r.body['detail'] except Exception: pass editor.error_message('Unable to create workspace: %s' % r.body) return if r.code == 402: try: r.body = r.body['detail'] except Exception: pass yes = yield self.user_y_or_n, context, '%s Open billing settings?' % r.body, "Yes" if yes: webbrowser.open('https://%s/%s/settings#billing' % (host, owner)) return if r.code == 400: # TODO: strip leading dots/dashes/etc name = re.sub('[^A-Za-z0-9_\-\.]', '_', name) prompt = 'Workspace names may only contain [A-Za-z0-9_\-\.]. Choose another name: ' continue yes = yield self.user_y_or_n, context, 'Workspace %s/%s already exists. Overwrite?' % (owner, name), 'Yes' if yes: # TODO: this doesn't set permissions on the workspace correctly self.remote_connect(context, host, owner, name, dir_to_share, utils.JOIN_ACTION.PROMPT) return prompt = 'Workspace %s/%s already exists. Choose new name: ' % (owner, name)
def _on_delete_buf(self, data): path = utils.get_full_path(data['path']) try: utils.rm(path) except Exception: pass user_id = data.get('user_id') username = self.get_username_by_id(user_id) msg.log('%s deleted %s' % (username, path))
def start_proxy(self): if G.PROXY_PORT: self._port = int(G.PROXY_PORT) msg.log("SSL proxy in debug mode: Port is set to %s", self._port) return args = ("python", "-m", "floo.proxy", self.host, str(self.port), str(int(self.secure))) self._proc = proxy.ProxyProtocol() self._port = self._proc.connect(args)
def start_proxy(self): if G.PROXY_PORT: self._port = int(G.PROXY_PORT) msg.log('SSL proxy in debug mode: Port is set to %s' % self._port) return args = ('python', '-m', 'floo.proxy', '--host=%s' % self.host, '--port=%s' % str(self.port), '--ssl=%s' % str(bool(self.secure))) self._proc = proxy.ProxyProtocol() self._port = self._proc.connect(args)
def floobits_check_credentials(): msg.debug('Print checking credentials.') if not (G.USERNAME and G.SECRET): if not utils.has_browser(): msg.log( 'You need a Floobits account to use the Floobits plugin. Go to https://floobits.com to sign up.' ) return floobits_setup_credentials()
def on_done(owner): msg.log('Colab dir: %s, Username: %s, Workspace: %s/%s' % (G.COLAB_DIR, username, owner[0], workspace_name)) self.window.run_command('floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'upload': file_to_share or dir_to_share, 'api_args': self.api_args, 'owner': owner[0], 'host': host, })
def on_input(self, workspace_name, dir_to_share=None): if dir_to_share: self.dir_to_share = dir_to_share if workspace_name == '': return self.run(dir_to_share=self.dir_to_share) try: self.api_args['name'] = workspace_name self.api_args['owner'] = self.owner msg.debug(str(self.api_args)) r = api.create_workspace(self.host, self.api_args) except Exception as e: msg.error('Unable to create workspace: %s' % str_e(e)) return sublime.error_message('Unable to create workspace: %s' % str_e(e)) workspace_url = 'https://%s/%s/%s' % (self.host, self.owner, workspace_name) msg.log('Created workspace %s' % workspace_url) if r.code < 400: utils.add_workspace_to_persistent_json(self.owner, workspace_name, workspace_url, self.dir_to_share) return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'upload': dir_to_share }) msg.error('Unable to create workspace: %s' % r.body) if r.code not in [400, 402, 409]: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('Unable to create workspace: %s' % r.body) kwargs = { 'dir_to_share': self.dir_to_share, 'workspace_name': workspace_name, 'api_args': self.api_args, 'owner': self.owner, 'upload': self.upload, 'host': self.host, } if r.code == 400: kwargs['workspace_name'] = re.sub('[^A-Za-z0-9_\-\.]', '-', workspace_name) kwargs['prompt'] = 'Invalid name. Workspace names must match the regex [A-Za-z0-9_\-\.]. Choose another name:' elif r.code == 402: try: r.body = r.body['detail'] except Exception: pass if sublime.ok_cancel_dialog('%s' % r.body, 'Open billing settings'): webbrowser.open('https://%s/%s/settings#billing' % (self.host, self.owner)) return else: kwargs['prompt'] = 'Workspace %s/%s already exists. Choose another name:' % (self.owner, workspace_name) return self.window.run_command('floobits_create_workspace', kwargs)
def floobits_info(self): kwargs = { 'cs': bool(int(vim.eval('has("clientserver")'))), 'mode': (using_feedkeys and 'feedkeys') or 'client-server', 'servername': vim.eval('v:servername'), 'ticker_errors': ticker_errors, 'updatetime': vim.eval('&l:updatetime'), 'version': G.__PLUGIN_VERSION__, } msg.log(FLOOBITS_INFO.format(**kwargs))
def reconnect(self): if self._reconnect_timeout: return self.cleanup() self._reconnect_delay = min(10000, int(1.5 * self._reconnect_delay)) if self._retries > 0: msg.log('Floobits: Reconnecting in %sms' % self._reconnect_delay) self._reconnect_timeout = utils.set_timeout(self.connect, self._reconnect_delay) elif self._retries == 0: editor.error_message('Floobits Error! Too many reconnect failures. Giving up.') self._retries -= 1
def stop_handler(self, handler): try: handler.proto.stop() except Exception as e: msg.warn('Error stopping connection: %s' % str_e(e)) self._handlers.remove(handler) self._protos.remove(handler.proto) if hasattr(handler, 'listener_factory'): return handler.listener_factory.stop() if not self._handlers and not self._protos: msg.log('All handlers stopped. Stopping reactor.') self.stop()
def floobits_complete_signup(): msg.debug('Completing signup.') if not utils.has_browser(): msg.log('You need a modern browser to complete the sign up. Go to https://floobits.com to sign up.') return floorc = utils.load_floorc() username = floorc.get('USERNAME') secret = floorc.get('SECRET') msg.debug('Completing sign up with %s %s' % (username, secret)) if not (username and secret): return msg.error('You don\'t seem to have a Floobits account of any sort.') webbrowser.open('https://%s/%s/pinocchio/%s' % (G.DEFAULT_HOST, username, secret))
def on_done(owner): msg.log('Colab dir: %s, Username: %s, Workspace: %s/%s' % (G.COLAB_DIR, username, owner[0], workspace_name)) self.window.run_command( 'floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'upload': file_to_share or dir_to_share, 'api_args': self.api_args, 'owner': owner[0], 'host': host, })
def stop_handler(self, handler): try: handler.proto.stop() except Exception as e: msg.warn('Error stopping connection: %s' % str(e)) self._handlers.remove(handler) self._protos.remove(handler.proto) if hasattr(handler, 'listener_factory'): return handler.listener_factory.stop() if not self._handlers and not self._protos: msg.log('All handlers stopped. Stopping reactor.') self.stop()
def on_input(self, workspace_name, dir_to_share=None): if dir_to_share: self.dir_to_share = dir_to_share if workspace_name == '': return self.run(dir_to_share=self.dir_to_share) try: self.api_args['name'] = workspace_name self.api_args['owner'] = self.owner msg.debug(str(self.api_args)) r = api.create_workspace(self.api_args) except Exception as e: msg.error('Unable to create workspace: %s' % unicode(e)) return sublime.error_message('Unable to create workspace: %s' % unicode(e)) workspace_url = 'https://%s/%s/%s/' % (G.DEFAULT_HOST, self.owner, workspace_name) msg.log('Created workspace %s' % workspace_url) if r.code < 400: utils.add_workspace_to_persistent_json(self.owner, workspace_name, workspace_url, self.dir_to_share) return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'agent_conn_kwargs': { 'get_bufs': False } }) msg.error('Unable to create workspace: %s' % r.body) if r.code not in [400, 402, 409]: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('Unable to create workspace: %s' % r.body) kwargs = { 'dir_to_share': self.dir_to_share, 'workspace_name': workspace_name, 'api_args': self.api_args, 'owner': self.owner, } if r.code == 400: kwargs['workspace_name'] = re.sub('[^A-Za-z0-9_\-\.]', '-', workspace_name) kwargs['prompt'] = 'Invalid name. Workspace names must match the regex [A-Za-z0-9_\-\.]. Choose another name:' elif r.code == 402: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('%s' % r.body) else: kwargs['prompt'] = 'Workspace %s/%s already exists. Choose another name:' % (self.owner, workspace_name) return self.window.run_command('floobits_create_workspace', kwargs)
def _on_saved(self, data): buf_id = data['id'] buf = self.bufs.get(buf_id) if not buf: return if G.MIRRORED_SAVES: view = self.get_view(data['id']) if view: self.save_view(view) elif 'buf' in buf: utils.save_buf(buf) username = self.get_username_by_id(data['user_id']) msg.log('%s saved buffer %s' % (username, buf['path']))
def create_workspace(self, context, host, owner, name, api_args, dir_to_share): prompt = "Workspace name: " api_args["name"] = name api_args["owner"] = owner while True: new_name = yield self.user_charfield, context, prompt, name name = new_name or name try: api_args["name"] = name r = api.create_workspace(host, api_args) except Exception as e: msg.error("Unable to create workspace ", str_e(e)) editor.error_message("Unable to create workspace: %s" % str_e(e)) return if r.code < 400: workspace_url = "https://%s/%s/%s" % (host, owner, name) msg.log("Created workspace ", workspace_url) self.remote_connect(context, host, owner, name, dir_to_share, utils.JOIN_ACTION.UPLOAD) return msg.error("Unable to create workspace: ", r.body) if r.code not in (400, 402, 409): try: r.body = r.body["detail"] except Exception: pass editor.error_message("Unable to create workspace: %s" % r.body) return if r.code == 402: try: r.body = r.body["detail"] except Exception: pass yes = yield self.user_y_or_n, context, "%s Open billing settings?" % r.body, "Yes" if yes: webbrowser.open("https://%s/%s/settings#billing" % (host, owner)) return if r.code == 400: # TODO: strip leading dots/dashes/etc name = re.sub("[^A-Za-z0-9_\-\.]", "_", name) prompt = "Workspace names may only contain [A-Za-z0-9_\-\.]. Choose another name: " continue prompt = "Workspace %s/%s already exists. Choose another name: " % (owner, name)
def connect(self, args): self._proc = proc = subprocess.Popen(args, cwd=G.PLUGIN_PATH, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) line = proc.stdout.readline().decode('utf-8') self.fd = proc.stdout.fileno() fl = fcntl.fcntl(self.fd, fcntl.F_GETFL) fcntl.fcntl(self.fd, fcntl.F_SETFL, fl | os.O_NONBLOCK | os.O_ASYNC) msg.log("Read line from Floobits SSL proxy: %s" % line) match = re.search('Now listening on <(\d+)>', line) if not match: raise Exception("Couldn't find port in line from proxy: %s" % line) self._port = int(match.group(1)) self.reactor._protos.append(self) return self._port
def reconnect(self): if self._reconnect_timeout: return self.cleanup() self._reconnect_delay = min(10000, int(1.5 * self._reconnect_delay)) if self._retries > 0: msg.log('Floobits: Reconnecting in %sms' % self._reconnect_delay) self._reconnect_timeout = utils.set_timeout(self.connect, self._reconnect_delay) elif self._retries == 0: editor.error_message('Floobits Error! Too many reconnect failures. Giving up.') # Only use proxy.floobits.com if we're trying to connect to floobits.com G.OUTBOUND_FILTERING = self.host == 'floobits.com' and self._retries % 4 == 0 self._retries -= 1
def _on_saved(self, data): buf_id = data['id'] buf = self.bufs.get(buf_id) if not buf: return on_view_load = self.on_load.get(buf_id) if on_view_load: del on_view_load['patch'] view = self.get_view(data['id']) if view: self.save_view(view) elif 'buf' in buf: utils.save_buf(buf) username = self.get_username_by_id(data['user_id']) msg.log('%s saved buffer %s' % (username, buf['path']))
def floobits_complete_signup(): msg.debug('Completing signup.') if not utils.has_browser(): msg.log( 'You need a modern browser to complete the sign up. Go to https://floobits.com to sign up.' ) return floorc = utils.load_floorc() username = floorc.get('USERNAME') secret = floorc.get('SECRET') msg.debug('Completing sign up with %s %s' % (username, secret)) if not (username and secret): return msg.error( 'You don\'t seem to have a Floobits account of any sort.') webbrowser.open('https://%s/%s/pinocchio/%s' % (G.DEFAULT_HOST, username, secret))
def _on_perms(self, data): action = data['action'] user_id = str(data['user_id']) user = self.workspace_info['users'].get(user_id) if user is None: msg.log('No user for id ', user_id, '. Not handling perms event') return perms = set(user['perms']) if action == 'add': perms |= set(data['perms']) elif action == 'remove': perms -= set(data['perms']) else: return user['perms'] = list(perms) if user_id == self.workspace_info['user_id']: G.PERMS = perms
def _on_perms(self, data): action = data['action'] user_id = str(data['user_id']) user = self.workspace_info['users'].get(user_id) if user is None: msg.log('No user for id %s. Not handling perms event' % user_id) return perms = set(user['perms']) if action == 'add': perms |= set(data['perms']) elif action == 'remove': perms -= set(data['perms']) else: return user['perms'] = list(perms) if user_id == self.workspace_info['user_id']: G.PERMS = perms
def reconnect(self): if self._reconnect_timeout: return self.cleanup() self._reconnect_delay = min(10000, int(1.5 * self._reconnect_delay)) if self._retries > 0: msg.log('Floobits: Reconnecting in %sms' % self._reconnect_delay) self._reconnect_timeout = utils.set_timeout( self.connect, self._reconnect_delay) elif self._retries == 0: editor.error_message( 'Floobits Error! Too many reconnect failures. Giving up.') # Only use proxy.floobits.com if we're trying to connect to floobits.com G.OUTBOUND_FILTERING = self.host == 'floobits.com' and self._retries % 4 == 0 self._retries -= 1
def connect(self, args): msg.debug('Running proxy with args %s in %s' % (args, G.PLUGIN_PATH)) self._proc = proc = subprocess.Popen(args, cwd=G.PLUGIN_PATH, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) line = proc.stdout.readline().decode('utf-8') self.fd = proc.stdout.fileno() fl = fcntl.fcntl(self.fd, fcntl.F_GETFL) fcntl.fcntl(self.fd, fcntl.F_SETFL, fl | os.O_NONBLOCK | os.O_ASYNC) msg.log("Read line from Floobits SSL proxy: %s" % line) match = re.search('Now listening on <(\d+)>', line) if not match: raise Exception("Couldn't find port in line from proxy: %s" % line) self._port = int(match.group(1)) self.reactor._protos.append(self) return self._port
def _uploader(self, paths_iter, cb, total_bytes, bytes_uploaded=0.0): reactor.tick() if len(self.proto) > 0: return utils.set_timeout(self._uploader, 10, paths_iter, cb, total_bytes, bytes_uploaded) bar_len = 20 try: p = next(paths_iter) size = self._upload(p) bytes_uploaded += size try: percent = (bytes_uploaded / total_bytes) except ZeroDivisionError: percent = 0.5 bar = ' |' + ('|' * int(bar_len * percent)) + (' ' * int((1 - percent) * bar_len)) + '|' editor.status_message('Uploading... %2.2f%% %s' % (percent * 100, bar)) except StopIteration: editor.status_message('Uploading... 100% ' + ('|' * bar_len) + '| complete') msg.log('All done uploading') return cb and cb() return utils.set_timeout(self._uploader, 50, paths_iter, cb, total_bytes, bytes_uploaded)
def _on_delete_buf(self, data): buf_id = data['id'] try: buf = self.bufs.get(buf_id) if buf: del self.paths_to_ids[buf['path']] del self.bufs[buf_id] except KeyError: msg.debug('KeyError deleting buf id ', buf_id) # TODO: if data['unlink'] == True, add to ignore? action = 'removed' path = utils.get_full_path(data['path']) if data.get('unlink', False): action = 'deleted' try: utils.rm(path) except Exception as e: msg.debug('Error deleting ', path, ': ', str_e(e)) user_id = data.get('user_id') username = self.get_username_by_id(user_id) msg.log(username, ' ', action, ' ', path)
def run(self, paths, current_file=False): if not self.is_enabled(): return if paths is None and current_file: active_view = self.window.active_view() if active_view is None: msg.log('RemoveFromWorkspace: No active view found. Perhaps active tab is an image?') return paths = [active_view.file_name()] if not hasattr(sublime, 'yes_no_cancel_dialog'): unlink = bool(sublime.ok_cancel_dialog('Delete? Select cancel to remove from the workspace without deleting.', 'Delete')) else: ret = sublime.yes_no_cancel_dialog("What should I do with\n%s" % "\n".join(paths[:5]), "Delete!", "Just Remove from Workspace.") if ret == 0: return unlink = ret == 1 for path in paths: G.AGENT.delete_buf(path, unlink)
def connect(self, conn=None): utils.cancel_timeout(self._reconnect_timeout) self._reconnect_timeout = None self.cleanup() self._empty_selects = 0 if self.proxy: self.start_proxy() self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.setblocking(False) if self._secure: with open(self._cert_path, 'wb') as cert_fd: cert_fd.write(cert.CA_CERT.encode('utf-8')) conn_msg = 'Connecting to %s:%s' % (self.host, self.port) if self.port != self._port or self.host != self._host: conn_msg += ' (proxying through %s:%s)' % (self._host, self._port) msg.log(conn_msg) editor.status_message(conn_msg) self._connect()
def connect(self, conn=None): utils.cancel_timeout(self._reconnect_timeout) self._reconnect_timeout = None self.cleanup() self._empty_selects = 0 self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.setblocking(False) if self.secure: if ssl: with open(self._cert_path, 'wb') as cert_fd: cert_fd.write(cert.CA_CERT.encode('utf-8')) else: msg.log('No SSL module found. Connection will not be encrypted.') self.secure = False if self.port == G.DEFAULT_PORT: self.port = 3148 # plaintext port conn_msg = 'Connecting to %s:%s' % (self.host, self.port) msg.log(conn_msg) editor.status_message(conn_msg) self._connect()
def run(self, paths, current_file=False): if not self.is_enabled(): return if paths is None and current_file: active_view = self.window.active_view() if active_view is None: msg.log('AddToWorkspace: No active view found. Perhaps active tab is an image?') return paths = [active_view.file_name()] notshared = [] for path in paths: if utils.is_shared(path): G.AGENT.upload(path) else: notshared.append(path) if notshared: limit = 5 sublime.error_message("The following paths are not a child of\n\n%s\n\nand will not be shared for security reasons:\n\n%s%s." % (G.PROJECT_PATH, ",\n".join(notshared[:limit]), len(notshared) > limit and ",\n..." or ""))
def _upload(self, path, text=None): size = 0 try: if text: # TODO: possible encoding issues with python 3 buf = text else: with open(path, 'rb') as buf_fd: buf = buf_fd.read() size = len(buf) encoding = 'utf8' rel_path = utils.to_rel_path(path) existing_buf = self.get_buf_by_path(path) if existing_buf: buf_md5 = hashlib.md5(buf).hexdigest() if existing_buf['md5'] == buf_md5: msg.log('%s already exists and has the same md5. Skipping.' % path) return size msg.log('Setting buffer ', rel_path) try: buf = buf.decode('utf-8') except Exception: buf = base64.b64encode(buf).decode('utf-8') encoding = 'base64' existing_buf['buf'] = buf existing_buf['encoding'] = encoding existing_buf['md5'] = buf_md5 self.send({ 'name': 'set_buf', 'id': existing_buf['id'], 'buf': buf, 'md5': buf_md5, 'encoding': encoding, }) return size try: buf = buf.decode('utf-8') except Exception: buf = base64.b64encode(buf).decode('utf-8') encoding = 'base64' msg.log('Creating buffer ', rel_path) event = { 'name': 'create_buf', 'buf': buf, 'path': rel_path, 'encoding': encoding, } self.send(event) except (IOError, OSError): msg.error('Failed to open %s.' % path) except Exception as e: msg.error('Failed to create buffer %s: %s' % (path, unicode(e))) return size
def connect(self, conn=None): utils.cancel_timeout(self._reconnect_timeout) self._reconnect_timeout = None self.cleanup() self._empty_selects = 0 self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.setblocking(False) if self.secure: if ssl: with open(self._cert_path, 'wb') as cert_fd: cert_fd.write(cert.CA_CERT.encode('utf-8')) else: msg.log( 'No SSL module found. Connection will not be encrypted.') self.secure = False if self.port == G.DEFAULT_PORT: self.port = 3148 # plaintext port conn_msg = 'Connecting to %s:%s' % (self.host, self.port) msg.log(conn_msg) editor.status_message(conn_msg) self._connect()
def _rate_limited_upload(self, paths_iter, total_bytes, bytes_uploaded=0.0, upload_func=None): reactor.tick() upload_func = upload_func or (lambda x: self._upload(utils.get_full_path(x))) if len(self.proto) > 0: self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 10, paths_iter, total_bytes, bytes_uploaded, upload_func) return bar_len = 20 try: p = next(paths_iter) size = upload_func(p) bytes_uploaded += size try: percent = (bytes_uploaded / total_bytes) except ZeroDivisionError: percent = 0.5 bar = ' |' + ('|' * int(bar_len * percent)) + (' ' * int((1 - percent) * bar_len)) + '|' editor.status_message('Uploading... %2.2f%% %s' % (percent * 100, bar)) except StopIteration: editor.status_message('Uploading... 100% ' + ('|' * bar_len) + '| complete') msg.log('All done uploading') return self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 50, paths_iter, total_bytes, bytes_uploaded, upload_func)
def run(self): G.FOLLOW_MODE = False G.FOLLOW_USERS.clear() G.SPLIT_MODE = False msg.log('Follow mode disabled') G.AGENT.update_status_msg('Stopped following changes.')