# Path: conpot/core/filesystem.py
# class AbstractFS(WrapFS):
#     def __init__(
#         self,
#         src_path: str,
#         create_mode: int = 0o777,  # Default file system permissions.
#         temp_dir: Union[str, None] = None,
#         identifier: Optional[str] = "__conpot__",
#         auto_clean: Optional[bool] = True,
#         ignore_clean_errors: Optional[bool] = True,
#     ) -> None:
#     def norm_path(self, path):
#     def _initialize_fs(self, src_path: str) -> None:
#     def __str__(self):
#     def users(self):
#     def groups(self):
#     def user_groups(self):
#     def getmeta(self, namespace="standard"):
#     def check_access(self, path=None, user=None, perms=None):
#     def setinfo(self, path, info):
#     def makedir(
#         self,
#         path,  # type: Text
#         permissions=None,  # type: Optional[int]
#         recreate=True,  # type: bool
#     ):
#     def removedir(self, path, rf=True):
#     def remove(self, path):
#     def openbin(self, path, mode="r", buffering=-1, **options):
#     def open(
#         self,
#         path,  # type: Text
#         mode="r",  # type: Text
#         buffering=-1,  # type: int
#         encoding=None,  # type: Optional[Text]
#         newline="",  # type: Text
#         line_buffering=False,  # type: bool
#         **options  # type: Any
#     ):
#     def setbinfile(self, path, file):
#     def move(self, src_path, dst_path, overwrite=False):
#     def copy(self, src_path, dst_path, overwrite=False):
#     def opendir(self, path, factory=SubAbstractFS):
#     def settimes(self, path, accessed=None, modified=None):
#     def getinfo(self, path: str, get_actual: bool = False, namespaces=None):
#     def listdir(self, path):
#     def getfile(self, path, file, chunk_size=None, **options):
#     def __del__(self):
#     def create_jail(self, path):
#     def getcwd(self):
#     def take_snapshot(self):
#     def register_user(self, name: str, uid: int) -> None:
#     def create_group(self, name: str, gid: int) -> None:
#     def add_users_to_group(self, gid: int, uids: List) -> None:
#     def chown(
#         self, fs_path: str, uid: int, gid: int, recursive: Optional[bool] = False
#     ) -> None:
#     def clean(self):
#     def root(self):
#     def stat(self, path):
#     def readlink(self, path):
#     def format_list(self, basedir, listing):
#     def getmtime(self, path):
#     def access(
#         self, path: str, name_or_id: Union[int, str] = None, required_perms: str = None
#     ):
#     def get_permissions(self, path):
#     def chmod(self, path: str, mode: oct, recursive: bool = False) -> None:
#     def mount_fs(
#         self,
#         dst_path: str,
#         fs_url: str = None,
#         owner_uid: Optional[int] = 0,
#         group_gid: Optional[int] = 0,
#         perms: Optional[Union[Permissions, int]] = 0o755,
#     ) -> subfs.SubFS:
#     def __getattribute__(self, attr):
# 
# Path: conpot/protocols/ftp/ftp_utils.py
# class FTPPrivilegeException(FTPException):
#     pass
# 
# Path: conpot/utils/networking.py
# def sanitize_file_name(name, host, port):
#     """
#     Ensure that file_name is legal. Slug the filename and store it onto the server.
#     This would ensure that there are no duplicates as far as writing a file is concerned. Also client addresses are
#     noted so that one can verify which client uploaded the file.
#     :param name: Name of the file
#     :param host: host/client address
#     :param port port/client port
#     :type name: str
#     """
#     return (
#         "("
#         + host
#         + ", "
#         + str(port)
#         + ")-"
#         + datetime.now().strftime("%Y-%m-%d %H:%M:%S")
#         + "-"
#         + slugify(name)
#     )


import socketserver
import gevent
import conpot.core as conpot_core
import logging
import errno
import time
import fs
import os
from conpot.core.filesystem import FilesystemError
from datetime import datetime
from conpot.protocols.ftp.ftp_utils import FTPPrivilegeException
from conpot.utils.networking import sanitize_file_name
from gevent import socket
                                    self.cli_ip,
                                    self.cli_port,
                                )
                            )
                            self.metrics.data_channel_bytes_recv += len(data)
                            self._data_channel_input_q.put(data)
                    # we have received all data. Time to finish this process.
                    # set the writing event to set - so that we can write this data to files.
                    self._data_channel_recv.set()
                    self.respond(b"226 Transfer complete.")
                else:
                    # assume that the read/write event has finished
                    # send a nice resp to the client saying everything has finished.
                    # set the self._data_channel(_recv/_send) markers. This would also wait for read write to finish.
                    self.stop_data_channel(reason="Transfer has completed!.")
            except (socket.error, socket.timeout) as se:
                # TODO: send appropriate response
                # Flush contents of the data channel
                reason = (
                    "connection timed out"
                    if isinstance(se, socket.timeout)
                    else "socket error"
                )
                msg = "Stopping FTP data channel {}:{}. Reason: {}".format(
                    self.cli_ip, self.cli_port, reason
                )
                self.stop_data_channel(abort=True, purge=True, reason=msg)
            except (
                fs.errors.FSError,
                FilesystemError,

# Path: conpot/core/filesystem.py
# class AbstractFS(WrapFS):
#     def __init__(
#         self,
#         src_path: str,
#         create_mode: int = 0o777,  # Default file system permissions.
#         temp_dir: Union[str, None] = None,
#         identifier: Optional[str] = "__conpot__",
#         auto_clean: Optional[bool] = True,
#         ignore_clean_errors: Optional[bool] = True,
#     ) -> None:
#     def norm_path(self, path):
#     def _initialize_fs(self, src_path: str) -> None:
#     def __str__(self):
#     def users(self):
#     def groups(self):
#     def user_groups(self):
#     def getmeta(self, namespace="standard"):
#     def check_access(self, path=None, user=None, perms=None):
#     def setinfo(self, path, info):
#     def makedir(
#         self,
#         path,  # type: Text
#         permissions=None,  # type: Optional[int]
#         recreate=True,  # type: bool
#     ):
#     def removedir(self, path, rf=True):
#     def remove(self, path):
#     def openbin(self, path, mode="r", buffering=-1, **options):
#     def open(
#         self,
#         path,  # type: Text
#         mode="r",  # type: Text
#         buffering=-1,  # type: int
#         encoding=None,  # type: Optional[Text]
#         newline="",  # type: Text
#         line_buffering=False,  # type: bool
#         **options  # type: Any
#     ):
#     def setbinfile(self, path, file):
#     def move(self, src_path, dst_path, overwrite=False):
#     def copy(self, src_path, dst_path, overwrite=False):
#     def opendir(self, path, factory=SubAbstractFS):
#     def settimes(self, path, accessed=None, modified=None):
#     def getinfo(self, path: str, get_actual: bool = False, namespaces=None):
#     def listdir(self, path):
#     def getfile(self, path, file, chunk_size=None, **options):
#     def __del__(self):
#     def create_jail(self, path):
#     def getcwd(self):
#     def take_snapshot(self):
#     def register_user(self, name: str, uid: int) -> None:
#     def create_group(self, name: str, gid: int) -> None:
#     def add_users_to_group(self, gid: int, uids: List) -> None:
#     def chown(
#         self, fs_path: str, uid: int, gid: int, recursive: Optional[bool] = False
#     ) -> None:
#     def clean(self):
#     def root(self):
#     def stat(self, path):
#     def readlink(self, path):
#     def format_list(self, basedir, listing):
#     def getmtime(self, path):
#     def access(
#         self, path: str, name_or_id: Union[int, str] = None, required_perms: str = None
#     ):
#     def get_permissions(self, path):
#     def chmod(self, path: str, mode: oct, recursive: bool = False) -> None:
#     def mount_fs(
#         self,
#         dst_path: str,
#         fs_url: str = None,
#         owner_uid: Optional[int] = 0,
#         group_gid: Optional[int] = 0,
#         perms: Optional[Union[Permissions, int]] = 0o755,
#     ) -> subfs.SubFS:
#     def __getattribute__(self, attr):
# 
# Path: conpot/protocols/ftp/ftp_utils.py
# class FTPPrivilegeException(FTPException):
#     pass
# 
# Path: conpot/utils/networking.py
# def sanitize_file_name(name, host, port):
#     """
#     Ensure that file_name is legal. Slug the filename and store it onto the server.
#     This would ensure that there are no duplicates as far as writing a file is concerned. Also client addresses are
#     noted so that one can verify which client uploaded the file.
#     :param name: Name of the file
#     :param host: host/client address
#     :param port port/client port
#     :type name: str
#     """
#     return (
#         "("
#         + host
#         + ", "
#         + str(port)
#         + ")-"
#         + datetime.now().strftime("%Y-%m-%d %H:%M:%S")
#         + "-"
#         + slugify(name)
#     )


# Path: conpot/protocols/ftp/ftp_base_handler.py
import socketserver
import gevent
import conpot.core as conpot_core
import logging
import errno
import time
import fs
import os
from conpot.core.filesystem import FilesystemError
from datetime import datetime
from conpot.protocols.ftp.ftp_utils import FTPPrivilegeException
from conpot.utils.networking import sanitize_file_name
from gevent import socket

                                    self.cli_ip,
                                    self.cli_port,
                                )
                            )
                            self.metrics.data_channel_bytes_recv += len(data)
                            self._data_channel_input_q.put(data)
                    # we have received all data. Time to finish this process.
                    # set the writing event to set - so that we can write this data to files.
                    self._data_channel_recv.set()
                    self.respond(b"226 Transfer complete.")
                else:
                    # assume that the read/write event has finished
                    # send a nice resp to the client saying everything has finished.
                    # set the self._data_channel(_recv/_send) markers. This would also wait for read write to finish.
                    self.stop_data_channel(reason="Transfer has completed!.")
            except (socket.error, socket.timeout) as se:
                # TODO: send appropriate response
                # Flush contents of the data channel
                reason = (
                    "connection timed out"
                    if isinstance(se, socket.timeout)
                    else "socket error"
                )
                msg = "Stopping FTP data channel {}:{}. Reason: {}".format(
                    self.cli_ip, self.cli_port, reason
                )
                self.stop_data_channel(abort=True, purge=True, reason=msg)
            except (
                fs.errors.FSError,
                FilesystemError,

                FTPPrivilegeException,