Esempio n. 1
0
    def __init__(self, root='/tmp', outer_show=None):

        # local relative
        if not os.path.isdir(root):
            raise InternalError('input not a path')
        self.root_directory = root
        self.console_log(0, 'local root set to: ' + root)

        # connect relative
        self.status = self.STATUS_OFFLINE
        self.trans_mode = self.MODE_PASV
        self.control_sock = None
        self.data_sock = None
        if outer_show is not None and not callable(outer_show):
            raise InternalError('function given to Session not callable')
        self.outer_show = outer_show

        # file relative
        self.TRANSMITTING = False
        self.trans_size = 0
        self.trans_status = self.TRANS_NO_TASK
        self.current_upload = {}
        self.current_download = {}

        # server relative
        self.server_ip = ''
        self.server_port = 0
        self.server_root = ''
        self.server_current_dir = ''
Esempio n. 2
0
    def list_server_file(self):
        if self.trans_mode == self.MODE_PORT:
            self.data_port()
        else:
            self.data_pasv()
        self.send_msg('LIST')
        code = self.get_res_code(self.expect_respond())
        if code != 150:
            raise InternalError('Server return not 150')

        result = ''
        while True:
            data = self.data_sock.recv(self.BUFF_SIZE)
            if data is None or len(data) == 0:
                break
            result += data.decode()

        # 接受完毕
        self.data_sock.close()
        self.data_sock = None
        code = self.get_res_code(self.expect_respond())
        if code != 226:
            raise InternalError('LIST failed!')

        return result
Esempio n. 3
0
    def change_server_current_root(self, target_dir):
        # CWD命令,获取server_current_dir
        assert type(
            target_dir) == str and target_dir != '', 'given target dir wrong'
        # 可能要返回上级目录
        if target_dir == '..':
            if self.in_server_root():
                raise InternalError('should not have parent dir here')
            pare, child = os.path.split(self.server_current_dir)
            if child == '':
                raise InternalError('child path is none')
            self.send_msg('CWD ' + pare)
        else:
            self.send_msg('CWD ' + target_dir)

        res = self.expect_respond()
        code = self.get_res_code(res)
        if code not in [200, 250]:
            raise InternalError('Server rejected CWD')

        # 修改目录
        if target_dir == '..':
            self.server_current_dir = pare
        else:
            self.server_current_dir = os.path.join(self.server_current_dir,
                                                   target_dir)
        self.console_log(
            0, 'server\'s root dir changed to: ' + self.server_current_dir)
Esempio n. 4
0
 def continue_transmit(self):
     if self.trans_status == self.TRANS_DOWN_STOP or self.trans_status == self.TRANS_UP_STOP:
         self.send_msg('REST ' + str(self.trans_size))
         code = self.get_res_code(self.expect_respond())
         if code != 350:
             raise InternalError('Server rejected REST')
         return
     else:
         raise InternalError('continue but status wrong')
Esempio n. 5
0
 def get_res_code(self, res):
     assert type(res) == str, 'input res not string'
     lines = res.split('\n')
     if len(lines) < 2:
         raise InternalError('input for res code is empty')
     code = lines[-2][:3]
     return int(code)
Esempio n. 6
0
    def login(self, user, psd):
        assert type(user) == str, 'input user not a string'
        assert type(psd) == str, 'input password not a string'

        if user == '' or psd == '':
            raise LogicError('name and password can\'t be empty.')

        self.send_msg('USER ' + user)
        res = self.expect_respond()
        code = self.get_res_code(res)
        if code == 230:
            return
        elif code in [331, 332]:
            self.send_msg('PASS ' + psd)
            res = self.expect_respond()
            code = self.get_res_code(res)
            if code == 230:
                self.status = self.STATUS_LOGGED
                # 获取一下目录
                self.get_server_current_root()
                self.server_root = self.server_current_dir
                self.send_msg('TYPE I')
                code = self.get_res_code(self.expect_respond())
                if code != 200:
                    raise InternalError('Server rejected TYPE')
                return
            elif code == 202:
                raise LogicError('permission already granted')
            elif code == 530:
                raise LogicError('username or password unacceptable')
            else:
                raise LogicError(
                    'failed to login, see command prompt for infomation')
        else:
            raise LogicError('server denied the input user name')
Esempio n. 7
0
    def data_pasv(self):
        self.send_msg('PASV')
        res = self.expect_respond()
        code = self.get_res_code(res)
        if code != 227:
            raise InternalError('Server rejected pasv')
        # 解析服务器返回的字符串
        reg = re.compile(
            '^\S*\s\D*(\d{1,3},\d{1,3},\d{1,3},\d{1,3}),(\d{1,3},\d{1,3}).*$')
        match_ans = reg.match(res)
        assert match_ans is not None, 'matching result is none, respond is: ' + res
        assert len(match_ans.groups()
                   ) == 2, 'match result is wrong: ' + str(match_ans)

        datacon_ip = match_ans.groups()[0].replace(',', '.')
        port_ls = match_ans.groups()[1].split(',')
        assert len(port_ls) == 2, 'port recived error'
        datacon_port = int(port_ls[0]) * 256 + int(port_ls[1])
        assert utility.is_address(
            datacon_ip, datacon_port), 'recived ip or address format wrong.'

        # 开始连接
        if self.data_sock:
            self.data_sock.close()
            self.data_sock = None
        self.data_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # self.data_sock.connect((datacon_ip, datacon_port))
        self.data_sock.connect((self.server_ip, datacon_port))
        return
Esempio n. 8
0
 def finish_trans_file(self, is_done, size_done):
     if is_done:
         code = self.get_res_code(self.expect_respond())
         if code != 226:
             raise InternalError('failed to transmit')
         self.trans_size = 0
         self.TRANSMITTING = False
         self.trans_status = self.TRANS_NO_TASK
         self.console_log(0, 'finished transmit')
     else:
         code = self.get_res_code(self.expect_respond())
         self.TRANSMITTING = False
         self.trans_size = size_done
         if self.trans_status == self.TRANS_DOWN_GOING:
             self.trans_status = self.TRANS_DOWN_STOP
         elif self.trans_status == self.TRANS_UP_GOING:
             self.trans_status = self.TRANS_UP_STOP
         else:
             raise InternalError('pause but status wrong')
         self.console_log(0, 'stopped at size ' + str(self.trans_size))
Esempio n. 9
0
 def get_server_current_root(self):
     # PWD 命令,获取server_current_dir
     self.send_msg('PWD')
     res = self.expect_respond()
     code = self.get_res_code(res)
     if code != 257:
         raise InternalError('Server rejected PWD')
     dir_re = re.compile('[^"]*"([^"]*)".*')
     match_ans = dir_re.match(res)
     assert match_ans is not None, 'matching result is none, respond is:' + res
     assert len(match_ans.groups()
                ) == 1, 'match result is wrong: ' + str(match_ans)
     self.server_current_dir = match_ans.groups()[0]
     self.console_log(0,
                      'server\'s root dir is: ' + self.server_current_dir)
     return
Esempio n. 10
0
 def pause_or_continue(self, *args, **kwargs):
     if self.session.TRANSMITTING:
         # 正在传输,意味着要停止
         self.session.stop_trans()
         self.downloading_btn.setText('Continue')
     else:
         # 停止了,意味着要继续
         self.session.continue_transmit()
         if self.session.trans_status == self.session.TRANS_DOWN_STOP:
             self.session.download_file(progress_func=self.change_progress_bar, 
                 finish_func=self.finish_transmit)
         elif self.session.trans_status == self.session.TRANS_UP_STOP:
             self.session.upload_file(progress_func=self.change_progress_bar, 
                 finish_func=self.finish_transmit)
         else:
             raise InternalError('wrong in widget')
         self.downloading_btn.setText('Pause')
Esempio n. 11
0
    def upload_file(self,
                    name='',
                    size=0,
                    progress_func=None,
                    finish_func=None):
        if self.trans_status == self.TRANS_NO_TASK:
            # 开启一个新上传任务
            self.current_upload['name'] = name
            self.current_upload['size'] = size
            self.trans_size = 0
            local_file = open(name, 'rb')
        elif self.trans_status == self.TRANS_UP_STOP:
            # 继续上传文件
            name = self.current_upload['name']
            size = self.current_upload['size']
            local_file = open(name, 'rb')
            local_file.seek(self.trans_size)
        else:
            return

        # enter mode
        if self.trans_mode == self.MODE_PORT:
            self.data_port()
        else:
            self.data_pasv()

        basename, filename = os.path.split(name)
        self.send_msg('STOR ' + filename)

        code = self.get_res_code(self.expect_respond())
        if code != 150:
            raise InternalError('Server rejected STOR, see command for info')

        # 创建进程开始下载
        self.up_thread = uploadThread(self.data_sock,
                                      local_file,
                                      self.BUFF_SIZE,
                                      size,
                                      progress_func=progress_func,
                                      finish_func=finish_func,
                                      have_done=self.trans_size)
        self.up_thread.start()
        self.TRANSMITTING = True
        self.trans_status = self.TRANS_UP_GOING
        self.console_log(0, 'begin uploading')
Esempio n. 12
0
    def download_file(self,
                      name='',
                      size=0,
                      progress_func=None,
                      finish_func=None):
        if self.trans_status == self.TRANS_NO_TASK:
            # 开启一个新下载任务
            self.current_download['name'] = name
            self.current_download['size'] = size
            self.trans_size = 0
            local_file = open(os.path.join(self.root_directory, name), 'wb')
        elif self.trans_status == self.TRANS_DOWN_STOP:
            # 继续下载文件
            name = self.current_download['name']
            size = self.current_download['size']
            local_file = open(os.path.join(self.root_directory, name), 'ab+')
        else:
            return

        # enter mode
        if self.trans_mode == self.MODE_PORT:
            self.data_port()
        else:
            self.data_pasv()
        self.send_msg('RETR ' + name)
        code = self.get_res_code(self.expect_respond())
        if code != 150:
            raise InternalError('Server rejected RETR, see command for info')

        # 创建进程开始下载
        self.down_thread = downloadThread(self.data_sock,
                                          local_file,
                                          self.BUFF_SIZE,
                                          size,
                                          progress_func=progress_func,
                                          finish_func=finish_func,
                                          have_done=self.trans_size)
        self.down_thread.start()
        self.TRANSMITTING = True
        self.trans_status = self.TRANS_DOWN_GOING
        self.console_log(0, 'begin downloading')
Esempio n. 13
0
def parse_file_info(file_str):
    '''
    解析形如
    -rw-r--r--    1 1000     121       5689110 Oct 31 13:54 bbb.pdf
    格式的字符串
    返回json字典,type、size、name字段分别表示:类型,大小,名字
    '''
    file_re = re.compile('^(\S*)\s*\S*\s*\S*\s*\S*\s*(\S*)\s*\S*\s*\S*\s*\S*\s*(.*)$')
    match_ans = file_re.match(file_str)
    if len(match_ans.groups()) < 3:
        raise InternalError('parse file info accept wrong input: ' + file_str)
    
    info = {}
    if match_ans.groups()[0][0] == 'd':
        info['type'] = FILE_INFO_DIR
    else:
        info['type'] = FILE_INFO_FILE
    
    info['size'] = int(match_ans.groups()[1])
    info['name'] = match_ans.groups()[2]
    return info