forked from jorith88/vscode-webdav
-
Notifications
You must be signed in to change notification settings - Fork 0
/
extension.js
257 lines (208 loc) · 9.25 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
const vscode = require('vscode');
const fs = require("fs");
const findConfig = require('find-config');
const path = require('path');
const tmp = require('tmp');
const CredentialStore = require('./credentialstore/credentialstore.js');
const nodeUrl = require('url');
const webdavFs = require("webdav-fs")
const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 5);
const credStore = new CredentialStore.CredentialStore("vscode-webdav:", ".webdav", "webdav-secrets.json");
const EMPTY_CREDENTIALS = {
newCredentials: true,
_username: '',
_password: ''
}
function activate(context) {
const uploadCommand = vscode.commands.registerCommand('extension.webdavUpload', upload);
const compareCommand = vscode.commands.registerCommand('extension.webdavCompare', compare);
statusBar.command = 'extension.webdavUpload';
statusBar.text = '$(cloud-upload) Upload to WebDAV';
context.subscriptions.push(statusBar);
context.subscriptions.push(uploadCommand);
context.subscriptions.push(compareCommand);
statusBar.show();
}
exports.activate = activate;
// this method is called when your extension is deactivated
function deactivate() {}
exports.deactivate = deactivate;
function upload() {
doWebdavAction(function(webdav, workingFile, remoteFile) {
return new Promise(function(resolve, reject) {
const editor = vscode.window.activeTextEditor;
webdav.writeFile(remoteFile, editor.document.getText() , function(err) {
if (err != null) {
console.error(err);
vscode.window.showErrorMessage('Failed to upload file to remote host: ' + err.message);
reject(err);
} else {
const fileName = remoteFile.slice(remoteFile.lastIndexOf('/') + 1);
statusBar.text = "$(cloud-upload) Uploaded " + fileName + "...";
statusBar.command = null;
statusBar.color = '#4cff4c';
setTimeout(function() {
statusBar.text = '$(cloud-upload) Upload to WebDAV';
statusBar.command = 'extension.webdavUpload';
statusBar.color = '#fff';
}, 2000)
resolve(undefined);
}
});
});
});
}
function compare() {
doWebdavAction(function(webdav, workingFile, remoteFile) {
return new Promise(function(resolve, reject) {
// Write the remote file to a local temporary file
const extension = workingFile.slice(workingFile.lastIndexOf('.'));
const tmpFile = tmp.fileSync({ postfix: extension });
webdav.readFile(remoteFile, "utf8", function(error, data) {
if (error != null) {
console.log(error);
reject(error);
}
fs.writeFileSync(tmpFile.name, data, function(err) {
if(err) {
console.log(err);
reject(error);
}
});
if (!data) {
reject("Cannot download remote file " + remoteFile);
return;
}
// Compare!
try {
const fileName = remoteFile.slice(remoteFile.lastIndexOf('/') + 1);
vscode.commands.executeCommand('vscode.diff',
vscode.Uri.file(tmpFile.name),
vscode.Uri.file(workingFile),
fileName + ' (WebDAV Compare)',
{
preview: false, // Open the diff in an additional tab instead of replacing the current one
selection: null // Don't select any text in the compare
}
);
resolve(undefined);
} catch (error) {
console.log(error);
reject(error);
}
});
});
});
}
function doWebdavAction(webdavAction) {
if (!vscode.window.activeTextEditor) {
vscode.window.showErrorMessage('Cannot find an active text editor...');
return;
}
const workingFile = vscode.window.activeTextEditor.document.uri.fsPath;
const workingDir = workingFile.slice(0, workingFile.lastIndexOf(path.sep));
// Read configuration
const config = getEndpointConfigForCurrentPath(workingDir);
if (!config) {
return;
}
// Ignore SSL errors, needed for self signed certificates
if (config.remoteEndpoint.ignoreSSLErrors) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
}
// Initialize WebDAV
const remoteFile = workingFile.replace(/\\/g, '/').replace(vscode.workspace.rootPath.replace(/\\/g, '/') + config.localRootPath, ''); // On Windows replace \ with /
const url = nodeUrl.parse(config.remoteEndpoint.url);
const credentialsKey = url.port ? url.hostname + ":" + url.port : url.hostname;
getWebdavCredentials(credentialsKey).then(credentials => {
if (!credentials) {
vscode.window.showWarningMessage('WebDAV login cancelled...');
return;
}
const webdav = webdavFs(config.remoteEndpoint.url, credentials._username, credentials._password);
webdavAction(webdav, workingFile, remoteFile).then(() => {
// store the password only if there is no WebDAV error and
// the credentials contains at least a user name
if (credentials.newCredentials && credentials._username) {
storeCredentials(credentialsKey, credentials._username, credentials._password);
}
}, error => vscode.window.showErrorMessage('Error in WebDAV communication: ' + error));
}, error => {
console.error('Error while retrieving credentials', error);
vscode.window.showErrorMessage('Error while retrieving credentials ');
});
}
function getEndpointConfigForCurrentPath(absoluteWorkingDir) {
const configFile = findConfig('webdav.json', {cwd: absoluteWorkingDir});
if (configFile != null) {
const allEndpointsConfig = JSON.parse(fs.readFileSync(configFile));
const endpointConfigDirectory = configFile.slice(0, configFile.lastIndexOf(path.sep));
const relativeWorkingDir = absoluteWorkingDir.slice(endpointConfigDirectory.length).replace(/\\/g, '/'); // On Windows replace \ with /
let endpointConfig = null;
let currentSearchPath = relativeWorkingDir;
let configOnCurrentSearchPath = null;
while (!endpointConfig) {
configOnCurrentSearchPath = allEndpointsConfig[currentSearchPath];
if (!configOnCurrentSearchPath) {
// Maybe the path in the configuration has a trailing '/'
configOnCurrentSearchPath = allEndpointsConfig[currentSearchPath + '/'];
}
if (configOnCurrentSearchPath) {
endpointConfig = configOnCurrentSearchPath;
} else {
currentSearchPath = currentSearchPath.slice(0, currentSearchPath.lastIndexOf("/"));
if (currentSearchPath === "") {
// issue #1 - check root mapping
endpointConfig = allEndpointsConfig["/"]
if (!endpointConfig) {
vscode.window.showErrorMessage('Cannot find a remote endpoint configuration for the current working directory ' + relativeWorkingDir + ' in webdav.json...');
return null;
}
}
}
}
return {
localRootPath: currentSearchPath,
remoteEndpoint: endpointConfig
}
} else {
vscode.window.showErrorMessage('Endpoint config file for WebDAV (webdav.json) not found...');
}
}
function getWebdavCredentials(key) {
return new Promise(function(resolve, reject) {
credStore.GetCredential(key).then(credentials => {
if (credentials !== undefined) {
resolve(credentials);
} else {
askForCredentials(key).then(credentials => {
resolve(credentials);
}, error => reject(error));
}
}, error => reject(error))
});
}
function askForCredentials(key) {
return new Promise(function(resolve, reject) {
vscode.window.showInputBox({prompt: 'Username for ' + key + ' ?'}).then(username => {
if (!username) {
resolve(EMPTY_CREDENTIALS);
return;
}
vscode.window.showInputBox({prompt: 'Password ?', password: true}).then(password => {
if (!password) {
resolve(EMPTY_CREDENTIALS);
return;
}
resolve({
newCredentials: true,
_username: username,
_password: password
});
}, error => reject(error));
}, error => reject(error));
});
}
function storeCredentials(key, username, password) {
credStore.SetCredential(key, username, password)
}