├── chrome app
├── version
├── logo.png
├── server_script_compile.bat
├── favicon.ico
├── logo_128.png
├── logo_16.png
├── Small_tile.png
├── screenshot.png
├── display_script.js
├── launch.js
├── loading.svg
├── dat_site_script.js
├── manifest.json
├── dat_site.html
├── server_app.html
├── nothing.html
├── loading.html
├── logo.svg
└── style.css
├── .github
└── FUNDING.yml
├── chrome extension
├── logo.png
├── favicon.ico
├── logo_128.png
├── logo_16.png
├── datsite.js
├── welcome_script.js
├── protocol_script.js
├── pac.js
├── qr_generator_script.js
├── redirector.html
├── torrent_error.html
├── qr_code_script.js
├── dat_error.html
├── qr_code.html
├── manifest.json
├── firefox-manifest.json
├── dat_error.js
├── datparse.js
├── redirector_script.js
├── qr_scanner_script.js
├── credits.html
├── options_script.js
├── qr_generator.html
├── logo.svg
├── qr_scanner.html
├── options.html
├── welcome.html
├── style.css
├── popup.html
└── popup.js
├── firefox extension
├── logo.png
├── favicon.ico
├── logo_16.png
├── logo_128.png
├── welcome_script.js
├── protocol_script.js
├── pac.js
├── redirector.html
├── dat_error.js
├── torrent_error.html
├── options_script.js
├── dat_error.html
├── manifest.json
├── redirector_script.js
├── datparse.js
├── options.html
├── style.css
├── popup.js
├── logo.svg
└── popup.html
├── electron app
└── resources
│ └── datpart
│ ├── logo.png
│ ├── favicon.ico
│ ├── logo_128.png
│ ├── logo_16.png
│ ├── display_script.js
│ ├── index.html
│ ├── package.json
│ ├── server_app.html
│ ├── launch.js
│ ├── logo.svg
│ ├── style.css
│ └── server_script.js
├── LICENSE
└── README.md
/chrome app/version:
--------------------------------------------------------------------------------
1 | v1.7.9
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: ['https://paypal.me/hughisaacs2']
2 |
--------------------------------------------------------------------------------
/chrome app/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome app/logo.png
--------------------------------------------------------------------------------
/chrome app/server_script_compile.bat:
--------------------------------------------------------------------------------
1 | browserify server_script_noncompile.js -o server_script.js
--------------------------------------------------------------------------------
/chrome app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome app/favicon.ico
--------------------------------------------------------------------------------
/chrome app/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome app/logo_128.png
--------------------------------------------------------------------------------
/chrome app/logo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome app/logo_16.png
--------------------------------------------------------------------------------
/chrome app/Small_tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome app/Small_tile.png
--------------------------------------------------------------------------------
/chrome app/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome app/screenshot.png
--------------------------------------------------------------------------------
/chrome extension/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome extension/logo.png
--------------------------------------------------------------------------------
/firefox extension/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/firefox extension/logo.png
--------------------------------------------------------------------------------
/chrome extension/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome extension/favicon.ico
--------------------------------------------------------------------------------
/chrome extension/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome extension/logo_128.png
--------------------------------------------------------------------------------
/chrome extension/logo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/chrome extension/logo_16.png
--------------------------------------------------------------------------------
/firefox extension/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/firefox extension/favicon.ico
--------------------------------------------------------------------------------
/firefox extension/logo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/firefox extension/logo_16.png
--------------------------------------------------------------------------------
/firefox extension/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/firefox extension/logo_128.png
--------------------------------------------------------------------------------
/electron app/resources/datpart/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/electron app/resources/datpart/logo.png
--------------------------------------------------------------------------------
/electron app/resources/datpart/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/electron app/resources/datpart/favicon.ico
--------------------------------------------------------------------------------
/electron app/resources/datpart/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/electron app/resources/datpart/logo_128.png
--------------------------------------------------------------------------------
/electron app/resources/datpart/logo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HughIsaacs2/DatPart/HEAD/electron app/resources/datpart/logo_16.png
--------------------------------------------------------------------------------
/chrome extension/datsite.js:
--------------------------------------------------------------------------------
1 | var DatPart = true;
2 |
3 | Array.from(document.querySelectorAll('a[href^="dat://"]:not(a[href*="."])')).forEach(function(link){
4 | var theLink = link.href;
5 | link.href = "web+" + theLink;
6 | });
--------------------------------------------------------------------------------
/chrome extension/welcome_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | window.onload = function(){
6 | document.getElementById("desktop-link").href="https://github.com/HughIsaacs2/DatPart/releases/tag/";
7 |
8 | document.getElementById("version-notice").textContent="This is version "+chrome.runtime.getManifest().version+" of "+chrome.runtime.getManifest().short_name+".";
9 | }
--------------------------------------------------------------------------------
/firefox extension/welcome_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | window.onload = function(){
6 | document.getElementById("desktop-link").href="https://github.com/HughIsaacs2/DatPart/releases/tag/"+chrome.runtime.getManifest().version;
7 |
8 | document.getElementById("version-notice").textContent="This is version "+chrome.runtime.getManifest().version+" of DatPart.";
9 | }
--------------------------------------------------------------------------------
/chrome extension/protocol_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | //navigator.registerProtocolHandler("web+magnet", "/redirector.html?torrent=%s", "Web Magnet");
6 | //navigator.registerProtocolHandler("magnet", "/redirector.html?torrent=%s", "Magnet");
7 | navigator.registerProtocolHandler("web+dat", "/redirector.html?dat=%s", "Web Dat");
8 | navigator.registerProtocolHandler("dat", "/redirector.html?dat=%s", "Dat");
--------------------------------------------------------------------------------
/firefox extension/protocol_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | //navigator.registerProtocolHandler("web+magnet", "/redirector.html?torrent=%s", "Web Magnet");
6 | //navigator.registerProtocolHandler("magnet", "/redirector.html?torrent=%s", "Magnet");
7 | navigator.registerProtocolHandler("web+dat", "/redirector.html?dat=%s", "Web Dat");
8 | navigator.registerProtocolHandler("dat", "/redirector.html?dat=%s", "Dat");
--------------------------------------------------------------------------------
/chrome app/display_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | document.getElementById("version-number").textContent = chrome.runtime.getManifest().version;
4 |
5 | document.getElementById("app-user-agent").textContent = navigator.userAgent;
6 |
7 | var logToScreen = function(log) {
8 | console.log(log);
9 | var printLog = log;
10 | if (typeof log == 'object') {
11 | printLog = JSON.stringify(log);
12 | }
13 | var logger = document.getElementById("logger");
14 | logger.textContent += printLog + "\n" + "\r\n";
15 | logger.scrollTop = logger.scrollHeight;
16 | };
--------------------------------------------------------------------------------
/chrome extension/pac.js:
--------------------------------------------------------------------------------
1 | // domain => [IPs].
2 | var cache = {};
3 | var debug = true;
4 |
5 | //var dathost = currentURLRequest.hostname;
6 | var port = "9989";
7 | var access = "PROXY";
8 | var appip = "localhost";
9 |
10 | function FindProxyForURL(url, host) {
11 | if (url.substring(0, 5) == "http:" && host.lastIndexOf('.dat_site', host.length)) { return "PROXY localhost:9989;"; } else { return "DIRECT"; }
12 | }
13 |
14 | /*
15 |
16 | url.substring(0, 5) == "http:" && host.indexOf(".dat_site") > -1 &&
17 |
18 | .lastIndexOf('.dat_site', host.length)
19 |
20 | */
--------------------------------------------------------------------------------
/firefox extension/pac.js:
--------------------------------------------------------------------------------
1 | // domain => [IPs].
2 | var cache = {};
3 | var debug = true;
4 |
5 | //var dathost = currentURLRequest.hostname;
6 | var port = "9989";
7 | var access = "PROXY";
8 | var appip = "127.0.0.1";
9 |
10 | function FindProxyForURL(url, host) {
11 | if (url.substring(0, 5) == "http:" && host.lastIndexOf('.dat_site', host.length)) { return "PROXY 127.0.0.1:9989;"; } else { return "DIRECT"; }
12 | }
13 |
14 | /*
15 |
16 | url.substring(0, 5) == "http:" && host.indexOf(".dat_site") > -1 &&
17 |
18 | .lastIndexOf('.dat_site', host.length)
19 |
20 | */
--------------------------------------------------------------------------------
/electron app/resources/datpart/display_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const {shell} = require('electron');
4 |
5 | var versionNumber = require('electron').remote.getGlobal('sharedObject').appVersionNumber;
6 |
7 | document.getElementById("version-number").textContent = versionNumber;
8 |
9 | document.getElementById("app-user-agent").textContent = navigator.userAgent;
10 |
11 | document.querySelectorAll("a.external-link").forEach(function (el) {
12 | el.onclick = function(){shell.openExternal(el.href);return false;};
13 | });
14 |
15 | var logToScreen = function(log) {
16 | console.log(log);
17 | var printLog = log;
18 | /* if (typeof log == 'object') {
19 | printLog = JSON.stringify(log);
20 | } */
21 | var logger = document.getElementById("logger");
22 | logger.textContent += printLog + "\n" + "\r\n";
23 | logger.scrollTop = logger.scrollHeight;
24 | };
--------------------------------------------------------------------------------
/chrome extension/qr_generator_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | function queryObj() {
3 |
4 | var result = {}, keyValuePairs = location.search.slice(1).split('&');
5 |
6 | keyValuePairs.forEach(function(keyValuePair) {
7 | keyValuePair = keyValuePair.split('=');
8 | result[keyValuePair[0]] = keyValuePair[1] || '';
9 | });
10 |
11 | return result;
12 | }
13 |
14 | var code_URL = queryObj()["code_URL"];
15 |
16 | var qrUrl = unescape(code_URL);
17 |
18 | window.onload = function() {
19 | document.getElementById("code_image").src = "/qr_code.html?link="+ qrUrl;
20 | document.getElementById("code_image").title = "QR Code for "+ qrUrl;
21 | document.getElementById("code_link").href = qrUrl;
22 | document.getElementById("code_link").textContent = qrUrl;
23 | document.getElementById("version-notice").textContent="This is version "+chrome.runtime.getManifest().version+" of "+chrome.runtime.getManifest().short_name+".";
24 | }
--------------------------------------------------------------------------------
/chrome extension/redirector.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ...
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | ...
23 |
24 |
--------------------------------------------------------------------------------
/firefox extension/redirector.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ...
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | ...
23 |
24 |
--------------------------------------------------------------------------------
/chrome app/launch.js:
--------------------------------------------------------------------------------
1 | chrome.app.runtime.onLaunched.addListener(function() {
2 | chrome.app.window.create('/server_app.html?platform=chromeApp', {
3 | 'innerBounds': {
4 | 'width': 800,
5 | 'height': 600
6 | },
7 | 'minWidth': 800,
8 | 'minHeight': 400,
9 | 'frame': {
10 | 'type': 'chrome',
11 | 'color': '#424242',
12 | 'activeColor': '#ffffff',
13 | 'inactiveColor': '#424242'
14 | },
15 | id: 'datpart_server'
16 | });
17 | });
18 |
19 | chrome.runtime.onMessageExternal.addListener(function() {
20 | if(chrome.app.window.get('datpart_server')){
21 | //Do Nothing
22 | } else {
23 | chrome.app.window.create('/server_app.html?platform=chromeApp', {
24 | 'innerBounds': {
25 | 'width': 800,
26 | 'height': 600
27 | },
28 | 'minWidth': 800,
29 | 'minHeight': 400,
30 | 'state': 'minimized',
31 | 'frame': {
32 | 'type': 'chrome',
33 | 'color': '#424242',
34 | 'activeColor': '#ffffff',
35 | 'inactiveColor': '#424242'
36 | },
37 | id: 'datpart_server'
38 | });
39 | }
40 | });
--------------------------------------------------------------------------------
/firefox extension/dat_error.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function queryObj() {
4 |
5 | var result = {}, keyValuePairs = location.search.slice(1).split('&');
6 |
7 | keyValuePairs.forEach(function(keyValuePair) {
8 | keyValuePair = keyValuePair.split('=');
9 | result[keyValuePair[0]] = keyValuePair[1] || '';
10 | });
11 |
12 | return result;
13 | }
14 |
15 | var datHash = queryObj()["datHash"];
16 | var datPath = queryObj()["path"];
17 |
18 | var retryLink = document.createElement('a');
19 | retryLink.href = "http://"+datHash+".dat_site"+datPath;
20 | retryLink.innerText = "Retry";
21 | retryLink.className = "button";
22 | document.body.appendChild(retryLink);
23 |
24 | var thaBr = document.createElement('br');
25 | document.body.appendChild(thaBr);
26 |
27 | var onx = document.createElement('br');
28 | document.body.appendChild(onx);
29 |
30 | var datLink = document.createElement('a');
31 | datLink.href = "dat://"+datHash+datPath;
32 | datLink.innerText = "Dat link";
33 | datLink.className = "button";
34 | document.body.appendChild(datLink);
--------------------------------------------------------------------------------
/electron app/resources/datpart/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DatPart Server
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/chrome extension/torrent_error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Not ready yet
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
27 |
28 |
29 | Error
30 | The Torrent site feature isn't ready yet.
31 |
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Hugh Isaacs II
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chrome app/loading.svg:
--------------------------------------------------------------------------------
1 | Loading...
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/chrome extension/qr_code_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | function queryObj() {
3 |
4 | var result = {}, keyValuePairs = location.search.slice(1).split('&');
5 |
6 | keyValuePairs.forEach(function(keyValuePair) {
7 | keyValuePair = keyValuePair.split('=');
8 | result[keyValuePair[0]] = keyValuePair[1] || '';
9 | });
10 |
11 | return result;
12 | }
13 |
14 | var qrLink = queryObj()["link"];
15 |
16 | var qrUrl = unescape(qrLink);
17 |
18 | if (qrUrl.substring(0, 10) == "web+dat://") {
19 | qrUrl = qrUrl.substring(4, qrUrl.length);
20 | }
21 |
22 | window.onload = function() {
23 |
24 | var qrcode = new QRCode({
25 | content: qrUrl,
26 | padding: 1,
27 | width: 512,
28 | height: 512,
29 | color: "#000000",
30 | background: "#ffffff",
31 | ecl: "M"
32 | });
33 | var svg = qrcode.svg();
34 | document.getElementById("qrcode").innerHTML = svg;
35 | document.querySelector("#qrcode > svg").setAttribute("viewBox","0 0 512 512");
36 | document.getElementById("qrcode").title = "QR Code for "+qrUrl;
37 | document.querySelector("#qrcode > svg").appendChild(document.createElement("title"));
38 | document.querySelector("#qrcode > svg > title").innerText = "QR Code for "+qrUrl;
39 | document.title = "QR Code for "+qrUrl;
40 | }
--------------------------------------------------------------------------------
/firefox extension/torrent_error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Loading...
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
30 |
31 |
32 | Error
33 |
34 |
--------------------------------------------------------------------------------
/chrome app/dat_site_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 0);
4 | window.scrollTo(0, 1);
5 |
6 | var currentTLD = location.hostname.split(".").pop();
7 | var currentURLhostNoTLD = location.hostname.split(".")[0];
8 |
9 | function loadDat(urlToLoad) {
10 |
11 | document.documentElement.className=document.documentElement.className.replace("not-loading","loading");
12 |
13 | document.getElementById("progress").remove();
14 | document.getElementById("browser").remove();
15 | document.getElementById("log").innerHTML = "Sorry, Dat protocol support isn't ready yet for Chrome OS. ";
16 |
17 | document.title = "Dat Site [" + urlToLoad + "]";
18 |
19 | document.getElementById("info").innerHTML+="dat://" + urlToLoad + " ";
20 |
21 | var a = document.createElement('a');
22 | a.href = "dat://" + urlToLoad;
23 | a.target = "_blank";
24 | a.textContent = 'Dat Link: ' + urlToLoad;
25 | a.className = "button download-link";
26 | document.getElementById("links").appendChild(a);
27 |
28 | }
29 |
30 | if (currentTLD == 'dat_site') {
31 | loadDat(currentURLhostNoTLD);
32 | };
--------------------------------------------------------------------------------
/firefox extension/options_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | window.onload = function(){
6 | document.getElementById("version-notice").textContent="This is version "+chrome.runtime.getManifest().version+" of DatPart.";
7 |
8 | chrome.permissions.contains({
9 | origins: ['https://*/.well-known/dat']
10 | }, function(result) {
11 | if (result) {
12 | document.documentElement.setAttribute('check-dat', 'true');
13 | checkDatAvailable();
14 | } else {
15 | document.documentElement.setAttribute('check-dat', 'false');
16 | }
17 | });
18 |
19 | document.getElementById("check-dat").addEventListener('click', function(event) {
20 | // Permissions must be requested from inside a user gesture, like a button's
21 | // click handler.
22 | chrome.permissions.request({
23 | origins: ['https://*/.well-known/dat']
24 | }, function(granted) {
25 | // The callback argument will be true if the user granted the permissions.
26 | if (granted) {
27 | document.documentElement.setAttribute('check-dat', 'true');
28 | } else {
29 | document.documentElement.setAttribute('check-dat', 'false');
30 | }
31 | });
32 | });
33 |
34 | }
--------------------------------------------------------------------------------
/chrome app/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DatPart [App]",
3 | "short_name": "DatPart",
4 | "description": "DatPart server app.",
5 | "manifest_version": 2,
6 |
7 | "version": "0.0.20",
8 | "version_name": "0.0.20 alpha (Debug)",
9 | "permissions": [ "browser", "webview", "*://*.dat_site/*", "*://*.torrent_site/*", "storage", "unlimitedStorage", "fileSystem",
10 | "system.network", "alarms", "power", {"fileSystem":["write","directory","retainEntries"]}],
11 | "optional_permissions": [ "notifications", "*://*/" ],
12 | "externally_connectable": { "ids": [ "hnblaajbillhajijlbaepnjglfgepdgm" ] },
13 | "icons": {
14 | "16": "logo_16.png",
15 | "24": "logo.png",
16 | "32": "logo.png",
17 | "128": "logo_128.png"
18 | },
19 | "sockets": {
20 | "udp": {
21 | "send": [""],
22 | "bind": [""],
23 | "multicastMembership": ""
24 | },
25 | "tcp": {
26 | "connect": [""]
27 | },
28 | "tcpServer": {
29 | "listen": ["*"]
30 | }
31 | },
32 | "manifest_version": 2,
33 | "minimum_chrome_version": "72",
34 | "offline_enabled": true,
35 | "app": {
36 | "background": {
37 | "scripts": ["launch.js"]
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/chrome extension/dat_error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Error
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
25 |
26 | ❗️ Error
27 | The server app might not be running. Open it and then try to load the page again. If that doesn't work, try restarting it. If you don't have the app, you can get it here .
28 |
29 |
--------------------------------------------------------------------------------
/firefox extension/dat_error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Error
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
27 |
28 |
29 | ❗️ Error
30 | The server app might not be running. Run it and then try to load the page again. If you don't have it you can get it here .
31 |
32 |
--------------------------------------------------------------------------------
/chrome extension/qr_code.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | QR Code Generator
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/chrome extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DatPart [Extension]",
3 | "short_name": "DatPart",
4 | "description": "DatPart extension.",
5 | "manifest_version": 2,
6 | "version": "0.0.20",
7 | "version_name": "0.0.20 alpha",
8 | "permissions": ["tabs", "activeTab", "webRequestBlocking", "webRequest", "webNavigation", "proxy", "http://127.0.0.1:9989/*", "http://127.0.0.1:9988/*", "http://localhost:9989/", "http://localhost:9988/", "*://*.dat_site/*", "*://*.torrent_site/*", "storage", "nativeMessaging"],
9 | "optional_permissions": [ "tabs", "notifications", "background", "http://localhost/", "https://*/.well-known/dat" ],
10 | "externally_connectable": { "ids": [ "pgdnnmekclkafnpfofleebhhnmolopgl" ] },
11 | "omnibox": { "keyword" : "DatPart" },
12 | "web_accessible_resources": [
13 | "redirector.html",
14 | "redirector_script.js"
15 | ],
16 | "options_page": "options.html",
17 | "background": {
18 | "persistent": true,
19 | "scripts": ["background.js"]
20 | },
21 | "content_scripts": [
22 | {
23 | "matches": ["*://*.dat_site/*"],
24 | "run_at": "document_start",
25 | "all_frames": true,
26 | "js": ["datsite.js"]
27 | }
28 | ],
29 | "icons": {
30 | "16": "logo_16.png",
31 | "24": "logo.png",
32 | "32": "logo.png",
33 | "128": "logo_128.png"
34 | },
35 | "browser_action": {
36 | "default_icon": {
37 | "16": "logo_16.png",
38 | "24": "logo.png",
39 | "32": "logo.png",
40 | "128": "logo_128.png"
41 | },
42 | "default_title": "DatPart",
43 | "default_popup": "popup.html"
44 | }
45 | }
--------------------------------------------------------------------------------
/chrome app/dat_site.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Dat Site
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Nothing yet...
39 |
40 |
41 |
--------------------------------------------------------------------------------
/firefox extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DatPart [Extension]",
3 | "short_name": "DatPart",
4 | "description": "DatPart extension.",
5 | "manifest_version": 2,
6 | "version": "0.0.7",
7 | "applications": {
8 | "gecko": {
9 | "strict_min_version": "57"
10 | }
11 | },
12 | "homepage_url": "https://github.com/hughisaacs2/DatPart",
13 | "developer": {
14 | "name": "Hugh Isaacs II",
15 | "url": "https://github.com/hughisaacs2/DatPart"
16 | },
17 | "permissions": ["activeTab", "webRequestBlocking", "webRequest", "webNavigation", "proxy", "http://127.0.0.1:9989/*", "http://127.0.0.1:9988/*", "http://localhost:9989/", "http://localhost:9988/", "*://*.dat_site/*", "*://*.torrent_site/*", "storage", "nativeMessaging"],
18 | "optional_permissions": [ "tabs", "notifications", "https://*/", "*://*/", "" ],
19 | "omnibox": { "keyword" : "DatPart" },
20 | "web_accessible_resources": [
21 | "redirector.html",
22 | "redirector_script.js"
23 | ],
24 | "protocol_handlers": [
25 | {
26 | "protocol": "web+dat",
27 | "name": "Web Dat Protocol",
28 | "uriTemplate": "/redirector.html?dat=%s"
29 | },
30 | {
31 | "protocol": "dat",
32 | "name": "Dat Protocol",
33 | "uriTemplate": "/redirector.html?dat=%s"
34 | }
35 | ],
36 | "background": {
37 | "scripts": ["background.js"]
38 | },
39 | "content_scripts": [
40 | {
41 | "matches": ["*://*.dat_site/*"],
42 | "run_at": "document_start",
43 | "js": ["datparse.js"]
44 | }
45 | ],
46 | "icons": {
47 | "16": "logo_16.png",
48 | "24": "logo.png",
49 | "32": "logo.png",
50 | "128": "logo_128.png"
51 | },
52 | "browser_action": {
53 | "default_icon": {
54 | "16": "logo_16.png",
55 | "24": "logo.png",
56 | "32": "logo.png",
57 | "128": "logo_128.png"
58 | },
59 | "default_title": "DatPart",
60 | "default_popup": "popup.html"
61 | }
62 | }
--------------------------------------------------------------------------------
/chrome extension/firefox-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DatPart [Extension]",
3 | "short_name": "DatPart",
4 | "description": "DatPart extension.",
5 | "manifest_version": 2,
6 | "version": "0.0.20",
7 | "applications": {
8 | "gecko": {
9 | "strict_min_version": "57"
10 | }
11 | },
12 | "homepage_url": "https://github.com/hughisaacs2/DatPart",
13 | "developer": {
14 | "name": "Hugh Isaacs II",
15 | "url": "https://github.com/hughisaacs2/DatPart"
16 | },
17 | "permissions": ["activeTab", "webRequestBlocking", "webRequest", "webNavigation", "proxy", "http://127.0.0.1:9989/*", "http://127.0.0.1:9988/*", "http://localhost:9989/", "http://localhost:9988/", "*://*.dat_site/*", "*://*.torrent_site/*", "storage", "nativeMessaging"],
18 | "optional_permissions": [ "tabs", "notifications", "https://*/", "*://*/", "" ],
19 | "omnibox": { "keyword" : "DatPart" },
20 | "web_accessible_resources": [
21 | "redirector.html",
22 | "redirector_script.js"
23 | ],
24 | "protocol_handlers": [
25 | {
26 | "protocol": "web+dat",
27 | "name": "Web Dat Protocol",
28 | "uriTemplate": "/redirector.html?dat=%s"
29 | },
30 | {
31 | "protocol": "dat",
32 | "name": "Dat Protocol",
33 | "uriTemplate": "/redirector.html?dat=%s"
34 | }
35 | ],
36 | "background": {
37 | "scripts": ["background.js"]
38 | },
39 | "content_scripts": [
40 | {
41 | "matches": ["*://*.dat_site/*"],
42 | "run_at": "document_start",
43 | "js": ["datsite.js"]
44 | }
45 | ],
46 | "icons": {
47 | "16": "logo_16.png",
48 | "24": "logo.png",
49 | "32": "logo.png",
50 | "128": "logo_128.png"
51 | },
52 | "browser_action": {
53 | "default_icon": {
54 | "16": "logo_16.png",
55 | "24": "logo.png",
56 | "32": "logo.png",
57 | "128": "logo_128.png"
58 | },
59 | "default_title": "DatPart",
60 | "default_popup": "popup.html"
61 | }
62 | }
--------------------------------------------------------------------------------
/firefox extension/redirector_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | function queryObj() {
6 |
7 | var result = {}, keyValuePairs = location.search.slice(1).split('&');
8 |
9 | keyValuePairs.forEach(function(keyValuePair) {
10 | keyValuePair = keyValuePair.split('=');
11 | result[keyValuePair[0]] = keyValuePair[1] || '';
12 | });
13 |
14 | return result;
15 | }
16 |
17 | var datLink = queryObj()["dat"];
18 |
19 | var datUrl = unescape(datLink);
20 | document.title = "Redirecting to "+datUrl;
21 | document.body.textContent = "Redirecting to "+datUrl;
22 |
23 | if (datUrl.substring(0, 4) == "web+") {
24 | datUrl = datUrl.substring(4, datUrl.length);
25 | document.title = "Redirecting to "+datUrl;
26 | document.body.textContent = "Redirecting to "+datUrl;
27 | }
28 |
29 | document.body.appendChild(document.createElement('br'));
30 |
31 | var redirectLink = document.createElement('a');
32 | redirectLink.className = "button";
33 | redirectLink.textContent = "Redirect";
34 | redirectLink.title = "Click here to redirect to the site if it's not working.";
35 | redirectLink.href = "http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length);
36 | document.body.appendChild(redirectLink);
37 |
38 | var redirectMeta = document.createElement('meta');
39 | redirectMeta.setAttribute("http-equiv", "refresh");
40 | redirectMeta.setAttribute("content", "0; url="+"http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length));
41 | document.head.appendChild(redirectMeta);
42 |
43 | document.location.replace("http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length));
44 | window.location.replace("http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length));
--------------------------------------------------------------------------------
/electron app/resources/datpart/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DatPart",
3 | "productName": "DatPart",
4 | "description": "DatPart server app.",
5 | "homepage": "https://github.com/HughIsaacs2/DatPart",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/HughIsaacs2/DatPart.git"
9 | },
10 | "version": "0.0.20",
11 | "author": "Hugh Isaacs II ",
12 | "license": "MIT",
13 | "main": "launch.js",
14 | "dependencies": {
15 | "dat-node": "3.5.14"
16 | },
17 | "build": {
18 | "files": [
19 | "node_modules/",
20 | "favicon.ico",
21 | "logo.png",
22 | "logo_16.png",
23 | "logo_128.png",
24 | "logo.svg",
25 | "style.css",
26 | "launch.js",
27 | "display_script.js",
28 | "server_script.js",
29 | "index.html",
30 | "server_app.html",
31 | "package.json"
32 | ],
33 | "win": {
34 | "target": [
35 | {
36 | "target": "zip",
37 | "arch": [
38 | "ia32"
39 | ]
40 | }
41 | ],
42 | "icon": "favicon.ico"
43 | },
44 | "dmg": {
45 | "contents": [
46 | {
47 | "x": 130,
48 | "y": 220
49 | },
50 | {
51 | "x": 410,
52 | "y": 220,
53 | "type": "link",
54 | "path": "/Applications"
55 | }
56 | ]
57 | },
58 | "linux": {
59 | "target": [
60 | "AppImage",
61 | "deb"
62 | ]
63 | }
64 | },
65 | "scripts": {
66 | "postinstall": "install-app-deps",
67 | "start": "npm install && electron ./",
68 | "pack": "build --dir",
69 | "dist": "build"
70 | },
71 | "electronVersion": "4.1.2",
72 | "electronDownload": {
73 | "version": "4.1.2"
74 | },
75 | "devDependencies": {
76 | "dat-node": "3.5.14",
77 | "electron": "9.1.0"
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/chrome extension/dat_error.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function queryObj() {
4 |
5 | var result = {}, keyValuePairs = location.search.slice(1).split('&');
6 |
7 | keyValuePairs.forEach(function(keyValuePair) {
8 | keyValuePair = keyValuePair.split('=');
9 | result[keyValuePair[0]] = keyValuePair[1] || '';
10 | });
11 |
12 | return result;
13 | }
14 |
15 | var datLink = queryObj()["dat"];
16 |
17 | var datDomainQuery = queryObj()["dat_domain"];
18 |
19 | var datUrl = unescape(datLink);
20 |
21 | var datDomain = unescape(datDomainQuery);
22 |
23 | if (datUrl.substring(0, 4) == "web+") {
24 | datUrl = datUrl.substring(4, datUrl.length);
25 | }
26 |
27 | if (datDomain == "notyet") {
28 | document.getElementById("message").textContent = "Sorry. Dat Domains aren't supported in " + chrome.runtime.getManifest().short_name + " yet.";
29 | }
30 |
31 | document.body.appendChild(document.createElement('br'));
32 |
33 | var siteInfo = document.createElement('span');
34 | siteInfo.id = "error-site-info";
35 | siteInfo.className = "info-box";
36 | siteInfo.innerText = datUrl;
37 | document.body.appendChild(siteInfo);
38 |
39 | document.body.appendChild(document.createElement('br'));
40 | document.body.appendChild(document.createElement('br'));
41 |
42 | if (datDomain !== "notyet") {
43 | var retryLink = document.createElement('a');
44 | retryLink.href = "http://" + datUrl.substring(6, 70) + ".dat_site" + datUrl.substring(70, datUrl.length);
45 | retryLink.innerText = "Retry";
46 | retryLink.title = "Try loading the page again";
47 | retryLink.className = "button";
48 | document.body.appendChild(retryLink);
49 | }
50 |
51 | document.body.appendChild(document.createElement('br'));
52 | document.body.appendChild(document.createElement('br'));
53 |
54 | var datLink = document.createElement('a');
55 | datLink.href = datUrl;
56 | datLink.title = datUrl;
57 | datLink.innerText = "dat:// link";
58 | datLink.className = "button";
59 | document.body.appendChild(datLink);
--------------------------------------------------------------------------------
/chrome extension/datparse.js:
--------------------------------------------------------------------------------
1 | const isNode = typeof window === 'undefined'
2 | const parse = isNode ? require('url').parse : browserParse
3 |
4 | const SCHEME_REGEX = /[a-z]+:\/\//i
5 | // 1 2 3 4
6 | const VERSION_REGEX = /^(dat:\/\/)?([^/]+)(\+[^/]+)(.*)$/i
7 |
8 | function parseDatURL (str, parseQS) {
9 | // prepend the scheme if it's missing
10 | if (!SCHEME_REGEX.test(str)) {
11 | str = 'dat://' + str
12 | }
13 |
14 | var parsed, version = null, match = VERSION_REGEX.exec(str)
15 | if (match) {
16 | // run typical parse with version segment removed
17 | parsed = parse((match[1] || '') + (match[2] || '') + (match[4] || ''), parseQS)
18 | version = match[3].slice(1)
19 | } else {
20 | parsed = parse(str, parseQS)
21 | }
22 | if (isNode) parsed.href = str // overwrite href to include actual original
23 | parsed.version = version // add version segment
24 | console.log(parsed);
25 | return parsed
26 | }
27 |
28 | function browserParse (str) {
29 | return new URL(str)
30 | }
31 |
32 | var started = false;
33 |
34 | function startup() {
35 | if (started == false) {
36 | started = true;
37 |
38 | Array.from(document.querySelectorAll('[href^="dat://"]')).forEach(function(link){
39 | console.log(parseDatURL(link.href));
40 | //console.log(parseDatURL("dat://2714774d6c464dd12d5f8533e28ffafd79eec23ab20990b5ac14de940680a6fe/rotonde.js"));
41 | //link.href="about:blank";
42 | });
43 |
44 | Array.from(document.querySelectorAll('[src^="dat://"]')).forEach(function(link){
45 | console.log(parseDatURL(link.src));
46 | console.log("separator");
47 | console.log(parseDatURL("dat://2714774d6c464dd12d5f8533e28ffafd79eec23ab20990b5ac14de940680a6fe+1/rotonde.js?lol#ten"));
48 | //link.src="about:blank";
49 | });
50 |
51 | }}
52 |
53 | window.setTimeout(function() {
54 | if (document.readyState === "complete") {
55 | startup();
56 | } else {
57 | document.addEventListener("DOMContentLoaded", startup, false);
58 | document.addEventListener("load", startup, false);
59 | window.addEventListener("load", startup, false);
60 | }
61 |
62 | }, 0);
63 |
--------------------------------------------------------------------------------
/firefox extension/datparse.js:
--------------------------------------------------------------------------------
1 | const isNode = typeof window === 'undefined'
2 | const parse = isNode ? require('url').parse : browserParse
3 |
4 | const SCHEME_REGEX = /[a-z]+:\/\//i
5 | // 1 2 3 4
6 | const VERSION_REGEX = /^(dat:\/\/)?([^/]+)(\+[^/]+)(.*)$/i
7 |
8 | function parseDatURL (str, parseQS) {
9 | // prepend the scheme if it's missing
10 | if (!SCHEME_REGEX.test(str)) {
11 | str = 'dat://' + str
12 | }
13 |
14 | var parsed, version = null, match = VERSION_REGEX.exec(str)
15 | if (match) {
16 | // run typical parse with version segment removed
17 | parsed = parse((match[1] || '') + (match[2] || '') + (match[4] || ''), parseQS)
18 | version = match[3].slice(1)
19 | } else {
20 | parsed = parse(str, parseQS)
21 | }
22 | if (isNode) parsed.href = str // overwrite href to include actual original
23 | parsed.version = version // add version segment
24 | console.log(parsed);
25 | return parsed
26 | }
27 |
28 | function browserParse (str) {
29 | return new URL(str)
30 | }
31 |
32 | var started = false;
33 |
34 | function startup() {
35 | if (started == false) {
36 | started = true;
37 |
38 | Array.from(document.querySelectorAll('[href^="dat://"]')).forEach(function(link){
39 | console.log(parseDatURL(link.href));
40 | //console.log(parseDatURL("dat://2714774d6c464dd12d5f8533e28ffafd79eec23ab20990b5ac14de940680a6fe/rotonde.js"));
41 | //link.href="about:blank";
42 | });
43 |
44 | Array.from(document.querySelectorAll('[src^="dat://"]')).forEach(function(link){
45 | console.log(parseDatURL(link.src));
46 | console.log("separator");
47 | console.log(parseDatURL("dat://2714774d6c464dd12d5f8533e28ffafd79eec23ab20990b5ac14de940680a6fe+1/rotonde.js?lol#ten"));
48 | //link.src="about:blank";
49 | });
50 |
51 | }}
52 |
53 | window.setTimeout(function() {
54 | if (document.readyState === "complete") {
55 | startup();
56 | } else {
57 | document.addEventListener("DOMContentLoaded", startup, false);
58 | document.addEventListener("load", startup, false);
59 | window.addEventListener("load", startup, false);
60 | }
61 |
62 | }, 0);
63 |
--------------------------------------------------------------------------------
/chrome extension/redirector_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | function queryObj() {
6 |
7 | var result = {}, keyValuePairs = location.search.slice(1).split('&');
8 |
9 | keyValuePairs.forEach(function(keyValuePair) {
10 | keyValuePair = keyValuePair.split('=');
11 | result[keyValuePair[0]] = keyValuePair[1] || '';
12 | });
13 |
14 | return result;
15 | }
16 |
17 | var datLink = queryObj()["dat"];
18 |
19 | var datUrl = unescape(datLink);
20 | document.title = "Redirecting to "+datUrl;
21 | document.body.textContent = "Redirecting to "+datUrl;
22 |
23 | if (datUrl.substring(0, 4) == "web+") {
24 | datUrl = datUrl.substring(4, datUrl.length);
25 | document.title = "Redirecting to "+datUrl;
26 | document.body.textContent = "Redirecting to "+datUrl;
27 | }
28 |
29 | var firstBracket = datUrl.indexOf('dat://');
30 | var secondBracket = datUrl.indexOf(0, firstBracket+1);
31 | console.log(datUrl.substring(firstBracket, secondBracket));
32 |
33 | var datPartUrl = "http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length);
34 |
35 | document.body.appendChild(document.createElement('br'));
36 | document.body.appendChild(document.createElement('br'));
37 |
38 | var redirectLink = document.createElement('a');
39 | redirectLink.className = "button";
40 | redirectLink.textContent = "Redirect";
41 | redirectLink.title = "Click here to redirect to the site if it's not working.";
42 | redirectLink.href = "http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length);
43 | document.body.appendChild(redirectLink);
44 |
45 | var redirectMeta = document.createElement('meta');
46 | redirectMeta.setAttribute("http-equiv", "refresh");
47 | redirectMeta.setAttribute("content", "0; url="+"http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length));
48 | document.head.appendChild(redirectMeta);
49 |
50 | document.location.replace("http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length));
51 | window.location.replace("http://"+datUrl.substring(6, 70)+".dat_site"+datUrl.substring(70, datUrl.length));
52 |
--------------------------------------------------------------------------------
/electron app/resources/datpart/server_app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DatPart Server
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
25 |
26 |
--------------------------------------------------------------------------------
/chrome app/server_app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | DatPart Server
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
28 |
29 |
--------------------------------------------------------------------------------
/chrome app/nothing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Nothing.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
69 |
74 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | This page does nothing.
85 |
86 |
87 |
--------------------------------------------------------------------------------
/chrome extension/qr_scanner_script.js:
--------------------------------------------------------------------------------
1 | var video = document.createElement("video");
2 | var canvasElement = document.getElementById("canvas");
3 | var canvas = canvasElement.getContext("2d");
4 | var loadingMessage = document.getElementById("loadingMessage");
5 | var outputContainer = document.getElementById("output");
6 | var outputMessage = document.getElementById("outputMessage");
7 | var outputData = document.getElementById("outputData");
8 |
9 | function drawLine(begin, end, color) {
10 | canvas.beginPath();
11 | canvas.moveTo(begin.x, begin.y);
12 | canvas.lineTo(end.x, end.y);
13 | canvas.lineWidth = 4;
14 | canvas.strokeStyle = color;
15 | canvas.stroke();
16 | }
17 |
18 | // Use facingMode: environment to attemt to get the front camera on phones
19 | navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
20 | video.srcObject = stream;
21 | video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
22 | video.play();
23 | requestAnimationFrame(tick);
24 | });
25 |
26 | function tick() {
27 | loadingMessage.innerText = "⌛ Loading video..."
28 | if (video.readyState === video.HAVE_ENOUGH_DATA) {
29 | loadingMessage.hidden = true;
30 | canvasElement.hidden = false;
31 | outputContainer.hidden = false;
32 |
33 | canvasElement.height = video.videoHeight;
34 | canvasElement.width = video.videoWidth;
35 | canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
36 | var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
37 | var code = jsQR(imageData.data, imageData.width, imageData.height);
38 |
39 | if (code) {
40 | drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
41 | drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
42 | drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
43 | drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
44 | outputMessage.hidden = true;
45 | outputData.parentElement.hidden = false;
46 | outputData.innerText = code.data;
47 | if (code.data.substring(0, 6) == "dat://"){
48 | window.location.hash = "dat="+code.data;
49 | document.getElementById("output-datlink").href = code.data;
50 | document.getElementById("output-datlink").title = code.data;
51 | document.getElementById("output-datlink").hidden = false;
52 | document.getElementById("output-qrlink").href = "/qr_generator.html?code_URL=" + code.data;
53 | document.getElementById("output-qrlink").hidden = false;
54 | document.getElementById("output-link").href = "/redirector.html?link="+code.data;
55 | document.getElementById("output-link").hidden = false;
56 | } else if (code.data.substring(0, 7) == "http://" || code.data.substring(0, 8) == "https://" || code.data.substring(0, 7) == "magnet:") {
57 | document.getElementById("output-link").href = code.data;
58 | document.getElementById("output-link").hidden = false;
59 | document.getElementById("output-datlink").hidden = true;
60 | document.getElementById("output-qrlink").href = "/qr_generator.html?code_URL=" + code.data;
61 | document.getElementById("output-qrlink").hidden = false;
62 | }
63 | } else {
64 | //outputMessage.hidden = false;
65 | //outputData.parentElement.hidden = true;
66 | }
67 | }
68 | requestAnimationFrame(tick);
69 | }
70 |
71 | document.getElementById("version-notice").textContent="This is version "+chrome.runtime.getManifest().version+" of "+chrome.runtime.getManifest().short_name+".";
--------------------------------------------------------------------------------
/firefox extension/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | DatPart - Options
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
35 |
36 |
37 |
38 |
39 | 🔧 The options page isn't ready yet.
40 |
41 |
42 |
51 |
52 | Check Dat available
53 |
54 |
55 |
56 |
57 |
70 |
71 |
--------------------------------------------------------------------------------
/chrome app/loading.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Loading...
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
81 |
86 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Loading...
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/firefox extension/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 100%;
3 | -webkit-text-size-adjust: 100%;
4 | -ms-text-size-adjust: 100%;
5 | text-size-adjust: none;
6 | -moz-osx-font-smoothing: grayscale;
7 | -webkit-font-smoothing: antialiased;
8 | -webkit-overflow-scrolling: touch;
9 | -ms-overflow-style: scrollbar;
10 | scroll-behavior: smooth;
11 | }
12 |
13 | html, body {
14 | width: 100%;
15 | height: 100%;
16 | }
17 |
18 | body {
19 | display: block;
20 | margin: 0;
21 | padding: 0;
22 | border: none;
23 | width: 100%;
24 | height: auto;
25 | min-height: 100%;
26 | text-align: center;
27 | font-size: 100%;
28 | -webkit-text-size-adjust: none;
29 | -ms-text-size-adjust: none;
30 | text-size-adjust: none;
31 | -moz-osx-font-smoothing: grayscale;
32 | -webkit-font-smoothing: antialiased;
33 | overflow: auto;
34 | -ms-overflow-style: scrollbar;
35 | -webkit-overflow-scrolling: touch;
36 | -ms-touch-action: auto;
37 | touch-action: auto;
38 | scroll-behavior: smooth;
39 | font-family: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, Lucida Sans, Lucida Grande, Lucida Sans Unicode, HelveticaNeue-Light, HelveticaNeue, Helvetica, Arial, Verdana, sans-serif, caption, noto, 'Segoe UI Emoji', 'Segoe UI Symbol', 'emoji', 'Apple Color Emoji','EmojiSymbols', 'Symbola';
40 | background-attachment: fixed;
41 | z-index: -1;
42 | -ms-word-break: break-all;
43 | word-break: break-all;
44 | word-break: break-word;
45 | overflow-wrap: break-word;
46 | word-wrap: break-word;
47 | -webkit-hyphens: auto;
48 | -ms-hyphens: auto;
49 | -moz-hyphens: auto;
50 | hyphens: auto;
51 | background-color: #424242;
52 | color: #ffffff;
53 | }
54 |
55 | #universe {
56 | display: block;
57 | clear: both;
58 | margin-left: auto;
59 | margin-right: auto;
60 | //min-height: 100%;
61 | height: auto;
62 | //padding-top: 2px;
63 | padding-bottom: 2px;
64 | border-radius: 4px;
65 | width: calc(100% - 4px);
66 | background-color: #424242;
67 | color: #ffffff;
68 | }
69 |
70 | a, a:visited {
71 | color: #ffffff;
72 | }
73 |
74 | .icon {
75 | display: inline-block;
76 | width: 1em;
77 | height: 1em;
78 | width: 1.4em;
79 | height: 1.4em;
80 | margin-top: 0.4em;
81 | }
82 |
83 | @font-face {
84 | font-family: emoji;
85 |
86 | /* Fonts for text outside emoji blocks */
87 | src: local('Droid Sans Mono'),
88 | local('Lucida Console'),
89 | local('Arial Monospaced'),
90 | local(Arial);
91 | }
92 | @font-face {
93 | font-family: emoji;
94 |
95 | src: local('Apple Color Emoji'),
96 | local('Android Emoji'),
97 | local('Segoe UI Emoji'),
98 | local('Segoe UI'),
99 | local('Segoe UI Symbol'),
100 | local(EmojiSymbols),
101 | local(Symbola),
102 | local(emoji);
103 |
104 | /* Emoji unicode blocks */
105 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
106 | }
107 |
108 | .button {
109 | border: 0;
110 | outline: 0;
111 | -webkit-appearance: none;
112 | -moz-appearance: none;
113 | -webkit-user-select: none;
114 | -khtml-user-select: none;
115 | -moz-user-select: none;
116 | -ms-user-select: none;
117 | user-select: none;
118 | cursor: pointer;
119 | vertical-align: middle;
120 | text-decoration: none;
121 | display: block;
122 | display: inline-block;
123 | position: relative;
124 | color: #ffffff;
125 | background-color: #262C32;
126 | background-color: rgba(38, 44, 50, 0.9);
127 | font-size: 80%;
128 | padding-left: 1em;
129 | padding-right: 1em;
130 | margin-top: 1px;
131 | margin-bottom: 1px;
132 | text-align: center;
133 | display: inline-block;
134 | min-height: 2.1em;
135 | max-width: 80%;
136 | height: auto;
137 | line-height: 2.125em;
138 | text-decoration: none;
139 | //text-transform: uppercase;
140 | text-shadow: none;
141 | border-radius: 4px;
142 | background-repeat: repeat;
143 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
144 | border: none;
145 | border-bottom: 1px solid transparent;
146 | }
147 |
148 | .button:hover, .button:focus {
149 | color: #ffffff;
150 | border: 0;
151 | background-color: rgba(255, 255, 255, 0.3);
152 | box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1), 0 8px 17px 0 rgba(0, 0, 0, 0.2);
153 | border: none;
154 | border-bottom: 1px solid transparent;
155 | }
156 |
157 | .button:active {
158 | background-color: rgba(255, 255, 255, 0.2);
159 | box-shadow: inset 0 2px 0 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.12);
160 | border: none;
161 | border-top: 1px solid transparent;
162 | }
163 |
164 | .button:visited {
165 | color: #ffffff;
166 | }
--------------------------------------------------------------------------------
/chrome extension/credits.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | DatPart - Credits
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
31 |
32 |
33 | Also check out
34 |
35 | Bunsen Browser for Android : A Dat browser for Android (also works on Play Store supporting Chromebooks).
36 | Dat Mobile for Android : Another Dat browser for Android (also works on Play Store supporting Chromebooks).
37 | Dat Fox for Firefox : A Dat extension (similar to this one) for Mozilla Firefox.
38 | Dat_QR (dat:// link): Another Dat QR Code scanner and generator.
39 |
40 |
41 |
42 |
43 |
44 |
45 |
57 |
58 |
--------------------------------------------------------------------------------
/electron app/resources/datpart/launch.js:
--------------------------------------------------------------------------------
1 | var dev = false;
2 |
3 | const {app, BrowserWindow, Menu, Tray} = require('electron')
4 | const path = require('path')
5 | const url = require('url')
6 | const fs = require('fs')
7 |
8 | // Keep a global reference of the window object, if you don't, the window will
9 | // be closed automatically when the JavaScript object is garbage collected.
10 | let win
11 | let tray = null
12 |
13 | var versionNumber = app.getVersion();
14 | var appName = app.getName();
15 | var appIcon = __dirname+'/logo_128.png';
16 | var appPath = app.getAppPath();
17 |
18 | global.sharedObject = {
19 | appVersionNumber: versionNumber
20 | }
21 |
22 | if (fs.existsSync(__dirname + '/../../dev.hta')) {
23 | dev = true;
24 | }
25 |
26 | if (!fs.existsSync(__dirname + '/../../dats/')) {
27 | fs.mkdirSync(__dirname + '/../../dats/');
28 | }
29 |
30 | function createWindow () {
31 | // Create the browser window.
32 | win = new BrowserWindow({
33 | width: 800,
34 | height: 600,
35 | icon: appIcon,
36 | backgroundColor: '#424242',
37 | show: false
38 | })
39 |
40 | const devTopMenu = Menu.buildFromTemplate([
41 | {label: appName + " v" + versionNumber + " dev mode"},
42 | {label: 'Quit for real', click: function() {app.isQuiting = true; app.quit();}}
43 | ])
44 |
45 | // Open the DevTools if dev is true.
46 | if(dev == true) {
47 | win.setMenu(devTopMenu)
48 | win.setThumbnailToolTip(appName + " v" + versionNumber + " dev mode")
49 | win.setTitle(appName + " v" + versionNumber + " dev mode")
50 | win.webContents.openDevTools({mode:'detach'})
51 | } else if (dev != true) {
52 | win.setMenu(null)
53 | win.setThumbnailToolTip(appName + " v" + versionNumber)
54 | win.setTitle(appName + " v" + versionNumber)
55 | }
56 |
57 | win.on('show', () => {
58 | if(dev == true) {
59 | win.webContents.openDevTools({mode:'detach'})
60 | }
61 | })
62 |
63 | // and load the index.html of the app.
64 | win.loadURL('file://' + __dirname + '/server_app.html')
65 |
66 | win.on('close', function (event) {
67 | if( !app.isQuiting){
68 | event.preventDefault()
69 | win.hide();
70 | }
71 | return false;
72 | });
73 |
74 | // Emitted when the window is closed.
75 | win.on('closed', () => {
76 | // Dereference the window object, usually you would store windows
77 | // in an array if your app supports multi windows, this is the time
78 | // when you should delete the corresponding element.
79 | win = null
80 | })
81 |
82 | }
83 | app.requestSingleInstanceLock()
84 | app.on('second-instance', (event, argv, cwd) => {
85 | app.quit()
86 | })
87 | /*
88 | const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
89 | // Someone tried to run a second instance, we should focus our window.
90 | if (win) {
91 | if (win.isMinimized()) win.restore()
92 | win.show()
93 | win.focus()
94 | }
95 | })
96 |
97 | if (isSecondInstance) {
98 | app.quit()
99 | }
100 | */
101 | app.on('ready', () => {
102 | if (!fs.existsSync(__dirname + '/../../dats/')) {
103 | fs.mkdirSync(__dirname + '/../../dats/');
104 | }
105 |
106 | tray = new Tray(appIcon)
107 |
108 | const contextMenu = Menu.buildFromTemplate([
109 | {label: 'Show', click: function() {win.show();}},
110 | {label: 'Quit', click: function() {app.isQuiting = true; app.quit();}}
111 | ])
112 |
113 | const devContextMenu = Menu.buildFromTemplate([
114 | {label: 'Show', click: function() {win.show();}},
115 | {label: 'Quit', click: function() {app.isQuiting = true; app.quit();}},
116 | {label: appName + " v" + versionNumber + " dev mode"}
117 | ])
118 |
119 | if(dev == true) {
120 | tray.setContextMenu(devContextMenu)
121 | tray.setToolTip(appName + " v" + versionNumber + " dev mode")
122 | } else if (dev != true) {
123 | tray.setContextMenu(contextMenu)
124 | tray.setToolTip(appName + " v" + versionNumber)
125 | }
126 |
127 | tray.on('click', () => {
128 | win.show()
129 | })
130 |
131 | if(app.isDefaultProtocolClient(appName)) {
132 |
133 | } else {
134 | app.setAsDefaultProtocolClient(appName)
135 | }
136 |
137 | //var openingNotification = new Notification({title: "ggggggggo", body: "lol"})
138 | //openingNotification.show()
139 |
140 | createWindow();
141 | })
142 |
143 | app.on('activate', () => {
144 | // On macOS it's common to re-create a window in the app when the
145 | // dock icon is clicked and there are no other windows open.
146 | if (win === null) {
147 | createWindow()
148 | }
149 | })
--------------------------------------------------------------------------------
/chrome extension/options_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | document.documentElement.className=document.documentElement.className.replace("no-js","js");
3 | window.scrollTo(0, 1);
4 |
5 | function saveProxySettings() {
6 | console.log(document.getElementById("proxyaccess").value + ' ' + document.getElementById("proxyurl").value);
7 | var theGate = {};
8 | theGate = {
9 | 'proxyurl': document.getElementById("proxyurl").value,
10 | 'proxyaccess': document.getElementById("proxyaccess").value
11 | };
12 | var gatewaySet = {};
13 | gatewaySet["gatewaySettings"] = theGate;
14 | chrome.storage.local.set(gatewaySet, function() {
15 | console.log('Gateway settings set to ' + theGate);
16 | console.log(theGate);
17 | });
18 |
19 | chrome.notifications.getPermissionLevel(function(granted){
20 | chrome.notifications.create("proxysettingssaved", {
21 | type: "basic",
22 | title: "Proxy setting saved!",
23 | message: "Proxy setting successfully saved.",
24 | contextMessage: "Set to: "+document.getElementById("proxyaccess").value + ' ' + document.getElementById("proxyurl").value,
25 | iconUrl: "logo.svg"
26 | });
27 | });
28 | window.setTimeout(function(){ chrome.notifications.clear("proxysettingssaved"); }, 1800);
29 |
30 | };
31 |
32 | function defaultProxySettings() {
33 | document.getElementById("proxyurl").value = "localhost:9989";
34 | document.getElementById("proxyaccess").value = "PROXY";
35 | saveProxySettings();
36 | };
37 |
38 | window.onload = function(){
39 | document.getElementById("version-notice").textContent="This is version "+chrome.runtime.getManifest().version+" of DatPart.";
40 |
41 | chrome.permissions.contains({
42 | origins: ['https://*/.well-known/dat']
43 | }, function(result) {
44 | if (result) {
45 | document.documentElement.setAttribute('check-dat', 'true');
46 | document.getElementById("check-dat").checked = true;
47 | } else {
48 | document.documentElement.setAttribute('check-dat', 'false');
49 | document.getElementById("check-dat").checked = false;
50 | }
51 | });
52 |
53 | chrome.permissions.contains({
54 | permissions: ['notifications']
55 | }, function(result) {
56 | if (result) {
57 | document.getElementById("check-notifications").checked = true;
58 | } else {
59 | document.getElementById("check-notifications").checked = false;
60 | }
61 | });
62 |
63 | document.getElementById("check-dat").addEventListener('change', function(event) {
64 | // Permissions must be requested from inside a user gesture, like a button's
65 | // click handler.
66 | if (document.getElementById("check-dat").checked == true) {
67 |
68 | chrome.permissions.request({
69 | origins: ['https://*/.well-known/dat']
70 | }, function(granted) {
71 | // The callback argument will be true if the user granted the permissions.
72 | if (granted) {
73 | document.documentElement.setAttribute('check-dat', 'true');
74 | } else {
75 | document.documentElement.setAttribute('check-dat', 'false');
76 | }
77 | });
78 |
79 | } else if (document.getElementById("check-dat").checked == false) {
80 |
81 | chrome.permissions.remove({
82 | origins: ['https://*/.well-known/dat']
83 | }, function(removed) {
84 | // The callback argument will be true if the user granted the permissions.
85 | if (removed) {
86 | document.documentElement.setAttribute('check-dat', 'true');
87 | } else {
88 | document.documentElement.setAttribute('check-dat', 'false');
89 | }
90 | });
91 | }
92 |
93 | });
94 |
95 | document.getElementById("proxydefault").addEventListener('click', defaultProxySettings);
96 |
97 | document.getElementById("proxysave").addEventListener('click', saveProxySettings);
98 |
99 | document.getElementById("check-notifications").addEventListener('change', function(event) {
100 | // Permissions must be requested from inside a user gesture, like a button's
101 | // click handler.
102 | if (document.getElementById("check-notifications").checked == true) {
103 |
104 | chrome.permissions.request({
105 | permissions: ['notifications']
106 | }, function(granted) {
107 | // The callback argument will be true if the user granted the permissions.
108 | if (granted) {
109 |
110 | } else {
111 |
112 | }
113 | });
114 |
115 | } else if (document.getElementById("check-notifications").checked == false) {
116 |
117 | chrome.permissions.remove({
118 | permissions: ['notifications']
119 | }, function(removed) {
120 | // The callback argument will be true if the user granted the permissions.
121 | if (removed) {
122 |
123 | } else {
124 |
125 | }
126 | });
127 | }
128 |
129 | });
130 |
131 | }
--------------------------------------------------------------------------------
/firefox extension/popup.js:
--------------------------------------------------------------------------------
1 | var appip = "127.0.0.1";
2 | var port = "9989";
3 | var commandPort = "9988";
4 |
5 | function checkTab() {
6 | chrome.tabs.query (
7 | { currentWindow: true, active: true },
8 | function(tabs) {
9 | var activeTab = tabs[0];
10 | console.log(JSON.stringify(activeTab));
11 |
12 | var currentURLRequest = document.createElement('a');
13 | currentURLRequest.href = activeTab.url;
14 |
15 | var currentTLD = currentURLRequest.hostname.split(".").pop();
16 | console.log(currentTLD);
17 |
18 | if (currentTLD != 'dat_site') {
19 | document.documentElement.setAttribute('dat-site', 'false');
20 |
21 | return;
22 | } else {
23 | document.documentElement.setAttribute('dat-site', 'true');
24 |
25 | var siteURL = document.getElementById("site-url");
26 | siteURL.innerText = activeTab.url;
27 |
28 | var siteTitle = document.getElementById("site-title");
29 | siteTitle.innerText = activeTab.title;
30 |
31 | var faviconIMG = document.getElementById("site-favicon");
32 | faviconIMG.src = activeTab.favIconUrl;
33 | faviconIMG.title = activeTab.title;
34 |
35 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
36 | console.log(currentURLhostNoTLD);
37 | /*
38 | var datHash = currentURLRequest.hostname;
39 | var datUrlPathname = currentURLRequest.pathname;
40 | var datUrlSearch = currentURLRequest.search;
41 | var datUrlHash = currentURLRequest.hash;
42 | */
43 | siteURL.innerText = "dat://" + currentURLhostNoTLD + currentURLRequest.pathname + currentURLRequest.search + currentURLRequest.hash;
44 |
45 | }
46 |
47 | });
48 | }
49 |
50 | function pinSite() {
51 | chrome.tabs.query (
52 | { currentWindow: true, active: true },
53 | function(tabs) {
54 | var activeTab = tabs[0];
55 | console.log(JSON.stringify(activeTab));
56 |
57 | var currentURLRequest = document.createElement('a');
58 | currentURLRequest.href = activeTab.url;
59 |
60 | var currentTLD = currentURLRequest.hostname.split(".").pop();
61 | console.log(currentTLD);
62 |
63 | if (currentTLD != 'dat_site') {
64 | return;
65 | } else {
66 |
67 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
68 | console.log(currentURLhostNoTLD);
69 |
70 | var myHeaders = new Headers();
71 | myHeaders.append("Content-Type", "text/plain");
72 | myHeaders.append("Type", "dat");
73 | myHeaders.append("Dat", currentURLhostNoTLD);
74 | myHeaders.append("Task", "pin");
75 |
76 | fetch("http://"+ appip +":" + commandPort + "/pin/", {
77 | method: "POST",
78 | headers: myHeaders
79 | }).then(function(response) {
80 | console.log(response);
81 | }).then(function(data) {
82 | console.log(data);
83 | });
84 |
85 | }
86 |
87 | });
88 | }
89 |
90 | function unpinSite() {
91 | chrome.tabs.query (
92 | { currentWindow: true, active: true },
93 | function(tabs) {
94 | var activeTab = tabs[0];
95 | console.log(JSON.stringify(activeTab));
96 |
97 | var currentURLRequest = document.createElement('a');
98 | currentURLRequest.href = activeTab.url;
99 |
100 | var currentTLD = currentURLRequest.hostname.split(".").pop();
101 | console.log(currentTLD);
102 |
103 | if (currentTLD != 'dat_site') {
104 | return;
105 | } else {
106 |
107 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
108 | console.log(currentURLhostNoTLD);
109 |
110 | var myHeaders = new Headers();
111 | myHeaders.append("Content-Type", "text/plain");
112 | myHeaders.append("Type", "dat");
113 | myHeaders.append("Dat", currentURLhostNoTLD);
114 | myHeaders.append("Task", "unpin");
115 |
116 | fetch("http://"+ appip +":" + commandPort + "/unpin/", {
117 | method: "POST",
118 | headers: myHeaders
119 | }).then(function(response) {
120 | console.log(response);
121 | }).then(function(data) {
122 | console.log(data);
123 | });
124 |
125 | }
126 |
127 | });
128 | }
129 |
130 | window.onload = function(){
131 |
132 | checkTab();
133 |
134 | chrome.tabs.onUpdated.addListener(checkTab);
135 |
136 | document.getElementById("pin").addEventListener("click",pinSite);
137 |
138 | document.getElementById("unpin").addEventListener("click",unpinSite);
139 |
140 | };
--------------------------------------------------------------------------------
/chrome extension/qr_generator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | QR Code Generator
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
39 |
40 | QR Code generator powered by the qrcode-svg library.
41 |
42 |
43 |
44 |
45 |
58 |
59 |
--------------------------------------------------------------------------------
/chrome app/logo.svg:
--------------------------------------------------------------------------------
1 |
2 | image/svg+xml
--------------------------------------------------------------------------------
/chrome extension/logo.svg:
--------------------------------------------------------------------------------
1 |
2 | image/svg+xml
--------------------------------------------------------------------------------
/firefox extension/logo.svg:
--------------------------------------------------------------------------------
1 |
2 | image/svg+xml
--------------------------------------------------------------------------------
/electron app/resources/datpart/logo.svg:
--------------------------------------------------------------------------------
1 |
2 | image/svg+xml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DatPart
2 | Proof of concept [Dat](https://datproject.org/) site viewer extension [and app] for Chrome.
3 |
4 | Sites can be loaded via the .dat_site. top-level domain.
5 |
6 | For example you can load the Acrylic Style Dat site at http://1c7639eedaf8f7533f92e7c34f5a6d2b43645347836ab5e9f2489e89d3b08306.dat_site/
7 |
8 | Oh also, Chrome's Omnibar treats all non-standard TLDs as searches, so you'll have to type the inital HTTP:// or put a slash at the end of the URL for it to load the site.
9 |
10 | (BitTorrent/WebTorrent support coming soon, it's already coded into the extension just not the server app. Also it'll load the same torrent sites as [PeerCloud](https://github.com/jhiesey/peercloud) and [BitTorrent Maelstrom](http://blog.bittorrent.com/2014/12/10/project-maelstrom-the-internet-we-build-next/))
11 |
12 | ### Try it
13 |
14 | [Get the Chrome extension here](https://chrome.google.com/webstore/detail/datpart-extension/hnblaajbillhajijlbaepnjglfgepdgm)
15 |
16 | [Get the Desktop app here](https://github.com/HughIsaacs2/DatPart/releases)
17 |
18 | Note: You need both for this to work.
19 |
20 | ### How this works
21 |
22 | Basically all this does is use the Chrome Extension WebRequest API and Proxy API to intercept any requests to the top level domain .dat_site. When that TLD is requested, Chrome uses the Proxy API to redirect the request to the local Electron server at http://127.0.0.1:9989/ and from there the server loads the Dat (using sparse mode) and returns the page or file that was requested.
23 |
24 | ### To-Do
25 |
26 | * Update to [Hypercore/Hyperdrive](https://blog.datproject.org/2020/05/15/dat-protocol-renamed-hypercore-protocol/).
27 | * Firefox support (this is trouble as [the Firefox WebExtension Proxy API](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/proxy) is different, I'm just being lazy here).
28 | * Firefox for Android support.
29 | * Opera support.
30 | * Mac OS support.
31 | * Linux support.
32 | * ~~Chrome OS support (aka a Chrome packaged app).~~ (In the works!)
33 | * ~~WebRTC support (for Chrome OS and providing a web proxy).~~ (In the works!)
34 | * UDP support on Chrome OS.
35 | * dat:// link support.
36 | * This'll require coming up with a way to simply parse Dat URLs in a regular web browser, as [parse-dat-url](https://github.com/pfrazee/parse-dat-url "parse-dat-url") doesn't work very well on the web (there's likely a fix that can be done with regular expressions but I suck at them so... yeah).
37 | * Have the extension automatically open the app in the background when a .dat_site is requested via the [Native Messaging API](https://developer.chrome.com/apps/nativeMessaging).
38 | * Polyfill [the Beaker Browser APIs](https://beakerbrowser.com/docs/apis/) (doesn't need all of them, just the ones to make sure certain sites are viewable, e.g. [Fritter](https://github.com/beakerbrowser/fritter) and [Rotonde](https://github.com/Rotonde/rotonde-client) sites).
39 | * ~~Notifications! For everything possible (optional of course).~~ ✓
40 | * ~~Options! (A real options page)~~ ✓
41 | * Let the user set the port of the local server via options using the [Native Messaging API](https://developer.chrome.com/apps/nativeMessaging).
42 | * Optional background functionality.
43 | * Maybe support regular domain names [the way Beaker Browser does](https://beakerbrowser.com/2017/02/22/beaker-0-6-1.html), I don't know how this would be done via a browser extension but I feel like it might be possible (if well executed this could be useful for easing bandwidth/data use on certain sites).
44 | * Safari support?
45 | * Internet Explorer support?
46 |
47 | ## To-Do [Short term + more specific list]
48 | * ~~Dat URL for current tab in the extension pop up.~~ ✓
49 | * ~~Support for 404 pages by reading “fallback_page” in dat.json (updated this further to work the same way it does in Beaker Browser).~~ ✓
50 | * A button in the extension pop up to tell the app to download the entire Dat.
51 | * A button in the extension pop up to tell the app to delete the entire Dat.
52 | * ~~A landing page for introducing users to the extension/app.~~ ✓
53 | * ~~Display a badge for Dat sites.~~ ✓
54 | * ~~The ability to submit dat links or hashes as searches in the extension via the [omnibox API](https://developer.chrome.com/extensions/omnibox) (needs [Dat parse](https://github.com/pfrazee/parse-dat-url "parse-dat-url") for web).~~ (Works via hacky method, needs lots of improving)
55 | * Come up with a fallback for when the dat can't be found (Maybe a "Did you mean?" page or something).
56 | * Fix how much the server app checks for the dat.json file (it seriously goes nuts, checks the network for dat.json again on every HTTP request).
57 | * Code something to let the extension know to hide the "Pin" or "Unpin" button (likely going to be more HTTP headers, for now).
58 | * Build a web page that displays a list of the Dats stored offline for clarity (this is the last thing I need before building a Mac OS X and Linux version).
59 | * A page for deleting dats and other information.
60 | * Get Travis CI working with this repo to auto-build Mac OS X and Linux versions.
61 | * Get AppVeyor working with this repo to auto-build Windows versions.
62 | * Provide an optional feature to convert dat:// URLs that aren't anchor links to anchor links (Useful for sites like Twitter).
63 | * Provide an option to have said links either stay in the dat:// URL format for Beaker Browser or other Dat apps, or to have them switch to the .dat_site domain name format for DatPart to open them (consider providing a context menu item for letting users on the fly decide what should be done).
64 |
65 | ## Credits
66 | * dat-node - https://github.com/datproject/dat-node (MIT License)
67 | * dat-js - https://github.com/datproject/dat-js
68 | * jsQR - https://github.com/cozmo/jsQR (Apache License 2.0)
69 | * qrcode-svg - https://github.com/papnkukn/qrcode-svg (MIT License)
70 | * Font Awesome v4.7.0 - https://fontawesome.com/v4.7.0/ (CC BY 4.0 License)
71 | * Chrome Apps Samples Web Server - https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webserver (Apache License 2.0)
72 |
73 | ## Donate
74 | Donate to the [Dat Project](https://donate.datproject.org/) and the [Beaker Browser](https://opencollective.com/beaker?referral=17298) teams, we're not affiliated but this relies on their work.
75 |
--------------------------------------------------------------------------------
/chrome extension/qr_scanner.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | QR Code Scanner
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
36 |
37 |
38 |
39 |
40 |
41 | Unable to access video stream (please make sure you have a webcam enabled)
42 |
43 |
44 |
45 |
No QR code detected.
46 |
51 |
52 |
53 |
54 |
55 | QR Code scanner powered by the jsQR library.
56 |
57 |
58 |
59 |
60 |
73 |
74 |
--------------------------------------------------------------------------------
/chrome extension/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | DatPart - Options
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Gateway
25 |
26 | PROXY
27 | HTTP
28 | HTTPS
29 | SOCKS
30 | SOCKS4
31 | SOCKS5
32 |
33 |
34 |
35 |
36 | Save
37 |
38 | Default
39 |
40 | Permissions
41 |
46 |
47 | Tools
48 |
49 | QR Code Generator
50 |
51 | QR Code Scanner (Requires camera)
52 |
53 | Links
54 |
65 |
66 |
67 |
68 |
69 |
82 |
83 |
--------------------------------------------------------------------------------
/chrome extension/welcome.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ✨ Welcome!
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Before you can start viewing Dat sites with this extension you must first download and run the companion desktop app , if you haven't already.
24 |
25 | Then once it's installed and running, test it with the official Acrylic Style Dat site (shameless promo) to see if it works.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | Official DatProject Dat site
36 |
37 |
38 |
39 |
40 |
41 |
42 | Official Beaker Browser Dat site
43 |
44 |
45 |
58 |
59 |
--------------------------------------------------------------------------------
/firefox extension/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | DatPart!
4 |
5 |
64 |
65 |
66 |
82 |
--------------------------------------------------------------------------------
/chrome app/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: emoji;
3 |
4 | /* Fonts for text outside emoji blocks */
5 | src: local('Droid Sans Mono'),
6 | local('Lucida Console'),
7 | local('Arial Monospaced'),
8 | local(Arial);
9 | }
10 | @font-face {
11 | font-family: emoji;
12 |
13 | src: local('Apple Color Emoji'),
14 | local('Android Emoji'),
15 | local('Segoe UI'),
16 | local('Segoe UI Symbol'),
17 | local(EmojiSymbols),
18 | local(Symbola),/*,
19 | url('fonts/Symbola-Emoji.eot?#iefix') format('embedded-opentype'),
20 | url('fonts/Symbola-Emoji.woff') format('woff'),
21 | url('fonts/Symbola-Emoji.ttf') format('truetype')*/
22 | local(emoji);
23 |
24 | /* Emoji unicode blocks */
25 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
26 | }
27 |
28 | @font-face {
29 | font-family: emoji;
30 |
31 | /* Fonts for text outside emoji blocks */
32 | src: local('Droid Sans Mono'),
33 | local('Lucida Console'),
34 | local('Arial Monospaced'),
35 | local(Arial);
36 | }
37 | @font-face {
38 | font-family: emoji;
39 |
40 | src: local('Apple Color Emoji'),
41 | local('Android Emoji'),
42 | local('Segoe UI Emoji'),
43 | local('Segoe UI'),
44 | local('Segoe UI Symbol'),
45 | local(EmojiSymbols),
46 | local(Symbola),
47 | local(emoji);
48 |
49 | /* Emoji unicode blocks */
50 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
51 | }
52 |
53 |
54 | :root {
55 | //--widget-color: rgba(51, 105, 158, 0.9);
56 | --widget-color: rgba(41, 147, 251, 0.9);
57 | }
58 |
59 | /* background-color: #bada55; */
60 |
61 | html {
62 | font-size: 100%;
63 | -webkit-text-size-adjust: 100%;
64 | -ms-text-size-adjust: 100%;
65 | text-size-adjust: none;
66 | -moz-osx-font-smoothing: grayscale;
67 | -webkit-font-smoothing: antialiased;
68 | -webkit-overflow-scrolling: touch;
69 | -ms-overflow-style: scrollbar;
70 | scroll-behavior: smooth;
71 | }
72 |
73 | html, body {
74 | width: 100%;
75 | height: 100%;
76 | }
77 |
78 | body {
79 | display: block;
80 | margin: 0;
81 | padding: 0;
82 | border: none;
83 | width: 100%;
84 | height: auto;
85 | min-height: 100%;
86 | text-align: center;
87 | font-size: 100%;
88 | -webkit-text-size-adjust: none;
89 | -ms-text-size-adjust: none;
90 | text-size-adjust: none;
91 | -moz-osx-font-smoothing: grayscale;
92 | -webkit-font-smoothing: antialiased;
93 | overflow: auto;
94 | -ms-overflow-style: scrollbar;
95 | -webkit-overflow-scrolling: touch;
96 | -ms-touch-action: auto;
97 | touch-action: auto;
98 | scroll-behavior: smooth;
99 | font-family: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, Lucida Sans, Lucida Grande, Lucida Sans Unicode, HelveticaNeue-Light, HelveticaNeue, Helvetica, Arial, Verdana, sans-serif, caption, noto, 'Segoe UI Emoji', 'Segoe UI Symbol', 'emoji', 'Apple Color Emoji','EmojiSymbols', 'Symbola';
100 | background-attachment: fixed;
101 | z-index: -1;
102 | -ms-word-break: break-all;
103 | word-break: break-all;
104 | word-break: break-word;
105 | overflow-wrap: break-word;
106 | word-wrap: break-word;
107 | -webkit-hyphens: auto;
108 | -ms-hyphens: auto;
109 | -moz-hyphens: auto;
110 | hyphens: auto;
111 | background-color: #424242;
112 | color: #ffffff;
113 | }
114 |
115 | #universe {
116 | display: block;
117 | clear: both;
118 | margin-left: auto;
119 | margin-right: auto;
120 | height: auto;
121 | min-height: 150px;
122 | //padding-top: 2px;
123 | padding-bottom: 2px;
124 | border-radius: 4px;
125 | width: calc(100% - 4px);
126 | background-color: #424242;
127 | color: #ffffff;
128 |
129 | position: relative;
130 | top: 2px;
131 | margin-bottom: 3px;
132 | }
133 |
134 | a, a:visited {
135 | color: #ffffff;
136 | }
137 |
138 | *[hidden] {
139 | display: none !important;
140 | }
141 |
142 | .icon {
143 | display: inline-block;
144 | width: 1em;
145 | height: 1em;
146 | //width: 1.4em;
147 | //height: 1.4em;
148 | margin-top: 0.4em;
149 | }
150 |
151 |
152 | .button {
153 | border: 0;
154 | outline: 0;
155 | -webkit-appearance: none;
156 | -moz-appearance: none;
157 | -webkit-user-select: none;
158 | -khtml-user-select: none;
159 | -moz-user-select: none;
160 | -ms-user-select: none;
161 | user-select: none;
162 | cursor: pointer;
163 | vertical-align: middle;
164 | text-decoration: none;
165 | display: block;
166 | display: inline-block;
167 | position: relative;
168 | color: #ffffff;
169 | background-color: var(--widget-color);
170 | font-size: 80%;
171 | padding-left: 1em;
172 | padding-right: 1em;
173 | margin-top: 1px;
174 | margin-bottom: 1px;
175 | text-align: center;
176 | display: inline-block;
177 | min-height: 2.1em;
178 | max-width: 80%;
179 | height: auto;
180 | line-height: 2.125em;
181 | text-decoration: none;
182 | //text-transform: uppercase;
183 | text-shadow: none;
184 | border-radius: 4px;
185 | background-repeat: repeat;
186 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
187 | border: none;
188 | border-bottom: 1px solid transparent;
189 | }
190 |
191 | .button:hover, .button:focus {
192 | color: #ffffff;
193 | border: 0;
194 | background-color: rgba(255, 255, 255, 0.3);
195 | box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1), 0 8px 17px 0 rgba(0, 0, 0, 0.2);
196 | border: none;
197 | border-bottom: 1px solid transparent;
198 | }
199 |
200 | .button:active {
201 | background-color: rgba(255, 255, 255, 0.2);
202 | box-shadow: inset 0 2px 0 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.12);
203 | border: none;
204 | border-top: 1px solid transparent;
205 | }
206 |
207 | .button:visited {
208 | color: #ffffff;
209 | }
210 |
211 | .button[hidden] {
212 | visibility: hidden;
213 | display: none;
214 | opacity: 0;
215 | }
216 |
217 | .dropdown {
218 | border: 0;
219 | outline: 0;
220 | -webkit-appearance: menulist;
221 | -moz-appearance: menulist;
222 | -webkit-user-select: none;
223 | -khtml-user-select: none;
224 | -moz-user-select: none;
225 | -ms-user-select: none;
226 | user-select: none;
227 | cursor: pointer;
228 | vertical-align: middle;
229 | text-decoration: none;
230 | display: block;
231 | display: inline-block;
232 | position: relative;
233 | color: #ffffff;
234 | background-color: var(--widget-color);
235 | font-size: 80%;
236 | padding-left: 1em;
237 | padding-right: 1em;
238 | margin-top: 1px;
239 | margin-bottom: 1px;
240 | text-align: center;
241 | display: inline-block;
242 | min-height: 2.1em;
243 | max-width: 80%;
244 | height: auto;
245 | line-height: 2.125em;
246 | text-decoration: none;
247 | //text-transform: uppercase;
248 | text-shadow: none;
249 | border-radius: 2px;
250 | background-repeat: repeat;
251 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
252 | border: none;
253 | border-bottom: 1px solid transparent;
254 | }
255 |
256 | input[type=checkbox].toggle {
257 | height: 0;
258 | width: 0;
259 | visibility: hidden;
260 | }
261 |
262 | label.toggle {
263 | cursor: pointer;
264 | text-indent: -9999px;
265 | width: 2em;
266 | height: 1em;
267 | background-color: grey;
268 | display: inline-block;
269 | border-radius: 100px;
270 | position: relative;
271 | top: 0.2em;
272 | overflow: hidden;
273 | }
274 |
275 | label.toggle:after {
276 | content: '';
277 | position: absolute;
278 | top: 0.05em;
279 | left: 0.05em;
280 | width: 0.9em;
281 | height: 0.9em;
282 | background-color: #fff;
283 | border-radius: 90px;
284 | transition-duration: 0.3s;
285 | transition-property: transform;
286 | transform: scaleX(1);
287 | }
288 |
289 | input.toggle:checked + label.toggle {
290 | background-color: var(--widget-color);
291 | }
292 |
293 | input.toggle:checked + label.toggle:after {
294 | transform: translateX(1em);
295 | }
296 |
297 | label.toggle:active:after {
298 | transform: scaleX(2);
299 | }
300 |
301 | input.toggle:checked + label.toggle:active:after {
302 | transform: scaleX(2);
303 | }
304 |
305 | .button, input.toggle:checked + label.toggle {
306 | background-color: var(--widget-color);
307 | }
308 |
309 | input.textbox {
310 | border-radius: 4px;
311 | border: 0;
312 | outline: 0;
313 | -webkit-appearance: none;
314 | -moz-appearance: none;
315 | vertical-align: middle;
316 | font-size: 80%;
317 | padding-left: 1em;
318 | padding-right: 1em;
319 | margin-top: 1px;
320 | margin-bottom: 1px;
321 | text-align: center;
322 | display: inline-block;
323 | min-height: 2.1em;
324 | max-width: 80%;
325 | height: auto;
326 | line-height: 2.125em;
327 | text-decoration: none;
328 | border: none;
329 | box-shadow: inset 0 2px 5px 0 rgba(0, 0, 0, 0.26);
330 | }
331 |
332 | .info-box {
333 | display: inline-block;
334 | font-family: monospace;
335 | background-color: #313131;
336 | padding: 4px;
337 | border-radius: 4px;
338 | //max-width: 20%;
339 | //max-width: calc(20% - 8px);
340 | }
341 |
342 | #version-notice {
343 | display: block;
344 | position: fixed;
345 | bottom: 0;
346 | left: 0;
347 | float: left;
348 | opacity: 0.5;
349 | }
350 |
351 | #app-user-agent {
352 | position: fixed;
353 | bottom: 0;
354 | left: 0;
355 | text-align: left;
356 | font-size: 10px;
357 | color: rgba(255,255,255,0.5);
358 | z-index: -1;
359 | }
360 |
361 | #logger {
362 | display: block;
363 | overflow: auto;
364 | overflow-y: auto;
365 | white-space: pre;
366 | -ms-word-break: break-all;
367 | word-break: break-all;
368 | word-break: break-word;
369 | overflow-wrap: break-word;
370 | word-wrap: break-word;
371 | -webkit-hyphens: auto;
372 | -ms-hyphens: auto;
373 | -moz-hyphens: auto;
374 | hyphens: auto;
375 | max-height: 250px;
376 | border-top: solid 1px #c6c6c6;
377 | border-bottom: solid 1px #c6c6c6;
378 | }
--------------------------------------------------------------------------------
/chrome extension/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: emoji;
3 |
4 | /* Fonts for text outside emoji blocks */
5 | src: local('Droid Sans Mono'),
6 | local('Lucida Console'),
7 | local('Arial Monospaced'),
8 | local(Arial);
9 | }
10 | @font-face {
11 | font-family: emoji;
12 |
13 | src: local('Apple Color Emoji'),
14 | local('Android Emoji'),
15 | local('Segoe UI'),
16 | local('Segoe UI Symbol'),
17 | local(EmojiSymbols),
18 | local(Symbola),/*,
19 | url('fonts/Symbola-Emoji.eot?#iefix') format('embedded-opentype'),
20 | url('fonts/Symbola-Emoji.woff') format('woff'),
21 | url('fonts/Symbola-Emoji.ttf') format('truetype')*/
22 | local(emoji);
23 |
24 | /* Emoji unicode blocks */
25 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
26 | }
27 |
28 | @font-face {
29 | font-family: emoji;
30 |
31 | /* Fonts for text outside emoji blocks */
32 | src: local('Droid Sans Mono'),
33 | local('Lucida Console'),
34 | local('Arial Monospaced'),
35 | local(Arial);
36 | }
37 | @font-face {
38 | font-family: emoji;
39 |
40 | src: local('Apple Color Emoji'),
41 | local('Android Emoji'),
42 | local('Segoe UI Emoji'),
43 | local('Segoe UI'),
44 | local('Segoe UI Symbol'),
45 | local(EmojiSymbols),
46 | local(Symbola),
47 | local(emoji);
48 |
49 | /* Emoji unicode blocks */
50 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
51 | }
52 |
53 |
54 | :root {
55 | //--widget-color: rgba(51, 105, 158, 0.9);
56 | --widget-color: rgba(41, 147, 251, 0.9);
57 | }
58 |
59 | /* background-color: #bada55; */
60 |
61 | html {
62 | font-size: 100%;
63 | -webkit-text-size-adjust: 100%;
64 | -ms-text-size-adjust: 100%;
65 | text-size-adjust: none;
66 | -moz-osx-font-smoothing: grayscale;
67 | -webkit-font-smoothing: antialiased;
68 | -webkit-overflow-scrolling: touch;
69 | -ms-overflow-style: scrollbar;
70 | scroll-behavior: smooth;
71 | }
72 |
73 | html, body {
74 | width: 100%;
75 | height: 100%;
76 | }
77 |
78 | body {
79 | display: block;
80 | margin: 0;
81 | padding: 0;
82 | border: none;
83 | width: 100%;
84 | height: auto;
85 | min-height: 100%;
86 | text-align: center;
87 | font-size: 100%;
88 | -webkit-text-size-adjust: none;
89 | -ms-text-size-adjust: none;
90 | text-size-adjust: none;
91 | -moz-osx-font-smoothing: grayscale;
92 | -webkit-font-smoothing: antialiased;
93 | overflow: auto;
94 | -ms-overflow-style: scrollbar;
95 | -webkit-overflow-scrolling: touch;
96 | -ms-touch-action: auto;
97 | touch-action: auto;
98 | scroll-behavior: smooth;
99 | font-family: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, Lucida Sans, Lucida Grande, Lucida Sans Unicode, HelveticaNeue-Light, HelveticaNeue, Helvetica, Arial, Verdana, sans-serif, caption, noto, 'Segoe UI Emoji', 'Segoe UI Symbol', 'emoji', 'Apple Color Emoji','EmojiSymbols', 'Symbola';
100 | background-attachment: fixed;
101 | z-index: -1;
102 | -ms-word-break: break-all;
103 | word-break: break-all;
104 | word-break: break-word;
105 | overflow-wrap: break-word;
106 | word-wrap: break-word;
107 | -webkit-hyphens: auto;
108 | -ms-hyphens: auto;
109 | -moz-hyphens: auto;
110 | hyphens: auto;
111 | background-color: #424242;
112 | color: #ffffff;
113 | }
114 |
115 | #universe {
116 | display: block;
117 | clear: both;
118 | margin-left: auto;
119 | margin-right: auto;
120 | height: auto;
121 | min-height: 150px;
122 | //padding-top: 2px;
123 | padding-bottom: 2px;
124 | border-radius: 4px;
125 | width: calc(100% - 4px);
126 | background-color: #424242;
127 | color: #ffffff;
128 |
129 | position: relative;
130 | top: 2px;
131 | margin-bottom: 3px;
132 | }
133 |
134 | a, a:visited {
135 | color: #ffffff;
136 | }
137 |
138 | *[hidden] {
139 | display: none !important;
140 | }
141 |
142 | .icon {
143 | display: inline-block;
144 | width: 1em;
145 | height: 1em;
146 | //width: 1.4em;
147 | //height: 1.4em;
148 | margin-top: 0.4em;
149 | }
150 |
151 |
152 | .button {
153 | border: 0;
154 | outline: 0;
155 | -webkit-appearance: none;
156 | -moz-appearance: none;
157 | -webkit-user-select: none;
158 | -khtml-user-select: none;
159 | -moz-user-select: none;
160 | -ms-user-select: none;
161 | user-select: none;
162 | cursor: pointer;
163 | vertical-align: middle;
164 | text-decoration: none;
165 | display: block;
166 | display: inline-block;
167 | position: relative;
168 | color: #ffffff;
169 | background-color: var(--widget-color);
170 | font-size: 80%;
171 | padding-left: 1em;
172 | padding-right: 1em;
173 | margin-top: 1px;
174 | margin-bottom: 1px;
175 | text-align: center;
176 | display: inline-block;
177 | min-height: 2.1em;
178 | max-width: 80%;
179 | height: auto;
180 | line-height: 2.125em;
181 | text-decoration: none;
182 | //text-transform: uppercase;
183 | text-shadow: none;
184 | border-radius: 4px;
185 | background-repeat: repeat;
186 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
187 | border: none;
188 | border-bottom: 1px solid transparent;
189 | }
190 |
191 | .button:hover, .button:focus {
192 | color: #ffffff;
193 | border: 0;
194 | background-color: rgba(255, 255, 255, 0.3);
195 | box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1), 0 8px 17px 0 rgba(0, 0, 0, 0.2);
196 | border: none;
197 | border-bottom: 1px solid transparent;
198 | }
199 |
200 | .button:active {
201 | background-color: rgba(255, 255, 255, 0.2);
202 | box-shadow: inset 0 2px 0 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.12);
203 | border: none;
204 | border-top: 1px solid transparent;
205 | }
206 |
207 | .button:visited {
208 | color: #ffffff;
209 | }
210 |
211 | .button[hidden] {
212 | visibility: hidden;
213 | display: none;
214 | opacity: 0;
215 | }
216 |
217 | .dropdown {
218 | border: 0;
219 | outline: 0;
220 | -webkit-appearance: menulist;
221 | -moz-appearance: menulist;
222 | -webkit-user-select: none;
223 | -khtml-user-select: none;
224 | -moz-user-select: none;
225 | -ms-user-select: none;
226 | user-select: none;
227 | cursor: pointer;
228 | vertical-align: middle;
229 | text-decoration: none;
230 | display: block;
231 | display: inline-block;
232 | position: relative;
233 | color: #ffffff;
234 | background-color: var(--widget-color);
235 | font-size: 80%;
236 | padding-left: 1em;
237 | padding-right: 1em;
238 | margin-top: 1px;
239 | margin-bottom: 1px;
240 | text-align: center;
241 | display: inline-block;
242 | min-height: 2.1em;
243 | max-width: 80%;
244 | height: auto;
245 | line-height: 2.125em;
246 | text-decoration: none;
247 | //text-transform: uppercase;
248 | text-shadow: none;
249 | border-radius: 2px;
250 | background-repeat: repeat;
251 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
252 | border: none;
253 | border-bottom: 1px solid transparent;
254 | }
255 |
256 | input[type=checkbox].toggle {
257 | height: 0;
258 | width: 0;
259 | visibility: hidden;
260 | }
261 |
262 | label.toggle {
263 | cursor: pointer;
264 | text-indent: -9999px;
265 | width: 2em;
266 | height: 1em;
267 | background-color: grey;
268 | display: inline-block;
269 | border-radius: 100px;
270 | position: relative;
271 | top: 0.2em;
272 | overflow: hidden;
273 | }
274 |
275 | label.toggle:after {
276 | content: '';
277 | position: absolute;
278 | top: 0.05em;
279 | left: 0.05em;
280 | width: 0.9em;
281 | height: 0.9em;
282 | background-color: #fff;
283 | border-radius: 90px;
284 | transition-duration: 0.3s;
285 | transition-property: transform;
286 | transform: scaleX(1);
287 | }
288 |
289 | input.toggle:checked + label.toggle {
290 | background-color: var(--widget-color);
291 | }
292 |
293 | input.toggle:checked + label.toggle:after {
294 | transform: translateX(1em);
295 | }
296 |
297 | label.toggle:active:after {
298 | transform: scaleX(2);
299 | }
300 |
301 | input.toggle:checked + label.toggle:active:after {
302 | transform: scaleX(2);
303 | }
304 |
305 | .button, input.toggle:checked + label.toggle {
306 | background-color: var(--widget-color);
307 | }
308 |
309 | input.textbox {
310 | border-radius: 4px;
311 | border: 0;
312 | outline: 0;
313 | -webkit-appearance: none;
314 | -moz-appearance: none;
315 | vertical-align: middle;
316 | font-size: 80%;
317 | padding-left: 1em;
318 | padding-right: 1em;
319 | margin-top: 1px;
320 | margin-bottom: 1px;
321 | text-align: center;
322 | display: inline-block;
323 | min-height: 2.1em;
324 | max-width: 80%;
325 | height: auto;
326 | line-height: 2.125em;
327 | text-decoration: none;
328 | border: none;
329 | box-shadow: inset 0 2px 5px 0 rgba(0, 0, 0, 0.26);
330 | }
331 |
332 | .info-box {
333 | display: inline-block;
334 | font-family: monospace;
335 | background-color: #313131;
336 | padding: 4px;
337 | border-radius: 4px;
338 | //max-width: 20%;
339 | //max-width: calc(20% - 8px);
340 | }
341 |
342 | #version-notice {
343 | display: block;
344 | position: fixed;
345 | bottom: 2px;
346 | left: 4px;
347 | float: left;
348 | opacity: 0.5;
349 | }
350 |
351 | #app-user-agent {
352 | position: fixed;
353 | bottom: 0;
354 | left: 0;
355 | text-align: left;
356 | font-size: 10px;
357 | color: rgba(255,255,255,0.5);
358 | z-index: -1;
359 | }
360 |
361 | #logger {
362 | display: block;
363 | overflow: auto;
364 | overflow-y: auto;
365 | white-space: pre;
366 | -ms-word-break: break-all;
367 | word-break: break-all;
368 | word-break: break-word;
369 | overflow-wrap: break-word;
370 | word-wrap: break-word;
371 | -webkit-hyphens: auto;
372 | -ms-hyphens: auto;
373 | -moz-hyphens: auto;
374 | hyphens: auto;
375 | max-height: 250px;
376 | border-top: solid 1px #c6c6c6;
377 | border-bottom: solid 1px #c6c6c6;
378 | }
--------------------------------------------------------------------------------
/electron app/resources/datpart/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: emoji;
3 |
4 | /* Fonts for text outside emoji blocks */
5 | src: local('Droid Sans Mono'),
6 | local('Lucida Console'),
7 | local('Arial Monospaced'),
8 | local(Arial);
9 | }
10 | @font-face {
11 | font-family: emoji;
12 |
13 | src: local('Apple Color Emoji'),
14 | local('Android Emoji'),
15 | local('Segoe UI'),
16 | local('Segoe UI Symbol'),
17 | local(EmojiSymbols),
18 | local(Symbola),/*,
19 | url('fonts/Symbola-Emoji.eot?#iefix') format('embedded-opentype'),
20 | url('fonts/Symbola-Emoji.woff') format('woff'),
21 | url('fonts/Symbola-Emoji.ttf') format('truetype')*/
22 | local(emoji);
23 |
24 | /* Emoji unicode blocks */
25 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
26 | }
27 |
28 | @font-face {
29 | font-family: emoji;
30 |
31 | /* Fonts for text outside emoji blocks */
32 | src: local('Droid Sans Mono'),
33 | local('Lucida Console'),
34 | local('Arial Monospaced'),
35 | local(Arial);
36 | }
37 | @font-face {
38 | font-family: emoji;
39 |
40 | src: local('Apple Color Emoji'),
41 | local('Android Emoji'),
42 | local('Segoe UI Emoji'),
43 | local('Segoe UI'),
44 | local('Segoe UI Symbol'),
45 | local(EmojiSymbols),
46 | local(Symbola),
47 | local(emoji);
48 |
49 | /* Emoji unicode blocks */
50 | unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF;
51 | }
52 |
53 |
54 | :root {
55 | //--widget-color: rgba(51, 105, 158, 0.9);
56 | --widget-color: rgba(41, 147, 251, 0.9);
57 | }
58 |
59 | /* background-color: #bada55; */
60 |
61 | html {
62 | font-size: 100%;
63 | -webkit-text-size-adjust: 100%;
64 | -ms-text-size-adjust: 100%;
65 | text-size-adjust: none;
66 | -moz-osx-font-smoothing: grayscale;
67 | -webkit-font-smoothing: antialiased;
68 | -webkit-overflow-scrolling: touch;
69 | -ms-overflow-style: scrollbar;
70 | scroll-behavior: smooth;
71 | }
72 |
73 | html, body {
74 | width: 100%;
75 | height: 100%;
76 | }
77 |
78 | body {
79 | display: block;
80 | margin: 0;
81 | padding: 0;
82 | border: none;
83 | width: 100%;
84 | height: auto;
85 | min-height: 100%;
86 | text-align: center;
87 | font-size: 100%;
88 | -webkit-text-size-adjust: none;
89 | -ms-text-size-adjust: none;
90 | text-size-adjust: none;
91 | -moz-osx-font-smoothing: grayscale;
92 | -webkit-font-smoothing: antialiased;
93 | overflow: auto;
94 | -ms-overflow-style: scrollbar;
95 | -webkit-overflow-scrolling: touch;
96 | -ms-touch-action: auto;
97 | touch-action: auto;
98 | scroll-behavior: smooth;
99 | font-family: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, Lucida Sans, Lucida Grande, Lucida Sans Unicode, HelveticaNeue-Light, HelveticaNeue, Helvetica, Arial, Verdana, sans-serif, caption, noto, 'Segoe UI Emoji', 'Segoe UI Symbol', 'emoji', 'Apple Color Emoji','EmojiSymbols', 'Symbola';
100 | background-attachment: fixed;
101 | z-index: -1;
102 | -ms-word-break: break-all;
103 | word-break: break-all;
104 | word-break: break-word;
105 | overflow-wrap: break-word;
106 | word-wrap: break-word;
107 | -webkit-hyphens: auto;
108 | -ms-hyphens: auto;
109 | -moz-hyphens: auto;
110 | hyphens: auto;
111 | background-color: #424242;
112 | color: #ffffff;
113 | }
114 |
115 | #universe {
116 | display: block;
117 | clear: both;
118 | margin-left: auto;
119 | margin-right: auto;
120 | height: auto;
121 | min-height: 150px;
122 | //padding-top: 2px;
123 | padding-bottom: 2px;
124 | border-radius: 4px;
125 | width: calc(100% - 4px);
126 | background-color: #424242;
127 | color: #ffffff;
128 |
129 | position: relative;
130 | top: 2px;
131 | margin-bottom: 3px;
132 | }
133 |
134 | a, a:visited {
135 | color: #ffffff;
136 | }
137 |
138 | *[hidden] {
139 | display: none !important;
140 | }
141 |
142 | .icon {
143 | display: inline-block;
144 | width: 1em;
145 | height: 1em;
146 | //width: 1.4em;
147 | //height: 1.4em;
148 | margin-top: 0.4em;
149 | }
150 |
151 |
152 | .button {
153 | border: 0;
154 | outline: 0;
155 | -webkit-appearance: none;
156 | -moz-appearance: none;
157 | -webkit-user-select: none;
158 | -khtml-user-select: none;
159 | -moz-user-select: none;
160 | -ms-user-select: none;
161 | user-select: none;
162 | cursor: pointer;
163 | vertical-align: middle;
164 | text-decoration: none;
165 | display: block;
166 | display: inline-block;
167 | position: relative;
168 | color: #ffffff;
169 | background-color: var(--widget-color);
170 | font-size: 80%;
171 | padding-left: 1em;
172 | padding-right: 1em;
173 | margin-top: 1px;
174 | margin-bottom: 1px;
175 | text-align: center;
176 | display: inline-block;
177 | min-height: 2.1em;
178 | max-width: 80%;
179 | height: auto;
180 | line-height: 2.125em;
181 | text-decoration: none;
182 | //text-transform: uppercase;
183 | text-shadow: none;
184 | border-radius: 4px;
185 | background-repeat: repeat;
186 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
187 | border: none;
188 | border-bottom: 1px solid transparent;
189 | }
190 |
191 | .button:hover, .button:focus {
192 | color: #ffffff;
193 | border: 0;
194 | background-color: rgba(255, 255, 255, 0.3);
195 | box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1), 0 8px 17px 0 rgba(0, 0, 0, 0.2);
196 | border: none;
197 | border-bottom: 1px solid transparent;
198 | }
199 |
200 | .button:active {
201 | background-color: rgba(255, 255, 255, 0.2);
202 | box-shadow: inset 0 2px 0 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.12);
203 | border: none;
204 | border-top: 1px solid transparent;
205 | }
206 |
207 | .button:visited {
208 | color: #ffffff;
209 | }
210 |
211 | .button[hidden] {
212 | visibility: hidden;
213 | display: none;
214 | opacity: 0;
215 | }
216 |
217 | .dropdown {
218 | border: 0;
219 | outline: 0;
220 | -webkit-appearance: menulist;
221 | -moz-appearance: menulist;
222 | -webkit-user-select: none;
223 | -khtml-user-select: none;
224 | -moz-user-select: none;
225 | -ms-user-select: none;
226 | user-select: none;
227 | cursor: pointer;
228 | vertical-align: middle;
229 | text-decoration: none;
230 | display: block;
231 | display: inline-block;
232 | position: relative;
233 | color: #ffffff;
234 | background-color: var(--widget-color);
235 | font-size: 80%;
236 | padding-left: 1em;
237 | padding-right: 1em;
238 | margin-top: 1px;
239 | margin-bottom: 1px;
240 | text-align: center;
241 | display: inline-block;
242 | min-height: 2.1em;
243 | max-width: 80%;
244 | height: auto;
245 | line-height: 2.125em;
246 | text-decoration: none;
247 | //text-transform: uppercase;
248 | text-shadow: none;
249 | border-radius: 2px;
250 | background-repeat: repeat;
251 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
252 | border: none;
253 | border-bottom: 1px solid transparent;
254 | }
255 |
256 | input[type=checkbox].toggle {
257 | height: 0;
258 | width: 0;
259 | visibility: hidden;
260 | }
261 |
262 | label.toggle {
263 | cursor: pointer;
264 | text-indent: -9999px;
265 | width: 2em;
266 | height: 1em;
267 | background-color: grey;
268 | display: inline-block;
269 | border-radius: 100px;
270 | position: relative;
271 | top: 0.2em;
272 | overflow: hidden;
273 | }
274 |
275 | label.toggle:after {
276 | content: '';
277 | position: absolute;
278 | top: 0.05em;
279 | left: 0.05em;
280 | width: 0.9em;
281 | height: 0.9em;
282 | background-color: #fff;
283 | border-radius: 90px;
284 | transition-duration: 0.3s;
285 | transition-property: transform;
286 | transform: scaleX(1);
287 | }
288 |
289 | input.toggle:checked + label.toggle {
290 | background-color: var(--widget-color);
291 | }
292 |
293 | input.toggle:checked + label.toggle:after {
294 | transform: translateX(1em);
295 | }
296 |
297 | label.toggle:active:after {
298 | transform: scaleX(2);
299 | }
300 |
301 | input.toggle:checked + label.toggle:active:after {
302 | transform: scaleX(2);
303 | }
304 |
305 | .button, input.toggle:checked + label.toggle {
306 | background-color: var(--widget-color);
307 | }
308 |
309 | input.textbox {
310 | border-radius: 4px;
311 | border: 0;
312 | outline: 0;
313 | -webkit-appearance: none;
314 | -moz-appearance: none;
315 | vertical-align: middle;
316 | font-size: 80%;
317 | padding-left: 1em;
318 | padding-right: 1em;
319 | margin-top: 1px;
320 | margin-bottom: 1px;
321 | text-align: center;
322 | display: inline-block;
323 | min-height: 2.1em;
324 | max-width: 80%;
325 | height: auto;
326 | line-height: 2.125em;
327 | text-decoration: none;
328 | border: none;
329 | box-shadow: inset 0 2px 5px 0 rgba(0, 0, 0, 0.26);
330 | }
331 |
332 | .info-box {
333 | display: inline-block;
334 | font-family: monospace;
335 | background-color: #313131;
336 | padding: 4px;
337 | border-radius: 4px;
338 | //max-width: 20%;
339 | //max-width: calc(20% - 8px);
340 | }
341 |
342 | #version-notice {
343 | display: block;
344 | position: fixed;
345 | bottom: 2px;
346 | left: 4px;
347 | float: left;
348 | opacity: 0.5;
349 | }
350 |
351 | #app-user-agent {
352 | position: fixed;
353 | bottom: 0;
354 | left: 0;
355 | text-align: left;
356 | font-size: 10px;
357 | color: rgba(255,255,255,0.5);
358 | z-index: -1;
359 | }
360 |
361 | #logger {
362 | display: block;
363 | overflow: auto;
364 | overflow-y: auto;
365 | white-space: pre;
366 | -ms-word-break: break-all;
367 | word-break: break-all;
368 | word-break: break-word;
369 | overflow-wrap: break-word;
370 | word-wrap: break-word;
371 | -webkit-hyphens: auto;
372 | -ms-hyphens: auto;
373 | -moz-hyphens: auto;
374 | hyphens: auto;
375 | height: 250px;
376 | border-top: solid 1px #c6c6c6;
377 | border-bottom: solid 1px #c6c6c6;
378 | }
--------------------------------------------------------------------------------
/chrome extension/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | DatPart - Popup
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
128 |
129 |
130 |
180 |
--------------------------------------------------------------------------------
/chrome extension/popup.js:
--------------------------------------------------------------------------------
1 | var appip = "127.0.0.1";
2 | var port = "9989";
3 |
4 | const cachedFetch = (url, options) => {
5 | let expiry = 5 * 60 // 5 min default
6 | if (typeof options === 'number') {
7 | expiry = options
8 | options = undefined
9 | } else if (typeof options === 'object') {
10 | // I hope you didn't set it to 0 seconds
11 | expiry = options.seconds || expiry
12 | }
13 |
14 | var currentURLRequest = document.createElement('a');
15 | currentURLRequest.href = url;
16 |
17 | var currentTLD = currentURLRequest.hostname.split(".").pop();
18 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
19 |
20 | caches.open('dat-'+currentURLhostNoTLD).then(function(cache) {
21 | cache.match(url).then(function(matchedResponse) {
22 | console.log(matchedResponse);
23 | return matchedResponse;
24 | });
25 | });
26 |
27 | return fetch(url, options).then(response => {
28 | // let's only store in cache if the content-type is
29 | // JSON or something non-binary
30 | if (response.status === 200) {
31 | let ct = response.headers.get('Content-Type')
32 | if (ct && (ct.match(/application\/json/i) || ct.match(/text\//i))) {
33 | // There is a .json() instead of .text() but
34 | // we're going to store it in sessionStorage as
35 | // string anyway.
36 | // If we don't clone the response, it will be
37 | // consumed by the time it's returned. This
38 | // way we're being un-intrusive.
39 |
40 | var currentURLRequest = document.createElement('a');
41 | currentURLRequest.href = url;
42 |
43 | var currentTLD = currentURLRequest.hostname.split(".").pop();
44 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
45 |
46 | caches.open('dat-'+currentURLhostNoTLD).then(function(cache) {
47 | // Cache is created and accessible
48 | cache.add(url);
49 | });
50 | /*
51 | response.clone().text().then(content => {
52 | localStorage.setItem(cacheKey, content)
53 | localStorage.setItem(cacheKey+':ts', Date.now())
54 | })
55 | */
56 | }
57 | }
58 | return response
59 | })
60 | }
61 |
62 | function checkDatJSON() {
63 |
64 | chrome.tabs.query (
65 | { currentWindow: true, active: true },
66 | function(tabs) {
67 | var activeTab = tabs[0];
68 | //console.log(JSON.stringify(activeTab));
69 |
70 | var currentURLRequest = document.createElement('a');
71 | currentURLRequest.href = activeTab.url;
72 |
73 | var currentTLD = currentURLRequest.hostname.split(".").pop();
74 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
75 |
76 | //console.log(currentTLD);
77 |
78 | if (currentTLD != 'dat_site') {
79 | document.documentElement.setAttribute('dat-site', 'false');
80 |
81 | return;
82 | } else {
83 |
84 | var siteURL = document.getElementById("site-url");
85 | siteURL.innerText = activeTab.url;
86 |
87 | var siteTitle = document.getElementById("site-title");
88 | siteTitle.innerText = activeTab.title;
89 |
90 | var siteDescription = document.getElementById("site-description");
91 | siteDescription.innerText = activeTab.title;
92 |
93 | var siteAuthorName = document.getElementById("author-name");
94 | var siteAuthorEmail = document.getElementById("author-email");
95 | var siteAuthorWeb = document.getElementById("author-web");
96 | var siteAuthorSection = document.getElementById("site-author-section");
97 | siteAuthorSection.setAttribute("hidden","");
98 |
99 | var siteREADME = document.getElementById("site-readme");
100 | var siteREADMEsection = document.getElementById("site-readme-section");
101 | siteREADMEsection.setAttribute("hidden","");
102 |
103 | var donateLink = document.getElementById("donate-link");
104 | donateLink.setAttribute("hidden","");
105 |
106 | var faviconIMG = document.getElementById("site-favicon");
107 | if(activeTab.favIconUrl != "undefined"){faviconIMG.src = activeTab.favIconUrl;}
108 |
109 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
110 | console.log(currentURLhostNoTLD);
111 |
112 | /*
113 | var datHash = currentURLRequest.hostname;
114 | var datUrlPathname = currentURLRequest.pathname;
115 | var datUrlSearch = currentURLRequest.search;
116 | var datUrlHash = currentURLRequest.hash;
117 | */
118 | siteURL.innerText = "dat://" + currentURLhostNoTLD + currentURLRequest.pathname + currentURLRequest.search + currentURLRequest.hash;
119 | document.getElementById("copy-link").href = "dat://" + currentURLhostNoTLD + currentURLRequest.pathname + currentURLRequest.search + currentURLRequest.hash;
120 |
121 | document.getElementById("qr-iframe").src="/qr_code.html?link=" + "dat://" + currentURLhostNoTLD + currentURLRequest.pathname + currentURLRequest.search + currentURLRequest.hash;
122 | document.getElementById("qr-link").href="/qr_code.html?link=" + "dat://" + currentURLhostNoTLD + currentURLRequest.pathname + currentURLRequest.search + currentURLRequest.hash;
123 |
124 | fetch("http://"+ currentURLhostNoTLD + "." + currentTLD + "/favicon.ico").then(function(response) {
125 | if (response.status !== 200) {
126 | console.log('Looks like there was a problem getting favicon.ico. Status Code: ' +
127 | response.status);
128 |
129 | fetch("http://"+ currentURLhostNoTLD + "." + currentTLD + "/favicon.png").then(function(response) {
130 | console.log("Trying for favicon.png now.");
131 |
132 | if (response.status !== 200) {
133 | console.log('Looks like there was a problem getting favicon.png. Status Code: ' +
134 | response.status);
135 | if(activeTab.favIconUrl != "undefined"){faviconIMG.src = activeTab.favIconUrl;}
136 | return;
137 | } else { faviconIMG.src = "http://"+ currentURLhostNoTLD + "." + currentTLD + "/favicon.png"; }
138 |
139 | });
140 |
141 | return;
142 | } else { faviconIMG.src = "http://"+ currentURLhostNoTLD + "." + currentTLD + "/favicon.ico"; }
143 |
144 | });
145 |
146 | cachedFetch("http://"+ currentURLhostNoTLD + "." + currentTLD + "/README.md").then(function(response) {
147 | if (response.status !== 200) {
148 | console.log('Looks like there was a problem. Status Code: ' +
149 | response.status);
150 | siteREADMEsection.setAttribute("hidden","");
151 | return;
152 | }
153 |
154 | response.text().then(function(data) {
155 | if (data !== "") {
156 | console.log(data);
157 | siteREADME.innerText = data;
158 | siteREADMEsection.removeAttribute("hidden");
159 | } else {
160 | siteREADMEsection.setAttribute("hidden","");
161 | }
162 | });
163 |
164 | });
165 |
166 | fetch("http://"+ currentURLhostNoTLD + "." + currentTLD + "/dat.json").then(function(response) {
167 | console.log("Server response: "+response);
168 | console.log(response);
169 |
170 | if (response.status !== 200) {
171 | console.log('Looks like there was a problem. Status Code: ' +
172 | response.status);
173 | return;
174 | }
175 |
176 | // Examine the text in the response
177 | response.json().then(function(data) {
178 | console.log(data);
179 |
180 | if(data.title != "undefined"){
181 | siteTitle.innerText = data.title;
182 | faviconIMG.title = data.title;
183 | donateLink.getElementsByTagName('span')[0].innerText = "Contribute to "+data.title;
184 | }
185 |
186 | if(data.description != "undefined"){
187 | siteDescription.innerText = data.description;}else{
188 | siteDescription.innerText = data.title;
189 | }
190 |
191 | if (data.author != "undefined" && typeof data.author == 'string' || data.author != "undefined" && data.author instanceof String) {
192 | siteAuthorName.innerText = data.author;
193 | siteAuthorSection.removeAttribute("hidden");
194 | } else if (data.author != "undefined") {
195 | if(data.author.name != "undefined"){
196 | siteAuthorName.innerText = data.author.name;
197 |
198 | siteAuthorSection.removeAttribute("hidden");
199 | }
200 |
201 | if(data.author.email != "undefined"){
202 | siteAuthorEmail.innerText = "";
203 |
204 | siteAuthorEmail.href = "mailto:" + data.author.email;
205 | siteAuthorEmail.innerText = data.author.email;
206 |
207 | siteAuthorSection.removeAttribute("hidden");
208 | }
209 |
210 | if(data.author.web != "undefined"){
211 | siteAuthorWeb.innerText = "";
212 |
213 | siteAuthorWeb.href = data.author.web;
214 | siteAuthorWeb.innerText = data.author.web;
215 |
216 | siteAuthorSection.removeAttribute("hidden");
217 | }
218 | }
219 |
220 | if(data.links.payment[0].href != "undefined"){
221 | donateLink.href = data.links.payment[0].href;
222 | donateLink.removeAttribute("hidden");
223 | } else {
224 | donateLink.setAttribute("hidden","");
225 | }
226 | /*
227 | if(data.links.icon[0].href != "undefined"){
228 | faviconIMG.src = data.links.icon[0].href;
229 | }
230 | */
231 | });
232 |
233 | });
234 |
235 | }
236 |
237 | });
238 |
239 | }
240 |
241 | function checkTab() {
242 | console.log("Checking tab");
243 | chrome.tabs.query (
244 | { currentWindow: true, active: true },
245 | function(tabs) {
246 | var activeTab = tabs[0];
247 | //console.log(JSON.stringify(activeTab));
248 |
249 | var currentURLRequest = document.createElement('a');
250 | currentURLRequest.href = activeTab.url;
251 |
252 | var currentTLD = currentURLRequest.hostname.split(".").pop();
253 | //console.log(currentTLD);
254 |
255 | if (currentTLD != 'dat_site') {
256 | document.documentElement.setAttribute('dat-site', 'false');
257 |
258 | return;
259 | } else {
260 | document.documentElement.setAttribute('dat-site', 'true');
261 |
262 | checkDatJSON();
263 |
264 | }
265 |
266 | });
267 | }
268 |
269 | function checkDatAvailable() {
270 |
271 | chrome.permissions.contains({
272 | origins: ['https://*/.well-known/dat']
273 | }, function(result) {
274 | if (result) {
275 | chrome.tabs.query (
276 | { currentWindow: true, active: true },
277 | function(tabs) {
278 | var activeTab = tabs[0];
279 |
280 | var currentURLRequest = document.createElement('a');
281 | currentURLRequest.href = activeTab.url;
282 |
283 | var currentURLpage = currentURLRequest.pathname;
284 | var currentTLD = currentURLRequest.hostname.split(".").pop();
285 | var currentURLhostNoTLD = currentURLRequest.hostname.split(".")[0];
286 | var currentURLhost = currentURLRequest.hostname;
287 |
288 | chrome.storage.local.get([currentURLhost], function(result) {
289 | if (Object.keys(result).length != 0 && result.constructor == Object && result.dat != "" && result[currentURLhost].dat != "") {
290 | console.log(currentURLhost);
291 | console.log('Value for '+currentURLhost+' currently is ' + result);
292 | console.log(result);
293 | console.log(result.constructor === Object);
294 | console.log(Object.keys(result).length);
295 | console.log(result[currentURLhost].dat);
296 |
297 | document.documentElement.setAttribute('dat-available', 'true');
298 |
299 | document.getElementById("https-url").textContent=currentURLRequest.hostname;
300 | document.getElementById("dat-hash").textContent="dat://"+result[currentURLhost].dat;
301 |
302 | document.getElementById("dat-version").href="dat://";
303 | document.getElementById("dat-version").href="dat://"+result[currentURLhost].dat;
304 | document.getElementById("dat-version").href="http://"+result[currentURLhost].dat+".dat_site/";
305 | document.getElementById("dat-version-url").href="dat://"+result[currentURLhost].dat;
306 |
307 | } else {
308 |
309 | document.getElementById("dat-version").href="about:blank";
310 | document.getElementById("dat-version-url").href="about:blank";
311 | document.documentElement.setAttribute('dat-available', 'false');
312 |
313 | }
314 | });
315 | });
316 | } else {
317 | //document.documentElement.setAttribute('dat-available', 'false');
318 | }
319 | });
320 | }
321 |
322 | window.onload = function(){
323 |
324 | chrome.permissions.contains({
325 | origins: ['https://*/.well-known/dat']
326 | }, function(result) {
327 | if (result) {
328 | document.documentElement.setAttribute('check-dat', 'true');
329 | checkDatAvailable();
330 | } else {
331 | document.documentElement.setAttribute('check-dat', 'false');
332 | }
333 | });
334 |
335 | checkDatJSON();
336 |
337 | checkTab();
338 |
339 | checkDatAvailable();
340 |
341 | document.getElementById("check-dat").addEventListener('click', function(event) {
342 |
343 | chrome.runtime.openOptionsPage();
344 |
345 | });
346 |
347 | document.getElementById("version-notice").textContent=" v"+chrome.runtime.getManifest().version;
348 | };
--------------------------------------------------------------------------------
/electron app/resources/datpart/server_script.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | //const {shell} = require('electron');
4 | const http = require('http');
5 | const url = require("url");
6 | const dat = require('dat-node');
7 | const fs = require('fs');
8 | const path = require("path");
9 |
10 | // "chrome-native-messaging": "^0.2.0",
11 | // "node-dat-archive": "^1.5.0",
12 | // "pauls-dat-api": "^8.0.1"
13 |
14 | var host = "127.0.0.1";
15 | var port = "9989";
16 |
17 | var versionNumber = require('electron').remote.getGlobal('sharedObject').appVersionNumber;
18 |
19 | logToScreen("DatPart Server Version "+versionNumber);
20 |
21 | var datMap = {};
22 |
23 | var mimeTypes = {
24 | //text formats
25 | "html": "text/html",
26 | "htm": "text/html",
27 | "xhtml": "application/xhtml+xml",
28 | "js": "text/javascript",
29 | "mjs": "text/javascript",
30 | "ts": "application/typescript",
31 | "css": "text/css",
32 | "txt": "text/plain",
33 | "appcache": "text/cache-manifest",
34 | "htc": "text/x-component",
35 | //image formats
36 | "svg": "image/svg+xml",
37 | "svgz": "image/svg+xml",
38 | "jpeg": "image/jpeg",
39 | "jpg": "image/jpeg",
40 | "png": "image/png",
41 | "apng": "image/png",
42 | "webp": "image/webp",
43 | "jxr": "image/vnd.ms-photo",
44 | "hdp": "image/vnd.ms-photo",
45 | "wdp": "image/vnd.ms-photo",
46 | "bpg": "image/bpg",
47 | "jp2": "image/jp2",
48 | "jpx": "image/jpx",
49 | "jpm": "image/jpm",
50 | "bmp": "image/bmp",
51 | "dib": "image/bmp",
52 | "flif": "image/flif",
53 | "heif": "image/heif",
54 | "heic": "image/heic",
55 | "tiff": "image/tiff",
56 | "tif": "image/tiff",
57 | "mpo": "image/mpo",
58 | "gif": "image/gif",
59 | "ico": "image/x-icon",
60 | "avif": "image/avif",
61 | //font formats
62 | "woff": "application/font-woff",
63 | "woff2": "font/woff2",
64 | "ttf": "application/x-font-ttf",
65 | "ttc": "application/x-font-ttf",
66 | "otf": "font/opentype",
67 | "eot": "application/vnd.ms-fontobject",
68 | //video formats
69 | "webm": "video/webm",
70 | "mp4": "video/mp4",
71 | "m4v": "video/m4v",
72 | "ogv": "video/ogg",
73 | "mj2": "image/mj2",
74 | "mjp2": "image/mj2",
75 | "mjp": "video/x-motion-jpeg",
76 | "mkv": "video/x-matroska",
77 | "mk3d": "video/x-matroska",
78 | "flv": "video/x-flv",
79 | "mng": "video/x-mng",
80 | "avi": "video/x-msvideo",
81 | "wmv": "video/x-ms-wmv",
82 | "asf": "video/x-ms-asf",
83 | "3gp": "video/3gpp",
84 | "3g2": "video/3gpp2",
85 | "mov": "video/quicktime",
86 | "tsv": "video/MP2T",
87 | "asx": "video/x-ms-asf",
88 | //audio formats
89 | "ogg": "audio/ogg",
90 | "oga": "audio/ogg",
91 | "aac": "audio/x-aac",
92 | "mp3": "audio/mpeg",
93 | "weba": "audio/webm",
94 | "flac": "audio/flac",
95 | "spx": "audio/speex",
96 | "opus": "audio/opus",
97 | "aiff": "audio/aiff",
98 | "wma": "audio/x-ms-wma",
99 | "mka": "audio/x-matroska",
100 | "mid": "audio/midi",
101 | "midi": "audio/midi",
102 | "wav": "audio/wav",
103 | "pls": "audio/x-scpls",
104 | //application file formats
105 | "sxg": "application/signed-exchange",
106 | "wasm": "application/wasm",
107 | "nexe": "application/x-nacl",
108 | "xml": "application/xml",
109 | "json": "application/json",
110 | "map": "application/json",
111 | "rss": "application/rss+xml",
112 | "atom": "application/atom+xml",
113 | "opensearchxml": "application/opensearchdescription+xml",
114 | "torrent": "application/x-bittorrent",
115 | "webmanifest": "application/manifest+json",
116 | //browser extension file formats
117 | "crx": "application/x-chrome-extension",
118 | "xpi": "application/x-xpinstall",
119 | "nex": "application/x-navigator-extension",
120 | //plugin file formats
121 | "swf": "application/x-shockwave-flash",
122 | "xap": "application/x-silverlight-app",
123 | "unity3d": "application/vnd.unity",
124 | "jar": "application/java-archive",
125 | "class": "application/x-java-applet",
126 | //random Misc
127 | "webapp": "application/x-web-app-manifest+json",
128 | "pdf": "application/pdf",
129 | "ics": "text/calendar",
130 | "pkpass": "application/vnd.apple.pkpass",
131 | "mobileconfig": "application/x-apple-aspen-config",
132 | "prs": "application/x-psp-radio-skin",
133 | "p3t": "application/x-ps3-theme",
134 | "ptf": "application/x-psp-theme",
135 | "pbp": "application/x-psp-game",
136 | "epub": "application/epub+zip",
137 | "zip": "application/zip",
138 | "wpl": "application/vnd.ms-wpl",
139 | "m3u": "application/x-mpegURL",
140 | "m3u8": "application/x-mpegURL",
141 | "xspf": "application/xspf+xml"
142 | };
143 |
144 | var HTTPheaders = {
145 | "Server": "DatPart "+versionNumber,
146 | "X-Powered-By": "DatPart "+versionNumber,
147 | //"Cache-Control": "no-cache, no-store, must-revalidate, no-transform",
148 | //"Pragma": "no-cache",
149 | //"Expires": "0",
150 | "Cache-Control": "public, max-age: 60, no-transform",
151 | "Accept-Charset": "utf-8",
152 | "Access-Control-Allow-Origin": "*",
153 | //"Content-Security-Policy": "",
154 | "Upgrade-Insecure-Requests": "1"
155 | };
156 |
157 | if (!fs.existsSync(__dirname + '/../../dats/')) {
158 | fs.mkdirSync(__dirname + '/../../dats/');
159 | }
160 |
161 | const requestHandler = (request, response) => {
162 | logToScreen(request.url);
163 | logToScreen(request);
164 |
165 | var uri = url.parse(request.url).pathname,
166 | filename = path.join(process.cwd(), uri);
167 |
168 | var mimeType = mimeTypes[filename.split('.').pop()];
169 |
170 | if (!mimeType) {
171 | mimeType = 'text/plain';
172 | }
173 |
174 | var currentTLD = url.parse(request.url).hostname.split(".").pop();
175 |
176 | var currentURLhostNoTLD = url.parse(request.url).hostname.split(".")[0];
177 |
178 | var datPath = url.parse(request.url).pathname;
179 |
180 | logToScreen(datPath);
181 |
182 | if(request.method == 'GET' && currentTLD == 'dat_site' || request.method == 'GET' && currentTLD == 'datsite') {
183 | datMap[currentURLhostNoTLD] = {};
184 | dat( __dirname + '/../../dats/'+currentURLhostNoTLD, {
185 | // 2. Tell Dat what link I want
186 | key: currentURLhostNoTLD, temp: false, sparse: true // (a 64 character hash from above)
187 | }, function (err, dat) {
188 | if (err) {throw err;logToScreen(err);}
189 |
190 | var stats = dat.trackStats();
191 | logToScreen(currentURLhostNoTLD+" "+dat.stats.get());
192 | logToScreen(dat.stats.get());
193 | logToScreen("Dat Version: "+dat.stats.get().version);
194 | logToScreen("Number of files: "+dat.stats.get().files);
195 |
196 | var fourOhFourPage = null;
197 |
198 | // 3. Join the network & download (files are automatically downloaded)
199 | dat.joinNetwork();
200 | /*
201 | dat.joinNetwork(function (err) {
202 | if (err) { throw err; }
203 |
204 | if (!dat.network.connected || !dat.network.connecting) {
205 | console.error('No users currently online for dat://'+currentURLhostNoTLD);
206 | process.exit(1);
207 | }
208 | });
209 | */
210 |
211 | datMap[currentURLhostNoTLD].fourOhFourFallback = null;
212 |
213 | datMap[currentURLhostNoTLD].contentSecurityPolicy = "";
214 |
215 | /*
216 | dat.archive.readFile(datPath+'/dat.json', function (err, content) {
217 | if (content != null) {
218 | logToScreen("Got dat.json for "+ currentURLhostNoTLD);
219 | logToScreen(datMap[currentURLhostNoTLD]);
220 |
221 | if (JSON.parse(content.toString()).content_security_policy != null || JSON.parse(content.toString()).content_security_policy != undefined) {
222 | datMap[currentURLhostNoTLD].contentSecurityPolicy = JSON.parse(content.toString()).content_security_policy;
223 | logToScreen(JSON.parse(content.toString()).content_security_policy);
224 | } else {
225 | datMap[currentURLhostNoTLD].contentSecurityPolicy = "";
226 | }
227 |
228 | if (JSON.parse(content.toString()).fallback_page != null || JSON.parse(content.toString()).fallback_page != undefined) {
229 | datMap[currentURLhostNoTLD].fallback_page = JSON.parse(content.toString()).fallback_page;
230 | logToScreen(JSON.parse(content.toString()).fallback_page);
231 | } else {
232 | datMap[currentURLhostNoTLD].fallback_page = "";
233 | }
234 |
235 | } else {
236 | logToScreen("dat.json not found for "+ currentURLhostNoTLD);
237 |
238 | }
239 | if (err) {throw err; logToScreen(err);}
240 | });
241 | */
242 |
243 | /*
244 | datMap[currentURLhostNoTLD].fourOhFourFallback = new Promise(function(resolve, reject) {
245 | dat.archive.readFile('/dat.json', function (err, content) {
246 |
247 | logToScreen("Grabbing JSON for fallback_page "+JSON.stringify(content));
248 |
249 | dat.archive.readFile(content.fallback_page, function (err, fallbackContent) {
250 | if (fallbackContent != null) {
251 | logToScreen("Got fallback page for dat://"+ currentURLhostNoTLD +" " + content.fallback_page);
252 | resolve(fallbackContent);
253 | } else {
254 | logToScreen("fallback_page not found for dat://"+ currentURLhostNoTLD);
255 | reject("fallback_page not found for dat://"+ currentURLhostNoTLD);
256 | }
257 | });
258 |
259 | }, function(err) {
260 | logToScreen(err);
261 | });
262 | });
263 | */
264 | /*
265 | datMap[currentURLhostNoTLD].contentSecurityPolicy = new Promise(function(resolve, reject) {
266 | datMap[currentURLhostNoTLD].datJSON.then(function(result) {
267 |
268 | logToScreen("Grabbing JSON for content_security_policy "+JSON.stringify(result));
269 |
270 | dat.archive.readFile(result.content_security_policy, function (err, cspContent) {
271 | if (cspContent != null) {
272 | logToScreen("Got fallback page for dat://"+ currentURLhostNoTLD +" " + result.content_security_policy);
273 | resolve(cspContent);
274 | } else {
275 | logToScreen("content_security_policy not found for dat://"+ currentURLhostNoTLD);
276 | reject("content_security_policy not found for dat://"+ currentURLhostNoTLD);
277 | }
278 | });
279 |
280 | }, function(err) {
281 | logToScreen(err);
282 | });
283 | });
284 | */
285 | var lastChar = request.url.substr(-1); // Selects the last character
286 | if (lastChar == '/') { // If the last character is not a slash
287 |
288 | dat.archive.readFile(datPath+'/index.html', function (err, content) {
289 |
290 | if (content != null) {
291 | logToScreen(datPath);
292 | var newHeaders = HTTPheaders;
293 | delete newHeaders["X-Frame-Options"];
294 | delete newHeaders["Location"];
295 | newHeaders["Content-Type"] = "text/html; charset=utf8";
296 | newHeaders["Alt-Svc"] = "dat='dat://"+currentURLhostNoTLD+datPath+"'";
297 | newHeaders["Dat-Url"] = "dat://"+currentURLhostNoTLD+datPath;
298 | newHeaders["Hyperdrive-Key"] = currentURLhostNoTLD;
299 | newHeaders["Hyperdrive-Version"] = dat.stats.get().version;
300 | //newHeaders["Content-Security-Policy"] = datMap[currentURLhostNoTLD].contentSecurityPolicy;
301 |
302 | response.writeHead(200, newHeaders);
303 | response.end(content);
304 | } else {
305 | logToScreen("File "+datPath+" not found!");
306 |
307 | var newHeaders = HTTPheaders;
308 | delete newHeaders["X-Frame-Options"];
309 | delete newHeaders["Location"];
310 | //newHeaders["Content-Security-Policy"] = "";
311 | newHeaders["X-Frame-Options"] = "DENY";
312 |
313 | if(datMap[currentURLhostNoTLD].fourOhFourFallback != null) {
314 | logToScreen(result);
315 |
316 | newHeaders["Alt-Svc"] = "dat='dat://"+currentURLhostNoTLD+datPath+"'";
317 | newHeaders["Dat-Url"] = "dat://"+currentURLhostNoTLD+datPath;
318 | newHeaders["Hyperdrive-Key"] = currentURLhostNoTLD;
319 | newHeaders["Hyperdrive-Version"] = dat.stats.get().version;
320 |
321 | response.writeHead(404, newHeaders);
322 | response.end(result);
323 | } else {
324 | logToScreen(err);
325 | response.writeHead(204, newHeaders);
326 | response.end("Nothing");
327 | }
328 |
329 | }
330 | if (err) {throw err; logToScreen(err);}
331 | });
332 |
333 | } else {
334 |
335 | dat.archive.readFile(datPath, function (err, content) {
336 |
337 | if (content != null) {
338 | logToScreen(datPath);
339 |
340 | var newHeaders = HTTPheaders;
341 | delete newHeaders["X-Frame-Options"];
342 | delete newHeaders["Location"];
343 | newHeaders["Content-Type"] = mimeType;
344 | newHeaders["Alt-Svc"] = "dat='dat://"+currentURLhostNoTLD+datPath+"'";
345 | newHeaders["Dat-Url"] = "dat://"+currentURLhostNoTLD+datPath;
346 | newHeaders["Hyperdrive-Key"] = currentURLhostNoTLD;
347 | newHeaders["Hyperdrive-Version"] = dat.stats.get().version;
348 |
349 | delete newHeaders["X-Frame-Options"];
350 | delete newHeaders["Location"];
351 |
352 | //newHeaders["Content-Security-Policy"] = datMap[currentURLhostNoTLD].contentSecurityPolicy;
353 |
354 | response.writeHead(200, newHeaders);
355 | response.end(content);
356 | } else {
357 | logToScreen("File "+datPath+" not found!");
358 |
359 | var newHeaders = HTTPheaders;
360 | delete newHeaders["X-Frame-Options"];
361 | delete newHeaders["Location"];
362 | newHeaders["Content-Security-Policy"] = "frame-ancestors 'none'";
363 | newHeaders["X-Frame-Options"] = "DENY";
364 |
365 | if(datMap[currentURLhostNoTLD].fourOhFourFallback != null) {
366 | logToScreen(result);
367 |
368 | newHeaders["Alt-Svc"] = "dat='dat://"+currentURLhostNoTLD+datPath+"'";
369 | newHeaders["Dat-Url"] = "dat://"+currentURLhostNoTLD+datPath;
370 | newHeaders["Hyperdrive-Key"] = currentURLhostNoTLD;
371 | newHeaders["Hyperdrive-Version"] = dat.stats.get().version;
372 |
373 | response.writeHead(404, newHeaders);
374 | response.end(result);
375 | } else {
376 | logToScreen(err);
377 | response.writeHead(204, newHeaders);
378 | response.end("Nothing");
379 | }
380 |
381 | }
382 | if (err) {throw err; logToScreen(err);}
383 | });
384 |
385 | }
386 |
387 | //dat.leaveNetwork();
388 |
389 | });
390 |
391 | } else if(request.method == 'GET' && currentTLD != 'dat_site' && currentTLD != 'datsite') {
392 |
393 | logToScreen("Non Dat Site request "+request);
394 | logToScreen(request);
395 |
396 | //var newHeaders;
397 | //newHeaders["location"] = "http://0.0.0.0/";
398 | //response.writeHead(301, newHeaders);
399 | response.end();
400 |
401 | } else if(fs.existsSync(__dirname + "/../../dats/")) {
402 |
403 | logToScreen(request.url);
404 |
405 | var currentTLD = url.parse(request.url).hostname.split(".").pop();
406 |
407 | var currentURLhostNoTLD = url.parse(request.url).hostname.split(".")[0];
408 |
409 | var datPath = url.parse(request.url).pathname;
410 |
411 | logToScreen(datPath);
412 |
413 | logToScreen("TLD: " + currentTLD + " Hash: " + currentURLhostNoTLD);
414 |
415 | } else {
416 |
417 | fs.mkdirSync(appPath + "/dats/");
418 | logToScreen(request.url);
419 |
420 | }
421 |
422 | };
423 |
424 | const server = http.createServer(requestHandler);
425 |
426 | server.listen(port, (err) => {
427 | if (err) {
428 | return logToScreen('something bad happened', err);
429 | }
430 |
431 | logToScreen(`server is listening on ${port}`);
432 | });
--------------------------------------------------------------------------------