2018-08-04 02:52:45 +00:00
/* handy localstorage functions for quick usage */
function set ( key , val ) {
return localStorage . setItem ( key , val ) ;
}
function get ( key , df ) { // df is default
value = localStorage . getItem ( key ) ;
if ( value == null )
value = df ;
return value ;
}
function remove ( key ) {
return localStorage . removeItem ( key ) ;
}
2018-09-02 22:44:23 +00:00
function getParameter ( name ) {
var match = RegExp ( '[?&]' + name + '=([^&]*)' ) . exec ( window . location . search ) ;
return match && decodeURIComponent ( match [ 1 ] . replace ( /\+/g , ' ' ) ) ;
}
/* usermap localStorage stuff */
2018-08-04 02:52:45 +00:00
var usermap = JSON . parse ( get ( 'usermap' , '{}' ) ) ;
2018-09-08 06:45:33 +00:00
var postmap = JSON . parse ( get ( 'postmap' , '{}' ) )
2018-08-04 02:52:45 +00:00
function getUserMap ( ) {
return usermap ;
}
2018-09-08 06:45:33 +00:00
function getPostMap ( hash ) {
if ( hash !== undefined ) {
if ( hash in postmap )
return postmap [ hash ] ;
return null ;
}
return postmap ;
}
2018-08-04 02:52:45 +00:00
function deserializeUser ( id ) {
2018-09-02 22:44:23 +00:00
if ( ! ( id in getUserMap ( ) ) )
return null ;
2018-08-04 02:52:45 +00:00
var serialized = getUserMap ( ) [ id ]
var user = new User ( ) ;
2018-09-02 22:44:23 +00:00
2018-08-04 02:52:45 +00:00
user . setName ( serialized [ 'name' ] ) ;
user . setID ( serialized [ 'id' ] ) ;
user . setIcon ( serialized [ 'icon' ] ) ;
2018-09-13 05:30:49 +00:00
user . setDescription ( serialized [ 'description' ] ) ;
2018-09-02 22:44:23 +00:00
return user ;
}
2018-09-03 05:08:12 +00:00
function getCurrentUser ( ) {
var user = get ( 'currentUser' , null ) ;
2018-09-02 22:44:23 +00:00
2018-09-03 05:08:12 +00:00
if ( user === null )
return null ;
2018-09-02 22:44:23 +00:00
2018-09-03 05:08:12 +00:00
return User . getUser ( user , function ( ) { } ) ;
}
2018-09-02 22:44:23 +00:00
2018-09-03 05:08:12 +00:00
function setCurrentUser ( user ) {
set ( 'currentUser' , user . getID ( ) ) ;
2018-08-04 02:52:45 +00:00
}
2018-07-30 00:43:28 +00:00
/* returns a relative date format, e.g. "5 minutes" */
2018-08-04 02:52:45 +00:00
function timeSince ( date , size ) {
2018-07-30 00:43:28 +00:00
// taken from https://stackoverflow.com/a/3177838/3678023
var seconds = Math . floor ( ( new Date ( ) - date ) / 1000 ) ;
var interval = Math . floor ( seconds / 31536000 ) ;
2018-08-04 02:52:45 +00:00
if ( size === null )
size = 'desktop' ;
var dates = {
'mobile' : {
'yr' : 'yrs' ,
'mo' : 'mo' ,
'd' : 'd' ,
'hr' : 'h' ,
'min' : 'm' ,
'secs' : 's' ,
'sec' : 's' ,
} ,
'desktop' : {
'yr' : ' years' ,
'mo' : ' months' ,
'd' : ' days' ,
'hr' : ' hours' ,
'min' : ' minutes' ,
'secs' : ' seconds' ,
'sec' : ' second' ,
} ,
} ;
2018-07-30 00:43:28 +00:00
if ( interval > 1 )
2018-08-04 02:52:45 +00:00
return interval + dates [ size ] [ 'yr' ] ;
2018-07-30 00:43:28 +00:00
interval = Math . floor ( seconds / 2592000 ) ;
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
if ( interval > 1 )
2018-08-04 02:52:45 +00:00
return interval + dates [ size ] [ 'mo' ] ;
2018-07-30 00:43:28 +00:00
interval = Math . floor ( seconds / 86400 ) ;
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
if ( interval > 1 )
2018-08-04 02:52:45 +00:00
return interval + dates [ size ] [ 'd' ] ;
2018-07-30 00:43:28 +00:00
interval = Math . floor ( seconds / 3600 ) ;
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
if ( interval > 1 )
2018-08-04 02:52:45 +00:00
return interval + dates [ size ] [ 'hr' ] ;
2018-07-30 00:43:28 +00:00
interval = Math . floor ( seconds / 60 ) ;
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
if ( interval > 1 )
2018-08-04 02:52:45 +00:00
return interval + dates [ size ] [ 'min' ] ;
if ( Math . floor ( seconds ) !== 1 )
return Math . floor ( seconds ) + dates [ size ] [ 'secs' ] ;
return '1' + dates [ size ] [ 'sec' ] ;
2018-07-30 00:43:28 +00:00
}
/* replace all instances of string */
2018-09-08 05:47:56 +00:00
String . prototype . replaceAll = function ( search , replacement , limit ) {
2018-07-30 00:43:28 +00:00
// taken from https://stackoverflow.com/a/17606289/3678023
var target = this ;
2018-09-08 05:47:56 +00:00
return target . split ( search , limit ) . join ( replacement ) ;
2018-07-30 00:43:28 +00:00
} ;
2018-08-05 04:09:33 +00:00
/* useful functions to sanitize data */
class Sanitize {
/* 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 ) ;
}
2018-09-03 05:08:12 +00:00
/* usernames */
static username ( username ) {
return String ( username ) . replace ( /[\W_]+/g , " " ) . substring ( 0 , 25 ) ;
}
2018-09-13 05:30:49 +00:00
/* profile descriptions */
static description ( description ) {
return String ( description ) . substring ( 0 , 128 ) ;
}
2018-08-05 04:09:33 +00:00
}
/* config stuff */
function getWebPassword ( ) {
return get ( "web-password" , null ) ;
2018-07-30 00:43:28 +00:00
}
2018-08-05 04:09:33 +00:00
function setWebPassword ( password ) {
return set ( "web-password" , password ) ;
}
function getTimingToken ( ) {
return get ( "timing-token" , null ) ;
}
function setTimingToken ( token ) {
return set ( "timing-token" , token ) ;
2018-07-30 00:43:28 +00:00
}
/* user class */
2018-08-04 02:52:45 +00:00
class User {
2018-07-30 00:43:28 +00:00
constructor ( ) {
this . name = 'Unknown' ;
this . id = 'unknown' ;
this . image = 'img/default.png' ;
}
setName ( name ) {
this . name = name ;
}
getName ( ) {
return this . name ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
setID ( id ) {
this . id = id ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
getID ( ) {
return this . id ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
setIcon ( image ) {
this . image = image ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
getIcon ( ) {
return this . image ;
}
2018-08-04 02:52:45 +00:00
2018-09-03 05:08:12 +00:00
setDescription ( description ) {
this . description = description ;
}
getDescription ( ) {
return this . description ;
}
2018-08-04 02:52:45 +00:00
serialize ( ) {
return {
'name' : this . getName ( ) ,
'id' : this . getID ( ) ,
2018-09-03 05:08:12 +00:00
'icon' : this . getIcon ( ) ,
'description' : this . getDescription ( )
2018-08-04 02:52:45 +00:00
} ;
}
2018-09-03 05:08:12 +00:00
/* save in usermap */
2018-08-04 02:52:45 +00:00
remember ( ) {
usermap [ this . getID ( ) ] = this . serialize ( ) ;
set ( 'usermap' , JSON . stringify ( usermap ) ) ;
}
2018-09-03 05:08:12 +00:00
/* save as a block */
save ( callback ) {
var block = new Block ( ) ;
block . setType ( 'onionr-user' ) ;
block . setContent ( JSON . stringify ( this . serialize ( ) ) ) ;
return block . save ( true , callback ) ;
}
static getUser ( id , callback ) {
2018-09-30 03:13:30 +00:00
// console.log(callback);
2018-09-03 05:08:12 +00:00
var user = deserializeUser ( id ) ;
if ( user === null ) {
Block . getBlocks ( { 'type' : 'onionr-user-info' , 'signed' : true , 'reverse' : true } , function ( data ) {
if ( data . length !== 0 ) {
try {
user = new User ( ) ;
var userInfo = JSON . parse ( data [ 0 ] . getContent ( ) ) ;
if ( userInfo [ 'id' ] === id ) {
user . setName ( userInfo [ 'name' ] ) ;
user . setIcon ( userInfo [ 'icon' ] ) ;
2018-09-13 05:30:49 +00:00
user . setDescription ( userInfo [ 'description' ] ) ;
2018-09-03 05:08:12 +00:00
user . setID ( id ) ;
user . remember ( ) ;
2018-09-30 03:13:30 +00:00
// console.log(callback);
2018-09-03 05:08:12 +00:00
callback ( user ) ;
return user ;
}
} catch ( e ) {
console . log ( e ) ;
callback ( null ) ;
return null ;
}
} else {
callback ( null ) ;
return null ;
}
} ) ;
} else {
2018-09-30 03:13:30 +00:00
// console.log(callback);
2018-09-03 05:08:12 +00:00
callback ( user ) ;
return user ;
}
}
2018-07-30 00:43:28 +00:00
}
/* post class */
class Post {
/* returns the html content of a post */
2018-09-30 03:13:30 +00:00
getHTML ( type ) {
var replyTemplate = ' <!-- POST -- > \
< div class = "col-12" > \
< div class = "onionr-post" id = "onionr-post-$post-hash" onclick = "focusPost(\'$post-hash\', \'user-id-url\', \'user-name-url\', \'\')" > \
< div class = "row" > \
< div class = "col-3" > \
< img class = "onionr-post-user-icon" src = "$user-image" > \
< / d i v > \
< div class = "col-9" > \
< div class = "row" > \
< div class = "col col-auto" > \
< a class = "onionr-post-user-name" id = "onionr-post-user-name" href = "#!" onclick = "viewProfile(\'$user-id-url\', \'$user-name-url\')" > $user - name < / a > \
< / d i v > \
\
< div class = "col col-auto text-right ml-auto pl-0" > \
< div class = "onionr-post-date text-right" data - placement = "top" data - toggle = "tooltip" title = "$date" > $date - relative - truncated < / d i v > \
< / d i v > \
< / d i v > \
\
< div class = "onionr-post-content" > \
$content \
< / d i v > \
\
< div class = "onionr-post-controls pt-2" > \
< a href = "#!" onclick = "toggleLike(\'$post-hash\')" class = "glyphicon glyphicon-heart mr-2" > $liked < / a > \
< a href = "#!" onclick = "reply(\'$post-hash\')" class = "glyphicon glyphicon-comment mr-2" > reply < / a > \
< / d i v > \
< / d i v > \
< / d i v > \
< / d i v > \
< / d i v > \
<!-- END POST -- > \
' ;
2018-07-30 00:43:28 +00:00
var postTemplate = ' <!-- POST -- > \
< div class = "col-12" > \
2018-09-27 00:40:02 +00:00
< div class = "onionr-post" id = "onionr-post-$post-hash" onclick = "focusPost(\'$post-hash\', \'user-id-url\', \'user-name-url\', \'\')" > \
2018-07-30 00:43:28 +00:00
< div class = "row" > \
< div class = "col-2" > \
< img class = "onionr-post-user-icon" src = "$user-image" > \
< / d i v > \
< div class = "col-10" > \
< div class = "row" > \
2018-08-04 02:52:45 +00:00
< div class = "col col-auto" > \
2018-09-27 00:40:02 +00:00
< a class = "onionr-post-user-name" id = "onionr-post-user-name" href = "#!" onclick = "viewProfile(\'$user-id-url\', \'$user-name-url\')" > $user - name < / a > \
< a class = "onionr-post-user-id" id = "onionr-post-user-id" href = "#!" onclick = "viewProfile(\'$user-id-url\', \'$user-name-url\')" data - placement = "top" data - toggle = "tooltip" title = "$user-id" > $user - id - truncated < / a > \
2018-07-30 00:43:28 +00:00
< / d i v > \
2018-08-04 02:52:45 +00:00
\
< div class = "col col-auto text-right ml-auto pl-0" > \
< div class = "onionr-post-date text-right" data - placement = "top" data - toggle = "tooltip" title = "$date" > $date - relative < / d i v > \
2018-07-30 00:43:28 +00:00
< / d i v > \
< / d i v > \
2018-08-04 02:52:45 +00:00
\
2018-07-30 00:43:28 +00:00
< div class = "onionr-post-content" > \
$content \
< / d i v > \
2018-08-04 02:52:45 +00:00
\
2018-07-30 00:43:28 +00:00
< div class = "onionr-post-controls pt-2" > \
2018-09-08 06:45:33 +00:00
< a href = "#!" onclick = "toggleLike(\'$post-hash\')" class = "glyphicon glyphicon-heart mr-2" > $liked < / a > \
2018-09-08 05:47:56 +00:00
< a href = "#!" onclick = "reply(\'$post-hash\')" class = "glyphicon glyphicon-comment mr-2" > reply < / a > \
2018-07-30 00:43:28 +00:00
< / d i v > \
< / d i v > \
< / d i v > \
< / d i v > \
< / d i v > \
<!-- END POST -- > \
' ;
2018-08-04 02:52:45 +00:00
2018-09-30 03:13:30 +00:00
var template = '' ;
if ( type !== undefined && type !== null && type == 'reply' )
template = replyTemplate ;
else
template = postTemplate ;
2018-08-04 02:52:45 +00:00
var device = ( jQuery ( document ) . width ( ) < 768 ? 'mobile' : 'desktop' ) ;
2018-09-30 03:13:30 +00:00
template = template . replaceAll ( '$user-name-url' , Sanitize . html ( Sanitize . url ( this . getUser ( ) . getName ( ) ) ) ) ;
template = template . replaceAll ( '$user-name' , Sanitize . html ( this . getUser ( ) . getName ( ) ) ) ;
template = template . replaceAll ( '$user-id-url' , Sanitize . html ( Sanitize . url ( this . getUser ( ) . getID ( ) ) ) ) ;
2018-08-05 04:09:33 +00:00
2018-09-30 03:13:30 +00:00
template = template . replaceAll ( '$user-id-truncated' , Sanitize . html ( this . getUser ( ) . getID ( ) . substring ( 0 , 12 ) + '...' ) ) ;
// template = template.replaceAll('$user-id-truncated', Sanitize.html(this.getUser().getID().split('-').slice(0, 4).join('-')));
2018-08-05 04:09:33 +00:00
2018-09-30 03:13:30 +00:00
template = template . replaceAll ( '$user-id' , Sanitize . html ( this . getUser ( ) . getID ( ) ) ) ;
template = template . replaceAll ( '$user-image' , "data:image/jpeg;base64," + Sanitize . html ( this . getUser ( ) . getIcon ( ) ) ) ;
template = template . replaceAll ( '$content' , Sanitize . html ( this . getContent ( ) ) . replaceAll ( '\n' , '<br />' , 16 ) ) ; // Maximum of 16 lines
template = template . replaceAll ( '$post-hash' , this . getHash ( ) ) ;
template = template . replaceAll ( '$date-relative-truncated' , timeSince ( this . getPostDate ( ) , 'mobile' ) ) ;
template = template . replaceAll ( '$date-relative' , timeSince ( this . getPostDate ( ) , device ) + ( device === 'desktop' ? ' ago' : '' ) ) ;
template = template . replaceAll ( '$date' , this . getPostDate ( ) . toLocaleString ( ) ) ;
2018-08-04 02:52:45 +00:00
2018-09-08 06:45:33 +00:00
if ( this . getHash ( ) in getPostMap ( ) && getPostMap ( ) [ this . getHash ( ) ] [ 'liked' ] ) {
2018-09-30 03:13:30 +00:00
template = template . replaceAll ( '$liked' , 'unlike' ) ;
2018-09-08 06:45:33 +00:00
} else {
2018-09-30 03:13:30 +00:00
template = template . replaceAll ( '$liked' , 'like' ) ;
2018-09-08 06:45:33 +00:00
}
2018-09-30 03:13:30 +00:00
return template ;
2018-07-30 00:43:28 +00:00
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
setUser ( user ) {
this . user = user ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
getUser ( ) {
return this . user ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
setContent ( content ) {
this . content = content ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
getContent ( ) {
return this . content ;
}
2018-08-04 02:52:45 +00:00
2018-09-30 03:13:30 +00:00
setParent ( parent ) {
this . parent = parent ;
}
getParent ( ) {
return this . parent ;
}
2018-07-30 00:43:28 +00:00
setPostDate ( date ) { // unix timestamp input
if ( date instanceof Date )
this . date = date ;
else
this . date = new Date ( date * 1000 ) ;
}
2018-08-04 02:52:45 +00:00
2018-07-30 00:43:28 +00:00
getPostDate ( ) {
return this . date ;
}
2018-09-03 05:08:12 +00:00
2018-09-08 05:47:56 +00:00
setHash ( hash ) {
this . hash = hash ;
}
getHash ( ) {
return this . hash ;
}
2018-09-03 05:08:12 +00:00
save ( callback ) {
var args = { 'type' : 'onionr-post' , 'sign' : true , 'content' : JSON . stringify ( { 'content' : this . getContent ( ) } ) } ;
2018-09-30 03:13:30 +00:00
if ( this . getParent ( ) !== undefined && this . getParent ( ) !== null )
args [ 'parent' ] = ( this . getParent ( ) instanceof Post ? this . getParent ( ) . getHash ( ) : ( this . getParent ( ) instanceof Block ? this . getParent ( ) . getHash ( ) : this . getParent ( ) ) ) ;
2018-09-03 05:08:12 +00:00
var url = '/client/?action=insertBlock&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
2018-09-08 05:47:56 +00:00
var thisObject = this ;
2018-09-03 05:08:12 +00:00
http . addEventListener ( 'load' , function ( ) {
2018-09-08 05:47:56 +00:00
thisObject . setHash ( Block . parseBlockArray ( JSON . parse ( http . responseText ) [ 'hash' ] ) ) ;
callback ( thisObject . getHash ( ) ) ;
2018-09-03 05:08:12 +00:00
} , false ) ;
http . open ( 'GET' , url , true ) ;
http . timeout = 5000 ;
http . send ( null ) ;
} else {
// sync
http . open ( 'GET' , url , false ) ;
http . send ( null ) ;
2018-09-08 05:47:56 +00:00
this . setHash ( Block . parseBlockArray ( JSON . parse ( http . responseText ) [ 'hash' ] ) ) ;
return this . getHash ( ) ;
2018-09-03 05:08:12 +00:00
}
}
2018-07-30 00:43:28 +00:00
}
2018-08-05 04:09:33 +00:00
/* 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 ( ) {
2018-09-30 03:13:30 +00:00
// console.log(this.parent);
// TODO: Create a function to fetch the block contents and parse it from the server; right now it is only possible to search for types of blocks (see Block.getBlocks), so it is impossible to return a Block object here
// if(!(this.parent instanceof Block) && this.parent !== undefined && this.parent !== null)
// this.parent = Block.openBlock(this.parent); // convert hash to Block object
2018-08-05 04:09:33 +00:00
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 ) ;
}
2018-09-03 05:08:12 +00:00
// saves the block, returns the hash
save ( sign , callback ) {
var type = this . getType ( ) ;
var content = this . getContent ( ) ;
var parent = this . getParent ( ) ;
if ( content !== undefined && content !== null && type !== '' ) {
var args = { 'content' : content } ;
if ( type !== undefined && type !== null && type !== '' )
args [ 'type' ] = type ;
if ( parent !== undefined && parent !== null && parent . getHash ( ) !== undefined && parent . getHash ( ) !== null && parent . getHash ( ) !== '' )
args [ 'parent' ] = parent . getHash ( ) ;
if ( sign !== undefined && sign !== null )
args [ 'sign' ] = String ( sign ) !== 'false'
var url = '/client/?action=insertBlock&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 ) [ 'hash' ] ) ) ;
} , 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 ) [ 'hash' ] ) ;
}
}
return false ;
}
2018-08-05 04:09:33 +00:00
/* static functions */
// recreates a block by hash
static openBlock ( hash ) {
2018-09-30 03:13:30 +00:00
return Block . parseBlock ( hash ) ;
2018-08-05 04:09:33 +00:00
}
// 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 */
2018-09-03 05:08:12 +00:00
var tt = getParameter ( "timingToken" ) ;
if ( tt !== null && tt !== undefined ) {
setTimingToken ( tt ) ;
}
2018-08-05 04:09:33 +00:00
if ( getWebPassword ( ) === null ) {
var password = "" ;
while ( password . length != 64 ) {
password = prompt ( "Please enter the web password (run `./RUN-LINUX.sh --get-password`)" ) ;
}
setWebPassword ( password ) ;
}
2018-09-02 22:44:23 +00:00
2018-09-03 05:08:12 +00:00
if ( getCurrentUser ( ) === null ) {
2018-09-13 05:30:49 +00:00
jQuery ( '#modal' ) . modal ( 'show' ) ;
2018-09-03 05:08:12 +00:00
var url = '/client/?action=info&token=' + Sanitize . url ( getWebPassword ( ) ) + '&timingToken=' + Sanitize . url ( getTimingToken ( ) ) ;
console . log ( url ) ;
var http = new XMLHttpRequest ( ) ;
// sync
2018-09-13 05:30:49 +00:00
http . addEventListener ( 'load' , function ( ) {
var id = JSON . parse ( http . responseText ) [ 'pubkey' ] ;
2018-09-03 05:08:12 +00:00
2018-09-13 05:30:49 +00:00
User . getUser ( id , function ( data ) {
if ( data === null || data === undefined ) {
var user = new User ( ) ;
2018-09-03 05:08:12 +00:00
2018-09-13 05:30:49 +00:00
user . setName ( 'New User' ) ;
user . setID ( id ) ;
user . setIcon ( ' / 9 j / 4 AAQSkZJRgABAQEAYABgAAD / 2 wBDAAcFBQYFBAcGBQYIBwcIChELCgkJChUPEAwRGBUaGRgVGBcbHichGx0lHRcYIi4iJSgpKywrGiAvMy8qMicqKyr / 2 wBDAQcICAoJChQLCxQqHBgcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKir / wAARCACAAIADASIAAhEBAxEB / 8 QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL / 8 QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4 + Tl5ufo6erx8vP09fb3 + Pn6 / 8 QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL / 8 QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3 + Pn6 / 9 oADAMBAAIRAxEAPwDrtTvrlL51jlkyGPANUZNSuvJZ2uJFYHjB6UmpTE6jcZUH5iCR0FQQLHvww3An8K8jmuz0lHQvwXV1gNLcSBmGcZqcXtwo / wBe / X1rzqw1e / stWmaTdKpcl1Le9dqmoJc2qupxnoCOauUWkOzRpnULhsATMPXmoptSuFGPPfjvms8Xew4OaY7NOSEyAT3rK9w5bFn + 0 rlmCrPIvqc9KRL + 9 UGVrr5ew39aoN5qkRhjt9Vp0Vv5bFmHJ6Z7Ucz2KsjXi1K4kUYmk6Z61Ot1Owz5z9OOayYcquGZgw59sVaikZ1OSQB0FUmQ0XftVwP + WznjoDS / bZx83msBjpmqobb1IBPv1prOpGD + lVzE2LP9ozEHEznPvTDe3JBImbaO4NZ0jlfliGM52jHWlW2nEO6eRuBnCU7jsXft068 + dIR9amtLycupaduvOTWH / aIPyqjxkHBDd / pV2BiZEYdAacZJ7Eyi0QXC7dVn3Nw0hzxxTRPCgAXAZucY + 9 RewzDUpjuYp5h7VGLZW + VAVJ6Fj0rn5pX2Nkkc / qFuV1KbdGHiLb1ZcZTPYj61JazNbNtfJib + HofqD6ioPEQ + y6lAQziTZ9 / djvwM0z7XfSRhJj8hxnzAMj8a9CDUqepErp6G0uriOdYNQOQRmKZRw49x2PrWnHd2 / lZDqufeuIulcWpjlYb433IR0B6EUnmyMu55AFiHrzz0rzpO0rI6uRNXO08yNySGVv8AgXWpTKEXaRg + 9 cLZvIzM7s + M / L61Oby5 + 0 eXG7ZXknqFHqTSE6Z10ksUMZknJVR7Vg3viCV / 3 dngAHl / Wsh759QuPKDmSJT8x3Ec1pRQReSViKMf7prtp0rq7MZWi9SvpmsTvrEKTuWDNt4OcZrs1kaBVcweYpPU1w2n2Dt4mtsqFAffgH0rugSr4Y7j168fhWdRcrKmlpYJJy2H2IHHpwB / 9 eoxO5G0ZxjpnrSGNpW5ZVGePb1p3ynKMPn6ZHGKzWpGiIVt / mwycjJPrVi2ZvMA3dcAEelOAYEHBdTwfWnwxATgldqE9B1FaqyehndvcsXSk6hNzxuNRpFuyCQO / Spr35b6Tp944xVaeby4GkH8Kkn8BUDOU8QvG2p + Qy7wqjk96rtes0KJsGMYBI6j0qCwf + 0 J2u7hgCx + X3H9K1xpp + 0 RkkFO / wDhVXk1ZGlktzAu1kdyMLleFyeuapSWbrsjYnO4Bs9 / f + laNxKsk7vkeX9q8pCO2AS1XNMRbtby5lTekOGII5J7AD8BWPLd2OhSsiitnLDeFGUkeSD + JNWEQ7Xixt3dcHPNS7ZVvnWQ7p3jDOPTvj9f0pwTeBwQwPPHSp21HqzIltDY3BZdylz8oUEnP4VBHqzyXot7uHysdJGOOfwroy7iP5iQBxkHFYl / YWzXsZZXJZhliMd + wrtp1FYx5XzanQ + F7b / iZXHmIS6fL5jd / YVu3cLxyBdzZP3eM8VBpMUYdjHn52GPwAH9K6aS0ElqCy / Mo4qV + 8 bMqsuV3MJLVduJJMfhxVxYovL / ANpeMFeKx7vXLSzmZJHbKHoqGs6TxZBI22KOV29 + AKy5lHcPZylsdMu9EG3I5zjFQ / a1imXzWyVG3k5rlf7bvLudU8zyYs8hD1 / Gty3jWSNORjjrVKd9gdNrc0bqVRfT7sg7yR71A7edGYzIoDqRyarXjeXfzebwd7Z + b + lQM7KodcMvrjFLqI4nSbC0ivpoNQmdGZiI8OVxg + orJ1TWfEfhnWnS2uWuLYPgRSLv3Iff1966LUlP26RGVnw + QpH3gecg + orS06yTVLHyNRtvtEUYIVnOGQezDqK0pvldmrlzXNG9zmtK1F7qGxIiPlM7srP1Vxncp / xr0bw7p6WukzvMhKzPuxj0rz2ztxb3I06yiZktbh5mbOQC + Bt / nXsNor23h2NLeESXZjPlRFgNx9ee3rWlOMXN2MqspKKPOb3WtN0fxRevqd2tv5qKkKYLMeOTgdPTmtC31PQ7qEraXsbSYztbgn35FUNS + FGq3zTSzzQzSXMnmyT7yrof6 / hWtpGk6f4dR4riJr27nULLM6YUAdFGf51M6UILUuNRyegxHhnUhWXHoCDzSWwAkwyrwepHSobnQ3l1BrvRIjbso + ZcYVqYL1kcCdfKlxhlYYFcTTTOlNNaHWaU5MyIETIPUADFdVJgx9O1cl4fuFuSNrAleu2uivL1Le3LyHAArtwzsmzhxGskjzPxNCiazOqdM5xXOBGWZiMDNdLqRW7ee + bA3EhQeuPWsA8MecZAwDXFLWbZ6MNIpMnhV2ZWD9 + wrr7fKRxqik9Msa4pYmEyMsyo2eATj8q6XT7i8QoG2FOxV60j3M6hraope / n3cfOcVnOpPVsj0ra1CaJLybC7iXOfasm6dWUBAMk5JxitNDlVzF1SEZEykgrwR6irtjqiW9jLFIhTzY9qHHU9qrXQzCQ + CD2z0rHMrO3llyjKeCDgNWsJWE1cTw8IvtVw8r + XN5xUknJ4PP416DHq9 / N4hguLOAyW1nH5LZHDEj9DivOprSCTWreUymJLg7bkL1YAdRjuRxXrGk6jZWemx29lHEkCjIG4j8 + DzWkKbfWxVapFJaXZuvdo8AK4BK52nqPwrnbyO3aYyttYHtkirrXkNxC7K0cbKM8S5H6isKQSSyHy1 + U9HByK2l7y1OOF4vQs7UuWCGFfL6Ehzx9BTH0C2m / ds8j + m4D5adZRT + Z8rAj124rSMqW6Evkc4Yk1HJF7ov2klsS2Gn22nW4SHC + 9 YXiW + MrpZqQQxwxq7qWpR2tqXLowYcDPWuBe9ka / M4PsFNYV5KEeWJvQg5y5mXtYmiW1WJChGduB1Fc + qqyyZDGMdDnIzVnU7mUzfOHiOPmJHWpI4zHpOIwu5upyOfwriWrO / ZGZmeGeNjHuGeAB1H41vWOpxzypKgGeCV2jqD6VzpNzGwLOjKrZGByv4VVe6aG + Zo + CjBgQB0zyPpWiFJXPStSnAv5wso3Bzxj3rOkkWUAnBZOQ2 / vUWpysdTuBk7jKw + ZfeqsjfZ1KzEH3XmtDjK9 / MkYGZD83UA9KxXuEfnd0PBPU1ZvZYip2tgnqCKwHlJuRGjBueMVSd9CraHS209tKuJEUnP0zWxDIkIAhuJl7gbyRXHrbzBgcEt2UdquwSTRnbI / 19 q2i2ZyR2UF7JwJJGYdAM5ratImMW / hRn5lHQ ++ K5Ow1BWVGdduBxkdTWtDqbvKY4 + MdDWqZhJHUx
2018-09-03 05:08:12 +00:00
' ) ;
2018-09-13 05:30:49 +00:00
user . setDescription ( 'A new OnionrUI user' ) ;
2018-09-03 05:08:12 +00:00
2018-09-13 05:30:49 +00:00
user . remember ( ) ;
user . save ( ) ;
2018-09-03 05:08:12 +00:00
2018-09-13 05:30:49 +00:00
setCurrentUser ( user ) ;
} else {
setCurrentUser ( data ) ;
}
2018-09-03 05:08:12 +00:00
window . location . reload ( ) ;
2018-09-13 05:30:49 +00:00
} ) ;
} , false ) ;
http . open ( 'GET' , url , true ) ;
http . send ( null ) ;
2018-09-02 22:44:23 +00:00
}
2018-09-03 05:08:12 +00:00
currentUser = getCurrentUser ( ) ;