Skip to content

Commit 90c43fb

Browse files
authored
Merge pull request #5 from cmaglie/backslashes-of-hell
Support buggy .zips containing backslashes in the filename
2 parents b8419e6 + f3205c2 commit 90c43fb

3 files changed

Lines changed: 35 additions & 1 deletion

File tree

extract.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"io/ioutil"
3838
"os"
3939
"path/filepath"
40+
"strings"
4041

4142
filetype "github.com/h2non/filetype"
4243
"github.com/h2non/filetype/types"
@@ -245,6 +246,15 @@ func Zip(ctx context.Context, body io.Reader, location string, rename Renamer) e
245246
}
246247

247248
path := header.Name
249+
250+
// Replace backslash with forward slash. There are archives in the wild made with
251+
// buggy compressors that use backslash as path separator. The ZIP format explicitly
252+
// denies the use of "\" so we just replace it with slash "/".
253+
// Moreover it seems that folders are stored as "files" but with a final "\" in the
254+
// filename... oh, well...
255+
forceDir := strings.HasSuffix(path, "\\")
256+
path = strings.Replace(path, "\\", "/", -1)
257+
248258
if rename != nil {
249259
path = rename(path)
250260
}
@@ -257,7 +267,7 @@ func Zip(ctx context.Context, body io.Reader, location string, rename Renamer) e
257267
info := header.FileInfo()
258268

259269
switch {
260-
case info.IsDir():
270+
case info.IsDir() || forceDir:
261271
if err := os.MkdirAll(path, info.Mode()|os.ModeDir|100); err != nil {
262272
return errors.Annotatef(err, "Create directory %s", path)
263273
}

extract_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,30 @@ var ExtractCases = []struct {
147147
"/archive/folder/file1.txt": "folder/File1",
148148
"/archive/folderlink": "link",
149149
}},
150+
151+
{"standard zip with backslashes", "testdata/archive-with-backslashes.zip", nil, Files{
152+
"": "dir",
153+
"/AZ3166": "dir",
154+
"/AZ3166/libraries": "dir",
155+
"/AZ3166/libraries/AzureIoT": "dir",
156+
"/AZ3166/libraries/AzureIoT/keywords.txt": "Azure",
157+
"/AZ3166/cores": "dir",
158+
"/AZ3166/cores/arduino": "dir",
159+
"/AZ3166/cores/arduino/azure-iot-sdk-c": "dir",
160+
"/AZ3166/cores/arduino/azure-iot-sdk-c/umqtt": "dir",
161+
"/AZ3166/cores/arduino/azure-iot-sdk-c/umqtt/src": "dir",
162+
}},
163+
{"shift zip with backslashes", "testdata/archive-with-backslashes.zip", shift, Files{
164+
"": "dir",
165+
"/libraries": "dir",
166+
"/libraries/AzureIoT": "dir",
167+
"/libraries/AzureIoT/keywords.txt": "Azure",
168+
"/cores": "dir",
169+
"/cores/arduino": "dir",
170+
"/cores/arduino/azure-iot-sdk-c": "dir",
171+
"/cores/arduino/azure-iot-sdk-c/umqtt": "dir",
172+
"/cores/arduino/azure-iot-sdk-c/umqtt/src": "dir",
173+
}},
150174
}
151175

152176
func TestArchiveFailure(t *testing.T) {
403 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)