Symfoware

Symfowareについての考察blog

Python + pyftpdlibでカスタムFTPサーバーを作成2 ディレクトリの表示

pyftpdlibでFTPサーバーをカスタムしてみています。
Python + pyftpdlibでカスタムFTPサーバーを作成1 起動とユーザー認証

Javaでやったときと同様に、仮想のファイルシステムを生み出してみます。
Java + MockFtpServerでFTPサーバー側のプログラムを作成する その2





ダミーのファイルシステム



架空のディレクトリ情報を返す「MyFileSystem」クラスを実装してみます。
最上位のディレクトリを表示するための、最小限のプログラムは以下の通り。


  1. # -*- coding:utf-8 -*-
  2. from pyftpdlib.authorizers import DummyAuthorizer
  3. from pyftpdlib.authorizers import AuthenticationFailed
  4. from pyftpdlib.handlers import FTPHandler
  5. from pyftpdlib.servers import FTPServer
  6. class MyAuthorizer(object):
  7.     
  8.     # ユーザー名、パスワードで認証
  9.     def validate_authentication(self, username, password, handler):
  10.         
  11.         msg = "Authentication failed."
  12.         if username != 'symfo':
  13.             raise AuthenticationFailed(msg)
  14.         
  15.         if password != 'pass':
  16.             raise AuthenticationFailed(msg)
  17.     
  18.     # ユーザーのホームディレクトリを返す
  19.     def get_home_dir(self, username):
  20.         import os
  21.         homedir = '.'
  22.         return os.path.realpath(homedir).decode('utf8')
  23.     
  24.     # アクセス権限チェック
  25.     def has_perm(self, username, perm, path=None):
  26.         return 'elr'
  27.     
  28.     def get_perms(self, username):
  29.         return 'elr'
  30.     
  31.     # ログイン時に表示するメッセージ
  32.     def get_msg_login(self, username):
  33.         return 'Login successful.'
  34.     
  35.     # ログアウト時に表示するメッセージ
  36.     def get_msg_quit(self, username):
  37.         return 'Goodbye.'
  38.         
  39.     # ファイルにアクセスする前のフック
  40.     def impersonate_user(self, username, password):
  41.         pass
  42.     
  43.     # ファイルにアクセスした後のフック
  44.     def terminate_impersonation(self, username):
  45.         pass
  46.         
  47. class MyFileSystem(object):
  48.     
  49.     def __init__(self, root, cmd_channel):
  50.         self._cwd = u'/'
  51.         self._root = root
  52.         self.cmd_channel = cmd_channel
  53.     
  54.     # 現在のカレントディレクトリ
  55.     @property
  56.     def cwd(self):
  57.         return self._cwd
  58.         
  59.     # ftp要求パスをリアルパスに変換
  60.     def ftp2fs(self, ftppath):
  61.         return u'.'
  62.     
  63.     
  64.     # 要求パスの妥当性検証
  65.     def validpath(self, path):
  66.         return True
  67.     
  68.     
  69.     # 指定されたパスがディレクトリであるか
  70.     def isdir(self, path):
  71.         return True
  72.     
  73.     # ディレクトリの内容をリストアップ
  74.     def listdir(self, path):
  75.         # ダミーの内容を返す
  76.         return [u'1', u'2']
  77.     
  78.     # フォーマット済の内容を返す
  79.     def format_mlsx(self, basedir, listing, perms, facts, ignore_err=True):
  80.         
  81.         line = u'type=dir;size=0;perm=el;modify=20071127230206;unique=801e33; 1\r\n'
  82.         yield line.encode('utf8', self.cmd_channel.unicode_errors)
  83.         
  84.         line = u'type=file;size=156;perm=r;modify=20071029155301;unique=8012; 2\r\n'
  85.         yield line.encode('utf8', self.cmd_channel.unicode_errors)
  86.     
  87.     
  88. def main():
  89.     
  90.     # 認証用のオブジェクトを作成
  91.     authorizer = MyAuthorizer()
  92.     # FTP通信のハンドラーを作成 ユーザー認証オブジェクトを設定する
  93.     handler = FTPHandler
  94.     handler.authorizer = authorizer
  95.     # 接続時に表示される文字列指定
  96.     handler.banner = "pyftpdlib based ftpd ready."
  97.     
  98.     # 使用するファイルシステム
  99.     handler.abstracted_fs = MyFileSystem
  100.     # ftpサーバーのポートを指定
  101.     address = ('localhost', 10021)
  102.     server = FTPServer(address, handler)
  103.     # サーバー起動
  104.     server.serve_forever()
  105. if __name__ == '__main__':
  106.     main()




format_mlsxがキモです。
ここでyieldした内容に従い、ディレクトリの内容が表示されます。

キー=値のセットをセミコロン区切りで列挙。
最後にディレクトリやファイル名を指定し、改行コード(\r\n)で終了します。

キーディレクトリファイル
typedirfile
size0ファイルのバイト数
permディレクトリパーミッション(el等)ファイルのパーミッション(r等)
modify作成日付作成日付
uniqueユニークキー(省略可)ユニークキー(省略可)



ちなみに、ディレクトリやファイルのパーミッション指定は以下の通り。


Read permissions:
"e" = change directory (CWD command)
"l" = list files (LIST, NLST, STAT, MLSD, MLST, SIZE, MDTM commands)
"r" = retrieve file from the server (RETR command)

Write permissions:
"a" = append data to an existing file (APPE command)
"d" = delete file or directory (DELE, RMD commands)
"f" = rename file or directory (RNFR, RNTO commands)
"m" = create directory (MKD command)
"w" = store a file to the server (STOR, STOU commands)
"M" = change file mode (SITE CHMOD command)





これでとりあえず実際には存在しないディレクトリやファイルを
仮想的に表示させることが出来ました。

527_01.png

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2015/01/17(土) 21:56:05|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Python + pyftpdlibでカスタムFTPサーバーを作成3 ファイルの取得 | ホーム | Python + pyftpdlibでカスタムFTPサーバーを作成1 起動とユーザー認証>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1584-52a300d6
この記事にトラックバックする(FC2ブログユーザー)