Add onionshare CLI to cli folder, move GUI to desktop folder, and start refactoring it to work with briefcase

This commit is contained in:
Micah Lee 2020-10-12 22:40:55 -07:00
parent 93e90c89ae
commit a54f99adf6
583 changed files with 14871 additions and 474 deletions

View file

@ -0,0 +1,393 @@
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
body {
margin: 0;
font-family: Helvetica, sans-serif;
}
.d-flex {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
header {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
background: #fcfcfc;
background: -webkit-linear-gradient(top, #fcfcfc 0%, #f2f2f2 100%);
padding: 0.8rem;
}
header .logo {
vertical-align: middle;
width: 45px;
height: 45px;
}
header h1 {
display: inline-block;
margin: 0 0 0 0.5rem;
vertical-align: middle;
font-weight: normal;
font-size: 1.5rem;
color: #666666;
}
header .information {
font-size: 1rem;
}
.button {
color: #ffffff;
background-color: #4e064f;
padding: 10px;
border: 0;
border-radius: 5px;
text-decoration: none;
margin-left: 1rem;
cursor: pointer;
}
a.button:visited {
color: #ffffff;
}
.close-button {
color: #ffffff;
background-color: #c90c0c;
padding: 10px;
border: 0;
border-radius: 5px;
text-decoration: none;
margin-left: 1rem;
cursor: pointer;
position: absolute;
right: 10px;
bottom: 10px;
}
ul.breadcrumbs {
display: block;
list-style: none;
margin: 10px 0;
padding: 0;
}
ul.breadcrumbs li {
display: inline-block;
list-style: none;
margin: 0;
padding: 5px;
color: #999999;
}
ul.breadcrumbs li span.sep {
padding-left: 5px;
}
ul.breadcrumbs li a:link, ul.breadcrumbs li a:visited {
color: #666666;
border-bottom: 1px solid #666666;
}
.file-list {
width: 100%;
margin: 0 auto;
border-collapse: collapse;
}
.file-list .heading {
text-align: left;
text-transform: uppercase;
font-weight: normal;
color: #666666;
padding: 0.5rem;
}
.file-list div.d-flex {
border-bottom: 1px solid #e0e0e0;
justify-content: flex-start;
}
.file-list div.d-flex div {
white-space: nowrap;
padding: 0.5rem 0.8rem 0.5rem 0.8rem;
}
.file-list div.d-flex div img {
vertical-align: middle;
margin-right: 0.5rem;
}
.file-list div.d-flex div:last-child {
padding-right: 0.8rem;
flex-basis: 0;
flex-grow: 1;
}
.file-list div.d-flex div:first-child {
flex-basis: 0;
flex-grow: 2;
}
@media (max-width: 950px) {
.file-list div.d-flex div:last-child {
flex-basis: auto;
flex-grow: 0;
}
}
@media (max-width: 655px) {
.file-list div.d-flex {
display: block;
}
.file-list div.d-flex span {
max-width: 100%;
word-break: break-all;
white-space: normal;
}
.file-list div.d-flex #size-header {
display: none;
}
.file-list div.d-flex div:last-child {
padding-left: 3.5rem;
font-size: 0.85rem;
padding-top: 0;
}
header .information {
padding: 1rem 0;
}
}
.chat-container {
display: flex;
font-family: monospace;
}
.chat-users {
width: 20%;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 2px;
overflow: auto;
background: #f2f2f2;
margin: 1rem 0 1rem 1rem;
}
.chat-users .editable-username {
display: flex;
padding: 1rem;
flex-direction: column;
}
.chat-users .editable-username input {
font-family: monospace;
font-size: 1em;
}
.chat-users .editable-username #username-error {
color: #c90c0c;
margin: 0.5rem;
}
.chat-users #user-list li {
margin-bottom: 1em;
}
.chat-wrapper {
display: flex;
flex-direction: column;
flex: 1;
margin: 1rem 1rem 0 1rem;
height: calc(100vh - (65px + 2em));
}
.chat-wrapper #chat {
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 2px;
flex: 1;
overflow: auto;
background: #f2f2f2;
padding: 0 1rem;
}
.chat-wrapper .status {
font-style: italic;
font-size: 0.8em;
color: #666666;
}
.chat-wrapper .username {
font-weight: bold;
display: block;
}
.chat-wrapper .message {
font-weight: normal;
display: block;
margin-bottom: 0.3em;
}
.chat-wrapper .chat-form {
display: block;
margin: 0.2rem 1rem 1rem 0;
padding: -0.5em;
}
.chat-wrapper input#new-message {
height: 100%;
width: 100%;
font-family: monospace;
font-size: 1em;
}
@media (max-width: 992px) {
.chat-users .editable-username {
display: block;
}
.chat-users input#username {
width: 90%;
}
}
.no-js {
display: none;
}
.upload-wrapper {
align-items: center;
justify-content: center;
min-height: 400px;
text-align: center;
}
.upload-wrapper img.logo {
width: 120px;
height: 120px;
}
.upload-wrapper .upload-header {
font-size: 30px;
font-weight: normal;
color: #666666;
margin: 0 0 10px 0;
}
.upload-wrapper .upload-description {
color: #666666;
margin: 0 0 20px 0;
}
div#uploads {
width: 800px;
max-width: 90%;
margin: 0 auto;
}
div#uploads .upload {
border: 1px solid #DDDDDD;
margin: 20px 0;
padding: 10px;
text-align: left;
}
div#uploads .upload .upload-filename {
font-weight: bold;
font-family: monospace;
font-size: 1.1em;
margin-bottom: 5px;
}
div#uploads .upload .upload-status {
color: #999999;
font-size: 0.9em;
margin-bottom: 5px;
}
div#uploads .upload input.cancel {
color: #d0011b;
border: 0;
background: none;
box-shadow: none;
border-radius: 0px;
cursor: pointer;
font-family: sans-serif;
font-size: 12px;
text-decoration: none;
display: inline-block;
float:right;
}
div#uploads .upload progress {
width: 100%;
height: 20px;
}
ul.flashes {
list-style: none;
margin: 0;
padding: 0;
width: 800px;
max-width: 100%;
margin: 0 auto;
}
ul.flashes li {
margin: 0 0 5px 0;
padding: 5px;
list-style: none;
text-align: center;
word-break: break-word;
}
li.error {
color: #d0011b;
}
li.info {
color: #5fa416;
}
.closed-wrapper {
display: flex;
align-items: center;
justify-content: center;
min-height: 400px;
}
.info {
text-align: center;
}
.info img {
width: 120px;
height: 120px;
}
.info .info-header {
font-size: 30px;
font-weight: normal;
color: #666666;
margin: 0 0 10px 0;
}
.info .info-description {
color: #666666;
margin: 0 0 20px 0;
}
a {
text-decoration: none;
color: #1c1ca0;
}
a:visited {
color: #601ca0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

View file

@ -0,0 +1,165 @@
$(function () {
$(document).ready(function () {
$('.chat-container').removeClass('no-js');
var socket = io.connect('http://' + document.domain + ':' + location.port + '/chat');
// Store current username received from app context
var current_username = $('#username').val();
// On browser connect, emit a socket event to be added to
// room and assigned random username
socket.on('connect', function () {
socket.emit('joined', {});
});
// Triggered on any status change by any user, such as some
// user joined, or changed username, or left, etc.
socket.on('status', function (data) {
addMessageToRoom(data, current_username, 'status');
console.log(data, current_username);
});
// Triggered when message is received from a user. Even when sent
// by self, it get triggered after the server sends back the emit.
socket.on('message', function (data) {
addMessageToRoom(data, current_username, 'chat');
console.log(data, current_username);
});
// Triggered when disconnected either by server stop or timeout
socket.on('disconnect', function (data) {
addMessageToRoom({ 'msg': 'The chat server is disconnected.' }, current_username, 'status');
})
socket.on('connect_error', function (error) {
console.log("error");
})
// Trigger new message on enter or click of send message button.
$('#new-message').on('keypress', function (e) {
var code = e.keyCode || e.which;
if (code == 13) {
emitMessage(socket);
}
});
// Keep buttons disabled unless changed or not empty
$('#username').on('keyup', function (event) {
if ($('#username').val() !== '' && $('#username').val() !== current_username) {
if (event.keyCode == 13) {
current_username = updateUsername(socket) || current_username;
}
}
});
// Show warning of losing data
$(window).on('beforeunload', function (e) {
e.preventDefault();
e.returnValue = '';
return '';
});
});
});
var addMessageToRoom = function (data, current_username, messageType) {
var scrollDiff = getScrollDiffBefore();
if (messageType === 'status') {
addStatusMessage(data.msg);
if (data.connected_users) {
addUserList(data.connected_users, current_username);
}
} else if (messageType === 'chat') {
addChatMessage(data.username, data.msg)
}
scrollBottomMaybe(scrollDiff);
}
var emitMessage = function (socket) {
var text = $('#new-message').val();
$('#new-message').val('');
$('#chat').scrollTop($('#chat')[0].scrollHeight);
socket.emit('text', { msg: text });
}
var updateUsername = function (socket) {
var username = $('#username').val();
if (!checkUsernameExists(username)) {
socket.emit('update_username', { username: username });
$.ajax({
method: 'POST',
url: `http://${document.domain}:${location.port}/update-session-username`,
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({ 'username': username })
}).done(function (response) {
console.log(response);
});
return username;
}
return false;
}
/************************************/
/********* Util Functions ***********/
/************************************/
var createUserListHTML = function (connected_users, current_user) {
var userListHTML = '';
connected_users.sort();
connected_users.forEach(function (username) {
if (username !== current_user) {
userListHTML += `<li>${sanitizeHTML(username)}</li>`;
}
});
return userListHTML;
}
var checkUsernameExists = function (username) {
$('#username-error').text('');
var userMatches = $('#user-list li').filter(function () {
return $(this).text() === username;
});
if (userMatches.length) {
$('#username-error').text('User with that username exists!');
return true;
}
return false;
}
var getScrollDiffBefore = function () {
return $('#chat').scrollTop() - ($('#chat')[0].scrollHeight - $('#chat')[0].offsetHeight);
}
var scrollBottomMaybe = function (scrollDiff) {
// Scrolls to bottom if the user is scrolled at bottom
// if the user has scrolled upp, it wont scroll at bottom.
// Note: when a user themselves send a message, it will still
// scroll to the bottom even if they had scrolled up before.
if (scrollDiff > 0) {
$('#chat').scrollTop($('#chat')[0].scrollHeight);
}
}
var addStatusMessage = function (message) {
$('#chat').append(
`<p class="status">${sanitizeHTML(message)}</p>`
);
}
var addChatMessage = function (username, message) {
$('#chat').append(`<p><span class="username">${sanitizeHTML(username)}</span><span class="message">${sanitizeHTML(message)}</span></p>`);
}
var addUserList = function (connected_users, current_username) {
$('#user-list').html(
createUserListHTML(
connected_users,
current_username
)
);
}
var sanitizeHTML = function (str) {
var temp = document.createElement('span');
temp.textContent = str;
return temp.innerHTML;
};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,130 @@
$(function(){
// Add a flash message
var flash = function(category, message) {
$('#flashes').append($('<li>').addClass(category).text(message));
};
var scriptSrc = document.getElementById('receive-script').src;
var staticImgPath = scriptSrc.substr(0, scriptSrc.lastIndexOf( '/' )+1).replace('js', 'img');
// Intercept submitting the form
$('#send').submit(function(event){
event.preventDefault();
// Create form data, and list of filenames
var files = $('#file-select').get(0).files;
var filenames = [];
var formData = new FormData();
for(var i = 0; i < files.length; i++) {
var file = files[i];
filenames.push(file.name);
formData.append('file[]', file, file.name);
}
// Reset the upload form
$('#send').get(0).reset();
// Don't use jQuery for ajax request, because the upload progress event doesn't
// have access to the the XMLHttpRequest object
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener('progress', function(event){
// Update progress bar for this specific upload
if(event.lengthComputable) {
$('progress', ajax.$upload_div).attr({
value: event.loaded,
max: event.total,
});
}
// If it's finished sending all data to the first Tor node, remove cancel button
// and update the status
if(event.loaded == event.total) {
$('.cancel', ajax.$upload_div).remove();
$('.upload-status', ajax.$upload_div).html('<img src="' + staticImgPath + '/ajax.gif" alt="" /> Waiting for data to finish traversing Tor network ...');
}
}, false);
ajax.addEventListener('load', function(event){
// Remove the upload div
ajax.$upload_div.remove();
// Parse response
try {
var response = JSON.parse(ajax.response);
// The 'new_body' response replaces the whole HTML document and ends
if('new_body' in response) {
$('body').html(response['new_body']);
return;
}
// Show error flashes
if('error_flashes' in response) {
for(var i=0; i<response['error_flashes'].length; i++) {
flash('error', response['error_flashes'][i]);
}
}
// Show info flashes
if('info_flashes' in response) {
for(var i=0; i<response['info_flashes'].length; i++) {
flash('info', response['info_flashes'][i]);
}
}
} catch(e) {
flash('error', 'Invalid response from server: '+data);
}
}, false);
ajax.addEventListener('error', function(event){
flash('error', 'Error uploading: '+filenames.join(', '));
// Remove the upload div
ajax.$upload_div.remove()
}, false);
ajax.addEventListener('abort', function(event){
flash('error', 'Upload aborted: '+filenames.join(', '));
}, false);
// Make the upload div
/* The DOM for an upload looks something like this:
<div class="upload">
<div class="upload-meta">
<input class="cancel" type="button" value="Cancel" />
<div class="upload-filename">educational-video.mp4, secret-plans.pdf</div>
<div class="upload-status">Sending to first Tor node ...</div>
</div>
<progress value="25" max="100"></progress>
</div> */
var $progress = $('<progress>').attr({ value: '0', max: 100 });
var $cancel_button = $('<input>').addClass('cancel').attr({ type: 'button', value: 'Cancel' });
var $upload_filename = $('<div>').addClass('upload-filename').text(filenames.join(', '));
var $upload_status = $('<div>').addClass('upload-status').text('Sending data to initial Tor node ...');
var $upload_div = $('<div>')
.addClass('upload')
.append(
$('<div>').addClass('upload-meta')
.append($cancel_button)
.append($upload_filename)
.append($upload_status)
)
.append($progress);
$cancel_button.click(function(){
// Abort the upload, and remove the upload div
ajax.abort();
$upload_div.remove()
});
ajax.$upload_div = $upload_div;
$('#uploads').append($upload_div);
// Send the request
ajax.open('POST', '/upload-ajax', true);
ajax.send(formData);
});
});

View file

@ -0,0 +1,75 @@
// Function to convert human-readable sizes back to bytes, for sorting
function unhumanize(text) {
var powers = {'b': 0, 'k': 1, 'm': 2, 'g': 3, 't': 4};
var regex = /(\d+(?:\.\d+)?)\s?(B|K|M|G|T)?/i;
var res = regex.exec(text);
if(res[2] === undefined) {
// Account for alphabetical words (file/dir names)
return text;
} else {
return res[1] * Math.pow(1024, powers[res[2].toLowerCase()]);
}
}
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("file-list");
switching = true;
// Set the sorting direction to ascending:
dir = "asc";
/* Make a loop that will continue until
no switching has been done: */
while (switching) {
// Start by saying: no switching is done:
switching = false;
rows = table.getElementsByTagName("TR");
/* Loop through all table rows (except the
first, which contains table headers): */
for (i = 1; i < (rows.length - 1); i++) {
// Start by saying there should be no switching:
shouldSwitch = false;
/* Get the two elements you want to compare,
one from current row and one from the next: */
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
/* Check if the two rows should switch place,
based on the direction, asc or desc: */
if (dir == "asc") {
if (unhumanize(x.innerHTML.toLowerCase()) > unhumanize(y.innerHTML.toLowerCase())) {
// If so, mark as a switch and break the loop:
shouldSwitch= true;
break;
}
} else if (dir == "desc") {
if (unhumanize(x.innerHTML.toLowerCase()) < unhumanize(y.innerHTML.toLowerCase())) {
// If so, mark as a switch and break the loop:
shouldSwitch= true;
break;
}
}
}
if (shouldSwitch) {
/* If a switch has been marked, make the switch
and mark that a switch has been done: */
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
// Each time a switch is done, increase this count by 1:
switchcount ++;
} else {
/* If no switching has been done AND the direction is "asc",
set the direction to "desc" and run the while loop again. */
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
// Set click handlers
document.getElementById("filename-header").addEventListener("click", function(){
sortTable(0);
});
document.getElementById("size-header").addEventListener("click", function(){
sortTable(1);
});

File diff suppressed because one or more lines are too long