求个完美的文件夹校验正则

2020-02-16 16:18:17 +08:00
 lolizeppelin
if WINDOWS:
    if IS_WINDOWS_LINUX_SUBSYSTEM:
        DIRECTORY_REGEX = '^/[a-z](/([0-9a-z_.]+?[0-9a-z_.-]*){1,}){0,}$'
    else:
        DIRECTORY_REGEX = '^[a-z]:(\\\\([0-9a-z_.]+?[0-9a-z_.-]*){1,}){0,}$'
else:
    DIRECTORY_REGEX = '(/([0-9a-zA-Z_.]+?[0-9a-zA-Z_.-]*){1,}){1,}$'

上面的基本校验没问题...

但是没办法避免相对路径比如../ 做法是禁止出现斜杠后有../和./ 我以前写过一个类似的文件名校验的

PATHPATTERN = r'^[A-Za-z0-9]+?(?!.*?/[\.]{1,}/)([A-Za-z0-9\.\-_/])+?[A-Za-z0-9]+?$'

然后我现在看不懂了...求个最优的写法 orz

4517 次点击
所在节点    程序员
19 条回复
jaynos
2020-02-16 16:27:47 +08:00
这是在校验是否有权限访问某个目录么?换个思路,可以直接拿着这个路径取得绝对路径,这样判断就简单了。
lolizeppelin
2020-02-16 16:31:39 +08:00
@jaynos
配置文件模块只支持正则校验, 用访问目录校验就得在具体业务代码里做了

就是希望在配置文件模块里通过正则做完校验,这样更通用一点
imn1
2020-02-16 17:01:54 +08:00
没有完美的,如果不是实例检验的话,就是一个字符串
测一下有没有非法字符,有没有路径符,仅此而已
zhijiansha
2020-02-16 18:05:02 +08:00
(?!.*?\.+/) 禁止路径中出现../ ./,可以加在你上面的那些正则表达式的前面
ysc3839
2020-02-16 18:25:52 +08:00
用 lexically normalize 可以去掉 ../ 和 ./ 这种相对路径。
AX5N
2020-02-16 20:20:43 +08:00
你的意思是只能根据一段字串符来判断这段字串符是否是目录? 我觉得做不到,比如文件夹也可以起名为“a.exe”
nightwitch
2020-02-16 20:42:24 +08:00
应该放到业务代码里去校验。采用文本的方法去匹配就像打地鼠一样,总能出现匹配不上的情况。
azh7138m
2020-02-16 20:44:47 +08:00
提供一个 case
'/😀'
再来一个
'/ b' (b 前面有个空格)
raysonx
2020-02-16 20:54:31 +08:00
Linux 系统下只有两个字符不能用作文件名,一个是路径分割符 /,另一个是 NUL (\0 )。
MrUser
2020-02-16 22:20:55 +08:00
只能通过判断是否包含有路径禁止使用的符号来实现了吧?
路径中可以有 .. 比如下图:
https://s2.ax1x.com/2020/02/16/39w2B6.png
Buges
2020-02-16 22:31:10 +08:00
你应该仿照系统处理路径的思路去处理。
lolizeppelin
2020-02-17 12:07:54 +08:00
@zhijiansha
谢谢...就是这个,比我之前处理文件名的那个写法好

我发现我之前也用了环视处理文件名,但是现在已经看不懂了 2333
ceyes
2020-02-17 15:41:47 +08:00
X-Y Problem 又叫“过早下结论”:提问者其实并不非常清楚想要解决的 X 问题,他猜测用 Y 可以搞定,于是他问大家如何实现 Y。

Ref: https://coolshell.cn/articles/10804.html


所以楼主真正想解决的是什么问题呢?
no1xsyzy
2020-02-17 15:51:44 +08:00
第一,有什么阻止相对路径的必要?如果哪个程序不让我用相对路径我多半会骂娘
第二,阻止相对路径建议添加反判断 r"/\.\./" 和 r"/\./",正反判断组合能够让正则效率和可读性同时提升不少。
第三,不行就找 r"(/[^.].*|.[^.].*|\.\..+)+/?" 找出“第一个字符不是 . 的”、“第二个字符不是 . 的”、“前两个字符都是 . 但还有更多内容的”
括号内对应 if 就是:
if len(s)>=1 and s[0] != ".": return True
if len(s)>=2 and s[1] != ".": return True
if len(s)>=3: return True
lolizeppelin
2020-02-17 18:16:17 +08:00
@ceyes

1.配置文件模块只支持字符串做正字校验
2.尽量在配置模块中避免用户输入相对路径(并尽量保证路径字符串正确)
这样应用可以直接拼写路径而不用做一次转换

通过非正则方式校验简单.但是要在配置文件模块以外做
用正则就是为了在配置文件模块部分校验字符串而不是让后面应用做

oslo config 的配置提供了多种 opt,如果需要可以自己创建文件夹类型 opt 以及对应校验
但是这样需要载入自己的 class,所以才直接用了 StringOpt 加正则来做

https://github.com/openstack/oslo.config/blob/master/oslo_config/cfg.py


@no1xsyzy
1.配置文件里路径绝对路径安全避免问题,又不是命令行工具次次要你输一长串
2.IDE 里用 r 有警告提示看着烦
3.oslo config 不支持直接传入校验函数,需要集成重写,原因上面也说了
no1xsyzy
2020-02-17 18:42:58 +08:00
@lolizeppelin
1. 配置文件要求更高,我认为包括 ~ 都需要正确响应。
2. 这是什么鬼 IDE 用 r 有警告的?还是 lint 配置没配置好?(注意:大部分语言的大部分 linter 的默认配置是垃圾,比如 pylint 默认配置不符合 pep-20,请复制别人或者大公司的现成配置,自己配能有多个项目用得上也行)另外,我认为所有的正则都**必须**加 r,无论其中是否用到反斜杠,本来 r-string 语法一定程度上就是为了正则才加的,并且也是一个显著视觉标记,最重要的是,VS Code 里加了 r 的话代码高亮也会按正则来。
3. 我是在用 if 描述 r"(/[^.].*|.[^.].*|\.\..+)+/?"。你可能不知道:正则表达式的实质是 if 语句和一种非无限递归的混合;
4. 我不认为有必要在配置文件模块中确认配置无误,尤其在此配置业务层还会再验证一遍的情况下,唯一的例外是需要错误信息前置。
5. tips: 看不懂自己曾经写的正则的问题可以靠 re.VERBOSE 解决
no1xsyzy
2020-02-17 19:23:23 +08:00
lolizeppelin
2020-02-17 21:34:47 +08:00
配置文件是字符串.没必要在配置文件部分确保他表达的对象正确
比如说一个动态加载的 backend, 你只要在配置里确保这个 backend 的字符串符合你自己定义的规范就可以
而不需要确保这个 backend 确实存在

同样我的 path 是否正确配置文件层面我只要确定 path 的字符串的正确性符合我的规范就是

因为配置文件代码最先执行,当然会前置错误信息....否则报错得到具体 api 调用的时候了

需求这个正则是因为路径最后要和 url 资源路径对应
配置文件层我就可以通过正则避免相对路径导致可能的越界
这样业务层就不用再检查路径问题了,只要处理 io 错误而不用每次都要调用一次转绝对路径函数


正则这个 if 我确实不知道,因为不是很喜欢写正则,今天会了过两天就忘记了,脑壳痛
no1xsyzy
2020-02-18 20:05:50 +08:00
@lolizeppelin
我看了下 oslo.config 好像没有前置错误信息(注意连错误信息内容都需要前置),仅仅是时间上提前。
也就是说,发生以下两种操作不一致:
1. 输入 `/something/../something/` 提示配置错误
2. 输入 `/something/.../something/` 没有提示配置错误,但访问相应 API 时发生错误
第二种更加 insane,但却透过了前一层 sanity 过滤器。
另外,指望正则检查越界感觉挺不稳妥的。且问下,用户是否有文件系统控制权?如果有,那么可以构造指向 / 的符号链接来跳过。如果没有,那么让用户任意输入一个路径就显得比较诡异。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/645024

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX