#!/usr/bin/tclsh

source ../config.tcl

global stderrCatch 
if {$outputFile != ""} {
	set stderrCatch ""
}

global keys
array set keys {
	I {}
	S {}
	N {}
	V {}
	X {}
	K {}
}
global systems
array set systems {
	I Irdeto
	S Seca/Mediaguard
	N Nagravision
	V Viaccess
	K SkyCrypt
	X Conax
}

proc stripHTML {text} {
	set t $text
	regsub -all {<>} $t xxx t
	regsub -all {<[^>]*>} $t "" t
	regsub -all {xxx} $t {<>} t
	regsub -all {\&} $t {\&} t
	regsub -all {<} $t {<} t
	regsub -all {>} $t {>} t
	regsub -all {"} $t {"} t
	return $t;
}

proc addKey {type chanId keyName keyValue chanName update source} {
	global config stderrCatch
	if {$type == ""} {
		return;
	}
	if {$keyValue == "0000000000000000"} {
		return;
	}
	if {$update == ""} {
		set update [clock format [clock seconds] -format {%d.%m.%Y-%H:%M:%S}]
	}
	global keys
	if {[string first "?" $keyValue] == -1} {
		if {[string index $keyValue end] != ";" && $type != "X"} {
			append keyValue ";"
		}
		# Check for duplicates ?
		set duplicates 0
		set exactDuplicates 0
		foreach keyline $keys($type) {
			
			if {$keyline != ""} {
				set t [lindex $keyline 0]
				set cid [lindex $keyline 1]
				set kname [lindex $keyline 2]
				set kvalue [lindex $keyline 3]
				set chan [lindex $keyline 4]
				if {($t == $type) && ("$chanId" == "$cid") && ("$keyName" == "$kname") && ($chan == $chanName) } {
					if {$kvalue == $keyValue} {
						incr exactDuplicates
					}
					incr duplicates
				}
			}
		}
		if {$duplicates > 0} {
			if {$config(acceptDuplicates) == 1} {
				if {[info exists stderrCatch]} {
					lappend stderrCatch "; Duplicate key added (check validity): [format "%s %-6s %-2s %s %-32s; Update: %-19s; Source: %-20s" $type $chanId $keyName $keyValue $chanName $update $source]"
				} else {
					puts stderr "; Duplicate key added (check validity): [format "%s %-6s %-2s %s %-32s; Update: %-19s; Source: %-20s" $type $chanId $keyName $keyValue $chanName $update $source]"
				}
				lappend keys($type) "{$type} {$chanId} {$keyName} {$keyValue} {$chanName} {$update} {$source}"
			} else {
				# No duplicates allowed.
				if {[info exists stderrCatch]} {
					lappend stderrCatch "; Duplicate key NOT ADDED : [format "%s %-6s %-2s %s %-32s; Update: %-19s; Source: %-20s" $type $chanId $keyName $keyValue $chanName $update $source]"
				} else {
					puts stderr "; Duplicate key NOT ADDED : [format "%s %-6s %-2s %s %-32s; Update: %-19s; Source: %-20s" $type $chanId $keyName $keyValue $chanName $update $source]"
				}
			}
		} else {
			lappend keys($type) "{$type} {$chanId} {$keyName} {$keyValue} {$chanName} {$update} {$source}"
		}
		
	}
}
                                                                            

proc parse {fname} {
	global keys
	set fid [open $fname  r]
	while {![eof $fid]} {
		set line [gets $fid]
	} 
	close $fid
}

proc parseSatKeyNagra {fname} {
	global keys
	set fid [open $fname  r]
	set data [read $fid]
	close $fid
}

proc parseSatKeyIrdeto {fname} {
	global keys
	set fid [open $fname  r]
	set data [split [read $fid] \n]
	close $fid
	set id [lsearch -glob $data "   id*"]
	
	while {$id != -1} {
		set name [lindex $data [expr $id -2]]
		if {[string match "   ??.??.????" $name]} {
			set name [lindex $data [expr $id -3]]
			if {[string match "   ??.??.????" $name]} {
				set name [lindex $data [expr $id -4]]
			}
		}
		set idline [lindex $data $id] 
		set data [lrange $data [expr $id +1] end]
		set id [lsearch -glob $data "   id*"]
		if {$id != -1} {
			set k "$idline [join [lrange $data 0 [expr $id -1]]]"
			set provIndex [lsearch -exact $k "prov"]
			set prov 00
			if {$provIndex != -1} {
				set prov [lindex $k [expr $provIndex +1]]
			}
			regsub -all ":" $k " " k
			set ki [lsearch -exact $k "key"]
			while {$ki != -1} {
				set keyName [lindex $k [expr $ki +1]]
				set keyValue [lrange $k [expr $ki +2 ] [expr $ki+9]]
				regsub -all " " $keyValue "" keyValue
				#puts "$name key$keyName : $keyValue"
				addKey I $prov $keyName $keyValue $name "" "www.sat-key.com"
				
				set k [lrange $k [expr $ki +1] end]
				set ki [lsearch -exact $k "key"]
			}
			#puts "keys=$k"
		}
		
	}
}

# Parses the softcam.key file from softcam.tforums.com
# Comment lines begin with ;
proc parseSoftcamTforumsCom {fname} {
	set fid [open $fname  r]
	while {![eof $fid]} {
		set line [gets $fid]
		set firstChar [string index $line 0]
		if {($firstChar != ";") && ($firstChar != "\#")} {
			set type $firstChar
			while {[regsub -all "  " $line " " line]} {;}
			set elems [split $line]
			set chanId [lindex $elems 1]
			set keyName [lindex $elems 2]
			set keyValue [lindex $elems 3]
			set chanName [join [lrange $elems 4 [expr [lsearch -exact $elems "Update:"] -1]] " "]
			set update [string trim [string range $line [expr [string first Update $line] +8] end]]
			
			addKey $type $chanId $keyName $keyValue $chanName $update "softcam.tforums.com"
		}
	}
	close $fid
}


proc parseSoftcamKey {fname} {
	set fid [open $fname  r]
	set data [split [read $fid] \n]
	close $fid
	foreach line $data {
		
		set line [string trim $line]
		set firstChar [string index $line 0]
		if {($firstChar != ";") && ($firstChar != "\#")} {
			
			set type $firstChar
			while {[regsub -all "  " $line " " line]} {;}
			regsub -all ";" $line "" line
			set elems [split $line]
			set chanId [lindex $elems 1]
			set keyName [lindex $elems 2]
			set keyValue [lindex $elems 3]
			set chanName ""
			if {[string last ";" $keyValue] != -1} {
				set keyValue [string range $keyValue 0 [expr [string length $keyValue]-1]]
			}
			
			if {[lsearch -exact $elems "Update:"] != -1} {
				set chanName [join [lrange $elems 4 [expr [lsearch -exact $elems "Update:"] -1]] " "]
			} elseif {[lsearch -exact $elems "key"] != -1} {
				set chanName [join [lrange $elems 4 [expr [lsearch -exact $elems "key"] -1]] " "]
			} else {
				set chanName [join [lrange $elems 4 end]]
			}
			
			set updateStart [string first update [string tolower $line]]
			set update ""
			if {$updateStart != -1} {
				set update [string trim [string range [string tolower $line] [expr $updateStart +8] end]]
			}
#			puts "chanID=$chanId.chanName=$chanName.keyName=$keyName.keyValue=$keyValue.update=$update"
			addKey $type $chanId $keyName $keyValue $chanName $update "$fname file"
		}
	}
}

# Parses the file from pablosat
proc parsePablosat {fname} {
	global keys
	set fid [open $fname  r]
	set data [read $fid] 
	close $fid
	regsub -all "\r" $data "" data
	regsub -all "\n\n" $data "\~" data
	set d [split $data ~]
	foreach chan $d {
		set lines [split $chan \n]
		set chanName [string trim [lindex $lines 0]]
		if {[string index $chanName 0] == "*"} {break;}
		#regsub -all "\*" $chanName "A" chanName
		set i [lsearch -glob $lines "IDENT*"]
		set id "[lindex [lindex $lines $i] 1][lindex [lindex $lines $i] 2]"
		
		set type "SNVI"
		# Decide which system it is.
		if {[string length $id] == 6} {
			# V*s
			set type V
		} elseif {[string length $id] == 4} {
			# Hmm, S*a or N*avision
			set type SN
		} elseif {[string length $id] == 2} {
			# I*o
			set type I
		} 
		
		set tmpKeys [list]
		foreach line $lines {
			if {[string match "INDEX*" $line]} {
				set keyName [lindex $line 1]
				set keyValue [join [lrange $line 3 10] ""]
				set keyValue [string range $keyValue 0 15]
				lappend tmpKeys [list $keyName $keyValue]
			}
		}
		#puts "$chanName $id"
		foreach t [split $type {}] {
			foreach k $tmpKeys {
				#puts "\t$t [lindex $k 0] [lindex $k 1]"
				addKey $t $id [lindex $k 0] [lindex $k 1] $chanName [clock format [clock seconds] -format {%d.%m.%Y-%H:%M:%S}] "pablosat"
			}
		}
	}
	
}


###########################################################################
# 							RDI Sat
#
###########################################################################
proc parseRdiSatSeca {fname} {
	global keys
	set fid [open $fname  r]
	set data [split [read $fid] \n]
	close $fid
	set ndx [lsearch -glob $data "*HEX key*"]
	set time [clock format [file mtime $fname] -format {%d.%m.%Y-%H:%M:%S}]
	while {$ndx != -1} {
		set chanName [stripHTML [lindex $data [expr $ndx - 8]]]
		set chanID [string range $chanName [expr [string last "id " $chanName]+3] end]
		regsub -all " " $chanID "" chanID
		set chanName [string range $chanName 0 [expr [string last "id " $chanName]-1]]
		set chanName [string trim $chanName]
		
		set key0C [stripHTML [lindex $data [expr $ndx + 4]]]
		set key0D [stripHTML [lindex $data [expr $ndx + 8]]]
		set key0E [stripHTML [lindex $data [expr $ndx + 12]]]
		regsub -all " " $key0C "" key0C
		regsub -all " " $key0D "" key0D
		regsub -all " " $key0E "" key0E
		set key0C [string trim $key0C]
		set key0D [string trim $key0D]
		set key0E [string trim $key0E]
		
		if {$key0C != "unknown"} {
			addKey S $chanID 0C $key0C $chanName $time www.rdi-sat.com
		}
		if {$key0D != "unknown"} {
			addKey S $chanID 0D $key0D $chanName $time www.rdi-sat.com
		}
		if {$key0E != "unknown"} {
			addKey S $chanID 0E $key0E $chanName $time www.rdi-sat.com
		}
		
		set data [lrange $data [expr $ndx +1] end]
		set ndx [lsearch -glob $data "*HEX key*"]
	}
}

proc parseRdiSatViaccess {fname} {
	global keys
	set fid [open $fname  r]
	set data [split [read $fid] \n]
	set start [lsearch -glob $data "*Viaccess 1 keys*"]
	set end [lsearch -glob $data "*Viaccess 2 keys*"]
	set data [lrange $data $start $end]
	set time [clock format [file mtime $fname] -format {%d.%m.%Y-%H:%M:%S}]
	foreach l $data {
		if {[string match "*<b>id *" $l]} {
			set idline [lsearch -exact $data $l]
			set chanName [string trim [stripHTML [lindex $data [expr $idline -1]]]]
			if {$chanName == ""} {
				set chanName [stripHTML [string trim [lindex $data [expr $idline -1]][lindex $data $idline]]]
			}
			set id [string trim [string range $chanName [expr [string last "id " $chanName] +3] end]]
			regsub -all " " $id "" id
			set chanName [string range $chanName 0 [expr [string last "id " $chanName] -1]]
			
			set i 12
			set keyLine [string trim [stripHTML [lindex $data [expr $idline +$i]]]]
			regsub -all " " $keyLine "" keyLine
			while {$keyLine != "" && [string length $keyLine] == 16} {
				set keyName [string trim [stripHTML [lindex $data [expr $idline +$i-1]]]]
				regsub -all " " $keyName "" keyName
				if {$keyName != "remote"} {
					set keyValue $keyLine
					regsub -all " " $keyValue "" keyValue
					#puts "$chanName ($id) key$keyName : $keyValue"
					addKey V $id $keyName $keyValue $chanName $time "www.rdi-sat.com"
				}
				incr i 8
				set keyLine [string trim [stripHTML [lindex $data [expr $idline +$i]]]]
				regsub -all " " $keyLine "" keyLine
			}
		}
	}
	close $fid
}

proc parseRdiSatNagra {fname} {
	array set ids {
		"Star Digital" 7801
		"TV Cabo" 4801
		"Via Digital" 4001
		"Polsat" 7001
	}
	global keys
	set fid [open $fname  r]
	set data [split [read $fid] \n]
	close $fid
	set start [lsearch -glob $data "*Nagravision keys*"]
	set data [lrange $data $start end]
	set time [clock format [file mtime $fname] -format {%d.%m.%Y-%H:%M:%S}]
	foreach id [array names ids] {
		set i [lsearch -glob $data "*$id*"]
		if {$i != -1} {
			set key0 [string trim [stripHTML [lindex $data [expr $i +8]]]]
			set key1 [string trim [stripHTML [lindex $data [expr $i +12]]]]
			regsub -all " " $key0 "" key0
			regsub -all " " $key1 "" key1
			addKey N $ids($id) 00 $key0 $id $time www.rdi-sat.com
			addKey N $ids($id) 01 $key1 $id $time www.rdi-sat.com
		}
	}
	
	
}


#########################################################################
#
#							Main program
#########################################################################
catch {
global config
set config(acceptDuplicates) 0

# RDI Sat
parseRdiSatSeca rdi-sat.com.seca
parseRdiSatNagra rdi-sat.com.nagra
parseRdiSatViaccess rdi-sat.com.viaccess

# Currently down.
#parseSoftcamTforumsCom softcam.tforums.com.key

# Pablosat. Currently down.
#parsePablosat Ird_to.Key
#parsePablosat Nagra.Key
#parsePablosat seka.txt
#parsePablosat Vxs.Key

# Sat-Key
#parseSatKeyNagra sat-key.com.nagrakeys
#parseSatKeyIrdeto sat-key.com.irdetoopkeys

# Cardmanie
parseSoftcamKey SoftCam-cardmanie.Key

# Xamuh
catch {
parseSoftcamKey SoftCam-xamuh.Key
}

}

set fid stdout

if {$outputFile != ""} {
	set fid [open $outputFile w]
}

puts $fid ";SoftCam.key - KeyFile (generated by satcat script)"
puts $fid ";File generated at: [clock format [clock seconds] -format {%d.%m.%Y-%H:%M:%S}]"
foreach sys [array names systems] {
	puts $fid ";============================================================================================"
	puts $fid ";===                                $systems($sys)                                       ==="
	puts $fid ";============================================================================================"
	
	foreach line $keys($sys) {
		set type [lindex $line 0]
		set chanId [lindex $line 1]
		set keyName [lindex $line 2]
		set keyValue [lindex $line 3]
		set chanName [lindex $line 4]
		set update [lindex $line 5]
		set source [lindex $line 6]
		puts $fid [format "%s %-6s %-2s %s %-32s; Update: %-19s; Source: %s" $type $chanId $keyName $keyValue $chanName $update $source]
	}
	puts $fid ""
}

if {$outputFile != ""} {
	foreach line $stderrCatch {
		puts $fid $line
	}
	close $fid
}
