def _handle(self, data):
        self._buf_in += data
        while True:
            before, sep, after = self._buf_in.partition(b'\n')
            if not sep:
                return
            try:
                # Node.js sends invalid utf8 even though we're calling write(string, "utf8")
                # Python 2 can figure it out, but python 3 hates it and will die here with some byte sequences
                # Instead of crashing the plugin, we drop the data. Yes, this is horrible.
                before = before.decode('utf-8', 'ignore')
                data = json.loads(before)
            except Exception as e:
                msg.error('Unable to parse json: %s' % str_e(e))
                msg.error('Data: %s' % before)
                # XXXX: THIS LOSES DATA
                self._buf_in = after
                continue

            name = data.get('name')
            try:
                msg.debug('got data ' + (name or 'no name'))
                self.emit('data', name, data)
            except Exception as e:
                api.send_error('Error handling %s event.' % name, str_e(e))
                if name == 'room_info':
                    editor.error_message('Error joining workspace: %s' % str_e(e))
                    self.stop()
            self._buf_in = after
    def _handle(self, data):
        self._buf_in += data
        if self._handling:
            return
        self._handling = True
        while True:
            before, sep, after = self._buf_in.partition(b'\n')
            if not sep:
                break
            try:
                # Node.js sends invalid utf8 even though we're calling write(string, "utf8")
                # Python 2 can figure it out, but python 3 hates it and will die here with some byte sequences
                # Instead of crashing the plugin, we drop the data. Yes, this is horrible.
                before = before.decode('utf-8', 'ignore')
                data = json.loads(before)
            except Exception as e:
                msg.error('Unable to parse json: ', str_e(e))
                msg.error('Data: ', before)
                # XXXX: THIS LOSES DATA
                self._buf_in = after
                continue

            name = data.get('name')
            self._buf_in = after
            try:
                msg.debug('got data ' + (name or 'no name'))
                self.emit('data', name, data)
            except Exception as e:
                api.send_error('Error handling %s event.' % name, str_e(e))
                if name == 'room_info':
                    editor.error_message('Error joining workspace: %s' % str_e(e))
                    self.stop()
        self._handling = False
Exemple #3
0
    def _connect(self, host, port, attempts=0):
        if attempts > (self.proxy and 500 or 500):
            msg.error('Connection attempt timed out.')
            return self.reconnect()
        if not self._sock:
            msg.debug('_connect: No socket')
            return
        try:
            self._sock.connect((host, port))
            select.select([self._sock], [self._sock], [], 0)
        except socket.error as e:
            if e.errno == iscon_errno:
                pass
            elif e.errno in connect_errno:
                msg.debug('connect_errno: ', str_e(e))
                return utils.set_timeout(self._connect, 20, host, port,
                                         attempts + 1)
            else:
                msg.error('Error connecting: ', str_e(e))
                return self.reconnect()
        if self._secure:
            sock_debug('SSL-wrapping socket')
            self._sock = ssl.wrap_socket(self._sock,
                                         ca_certs=self._cert_path,
                                         cert_reqs=ssl.CERT_REQUIRED,
                                         do_handshake_on_connect=False)

        self._q.clear()
        self._buf_out = bytes()
        self.emit('connect')
        self.connected = True
    def _connect(self, host, port, attempts=0):
        if attempts > (self.proxy and 500 or 500):
            msg.error('Connection attempt timed out.')
            return self.reconnect()
        if not self._sock:
            msg.debug('_connect: No socket')
            return
        try:
            self._sock.connect((host, port))
            select.select([self._sock], [self._sock], [], 0)
        except socket.error as e:
            if e.errno == iscon_errno:
                pass
            elif e.errno in connect_errno:
                msg.debug('connect_errno: ', str_e(e))
                return utils.set_timeout(self._connect, 20, host, port, attempts + 1)
            else:
                msg.error('Error connecting: ', str_e(e))
                return self.reconnect()
        if self._secure:
            sock_debug('SSL-wrapping socket')
            self._sock = ssl.wrap_socket(self._sock, ca_certs=self._cert_path, cert_reqs=ssl.CERT_REQUIRED, do_handshake_on_connect=False)

        self._q.clear()
        self._buf_out = bytes()
        self.emit('connect')
        self.connected = True
Exemple #5
0
    def select(self, timeout=0):
        if not self._protos:
            return

        readable = []
        writeable = []
        errorable = []
        fd_map = {}

        for fd in self._protos:
            fileno = fd.fileno()
            if not fileno:
                continue
            fd.fd_set(readable, writeable, errorable)
            fd_map[fileno] = fd

        if not readable and not writeable:
            return

        try:
            _in, _out, _except = select.select(readable, writeable, errorable,
                                               timeout)
        except (select.error, socket.error, Exception) as e:
            # TODO: with multiple FDs, must call select with just one until we find the error :(
            for fileno in readable:
                try:
                    select.select([fileno], [], [], 0)
                except (select.error, socket.error, Exception) as e:
                    fd_map[fileno].reconnect()
                    msg.error('Error in select(): ', fileno, str_e(e))
            return

        for fileno in _except:
            fd = fd_map[fileno]
            self._reconnect(fd, _in, _out)

        for fileno in _out:
            fd = fd_map[fileno]
            try:
                fd.write()
            except ssl.SSLError as e:
                if e.args[0] != ssl.SSL_ERROR_WANT_WRITE:
                    raise
            except Exception as e:
                msg.error('Couldn\'t write to socket: ', str_e(e))
                msg.debug('Couldn\'t write to socket: ', pp_e(e))
                return self._reconnect(fd, _in)

        for fileno in _in:
            fd = fd_map[fileno]
            try:
                fd.read()
            except ssl.SSLError as e:
                if e.args[0] != ssl.SSL_ERROR_WANT_READ:
                    raise
            except Exception as e:
                msg.error('Couldn\'t read from socket: ', str_e(e))
                msg.debug('Couldn\'t read from socket: ', pp_e(e))
                fd.reconnect()
Exemple #6
0
    def select(self, timeout=0):
        if not self._protos:
            return

        readable = []
        writeable = []
        errorable = []
        fd_map = {}

        for fd in self._protos:
            fileno = fd.fileno()
            if not fileno:
                continue
            fd.fd_set(readable, writeable, errorable)
            fd_map[fileno] = fd

        if not readable and not writeable:
            return

        try:
            _in, _out, _except = select.select(readable, writeable, errorable, timeout)
        except (select.error, socket.error, Exception) as e:
            # TODO: with multiple FDs, must call select with just one until we find the error :(
            for fileno in readable:
                try:
                    select.select([fileno], [], [], 0)
                except (select.error, socket.error, Exception) as e:
                    fd_map[fileno].reconnect()
                    msg.error('Error in select(): ', fileno, str_e(e))
            return

        for fileno in _except:
            fd = fd_map[fileno]
            self._reconnect(fd, _in, _out)

        for fileno in _out:
            fd = fd_map[fileno]
            try:
                fd.write()
            except ssl.SSLError as e:
                if e.args[0] != ssl.SSL_ERROR_WANT_WRITE:
                    raise
            except Exception as e:
                msg.error('Couldn\'t write to socket: ', str_e(e))
                msg.debug('Couldn\'t write to socket: ', pp_e(e))
                return self._reconnect(fd, _in)

        for fileno in _in:
            fd = fd_map[fileno]
            try:
                fd.read()
            except ssl.SSLError as e:
                if e.args[0] != ssl.SSL_ERROR_WANT_READ:
                    raise
            except Exception as e:
                msg.error('Couldn\'t read from socket: ', str_e(e))
                msg.debug('Couldn\'t read from socket: ', pp_e(e))
                fd.reconnect()
Exemple #7
0
    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)
Exemple #8
0
    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_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)
Exemple #10
0
    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)
Exemple #11
0
    def remote_connect(self,
                       context,
                       host,
                       owner,
                       workspace,
                       d,
                       join_action=utils.JOIN_ACTION.PROMPT):
        G.PROJECT_PATH = os.path.realpath(d)
        try:
            utils.mkdir(os.path.dirname(G.PROJECT_PATH))
        except Exception as e:
            msg.error("Couldn't create directory", G.PROJECT_PATH, str_e(e))
            return

        auth = G.AUTH.get(host)
        if not auth:
            success = yield self.link_account, context, host
            if not success:
                return
            auth = G.AUTH.get(host)
            if not auth:
                msg.error("Something went really wrong.")
                return

        try:
            res = api.get_workspace(host, owner, workspace)
            if res.code == 404:
                msg.error("The workspace https://%s/%s/%s does not exist" %
                          (host, owner, workspace))
                return
        except Exception as e:
            message = 'Error getting workspace https://%s/%s/%s: %s' % (
                host, owner, workspace, str_e(e))
            msg.error(message)
            editor.error_message(message)
            return

        if self.agent:
            try:
                self.agent.stop()
            except Exception:
                pass

        G.WORKSPACE_WINDOW = yield self.get_a_window, d
        self.agent = self._make_agent(context, owner, workspace, auth,
                                      join_action)
        self.emit("agent", self.agent)
        reactor.reactor.connect(self.agent, host, G.DEFAULT_PORT, True)
        url = self.agent.workspace_url
        utils.add_workspace_to_persistent_json(owner, workspace, url, d)
        utils.update_recent_workspaces(url)
Exemple #12
0
    def prejoin_workspace(self, workspace_url, dir_to_share, api_args):
        try:
            result = utils.parse_url(workspace_url)
        except Exception as e:
            msg.error(str_e(e))
            return False

        host = result.get('host')
        if not api.get_basic_auth(host):
            raise ValueError(
                'No auth credentials for %s. Please add a username and secret for %s in your ~/.floorc.json'
                % (host, host))

        try:
            w = api.get_workspace_by_url(workspace_url)
        except Exception as e:
            editor.error_message('Error opening url %s: %s' %
                                 (workspace_url, str_e(e)))
            return False

        if w.code >= 400:
            try:
                d = utils.get_persistent_data()
                try:
                    del d['workspaces'][result['owner']][result['name']]
                except Exception:
                    pass
                try:
                    del d['recent_workspaces'][workspace_url]
                except Exception:
                    pass
                utils.update_persistent_data(d)
            except Exception as e:
                msg.debug(str_e(e))
            return False

        msg.debug('workspace: ', json.dumps(w.body))
        anon_perms = w.body.get('perms', {}).get('AnonymousUser', [])
        msg.debug('api args: ', api_args)
        new_anon_perms = api_args.get('perms', {}).get('AnonymousUser', [])
        # TODO: prompt/alert user if going from private to public
        if set(anon_perms) != set(new_anon_perms):
            msg.debug(str(anon_perms), str(new_anon_perms))
            w.body['perms']['AnonymousUser'] = new_anon_perms
            response = api.update_workspace(workspace_url, w.body)
            msg.debug(str(response.body))
        utils.add_workspace_to_persistent_json(w.body['owner'], w.body['name'],
                                               workspace_url, dir_to_share)
        return result
    def select(self, timeout=0):
        if not self._protos:
            return

        readable = []
        writeable = []
        errorable = []
        fd_map = {}

        for fd in self._protos:
            fileno = fd.fileno()
            if not fileno:
                continue
            fd.fd_set(readable, writeable, errorable)
            fd_map[fileno] = fd

        if not readable and not writeable:
            return

        try:
            _in, _out, _except = select.select(readable, writeable, errorable,
                                               timeout)
        except (select.error, socket.error, Exception) as e:
            # TODO: with multiple FDs, must call select with just one until we find the error :(
            if len(readable) == 1:
                readable[0].reconnect()
                return msg.error('Error in select(): %s' % str_e(e))
            raise Exception(
                "can't handle more than one fd exception in reactor")

        for fileno in _except:
            fd = fd_map[fileno]
            self._reconnect(fd, _in, _out)

        for fileno in _out:
            fd = fd_map[fileno]
            try:
                fd.write()
            except Exception as e:
                msg.error('Couldn\'t write to socket: %s' % str_e(e))
                return self._reconnect(fd, _in)

        for fileno in _in:
            fd = fd_map[fileno]
            try:
                fd.read()
            except Exception as e:
                msg.error('Couldn\'t read from socket: %s' % str_e(e))
                fd.reconnect()
Exemple #14
0
    def prejoin_workspace(self, workspace_url, dir_to_share, api_args):
        try:
            result = utils.parse_url(workspace_url)
        except Exception as e:
            msg.error(str_e(e))
            return False

        host = result.get("host")
        if not api.get_basic_auth(host):
            raise ValueError(
                "No auth credentials for %s. Please add a username and secret for %s in your ~/.floorc.json"
                % (host, host)
            )

        try:
            w = api.get_workspace_by_url(workspace_url)
        except Exception as e:
            editor.error_message("Error opening url %s: %s" % (workspace_url, str_e(e)))
            return False

        if w.code >= 400:
            try:
                d = utils.get_persistent_data()
                try:
                    del d["workspaces"][result["owner"]][result["name"]]
                except Exception:
                    pass
                try:
                    del d["recent_workspaces"][workspace_url]
                except Exception:
                    pass
                utils.update_persistent_data(d)
            except Exception as e:
                msg.debug(str_e(e))
            return False

        msg.debug("workspace: ", json.dumps(w.body))
        anon_perms = w.body.get("perms", {}).get("AnonymousUser", [])
        msg.debug("api args: ", api_args)
        new_anon_perms = api_args.get("perms", {}).get("AnonymousUser", [])
        # TODO: prompt/alert user if going from private to public
        if set(anon_perms) != set(new_anon_perms):
            msg.debug(str(anon_perms), str(new_anon_perms))
            w.body["perms"]["AnonymousUser"] = new_anon_perms
            response = api.update_workspace(workspace_url, w.body)
            msg.debug(str(response.body))
        utils.add_workspace_to_persistent_json(w.body["owner"], w.body["name"], workspace_url, dir_to_share)
        return result
def plugin_loaded():
    global called_plugin_loaded
    if called_plugin_loaded:
        return
    called_plugin_loaded = True
    print('Floobits: Called plugin_loaded.')

    if not os.path.exists(G.FLOORC_JSON_PATH):
        migrations.migrate_floorc()
    utils.reload_settings()

    # TODO: one day this can be removed (once all our users have updated)
    old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits')))
    if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR):
        print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR))
        os.rename(old_colab_dir, G.BASE_DIR)
        os.symlink(G.BASE_DIR, old_colab_dir)

    try:
        utils.normalize_persistent_data()
    except Exception as e:
        print('Floobits: Error normalizing persistent data:', str_e(e))
        # Keep on truckin' I guess

    d = utils.get_persistent_data()
    G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False)

    # Sublime plugin API stuff can't be called right off the bat
    if not utils.can_auth():
        utils.set_timeout(create_or_link_account, 1)

    utils.set_timeout(global_tick, 1)
Exemple #16
0
        def make_dir(d):
            d = os.path.realpath(os.path.expanduser(d))

            if not os.path.isdir(d):
                make_dir = sublime.ok_cancel_dialog(
                    '%s is not a directory. Create it?' % d)
                if not make_dir:
                    return self.window.show_input_panel(
                        '%s is not a directory. Enter an existing path:' % d,
                        d, None, None, None)
                try:
                    utils.mkdir(d)
                except Exception as e:
                    return sublime.error_message(
                        'Could not create directory %s: %s' % (d, str_e(e)))
            G.PROJECT_PATH = d

            if self.upload:
                result['upload'] = d
            else:
                result['upload'] = ""

            utils.add_workspace_to_persistent_json(result['owner'],
                                                   result['workspace'],
                                                   workspace_url, d)
            open_workspace_window(lambda: run_agent(**result))
Exemple #17
0
 def join_workspace(workspace_url):
     try:
         w = find_workspace(workspace_url)
     except Exception as e:
         sublime.error_message('Error: %s' % str_e(e))
         return False
     if not w:
         return False
     msg.debug('workspace: %s', json.dumps(w.body))
     # if self.api_args:
     anon_perms = w.body.get('perms', {}).get('AnonymousUser', [])
     new_anon_perms = self.api_args.get('perms').get(
         'AnonymousUser', [])
     # TODO: warn user about making a private workspace public
     if set(anon_perms) != set(new_anon_perms):
         msg.debug(str(anon_perms), str(new_anon_perms))
         w.body['perms']['AnonymousUser'] = new_anon_perms
         response = api.update_workspace(workspace_url, w.body)
         msg.debug(str(response.body))
     utils.add_workspace_to_persistent_json(w.body['owner'],
                                            w.body['name'],
                                            workspace_url, dir_to_share)
     self.window.run_command('floobits_join_workspace',
                             {'workspace_url': workspace_url})
     return True
def plugin_loaded():
    global called_plugin_loaded
    if called_plugin_loaded:
        return
    called_plugin_loaded = True
    print('Floobits: Called plugin_loaded.')

    if not os.path.exists(G.FLOORC_JSON_PATH):
        migrations.migrate_floorc()
    utils.reload_settings()

    # TODO: one day this can be removed (once all our users have updated)
    old_colab_dir = os.path.realpath(
        os.path.expanduser(os.path.join('~', '.floobits')))
    if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR):
        print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR))
        os.rename(old_colab_dir, G.BASE_DIR)
        os.symlink(G.BASE_DIR, old_colab_dir)

    try:
        utils.normalize_persistent_data()
    except Exception as e:
        print('Floobits: Error normalizing persistent data:', str_e(e))
        # Keep on truckin' I guess

    d = utils.get_persistent_data()
    G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False)

    # Sublime plugin API stuff can't be called right off the bat
    if not utils.can_auth():
        utils.set_timeout(create_or_link_account, 1)

    utils.set_timeout(global_tick, 1)
Exemple #19
0
    def _setup():
        # stupid yielding loop until we get a window from st2
        w = sublime.active_window()
        if w is None:
            return sublime.set_timeout(_setup, 50)

        try:
            settings = sublime.load_settings('Floobits.sublime-settings')
            now = time.time()
            old_time = settings.get('floobits-id')
            settings.set('floobits-id', now)
            interval = utils.set_interval(reactor.tick, G.TICK_TIME)

            def shutdown():
                print('Floobits plugin updated. Shutting down old instance.', old_time)
                try:
                    utils.cancel_timeout(interval)
                except Exception:
                    pass

            try:
                settings.clear_on_change('floobits-id')
            except Exception:
                pass
            settings.add_on_change('floobits-id', shutdown)
            w.run_command('floobits_setup')
        except Exception as e:
            print(str_e(e))
Exemple #20
0
    def join_workspace_by_url(self, context, workspace_url, possible_dirs=None):
        try:
            d = utils.parse_url(workspace_url)
        except Exception as e:
            return editor.error_message(str_e(e))

        return self.join_workspace(context, d['host'], d['workspace'], d['owner'], possible_dirs)
Exemple #21
0
    def run(self):
        try:
            agent = G.AGENT
            d = {
                'port': agent.proto.port,
                'secure': agent.proto.secure,
                'owner': agent.owner,
                'workspace': agent.workspace,
                'host': agent.proto.host,
            }
            view = self.window.active_view()
            if view:
                path = view.file_name()
                if path and utils.is_shared(path):
                    d['path'] = utils.to_rel_path(path)
                    try:
                        d['line'] = view.rowcol(view.sel()[0].a)[0]
                    except Exception:
                        pass

            url = utils.to_workspace_url(d)
            webbrowser.open(url)
        except Exception as e:
            sublime.error_message(
                'Unable to open workspace in web editor: %s' % str_e(e))
 def on_data(self, name, data):
     if name == 'create_user':
         del data['name']
         try:
             floorc = self.BASE_FLOORC + '\n'.join(
                 ['%s %s' % (k, v) for k, v in data.items()]) + '\n'
             with open(G.FLOORC_PATH, 'w') as floorc_fd:
                 floorc_fd.write(floorc)
             utils.reload_settings()
             if utils.can_auth():
                 p = os.path.join(G.BASE_DIR, 'welcome.md')
                 with open(p, 'w') as fd:
                     text = editor.welcome_text % (G.AUTH.get(
                         self.proto.host,
                         {}).get('username'), self.proto.host)
                     fd.write(text)
                 d = utils.get_persistent_data()
                 d['auto_generated_account'] = True
                 utils.update_persistent_data(d)
                 G.AUTO_GENERATED_ACCOUNT = True
                 editor.open_file(p)
             else:
                 editor.error_message(
                     'Something went wrong. You will need to sign up for an account to use Floobits.'
                 )
                 api.send_error('No username or secret')
         except Exception as e:
             msg.debug(traceback.format_exc())
             msg.error(str_e(e))
         try:
             d = utils.get_persistent_data()
             d['disable_account_creation'] = True
             utils.update_persistent_data(d)
         finally:
             self.proto.stop()
Exemple #23
0
 def open_workspace_settings(self):
     if not self.agent:
         return
     try:
         webbrowser.open(self.agent.workspace_url + '/settings', new=2, autoraise=True)
     except Exception as e:
         msg.error("Couldn't open a browser: %s" % (str_e(e)))
Exemple #24
0
    def join_workspace_by_url(self, context, workspace_url, possible_dirs=None):
        try:
            d = utils.parse_url(workspace_url)
        except Exception as e:
            return editor.error_message(str_e(e))

        return self.join_workspace(context, d['host'], d['workspace'], d['owner'], possible_dirs)
Exemple #25
0
    def _setup():
        # stupid yielding loop until we get a window from st2
        w = sublime.active_window()
        if w is None:
            return sublime.set_timeout(_setup, 50)

        try:
            settings = sublime.load_settings('Floobits.sublime-settings')
            now = time.time()
            old_time = settings.get('floobits-id')
            settings.set('floobits-id', now)
            interval = utils.set_interval(reactor.tick, G.TICK_TIME)

            def shutdown():
                print('Floobits plugin updated. Shutting down old instance.',
                      old_time)
                try:
                    utils.cancel_timeout(interval)
                except Exception:
                    pass

            try:
                settings.clear_on_change('floobits-id')
            except Exception:
                pass
            settings.add_on_change('floobits-id', shutdown)
            w.run_command('floobits_setup')
        except Exception as e:
            print(str_e(e))
Exemple #26
0
def plugin_loaded():
    global called_plugin_loaded
    if called_plugin_loaded:
        return
    called_plugin_loaded = True
    print('Floobits: Called plugin_loaded.')

    utils.reload_settings()

    G.SOCK_SINGLE_READ = SOCK_SINGLE_READ

    # TODO: one day this can be removed (once all our users have updated)
    old_colab_dir = os.path.realpath(
        os.path.expanduser(os.path.join('~', '.floobits')))
    if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR):
        print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR))
        os.rename(old_colab_dir, G.BASE_DIR)
        os.symlink(G.BASE_DIR, old_colab_dir)

    try:
        utils.normalize_persistent_data()
    except Exception as e:
        print('Floobits: Error normalizing persistent data:', str_e(e))
        # Keep on truckin' I guess

    d = utils.get_persistent_data()
    G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False)
    setup()
Exemple #27
0
 def _on_create_user(self, data):
     try:
         del data['name']
         floorc_json = {'auth': {}}
         floorc_json['auth'][G.DEFAULT_HOST] = data
         utils.save_floorc_json(floorc_json)
         utils.reload_settings()
         if utils.can_auth():
             p = os.path.join(G.BASE_DIR, 'welcome.md')
             with open(p, 'w') as fd:
                 username = G.AUTH.get(self.proto.host, {}).get('username')
                 text = editor.NEW_ACCOUNT_TXT.format(username=username,
                                                      host=self.proto.host)
                 fd.write(text)
             d = utils.get_persistent_data()
             d['auto_generated_account'] = True
             utils.update_persistent_data(d)
             G.AUTO_GENERATED_ACCOUNT = True
             editor.open_file(p)
         else:
             editor.error_message(
                 'Something went wrong. You will need to sign up for an account to use Floobits.'
             )
             api.send_error('No username or secret')
     except Exception as e:
         msg.debug(traceback.format_exc())
         msg.error(str_e(e))
     finally:
         try:
             d = utils.get_persistent_data()
             d['disable_account_creation'] = True
             utils.update_persistent_data(d)
         finally:
             self.stop()
Exemple #28
0
    def _scan_dir(self, bufs, ig, read_only):
        changed_bufs = []
        missing_bufs = []
        new_files = set()

        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in bufs.items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ',
                              buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace(
                            '\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ',
                              buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ',
                              buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ',
                          str_e(e))
                missing_bufs.append(buf)
        return changed_bufs, missing_bufs, new_files
Exemple #29
0
 def open_workspace(self):
     if not self.agent:
         return
     try:
         webbrowser.open(self.agent.workspace_url, new=2, autoraise=True)
     except Exception as e:
         msg.error("Couldn't open a browser: %s" % (str_e(e)))
Exemple #30
0
 def _on_create_user(self, data):
     try:
         del data['name']
         floorc_json = {
             'auth': {}
         }
         floorc_json['auth'][G.DEFAULT_HOST] = data
         utils.save_floorc_json(floorc_json)
         utils.reload_settings()
         if utils.can_auth():
             p = os.path.join(G.BASE_DIR, 'welcome.md')
             with open(p, 'w') as fd:
                 username = G.AUTH.get(self.proto.host, {}).get('username')
                 text = editor.NEW_ACCOUNT_TXT.format(username=username, host=self.proto.host)
                 fd.write(text)
             d = utils.get_persistent_data()
             d['auto_generated_account'] = True
             utils.update_persistent_data(d)
             G.AUTO_GENERATED_ACCOUNT = True
             editor.open_file(p)
         else:
             editor.error_message('Something went wrong. You will need to sign up for an account to use Floobits.')
             api.send_error('No username or secret')
     except Exception as e:
         msg.debug(traceback.format_exc())
         msg.error(str_e(e))
     finally:
         try:
             d = utils.get_persistent_data()
             d['disable_account_creation'] = True
             utils.update_persistent_data(d)
         finally:
             self.stop()
Exemple #31
0
def plugin_loaded():
    global called_plugin_loaded
    if called_plugin_loaded:
        return
    called_plugin_loaded = True
    print('Floobits: Called plugin_loaded.')

    utils.reload_settings()

    G.SOCK_SINGLE_READ = SOCK_SINGLE_READ

    # TODO: one day this can be removed (once all our users have updated)
    old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits')))
    if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR):
        print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR))
        os.rename(old_colab_dir, G.BASE_DIR)
        os.symlink(G.BASE_DIR, old_colab_dir)

    try:
        utils.normalize_persistent_data()
    except Exception as e:
        print('Floobits: Error normalizing persistent data:', str_e(e))
        # Keep on truckin' I guess

    d = utils.get_persistent_data()
    G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False)
    setup()
Exemple #32
0
    def delete_workspace(self, context, cb):
        host = yield self._get_host, context
        if not host:
            cb()
            return

        api_url = 'https://%s/api/workspaces/can/admin' % (host)

        try:
            r = api.api_request(host, api_url)
        except IOError as e:
            editor.error_message('Error getting workspaces can admin %s' %
                                 str_e(e))
            cb()
            return

        if r.code >= 400:
            editor.error_message('Error getting workspace list: %s' % r.body)
            cb()
            return

        choices = [
            '%s/%s' % (workspace['owner'], workspace['name'])
            for workspace in r.body
        ]
        (workspace, index) = yield self.user_select, context, 'Select workpace to delete', choices, []

        if not workspace:
            cb()
            return

        if G.EXPERT_MODE:
            yes = True
        else:
            yes = yield self.user_y_or_n, context, 'Really delete %s?' % workspace, 'Yes'

        if not yes:
            cb()
            return

        workspace = r.body[index]

        try:
            api.delete_workspace(host, workspace['owner'], workspace['name'])
        except IOError as e:
            editor.error_message('Error deleting workspace' % str_e(e))
        cb()
 def reconnect(self):
     try:
         api.get_workspace(self.host, 'Floobits', 'doesnotexist')
     except Exception as e:
         print(str_e(e))
         editor.error_message('Something went wrong. See https://%s/help/floorc to complete the installation.' % self.host)
     else:
         editor.error_message(PORT_BLOCK_MSG % self.host)
     self.stop()
Exemple #34
0
    def delete_workspace(self, context, cb):
        host = yield self._get_host, context
        if not host:
            cb()
            return

        api_url = "https://%s/api/workspaces/can/admin" % (host)

        try:
            r = api.api_request(host, api_url)
        except IOError as e:
            editor.error_message("Error getting workspaces can admin %s" % str_e(e))
            cb()
            return

        if r.code >= 400:
            editor.error_message("Error getting workspace list: %s" % r.body)
            cb()
            return

        choices = ["%s/%s" % (workspace["owner"], workspace["name"]) for workspace in r.body]
        (workspace, index) = yield self.user_select, context, "Select workpace to delete", choices, []

        if not workspace:
            cb()
            return

        if G.EXPERT_MODE:
            yes = True
        else:
            yes = yield self.user_y_or_n, context, "Really delete %s?" % workspace, "Yes"

        if not yes:
            cb()
            return

        workspace = r.body[index]

        try:
            api.delete_workspace(host, workspace["owner"], workspace["name"])
        except IOError as e:
            editor.error_message("Error deleting workspace" % str_e(e))
        cb()
Exemple #35
0
    def delete_workspace(self, context, cb):
        host = yield self._get_host, context
        if not host:
            cb()
            return

        api_url = 'https://%s/api/workspaces/can/admin' % (host)

        try:
            r = api.api_request(host, api_url)
        except IOError as e:
            editor.error_message('Error getting workspaces can admin %s' % str_e(e))
            cb()
            return

        if r.code >= 400:
            editor.error_message('Error getting workspace list: %s' % r.body)
            cb()
            return

        choices = ['%s/%s' % (workspace['owner'], workspace['name']) for workspace in r.body]
        (workspace, index) = yield self.user_select, context, 'Select workpace to delete', choices, []

        if not workspace:
            cb()
            return

        if G.EXPERT_MODE:
            yes = True
        else:
            yes = yield self.user_y_or_n, context, 'Really delete %s?' % workspace, 'Yes'

        if not yes:
            cb()
            return

        workspace = r.body[index]

        try:
            api.delete_workspace(host, workspace['owner'], workspace['name'])
        except IOError as e:
            editor.error_message('Error deleting workspace' % str_e(e))
        cb()
 def get_empty_window():
     for w in sublime.windows():
         project_data = w.project_data()
         try:
             folders = project_data.get('folders', [])
             if len(folders) == 0 or not folders[0].get('path'):
                 # no project data. co-opt this window
                 return w
         except Exception as e:
             print(str_e(e))
Exemple #37
0
 def get_empty_window():
     for w in sublime.windows():
         project_data = w.project_data()
         try:
             folders = project_data.get('folders', [])
             if len(folders) == 0 or not folders[0].get('path'):
                 # no project data. co-opt this window
                 return w
         except Exception as e:
             print(str_e(e))
Exemple #38
0
    def _scan_dir(self, bufs, ig, read_only):
        changed_bufs = []
        missing_bufs = []
        new_files = set()

        if not read_only:
            new_files = set([utils.to_rel_path(x) for x in ig.list_paths()])

        for buf_id, buf in bufs.items():
            buf_id = int(buf_id)  # json keys must be strings
            buf_path = utils.get_full_path(buf['path'])
            new_dir = os.path.dirname(buf_path)
            utils.mkdir(new_dir)
            self.bufs[buf_id] = buf
            self.paths_to_ids[buf['path']] = buf_id

            view = self.get_view(buf_id)
            if view and not view.is_loading() and buf['encoding'] == 'utf8':
                view_text = view.get_text()
                view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest()
                buf['buf'] = view_text
                buf['view'] = view
                G.VIEW_TO_HASH[view.native_id] = view_md5
                if view_md5 == buf['md5']:
                    msg.debug('md5 sum matches view. not getting buffer ', buf['path'])
                else:
                    changed_bufs.append(buf)
                    buf['md5'] = view_md5
                continue

            try:
                if buf['encoding'] == 'utf8':
                    if io:
                        buf_fd = io.open(buf_path, 'Urt', encoding='utf8')
                        buf_buf = buf_fd.read()
                    else:
                        buf_fd = open(buf_path, 'rb')
                        buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n')
                    md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest()
                else:
                    buf_fd = open(buf_path, 'rb')
                    buf_buf = buf_fd.read()
                    md5 = hashlib.md5(buf_buf).hexdigest()
                buf_fd.close()
                buf['buf'] = buf_buf
                if md5 == buf['md5']:
                    msg.debug('md5 sum matches. not getting buffer ', buf['path'])
                else:
                    msg.debug('md5 differs. possibly getting buffer later ', buf['path'])
                    changed_bufs.append(buf)
                    buf['md5'] = md5
            except Exception as e:
                msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e))
                missing_bufs.append(buf)
        return changed_bufs, missing_bufs, new_files
Exemple #39
0
 def find_workspace(workspace_url):
     r = api.get_workspace_by_url(workspace_url)
     if r.code < 400:
         return r
     try:
         result = utils.parse_url(workspace_url)
         d = utils.get_persistent_data()
         del d['workspaces'][result['owner']][result['name']]
         utils.update_persistent_data(d)
     except Exception as e:
         msg.debug(str_e(e))
 def find_workspace(workspace_url):
     r = api.get_workspace_by_url(workspace_url)
     if r.code < 400:
         return r
     try:
         result = utils.parse_url(workspace_url)
         d = utils.get_persistent_data()
         del d['workspaces'][result['owner']][result['name']]
         utils.update_persistent_data(d)
     except Exception as e:
         msg.debug(str_e(e))
 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 run(self):
     try:
         agent = G.AGENT
         url = utils.to_workspace_url({
             'port': agent.proto.port,
             'secure': agent.proto.secure,
             'owner': agent.owner,
             'workspace': agent.workspace,
             'host': agent.proto.host,
         })
         webbrowser.open(url)
     except Exception as e:
         sublime.error_message('Unable to open workspace in web editor: %s' % str_e(e))
Exemple #43
0
 def run(self):
     try:
         agent = G.AGENT
         url = utils.to_workspace_url({
             'port': agent.proto.port,
             'secure': agent.proto.secure,
             'owner': agent.owner,
             'workspace': agent.workspace,
             'host': agent.proto.host,
         })
         webbrowser.open(url)
     except Exception as e:
         sublime.error_message('Unable to open workspace in web editor: %s' % str_e(e))
Exemple #44
0
    def create_or_link_account(self, context, host, force, cb):
        if host != "floobits.com":
            self.link_account(context, host, cb)
            return
        disable_account_creation = utils.get_persistent_data().get(
            'disable_account_creation')
        if disable_account_creation and not force:
            print(
                'We could not automatically create or link your floobits account. Please go to floobits.com and sign up to use this plugin.'
            )
            return

        if not G.EXPERT_MODE:
            editor.message_dialog(
                'Thank you for installing the Floobits plugin!\n\nLet\'s set up your editor to work with Floobits.'
            )

        choices = [
            'Sign in to Floobits', 'Automatically create a Floobits account',
            'Cancel (see https://floobits.com/help/floorc)'
        ]

        (
            choice, index
        ) = yield self.user_select, context, 'You need an account to use Floobits! Do you want to:', choices, None

        if index == -1 or index == 2:
            d = utils.get_persistent_data()
            if not d.get('disable_account_creation'):
                d['disable_account_creation'] = True
                utils.update_persistent_data(d)
                # TODO: this instruction is only useful for Sublime Text
                editor.message_dialog(
                    '''You can set up a Floobits account at any time under:\n\nTools -> Floobits -> Set up'''
                )
            cb(None)
            return

        agent = None
        if index == 0:
            agent = credentials.RequestCredentialsHandler()
        else:
            agent = account.CreateAccountHandler()

        agent.once('end', cb)

        try:
            reactor.reactor.connect(agent, host, G.DEFAULT_PORT, True)
        except Exception as e:
            print(str_e(e))
Exemple #45
0
    def create_or_link_account(self, context, host, force, cb):
        if host != "floobits.com":
            self.link_account(context, host, cb)
            return
        disable_account_creation = utils.get_persistent_data().get("disable_account_creation")
        if disable_account_creation and not force:
            print(
                "We could not automatically create or link your floobits account. Please go to floobits.com and sign up to use this plugin."
            )
            return

        if not G.EXPERT_MODE:
            editor.message_dialog(
                "Thank you for installing the Floobits plugin!\n\nLet's set up your editor to work with Floobits."
            )

        choices = ["Sign in to Floobits", "Create a Floobits account", "Cancel (see https://floobits.com/help/floorc)"]

        (choice, index) = (
            yield self.user_select,
            context,
            "You need an account to use Floobits! Do you want to:",
            choices,
            None,
        )

        if index == -1 or index == 2:
            d = utils.get_persistent_data()
            if not d.get("disable_account_creation"):
                d["disable_account_creation"] = True
                utils.update_persistent_data(d)
                # TODO: this instruction is only useful for Sublime Text
                editor.message_dialog(
                    """You can set up a Floobits account at any time under\n\nTools -> Floobits -> Set up"""
                )
            cb(None)
            return

        agent = None
        if index == 0:
            agent = credentials.RequestCredentialsHandler()
        else:
            agent = account.CreateAccountHandler()

        agent.once("end", cb)

        try:
            reactor.reactor.connect(agent, host, G.DEFAULT_PORT, True)
        except Exception as e:
            print(str_e(e))
Exemple #46
0
 def reconnect(self):
     try:
         api.get_workspace(self.host, 'Floobits', 'doesnotexist')
     except Exception as e:
         print(str_e(e))
         editor.error_message('Something went wrong. See https://%s/help/floorc to complete the installation.' % self.host)
     else:
         if G.OUTBOUND_FILTERING:
             editor.error_message('Something went wrong. See https://%s/help/floorc to complete the installation.' % self.host)
             return self.stop()
         if self.host == 'floobits.com':
             G.OUTBOUND_FILTERING = True
             return self.connect()
         editor.error_message(PORT_BLOCK_MSG % self.host)
     self.stop()
Exemple #47
0
 def run_agent(owner, workspace, host, port, secure, upload):
     if G.AGENT:
         msg.debug('Stopping agent.')
         reactor.stop()
         G.AGENT = None
     try:
         auth = G.AUTH.get(host)
         if not auth:
             success = yield link_account, host
             if not success:
                 return
             auth = G.AUTH.get(host)
         conn = SublimeConnection(owner, workspace, auth, upload)
         reactor.connect(conn, host, port, secure)
     except Exception as e:
         msg.error(str_e(e))
 def run_agent(owner, workspace, host, port, secure, upload):
     if G.AGENT:
         msg.debug('Stopping agent.')
         reactor.stop()
         G.AGENT = None
     try:
         auth = G.AUTH.get(host)
         if not auth:
             success = yield link_account, host
             if not success:
                 return
             auth = G.AUTH.get(host)
         conn = SublimeConnection(owner, workspace, auth, upload)
         reactor.connect(conn, host, port, secure)
     except Exception as e:
         msg.error(str_e(e))
 def cb(index):
     if index == 0:
         token = binascii.b2a_hex(uuid.uuid4().bytes).decode('utf-8')
         agent = RequestCredentialsHandler(token)
     elif index == 1:
         agent = CreateAccountHandler()
     else:
         d = utils.get_persistent_data()
         if d.get('disable_account_creation'):
             return
         d['disable_account_creation'] = True
         utils.update_persistent_data(d)
         sublime.message_dialog('''You can set up a Floobits account at any time under\n\nTools -> Floobits -> Setup''')
     try:
         reactor.connect(agent, G.DEFAULT_HOST, G.DEFAULT_PORT, True)
     except Exception as e:
         print(str_e(e))
Exemple #50
0
 def _on_rename_buf(self, data):
     del self.paths_to_ids[data['old_path']]
     self.paths_to_ids[data['path']] = data['id']
     new = utils.get_full_path(data['path'])
     old = utils.get_full_path(data['old_path'])
     new_dir = os.path.split(new)[0]
     if new_dir:
         utils.mkdir(new_dir)
     view = self.get_view(data['id'])
     if view:
         view.rename(new)
     else:
         try:
             os.rename(old, new)
         except Exception as e:
             msg.debug('Error moving ', old, 'to', new, str_e(e))
             utils.save_buf(self.bufs[data.id])
     self.bufs[data['id']]['path'] = data['path']
Exemple #51
0
    def link_account(self, context, host, cb):
        prompt = 'No credentials found in ~/.floorc.json for %s. Would you like to sign in? (opens a browser)' % host
        yes = yield self.user_y_or_n, context, prompt, 'Sign in'
        if not yes:
            return

        agent = credentials.RequestCredentialsHandler()
        if not agent:
            self.error_message('''A configuration error occured earlier. Please go to %s and sign up to use this plugin.
    We're really sorry. This should never happen.''' % host)
            return

        agent.once('end', cb)

        try:
            reactor.reactor.connect(agent, host, G.DEFAULT_PORT, True)
        except Exception as e:
            print(str_e(e))
Exemple #52
0
    def link_account(self, context, host, cb):
        prompt = 'No credentials found in ~/.floorc.json for %s. Would you like to sign in? (opens a browser)' % host
        yes = yield self.user_y_or_n, context,  prompt, 'Sign in'
        if not yes:
            return

        agent = credentials.RequestCredentialsHandler()
        if not agent:
            self.error_message('''A configuration error occured earlier. Please go to %s and sign up to use this plugin.\n
    We're really sorry. This should never happen.''' % host)
            return

        agent.once('end', cb)

        try:
            reactor.reactor.connect(agent, host, G.DEFAULT_PORT, True)
        except Exception as e:
            print(str_e(e))
Exemple #53
0
 def stop_handler(self, handler):
     try:
         handler.proto.stop()
     except Exception as e:
         msg.warn('Error stopping connection: ', str_e(e))
     try:
         self._handlers.remove(handler)
     except Exception:
         pass
     try:
         self._protos.remove(handler.proto)
     except Exception:
         pass
     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 _do_ssl_handshake(self):
        try:
            sock_debug('Doing SSL handshake')
            self._sock.do_handshake()
        except ssl.SSLError as e:
            sock_debug('Floobits: ssl.SSLError. This is expected sometimes.')
            if e.args[0] in [ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE]:
                return False
        except Exception as e:
            msg.error('Error in SSL handshake:', str_e(e))
        else:
            sock_debug('Successful handshake')
            self._needs_handshake = False
            editor.status_message('SSL handshake completed to %s:%s' % (self.host, self.port))
            return True

        self.reconnect()
        return False
 def _on_rename_buf(self, data):
     del self.paths_to_ids[data['old_path']]
     self.paths_to_ids[data['path']] = data['id']
     new = utils.get_full_path(data['path'])
     old = utils.get_full_path(data['old_path'])
     new_dir = os.path.split(new)[0]
     if new_dir:
         utils.mkdir(new_dir)
     view = self.get_view(data['id'])
     if view:
         view.rename(new)
     else:
         try:
             os.rename(old, new)
         except Exception as e:
             msg.debug('Error moving ', old, 'to', new, str_e(e))
             utils.save_buf(self.bufs[data.id])
     self.bufs[data['id']]['path'] = data['path']
def link_account(host, cb):
    account = sublime.ok_cancel_dialog('No credentials found in ~/.floorc.json for %s.\n\n'
                                       'Click "Link Account" to open a web browser and add credentials.' % host,
                                       'Link Account')
    if not account:
        return
    token = binascii.b2a_hex(uuid.uuid4().bytes).decode('utf-8')
    agent = RequestCredentialsHandler(token)
    if not agent:
        sublime.error_message('''A configuration error occured earlier. Please go to %s and sign up to use this plugin.\n
We're really sorry. This should never happen.''' % host)
        return

    agent.once('end', cb)

    try:
        reactor.connect(agent, host, G.DEFAULT_PORT, True)
    except Exception as e:
        print(str_e(e))
Exemple #57
0
 def cb(index):
     if index == 0:
         token = binascii.b2a_hex(uuid.uuid4().bytes).decode('utf-8')
         agent = RequestCredentialsHandler(token)
     elif index == 1:
         agent = CreateAccountHandler()
     else:
         d = utils.get_persistent_data()
         if d.get('disable_account_creation'):
             return
         d['disable_account_creation'] = True
         utils.update_persistent_data(d)
         sublime.message_dialog(
             '''You can set up a Floobits account at any time under\n\nTools -> Floobits -> Setup'''
         )
     try:
         reactor.connect(agent, G.DEFAULT_HOST, G.DEFAULT_PORT, True)
     except Exception as e:
         print(str_e(e))
Exemple #58
0
 def reconnect(self):
     try:
         api.get_workspace(self.host, 'Floobits', 'doesnotexist')
     except Exception as e:
         print(str_e(e))
         editor.error_message(
             'Something went wrong. See https://%s/help/floorc to complete the installation.'
             % self.host)
     else:
         if G.OUTBOUND_FILTERING:
             editor.error_message(
                 'Something went wrong. See https://%s/help/floorc to complete the installation.'
                 % self.host)
             return self.stop()
         if self.host == 'floobits.com':
             G.OUTBOUND_FILTERING = True
             return self.connect()
         editor.error_message(PORT_BLOCK_MSG % self.host)
     self.stop()
Exemple #59
0
    def remote_connect(self, context, host, owner, workspace, d, join_action=utils.JOIN_ACTION.PROMPT):
        G.PROJECT_PATH = os.path.realpath(d)
        try:
            utils.mkdir(os.path.dirname(G.PROJECT_PATH))
        except Exception as e:
            msg.error("Couldn't create directory", G.PROJECT_PATH, str_e(e))
            return

        auth = G.AUTH.get(host)
        if not auth:
            success = yield self.link_account, context, host
            if not success:
                return
            auth = G.AUTH.get(host)
            if not auth:
                msg.error("Something went really wrong.")
                return

        try:
            res = api.get_workspace(host, owner, workspace)
            if res.code == 404:
                msg.error("The workspace https://%s/%s/%s does not exist" % (host, owner, workspace))
                return
        except Exception as e:
            message = 'Error getting workspace https://%s/%s/%s: %s' % (host, owner, workspace, str_e(e))
            msg.error(message)
            editor.error_message(message)
            return

        if self.agent:
            try:
                self.agent.stop()
            except Exception:
                pass

        G.WORKSPACE_WINDOW = yield self.get_a_window, d
        self.agent = self._make_agent(context, owner, workspace, auth, join_action)
        self.emit("agent", self.agent)
        reactor.reactor.connect(self.agent, host, G.DEFAULT_PORT, True)
        url = self.agent.workspace_url
        utils.add_workspace_to_persistent_json(owner, workspace, url, d)
        utils.update_recent_workspaces(url)