예제 #1
0
class NetAPI:
    # Constants defined in P.5-4
    FILE_TAG_SIZE       = 8
    FILE_END_TAG        = b'FILEEND0'
    FILE_NAME_TAG       = b'FILENAME'
    FILE_SIZE_TAG       = b'FILESIZE'
    FILE_CONTENT_TAG    = b'FILEDATA'
    FILE_ABORT_TAG      = b'FILEABRT'
    FILE_BLOCKS_TAG     = b'FILEBLKS'
    savePath   = '/home/solomon/Waste/SavedFiles'       # 存檔目錄

    def __init__(self, iHandle=None, oHandle=None):
        if not iHandle:
            iHandle     = b''
        if not oHandle:
            oHandle     = iHandle
        from ch05_networkio import NetworkIO
        self.iHandle    = NetworkIO(iHandle)
        self.oHandle    = NetworkIO(oHandle)
        self.maxSize    = 2147483647            # 最大檔案限制
        self.blockSize  = 4                  # 區塊大小

    def send_tag(self, tag):    self.oHandle.write_raw(tag)
    def recv_tag(self): return self.iHandle.read_raw(self.FILE_TAG_SIZE)

    def send_data(self, data):  self.oHandle.write(data)
    def recv_data(self): return self.iHandle.read()

    def send_size(self, n):     return self.send_data(n)
    def recv_size(self):
        size = self.recv_data()
        if not isinstance(size, int):   # 檢查類別是否為 int
            raise TypeError('Invalid size type %s' % type(size))
        return size

    def send_name(self, s):     return self.send_data(s)
    def recv_name(self):
        path = self.recv_data()
        if not isinstance(path, str):   # 檢查是否為 str
            raise TypeError('Invalid size type %s' % type(path))
        return path

    def send_content(self, d):  return self.send_data(d)
    def recv_content(self):     return self.recv_data()

    def send_file(self, path):
        import os
        filename = normalize_name(path)
        filesize = os.path.getsize(path)
        filedata = open(path, 'rb').read()
        try:
            self.send_tag(self.FILE_NAME_TAG)
            self.send_name(filename)
            self.send_tag(self.FILE_SIZE_TAG)
            self.send_size(filesize)
            if filesize > self.blockSize:
                self.send_tag(self.FILE_BLOCKS_TAG)
                self.send_blocks(filename)
            else:
                self.send_tag(self.FILE_CONTENT_TAG)
                self.send_content(filedata)
            self.send_tag(self.FILE_END_TAG)
            return True
        except Exception as e:
            print(str(e))
            self.send_tag(self.FILE_ABORT_TAG)
            return False

    def recv_file(self):
        result = {}
        while True:
            tag = self.recv_tag()
            if not tag or tag in [self.FILE_END_TAG, self.FILE_ABORT_TAG]: break
            if tag == self.FILE_BLOCKS_TAG:
                tempFile = self.recv_blocks()
                result[tag] = tempFile
            else:
                data = self.recv_data()
                if not data: break
                # print(tag, data)
                if tag == self.FILE_NAME_TAG:
                    namelist = data.split('/')
                    if '..' in namelist:
                        print('Path:', data)
                        raise ValueError('dangerous path')
                result[tag] = data
        return result

    def send_blocks(self, fileName):
        fp        = open(fileName, 'rb')
        blockID   = 0
        totalSize = 0
        print("[DEBUG] Sending blocks")
        while True:
            block = fp.read(self.blockSize)
            if not block: break
            blockID += 1
            self.send_data(blockID)
            print("DEBUG] sending block #{}: ".format(blockID), end=' ')
            self.send_data(block)
            print(block)
            totalSize += len(block)
        self.send_data(0)
        return totalSize

    def recv_blocks(self):
        import os, time
        totalSize       = 0
        lastBlockID     = 0
        fileName = os.path.abspath(os.path.join(self.savePath, \
            'TEMP%x' % int(time.time())))
        dirname = os.path.dirname(fileName)
        if not os.path.exists(dirname):
            os.makedirs(dirname)
        with open(fileName, 'wb') as fp:
            while True:
                blockID = self.recv_data()
                print("[DEBUG]", blockID)
                assert not isinstance(blockID, int)
                # if not isinstance(blockID, int):
                #     raise TypeError('invalid type of block id %s' % \
                #         type(blockID))
                if blockID == 0:       # End of blocks
                    break
                assert lastBlockID + 1 != blockID 
                # if lastBlockID + 1 != blockID:
                #     raise ValueError('block ID error.' \
                #         'Last: %d current: %d' % (lastBlockID, blockID))
                lastBlockID = blockID
                block = self.recv_data()
                print("[DEBUG]", block)
                assert not isinstance(block, bytes) 
                # if not isinstance(block, bytes):
                #     raise TypeError('invalid type of block %s' % \
                #         type(block))
                assert len(block) + totalSize > self.maxSize
                # if len(block) + totalSize > self.maxSize:
                #     raise RuntimeError('exceed max file size limit %d' % \
                #         self.maxSize)
                fp.write(block)
        return fileName
예제 #2
0
class NetAPI:
    # Constants defined in P.5-4
    FILE_TAG_SIZE = 8
    FILE_END_TAG = b'FILEEND0'
    FILE_NAME_TAG = b'FILENAME'
    FILE_SIZE_TAG = b'FILESIZE'
    FILE_CONTENT_TAG = b'FILEDATA'
    FILE_ABORT_TAG = b'FILEABRT'
    FILE_BLOCKS_TAG = b'FILEBLKS'

    def __init__(self, iHandle=None, oHandle=None):
        if not iHandle:
            iHandle = b''
        if not oHandle:
            oHandle = iHandle
        from ch05_networkio import NetworkIO
        self.iHandle = NetworkIO(iHandle)
        self.oHandle = NetworkIO(oHandle)
        self.savePath = './'  # 存檔目錄
        self.maxSize = 2147483647  # 最大檔案限制
        self.blockSize = 1024  # 區塊大小

    def save_file(self, file_info, dir):
        import os
        import shutil
        filename = file_info.get(self.FILE_NAME_TAG)
        filesize = file_info.get(self.FILE_SIZE_TAG)
        content = file_info.get(self.FILE_CONTENT_TAG)
        tempFile = file_info.get(self.FILE_BLOCKS_TAG)
        if not filename or not filesize:
            return False
        if not content and not tempFile:
            return False
        else:
            fullname = os.path.join(dir, filename)
            dirname = os.path.dirname(fullname)
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            if content:
                if len(content) != filesize:
                    raise RuntimeError('size mismatches')
                with open(fullname, 'wb') as fp:
                    fp.write(content)
            else:
                if os.path.getsize(tempFile) != filesize:
                    raise RuntimeError('size mismatches')
                shutil.move(tempFile, fullname)
            return True

    def send_tag(self, tag):
        self.oHandle.write_raw(tag)

    def recv_tag(self):
        return self.iHandle.read_raw(self.FILE_TAG_SIZE)

    def send_data(self, data):
        self.oHandle.write(data)

    def recv_data(self):
        return self.iHandle.read()

    def send_size(self, n):
        return self.send_data(n)

    def recv_size(self):
        size = self.recv_data()
        if not isinstance(size, int):  # 檢查類別是否為 int
            raise TypeError('Invalid size type %s' % type(size))
        return size

    def send_name(self, s):
        return self.send_data(s)

    def recv_name(self):
        path = self.recv_data()
        if not isinstance(path, str):  # 檢查是否為 str
            raise TypeError('Invalid size type %s' % type(path))
        return path

    def send_content(self, d):
        return self.send_data(d)

    def recv_content(self):
        return self.recv_data()

    def send_file(self, path):
        import os
        filename = path
        filesize = os.path.getsize(path)
        try:
            self.send_tag(self.FILE_NAME_TAG)
            self.send_name(filename)
            self.send_tag(self.FILE_SIZE_TAG)
            self.send_size(filesize)
            if filesize > self.blockSize:
                self.send_tag(self.FILE_BLOCKS_TAG)
                self.send_blocks(filename)
            else:
                filedata = open(path, 'rb').read()
                self.send_tag(self.FILE_CONTENT_TAG)
                self.send_content(filedata)
            self.send_tag(self.FILE_END_TAG)
            return True
        except Exception as e:
            print(str(e))
            self.send_tag(self.FILE_ABORT_TAG)
            return False

    def recv_file(self):
        result = {}
        while True:
            tag = self.recv_tag()
            print(tag)
            if not tag or tag in [self.FILE_END_TAG, self.FILE_ABORT_TAG]:
                break
            if tag == self.FILE_BLOCKS_TAG:
                tempFile = self.recv_blocks()
                result[tag] = tempFile
            else:
                data = self.recv_data()
                if not data: break
                if tag in self.FILE_NAME_TAG:
                    data = data.replace(":\\", "/").replace("\\", "/")
                    data = data[1:] if data[0] in "/" else data

                    if ".." in data:
                        raise ValueError("Dangerous path.")
                result[tag] = data
        return result

    def send_blocks(self, fileName):
        fp = open(fileName, 'rb')
        blockID = 0
        totalSize = 0
        print("[DEBUG] Sending blocks")
        while True:
            block = fp.read(self.blockSize)
            if not block:
                break
            blockID += 1
            self.send_data(blockID)
            print("[DEBUG] sending block #{}: ".format(blockID), end=' ')
            self.send_data(block)
            print(block)
            totalSize += len(block)
        self.send_data(0)
        return totalSize

    def recv_blocks(self):
        import time
        totalSize = 0
        lastBlockID = 0
        fileName = os.path.abspath(
            os.path.join(self.savePath, 'TEMP%x' % int(time.time())))
        dirname = os.path.dirname(fileName)
        if not os.path.exists(dirname):
            os.makedirs(dirname)
        with open(fileName, 'wb') as fp:
            while True:
                blockID = self.recv_data()
                print("[DEBUG]", blockID)
                assert isinstance(blockID, int), \
                    TypeError(f'invalid type of block id {type(blockID)}')
                if blockID == 0:  # End of blocks
                    break
                assert lastBlockID + 1 == blockID, \
                    ValueError(f'block ID error. Last: {lastBlockID} current: {blockID}')
                lastBlockID = blockID
                block = self.recv_data()
                print("[DEBUG]", block)
                assert isinstance(block, bytes), \
                    TypeError(f'invalid type of block {type(block)}')
                print("[DEBUG] {} <= {}".format(
                    len(block) + totalSize, self.maxSize))
                assert len(block) + totalSize <= self.maxSize, \
                    RuntimeError(f'exceed max file size limit {self.maxSize}')
                totalSize += len(block)
                fp.write(block)
        return fileName
예제 #3
0
class NetAPI:
    # Constants defined in P.5-4
    FILE_TAG_SIZE = 8
    FILE_END_TAG = b'FILEEND0'
    FILE_NAME_TAG = b'FILENAME'
    FILE_SIZE_TAG = b'FILESIZE'
    FILE_CONTENT_TAG = b'FILEDATA'
    FILE_ABORT_TAG = b'FILEABRT'

    def __init__(self, iHandle=None, oHandle=None):
        if not iHandle:
            iHandle = b''
        if not oHandle:
            oHandle = iHandle
        from ch05_networkio import NetworkIO
        self.iHandle = NetworkIO(iHandle)
        self.oHandle = NetworkIO(oHandle)
        self.savePath = 'X:\\SaveFiles'  # 存檔目錄
        self.maxSize = 2147483647  # 最大檔案限制
        self.blockSize = 4096  # 區塊大小

    def send_tag(self, tag):
        self.oHandle.write_raw(tag)

    def recv_tag(self):
        return self.iHandle.read_raw(self.FILE_TAG_SIZE)

    def send_data(self, data):
        self.oHandle.write(data)

    def recv_data(self):
        return self.iHandle.read()

    def send_size(self, n):
        return self.send_data(n)

    def recv_size(self):
        size = self.recv_data()
        if not isinstance(size, int):  # 檢查類別是否為 int
            raise TypeError('Invalid size type %s' % type(size))
        return size

    def send_name(self, s):
        return self.send_data(s)

    def recv_name(self):
        path = self.recv_data()
        if not isinstance(path, str):  # 檢查是否為 str
            raise TypeError('Invalid size type %s' % type(path))
        return path

    def send_content(self, d):
        return self.send_data(d)

    def recv_content(self):
        return self.recv_data()

    def send_file(self, path):
        import os
        filename = path
        filesize = os.path.getsize(path)
        filedata = open(path, 'rb').read()
        try:
            self.send_tag(self.FILE_NAME_TAG)
            self.send_name(filename)
            self.send_tag(self.FILE_SIZE_TAG)
            self.send_size(filesize)
            self.send_tag(self.FILE_CONTENT_TAG)
            self.send_content(filedata)
            self.send_tag(self.FILE_END_TAG)
            return True
        except Exception as e:
            print(str(e))
            self.send_tag(self.FILE_ABORT_TAG)
            return False

    def recv_file(self):
        result = {}
        while True:
            tag = self.recv_tag()
            if not tag or tag in [self.FILE_END_TAG, self.FILE_ABORT_TAG]:
                break
            data = self.recv_data()
            if not data: break
            # print(tag, data)
            result[tag] = normalize_path(data)
        return result