Пример #1
0
    def get_file_content(self, file_name, user_id):
        '''
        :param file_name: (string)
        :param user_id: (string)
        :return: content from the file (string)
        '''
        global dir_files

        file_path = os.path.join(dir_files, file_name)
        limited_files = self.limited_files_from_config(user_id)
        content, resp_code = "", RESP.OK

        lock.acquire()
        config = self.server_config_file()

        if os.path.isfile(file_path):
            # Check user's permissions
            if file_name not in limited_files:
                with open(file_path, "r") as f:
                    content = f.read()
            else:
                resp_code = RESP.PERMISSION_ERROR
        else:
            resp_code = RESP.FILE_DOES_NOT_EXIST

        am_i_owner = self.is_user_owner_of_file(config, file_name, user_id)
        am_i_owner = "1" if am_i_owner else "0"

        file_access = self.get_file_access(config, file_name)

        lock.release()

        sending_data = pack_list([am_i_owner, file_access, content])
        return resp_code, sending_data
Пример #2
0
    def notify(self, command, change):
        # Send notifications to all other users except the master
        if self.notify_me:
            sending_data = pack_list(change)
            tcp_send(self.__sock, command, sending_data)

        # Set current thread to "receive notifications" state
        self.notify_me = True
Пример #3
0
    def change_access_to_file(self, user_id, file_name, needed_access):
        '''
        :param user_id: (string)
        :param file_name: (string)
        :param needed_access: (enum)
        :return: response code
        '''
        global lock

        resp_code = RESP.OK

        lock.acquire()
        config = self.server_config_file()

        # Only owner can edit the access of the file
        if self.is_user_owner_of_file(config, file_name, user_id):
            files = value_of_option_from_config(config, "LIMITED_FILES",
                                                user_id)
            files = files.split(SEP) if files else []

            # Access to the file should be public
            if needed_access == ACCESS.PUBLIC:
                # Make access public by removing file from limited files
                if file_name in files:
                    files.remove(file_name)

            # Access to the file should be private
            else:
                # Add file to limited files (means file is private)
                if file_name not in files:
                    files.append(file_name)

            config.set("LIMITED_FILES", user_id, pack_list(files))
            self.save_config(config)

        # User wants to change access, but he/she is not owner of the file
        else:
            resp_code = RESP.PERMISSION_ERROR

        lock.release()

        return resp_code
Пример #4
0
    def remove_file(self, file_name, user_id):
        global dir_files, lock
        '''
        :param file_name: (string)
        :param user_id: (string)
        :return: response code (enum)
        '''
        file_path = os.path.join(dir_files, file_name)
        resp_code = RESP.OK

        lock.acquire()
        config = self.server_config_file()

        if self.is_user_owner_of_file(config, file_name, user_id):
            try:
                os.remove(file_path)

                # remove file from config
                self.remove_option_from_config(config, "OWNERS_FILES",
                                               file_name)

                # Remove file from limited files from config
                files = value_of_option_from_config(config, "LIMITED_FILES",
                                                    user_id)
                files = files.split(SEP) if files else []

                if file_name in files:
                    files.remove(file_name)
                    config.set("LIMITED_FILES", user_id, pack_list(files))
            except:
                resp_code = RESP.FAIL
        else:
            resp_code = RESP.FILE_ALREADY_EXISTS

        self.save_config(config)
        lock.release()

        return resp_code
Пример #5
0
    def run(self):
        global dir_files, lock

        current_thread = threading.current_thread()
        connection_n = current_thread.getName().split("-")[1]
        current_thread.socket = self.__sock

        LOG.debug("Client %s connected:" % connection_n)
        LOG.debug("Client's socket info : %s:%d:" % self.__sock.getsockname())

        user_id = ""

        while True:
            msg = tcp_receive(self.__sock)
            resp_code, sending_data = RESP.OK, ""

            # Msg received successfully
            if msg:
                command, data = parse_query(msg)
                LOG.debug(
                    "Client's request (%s) - %s|%s" %
                    (self.__sock.getsockname(), command, data[:10] + "..."))

            # Case: some problem with receiving data
            else:
                LOG.debug("Client(%s) closed the connection" % connection_n)
                break

            if command == COMMAND.GENERATE_USER_ID:
                # make a unique user_id based on the host ID and current time
                user_id = uuid.uuid1()

                resp_code, sending_data = RESP.OK, user_id
                LOG.debug(
                    "Server generated a new user_id (%s) and sent it to client"
                    % user_id)

            elif command == COMMAND.NOTIFY_ABOUT_USER_ID:
                user_id = data
                LOG.debug("Client sent his existing user_id (%s)" % user_id)

                resp_code = RESP.OK
                LOG.debug(
                    "Empty request with acknowledgement about receiving user_id was sent to client"
                )

            elif command == COMMAND.LIST_OF_ACCESIBLE_FILES:
                LOG.debug(
                    "Client requested to get a list of available files (client:%s...)"
                    % user_id[:7])

                all_files = [
                    f for f in os.listdir(dir_files)
                    if os.path.isfile(os.path.join(dir_files, f))
                ]
                limited_files = self.server.limited_files_from_config(user_id)
                available_files = set(all_files) - set(limited_files)

                resp_code, sending_data = RESP.OK, pack_list(available_files)
                LOG.debug(
                    "List of available files was sent to client (:%s...)" %
                    user_id[:7])

            elif command == COMMAND.GET_FILE:
                file_name = data
                LOG.debug(
                    "Client requested to get file \"%s\" (client:%s...)" %
                    (file_name, user_id[:7]))

                resp_code, sending_data = self.server.get_file_content(
                    file_name, user_id)
                LOG.debug(
                    "Response (code:%s) on getting requested file was sent to client (:%s...)"
                    % (resp_code, user_id[:7]))

            elif command == COMMAND.CREATE_NEW_FILE:
                LOG.debug(
                    "Client requested to create a new file (client:%s...)" %
                    user_id[:7])

                # print(data, SEP)
                file_name, access = data.split(SEP)

                resp_code = self.server.create_file(file_name, user_id, access)
                LOG.debug(
                    "Response(code:%s) of file creation was sent to client (:%s...)"
                    % (resp_code, user_id[:7]))

                # If access is public and result of file creation is OK, then notify other clients
                if access == ACCESS.PUBLIC and resp_code == RESP.OK:
                    change = [COMMAND.NOTIFICATION.FILE_CREATION, [file_name]]
                    self.add_notification(change)

            elif command == COMMAND.DELETE_FILE:
                LOG.debug(
                    "Client requested to delete a file \"%s\" (client:%s...)" %
                    (data, user_id[:7]))

                file_name = data

                resp_code = self.server.remove_file(file_name, user_id=user_id)
                LOG.debug(
                    "Response(code:%s) of file deletion was sent to client (:%s...)"
                    % (resp_code, user_id[:7]))

                # If response is OK, notify other clients about deletion of this file
                if resp_code == RESP.OK:
                    change = [COMMAND.NOTIFICATION.FILE_DELETION, [file_name]]
                    self.add_notification(change)

            elif command == COMMAND.UPDATE_FILE:
                LOG.debug("Client requested to update a file (client:%s...)" %
                          user_id[:7])

                file_name, change_type, pos, key = parse_change(
                    data, case_update_file=True)

                resp_code = self.server.update_file(file_name, change_type,
                                                    pos, key)
                LOG.debug(
                    "Response(code:%s) of change in file was sent to client (:%s...)"
                    % (resp_code, user_id[:7]))

                # Add change from client into the queue "changes"
                change = [
                    COMMAND.NOTIFICATION.UPDATE_FILE,
                    [file_name, change_type, pos, key]
                ]
                self.add_notification(change)

            elif command == COMMAND.CHANGE_ACCESS_TO_FILE:
                LOG.debug("Client requested to update a file (client:%s...)" %
                          user_id[:7])

                file_name, needed_access = parse_query(data)

                resp_code = self.server.change_access_to_file(
                    user_id, file_name, needed_access)
                LOG.debug(
                    "Response(code:%s) of change in file was sent to client (:%s...)"
                    % (resp_code, user_id[:7]))

                # If response is OK, notify other clients about deletion of this file
                if resp_code == RESP.OK:
                    change = [
                        COMMAND.NOTIFICATION.CHANGED_ACCESS_TO_FILE,
                        [file_name, needed_access]
                    ]
                    self.add_notification(change)

            # Send response on requested command
            res = tcp_send(self.__sock, resp_code, sending_data)

            # Trigger notify_clients function (if there're some changes in the queue, it will process them)
            self.server.notify_other_clients()

            # Case: some problem with receiving data
            if not res:
                LOG.debug("Client(%s, %s) closed the connection" %
                          self.__sock.getsockname())
                break

        close_socket(self.__sock, 'Close client socket.')