tii

Tcl-based suite for working with ii/idec protocol
git clone git://git.luxferre.top/tii.git
Log | Files | Refs | README

commit d8b658a92b6e6a958a8aabe38147749065826033
parent 88e0ee7c60c800d1f539669280dc2136a477d182
Author: Luxferre <lux@ferre>
Date:   Sat, 26 Oct 2024 20:22:10 +0300

added content_id field to control message integrity (TBD how)

Diffstat:
Mii-doc.txt | 2+-
Mtiifetch.tcl | 23++++++++++++++++++-----
2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/ii-doc.txt b/ii-doc.txt @@ -133,7 +133,7 @@ This algorithm must be implemented by every station to generate message IDs: 1. Calculate SHA256 of the message in the Node-to-Point format as binary data. 2. Calculate Base64 of the resulting binary hash sum. 3. Truncate to the first 20 characters. -4. Replace all occurrences of + or - with A, and / or _ with Z. +4. Replace all occurrences of + or - with A, and / or _ with z. 5. The result of these operations is your ii message ID. Implementation notes diff --git a/tiifetch.tcl b/tiifetch.tcl @@ -15,6 +15,7 @@ package require http package require uri package require sqlite3 +package require sha256 # autodetect TclTLS support and enable HTTPS request support if detected set tls_support 0 @@ -190,6 +191,14 @@ proc listcomp {a b} { return $diff } +# generate ID from the Node-to-Point msg contents +# (exactly how it was transferred inside base64) +proc n2p_id {binmsg} { + set hash [::sha2::sha256 -bin -- $binmsg] + set trimbased [string range [binary encode base64 $hash] 0 19] + return [string map {+ A - A / z _ z} $trimbased] +} + # main logic proc proc fetchiidb {url echos dbfile dolog maxids} { if {$maxids < 12} {set maxids 12} @@ -200,8 +209,9 @@ proc fetchiidb {url echos dbfile dolog maxids} { # prepare starting script sqlite3 msgdb $dbfile msgdb eval { - CREATE TABLE IF NOT EXISTS `msg` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `msgid` VARCHAR(20), `timestamp` INT, `echoname` VARCHAR(120), - `repto` TEXT, `msgfrom` TEXT, `msgfromaddr` TEXT, `msgto` TEXT, `subj` TEXT, `body` TEXT); + CREATE TABLE IF NOT EXISTS `msg` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `msgid` VARCHAR(20) UNIQUE, + `timestamp` INT, `echoname` VARCHAR(120), `repto` TEXT, `msgfrom` TEXT, `msgfromaddr` TEXT, + `msgto` TEXT, `subj` TEXT, `body` TEXT, `content_id` VARCHAR(20)); } # attempt to fetch the echolist if echos are empty @@ -308,7 +318,10 @@ proc fetchiidb {url echos dbfile dolog maxids} { set parts [split $bline ":"] if {[llength $parts] > 1} { # valid message set mid [lindex $parts 0] - set mdata [encoding convertfrom utf-8 [binary decode base64 [lindex $parts 1]]] + set bdata [binary decode base64 [lindex $parts 1]] + # calculate ii Node-to-Point ID to verify the message integrity + set content_id [n2p_id $bdata] + set mdata [encoding convertfrom utf-8 $bdata] set msglines [split $mdata "\n"] set replyto "" set tags [split [lindex $msglines 0] "/"] @@ -322,8 +335,8 @@ proc fetchiidb {url echos dbfile dolog maxids} { set msgto [string trim [lindex $msglines 5]] set subj [string trim [lindex $msglines 6]] set msgbody [string trimright [lrange $msglines 8 end]] - msgdb eval {INSERT INTO `msg` (`msgid`, `timestamp`, `echoname`, `repto`, `msgfrom`, `msgfromaddr`, `msgto`, `subj`, `body`) - VALUES ($mid, $timestamp, $echoarea, $replyto, $msgfrom, $msgfromaddr, $msgto, $subj, $msgbody);} + msgdb eval {INSERT OR IGNORE INTO `msg` (`msgid`, `timestamp`, `echoname`, `repto`, `msgfrom`, `msgfromaddr`, `msgto`, `subj`, `body`, `content_id`) + VALUES ($mid, $timestamp, $echoarea, $replyto, $msgfrom, $msgfromaddr, $msgto, $subj, $msgbody, $content_id);} } } }