Skip to content

Commit 0b42a7d

Browse files
guillaumevthosmos
authored andcommitted
Ported from https://github.com/thosmos/filelink-owncloud to support Thunderbird 68.*
1 parent 0a1135f commit 0b42a7d

39 files changed

+594
-1926
lines changed

build.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
cd src; zip -r ../../nextcloud-filelink-$1.xpi .

screenshots/addon-about.png

-103 KB
Binary file not shown.

screenshots/config.png

145 KB
Loading

screenshots/configured.png

-60.8 KB
Binary file not shown.

screenshots/setup.png

-47.5 KB
Binary file not shown.

src/_locales/en/messages.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"extensionName": {
3+
"message": "Nextcloud for Filelink",
4+
"description": "Name of the extension"
5+
},
6+
"extensionDescription": {
7+
"message": "Nextcloud provider for Thunderbird Filelink",
8+
"description": "Description of the extension"
9+
},
10+
"serviceName": {
11+
"message": "Nextcloud",
12+
"description": "Name of the service"
13+
},
14+
"serverURLLabel": {
15+
"message": "WebDAV URL"
16+
},
17+
"serverURLDesc": {
18+
"message": "Your Personal WebDAV file path can be found under Settings in the lower left of the Files screen."
19+
},
20+
"usernameLabel": {
21+
"message": "Username"
22+
},
23+
"usernameDesc": {
24+
"message": "Your NextCloud username"
25+
},
26+
"tokenLabel": {
27+
"message": "App Token / Password"
28+
},
29+
"tokenDesc": {
30+
"message": "An app token (preferrable) or password. Generate an app token via User -> Settings -> Security -> App Token. WARNING: this token is stored insecurely. NOTE: this may require the OAuth2 plugin on the server."
31+
},
32+
"pathLabel": {
33+
"message": "Storage Path"
34+
},
35+
"pathDesc": {
36+
"message": "The path where the files are stored in OwnCloud (it must already exist on the server)"
37+
}
38+
}

src/background.js

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/**
2+
* @copyright Copyright (c) 2020, Thomas Spellman ([email protected])
3+
*
4+
* @license GNU AGPL version 3 or any later version
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as
8+
* published by the Free Software Foundation, either version 3 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*
19+
*/
20+
21+
var uploads = new Map();
22+
23+
// browser.cloudFile.onAccountAdded.addListener(async (account) => {
24+
// //console.log("Account Added", account.id)
25+
// })
26+
27+
async function getAccountInfo(accountId) {
28+
let accountInfo = await browser.storage.local.get([accountId]);
29+
if (!accountInfo[accountId] || !("webdavUrl" in accountInfo[accountId])) {
30+
throw new Error("No Accounts found.");
31+
}
32+
return accountInfo[accountId];
33+
}
34+
35+
browser.cloudFile.onFileUpload.addListener(async (account, params) => {
36+
37+
let { id, name, data } = params;
38+
39+
name = "" + Date.now() + "_" + name;
40+
41+
console.log("onFileUpload", id, account, name);
42+
43+
let accountInfo = await getAccountInfo(account.id);
44+
45+
//console.log("accountInfo", accountInfo);
46+
47+
let uploadInfo = {
48+
id,
49+
name,
50+
abortController: new AbortController(),
51+
};
52+
53+
uploads.set(id, uploadInfo);
54+
55+
let {webdavUrl, username, token, path} = accountInfo;
56+
57+
const authHeader = "Basic " + btoa(username + ":" + token);
58+
59+
let url = webdavUrl + path + encodeURIComponent(name);
60+
61+
let headers = {
62+
"Content-Type": "application/octet-stream",
63+
Authorization: authHeader
64+
};
65+
let fetchInfo = {
66+
method: "PUT",
67+
headers,
68+
body: data,
69+
signal: uploadInfo.abortController.signal,
70+
};
71+
72+
//console.log("uploading to ", url, fetchInfo);
73+
74+
let response = await fetch(url, fetchInfo);
75+
76+
//console.log("file upload response", response);
77+
78+
delete uploadInfo.abortController;
79+
if (response.status > 299) {
80+
throw new Error("response was not ok: server status code: " + response.status + ", response message: " + response.statusText);
81+
}
82+
83+
const serverUrl = webdavUrl.substr(0, webdavUrl.indexOf("remote.php"));
84+
const shareUrl = serverUrl + "ocs/v1.php/apps/files_sharing/api/v1/shares?format=json";
85+
86+
uploadInfo.abortController = new AbortController();
87+
uploads.set(id, uploadInfo);
88+
89+
headers = {
90+
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
91+
Authorization: authHeader,
92+
"OCS-APIRequest": true
93+
};
94+
95+
fetchInfo = {
96+
method: "POST",
97+
headers,
98+
body: "shareType=3&path=" + encodeURIComponent(path + name),
99+
signal: uploadInfo.abortController.signal,
100+
};
101+
102+
console.log("requesting public link", shareUrl, fetchInfo);
103+
104+
response = await fetch(shareUrl, fetchInfo);
105+
106+
//console.log("public link response", response);
107+
108+
if(response.ok)
109+
{
110+
let respJson = await response.json();
111+
112+
uploadInfo.shareID = respJson.ocs.data.id;
113+
uploads.set(id, uploadInfo);
114+
115+
return {url: respJson.ocs.data.url + "/download"};
116+
}
117+
else
118+
return {aborted: true}
119+
120+
});
121+
122+
browser.cloudFile.onFileUploadAbort.addListener((account, id) => {
123+
//console.log("aborting upload", id);
124+
let uploadInfo = uploads.get(id);
125+
if (uploadInfo && uploadInfo.abortController) {
126+
uploadInfo.abortController.abort();
127+
}
128+
});
129+
130+
browser.cloudFile.onFileDeleted.addListener(async (account, id) => {
131+
//console.log("delete upload", id);
132+
let uploadInfo = uploads.get(id);
133+
if (!uploadInfo) {
134+
return;
135+
}
136+
137+
// FIXME how do we get a confirmation popup in TB MailExtensions?
138+
// let wishDelete = confirm("Do you wish to delete the file on the server?");
139+
// if(!wishDelete){
140+
// return;
141+
// }
142+
143+
let accountInfo = await getAccountInfo(account.id);
144+
145+
let {shareID} = uploadInfo;
146+
let {webdavUrl, username, token} = accountInfo;
147+
148+
const authHeader = "Basic " + btoa(username + ":" + token);
149+
150+
const serverUrl = webdavUrl.substr(0, webdavUrl.indexOf("remote.php"));
151+
const shareUrl = serverUrl + "ocs/v1.php/apps/files_sharing/api/v1/shares/" + shareID;
152+
153+
let headers = {
154+
Authorization: authHeader,
155+
"OCS-APIRequest": true
156+
};
157+
158+
let fetchInfo = {
159+
headers,
160+
method: "DELETE",
161+
};
162+
163+
//console.log("sending delete", url, fetchInfo);
164+
165+
let response = await fetch(shareUrl, fetchInfo);
166+
167+
//console.log("delete response", response);
168+
169+
uploads.delete(id);
170+
171+
if (response.status > 299) {
172+
throw new Error("response was not ok: server status code: " + response.status + ", response message: " + response.statusText);
173+
}
174+
175+
});
176+
177+
browser.cloudFile.getAllAccounts().then(async (accounts) => {
178+
let allAccountsInfo = await browser.storage.local.get();
179+
for (let account of accounts) {
180+
await browser.cloudFile.updateAccount(account.id, {
181+
configured: account.id in allAccountsInfo,
182+
});
183+
}
184+
});

src/chrome.manifest

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/chrome/content/about.xul

Lines changed: 0 additions & 117 deletions
This file was deleted.

src/chrome/content/aboutLogo.png

-7.06 KB
Binary file not shown.

0 commit comments

Comments
 (0)