@@ -17,40 +17,25 @@ pub mod path_splitting {
17
17
DuplicateFileDirPath ( String ) ,
18
18
}
19
19
20
- fn split_by_separator ( entry_path : & str ) -> Result < impl Iterator < Item = & str > , PathSplitError > {
21
- /* FIXME: The ZIP spec states (APPNOTE 4.4.17) that file paths are in Unix format, and Unix
22
- * filesystems treat a backslash as a normal character. Thus they should be allowed on Unix
23
- * and replaced with \u{fffd} on Windows. */
24
- if entry_path. contains ( '\\' ) {
25
- if entry_path. contains ( '/' ) {
26
- return Err ( PathSplitError :: PathFormat ( format ! (
27
- "path {:?} contained both '\\ ' and '/' separators" ,
28
- entry_path
29
- ) ) ) ;
30
- }
31
- Ok ( entry_path. split ( '\\' ) )
32
- } else {
33
- Ok ( entry_path. split ( '/' ) )
34
- }
35
- }
36
-
37
- /* TODO: consider using crate::unstable::path_to_string() for this--it involves new
38
- * allocations, but that really shouldn't matter for our purposes. I like the idea of using our
39
- * own logic here, since parallel/pipelined extraction is really a different use case than the
40
- * rest of the zip crate, but it's definitely worth considering. */
20
+ /* NB: path_to_string() performs some of this logic, but is intended to coerce filesystems
21
+ * paths into zip entry names, whereas we are processing entry names from a zip archive, so we
22
+ * perform much less error handling. */
41
23
pub ( crate ) fn normalize_parent_dirs < ' a > (
42
24
entry_path : & ' a str ,
43
25
) -> Result < ( Vec < & ' a str > , bool ) , PathSplitError > {
44
- if entry_path. starts_with ( '/' ) || entry_path. starts_with ( '\\' ) {
26
+ /* The ZIP spec states (APPNOTE 4.4.17) that file paths are in Unix format, and Unix
27
+ * filesystems treat a backslash as a normal character. Thus they should be allowed on Unix
28
+ * and replaced with \u{fffd} on Windows. */
29
+ if entry_path. starts_with ( '/' ) {
45
30
return Err ( PathSplitError :: PathFormat ( format ! (
46
- "path {:?} began with '/' or ' \\ ' and is absolute" ,
31
+ "path {:?} began with '/' and is absolute" ,
47
32
entry_path
48
33
) ) ) ;
49
34
}
50
35
let is_dir = is_dir ( entry_path) ;
51
36
52
37
let mut ret: Vec < & ' a str > = Vec :: new ( ) ;
53
- for component in split_by_separator ( entry_path) ? {
38
+ for component in entry_path. split ( '/' ) {
54
39
match component {
55
40
/* Skip over repeated separators "//". We check separately for ending '/' with the
56
41
* `is_dir` variable. */
@@ -139,7 +124,7 @@ pub mod path_splitting {
139
124
let mut cur_dir = & mut base_dir;
140
125
141
126
/* Split entries by directory components, and normalize any non-literal paths
142
- * (e.g. '..', '.', leading '/', repeated '/', similarly for windows '\\' ). */
127
+ * (e.g. '..', '.', leading '/', repeated '/'). */
143
128
let ( all_components, is_dir) = normalize_parent_dirs ( entry_path) ?;
144
129
/* If the entry is a directory by mode, then it does not need to end in '/'. */
145
130
let is_dir = is_dir || data. is_dir_by_mode ( ) ;
@@ -211,10 +196,13 @@ pub mod path_splitting {
211
196
) ;
212
197
assert_eq ! ( normalize_parent_dirs( "./a" ) . unwrap( ) , ( vec![ "a" ] , false ) ) ;
213
198
assert_eq ! ( normalize_parent_dirs( "a/../b/" ) . unwrap( ) , ( vec![ "b" ] , true ) ) ;
214
- assert_eq ! ( normalize_parent_dirs( "a\\ " ) . unwrap( ) , ( vec![ "a" ] , true ) ) ;
199
+ assert_eq ! ( normalize_parent_dirs( "a/ " ) . unwrap( ) , ( vec![ "a" ] , true ) ) ;
215
200
assert ! ( normalize_parent_dirs( "/a" ) . is_err( ) ) ;
216
- assert ! ( normalize_parent_dirs( "\\ a" ) . is_err( ) ) ;
217
- assert ! ( normalize_parent_dirs( "a\\ b/" ) . is_err( ) ) ;
201
+ assert_eq ! ( normalize_parent_dirs( "\\ a" ) . unwrap( ) , ( vec![ "\\ a" ] , false ) ) ;
202
+ assert_eq ! (
203
+ normalize_parent_dirs( "a\\ b/" ) . unwrap( ) ,
204
+ ( vec![ "a\\ b" ] , true )
205
+ ) ;
218
206
assert ! ( normalize_parent_dirs( "a/../../b" ) . is_err( ) ) ;
219
207
assert ! ( normalize_parent_dirs( "./" ) . is_err( ) ) ;
220
208
}
0 commit comments