├── 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 |
11 |

DatPart

12 |

Serving Dat sites locally

Test site: 1c7639eedaf8f7533f92e7c34f5a6d2b43645347836ab5e9f2489e89d3b08306 13 |

If you don't have it, get the Chrome Extension here. 14 |

15 | 16 |
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 |
14 |

DatPart server

15 |

Serving Dat sites locally

Test site: 1c7639eedaf8f7533f92e7c34f5a6d2b43645347836ab5e9f2489e89d3b08306 16 |

Log
17 |

If you don't have it, get the Chrome Extension here. 18 |

19 | 24 |
25 | 26 | -------------------------------------------------------------------------------- /chrome app/server_app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DatPart Server 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |

DatPart server

18 |

Serving Dat sites locally

Test site: 1c7639eedaf8f7533f92e7c34f5a6d2b43645347836ab5e9f2489e89d3b08306

19 |

Log
20 |

This requires the Chrome Extension to work. If you don't have it, get the Chrome Extension here. 21 |

22 | 27 |
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 | 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 |

Credits

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 |

QR Code Generator

30 |
31 |
32 |

33 | 34 | 35 |
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 |

QR Code Scanner

39 |
40 | 41 |
Unable to access video stream (please make sure you have a webcam enabled)
42 | 43 | 44 | 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 |

🔧 Options

22 |
23 | 24 |

Gateway

25 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

Permissions

41 |
    42 |
  • Enable checking domains for Dat sites:
  • 43 | 44 |
  • Enable notifications:
  • 45 |
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 |

✨ Welcome!

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 |
67 |

DatPart!

68 | 69 |
Title
70 | Description

71 | 72 |

73 | 74 | dat:// Linkdat:// Link dat://

75 | 76 | 78 | 79 | Options
80 | 81 |
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 |
131 |

  DatPart!

132 | 133 |
134 | Title
135 | Description

136 | 140 |
Dat URL 141 |
142 | 143 | 145 | 146 | 151 | 152 |
153 | QR Code 154 |
155 | 156 |
157 | Link to the QR Code 158 |
159 | 160 | dat:// Linkdat:// Link dat:// 161 | 162 |
163 | 164 | 170 | 171 |
172 | QR Code Scanner
173 | 176 | Options
177 | 178 | 🌐 Enable domain Dat check 179 | 🌌
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 | }); --------------------------------------------------------------------------------