Merge branch 'node-profiling' of gitlab.com:beardog/Onionr into node-profiling
commit
2fd387eeb8
|
@ -202,7 +202,14 @@ class Onionr:
|
||||||
'ui' : self.openUI,
|
'ui' : self.openUI,
|
||||||
'gui' : self.openUI,
|
'gui' : self.openUI,
|
||||||
|
|
||||||
'getpassword': self.printWebPassword
|
'getpassword': self.printWebPassword,
|
||||||
|
'get-password': self.printWebPassword,
|
||||||
|
'getpwd': self.printWebPassword,
|
||||||
|
'get-pwd': self.printWebPassword,
|
||||||
|
'getpass': self.printWebPassword,
|
||||||
|
'get-pass': self.printWebPassword,
|
||||||
|
'getpasswd': self.printWebPassword,
|
||||||
|
'get-passwd': self.printWebPassword
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cmdhelp = {
|
self.cmdhelp = {
|
||||||
|
@ -212,7 +219,7 @@ class Onionr:
|
||||||
'start': 'Starts the Onionr daemon',
|
'start': 'Starts the Onionr daemon',
|
||||||
'stop': 'Stops the Onionr daemon',
|
'stop': 'Stops the Onionr daemon',
|
||||||
'stats': 'Displays node statistics',
|
'stats': 'Displays node statistics',
|
||||||
'getpassword': 'Displays the web password',
|
'get-password': 'Displays the web password',
|
||||||
'enable-plugin': 'Enables and starts a plugin',
|
'enable-plugin': 'Enables and starts a plugin',
|
||||||
'disable-plugin': 'Disables and stops a plugin',
|
'disable-plugin': 'Disables and stops a plugin',
|
||||||
'reload-plugin': 'Reloads a plugin',
|
'reload-plugin': 'Reloads a plugin',
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="onionr-post-controls pt-2">
|
<div class="onionr-post-controls pt-2">
|
||||||
<a href="#!" class="glyphicon glyphicon-heart mr-2">like</a>
|
<a href="#!" onclick="toggleLike('$post-id')" class="glyphicon glyphicon-heart mr-2"><$= LANG.POST_LIKE $></a>
|
||||||
<a href="#!" class="glyphicon glyphicon-comment mr-2">comment</a>
|
<a href="#!" onclick="reply('$post-id')" class="glyphicon glyphicon-comment mr-2"><$= LANG.POST_REPLY $></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -40,53 +40,60 @@ with open('lang.json', 'r') as file:
|
||||||
LANG = type('LANG', (), langmap)
|
LANG = type('LANG', (), langmap)
|
||||||
|
|
||||||
# templating
|
# templating
|
||||||
def jsTemplate(template):
|
class Template:
|
||||||
with open('common/%s.html' % template, 'r') as file:
|
def jsTemplate(template):
|
||||||
return file.read().replace('\\', '\\\\').replace('\'', '\\\'').replace('\n', "\\\n")
|
with open('common/%s.html' % template, 'r') as file:
|
||||||
|
return Template.parseTags(file.read().replace('\\', '\\\\').replace('\'', '\\\'').replace('\n', "\\\n"))
|
||||||
|
|
||||||
def htmlTemplate(template):
|
def htmlTemplate(template):
|
||||||
with open('common/%s.html' % template, 'r') as file:
|
with open('common/%s.html' % template, 'r') as file:
|
||||||
return file.read()
|
return Template.parseTags(file.read())
|
||||||
|
|
||||||
# tag parser
|
# tag parser
|
||||||
def parseTags(contents):
|
def parseTags(contents):
|
||||||
# <$ logic $>
|
# <$ logic $>
|
||||||
for match in re.findall(r'(<\$(?!=)(.*?)\$>)', contents):
|
for match in re.findall(r'(<\$(?!=)(.*?)\$>)', contents):
|
||||||
try:
|
try:
|
||||||
out = exec(match[1].strip())
|
out = exec(match[1].strip())
|
||||||
contents = contents.replace(match[0], '' if out is None else str(out))
|
contents = contents.replace(match[0], '' if out is None else str(out))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
|
print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print('\nIgnoring this error, continuing to compile...\n')
|
print('\nIgnoring this error, continuing to compile...\n')
|
||||||
|
|
||||||
# <$= data $>
|
# <$= data $>
|
||||||
for match in re.findall(r'(<\$=(.*?)\$>)', contents):
|
for match in re.findall(r'(<\$=(.*?)\$>)', contents):
|
||||||
try:
|
try:
|
||||||
out = eval(match[1].strip())
|
out = eval(match[1].strip())
|
||||||
contents = contents.replace(match[0], '' if out is None else str(out))
|
contents = contents.replace(match[0], '' if out is None else str(out))
|
||||||
except NameError as e:
|
except NameError as e:
|
||||||
name = match[1].strip()
|
name = match[1].strip()
|
||||||
print('Warning: %s does not exist, treating as an str' % name)
|
print('Warning: %s does not exist, treating as an str' % name)
|
||||||
contents = contents.replace(match[0], name)
|
contents = contents.replace(match[0], name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
|
print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print('\nIgnoring this error, continuing to compile...\n')
|
print('\nIgnoring this error, continuing to compile...\n')
|
||||||
|
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
|
def jsTemplate(contents):
|
||||||
|
return Template.jsTemplate(contents)
|
||||||
|
|
||||||
|
def htmlTemplate(contents):
|
||||||
|
return Template.htmlTemplate(contents)
|
||||||
|
|
||||||
# get header file
|
# get header file
|
||||||
with open(HEADER_FILE, 'r') as file:
|
with open(HEADER_FILE, 'r') as file:
|
||||||
HEADER_FILE = file.read()
|
HEADER_FILE = file.read()
|
||||||
if settings['python_tags']:
|
if settings['python_tags']:
|
||||||
HEADER_FILE = parseTags(HEADER_FILE)
|
HEADER_FILE = Template.parseTags(HEADER_FILE)
|
||||||
|
|
||||||
# get footer file
|
# get footer file
|
||||||
with open(FOOTER_FILE, 'r') as file:
|
with open(FOOTER_FILE, 'r') as file:
|
||||||
FOOTER_FILE = file.read()
|
FOOTER_FILE = file.read()
|
||||||
if settings['python_tags']:
|
if settings['python_tags']:
|
||||||
FOOTER_FILE = parseTags(FOOTER_FILE)
|
FOOTER_FILE = Template.parseTags(FOOTER_FILE)
|
||||||
|
|
||||||
# iterate dst, replace files
|
# iterate dst, replace files
|
||||||
def iterate(directory):
|
def iterate(directory):
|
||||||
|
@ -111,7 +118,7 @@ def iterate(directory):
|
||||||
|
|
||||||
# do python tags
|
# do python tags
|
||||||
if settings['python_tags']:
|
if settings['python_tags']:
|
||||||
contents = parseTags(contents)
|
contents = Template.parseTags(contents)
|
||||||
|
|
||||||
# write file
|
# write file
|
||||||
file.write(contents)
|
file.write(contents)
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="h-divider d-block d-lg-none pb-3"></div>
|
<div class="h-divider pb-3 d-block d-lg-none"></div>
|
||||||
|
|
||||||
<div class="col-sm-12 col-lg-6">
|
<div class="col-sm-12 col-lg-6">
|
||||||
<div class="row" id="onionr-timeline-posts">
|
<div class="row" id="onionr-timeline-posts">
|
||||||
|
|
|
@ -95,14 +95,34 @@ String.prototype.replaceAll = function(search, replacement) {
|
||||||
return target.split(search).join(replacement);
|
return target.split(search).join(replacement);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sanitizes HTML in a string */
|
/* useful functions to sanitize data */
|
||||||
function encodeHTML(html) {
|
class Sanitize {
|
||||||
return String(html).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
/* sanitizes HTML in a string */
|
||||||
|
static html(html) {
|
||||||
|
return String(html).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* URL encodes a string */
|
||||||
|
static url(url) {
|
||||||
|
return encodeURIComponent(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* URL encodes a string */
|
/* config stuff */
|
||||||
function encodeURL(url) {
|
function getWebPassword() {
|
||||||
return encodeURIComponent(url);
|
return get("web-password", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWebPassword(password) {
|
||||||
|
return set("web-password", password);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimingToken() {
|
||||||
|
return get("timing-token", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTimingToken(token) {
|
||||||
|
return set("timing-token", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* user class */
|
/* user class */
|
||||||
|
@ -179,8 +199,8 @@ class Post {
|
||||||
</div>\
|
</div>\
|
||||||
\
|
\
|
||||||
<div class="onionr-post-controls pt-2">\
|
<div class="onionr-post-controls pt-2">\
|
||||||
<a href="#!" class="glyphicon glyphicon-heart mr-2">like</a>\
|
<a href="#!" onclick="toggleLike(\'$post-id\')" class="glyphicon glyphicon-heart mr-2">like</a>\
|
||||||
<a href="#!" class="glyphicon glyphicon-comment mr-2">comment</a>\
|
<a href="#!" onclick="reply(\'$post-id\')" class="glyphicon glyphicon-comment mr-2">reply</a>\
|
||||||
</div>\
|
</div>\
|
||||||
</div>\
|
</div>\
|
||||||
</div>\
|
</div>\
|
||||||
|
@ -191,13 +211,16 @@ class Post {
|
||||||
|
|
||||||
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
|
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
|
||||||
|
|
||||||
postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
|
postTemplate = postTemplate.replaceAll('$user-name-url', Sanitize.html(Sanitize.url(this.getUser().getName())));
|
||||||
postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
|
postTemplate = postTemplate.replaceAll('$user-name', Sanitize.html(this.getUser().getName()));
|
||||||
postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(this.getUser().getID())));
|
postTemplate = postTemplate.replaceAll('$user-id-url', Sanitize.html(Sanitize.url(this.getUser().getID())));
|
||||||
postTemplate = postTemplate.replaceAll('$user-id-truncated', encodeHTML(this.getUser().getID().split('-').slice(0, 4).join('-')));
|
|
||||||
postTemplate = postTemplate.replaceAll('$user-id', encodeHTML(this.getUser().getID()));
|
postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().substring(0, 12) + '...'));
|
||||||
postTemplate = postTemplate.replaceAll('$user-image', encodeHTML(this.getUser().getIcon()));
|
// postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
|
||||||
postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
|
|
||||||
|
postTemplate = postTemplate.replaceAll('$user-id', Sanitize.html(this.getUser().getID()));
|
||||||
|
postTemplate = postTemplate.replaceAll('$user-image', Sanitize.html(this.getUser().getIcon()));
|
||||||
|
postTemplate = postTemplate.replaceAll('$content', Sanitize.html(this.getContent()));
|
||||||
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
|
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
|
||||||
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
||||||
|
|
||||||
|
@ -231,3 +254,198 @@ class Post {
|
||||||
return this.date;
|
return this.date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* block class */
|
||||||
|
class Block {
|
||||||
|
constructor(type, content) {
|
||||||
|
this.type = type;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block hash, if any
|
||||||
|
getHash() {
|
||||||
|
return this.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block type
|
||||||
|
getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block header
|
||||||
|
getHeader(key, df) { // df is default
|
||||||
|
if(key !== undefined) {
|
||||||
|
if(this.getHeader().hasOwnProperty(key))
|
||||||
|
return this.getHeader()[key];
|
||||||
|
else
|
||||||
|
return (df === undefined ? null : df);
|
||||||
|
} else
|
||||||
|
return this.header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block metadata
|
||||||
|
getMetadata(key, df) { // df is default
|
||||||
|
if(key !== undefined) {
|
||||||
|
if(this.getMetadata().hasOwnProperty(key))
|
||||||
|
return this.getMetadata()[key];
|
||||||
|
else
|
||||||
|
return (df === undefined ? null : df);
|
||||||
|
} else
|
||||||
|
return this.metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block content
|
||||||
|
getContent() {
|
||||||
|
return this.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the parent block's hash (not Block object, for performance)
|
||||||
|
getParent() {
|
||||||
|
if(!(this.parent instanceof Block) && this.parent !== undefined && this.parent !== null)
|
||||||
|
this.parent = Block.openBlock(this.parent); // convert hash to Block object
|
||||||
|
return this.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the date that the block was received
|
||||||
|
getDate() {
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a boolean that indicates whether or not the block is valid
|
||||||
|
isValid() {
|
||||||
|
return this.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a boolean thati ndicates whether or not the block is signed
|
||||||
|
isSigned() {
|
||||||
|
return this.signed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block signature
|
||||||
|
getSignature() {
|
||||||
|
return this.signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block type
|
||||||
|
setType(type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets block metadata by key
|
||||||
|
setMetadata(key, val) {
|
||||||
|
this.metadata[key] = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets block content
|
||||||
|
setContent(content) {
|
||||||
|
this.content = content;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the block parent by hash or Block object
|
||||||
|
setParent(parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// indicates if the Block exists or not
|
||||||
|
exists() {
|
||||||
|
return !(this.hash === null || this.hash === undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static functions */
|
||||||
|
|
||||||
|
// recreates a block by hash
|
||||||
|
static openBlock(hash) {
|
||||||
|
return parseBlock(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts an associative array to a Block
|
||||||
|
static parseBlock(val) {
|
||||||
|
var block = new Block();
|
||||||
|
|
||||||
|
block.type = val['type'];
|
||||||
|
block.content = val['content'];
|
||||||
|
block.header = val['header'];
|
||||||
|
block.metadata = val['metadata'];
|
||||||
|
block.date = new Date(val['date'] * 1000);
|
||||||
|
block.hash = val['hash'];
|
||||||
|
block.signature = val['signature'];
|
||||||
|
block.signed = val['signed'];
|
||||||
|
block.valid = val['valid'];
|
||||||
|
block.parent = val['parent'];
|
||||||
|
|
||||||
|
if(block.getParent() !== null) {
|
||||||
|
// if the block data is already in the associative array
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (blocks.hasOwnProperty(block.getParent()))
|
||||||
|
block.setParent(Block.parseAssociativeArray({blocks[block.getParent()]})[0]);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts an array of associative arrays to an array of Blocks
|
||||||
|
static parseBlockArray(blocks) {
|
||||||
|
var outputBlocks = [];
|
||||||
|
|
||||||
|
for(var key in blocks) {
|
||||||
|
if(blocks.hasOwnProperty(key)) {
|
||||||
|
var val = blocks[key];
|
||||||
|
|
||||||
|
var block = Block.parseBlock(val);
|
||||||
|
|
||||||
|
outputBlocks.push(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getBlocks(args, callback) { // callback is optional
|
||||||
|
args = args || {}
|
||||||
|
|
||||||
|
var url = '/client/?action=searchBlocks&data=' + Sanitize.url(JSON.stringify(args)) + '&token=' + Sanitize.url(getWebPassword()) + '&timingToken=' + Sanitize.url(getTimingToken());
|
||||||
|
|
||||||
|
console.log(url);
|
||||||
|
|
||||||
|
var http = new XMLHttpRequest();
|
||||||
|
|
||||||
|
if(callback !== undefined) {
|
||||||
|
// async
|
||||||
|
|
||||||
|
http.addEventListener('load', function() {
|
||||||
|
callback(Block.parseBlockArray(JSON.parse(http.responseText)['blocks']));
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
http.open('GET', url, true);
|
||||||
|
http.timeout = 5000;
|
||||||
|
http.send(null);
|
||||||
|
} else {
|
||||||
|
// sync
|
||||||
|
|
||||||
|
http.open('GET', url, false);
|
||||||
|
http.send(null);
|
||||||
|
|
||||||
|
return Block.parseBlockArray(JSON.parse(http.responseText)['blocks']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* temporary code */
|
||||||
|
|
||||||
|
if(getWebPassword() === null) {
|
||||||
|
var password = "";
|
||||||
|
while(password.length != 64) {
|
||||||
|
password = prompt("Please enter the web password (run `./RUN-LINUX.sh --get-password`)");
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimingToken(prompt("Please enter the timing token (optional)"));
|
||||||
|
|
||||||
|
setWebPassword(password);
|
||||||
|
window.location.reload(true);
|
||||||
|
}
|
||||||
|
|
|
@ -1,96 +1,27 @@
|
||||||
/* write a random post to the page, for testing */
|
/* just for testing rn */
|
||||||
|
Block.getBlocks({'type' : 'onionr-post', 'signed' : true, 'reverse' : true}, function(data) {
|
||||||
|
for(var i = 0; i < data.length; i++) {
|
||||||
|
try {
|
||||||
|
var block = data[i];
|
||||||
|
|
||||||
var verbs =
|
var post = new Post();
|
||||||
[
|
var user = new User();
|
||||||
["go to", "goes to", "going to", "went to", "gone to"],
|
|
||||||
["look at", "looks at", "looking at", "looked at", "looked at"],
|
|
||||||
["choose", "chooses", "choosing", "chose", "chosen"],
|
|
||||||
["torrent", "downloads", "downloading", "torrented", "downloaded"],
|
|
||||||
["detonate", "detonates", "detonating", "detonated", "detonated"],
|
|
||||||
["run", "runs", "running", "ran", "running"],
|
|
||||||
["program", "programs", "programming", "coded", "programmed"],
|
|
||||||
["start", "starts", "starting", "started", "started"]
|
|
||||||
];
|
|
||||||
var tenses =
|
|
||||||
[
|
|
||||||
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
|
||||||
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
|
||||||
{name:"Present Continues", singular:2, plural:2, format:"%subject %be %verb %complement"}
|
|
||||||
];
|
|
||||||
var subjects =
|
|
||||||
[
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"My cat", be:"is", singular:0},
|
|
||||||
{name:"My cat", be:"is", singular:0},
|
|
||||||
{name:"My dog", be:"is", singular:0},
|
|
||||||
{name:"My dog", be:"is", singular:0},
|
|
||||||
{name:"My mom", be:"is", singular:0},
|
|
||||||
{name:"My dad", be:"is", singular:0},
|
|
||||||
{name:"You", be:"are", singular:0},
|
|
||||||
{name:"He", be:"is", singular:1}
|
|
||||||
];
|
|
||||||
var complementsForVerbs =
|
|
||||||
[
|
|
||||||
["cinema", "Egypt", "home", "concert"],
|
|
||||||
["for a map", "them", "the stars", "the lake"],
|
|
||||||
["a book for reading", "a dvd for tonight"],
|
|
||||||
["the virus", "the malware", "that 0day", "Onionr"],
|
|
||||||
["a bomb", "a nuke", "some C4", "some ammonium nitrate"],
|
|
||||||
["the race", "towards someone", "to the stars", "on top of your roof"],
|
|
||||||
["Onionr", "the malware", "some software", "Onionr"],
|
|
||||||
["Onionr", "Onionr", "the race", "the timer"],
|
|
||||||
]
|
|
||||||
|
|
||||||
Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)];};
|
var blockContent = JSON.parse(block.getContent());
|
||||||
|
|
||||||
function generate(){
|
user.setName('unknown');
|
||||||
var index = Math.floor(verbs.length * Math.random());
|
user.setID(new String(block.getHeader('signer', 'unknown')));
|
||||||
var tense = tenses.random();
|
post.setContent(blockContent['content']);
|
||||||
var subject = subjects.random();
|
post.setPostDate(block.getDate());
|
||||||
var verb = verbs[index];
|
post.setUser(user);
|
||||||
var complement = complementsForVerbs[index];
|
|
||||||
var str = tense.format;
|
|
||||||
str = str.replace("%subject", subject.name).replace("%be", subject.be);
|
|
||||||
str = str.replace("%verb", verb[subject.singular ? tense.singular : tense.plural]);
|
|
||||||
str = str.replace("%complement", complement.random());
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
var curDate = new Date()
|
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
||||||
function addRandomPost() {
|
} catch(e) {
|
||||||
var post = new Post();
|
console.log(e);
|
||||||
var user = new User();
|
}
|
||||||
var items = ['arinerron', 'beardog108', 'samyk', 'snowden', 'aaronswartz'];
|
}
|
||||||
user.setName(items[Math.floor(Math.random()*items.length)]);
|
});
|
||||||
user.setID('i-eat-waffles-often-its-actually-crazy-like-i-dont-know-wow');
|
|
||||||
post.setContent(generate());
|
|
||||||
post.setUser(user);
|
|
||||||
|
|
||||||
curDate = new Date(curDate - (Math.random() * 1000000));
|
|
||||||
post.setPostDate(curDate);
|
|
||||||
|
|
||||||
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i = 0; i < Math.round(50 * Math.random()); i++)
|
|
||||||
addRandomPost();
|
|
||||||
|
|
||||||
function viewProfile(id, name) {
|
function viewProfile(id, name) {
|
||||||
document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
|
document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(decodeURIComponent(name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,40 @@
|
||||||
{
|
{
|
||||||
"eng" : {
|
"eng" : {
|
||||||
"ONIONR_TITLE" : "Onionr UI",
|
"ONIONR_TITLE" : "Onionr UI",
|
||||||
|
|
||||||
"TIMELINE" : "Timeline",
|
"TIMELINE" : "Timeline",
|
||||||
"NOTIFICATIONS" : "Notifications",
|
"NOTIFICATIONS" : "Notifications",
|
||||||
"MESSAGES" : "Messages",
|
"MESSAGES" : "Messages",
|
||||||
|
|
||||||
"TRENDING" : "Trending"
|
"TRENDING" : "Trending",
|
||||||
|
|
||||||
|
"POST_LIKE" : "like",
|
||||||
|
"POST_REPLY" : "reply"
|
||||||
},
|
},
|
||||||
|
|
||||||
"spa" : {
|
"spa" : {
|
||||||
"ONIONR_TITLE" : "Onionr UI",
|
"ONIONR_TITLE" : "Onionr UI",
|
||||||
|
|
||||||
"TIMELINE" : "Linea de Tiempo",
|
"TIMELINE" : "Linea de Tiempo",
|
||||||
"NOTIFICATIONS" : "Notificaciones",
|
"NOTIFICATIONS" : "Notificaciones",
|
||||||
"MESSAGES" : "Mensaje",
|
"MESSAGES" : "Mensaje",
|
||||||
|
|
||||||
"TRENDING" : "Trending"
|
"TRENDING" : "Trending",
|
||||||
|
|
||||||
|
"POST_LIKE" : "me gusta",
|
||||||
|
"POST_REPLY" : "comentario"
|
||||||
},
|
},
|
||||||
|
|
||||||
"zho" : {
|
"zho" : {
|
||||||
"ONIONR_TITLE" : "洋葱 用户界面",
|
"ONIONR_TITLE" : "洋葱 用户界面",
|
||||||
|
|
||||||
"TIMELINE" : "时间线",
|
"TIMELINE" : "时间线",
|
||||||
"NOTIFICATIONS" : "通知",
|
"NOTIFICATIONS" : "通知",
|
||||||
"MESSAGES" : "消息",
|
"MESSAGES" : "消息",
|
||||||
|
|
||||||
"TRENDING" : "趋势"
|
"TRENDING" : "趋势",
|
||||||
|
|
||||||
|
"POST_LIKE" : "喜欢",
|
||||||
|
"POST_REPLY" : "回复"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,14 +95,34 @@ String.prototype.replaceAll = function(search, replacement) {
|
||||||
return target.split(search).join(replacement);
|
return target.split(search).join(replacement);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sanitizes HTML in a string */
|
/* useful functions to sanitize data */
|
||||||
function encodeHTML(html) {
|
class Sanitize {
|
||||||
return String(html).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
/* sanitizes HTML in a string */
|
||||||
|
static html(html) {
|
||||||
|
return String(html).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* URL encodes a string */
|
||||||
|
static url(url) {
|
||||||
|
return encodeURIComponent(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* URL encodes a string */
|
/* config stuff */
|
||||||
function encodeURL(url) {
|
function getWebPassword() {
|
||||||
return encodeURIComponent(url);
|
return get("web-password", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWebPassword(password) {
|
||||||
|
return set("web-password", password);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimingToken() {
|
||||||
|
return get("timing-token", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTimingToken(token) {
|
||||||
|
return set("timing-token", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* user class */
|
/* user class */
|
||||||
|
@ -159,13 +179,16 @@ class Post {
|
||||||
|
|
||||||
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
|
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
|
||||||
|
|
||||||
postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
|
postTemplate = postTemplate.replaceAll('$user-name-url', Sanitize.html(Sanitize.url(this.getUser().getName())));
|
||||||
postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
|
postTemplate = postTemplate.replaceAll('$user-name', Sanitize.html(this.getUser().getName()));
|
||||||
postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(this.getUser().getID())));
|
postTemplate = postTemplate.replaceAll('$user-id-url', Sanitize.html(Sanitize.url(this.getUser().getID())));
|
||||||
postTemplate = postTemplate.replaceAll('$user-id-truncated', encodeHTML(this.getUser().getID().split('-').slice(0, 4).join('-')));
|
|
||||||
postTemplate = postTemplate.replaceAll('$user-id', encodeHTML(this.getUser().getID()));
|
postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().substring(0, 12) + '...'));
|
||||||
postTemplate = postTemplate.replaceAll('$user-image', encodeHTML(this.getUser().getIcon()));
|
// postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
|
||||||
postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
|
|
||||||
|
postTemplate = postTemplate.replaceAll('$user-id', Sanitize.html(this.getUser().getID()));
|
||||||
|
postTemplate = postTemplate.replaceAll('$user-image', Sanitize.html(this.getUser().getIcon()));
|
||||||
|
postTemplate = postTemplate.replaceAll('$content', Sanitize.html(this.getContent()));
|
||||||
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
|
postTemplate = postTemplate.replaceAll('$date-relative', timeSince(this.getPostDate(), device) + (device === 'desktop' ? ' ago' : ''));
|
||||||
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
postTemplate = postTemplate.replaceAll('$date', this.getPostDate().toLocaleString());
|
||||||
|
|
||||||
|
@ -199,3 +222,198 @@ class Post {
|
||||||
return this.date;
|
return this.date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* block class */
|
||||||
|
class Block {
|
||||||
|
constructor(type, content) {
|
||||||
|
this.type = type;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block hash, if any
|
||||||
|
getHash() {
|
||||||
|
return this.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block type
|
||||||
|
getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block header
|
||||||
|
getHeader(key, df) { // df is default
|
||||||
|
if(key !== undefined) {
|
||||||
|
if(this.getHeader().hasOwnProperty(key))
|
||||||
|
return this.getHeader()[key];
|
||||||
|
else
|
||||||
|
return (df === undefined ? null : df);
|
||||||
|
} else
|
||||||
|
return this.header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block metadata
|
||||||
|
getMetadata(key, df) { // df is default
|
||||||
|
if(key !== undefined) {
|
||||||
|
if(this.getMetadata().hasOwnProperty(key))
|
||||||
|
return this.getMetadata()[key];
|
||||||
|
else
|
||||||
|
return (df === undefined ? null : df);
|
||||||
|
} else
|
||||||
|
return this.metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block content
|
||||||
|
getContent() {
|
||||||
|
return this.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the parent block's hash (not Block object, for performance)
|
||||||
|
getParent() {
|
||||||
|
if(!(this.parent instanceof Block) && this.parent !== undefined && this.parent !== null)
|
||||||
|
this.parent = Block.openBlock(this.parent); // convert hash to Block object
|
||||||
|
return this.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the date that the block was received
|
||||||
|
getDate() {
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a boolean that indicates whether or not the block is valid
|
||||||
|
isValid() {
|
||||||
|
return this.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a boolean thati ndicates whether or not the block is signed
|
||||||
|
isSigned() {
|
||||||
|
return this.signed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block signature
|
||||||
|
getSignature() {
|
||||||
|
return this.signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the block type
|
||||||
|
setType(type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets block metadata by key
|
||||||
|
setMetadata(key, val) {
|
||||||
|
this.metadata[key] = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets block content
|
||||||
|
setContent(content) {
|
||||||
|
this.content = content;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the block parent by hash or Block object
|
||||||
|
setParent(parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// indicates if the Block exists or not
|
||||||
|
exists() {
|
||||||
|
return !(this.hash === null || this.hash === undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static functions */
|
||||||
|
|
||||||
|
// recreates a block by hash
|
||||||
|
static openBlock(hash) {
|
||||||
|
return parseBlock(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts an associative array to a Block
|
||||||
|
static parseBlock(val) {
|
||||||
|
var block = new Block();
|
||||||
|
|
||||||
|
block.type = val['type'];
|
||||||
|
block.content = val['content'];
|
||||||
|
block.header = val['header'];
|
||||||
|
block.metadata = val['metadata'];
|
||||||
|
block.date = new Date(val['date'] * 1000);
|
||||||
|
block.hash = val['hash'];
|
||||||
|
block.signature = val['signature'];
|
||||||
|
block.signed = val['signed'];
|
||||||
|
block.valid = val['valid'];
|
||||||
|
block.parent = val['parent'];
|
||||||
|
|
||||||
|
if(block.getParent() !== null) {
|
||||||
|
// if the block data is already in the associative array
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (blocks.hasOwnProperty(block.getParent()))
|
||||||
|
block.setParent(Block.parseAssociativeArray({blocks[block.getParent()]})[0]);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts an array of associative arrays to an array of Blocks
|
||||||
|
static parseBlockArray(blocks) {
|
||||||
|
var outputBlocks = [];
|
||||||
|
|
||||||
|
for(var key in blocks) {
|
||||||
|
if(blocks.hasOwnProperty(key)) {
|
||||||
|
var val = blocks[key];
|
||||||
|
|
||||||
|
var block = Block.parseBlock(val);
|
||||||
|
|
||||||
|
outputBlocks.push(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getBlocks(args, callback) { // callback is optional
|
||||||
|
args = args || {}
|
||||||
|
|
||||||
|
var url = '/client/?action=searchBlocks&data=' + Sanitize.url(JSON.stringify(args)) + '&token=' + Sanitize.url(getWebPassword()) + '&timingToken=' + Sanitize.url(getTimingToken());
|
||||||
|
|
||||||
|
console.log(url);
|
||||||
|
|
||||||
|
var http = new XMLHttpRequest();
|
||||||
|
|
||||||
|
if(callback !== undefined) {
|
||||||
|
// async
|
||||||
|
|
||||||
|
http.addEventListener('load', function() {
|
||||||
|
callback(Block.parseBlockArray(JSON.parse(http.responseText)['blocks']));
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
http.open('GET', url, true);
|
||||||
|
http.timeout = 5000;
|
||||||
|
http.send(null);
|
||||||
|
} else {
|
||||||
|
// sync
|
||||||
|
|
||||||
|
http.open('GET', url, false);
|
||||||
|
http.send(null);
|
||||||
|
|
||||||
|
return Block.parseBlockArray(JSON.parse(http.responseText)['blocks']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* temporary code */
|
||||||
|
|
||||||
|
if(getWebPassword() === null) {
|
||||||
|
var password = "";
|
||||||
|
while(password.length != 64) {
|
||||||
|
password = prompt("Please enter the web password (run `./RUN-LINUX.sh --get-password`)");
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimingToken(prompt("Please enter the timing token (optional)"));
|
||||||
|
|
||||||
|
setWebPassword(password);
|
||||||
|
window.location.reload(true);
|
||||||
|
}
|
||||||
|
|
|
@ -1,96 +1,28 @@
|
||||||
/* write a random post to the page, for testing */
|
|
||||||
|
|
||||||
var verbs =
|
/* just for testing rn */
|
||||||
[
|
Block.getBlocks({'type' : 'onionr-post', 'signed' : true, 'reverse' : true}, function(data) {
|
||||||
["go to", "goes to", "going to", "went to", "gone to"],
|
for(var i = 0; i < data.length; i++) {
|
||||||
["look at", "looks at", "looking at", "looked at", "looked at"],
|
try {
|
||||||
["choose", "chooses", "choosing", "chose", "chosen"],
|
var block = data[i];
|
||||||
["torrent", "downloads", "downloading", "torrented", "downloaded"],
|
|
||||||
["detonate", "detonates", "detonating", "detonated", "detonated"],
|
|
||||||
["run", "runs", "running", "ran", "running"],
|
|
||||||
["program", "programs", "programming", "coded", "programmed"],
|
|
||||||
["start", "starts", "starting", "started", "started"]
|
|
||||||
];
|
|
||||||
var tenses =
|
|
||||||
[
|
|
||||||
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
|
||||||
{name:"Present", singular:1, plural:0, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement"},
|
|
||||||
{name:"Past", singular:3, plural:3, format:"%subject just %verb %complement lol"},
|
|
||||||
{name:"Present Continues", singular:2, plural:2, format:"%subject %be %verb %complement"}
|
|
||||||
];
|
|
||||||
var subjects =
|
|
||||||
[
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"I", be:"am", singular:0},
|
|
||||||
{name:"My cat", be:"is", singular:0},
|
|
||||||
{name:"My cat", be:"is", singular:0},
|
|
||||||
{name:"My dog", be:"is", singular:0},
|
|
||||||
{name:"My dog", be:"is", singular:0},
|
|
||||||
{name:"My mom", be:"is", singular:0},
|
|
||||||
{name:"My dad", be:"is", singular:0},
|
|
||||||
{name:"You", be:"are", singular:0},
|
|
||||||
{name:"He", be:"is", singular:1}
|
|
||||||
];
|
|
||||||
var complementsForVerbs =
|
|
||||||
[
|
|
||||||
["the cinema", "Egypt", "the house", "the concert"],
|
|
||||||
["for a map", "them", "the stars", "the lake"],
|
|
||||||
["a book for reading", "a dvd for tonight"],
|
|
||||||
["the virus", "the malware", "that 0day", "Onionr"],
|
|
||||||
["a bomb", "a nuke", "some C4", "some ammonium nitrate"],
|
|
||||||
["the race", "towards someone", "to the stars", "on top of your roof"],
|
|
||||||
["Onionr", "the malware", "some software", "Onionr"],
|
|
||||||
["Onionr", "Onionr", "the race", "the timer"],
|
|
||||||
]
|
|
||||||
|
|
||||||
Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)];};
|
var post = new Post();
|
||||||
|
var user = new User();
|
||||||
|
|
||||||
function generate(){
|
var blockContent = JSON.parse(block.getContent());
|
||||||
var index = Math.floor(verbs.length * Math.random());
|
|
||||||
var tense = tenses.random();
|
|
||||||
var subject = subjects.random();
|
|
||||||
var verb = verbs[index];
|
|
||||||
var complement = complementsForVerbs[index];
|
|
||||||
var str = tense.format;
|
|
||||||
str = str.replace("%subject", subject.name).replace("%be", subject.be);
|
|
||||||
str = str.replace("%verb", verb[subject.singular ? tense.singular : tense.plural]);
|
|
||||||
str = str.replace("%complement", complement.random());
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
var curDate = new Date()
|
user.setName('unknown');
|
||||||
function addRandomPost() {
|
user.setID(new String(block.getHeader('signer', 'unknown')));
|
||||||
var post = new Post();
|
post.setContent(blockContent['content']);
|
||||||
var user = new User();
|
post.setPostDate(block.getDate());
|
||||||
var items = ['arinerron', 'beardog108', 'samyk', 'snowden', 'aaronswartz'];
|
post.setUser(user);
|
||||||
user.setName(items[Math.floor(Math.random()*items.length)]);
|
|
||||||
user.setID('i-eat-waffles-often-its-actually-crazy-like-i-dont-know-wow');
|
|
||||||
post.setContent(generate());
|
|
||||||
post.setUser(user);
|
|
||||||
|
|
||||||
curDate = new Date(curDate - (Math.random() * 1000000));
|
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
||||||
post.setPostDate(curDate);
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
for(var i = 0; i < Math.round(50 * Math.random()); i++)
|
|
||||||
addRandomPost();
|
|
||||||
|
|
||||||
function viewProfile(id, name) {
|
function viewProfile(id, name) {
|
||||||
document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
|
document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(decodeURIComponent(name));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue