diff --git a/onionr/onionr.py b/onionr/onionr.py
index 05f22099..8ed144ee 100755
--- a/onionr/onionr.py
+++ b/onionr/onionr.py
@@ -202,7 +202,14 @@ class Onionr:
'ui' : 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 = {
@@ -212,7 +219,7 @@ class Onionr:
'start': 'Starts the Onionr daemon',
'stop': 'Stops the Onionr daemon',
'stats': 'Displays node statistics',
- 'getpassword': 'Displays the web password',
+ 'get-password': 'Displays the web password',
'enable-plugin': 'Enables and starts a plugin',
'disable-plugin': 'Disables and stops a plugin',
'reload-plugin': 'Reloads a plugin',
diff --git a/onionr/static-data/www/ui/common/onionr-timeline-post.html b/onionr/static-data/www/ui/common/onionr-timeline-post.html
index 8e187b51..68440a01 100644
--- a/onionr/static-data/www/ui/common/onionr-timeline-post.html
+++ b/onionr/static-data/www/ui/common/onionr-timeline-post.html
@@ -22,8 +22,8 @@
diff --git a/onionr/static-data/www/ui/compile.py b/onionr/static-data/www/ui/compile.py
index c93e4aa7..2667b210 100755
--- a/onionr/static-data/www/ui/compile.py
+++ b/onionr/static-data/www/ui/compile.py
@@ -40,53 +40,60 @@ with open('lang.json', 'r') as file:
LANG = type('LANG', (), langmap)
# templating
-def jsTemplate(template):
- with open('common/%s.html' % template, 'r') as file:
- return file.read().replace('\\', '\\\\').replace('\'', '\\\'').replace('\n', "\\\n")
+class Template:
+ def jsTemplate(template):
+ with open('common/%s.html' % template, 'r') as file:
+ return Template.parseTags(file.read().replace('\\', '\\\\').replace('\'', '\\\'').replace('\n', "\\\n"))
-def htmlTemplate(template):
- with open('common/%s.html' % template, 'r') as file:
- return file.read()
+ def htmlTemplate(template):
+ with open('common/%s.html' % template, 'r') as file:
+ return Template.parseTags(file.read())
-# tag parser
-def parseTags(contents):
- # <$ logic $>
- for match in re.findall(r'(<\$(?!=)(.*?)\$>)', contents):
- try:
- out = exec(match[1].strip())
- contents = contents.replace(match[0], '' if out is None else str(out))
- except Exception as e:
- print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
- traceback.print_exc()
- print('\nIgnoring this error, continuing to compile...\n')
+ # tag parser
+ def parseTags(contents):
+ # <$ logic $>
+ for match in re.findall(r'(<\$(?!=)(.*?)\$>)', contents):
+ try:
+ out = exec(match[1].strip())
+ contents = contents.replace(match[0], '' if out is None else str(out))
+ except Exception as e:
+ print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
+ traceback.print_exc()
+ print('\nIgnoring this error, continuing to compile...\n')
- # <$= data $>
- for match in re.findall(r'(<\$=(.*?)\$>)', contents):
- try:
- out = eval(match[1].strip())
- contents = contents.replace(match[0], '' if out is None else str(out))
- except NameError as e:
- name = match[1].strip()
- print('Warning: %s does not exist, treating as an str' % name)
- contents = contents.replace(match[0], name)
- except Exception as e:
- print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
- traceback.print_exc()
- print('\nIgnoring this error, continuing to compile...\n')
+ # <$= data $>
+ for match in re.findall(r'(<\$=(.*?)\$>)', contents):
+ try:
+ out = eval(match[1].strip())
+ contents = contents.replace(match[0], '' if out is None else str(out))
+ except NameError as e:
+ name = match[1].strip()
+ print('Warning: %s does not exist, treating as an str' % name)
+ contents = contents.replace(match[0], name)
+ except Exception as e:
+ print('Error: Failed to execute python tag (%s): %s\n' % (filename, match[1]))
+ traceback.print_exc()
+ 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
with open(HEADER_FILE, 'r') as file:
HEADER_FILE = file.read()
if settings['python_tags']:
- HEADER_FILE = parseTags(HEADER_FILE)
+ HEADER_FILE = Template.parseTags(HEADER_FILE)
# get footer file
with open(FOOTER_FILE, 'r') as file:
FOOTER_FILE = file.read()
if settings['python_tags']:
- FOOTER_FILE = parseTags(FOOTER_FILE)
+ FOOTER_FILE = Template.parseTags(FOOTER_FILE)
# iterate dst, replace files
def iterate(directory):
@@ -111,7 +118,7 @@ def iterate(directory):
# do python tags
if settings['python_tags']:
- contents = parseTags(contents)
+ contents = Template.parseTags(contents)
# write file
file.write(contents)
diff --git a/onionr/static-data/www/ui/dist/index.html b/onionr/static-data/www/ui/dist/index.html
index 25cbb63b..6efaac1b 100644
--- a/onionr/static-data/www/ui/dist/index.html
+++ b/onionr/static-data/www/ui/dist/index.html
@@ -49,7 +49,7 @@
-
+
diff --git a/onionr/static-data/www/ui/dist/js/main.js b/onionr/static-data/www/ui/dist/js/main.js
index 1577beb2..75cb7f81 100644
--- a/onionr/static-data/www/ui/dist/js/main.js
+++ b/onionr/static-data/www/ui/dist/js/main.js
@@ -95,14 +95,34 @@ String.prototype.replaceAll = function(search, replacement) {
return target.split(search).join(replacement);
};
-/* sanitizes HTML in a string */
-function encodeHTML(html) {
- return String(html).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+/* useful functions to sanitize data */
+class Sanitize {
+ /* sanitizes HTML in a string */
+ static html(html) {
+ return String(html).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+ }
+
+ /* URL encodes a string */
+ static url(url) {
+ return encodeURIComponent(url);
+ }
}
-/* URL encodes a string */
-function encodeURL(url) {
- return encodeURIComponent(url);
+/* config stuff */
+function getWebPassword() {
+ 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 */
@@ -179,8 +199,8 @@ class Post {
\
\
\
-
like\
- \
+
like\
+ \
\
\
\
@@ -191,13 +211,16 @@ class Post {
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
- postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
- postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
- postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(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-image', encodeHTML(this.getUser().getIcon()));
- postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
+ postTemplate = postTemplate.replaceAll('$user-name-url', Sanitize.html(Sanitize.url(this.getUser().getName())));
+ postTemplate = postTemplate.replaceAll('$user-name', Sanitize.html(this.getUser().getName()));
+ postTemplate = postTemplate.replaceAll('$user-id-url', Sanitize.html(Sanitize.url(this.getUser().getID())));
+
+ postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().substring(0, 12) + '...'));
+ // postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
+
+ 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', this.getPostDate().toLocaleString());
@@ -231,3 +254,198 @@ class Post {
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);
+}
diff --git a/onionr/static-data/www/ui/dist/js/timeline.js b/onionr/static-data/www/ui/dist/js/timeline.js
index c03ee24e..0dbd634a 100644
--- a/onionr/static-data/www/ui/dist/js/timeline.js
+++ b/onionr/static-data/www/ui/dist/js/timeline.js
@@ -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 =
-[
- ["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"],
-]
+ var post = new Post();
+ var user = new User();
-Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)];};
+ var blockContent = JSON.parse(block.getContent());
-function generate(){
- 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;
-}
+ user.setName('unknown');
+ user.setID(new String(block.getHeader('signer', 'unknown')));
+ post.setContent(blockContent['content']);
+ post.setPostDate(block.getDate());
+ post.setUser(user);
-var curDate = new Date()
-function addRandomPost() {
- var post = new Post();
- 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();
+ document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
+ } catch(e) {
+ console.log(e);
+ }
+ }
+});
function viewProfile(id, name) {
- document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
+ document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(decodeURIComponent(name));
}
diff --git a/onionr/static-data/www/ui/lang.json b/onionr/static-data/www/ui/lang.json
index 49bde688..28606a56 100644
--- a/onionr/static-data/www/ui/lang.json
+++ b/onionr/static-data/www/ui/lang.json
@@ -1,31 +1,40 @@
{
"eng" : {
"ONIONR_TITLE" : "Onionr UI",
-
+
"TIMELINE" : "Timeline",
"NOTIFICATIONS" : "Notifications",
"MESSAGES" : "Messages",
-
- "TRENDING" : "Trending"
+
+ "TRENDING" : "Trending",
+
+ "POST_LIKE" : "like",
+ "POST_REPLY" : "reply"
},
-
+
"spa" : {
"ONIONR_TITLE" : "Onionr UI",
-
+
"TIMELINE" : "Linea de Tiempo",
"NOTIFICATIONS" : "Notificaciones",
"MESSAGES" : "Mensaje",
-
- "TRENDING" : "Trending"
+
+ "TRENDING" : "Trending",
+
+ "POST_LIKE" : "me gusta",
+ "POST_REPLY" : "comentario"
},
-
+
"zho" : {
"ONIONR_TITLE" : "洋葱 用户界面",
-
+
"TIMELINE" : "时间线",
"NOTIFICATIONS" : "通知",
"MESSAGES" : "消息",
-
- "TRENDING" : "趋势"
+
+ "TRENDING" : "趋势",
+
+ "POST_LIKE" : "喜欢",
+ "POST_REPLY" : "回复"
}
}
diff --git a/onionr/static-data/www/ui/src/js/main.js b/onionr/static-data/www/ui/src/js/main.js
index da969094..a99c187b 100644
--- a/onionr/static-data/www/ui/src/js/main.js
+++ b/onionr/static-data/www/ui/src/js/main.js
@@ -95,14 +95,34 @@ String.prototype.replaceAll = function(search, replacement) {
return target.split(search).join(replacement);
};
-/* sanitizes HTML in a string */
-function encodeHTML(html) {
- return String(html).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+/* useful functions to sanitize data */
+class Sanitize {
+ /* sanitizes HTML in a string */
+ static html(html) {
+ return String(html).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
+ }
+
+ /* URL encodes a string */
+ static url(url) {
+ return encodeURIComponent(url);
+ }
}
-/* URL encodes a string */
-function encodeURL(url) {
- return encodeURIComponent(url);
+/* config stuff */
+function getWebPassword() {
+ 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 */
@@ -159,13 +179,16 @@ class Post {
var device = (jQuery(document).width() < 768 ? 'mobile' : 'desktop');
- postTemplate = postTemplate.replaceAll('$user-name-url', encodeHTML(encodeURL(this.getUser().getName())));
- postTemplate = postTemplate.replaceAll('$user-name', encodeHTML(this.getUser().getName()));
- postTemplate = postTemplate.replaceAll('$user-id-url', encodeHTML(encodeURL(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-image', encodeHTML(this.getUser().getIcon()));
- postTemplate = postTemplate.replaceAll('$content', encodeHTML(this.getContent()));
+ postTemplate = postTemplate.replaceAll('$user-name-url', Sanitize.html(Sanitize.url(this.getUser().getName())));
+ postTemplate = postTemplate.replaceAll('$user-name', Sanitize.html(this.getUser().getName()));
+ postTemplate = postTemplate.replaceAll('$user-id-url', Sanitize.html(Sanitize.url(this.getUser().getID())));
+
+ postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().substring(0, 12) + '...'));
+ // postTemplate = postTemplate.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
+
+ 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', this.getPostDate().toLocaleString());
@@ -199,3 +222,198 @@ class Post {
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);
+}
diff --git a/onionr/static-data/www/ui/src/js/timeline.js b/onionr/static-data/www/ui/src/js/timeline.js
index 6acd819d..763fc7d0 100644
--- a/onionr/static-data/www/ui/src/js/timeline.js
+++ b/onionr/static-data/www/ui/src/js/timeline.js
@@ -1,96 +1,28 @@
-/* write a random post to the page, for testing */
-var verbs =
-[
- ["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 =
-[
- ["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"],
-]
+/* 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];
-Array.prototype.random = function(){return this[Math.floor(Math.random() * this.length)];};
+ var post = new Post();
+ var user = new User();
-function generate(){
- 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 blockContent = JSON.parse(block.getContent());
-var curDate = new Date()
-function addRandomPost() {
- var post = new Post();
- 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);
+ user.setName('unknown');
+ user.setID(new String(block.getHeader('signer', 'unknown')));
+ post.setContent(blockContent['content']);
+ post.setPostDate(block.getDate());
+ 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();
+ document.getElementById('onionr-timeline-posts').innerHTML += post.getHTML();
+ } catch(e) {
+ console.log(e);
+ }
+ }
+});
function viewProfile(id, name) {
- document.getElementById("onionr-profile-username").innerHTML = encodeHTML(decodeURIComponent(name));
+ document.getElementById("onionr-profile-username").innerHTML = Sanitize.html(decodeURIComponent(name));
}