Merge branch 'release-1.17'

# Conflicts:
#	desktop/package.json
#	package-lock.json
#	package.json
#	release-notes.md
This commit is contained in:
antelle 2021-04-09 18:56:48 +02:00
commit eeeb7702ba
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
7 changed files with 155 additions and 64 deletions

View File

@ -678,6 +678,7 @@
"dropboxLinkCustom": "Own Dropbox app",
"gdriveSharedWithMe": "Shared with me",
"gdriveTeamDrives": "Team drives",
"webdavSaveMethod": "Save method",
"webdavSaveMove": "Upload a temporary file and move",

View File

@ -1,6 +1,7 @@
import { StorageBase } from 'storage/storage-base';
import { Locale } from 'util/locale';
import { Features } from 'util/features';
import { UrlFormat } from 'util/formatting/url-format';
import { GDriveApps } from 'const/cloud-storage-apps';
const NewFileIdPrefix = 'NewFile:';
@ -27,11 +28,9 @@ class StorageGDrive extends StorageBase {
}
this.logger.debug('Load', path);
const ts = this.logger.ts();
const url =
this._baseUrl +
'/files/{id}/revisions/{rev}?alt=media'
.replace('{id}', path)
.replace('{rev}', stat.rev);
const url = UrlFormat.makeUrl(`${this._baseUrl}/files/${path}/revisions/${stat.rev}`, {
'alt': 'media'
});
this._xhr({
url,
responseType: 'arraybuffer',
@ -57,7 +56,11 @@ class StorageGDrive extends StorageBase {
}
this.logger.debug('Stat', path);
const ts = this.logger.ts();
const url = this._baseUrl + '/files/{id}?fields=headRevisionId'.replace('{id}', path);
const url = UrlFormat.makeUrl(`${this._baseUrl}/files/${path}`, {
fields: 'headRevisionId',
includeItemsFromAllDrives: true,
supportsAllDrives: true
});
this._xhr({
url,
responseType: 'json',
@ -95,9 +98,12 @@ class StorageGDrive extends StorageBase {
let dataType;
let dataIsMultipart = false;
if (isNew) {
url =
this._baseUrlUpload +
'/files?uploadType=multipart&fields=id,headRevisionId';
url = UrlFormat.makeUrl(`${this._baseUrlUpload}/files`, {
uploadType: 'multipart',
fields: 'id,headRevisionId',
includeItemsFromAllDrives: true,
supportsAllDrives: true
});
const fileName = path.replace(NewFileIdPrefix, '') + '.kdbx';
const boundary = 'b' + Date.now() + 'x' + Math.round(Math.random() * 1000000);
data = [
@ -123,9 +129,12 @@ class StorageGDrive extends StorageBase {
dataType = 'multipart/related; boundary="' + boundary + '"';
dataIsMultipart = true;
} else {
url =
this._baseUrlUpload +
'/files/{id}?uploadType=media&fields=headRevisionId'.replace('{id}', path);
url = UrlFormat.makeUrl(`${this._baseUrlUpload}/files/${path}`, {
uploadType: 'media',
fields: 'headRevisionId',
includeItemsFromAllDrives: true,
supportsAllDrives: true
});
}
this._xhr({
url,
@ -160,59 +169,103 @@ class StorageGDrive extends StorageBase {
return callback && callback(err);
}
this.logger.debug('List');
let query =
dir === 'shared'
? 'sharedWithMe=true'
: dir
? `"${dir}" in parents`
: '"root" in parents';
query += ' and trashed=false';
const url =
this._baseUrl +
'/files?fields={fields}&q={q}&pageSize=1000'
.replace(
'{fields}',
encodeURIComponent('files(id,name,mimeType,headRevisionId)')
)
.replace('{q}', encodeURIComponent(query));
const ts = this.logger.ts();
this._xhr({
url,
responseType: 'json',
success: (response) => {
if (!response) {
this.logger.error('List error', this.logger.ts(ts));
return callback && callback('list error');
}
this.logger.debug('Listed', this.logger.ts(ts));
const fileList = response.files.map((f) => ({
name: f.name,
path: f.id,
rev: f.headRevisionId,
dir: f.mimeType === 'application/vnd.google-apps.folder'
}));
if (!dir) {
fileList.unshift({
name: Locale.gdriveSharedWithMe,
path: 'shared',
rev: undefined,
if (dir === 'drives') {
const urlParams = {
pageSize: 100
};
const url = UrlFormat.makeUrl(`${this._baseUrl}/drives`, urlParams);
this._xhr({
url,
responseType: 'json',
success: (response) => {
if (!response) {
this.logger.error('Drive list error', this.logger.ts(ts));
return callback?.('drive list error');
}
this.logger.debug('Listed drives', this.logger.ts(ts));
const fileList = response.drives.map((d) => ({
name: d.name,
path: d.id,
dir: true
});
}));
return callback?.(null, fileList);
},
error: (err) => {
this.logger.error('Drive dist error', this.logger.ts(ts), err);
return callback?.(err);
}
return callback && callback(null, fileList);
},
error: (err) => {
this.logger.error('List error', this.logger.ts(ts), err);
return callback && callback(err);
});
} else {
let query = 'trashed=false and ';
if (dir === 'shared') {
query += 'sharedWithMe=true';
} else if (dir) {
query += `"${dir}" in parents`;
} else {
query += '"root" in parents';
}
});
const urlParams = {
fields: 'files(id,name,mimeType,headRevisionId)',
q: query,
pageSize: 1000,
includeItemsFromAllDrives: true,
supportsAllDrives: true
};
const url = UrlFormat.makeUrl(`${this._baseUrl}/files`, urlParams);
this._xhr({
url,
responseType: 'json',
success: (response) => {
if (!response) {
this.logger.error('List error', this.logger.ts(ts));
return callback?.('list error');
}
this.logger.debug('Listed', this.logger.ts(ts));
const fileList = response.files.map((f) => ({
name: f.name,
path: f.id,
rev: f.headRevisionId,
dir: f.mimeType === 'application/vnd.google-apps.folder'
}));
if (!dir) {
fileList.unshift({
name: Locale.gdriveSharedWithMe,
path: 'shared',
rev: undefined,
dir: true
});
fileList.unshift({
name: Locale.gdriveTeamDrives,
path: 'drives',
rev: undefined,
dir: true
});
}
return callback?.(null, fileList);
},
error: (err) => {
this.logger.error('List error', this.logger.ts(ts), err);
return callback?.(err);
}
});
}
});
}
remove(path, callback) {
this.logger.debug('Remove', path);
const ts = this.logger.ts();
const url = this._baseUrl + '/files/{id}'.replace('{id}', path);
const url = `${this._baseUrl}/files/${path}`;
this._xhr({
url,
method: 'DELETE',
@ -254,7 +307,7 @@ class StorageGDrive extends StorageBase {
width: 600,
height: 400,
pkce: true,
redirectUrlParams: {
urlParams: {
'access_type': 'offline'
}
};

View File

@ -1,6 +1,6 @@
{
"name": "KeeWeb",
"version": "1.17.5",
"version": "1.17.6",
"description": "Free cross-platform password manager compatible with KeePass",
"main": "main.js",
"homepage": "https://keeweb.info",

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "keeweb",
"version": "1.17.5",
"version": "1.17.6",
"lockfileVersion": 2,
"requires": true,
"packages": {

View File

@ -1,6 +1,6 @@
{
"name": "keeweb",
"version": "1.17.5",
"version": "1.17.6",
"description": "Free cross-platform password manager compatible with KeePass",
"main": "Gruntfile.js",
"private": true,

View File

@ -5,16 +5,22 @@ var app = Application.currentApplication();
app.includeStandardAdditions = true;
var args = getArgs();
if (args.verbose) console.log('KeeWeb installer:', JSON.stringify(args, null, 2));
if (args.update) {
var waitPid = args.waitPid | 0;
if (waitPid) {
waitForExitOrKill(waitPid);
waitForExitOrKill(waitPid, args.verbose);
}
var dmg = checkFilePath(args.dmg, 'dmg');
var target = checkFilePath(args.app, 'app');
if (args.verbose) console.log('dmg:', dmg);
if (args.verbose) console.log('target:', target);
var targetOwner = app.doShellScript("stat -f '%Su' " + target);
if (args.verbose) console.log('target owner:', targetOwner);
var setOwnerToRoot = targetOwner === 'root';
var runAsAdmin = setOwnerToRoot;
if (!runAsAdmin) {
@ -22,42 +28,63 @@ if (args.update) {
app.doShellScript('test -w ' + target);
var targetDir = target.replace(/[^\/]*$/, '');
app.doShellScript('test -w ' + targetDir);
if (args.verbose) console.log('permissions are ok');
} catch (e) {
runAsAdmin = true;
if (args.verbose) console.log('permissions check error', e);
}
}
if (args.verbose) console.log('run as admin:', runAsAdmin);
var tmpDir = dmg + '.mount';
var script = [
'set -euxo pipefail',
args.verbose ? 'echo detaching old disk image...' : '',
'hdiutil detach ' + tmpDir + ' 2>/dev/null || true',
args.verbose ? 'echo cleaning tmp dir...' : '',
'rm -rf ' + tmpDir,
args.verbose ? 'echo making tmp dir...' : '',
'mkdir -p ' + tmpDir,
args.verbose ? 'echo attaching disk image...' : '',
'hdiutil attach -readonly -nobrowse -mountpoint ' + tmpDir + ' ' + dmg,
args.verbose ? 'echo removing target...' : '',
'rm -rf ' + target,
args.verbose ? 'echo copying from tmp dir to target...' : '',
'cp -pR ' + tmpDir + '/KeeWeb.app ' + target,
args.verbose ? 'echo detaching disk image...' : '',
'hdiutil detach ' + tmpDir,
args.verbose ? 'echo cleaning tmp dir...' : '',
'rm -rf ' + tmpDir
];
var scriptOptions = {};
if (runAsAdmin) {
scriptOptions.administratorPrivileges = true;
if (setOwnerToRoot) {
if (args.verbose) script.push('echo changing target owner...');
script.push('chown -R 0 ' + target);
}
}
if (args.verbose) script.push('echo launching the app...');
script.push('open ' + target);
script = script.join('\n');
if (args.verbose) console.log('executing script:\n\n' + script + '\n');
try {
runScriptOrDie(script, scriptOptions);
var output = runScriptOrDie(script, scriptOptions);
if (args.verbose) console.log('script output:\n\n' + output.replace(/\r/g, '\n'));
} catch (e) {
if (args.verbose) console.log('script error', e);
try {
app.doShellScript('hdiutil detach ' + tmpDir);
app.doShellScript('rm -rf ' + tmpDir);
} catch (e) {}
throw e;
}
if (args.verbose) console.log('done');
} else if (args.install) {
try {
app.doShellScript('chown -R 0 /Applications/KeeWeb.app', { administratorPrivileges: true });
@ -78,7 +105,7 @@ function getArgs() {
var match = arg.match(/^--([^=]+)(=(.*))?/);
if (match) {
var argName = match[1].replace(/-./g, function (m) {
m[1].toUpperCase();
return m[1].toUpperCase();
});
args[argName] = match[3] || true;
}
@ -86,17 +113,22 @@ function getArgs() {
return args;
}
function waitForExitOrKill(pid) {
function waitForExitOrKill(pid, verbose) {
if (verbose) console.log('waiting for process:', pid);
for (var i = 0; i < 10; i++) {
var psCount = Application('System Events').processes.whose({ unixId: pid }).length;
if (verbose) console.log('process count:', psCount);
if (psCount === 0) {
return;
}
delay(1);
}
try {
if (verbose) console.log('killing process');
app.doShellScript('kill ' + pid);
} catch (e) {}
} catch (e) {
if (verbose) console.log('error killing process', e);
}
}
function checkFilePath(path, ext) {

View File

@ -1,5 +1,10 @@
Release notes
-------------
##### v1.17.6 (2021-04-09)
`+` team drives support in Google Drive
`-` fix #1786: saving refresh_token in Google Drive
`-` fix #1767: updater issues on macOS
##### v1.17.5 (2021-03-27)
`+` ykman v4 support
`+` fix #1725: setting expiry date in the past