File tree 2 files changed +82
-0
lines changed 2 files changed +82
-0
lines changed Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ import (
11
11
"hash"
12
12
"hash/crc32"
13
13
"io"
14
+ "unicode/utf8"
14
15
)
15
16
16
17
// TODO(adg): support zip file comments
@@ -201,6 +202,20 @@ func (w *Writer) Create(name string) (io.Writer, error) {
201
202
return w .CreateHeader (header )
202
203
}
203
204
205
+ func hasValidUTF8 (s string ) bool {
206
+ n := 0
207
+ for _ , r := range s {
208
+ // By default, ZIP uses CP437, which is only identical to ASCII for the printable characters.
209
+ if r < 0x20 || r >= 0x7f {
210
+ if ! utf8 .ValidRune (r ) {
211
+ return false
212
+ }
213
+ n ++
214
+ }
215
+ }
216
+ return n > 0
217
+ }
218
+
204
219
// CreateHeader adds a file to the zip file using the provided FileHeader
205
220
// for the file metadata.
206
221
// It returns a Writer to which the file contents should be written.
@@ -221,6 +236,10 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
221
236
222
237
fh .Flags |= 0x8 // we will write a data descriptor
223
238
239
+ if hasValidUTF8 (fh .Name ) || hasValidUTF8 (fh .Comment ) {
240
+ fh .Flags |= 0x800 // filename or comment have valid utf-8 string
241
+ }
242
+
224
243
fh .CreatorVersion = fh .CreatorVersion & 0xff00 | zipVersion20 // preserve compatibility byte
225
244
fh .ReaderVersion = zipVersion20
226
245
Original file line number Diff line number Diff line change @@ -87,6 +87,69 @@ func TestWriter(t *testing.T) {
87
87
}
88
88
}
89
89
90
+ func TestWriterUTF8 (t * testing.T ) {
91
+ var utf8Tests = []struct {
92
+ name string
93
+ comment string
94
+ expect uint16
95
+ }{
96
+ {
97
+ name : "hi, hello" ,
98
+ comment : "in the world" ,
99
+ expect : 0x8 ,
100
+ },
101
+ {
102
+ name : "hi, こんにちわ" ,
103
+ comment : "in the world" ,
104
+ expect : 0x808 ,
105
+ },
106
+ {
107
+ name : "hi, hello" ,
108
+ comment : "in the 世界" ,
109
+ expect : 0x808 ,
110
+ },
111
+ {
112
+ name : "hi, こんにちわ" ,
113
+ comment : "in the 世界" ,
114
+ expect : 0x808 ,
115
+ },
116
+ }
117
+
118
+ // write a zip file
119
+ buf := new (bytes.Buffer )
120
+ w := NewWriter (buf )
121
+
122
+ for _ , test := range utf8Tests {
123
+ h := & FileHeader {
124
+ Name : test .name ,
125
+ Comment : test .comment ,
126
+ Method : Deflate ,
127
+ }
128
+ w , err := w .CreateHeader (h )
129
+ if err != nil {
130
+ t .Fatal (err )
131
+ }
132
+ w .Write ([]byte {})
133
+ }
134
+
135
+ if err := w .Close (); err != nil {
136
+ t .Fatal (err )
137
+ }
138
+
139
+ // read it back
140
+ r , err := NewReader (bytes .NewReader (buf .Bytes ()), int64 (buf .Len ()))
141
+ if err != nil {
142
+ t .Fatal (err )
143
+ }
144
+ for i , test := range utf8Tests {
145
+ got := r .File [i ].Flags
146
+ t .Logf ("name %v, comment %v" , test .name , test .comment )
147
+ if got != test .expect {
148
+ t .Fatalf ("Flags: got %v, want %v" , got , test .expect )
149
+ }
150
+ }
151
+ }
152
+
90
153
func TestWriterOffset (t * testing.T ) {
91
154
largeData := make ([]byte , 1 << 17 )
92
155
for i := range largeData {
You can’t perform that action at this time.
0 commit comments