<!-- Copyright (C) 2021 Thomas Van Acker This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. This project is hosted on https://git.bitscuit.be/bitscuit/Fawkes --> <html> <head> <title>Fawkes</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css"> <link href="css/normalize.css" rel="stylesheet"> <link href="css/skeleton.css" rel="stylesheet"> <link href="css/extra.css" rel="stylesheet"> <link href="css/fontawesome/css/all.css" rel="stylesheet"> </head> <body style="padding-top: 10px;"> <div id="main" class="container" style="text-align: center;"> <h1>Fawkes</h1> <p>Protect your images from facial recognition.</p> <p>TODO: add more info</p> <p>The table below shows the status for each image you've uploaded. You can select the files you want to protect using the <i>Browse</i> and <i>Upload</i> buttons below.</p> </div> <div id="upload-area" class="container"> <div class="row"> <div class="twelve columns"> <label for="input-file">Your Image</label> <input class="u-full-width" type="file" id="input-file"> </div> </div> <button id="button-upload" class="button button-primary"><i class="fas fa-upload"></i> Upload</button> </div> <div id="table-area" class="container"> <table id="table-images" class="u-full-width"> <thead> <tr> <th>Image Name</th> <th>Status</th> </tr> </thead> <tbody> </tbody> </table> <p id="text-no-images" style="text-align: center;">You haven't uploaded any images yet.</p> <button class="button button-primary" id="button-start"><i class="fas fa-check"></i> Start Fawkes</button> </div> <div id="download-area" class="container"> </div> <div class="footer"> <p>Many thanks to the people who made <a href="http://sandlab.cs.uchicago.edu/fawkes/">Fawkes</a>!<br/>Copyright © 2021 Thomas Van Acker<br/>Project hosted on <a target="_blank" href="https://git.bitscuit.be/bitscuit/Fawkes">Gitscuit</a></p> </div> <!-- Socket.io stuff --> <script src="/socket.io/socket.io.js"></script> <script> // Vars var files = {}; // Start socket.io var socket = io(); // Init listeners document.getElementById("button-upload").addEventListener("click", function(){ if(document.getElementById("input-file").files.length != 0){ var file = document.getElementById("input-file").files[0]; // Add file to files list var id = Date.now(); files[id] = { file: file, uploading: true, error: false }; // Add file to table var table = document.getElementById("table-images").getElementsByTagName("tbody")[0]; var row = ""; row += "<tr id='row-"+id+"'>"; row += "<td>"+file.name+"</td>"; row += "<td id='status-"+id+"'><i class='fas fa-spinner fa-pulse'></i> Initializing Upload</td>"; row += "</tr>"; table.innerHTML += row; document.getElementById("text-no-images").style.display = "none"; // Send request to server socket.emit("FILE_START", {name:id, length:file.size}); }else{ // No file selected alert("Please select a file using the 'Browse' button."); } }); socket.on("FILE_ERROR", function(data){ // When error while uploading files[data.name].uploading = false; files[data.name].error = true; document.getElementById("status-"+data.name).innerHTML = "<i class='fas fa-exclamation-triangle'></i> Upload Error"; document.getElementById("status-"+data.name).title = data.error; }); socket.on("FILE_ACK", function(data){ // When can send next file segment var file = files[data.name]; var offset = data.nextSegment * 100000; var fileSegment = file.file.slice(offset, Math.min(offset + 100000, file.file.size)); var fileReader = new FileReader(); fileReader.onload = function(event){ socket.emit("FILE_DATA", {name:data.name, data:event.target.result, segment:data.nextSegment}); }; fileReader.readAsBinaryString(fileSegment); // Update status document.getElementById("status-"+data.name).innerHTML = "<i class='fas fa-spinner fa-pulse'></i> Uploading ("+Math.floor(100*data.nextSegment/data.numSegments)+"%)"; }); socket.on("FILE_DONE", function(data){ // File upload done files[data.name].uploading = false; document.getElementById("status-"+data.name).innerHTML = "<i class='fas fa-check'></i> Upload Complete"; }); document.getElementById("button-start").addEventListener("click", function(){ // When start button clicked // Check if all files uploaded var num = 0; for(let id in files){ if(files[id].uploading){ alert("Not all files have been uploaded!"); return; }else if(!files[id].error){ num++; } } if(num == 0){ alert("You haven't uploaded any files yet!"); return; } // Disable button and upload document.getElementById("button-start").style.display = "none"; document.getElementById("upload-area").style.display = "none"; // Send server request to start Fawkes socket.emit("FAWKES_START"); }); socket.on("FAWKES_STARTED", function(){ // Update all states for(let id in files){ if(!files[id].uploading && !files[id].error){ document.getElementById("status-"+id).innerHTML = "<i class='fas fa-hourglass-half'></i> In Queue"; } } }); socket.on("FAWKES_STATE", function(data){ // Update state if(data.face > data.numFaces){ document.getElementById("status-"+data.name).innerHTML = "<i class='fas fa-check'></i> Processing Complete"; }else if(data.numFaces == 0){ document.getElementById("status-"+data.name).innerHTML = "<i class='fas fa-check'></i> No Faces Detected"; }else{ document.getElementById("status-"+data.name).innerHTML = "<i class='fas fa-spinner fa-pulse'></i> Processing Faces ("+data.face+"/"+data.numFaces+")"; } }); socket.on("FAWKES_DONE", function(data){ // When fawkes exited if(data.success){ // Download ready var page = ""; page += "<h5><i class='fas fa-check'></i> Processing Complete</h5>"; page += "<p>Your images have been protected!</p>"; page += "<a class='button button-primary' href='"+data.downloadUrl+"' target='_blank'><i class='fas fa-download'></i> Download</a>"; document.getElementById("download-area").innerHTML = page; }else{ // Error var page = ""; page += "<h5><i class='fas fa-exclamation-triangle'></i> Processing Failed</h5>"; page += "<p>"+data.message+"</p>"; document.getElementById("download-area").innerHTML = page; } }); </script> </body> </html>