262 lines
7.8 KiB
HTML
262 lines
7.8 KiB
HTML
<!--
|
|
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>
|
|
</div>
|
|
|
|
<div id="manual-area" class="container" style="text-align: center;">
|
|
<p>Please upload the images you want to protect.</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" style="text-align: center;">
|
|
</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});
|
|
|
|
// Reset file input
|
|
document.getElementById("input-file").value = "";
|
|
|
|
}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";
|
|
|
|
// Display new manual text
|
|
var man = "";
|
|
man += "<p>Please wait while Fawkes processes your images. This might take a while.</p>";
|
|
document.getElementById("manual-area").innerHTML = man;
|
|
|
|
// 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;
|
|
document.getElementById("table-area").style.display = "none";
|
|
document.getElementById("manual-area").style.display = "none";
|
|
|
|
}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;
|
|
document.getElementById("table-area").style.display = "none";
|
|
document.getElementById("manual-area").style.display = "none";
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|