Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update permissions #205

Merged
merged 2 commits into from
Mar 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 11 additions & 22 deletions documentation/api_jszip/file_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,25 @@ compressionOptions | object | `null` | the options to use when compressing the f
comment | string | null | The comment for this file.
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.
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.
unixPermissions | object | null | The UNIX permissions of the file, if any.
dosPermissions | object | null | The DOS permissions of the file, if any.
unixPermissions | 16 bits number | null | The UNIX permissions of the file, if any.
dosPermissions | 6 bits number | null | The DOS permissions of the file, if any.
dir | boolean | false | Set to true if this is a directory and content should be ignored.

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

__For the permissions__ :

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

```js
unixPermissions : {
executable : false,
readOnly : false
}

dosPermissions : {
hidden : false,
readOnly : false
}
```
See also [the platform option of generate()]({{site.baseurl}}/documentation/api_jszip/generate.html).

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

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

__Returns__ : The current JSZip object, for chaining.

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

zip.file("script.sh", "echo 'hello world'", {
unixPermissions : {
executable : true
}
unixPermissions : "755"
});
// when generated with platform:UNIX, the script.sh file will be executable
```
5 changes: 4 additions & 1 deletion documentation/api_jszip/folder_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ layout: default
section: api
---

__Description__ : Add a directory to the zip file.
__Description__ : Create a directory if it doesn't exist, return a new JSZip
object with the new folder as root.

See also [the `dir` option of file()]({{site.baseurl}}/documentation/api_jszip/file_data.html).

__Arguments__

Expand Down
20 changes: 20 additions & 0 deletions documentation/api_jszip/generate.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ Possible values for `platform` : `DOS` and `UNIX`. It also accepts nodejs
When using `DOS`, the attribute `dosPermissions` of each file is used.
When using `UNIX`, the attribute `unixPermissions` of each file is used.

If you set the platform value on nodejs, be sure to use `process.platform`.
`fs.stats` returns a non executable mode for folders on windows, if you
force the platform to `UNIX` the generated zip file will have a strange
behavior on UNIX platforms.

__Returns__ : The generated zip file.

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

```js
// on nodejs
zip.file(pathname, content, {
date: stat.mtime,
unixPermissions: stat.mode
});

// ...

zip.generate({
type: 'nodebuffer',
platform: process.platform
});
```

```js
//This example will Generate a Open Document Spreasheet, with the correct mime type
var zip = new JSZip();
Expand Down
2 changes: 2 additions & 0 deletions documentation/api_zipobject.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ attribute name | type | description
`dir` | boolean | true if this is a directory
`date` | date | the last modification date
`comment` | string | the comment for this file
`unixPermissions` | 16 bits number | The UNIX permissions of the file, if any.
`dosPermissions` | 6 bits number | The DOS permissions of the file, if any.
`options` | object | the options of the file. The available options are :
`options.base64` | boolean | **Deprecated**, see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
`options.binary` | boolean | **Deprecated**, see [file(name, data [,options])]({{site.baseurl}}/documentation/api_jszip/file_data.html)
Expand Down
93 changes: 44 additions & 49 deletions lib/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,23 @@ var fileAdd = function(name, data, o) {

o = prepareFileAttrs(o);

if (typeof o.unixPermissions === "string") {
o.unixPermissions = parseInt(o.unixPermissions, 8);
}

// UNX_IFDIR 0040000 see zipinfo.c
if (o.unixPermissions && (o.unixPermissions & 0x4000)) {
o.dir = true;
}
// Bit 4 Directory
if (o.dosPermissions && (o.dosPermissions & 0x0010)) {
o.dir = true;
}

if (o.dir) {
name = forceTrailingSlash(name);
}

if (o.createFolders && (parent = parentFolder(name))) {
folderAdd.call(this, parent, true);
}
Expand All @@ -233,6 +250,7 @@ var fileAdd = function(name, data, o) {
o.base64 = false;
o.binary = false;
data = null;
dataType = null;
}
else if (dataType === "string") {
if (o.binary && !o.base64) {
Expand All @@ -258,15 +276,6 @@ var fileAdd = function(name, data, o) {
}
}

if (typeof o.unixPermissions === "number") {
o.unixPermissions = {
// executable for the owner
executable: !!(o.unixPermissions & 0x0040),
// NOT writable for the owner
readOnly: (o.unixPermissions & 0x0080) === 0
};
}

var object = new ZipObject(name, data, o);
this.files[name] = object;
return object;
Expand All @@ -286,6 +295,20 @@ var parentFolder = function (path) {
return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
};


/**
* Returns the path with a slash at the end.
* @private
* @param {String} path the path to check.
* @return {String} the path with a trailing slash.
*/
var forceTrailingSlash = function(path) {
// Check the name ends with a /
if (path.slice(-1) != "/") {
path += "/"; // IE doesn't like substr(-1)
}
return path;
};
/**
* Add a (sub) folder in the current folder.
* @private
Expand All @@ -295,13 +318,10 @@ var parentFolder = function (path) {
* @return {Object} the new folder.
*/
var folderAdd = function(name, createFolders) {
// Check the name ends with a /
if (name.slice(-1) != "/") {
name += "/"; // IE doesn't like substr(-1)
}

createFolders = (typeof createFolders !== 'undefined') ? createFolders : false;

name = forceTrailingSlash(name);

// Does this folder already exist?
if (!this.files[name]) {
fileAdd.call(this, name, null, {
Expand Down Expand Up @@ -380,29 +400,15 @@ var generateCompressedObjectFrom = function(file, compression, compressionOption
*/
var generateUnixExternalFileAttr = function (unixPermissions, isDir) {

// I can't use octal values in strict mode, hence the hexa.
var umask = 0x12; // 022

var permissions = 0x1FF; // 0777

permissions &= ~umask;

if (!(unixPermissions && unixPermissions.executable) && !isDir) {
permissions &= 0x1B6; // 0666
}
if (unixPermissions && unixPermissions.readOnly) {
permissions &= 0x16D; // 0555
}

var extFileAttr = permissions << 16;

if (isDir) {
extFileAttr |= 0x4000 << 16; // UNX_IFDIR 0040000 see zipinfo.c
} else {
extFileAttr |= 0x8000 << 16; // UNX_IFREG 0100000 see zipinfo.c
var result = unixPermissions;
if (!unixPermissions) {
// I can't use octal values in strict mode, hence the hexa.
// 040775 => 0x41fd
// 0100664 => 0x81b4
result = isDir ? 0x41fd : 0x81b4;
}

return extFileAttr;
return (result & 0xFFFF) << 16;
};

/**
Expand All @@ -420,20 +426,9 @@ var generateUnixExternalFileAttr = function (unixPermissions, isDir) {
*/
var generateDosExternalFileAttr = function (dosPermissions, isDir) {

var permissions = 0;

if (!dosPermissions) {
return permissions;
}

if (dosPermissions.hidden) {
permissions |= 0x0002;
}
if (dosPermissions.readOnly) {
permissions |= 0x0001;
}
// the dir flag is already set for compatibility

return permissions;
return (dosPermissions || 0) & 0x3F;
};

/**
Expand Down Expand Up @@ -482,7 +477,7 @@ var generateZipParts = function(name, file, compressedObject, offset, platform)
extFileAttr |= 0x00010;
}
if(platform === "UNIX") {
versionMadeBy = 0x0314; // UNIX, version 2.0
versionMadeBy = 0x031E; // UNIX, version 3.0
extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir);
} else { // DOS or other, fallback to DOS
versionMadeBy = 0x0014; // DOS, version 2.0
Expand Down
21 changes: 9 additions & 12 deletions lib/zipEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,22 +167,19 @@ ZipEntry.prototype = {
this.dosPermissions = null;
var madeBy = this.versionMadeBy >> 8;

// Check if we have the DOS directory flag set.
// We look for it in the DOS and UNIX permissions
// but some unknown platform could set it as a compatibility flag.
this.dir = this.externalFileAttributes & 0x0010 ? true : false;

if(madeBy === MADE_BY_DOS) {
this.dosPermissions = {
// Bit 1 Hidden
hidden: !!(this.externalFileAttributes & 0x0002),
// Bit 0 Read-Only
readOnly: !!(this.externalFileAttributes & 0x0001)
};
// Bit 5 Archive
this.dir = !!(this.externalFileAttributes & 0x0010);
// first 6 bits (0 to 5)
this.dosPermissions = this.externalFileAttributes & 0x3F;
}

if(madeBy === MADE_BY_UNIX) {
var fullFilePermissions = this.externalFileAttributes >> 16;
this.unixPermissions = fullFilePermissions;
// the octal permissions are in (fullFilePermissions & 0x01FF).toString(8);
this.dir = !!(fullFilePermissions & 0x4000);
this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;
// the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);
}

// fail safe : if the name ends with a / it probably means a folder
Expand Down
Binary file modified test/ref/permissions/linux_7z.zip
Binary file not shown.
Binary file modified test/ref/permissions/linux_ark.zip
Binary file not shown.
Binary file modified test/ref/permissions/linux_file_roller-ubuntu.zip
Binary file not shown.
Binary file modified test/ref/permissions/linux_file_roller-xubuntu.zip
Binary file not shown.
Binary file modified test/ref/permissions/linux_zip.zip
Binary file not shown.
Binary file modified test/ref/permissions/mac_finder.zip
Binary file not shown.
Loading