GS (2017-12-20) Docucolor Decoder can decode small yellow tracking dots pattern inserted automatically to identify the color laser printer and the date when the document was produced.
# docucolor.tcl # Author: Gerard Sookahet # Date: 20 Dec 2017 # Version: 0.1 # Description: Docucolor yellow tracking dots decoder for printers # Refs: https://w2.eff.org/Privacy/printers/docucolor/ # http://www.instructables.com/id/Yellow-Dots-of-Mystery-Is-Your-Printer-Spying-on-/ bind all <Escape> {exit} option add *Button.relief flat option add *Button.foreground white option add *Button.background blue option add *Button.width 14 option add *Label.foreground yellow option add *Label.background darkblue option add *Label.width 104 proc About {} { set w .about catch {destroy $w} toplevel $w .about configure -bg black wm title $w "About Docucolor Decoder" set txt "Docucolor Decoder - (v0.1 - Dec 2017) - Gerard Sookahet\n Docucolor Decoder can decode small yellow tracking dots pattern inserted automatically to identify the color laser printer and the date when the document was produced." message $w.msg -justify left -aspect 250 -relief flat -bg black -fg lightblue -text $txt button $w.bquit -text " OK " -command {destroy .about} pack $w.msg $w.bquit } proc CreateDot {x y tag} { .f1.c create oval [list $x $y [expr {$x+20}] [expr {$y+20}]] -tag $tag -fill darkblue .f1.c bind $tag <1> "ChangeDotColor $tag" } proc ChangeDotColor {tag} { set color [.f1.c itemcget $tag -fill] if {$color eq "darkblue"} then { .f1.c itemconfigure $tag -fill yellow } elseif {$color eq "yellow"} then { .f1.c itemconfigure $tag -fill darkblue } Decode } proc Reset {col row} { set sep : foreach i $col { foreach j $row { .f1.c itemconfigure $i$sep$j -fill darkblue } } foreach j [lrange $row 1 end] {.f1.c itemconfigure 9$sep$j -fill yellow} foreach j [lrange $row 1 2] { .f1.c itemconfigure 4$sep$j -fill midnightblue .f1.c itemconfigure 5$sep$j -fill midnightblue } foreach j [lrange $row 1 3] {.f1.c itemconfigure 6$sep$j -fill midnightblue} foreach j $row { .f1.c itemconfigure 2$sep$j -fill midnightblue .f1.c itemconfigure 3$sep$j -fill midnightblue .f1.c itemconfigure 8$sep$j -fill midnightblue } .f1.c itemconfigure 1:64 -fill midnightblue set ::code "" } proc GetCol {col row} { set l {} foreach i $col { set d 0 foreach j $row { set tag [join [list $i $j] :] if {[.f1.c itemcget $tag -fill] eq "yellow"} then {incr d $j} } lappend l $d } return $l } proc CheckParity {col row} { set lrow {} set lcol {} foreach i $col { set d 0 foreach j $row { set tag [join [list $i $j] :] if {[.f1.c itemcget $tag -fill] eq "yellow"} then {incr d} } lappend lcol [expr {$i*(($d % 2) ^ 1)}] } foreach j $row { set d 0 foreach i $col { set tag [join [list $i $j] :] if {[.f1.c itemcget $tag -fill] eq "yellow"} then {incr d} } lappend lrow [expr {$j*(($d % 2) ^ 1)}] } foreach k {2 3 8 0} { set lcol [lsearch -inline -all -not -exact $lcol $k] } set lrow [lsearch -inline -all -not -exact $lrow 0] return [concat ROW $lrow COL $lcol] } proc Decode {} { set col [list 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] set row [list 0 64 32 16 8 4 2 1] set lrow [lrange $row 1 end] set serial [GetCol [lreverse [lrange $col 10 end]] $lrow] set ymd [GetCol [lreverse [lrange $col 5 7]] $lrow] set hm [GetCol [list 4 1] $lrow] set year [lindex $ymd 0] set month [lindex $ymd 1] set day [lindex $ymd 2] set hour [lindex $hm 0] set min [lindex $hm 1] set serial [join $serial ""] if {$year < 70 || $year > 99} then {incr year 2000} else {incr year 1900} set date [join [concat $year [expr {$month < 13 ? $month : "MM"}] $day] "-"] set time [join [concat [expr {$hour < 25 ? $hour : "hh"}] [expr {$min < 61 ? $min : "mm"}]] ":"] set pc [CheckParity $col $row] if {$pc eq "ROW COL"} {set pc "OK"} set ::code "Date: $date at $time -- Printer Serial Number: $serial -- Parity Check: $pc" } . configure -bg black wm title . "Docucolor Decoder" set f1 [frame .f1 -relief flat -bg black] set f3 [frame .f3 -relief flat -bg black] set f4 [frame .f4 -relief flat -bg black] pack $f1 $f3 $f4 -pady 2 pack [canvas .f1.c -bg black -width 630 -height 390] set col [list 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] set row [list 0 64 32 16 8 4 2 1] set x 50 set y 30 .f1.c create text $x $y -text parity -angle 90 -fill white foreach {s c} {minute white unused grey unused grey hour white day white month white year white unused grey} { .f1.c create text [incr x 40] $y -text $s -angle 90 -fill $c } .f1.c create text 530 $y -text serial -fill white .f1.c create line 445 [expr {$y+10}] 620 [expr {$y+10}] -fill blue set x 50 foreach i $col { .f1.c create text $x 70 -text $i -fill white incr x 40 } set y 90 foreach j [concat parity [lrange $row 1 end]] { .f1.c create text 20 $y -text $j -fill white incr y 40 } set x 40 set sep : foreach i $col { set y 80 foreach j $row { CreateDot $x $y $i$sep$j incr y 40 } incr x 40 } label $f3.l -textvariable code pack $f3.l -pady 4 button $f4.b1 -text Reset -command {Reset $::col $::row} button $f4.b2 -text About -command {About} button $f4.b3 -text Exit -command {exit} pack {*}[winfo children $f4] -side left -padx 2 -pady 2 Reset $col $row