zoukankan      html  css  js  c++  java
  • socketserver模块写的一个简单ftp程序

    一坨需求...

    1. 用户加密认证
    2. 允许同时多用户登录
    3. 每个用户有自己的家目录 ,且只能访问自己的家目录
    4. 对用户进行磁盘配额,每个用户的可用空间不同
    5. 允许用户在ftp server上随意切换目录 (cd)
    6. 允许用户查看当前目录下文件 (ls)
    7. 允许上传和下载文件,保证文件一致性(get put)
    8. 文件传输过程中显示进度条
    9. 支持文件的断点续传

    程序实现

    1、README

     1 ### 作者信息
     2     姓名: hexm
     3     email: xiaoming.unix@gmail.com
     4 
     5 ### 实现功能
     6     用户加密认证
     7     允许同时多用户登录
     8     每个用户有自己的家目录 ,且只能访问自己的家目录
     9     对用户进行磁盘配额,每个用户的可用空间不同
    10     允许用户在ftp server上随意切换目录 (cd)
    11     允许用户查看当前目录下文件 (ls)
    12     允许上传和下载文件,保证文件一致性(get put)
    13     文件传输过程中显示进度条
    14     支持文件的断点续传
    15 
    16 ### 代码目录树
    17 ftpserver/
    18     ├── bin
    19     │   └── ftpserver.py
    20     ├── client
    21     │   └── ftp.py
    22     ├── db
    23     │   └── user.db
    24     ├── fstab
    25     ├── inittab
    26     ├── lib
    27     │   ├── common.py
    28     │   ├── __pycache__
    29     │   │   ├── common.cpython-35.pyc
    30     │   │   └── user_lib.cpython-35.pyc
    31     │   └── user_lib.py
    32     ├── src
    33     │   ├── ftpserver.py
    34     │   └── __pycache__
    35     │       └── ftpserver.cpython-35.pyc
    36     └── yum.conf
    37 
    38 ### 功能介绍
    39     默认有一个用户,hexm,密码也是hexm,家目录为/tmp,限额1M,
    40     pwd 查看用户家目录
    41     cd 进入家目录其他目录,并且不能进入其他目录
    42     ls 列出家目录下内容
    43     put 上传文件 支持断点续传
    44     get 下载文件 支持断点续传
    45     bye 退出
    46 
    47 ### 操作步骤
    48   * 启动服务端
    49     python3 ftpserver/bin/ftpserver.py &
    50   * 启动客户端
    51     python3 ftpserver/client/ftp.py hexm@127.0.0.1 21
    52     >> 输入ftp密码:hexm
    53     认证成功
    54 
    55   * ls 列出当前目录内容
    56    列出当前目录内容
    57     ftp> ls
    58     etc/ fstab inittab pip-53mpg1m2-unpack/ pip-poq_f3ob-unpack/ yum.conf
    59    列出某一目录内容
    60     ftp> ls etc
    61     fstab group inittab
    62     ftp> ls /etc
    63     fstab group inittab
    64    显示多个文件详细信息
    65     ftp> ls -l yum.conf fstab
    66     -rw-r--r-- 1 root root 970 11月 20 11:46 /tmp/yum.conf
    67     -rw-r--r-- 1 root root 396 11月 19 19:44 /tmp/fstab
    68 
    69   * cd 进入其他目录
    70    查看当前目录
    71     ftp> pwd
    72     /tmp
    73    进入家目录中/etc目录
    74     ftp> cd /etc
    75     ftp> pwd
    76     /tmp/etc
    77    返回上级目录
    78     ftp> cd ..
    79     ftp> pwd
    80     /tmp
    81 
    82   * 上传文件 支持断点续传
    83    上传bash文件,因为家目录限额为1M,不能上传
    84     ftp> put /bin/bash
    85     磁盘空间不足
    86    上传文件不存在
    87     ftp> put /bin/ifstat
    88     文件不存在
    89    正常上传
    90     ftp> put /etc/fstab
    91     开始上传[/etc/fstab]
    92     ====================================================================================================>100%
    93 
    94   * 下载文件,支持断点续传
    95     发送并校验成功
    96     ftp> get yum.conf
    97     ====================================================================================================>100%
    98   * 退出
    99     ftp> bye
    View Code

    2、目录树

     

     3、bin/ftpserver.py

     1 #!/usr/bin/env python
     2 # coding=utf-8
     3 
     4 import os
     5 import sys 
     6 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
     7 from src import ftpserver as src_server
     8 
     9 if __name__ == '__main__':
    10         src_server.run()
    View Code

    4、src/ftpserver.py

      1 #!/bin/python
      2 # coding=utf-8
      3 
      4 import socketserver
      5 import json
      6 import os
      7 import subprocess
      8 import re
      9 
     10 os.sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
     11 from lib.user_lib import User
     12 from lib.common import bytes_dumps, str_loads, bytes_encoding, str_encoding, getdirsize
     13 
     14 class FtpServer(socketserver.BaseRequestHandler):
     15 
     16     def handle(self):
     17         self.count = 0
     18         while True:
     19             recv_data = self.request.recv(1024)
     20             if len(recv_data) == 0: break
     21             task_data = str_loads(recv_data)
     22             task_action = task_data.get('action')
     23             # 根据客户端命令执行操作
     24             if hasattr(self, task_action):
     25                 func = getattr(self, task_action)
     26                 func(task_data)
     27 
     28     def auth(self, *args, **kwargs):
     29         """
     30         验证用户合法性
     31         param auth_user: 用户名
     32         param auth_pwd: 密码
     33         param ret: 是否验证成功, 结果为True或False
     34         param self.home_path: 用户家目录
     35         param auth_pass_msg: 发送给客户端是否验证成功的信息
     36         """
     37         auth_user = args[0].get('user')
     38         auth_pwd = args[0].get('pwd')
     39         auth = User(auth_user, auth_pwd)
     40         ret = auth.login()
     41         if ret:  # 认证成功获取用户家目录
     42             auth_pass_msg = {"status": "True"}
     43             self.home_path = auth.home_path()
     44             self.limit_home = auth.limit_home()
     45         else:
     46             auth_pass_msg = {"status": "False"}
     47         self.request.send(bytes_dumps(auth_pass_msg))
     48 
     49     def put(self, *args, **kwargs):
     50         file_size = args[0].get('file_size')
     51         file_name = args[0].get('file_name')
     52         md5sum = args[0].get('md5sum')
     53         abs_file = os.path.join(self.home_path, file_name)
     54         if os.path.isfile(abs_file):  # 上传的文件存在
     55             if self._md5sum(abs_file) == md5sum:  #上传的文件md5和本地的一致,不用重新上传
     56                 status_msg = {"status": "same"}
     57                 self.request.send(bytes_dumps(status_msg))
     58             else:  # 不一致断点续传
     59                 server_file_size = os.stat(abs_file).st_size
     60                 status_msg = {"status": "add", "from_size": server_file_size}
     61                 self.request.send(bytes_dumps(status_msg))
     62                 with open(abs_file, 'ab') as f:
     63                     recv_size = server_file_size
     64                     while recv_size < file_size:
     65                         data = self.request.recv(4096)
     66                         f.write(data)
     67                         recv_size += len(data)
     68         else:  #上传文件不存在,开始写入
     69             # 上传的文件大小加上家目录大小 大于 限制的家目录大小,不允许上传
     70             if getdirsize(self.home_path) + int(file_size) > int(self.limit_home.strip('M')) * 1024 * 1024:  
     71                 status_msg = {"status": "less"}
     72                 self.request.send(bytes_dumps(status_msg))
     73             else:
     74                 status_msg = {"status": "True"}
     75                 self.request.send(bytes_dumps(status_msg))
     76                 with open(abs_file, 'wb') as f:
     77                     recv_size = 0
     78                     while recv_size < file_size:
     79                         data = self.request.recv(4096)
     80                         f.write(data)
     81                         recv_size += len(data)
     82                 request_client_md5 = {"option": "md5"}
     83                 self.request.send(bytes_dumps(request_client_md5))
     84                 md5sum = self._md5sum(abs_file)
     85                 client_md5 = str_loads(self.request.recv(1024))
     86                 if client_md5['md5'] == md5sum:
     87                     check_msg = {"status": "True"}
     88                 else:
     89                     check_msg = {"status": "False"}
     90                 self.request.send(bytes_dumps(check_msg))
     91 
     92     @staticmethod
     93     def _md5sum(filename):
     94         cmd = 'md5sum %s' % filename
     95         ret = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     96         md5sum = ret.stdout.read().split()[0]
     97         return str(md5sum, encoding='utf-8')
     98 
     99     def get(self, *args, **kwargs):
    100         file_name = args[0].get('file_name')
    101         abs_filename = os.path.join(self.home_path, file_name)
    102         if os.path.isfile(abs_filename):
    103 
    104             # 文件存在的话,向客户端发送此文件状态信息
    105             file_size = os.stat(abs_filename).st_size
    106             md5sum = self._md5sum(abs_filename)
    107             status_msg = {"status": "True", "file_size": file_size, "md5sum": md5sum}
    108             self.request.send(bytes_dumps(status_msg))
    109 
    110             # 客户端接收状态信息后,接收客户端回复信息
    111             client_ack_msg = self.request.recv(1024)
    112             client_ack_msg = str_loads(client_ack_msg)
    113             if client_ack_msg["status"] == 'True':  # 客户端没有这个文件,完整下载
    114                 with open(abs_filename, 'rb') as f:
    115                     while True:
    116                         filedata = f.read(4096)
    117                         if not filedata: break
    118                         self.request.send(filedata)
    119                 client_request_md5 = str_loads(self.request.recv(1024))
    120                 if client_request_md5['option'] == 'md5':
    121                     md5sum = self._md5sum(abs_filename)
    122                     md5_msg = {"md5": md5sum}
    123                     self.request.send(bytes_dumps(md5_msg))
    124             elif client_ack_msg['status'] == 'same':  # 客户端和服务端文件相同
    125                 pass
    126             elif client_ack_msg['status'] == 'add':  # 客户端有文件但不完整
    127                 from_size = int(client_ack_msg['from_size'])
    128                 with open(abs_filename, 'rb') as f:
    129                     f.seek(from_size)
    130                     while True:
    131                         filedata = f.read(4096)
    132                         if not filedata: break
    133                         self.request.send(filedata)
    134         else:
    135             status_msg = {"status": "False"}
    136             self.request.send(bytes_dumps(status_msg))
    137 
    138 
    139     def cd(self, *args, **kwargs):
    140         if self.count == 0:
    141             self.tmp_home_path = self.home_path
    142         
    143         cd_dir = args[0].get('cd_dir')
    144         if cd_dir == '/':
    145             self.home_path = self.tmp_home_path
    146             status = {"status": "True"}
    147         elif cd_dir.startswith('/'):
    148             cd_dir = cd_dir[1:]
    149             if os.path.isdir(os.path.join(self.home_path, cd_dir)):
    150                 self.home_path = os.path.join(self.home_path, cd_dir)
    151                 status = {"status": "True"}
    152             else:
    153                 status = {"status": "False"}
    154         elif cd_dir == '':
    155             self.home_path = self.tmp_home_path
    156             status = {"status": "True"}
    157         else:
    158             if os.path.isdir(os.path.join(self.home_path, cd_dir)):
    159                 self.home_path = os.path.join(self.home_path, cd_dir)
    160                 status = {"status": "True"}
    161             else:
    162                 status = {"status": "False"}
    163         status = bytes_dumps(status)
    164         self.request.send(status)
    165 
    166         self.count += 1
    167 
    168     def pwd(self, *args, **kwargs):
    169         cmd = args[0].get('action')
    170         res = subprocess.Popen(cmd, shell=True, cwd=self.home_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    171         cmd_res = res.stdout.read()
    172         cmd_res_len = len(cmd_res)
    173         status_msg = {"status": "ready", "len_ret": cmd_res_len}
    174         self.request.send(bytes_dumps(status_msg))
    175         ack_msg = self.request.recv(1024)
    176         if str_loads(ack_msg).get('status') == 'yes':
    177             self.request.send(cmd_res)
    178 
    179     def ls(self, *args, **kwargs):
    180         cmd = args[0].get('action')
    181         args = args[0].get('args')
    182         if len(args) == 0:
    183             fnames = args = ''
    184         else:
    185             try:
    186                 args, fnames = re.search('(.*-w+ ?)(.*)', args).groups()
    187             except AttributeError as e:
    188                 fnames = args
    189                 args = ''
    190         cmd_res = ''
    191         if len(fnames.strip().split()) > 1:
    192             for i in fnames.strip().split():
    193                 res = subprocess.Popen(cmd + ' ' + args + ' ' + self.home_path + '/' + i, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    194                 cmd_res += str(res.stdout.read(), encoding='utf-8')
    195             cmd_res = bytes(cmd_res, encoding='utf-8')
    196         else: 
    197             res = subprocess.Popen(cmd + ' ' + args + ' ' + self.home_path + '/' + fnames, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    198             cmd_res = res.stdout.read()
    199             if '-l' not in args:
    200                 cmd_res = str(cmd_res, encoding='utf-8')
    201                 tmp = []
    202                 for res in cmd_res.strip().split():
    203                     if os.path.isdir(os.path.join(self.home_path, res)):
    204                         res = res + '/'
    205                     tmp.append(res)
    206                 cmd_res = ' '.join(tmp)
    207                 cmd_res = bytes(cmd_res, encoding='utf-8')
    208 
    209         cmd_res_len = len(cmd_res)
    210         if not cmd_res:
    211             cmd_res = res.stderr.read()
    212             cmd_res_len = len(cmd_res)
    213         status_msg = {"status": "ready", "len_ret": cmd_res_len}
    214         self.request.send(bytes_dumps(status_msg))
    215         ack_msg = self.request.recv(1024)
    216         if str_loads(ack_msg).get('status') == 'yes':
    217             self.request.send(cmd_res)
    218 
    219 
    220     def _bytes_dumps(self, msg_data):
    221         return bytes(json.dumps(msg_data), encoding='utf-8')
    222 
    223     def _str_loads(self, msg_data):
    224         return json.loads(str(msg_data, encoding='utf-8'))
    225 
    226 
    227 def main():
    228     server = socketserver.ThreadingTCPServer(('0.0.0.0', 21), FtpServer)
    229     server.serve_forever()
    230 
    231 
    232 def run():
    233     main()
    234 
    235 
    236 if __name__ == '__main__':
    237     run()
    View Code

    5、client/ftp.py

      1 #!/usr/bin/env python
      2 # coding=utf-8
      3 
      4 import subprocess
      5 import socket
      6 import json
      7 import sys
      8 import os
      9 
     10 os.sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
     11 from lib.common import bytes_dumps, str_loads, bytes_encoding, str_encoding, view_bar
     12 
     13 class FtpClient(object):
     14 
     15     def __init__(self, fuser, fpwd, fip, fport=21):
     16         self.fuser = fuser
     17         self.fpwd = fpwd
     18         self.fip = fip
     19         self.fport = int(fport)
     20         self.s = socket.socket()
     21 
     22 
     23     def connect_socket(self):
     24         self.s.connect((self.fip, self.fport))
     25 
     26 
     27     def auth(self):
     28         auth_msg = {"action": "auth", "user": self.fuser, "pwd": self.fpwd}
     29         self.s.send(bytes(json.dumps(auth_msg), encoding='utf-8'))
     30         server_ack_msg = self.s.recv(1024)
     31         ack_data = json.loads(server_ack_msg.decode())
     32         if ack_data['status'] == 'True':
     33             return True
     34         else:
     35             return False
     36 
     37 
     38     def send_data(self):
     39         while True:
     40             send_data = input('ftp> ')
     41             if len(send_data) == 0:
     42                 continue
     43             cmd_list = send_data.strip().split()
     44             if cmd_list == 0:
     45                 continue
     46             cmd = cmd_list[0]
     47             if hasattr(self, cmd):
     48                 func = getattr(self, cmd)
     49                 func(cmd_list)
     50             else:
     51                 print('--暂时不支持[%s]命令' % cmd)
     52 
     53 
     54     def put(self, *args):
     55         cmd = args[0][0]
     56         abs_filename = args[0][-1]
     57         if os.path.islink(abs_filename):
     58             print('符号链接不能上传')
     59         elif os.path.isfile(abs_filename):
     60             file_size = os.stat(abs_filename).st_size
     61             file_name = os.path.basename(abs_filename)
     62             md5sum = self._md5sum(abs_filename)
     63             msg_data = {"action": cmd, "file_name": file_name, "file_size":file_size, "md5sum": md5sum}
     64             self.s.send(bytes_dumps(msg_data))
     65             server_ack_msg = self.s.recv(1024)
     66             ack_data = str_loads(server_ack_msg)
     67             if ack_data['status'] == 'True':
     68                 print('开始上传[%s]' % abs_filename)
     69                 with open(abs_filename, 'rb') as f:
     70                     send_size = 0
     71                     while True:
     72                         filedata = f.read(8192)
     73                         send_size += len(filedata)
     74                         if not filedata: break
     75                         self.s.send(filedata)
     76                         view_bar(send_size, file_size) 
     77                     sys.stdout.write('
    ')
     78                 server_request_md5 = str_loads(self.s.recv(1024))
     79                 if server_request_md5['option'] == 'md5':
     80                     md5sum = self._md5sum(abs_filename)
     81                     md5_msg = {"md5": md5sum}
     82                     self.s.send(bytes_dumps(md5_msg))
     83                 md5_status = str_loads(self.s.recv(1024))
     84                 if md5_status['status'] == 'True':
     85                     print('发送并校验成功')
     86                 else:
     87                     print('上传文件失败')
     88             elif ack_data['status'] == 'add':
     89                 with open(abs_filename, 'rb') as f:
     90                     send_size = f.seek(ack_data['from_size'])
     91                     print('开始上传[%s]' % abs_filename)
     92                     while True:
     93                         filedata = f.read(8192)
     94                         send_size += len(filedata)
     95                         if not filedata: break
     96                         self.s.send(filedata)
     97                         view_bar(send_size, file_size)
     98                     sys.stdout.write('
    ')
     99                 print('增量上传成功')
    100             elif ack_data['status'] == 'same':
    101                 print('开始上传[%s]' % abs_filename)
    102                 print('====================================================================================================>100%')
    103                 print('发送并校验成功')
    104             elif ack_data['status'] == 'less':
    105                 print('磁盘空间不足')
    106         else:
    107             print('文件不存在')
    108 
    109 
    110     @staticmethod
    111     def _md5sum(filename):
    112         cmd = 'md5sum %s' % filename
    113         ret = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    114         md5sum = ret.stdout.read().split()[0]
    115         return str(md5sum, encoding='utf-8')
    116 
    117 
    118     def get(self, *args, **kwargs):
    119         cmd = args[0][0]
    120         abs_filename = args[0][-1]
    121         file_name = os.path.basename(abs_filename)
    122         msg_data = {"action": cmd, "file_name": file_name}
    123 
    124         self.s.send(bytes_dumps(msg_data))
    125 
    126         server_status_msg = self.s.recv(1024)
    127         status_msg = str_loads(server_status_msg)
    128 
    129         if status_msg['status'] == 'True':  # 如果要下载的文件在服务端存在
    130             file_size = status_msg['file_size']
    131 
    132             if os.path.exists(file_name):
    133                 if self._md5sum(file_name) == status_msg['md5sum']:  # 本地文件和服务端相同,不用重新下载
    134                     ack_msg = {"status": "same"}
    135                     self.s.send(bytes_dumps(ack_msg))
    136                     print('====================================================================================================>100%')
    137                     print('下载并校验成功')
    138                 else:  # 文件存在,但校验和不同,说明没有下载完全
    139                     local_file_size = os.stat(abs_filename).st_size
    140                     ack_msg = {"status": "add", "from_size":local_file_size}
    141                     self.s.send(bytes_dumps(ack_msg))
    142                     with open(file_name, 'ab') as f:
    143                         recv_size = local_file_size
    144                         while recv_size < file_size:
    145                             data = self.s.recv(4096)
    146                             f.write(data)
    147                             recv_size += len(data)
    148                         view_bar(recv_size, file_size) 
    149                     sys.stdout.write('
    ')
    150             else:  # 本地没有这个文件,可以下载
    151                 ack_msg = {"status": "True"}
    152                 self.s.send(bytes_dumps(ack_msg))
    153                 with open(file_name, 'wb') as f:
    154                     recv_size = 0
    155                     while recv_size < file_size:
    156                         data = self.s.recv(4096)
    157                         f.write(data)
    158                         recv_size += len(data)
    159                         view_bar(recv_size, file_size) 
    160                     sys.stdout.write('
    ')
    161                 request_server_md5 = {"option": "md5"}
    162                 self.s.send(bytes_dumps(request_server_md5))
    163                 md5sum = self._md5sum(file_name)
    164                 server_md5 = str_loads(self.s.recv(1024))
    165                 if server_md5['md5'] == md5sum:
    166                     print('下载并校验成功')
    167                 else:
    168                     print('校验失败')
    169         else:
    170             print('服务端没有这个文件')
    171 
    172 
    173     def pwd(self, *args, **kwargs):
    174         if len(args[0]) != 1:
    175             print('错误的参数')
    176         else:
    177             cmd = args[0][0]
    178             msg_data = {"action": cmd}
    179             self.s.send(bytes_dumps(msg_data))
    180             server_ack_msg = self.s.recv(1024)
    181             ack_data = str_loads(server_ack_msg)
    182             if ack_data['status'] == 'ready':
    183                 ack_msg = {"status": "yes"}
    184                 self.s.send(bytes_dumps(ack_msg))
    185                 cmd_recv_size = 0
    186                 cmd_ret = b''
    187                 while cmd_recv_size < ack_data['len_ret']:
    188                     cmd_recv = self.s.recv(1024)
    189                     cmd_ret += cmd_recv
    190                     cmd_recv_size += len(cmd_recv)
    191                 print(str(cmd_ret, encoding='utf-8'))
    192 
    193 
    194     def cd(self, *args, **kwargs):
    195         if len(args[0]) > 2:
    196             print('错误的参数')
    197         elif len(args[0]) == 1:
    198             cmd = args[0][0]
    199             cd_dir = ''
    200         else:
    201             cmd = args[0][0]
    202             cd_dir = args[0][1]
    203         msg_data = {"action": cmd, "cd_dir": cd_dir}
    204         self.s.send(bytes_dumps(msg_data))
    205         status = self.s.recv(1024)
    206         status = str_loads(status)
    207         if status['status'] == 'False':
    208             print('目录不存在')
    209 
    210 
    211     def bye(self, *args, **kwargs):
    212         sys.exit(0)
    213 
    214 
    215     def ls(self, *args):
    216         cmd = args[0][0]
    217         args = ' '.join(args[0][1:])
    218         msg_data = {"action": cmd, "args": args}
    219         self.s.send(bytes_dumps(msg_data))
    220         server_ack_msg = self.s.recv(1024)
    221         ack_data = str_loads(server_ack_msg)
    222         if ack_data['status'] == 'ready':
    223             ack_msg = {"status": "yes"}
    224             self.s.send(bytes_dumps(ack_msg))
    225             cmd_recv_size = 0
    226             cmd_ret = b''
    227             while cmd_recv_size < ack_data['len_ret']:
    228                 cmd_recv = self.s.recv(1024)
    229                 cmd_ret += cmd_recv
    230                 cmd_recv_size += len(cmd_recv)
    231             print(str(cmd_ret, encoding='utf-8'))
    232 
    233 
    234     def help(self, *args, **kwargs):
    235         print('--支持如下命令: ls, cd, pwd, get, put, bye')
    236 
    237 
    238 def main():
    239 
    240     user, ip = sys.argv[1].strip().split('@')
    241     port = sys.argv[2]
    242     pwd = input('>> 输入ftp密码:').strip()
    243 
    244     ftp = FtpClient(user, pwd, ip, port)
    245     ftp.connect_socket()
    246     ret = ftp.auth()
    247     if ret:
    248         print('认证成功')
    249         ftp.send_data()
    250     else:
    251         print('认证失败')
    252         ftp.bye()
    253     ftp.send_data()
    254 
    255 
    256 def run():
    257     main()
    258 
    259 
    260 if __name__ == '__main__':
    261     run()
    View Code

    6、lib/common.py

    #!/usr/bin/env python
    # coding=utf-8
    
    import json
    import sys
    import os
    
    def bytes_dumps( msg_data):
        return bytes(json.dumps(msg_data), encoding='utf-8')
    
    def str_loads(msg_data):
        return json.loads(str(msg_data, encoding='utf-8'))
    
    def bytes_encoding(msg_data):
        return bytes(msg_data, encoding='utf-8')
    
    def str_encoding(msg_data):
        return str(msg_data, encoding='utf-8')
    
    def view_bar(num, total):
        rate = num / total
        rate_num = int(rate * 100)
        r = '
    %s>%d%%' % ("="*rate_num, rate_num, )
        sys.stdout.write(r)
        sys.stdout.flush()
    
    def getdirsize(dir):
        size = 0
        for root, dirs, files in os.walk(dir):
            size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
        return size
    View Code

    7、lib/user_lib.py

    #!/usr/bin/env python
    # coding=utf-8
    
    import hashlib
    import re
    import os
    
    BASEPATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    USERDB = os.path.join(BASEPATH, 'db', 'user.db')
    
    
    class User(object):
        """
        实现登陆注册功能
        """
    
        def __init__(self, user, password):
            self.username = user
            self.password = password
    
        @staticmethod
        def check(match, filedb):
            """
            逐行匹配,查看是否用户名已经注册,不允许重复用户名
            """
            with open(filedb, 'r') as fuser:
                for line in fuser:
                    if re.match(match + '\b', line):
                        return False
                    else:
                        continue
                return True
    
        @staticmethod
        def login_check(username, password, filedb):
            """
            登陆验证
            """
            with open(filedb, 'r') as fuser:
                for line in fuser:
                    user, pwd, _, _ = line.strip().split()
                    if user == username and pwd == password:
                        return True
                    else:
                        continue
                return False
    
    
        def home_path(self):
            """
            返回用户家目录
            """
            with open(USERDB, 'r') as fpath:
                for line in fpath:
                    if line.startswith(self.username):
                        return line.strip().split()[-2]
                    else:
                        continue
                return False
    
        def limit_home(self):
            """
            返回用户家目录限额
            """
            with open(USERDB, 'r') as flimit:
                for line in flimit:
                    if line.startswith(self.username):
                        return line.strip().split()[-1]
                    else:
                        continue
                return False
    
    
        def register(self):
            """
            注册用户
            """
            passobj = hashlib.md5(bytes(self.password, encoding='utf-8'))
            passobj.update(bytes(self.password, encoding='utf-8'))
            secure_password = passobj.hexdigest()
    
            if self.check(self.username, USERDB):
                with open(USERDB, 'a') as fuser:
                    fuser.write(self.username + ' ' + secure_password + '
    ')
                    return True
            else:
                print('用户名已存在')
    
        def login(self):
            """
            用户登陆
            """
            passobj = hashlib.md5(bytes(self.password, encoding='utf-8'))
            passobj.update(bytes(self.password, encoding='utf-8'))
            secure_password = passobj.hexdigest()
            ret = self.login_check(self.username, secure_password, USERDB)
            if ret:
                return True
            else:
                return False
    
        def modify(self):
            """
            修改密码
            """
            pass
    View Code

    8、db/user.db

    hexm 92df47e9074c048e0afe84ce0a5c407d /tmp 1M
    xm 92df47e9074c048e0afe84ce0a5c407d /tmp/sb 5M
    View Code
  • 相关阅读:
    javascript+html5+css3下拉刷新 数据效果
    构建单页Web应用
    移动Web单页应用开发实践——页面结构化
    Vue.js——60分钟快速入门
    我们是如何做好前端工程化和静态资源管理
    基于React Native的58 APP开发实践
    你可能不需要 jQuery!使用原生 JavaScript 进行开发
    京东前端工程化和静态资源管理全面总结
    汇总前端最最常用的JS代码片段-你值得收藏
    PHP安装kafka插件
  • 原文地址:https://www.cnblogs.com/xiaoming279/p/6096208.html
Copyright © 2011-2022 走看看