Skip to content

Commit e930e39

Browse files
committed
Merge pull request #205 from dduponchel/update_permissions
Update permissions
2 parents d329558 + 3b6c23f commit e930e39

13 files changed

Lines changed: 217 additions & 107 deletions

documentation/api_jszip/file_data.md

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,25 @@ compressionOptions | object | `null` | the options to use when compressing the f
2626
comment | string | null | The comment for this file.
2727
optimizedBinaryString | boolean | `false` | Set to true if (and only if) the input is a "binary string" and has already been prepared with a 0xFF mask.
2828
createFolders | boolean | `false` | Set to true if folders in the file path should be automatically created, otherwise there will only be virtual folders that represent the path to the file.
29-
unixPermissions | object | null | The UNIX permissions of the file, if any.
30-
dosPermissions | object | null | The DOS permissions of the file, if any.
29+
unixPermissions | 16 bits number | null | The UNIX permissions of the file, if any.
30+
dosPermissions | 6 bits number | null | The DOS permissions of the file, if any.
31+
dir | boolean | false | Set to true if this is a directory and content should be ignored.
3132

3233
You shouldn't update the data given to this method : it is kept as it so any
3334
update will impact the stored data.
3435

3536
__For the permissions__ :
3637

37-
The `*Permissions` fields has the following structure (the value is the default behavior) :
38+
The field `unixPermissions` also accepts a string representing the octal value :
39+
"644", "755", etc. On nodejs you can use the `mode` attribute of
40+
[nodejs' fs.Stats](http://nodejs.org/api/fs.html#fs_class_fs_stats).
3841

39-
```js
40-
unixPermissions : {
41-
executable : false,
42-
readOnly : false
43-
}
44-
45-
dosPermissions : {
46-
hidden : false,
47-
readOnly : false
48-
}
49-
```
42+
See also [the platform option of generate()]({{site.baseurl}}/documentation/api_jszip/generate.html).
5043

51-
The field `unixPermissions` also accepts a number (the 2 bytes file attributes) :
52-
you can use the `mode` attribute of [nodejs' fs.Stats](http://nodejs.org/api/fs.html#fs_class_fs_stats).
53-
In that case, the executable/readOnly boolean will be extracted from the "user"
54-
part (ignoring the "group" and "other").
44+
__About `dir`__ :
5545

56-
See also [the platform option of generate()]({{site.baseurl}}/documentation/api_jszip/generate.html).
46+
If `dir` is true or if a permission says it's a folder, this entry be flagged
47+
as a folder and the content will be ignored.
5748

5849
__Returns__ : The current JSZip object, for chaining.
5950

@@ -93,9 +84,7 @@ zip.file("folder/file.txt", "file in folder", {createFolders: true});
9384
// It will exist whether or not "file.txt" is present.
9485

9586
zip.file("script.sh", "echo 'hello world'", {
96-
unixPermissions : {
97-
executable : true
98-
}
87+
unixPermissions : "755"
9988
});
10089
// when generated with platform:UNIX, the script.sh file will be executable
10190
```

documentation/api_jszip/folder_data.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ layout: default
44
section: api
55
---
66

7-
__Description__ : Add a directory to the zip file.
7+
__Description__ : Create a directory if it doesn't exist, return a new JSZip
8+
object with the new folder as root.
9+
10+
See also [the `dir` option of file()]({{site.baseurl}}/documentation/api_jszip/file_data.html).
811

912
__Arguments__
1013

documentation/api_jszip/generate.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ Possible values for `platform` : `DOS` and `UNIX`. It also accepts nodejs
5353
When using `DOS`, the attribute `dosPermissions` of each file is used.
5454
When using `UNIX`, the attribute `unixPermissions` of each file is used.
5555

56+
If you set the platform value on nodejs, be sure to use `process.platform`.
57+
`fs.stats` returns a non executable mode for folders on windows, if you
58+
force the platform to `UNIX` the generated zip file will have a strange
59+
behavior on UNIX platforms.
60+
5661
__Returns__ : The generated zip file.
5762

5863
__Throws__ : An exception if the asked `type` is not available in the browser,
@@ -78,6 +83,21 @@ var content = zip.generate({type:"nodebuffer"});
7883
require("fs").writeFile("hello.zip", content, function(err){/*...*/});
7984
```
8085

86+
```js
87+
// on nodejs
88+
zip.file(pathname, content, {
89+
date: stat.mtime,
90+
unixPermissions: stat.mode
91+
});
92+
93+
// ...
94+
95+
zip.generate({
96+
type: 'nodebuffer',
97+
platform: process.platform
98+
});
99+
```
100+
81101
```js
82102
//This example will Generate a Open Document Spreasheet, with the correct mime type
83103
var zip = new JSZip();

documentation/api_zipobject.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ attribute name | type | description
1616
`dir` | boolean | true if this is a directory
1717
`date` | date | the last modification date
1818
`comment` | string | the comment for this file
19+
`unixPermissions` | 16 bits number | The UNIX permissions of the file, if any.
20+
`dosPermissions` | 6 bits number | The DOS permissions of the file, if any.
1921
`options` | object | the options of the file. The available options are :
2022
`options.base64` | boolean | **Deprecated**, see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
2123
`options.binary` | boolean | **Deprecated**, see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)

lib/object.js

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,23 @@ var fileAdd = function(name, data, o) {
225225

226226
o = prepareFileAttrs(o);
227227

228+
if (typeof o.unixPermissions === "string") {
229+
o.unixPermissions = parseInt(o.unixPermissions, 8);
230+
}
231+
232+
// UNX_IFDIR 0040000 see zipinfo.c
233+
if (o.unixPermissions && (o.unixPermissions & 0x4000)) {
234+
o.dir = true;
235+
}
236+
// Bit 4 Directory
237+
if (o.dosPermissions && (o.dosPermissions & 0x0010)) {
238+
o.dir = true;
239+
}
240+
241+
if (o.dir) {
242+
name = forceTrailingSlash(name);
243+
}
244+
228245
if (o.createFolders && (parent = parentFolder(name))) {
229246
folderAdd.call(this, parent, true);
230247
}
@@ -233,6 +250,7 @@ var fileAdd = function(name, data, o) {
233250
o.base64 = false;
234251
o.binary = false;
235252
data = null;
253+
dataType = null;
236254
}
237255
else if (dataType === "string") {
238256
if (o.binary && !o.base64) {
@@ -258,15 +276,6 @@ var fileAdd = function(name, data, o) {
258276
}
259277
}
260278

261-
if (typeof o.unixPermissions === "number") {
262-
o.unixPermissions = {
263-
// executable for the owner
264-
executable: !!(o.unixPermissions & 0x0040),
265-
// NOT writable for the owner
266-
readOnly: (o.unixPermissions & 0x0080) === 0
267-
};
268-
}
269-
270279
var object = new ZipObject(name, data, o);
271280
this.files[name] = object;
272281
return object;
@@ -286,6 +295,20 @@ var parentFolder = function (path) {
286295
return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
287296
};
288297

298+
299+
/**
300+
* Returns the path with a slash at the end.
301+
* @private
302+
* @param {String} path the path to check.
303+
* @return {String} the path with a trailing slash.
304+
*/
305+
var forceTrailingSlash = function(path) {
306+
// Check the name ends with a /
307+
if (path.slice(-1) != "/") {
308+
path += "/"; // IE doesn't like substr(-1)
309+
}
310+
return path;
311+
};
289312
/**
290313
* Add a (sub) folder in the current folder.
291314
* @private
@@ -295,13 +318,10 @@ var parentFolder = function (path) {
295318
* @return {Object} the new folder.
296319
*/
297320
var folderAdd = function(name, createFolders) {
298-
// Check the name ends with a /
299-
if (name.slice(-1) != "/") {
300-
name += "/"; // IE doesn't like substr(-1)
301-
}
302-
303321
createFolders = (typeof createFolders !== 'undefined') ? createFolders : false;
304322

323+
name = forceTrailingSlash(name);
324+
305325
// Does this folder already exist?
306326
if (!this.files[name]) {
307327
fileAdd.call(this, name, null, {
@@ -380,29 +400,15 @@ var generateCompressedObjectFrom = function(file, compression, compressionOption
380400
*/
381401
var generateUnixExternalFileAttr = function (unixPermissions, isDir) {
382402

383-
// I can't use octal values in strict mode, hence the hexa.
384-
var umask = 0x12; // 022
385-
386-
var permissions = 0x1FF; // 0777
387-
388-
permissions &= ~umask;
389-
390-
if (!(unixPermissions && unixPermissions.executable) && !isDir) {
391-
permissions &= 0x1B6; // 0666
392-
}
393-
if (unixPermissions && unixPermissions.readOnly) {
394-
permissions &= 0x16D; // 0555
395-
}
396-
397-
var extFileAttr = permissions << 16;
398-
399-
if (isDir) {
400-
extFileAttr |= 0x4000 << 16; // UNX_IFDIR 0040000 see zipinfo.c
401-
} else {
402-
extFileAttr |= 0x8000 << 16; // UNX_IFREG 0100000 see zipinfo.c
403+
var result = unixPermissions;
404+
if (!unixPermissions) {
405+
// I can't use octal values in strict mode, hence the hexa.
406+
// 040775 => 0x41fd
407+
// 0100664 => 0x81b4
408+
result = isDir ? 0x41fd : 0x81b4;
403409
}
404410

405-
return extFileAttr;
411+
return (result & 0xFFFF) << 16;
406412
};
407413

408414
/**
@@ -420,20 +426,9 @@ var generateUnixExternalFileAttr = function (unixPermissions, isDir) {
420426
*/
421427
var generateDosExternalFileAttr = function (dosPermissions, isDir) {
422428

423-
var permissions = 0;
424-
425-
if (!dosPermissions) {
426-
return permissions;
427-
}
428-
429-
if (dosPermissions.hidden) {
430-
permissions |= 0x0002;
431-
}
432-
if (dosPermissions.readOnly) {
433-
permissions |= 0x0001;
434-
}
429+
// the dir flag is already set for compatibility
435430

436-
return permissions;
431+
return (dosPermissions || 0) & 0x3F;
437432
};
438433

439434
/**
@@ -482,7 +477,7 @@ var generateZipParts = function(name, file, compressedObject, offset, platform)
482477
extFileAttr |= 0x00010;
483478
}
484479
if(platform === "UNIX") {
485-
versionMadeBy = 0x0314; // UNIX, version 2.0
480+
versionMadeBy = 0x031E; // UNIX, version 3.0
486481
extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir);
487482
} else { // DOS or other, fallback to DOS
488483
versionMadeBy = 0x0014; // DOS, version 2.0

lib/zipEntry.js

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -167,22 +167,19 @@ ZipEntry.prototype = {
167167
this.dosPermissions = null;
168168
var madeBy = this.versionMadeBy >> 8;
169169

170+
// Check if we have the DOS directory flag set.
171+
// We look for it in the DOS and UNIX permissions
172+
// but some unknown platform could set it as a compatibility flag.
173+
this.dir = this.externalFileAttributes & 0x0010 ? true : false;
174+
170175
if(madeBy === MADE_BY_DOS) {
171-
this.dosPermissions = {
172-
// Bit 1 Hidden
173-
hidden: !!(this.externalFileAttributes & 0x0002),
174-
// Bit 0 Read-Only
175-
readOnly: !!(this.externalFileAttributes & 0x0001)
176-
};
177-
// Bit 5 Archive
178-
this.dir = !!(this.externalFileAttributes & 0x0010);
176+
// first 6 bits (0 to 5)
177+
this.dosPermissions = this.externalFileAttributes & 0x3F;
179178
}
180179

181180
if(madeBy === MADE_BY_UNIX) {
182-
var fullFilePermissions = this.externalFileAttributes >> 16;
183-
this.unixPermissions = fullFilePermissions;
184-
// the octal permissions are in (fullFilePermissions & 0x01FF).toString(8);
185-
this.dir = !!(fullFilePermissions & 0x4000);
181+
this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;
182+
// the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);
186183
}
187184

188185
// fail safe : if the name ends with a / it probably means a folder

test/ref/permissions/linux_7z.zip

106 Bytes
Binary file not shown.

test/ref/permissions/linux_ark.zip

158 Bytes
Binary file not shown.
106 Bytes
Binary file not shown.
158 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)