docs: def files_type(request, fstype=None):
      """Do all processing (directory listing, file downloads) for a given filesystem."""
      try:
          host = Host.objects.get(code=fstype)
      except Host.DoesNotExist:
          messages.error(request, "Could not find host in database.")
          return redirect("files")
  
      if host.available_to_all:
          pass
      elif not host.visible_to(request.user):
          messages.error(request, "You don't have permission to access this host.")
          return redirect("files")
  
      authinfo = get_authinfo(request)
  
      if not authinfo:
          return redirect("{}?next={}".format(reverse("files_auth"), request.get_full_path()))
  
      try:
          sftp = create_session(host.address, authinfo["username"], authinfo["password"])
      except exceptions as e:
          messages.error(request, e)
          error_msg = str(e).lower()
          if "authentication" in error_msg:
              return redirect("files_auth")
          return redirect("files")
      finally:
          # Delete the stored credentials, so they aren't mistakenly used or
          # accessed later.
          del authinfo
  
      if host.directory:
          host_dir = host.directory
          if "{}" in host_dir:
              host_dir = host_dir.format(request.user.username)
          if "{win}" in host_dir:
              host_dir = windows_dir_format(host_dir, request.user)
              try:
                  sftp.chdir(host_dir)
              except exceptions as e:
                  if "NoSuchFile" in "{}".format(e):
                      host_dir = "/"
                      try:
                          sftp.chdir(host_dir)
                      except exceptions as e2:
                          messages.error(request, e)
                          messages.error(request, "Root directory: {}".format(e2))
                          return redirect("files")
                      else:
                          messages.error(request, "Unable to access home folder -- showing root directory instead.")
                  else:
                      messages.error(request, e)
                      return redirect("files")
          else:
              try:
                  sftp.chdir(host_dir)
              except exceptions as e:
                  messages.error(request, e)
                  return redirect("files")
  
      default_dir = normpath(sftp.pwd)
  
      def can_access_path(fsdir):
          return normpath(fsdir).startswith(default_dir)
  
      if "file" in request.GET:
          # Download file
          filepath = request.GET.get("file")
          filepath = normpath(filepath)
          filebase = os.path.basename(filepath)
          filebase_escaped = re.sub(r"[^\w\s\-\.]", "", filebase).strip()
          if can_access_path(filepath):
              try:
                  fstat = sftp.stat(filepath)
              except exceptions as e:
                  messages.error(request, "Unable to access {}: {}".format(filebase, e))
                  return redirect("/files/{}?dir={}".format(fstype, os.path.dirname(filepath)))
  
              if fstat.st_size > settings.FILES_MAX_DOWNLOAD_SIZE:
                  messages.error(request, "Too large to download (>200MB)")
                  return redirect("/files/{}?dir={}".format(fstype, os.path.dirname(filepath)))
  
              tmpfile = tempfile.TemporaryFile(prefix="ion_filecenter_{}_{}".format(request.user.username, filebase_escaped))
              logger.debug(tmpfile)
  
              try:
                  sftp.getfo(filepath, tmpfile)
              except exceptions as e:
                  messages.error(request, e)
                  return redirect("/files/{}?dir={}".format(fstype, os.path.dirname(filepath)))
  
              content_len = tmpfile.tell()
              tmpfile.seek(0)
              chunk_size = 8192
              response = StreamingHttpResponse(FileWrapper(tmpfile, chunk_size), content_type="application/octet-stream")
              response['Content-Length'] = content_len
              response["Content-Disposition"] = "attachment; filename={}".format(filebase_escaped)
              return response
  
      fsdir = request.GET.get("dir")
      if fsdir:
          fsdir = normpath(fsdir)
          if can_access_path(fsdir):
              try:
                  sftp.chdir(fsdir)
              except exceptions as e:
                  messages.error(request, e)
                  return redirect("files")
          else:
              messages.error(request, "Access to the path you provided is restricted.")
              return redirect("/files/{}/?dir={}".format(fstype, default_dir))
  
      if "zip" in request.GET:
          dirbase_escaped = os.path.basename(fsdir)
          dirbase_escaped = slugify(dirbase_escaped)
          tmpfile = tempfile.TemporaryFile(prefix="ion_filecenter_{}_{}".format(request.user.username, dirbase_escaped))
  
          with tempfile.TemporaryDirectory(prefix="ion_filecenter_{}_{}_zip".format(request.user.username, dirbase_escaped)) as tmpdir:
              remote_directories = [fsdir]
              totalsize = 0
              while remote_directories:
                  rd = remote_directories.pop()
                  try:
                      remotelist = sftp.listdir(rd)
                  except PermissionError as e:
                      logger.debug("Exception %s on %s" % (e, rd))
                      continue
                  for item in remotelist:
                      itempath = os.path.join(rd, item)
                      try:
                          fstat = sftp.stat(itempath)
                      except exceptions as e:
                          logger.debug("Could not read %s: %s" % (item, e))
                          continue
  
                      if stat.S_ISDIR(fstat.st_mode):
                          remote_directories.append(itempath)
                          continue
  
                      totalsize += fstat.st_size
                      if totalsize > settings.FILES_MAX_DOWNLOAD_SIZE:
                          messages.error(request, "Too large to download (>200MB)")
                          return redirect("/files/{}?dir={}".format(fstype, os.path.dirname(fsdir)))
  
                      try:
                          localpath = os.path.join(tmpdir, os.path.relpath(rd, fsdir))
                          if not os.path.exists(localpath):
                              os.makedirs(localpath)
                          with open(os.path.join(localpath, item), "wb") as fh:
                              sftp.getfo(itempath, fh)
                      except exceptions as e:
                          logger.debug("Exception %s on %s" % (e, item))
                          continue
  
              with zipfile.ZipFile(tmpfile, "w", zipfile.ZIP_DEFLATED) as zf:
                  for root, dirs, files in os.walk(tmpdir):
                      for f in files:
                          zf.write(os.path.join(root, f), os.path.join(os.path.relpath(root, tmpdir), f))
  
          content_len = tmpfile.tell()
          tmpfile.seek(0)
          chunk_size = 8192
          response = StreamingHttpResponse(FileWrapper(tmpfile, chunk_size), content_type="application/octet-stream")
          response["Content-Length"] = content_len
          if not dirbase_escaped:
              dirbase_escaped = "files"
          response["Content-Disposition"] = "attachment; filename={}".format(dirbase_escaped + ".zip")
          return response
  
      try:
          listdir = sftp.listdir()
      except exceptions as e:
          messages.error(request, e)
          listdir = []
      files = []
      for f in listdir:
          if not f.startswith("."):
              try:
                  fstat = sftp.stat(f)
              except exceptions:
                  # If we can't stat the file, don't show it
                  continue
              files.append({
                  "name": f,
                  "folder": sftp.isdir(f),
                  "stat": fstat,
                  "stat_mtime": datetime.datetime.fromtimestamp(int(fstat.st_mtime or 0)),
                  "too_big": fstat.st_size > settings.FILES_MAX_DOWNLOAD_SIZE
              })
  
      logger.debug(files)
  
      current_dir = normpath(sftp.pwd)  # current directory
      dir_list = current_dir.split("/")
      if len(dir_list) > 1 and len(dir_list[-1]) == 0:
          dir_list.pop()
      parent_dir = "/".join(dir_list[:-1])
  
      if len(parent_dir) == 0:
          parent_dir = "/"
  
      files = sorted(files, key=lambda f: (not f["folder"], f["name"]))
  
      context = {
          "host": host,
          "files": files,
          "current_dir": current_dir,
          "parent_dir": parent_dir if can_access_path(parent_dir) else None,
          "max_download_mb": (settings.FILES_MAX_DOWNLOAD_SIZE / 1024 / 1024)
      }
  
      return render(request, "files/directory.html", context)