【山大智云开发日志】seafdav分析(8)

2021SC@SDUSC

本周继续分析剩余零散的代码

error_printer.py是WSGI中间件捕获应用程序抛出的DAVErrors并返回适当的响应。该文件中只包含一个名为ErrorPrinter的类。

ErrorPrinter主要代码集中在函数def __call__(self, environ, start_response)中。主要用来捕获DAVError和non-DAVError类错误。

代码及其注释

#拦截start_response
        sub_app_start_response = util.SubAppStartResponse()

        try:
            try:
                #request_server app可能是一个生成器(例如GET处理程序),所以我们必须迭代-而不 
  #是    返回self.next_app(..)!否则,我们无法在这里捕获异常。
                response_started = False
                app_iter = self.next_app(environ, sub_app_start_response)
                for v in app_iter:
                    # Start response (the first time)
                    if not response_started:
                        # Success!
                        start_response(
                            sub_app_start_response.status,
                            sub_app_start_response.response_headers,
                            sub_app_start_response.exc_info,
                        )
                    response_started = True

                    yield v

                # 结束迭代器
                if hasattr(app_iter, "close"):
                    app_iter.close()

                # 启动响应(如果还没有完成)
                if not response_started:
                    # Success!
                    start_response(
                        sub_app_start_response.status,
                        sub_app_start_response.response_headers,
                        sub_app_start_response.exc_info,
                    )

                return
            except DAVError as e:
                _logger.debug("re-raising {}".format(e))
                raise
            except Exception as e:
                # 捕获 non-DAVError异常
                if self.catch_all_exceptions:
                    #捕获所有异常,返回500内部错误
                    # 回溯。Print_exc (10, environ.get("wsgi.errors")或sys.stderr)
                    _logger.error("{}".format(traceback.format_exc(10)))
                    raise as_DAVError(e)
                else:
                    _logger.error(
                        "Caught Exception\n{}".format(traceback.format_exc(10))
                    )
                    # 回溯。sys.stderr print_exc (10)
                    raise

fs_dav_provider.py:实现从文件系统提供资源的DAV提供者。

类:“~ wsgidav.fs_dav_provider。FilesystemProvider实现DAV资源。发布文件系统的提供程序。如果传入' ' readonly=True ' ',写尝试将引发HTTP_FORBIDDEN。这个provider创建了:class:`~wsgidav.fs_dav_provider.FileResource`的实例和:类:“~ wsgidav.fs_dav_provider。表示文件和目录分别。

class FileResource(DAVNonCollection)表示一个现有的DAV资源实例。请参见_DAVResource、DAVNonCollection和FilesystemProvider。

该类中的def get_content函数负责作为阅读流的开放内容。看到DAVResource.get_content ()。

    def get_content(self):
        assert not self.is_collection
        # GC issue 28, 57: if we open in text mode, \r\n is converted to one byte.
        # So the file size reported by Windows differs from len(..), thus
        # content-length will be wrong.
        return open(self._file_path, "rb", BUFFER_SIZE)
 

def begin_write(self, content_type=None):开放内容作为写作流。看到DAVResource.begin_write ()

代码

    def begin_write(self, content_type=None):
        assert not self.is_collection
        if self.provider.readonly:
            raise DAVError(HTTP_FORBIDDEN)
        # _logger.debug("begin_write: {}, {}".format(self._file_path, "wb"))
        # GC issue 57: always store as binary
        return open(self._file_path, "wb", BUFFER_SIZE)

def delete(self):删除此资源或集合(递归)。参考DAVResource.delete ()

代码

    def delete(self):
        if self.provider.readonly:
            raise DAVError(HTTP_FORBIDDEN)
        os.unlink(self._file_path)
        self.remove_all_properties(True)
        self.remove_all_locks(True)

类FolderResource(DAVCollection):表示单个现有文件系统文件夹DAV资源。

请参见_DAVResource、DAVCollection和FilesystemProvider。

def get_member_names(self)函数是该类中的核心代码。其主要功能是

返回直接集合成员名列表(utf-8编码)。

参见DAVCollection.get_member_names()在Windows NT/2k/XP和Unix上,如果path是一个Unicode对象,结果将是一个Unicode对象列表。不可解码的文件名仍将作为字符串对象返回

如果我们不要求unicode,例如Vista可能会返回一个'?'而不是一个特殊字符。这个名字将无法使用

构建一个引用此资源的独特URL。

代码

 def get_member_names(self):
        nameList = []
        # self._file_path is unicode, so os.listdir returns unicode as well
        assert compat.is_unicode(self._file_path)
        for name in os.listdir(self._file_path):
            if not compat.is_unicode(name):
                name = name.decode(sys.getfilesystemencoding())
            assert compat.is_unicode(name)
            # Skip non files (links and mount points)
            fp = os.path.join(self._file_path, name)
            if not os.path.isdir(fp) and not os.path.isfile(fp):
                _logger.debug("Skipping non-file {!r}".format(fp))
                continue
            # name = name.encode("utf8")
            name = compat.to_native(name)
            nameList.append(name)
        return nameList

改文件中第三个核心类class FilesystemProvider(DAVProvider)是一个文件系统提供商。

def _loc_to_file_path(self, path, environ=None):是其主要函数。负责将资源路径转换为unicode绝对文件路径。可选的environ参数可能是有用的,例如在root_folder_path中针对每个用户的子文件夹chroot。

代码

    def _loc_to_file_path(self, path, environ=None):
        root_path = self.root_folder_path
        assert root_path is not None
        assert compat.is_native(root_path)
        assert compat.is_native(path)

        path_parts = path.strip("/").split("/")
        file_path = os.path.abspath(os.path.join(root_path, *path_parts))
        if not file_path.startswith(root_path):
            raise RuntimeError(
                "Security exception: tried to access file outside root: {}".format(
                    file_path
                )
            )

        # Convert to unicode
        file_path = util.to_unicode_safe(file_path)
        return file_path

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值