diff --git a/webif/lib/system.class.orig b/webif/lib/system.class.orig deleted file mode 100644 index 9da71279..00000000 --- a/webif/lib/system.class.orig +++ /dev/null @@ -1,921 +0,0 @@ - -source /mod/webif/lib/setup - -package require xconv - -if {![exists -command class]} { package require oo } -if {![exists -command sqlite3.open]} { package require sqlite3 } -if {![exists -command binary]} { package require binary } - -class system {} - -proc {system model} {} {{model ""}} { - if {$model ne ""} { return $model } - if {[catch {set fp [open /etc/model r]}]} { - set model {HD[R]} - } else { - set model [string trim [read $fp]] - close $fp - } - return $model -} - -proc {system hostname} {} { - if {[catch {set hostname [string trim [exec hostname]]}]} { - set hostname "humax" - } - return $hostname -} - -proc {system ip} {} { - if {[catch {set fp [open /etc/hosts r]}]} { - set ip "127.0.0.1" - } else { - set ipl [lindex [split [$fp read] "\n"] 1] - regsub -- {[[:space:]].*} $ipl "" ip - $fp close - } - return $ip -} - -proc {system modversion} {{short 0}} {{modver ""}} { - if {$modver eq ""} { - if {[catch {set fp [open /etc/modversion r]}]} { - set modver "102" - } else { - set modver [string trim [read $fp]] - close $fp - } - } - if {$short} { return $modver } - lassign [split $modver ""] a b c - return [format "%d.%d%d" $a $b $c] -} - -proc {system modbuild} {} {{modbuild ""}} { - if {$modbuild ne ""} { return $modbuild } - if {[catch {set modbuild [string trim [file read /etc/modbuild]]}]} { - set modbuild 0 - } - return $modbuild -} - -proc {system lastbootreason} {{descr 1}} {{lbr -1}} { - if {$lbr == -1} { - set lbr 0 - if {[file readable /tmp/.lbr]} { - set lbr [file read /tmp/.lbr] - } - } - if {!$descr} { return $lbr } - switch $lbr { - 1 { return "Front panel button" } - 2 { return "Remote control handset" } - 3 { return "Scheduled event" } - 4 { return "Power cycle" } - } - return "Unknown ($lbr)" -} - -proc {system idletime} {} { - if {[file exists "/tmp/.lastir"]} { - return $([clock seconds] - [file mtime "/tmp/.lastir"]) - } - return 0 -} - -proc {system fhtcpversion} {} {{ver ""}} { - if {$ver ne ""} { return $ver } - set file "/etc/fhtcpversion" - if {![file exists $file]} { set file "/root/fhtcpversion" } - if {[catch {set fp [open $file r]}]} { - set ver "?.??.??" - } else { - set ver [string trim [read $fp]] - close $fp - } - return $ver -} - -# :c0400 System ID -# 4:c8400 read 1128 bytes -# 3:c8c00 MAC address -# 2:c9000 -# 1:cb400 DTCP key material -# 0:cb800 Serial Number -# 5:cbc00 - -proc {system systemid} {} {{id ""}} { - if {$id ne ""} { return $id } - set fd [open /dev/mtd3 r] - - $fd seek 0xc0400 - set bytes [$fd read 4] - $fd close - binary scan $bytes H* hex - set id [format "%s.%s" [string range $hex 0 3] [string range $hex 4 end]] - return $id -} - -proc {system macaddr} {} {{mac ""}} { - if {$mac ne ""} { return $mac } - set fd [open /dev/mtd3 r] - - $fd seek 0xc8c00 - set bytes [$fd read 6] - $fd close - set tmac "" - foreach b [split $bytes ""] { - binary scan $b H* hex - if {$tmac ne ""} { append tmac : } - append tmac $hex - } - return [set mac $tmac] -} - -proc {system serialno} {} {{serial ""}} { - if {$serial ne ""} { return $serial } - set fd [open /dev/mtd3 r] - - $fd seek 0xcb800 - set bytes [$fd read 14] - $fd close - set serial "[string range $bytes 0 1] [string range $bytes 2 8] [ - string range $bytes 9 end]" - return $serial -} -proc {system keybytestostring} {key_bytes} { - binary scan $key_bytes H* key_str - if {[string length $key_str] == 32} { - return $key_str - } - return {} -} - -proc {system encryptionkey} {} {{key ""}} { - if {$key ne ""} { return $key } - set fd [open /dev/mtd3 r] - $fd seek 0xc8c00 - set bytes [$fd read 6] - $fd seek 0xcb800 - append bytes [$fd read 10] - $fd close - return [system keybytestostring $bytes] -} - -proc {system customencryptionkey} {{key ""}} {{keyfile "/mod/boot/cryptokey"}} { - - set ck_fd {} - try { - if {$key eq ""} { - set ck_fd [open $keyfile r] - set ck_bytes [$ck_fd read 16] - return [system keybytestostring $ck_bytes] - } elseif {[string equal -nocase $key [system encryptionkey]]} { - file delete -force $keyfile - return $key - } else { - set ck_bytes [binary format H* $key] - set test [system keybytestostring $ck_bytes] - if {![string equal -nocase $test $key]} { - throw 1 "Invalid custom key" - } - if {[file exists $keyfile]} { - # attempt not to truncate on update until written - set access r+ - } else { - set access w - } - set ck_fd [open $keyfile $access] - $ck_fd seek 0 - $ck_fd puts -nonewline $ck_bytes - $ck_fd close - set ck_fd {} - return $key - } - } on error {msg opts} { - return {} - } finally { - if {$ck_fd ne {}} { - $ck_fd close - } - } -} - -proc {system loaderver} {} {{ver ""}} { - if {$ver ne ""} { return $ver } - set fd [open /dev/mtd3 r] - $fd seek 0x20006 - set bytes [$fd read 2] - $fd close - set ver [switch $bytes { - "\x04\x5f" { format "a7.30" } - "\xec\xe5" { format "a7.31" } - "\x59\x9d" { format "a7.33" } - "\x72\x5c" { format "a7.34" } - "\xe5\xe3" { format "L7.26" } - "\x8f\x7c" { format "L7.27" } - default { - binary scan $bytes H* hex - format "Unknown - $hex" - } - }] - return $ver -} - -proc {system kernelver} {} {{ver ""}} { - if {$ver ne ""} { return $ver } - #1 SMP Sun Mar 25 18:30:38 KST 2012 - set rver [string range [exec uname -v] 11 end] - set ver [switch $rver { - # HDR - "Sep 16 20:17:56 KST 2010" { format "HDR_1.01.05" } - "Oct 11 21:11:05 KST 2010" { format "HDR_1.01.09" } - "Jan 21 15:44:39 KST 2011" { format "HDR_1.02.07" } - "Jun 11 00:54:19 KST 2011" { format "HDR_1.02.20" } - "Mar 25 18:30:38 KST 2012" { format "HDR_1.02.27" } - "May 27 00:19:34 KST 2012" { format "HDR_1.02.28" } - "Jul 5 11:11:28 KST 2012" { format "HDR_1.02.29" } - "Jan 12 16:49:05 KST 2013" { format "HDR_1.02.32" } - "Mar 6 07:27:02 KST 2013" { format "HDR_1.03.06(a)" } - "May 8 14:32:30 KST 2013" { format "HDR_1.03.06(b)" } - "Dec 10 14:36:54 KST 2013" { format "HDR_1.03.11" } - "Feb 7 14:15:02 KST 2014" { format "HDR_1.03.12" } - "May 19 22:39:27 BST 2014" { format "HDR_CFW_3.00" } - "Feb 19 20:58:57 GMT 2015" { format "HDR_CFW_3.03" } - "Mar 11 23:34:27 GMT 2016" { format "HDR_CFW_3.10" } - "Mar 11 23:37:22 GMT 2016" { format "HDR_CFW_3.10d" } - "Jan 9 04:46:49 GMT 2017" { format "HDR_CFW_3.11" } - "Jan 9 04:50:13 GMT 2017" { format "HDR_CFW_3.11d" } - "Mar 23 19:36:14 GMT 2017" { format "HDR_CFW_3.12" } - "Mar 23 19:39:44 GMT 2017" { format "HDR_CFW_3.12d" } - "Apr 18 22:42:30 BST 2017" { format "HDR_CFW_3.13" } - "Apr 18 22:45:34 BST 2017" { format "HDR_CFW_3.13d" } - "Mar 29 13:48:27 BST 2020" { format "HDR_CFW_3.14" } - "Mar 29 13:52:16 BST 2020" { format "HDR_CFW_3.14d" } - - # HD - "Oct 11 21:14:31 KST 2010" { format "HD_1.01.12" } - "May 17 14:16:20 KST 2011" { format "HD_1.02.18" } - "Jun 11 00:54:19 KST 2011" { format "HD_1.02.20" } - "Mar 25 07:09:19 KST 2012" { format "HD_1.02.27" } - "May 27 00:19:40 KST 2012" { format "HD_1.02.28" } - "Jul 5 19:41:17 KST 2012" { format "HD_1.02.29" } - "Oct 13 12:48:09 KST 2012" { format "HD_1.02.31" } - "Dec 9 14:15:07 KST 2014" { format "HD_1.03.02" } - - default { format "Unknown - $rver" } - }] - return $ver -} - -# Newer version below is over 100 times faster -#proc {system pkgver} {{pkg webif}} { -# return [lrange [split [exec opkg list-installed $pkg] " "] 2 end] -#} - -proc {system pkgver} {{pkg webif}} { - if {[catch {set fp [open /mod/var/opkg/info/$pkg.control r]}]} { - return 0 - } - - set v 0 - foreach line [split [$fp read] "\n"] { - if {[string equal -length 9 $line "Version: "]} { - lassign $line x v - break - } - } - $fp close - return $v -} - -proc {system pkginst} {pkg} { - return [file exists "/mod/var/opkg/info/$pkg.control"] -} - -proc {system mediaroot} {} { - switch [system model] { - HDR { return "/media/My Video" } - HD { return "/media/drive1/Video" } - } - return "" -} - -proc {system dlnastatus} {} { - return [system is_listening 9000] -} - -proc {system dlnadb} {} { - switch [system model] { - HDR { return "/mnt/hd2/dms_cds.db" } - HD { return "/media/drive1/dms_cds.db" } - } - return "" -} - -proc {system _dlnaurl} {file urlbase} { - set mime "video/mp2t" - set nfile $file - if {![catch {set nfile [file normalize $file]}]} { - set file $nfile - } - if {[catch {set db [sqlite3.open [system dlnadb]]}]} { - return {} - } - set muri [$db query { - select tblresource.mimetype, contenturi - from tblresource join tblmedia using (mediaid) - where localurl = '%s'} $file] - if {[llength $muri]} { - lassign [lindex $muri 0] x maybemime x xuri - if {$maybemime ne "video/ts"} { - set mime $maybemime - } - } else { - # Try for partially linked entry - set muri [$db query { - select mediaid from tblmedia - where localurl = '%s' - } $file] - if {![llength $muri]} { return {} } - lassign [lindex $muri 0] x mediaid - set xuri "media/$mediaid.TS" - } - - $db close - - set url "http://${urlbase}:9000/web/$xuri" - - return [list $url $mime] -} - -proc {system dlnaurl} {file {urlbase "127.0.0.1"}} { - if {$urlbase eq ""} { set urlbase [system ip] } - set retries 5 - set ret {} - while {$retries > 0 && [\ - catch {set ret [system _dlnaurl $file $urlbase]}]} { - incr retries -1 - sleep 1 - } - return $ret -} - -proc {system dlnahelper} {file {urlbase "127.0.0.1"}} { - set dir /mnt/hd2/mod/.dlnahelper - require lock - - if {$file eq "-release"} { - release_lock dlnahelper - return {} - } - - if {![acquire_lock dlnahelper 2]} { return {} } - - if {![file isdirectory $dir]} { file mkdir $dir } - - set base [file rootname $file] - foreach ext {hmt ts} { - file delete "$dir/helper.$ext" - file link -symbolic "$dir/helper.$ext" "$base.$ext" - } - - set ret [system dlnaurl "$dir/helper.ts" $urlbase] - if {![llength $ret]} { - # Manually import the helper file. - if {![catch {set db [sqlite3.open [system dlnadb]]}]} { - $db query { - insert into tblmedia - (localurl,folder,mediatype,refcount) - values('%s','%s',0,1) - } "$dir/helper.ts" $dir - $db close - set ret [system dlnaurl "$dir/helper.ts" $urlbase] - } - } - if {![llength $ret]} { - release_lock dlnahelper - } - return $ret -} - -proc {system dustbin} {{short 0}} { - set dustbin "\[Deleted Items\]" - if {![catch {set fd [open "/mod/boot/dustbin.name" r]}]} { - set dustbin [lindex [split [read $fd] "\n"] 0] - $fd close - } - if {$short} { return $dustbin } - return "[system mediaroot]/$dustbin" -} - -proc {system dustbinsize} {} { - set bin [system dustbin] - set ret 0 - if {[file isdirectory $bin]} { - if {[catch { - lassign [exec /mod/bin/busybox/du -s $bin] ret - }]} { - set ret 0 - } - } - return $($ret * 1024) -} - -proc {system diskpart} {} { - switch [system model] { - HDR { return "/mnt/hd2" } - HD { return "/media/drive1" } - } - return "" -} - -proc {system diskdev} {} { - return [lindex [lsearch -regexp -inline \ - [split [file read /proc/mounts] "\n\r"] " [system diskpart] "] 0] -} - -proc {system disk} {} { - return [string range [system diskdev] 0 end-1] -} - -proc {system disktemp} {} { - if {[catch { - set smart [exec /bin/smartctl -A [system disk] | grep ^194] - regsub -all -- {[[:space:]]+} $smart " " smart - set temp [lindex [split $smart] 9] - }]} { - set temp 0 - } - return $($temp + 0) -} - -proc {system tsrdir} {} { - switch [system model] { - HDR { - set tsrdir "/mnt/hd2/Tsr" - } - HD { - set tsrdir "/media/drive1/.tsr" - } - } - return $tsrdir -} - -proc {system tsr} {} { - return [file join [system tsrdir] "0.ts"] -} - -require pretty_size - -proc {system diskspace} {{raw 0}} { - set part [system diskpart] - - lassign [exec /mod/bin/busybox/stat -f -c {%S %b %f} $part] \ - bsize blocks fblocks - - set size $($bsize * $blocks) - set free $($bsize * $fblocks) - set used $($size - $free) - set perc $($used * 100 / $size) - set fperc $(100 - $perc) - - set tsrdir [system tsrdir] - switch [system model] { - HDR { - set tsrok [file isdirectory $tsrdir] - } - HD { - set tsrok [file exists "$tsrdir/0.ts"] - } - } - - if {$tsrok} { - set tsrbuf 21474836480 - if {[catch { - lassign [exec du -ks $tsrdir] tsrused - }]} { - set tsrused 0 - set tsrbuf 0 - } else { - set tsrused $($tsrused * 1024) - } - } else { - set tsrbuf 0 - set tsrused 0 - } - - if {!$raw} { - set size [pretty_size $size] - set free [pretty_size $free] - set used [pretty_size $used] - set tsrbuf [pretty_size $tsrbuf] - set tsrused [pretty_size $tsrused] - } - - return [list $size $used $perc $free $fperc $tsrbuf $tsrused] -} - -proc {system diskfree} {} { - lassign [exec /mod/bin/busybox/stat -f -c {%S %f} [system diskpart]] \ - bsize fblocks - return $($bsize * $fblocks) -} - -proc {system busy} {} { - # Is humaxtv doing anything important? - if {[catch {set pid [exec /mod/bin/busybox/pgrep -n humaxtv]}]} { - return 0 - } - set c 0 - foreach line [split [\ - exec /mod/webif/lib/bin/lsof -X -Fn -p $pid] "\n"] { - if {[string match {*Video*.ts} $line]} { incr c } - } - if {$c > 0} { return 1 } - return 0 -} - -proc {system inuse} {file} { - if {![file exists $file]} { return 0 } - set op [exec /mod/webif/lib/bin/lsof -X -Fn $file] - switch -glob -- $op { - "" - - "*status error*" { return 0 } - } - return 1 -} - -proc {system dirinuse} {dir} { - set files {} - foreach line [split [\ - exec /mod/webif/lib/bin/lsof -X -Fn +d $dir] "\n"] { - if {[string index $line 0] ne "n"} continue - lappend files [file tail $line] - } - return $files -} - -proc {system reboot} {{fast 0}} { - if {$fast} { - exec /mod/webif/lib/bin/reboot -f - } else { - exec /mod/webif/lib/bin/reboot - } -} - -proc {system restartpending} {{mode 1}} { - if {$mode} { - close [open /tmp/.restartpending w] - } else { - file delete /tmp/.restartpending - } -} - -proc {system param} {param {type Value} {tbl MENUCONFIG}} { - if {[catch {set db [sqlite3.open /var/lib/humaxtv/setup.db]} msg]} { - return 0 - } - set val 0 - set ret [$db query " - select item$type - from TBL_$tbl - where itemName = '$param' - "] - if {[llength $ret] == 1} { - lassign [lindex $ret 0] x val - } - $db close - return $val -} - -proc {system padding} {} { - return [list \ - [system param START_PADDING_TIME] \ - [system param STOP_PADDING_TIME] \ - ] -} - -proc {system instandby} {} { - return [system param LAST_STANDBY Value USERCONFIG] -} - -proc {system mkdir_p} {dir} { - exec /mod/bin/busybox/mkdir -p $dir -} - -proc {system dirblockers} {dir {permitted {".*"}}} { - set fl {} - foreach e [readdir -nocomplain $dir] { - if {$e in {. ..}} continue - if {[file isdirectory "$dir/$e"]} { - lappend fl $e - continue - } - set flag 1 - foreach p $permitted { - if {[string match -nocase $p $e]} { - set flag 0 - break - } - } - if {$flag} { - lappend fl $e - } - } - return $fl -} - -proc {system rmdir_if_empty} {dir {permitted {".*"}}} { - set fl [system dirblockers $dir $permitted] - - if {![llength $fl]} { - file delete -force $dir - return 1 - } - return 0 -} - -proc {system listening} {{mport 0}} { - set ret {} - foreach line [split [exec /mod/bin/busybox/netstat -lntpw] "\n"] { - # Remove repeated spaces - regsub -all -- {[[:space:]]+} $line " " line -# tcp 0 0 0.0.0.0:9955 0.0.0.0:* LISTEN 169/humaxtv - lassign [split $line " "] x x x port x type app - if {$type ne "LISTEN"} { continue } - lassign [split $port ":"] x port - - if {$mport && $mport != $port} { continue } - lappend ret [list $port [split $app "/"]] - } - return $ret -} - -proc {system is_listening} {mport} { - return [llength [system listening $mport]] -} - -proc {system logtimestamp} {} { - return [clock format [clock seconds] -format "%d/%m/%Y %H:%M:%S"] -} - -proc {system _log} {log msg} { - set logfd [open $log "a+"] - puts $logfd "[system logtimestamp] - $msg" - $logfd close -} - -proc {system log} {log msg} { - system _log "/var/log/$log.log" $msg -} - -proc {system plog} {log msg} { - system _log "/mod/tmp/$log.log" $msg -} - -proc {system notify} {msg} { - system plog notify $msg -} - -proc {system display} {hdr hd} { - if {[system model] eq "HDR"} { - exec /sbin/display $hdr - } else { - exec /sbin/display "\$$hd" - } -} - -proc {system tuners} {} { - if {[system model] eq "HDR"} { - return 2 - } else { - return 1 - } -} - -proc {system uptime} {} { - set fd [open /proc/uptime r] - set uptime [lindex [split [read $fd]] 0] - $fd close - return $uptime -} - -proc {system filename} {str {extra ""}} { - # Humax TV replaces these characters. - # "%*./:<>?\| - set chars "\"%*\./:<>?\\\\|$extra" - return [regsub -all -- "\[$chars]" $str "_"] -} - -proc {system connectivity} {{site "hpkg.tv"} {port 80} {ret "0"}} { - set extra [lassign [exec /mod/bin/tcpping $site $port] result] - if {$ret ne "0"} { upvar $ret err } - switch $result { - OK { return 1 } - default { - set err [list $result $extra] - return 0 - } - } -} - -proc {system nuggeted} {} { - if {![system pkginst nugget]} { return 0 } - if {[system nugget ping] eq "PONG"} { - return 1 - } - return 0 -} - -proc {system nugget} {args} { - if {[catch {set ret [exec /mod/bin/nugget {*}$args]} msg]} { - return "" - } - return $ret -} - -proc {system strip} {str} { - if {[string range $str 1 2] eq "i7"} { - # ISO6937, convert to UTF-8 - return [xconv [string range $str 3 end]] - } - if {[string first "\025" $str] == 0} { - # UTF-8 - return [string range $str 1 end] - } - return [xconv $str] -} - -proc {system usbdisks} {{full 0}} { - set disks [lmap i [glob -nocomplain \ - -directory /sys/bus/usb/drivers/usb-storage *:*] { - file tail $i - }] - if {!$full} { - return [llength $disks] - } - if {![llength $disks]} { return {} } - - # Build list of device to device ID - set map {} - foreach block [glob -nocomplain -directory /sys/block sd?] { - set link [file readlink $block/device] - foreach disk $disks { - if {[string first "/$disk/" $link] >= 0} { - set map([file tail $block]) $disk - } - } - - } - return $map -} - -proc {system usbmounts} {{full 0}} { - if {!$full} { - set num 0 - catch { - set num [ - exec grep -cE {^/dev/sd[a-z][1-9] /media/[^/]+ } \ - /proc/mounts] - } - return $num - } - set ret {} - if {[catch { - set lines [exec grep -E {^/dev/sd[a-z][1-9] /media/[^/]+ } \ - /proc/mounts] - }]} { return $ret } - foreach line [split $lines "\n"] { - lassign $line dev mp - set rec "DEV {$dev} MP {$mp} LABEL {NO NAME} TYPE Unknown" - - set rec(VENDOR) Unknown - set rec(MODEL) Unknown - - if {[regexp {/dev/(sd[a-z])} $dev x rdev]} { - set rec(RDEV) $rdev - if {[file readable [ - set f /sys/block/$rdev/device/vendor]]} { - set rec(VENDOR) [string trim [file read $f]] - } - if {[file readable [ - set f /sys/block/$rdev/device/model]]} { - set rec(MODEL) [string trim [file read $f]] - } - } - - lassign [exec stat -f -c {%S %b %f} $mp] blocks blockc blockf - set rec(SIZE) $($blockc * $blocks) - set rec(USED) $(100 - $blockf * 100 / $blockc) - - # /dev/sda1: LABEL="SAN" UUID="DBC1-1CF8" TYPE="vfat" - catch { - foreach field [ - split [exec /mod/sbin/blkid -c /dev/null $dev] "\n"] { - while {[regexp { *([A-Z]+)="?([^"]+)"?(.*)} \ - $field x k v field]} { - set rec($k) $v - } - } - } - # Test for EXFAT - if {$rec(TYPE) eq "Unknown" && [ - file exists /mod/sbin/exfatlabel]} { - catch { - set label [exec /mod/sbin/exfatlabel $dev 2>/dev/null] - if {$label ne ""} { - set rec(TYPE) "EXFAT" - set rec(LABEL) $label - } - } - } - - lappend ret $rec - } - - return $ret -} - -proc {system has} {comp} { - switch $comp { - wifi_dongle { - if {[catch {exec /mod/bin/iwgetid}]} { return 0 } - return 1 - } - tvdb { - require settings.class - return [[settings] _nval_setting tvdb] - } - } - return 0 -} - -# Note that {system checkop} can be called from processes other than that -# which started the operation. Hence no visilibty into the ::system::ops -# dictionary. -proc {system checkop} {op} { - if {![regexp -nocase -- {^[.a-z0-9]+$} $op]} { return 0 } - if {[catch {set fp [open "/tmp/.bgop.$op" "a"]}]} { - return 0 - } - set ret 1 - if {[$fp lock]} { - $fp unlock - set ret 0 - } - $fp close - return $ret -} - -set ::system::ops {} - -proc {system startop} {args op file} { - if {![regexp -nocase -- {^[a-z0-9]+$} $op]} { return 0 } - if {"-multiple" in $args} { - set i 0 - append op "[pid]." - while {[dict exists $::system::ops "$op$i"]} { incr i } - append op $i - } elseif {[dict exists $::system::ops $op]} { - system endop $op - } - if {[catch { - set fp [open "/tmp/.bgop.$op" "a"] - if {[$fp lock]} { - $fp puts "$file\n[pid]" - $fp flush - set ::system::ops($op) $fp - } else { - $fp close - error "Could not lock op file." - } - }]} { return 0 } - return $op -} - -proc {system endop} {op} { - if {![regexp -nocase -- {^[.a-z0-9]+$} $op]} { return 0 } - if {[dict exists $::system::ops $op]} { - catch { - set fp $::system::ops($op) - $fp unlock - $fp close - } - dict unset ::system::ops $op - } - if {[file exists "/tmp/.bgop.$op"]} { - file delete "/tmp/.bgop.$op" - return 1 - } - return 0 -} - -proc {system specialdir} {dir} { - if {[string match {\[*} [string trimleft [file tail $dir]]]} { - return 1 - } - return 0 -} - diff --git a/webif/lib/ts.class.orig b/webif/lib/ts.class.orig deleted file mode 100644 index 05fd9d86..00000000 --- a/webif/lib/ts.class.orig +++ /dev/null @@ -1,899 +0,0 @@ - -if {![exists -command class]} { package require oo } -if {![exists -command pack]} { package require pack } -if {![exists -command xconv]} { package require xconv } -if {![exists -command binary]} { package require binary } - -source /mod/webif/lib/setup -require system.class tvdb.class classdump - -set tsgroup {ts nts hmt thm} - -class ts { - file "" - base "" - title "" - synopsis "" - definition "" - channel_num 0 - channel_name "" - start 0 - end 0 - flags "" - error "" - guidance "" - bookmarks 0 - schedstart 0 - scheddur 0 - genre 0 - resume 0 - status "" - series "" - - seriescached 1 - seriesnum 0 - episodenum 0 - episodetot 0 - episodename "" - tvdb_method "" - tvdb_series {} - tvdb_data {} -} - -ts method bfile {} { - return [file tail [file rootname $file]] -} - -ts method dir {} { - return [file dirname $file] -} - -ts method duration {{raw 0}} { - set d [expr $end - $start] - if {!$raw} { set d $($d / 60) } - return $d -} - -ts method size {} { - return [file size $file] -} - -ts method _parse {line} { - set vars [split $line "\t"] - - lassign [split $line "\t"] \ - title synopsis definition channel_num channel_name \ - start end flags_list guidance bookmarks schedstart scheddur \ - genre resume status seriesnum episodenum episodetot - - set synopsis [xconv $synopsis] - - set flags [split [string range $flags_list 0 end-1] ,] -} - -ts method lastmod {} { - return [file mtime "[file rootname $file].hmt"] -} - -ts method inuse {} { - return [system inuse $file] -} - -ts method bookmarks {{aslist 0}} { - set marks [split [string trim [exec /mod/bin/hmt -bookmarks $file]]] - if {$aslist} { return $marks } - return [join $marks " "] -} - -ts method setbookmarks {marks} { - exec /mod/bin/hmt +setbookmarks=[join $marks :] $file -} - -ts method storeepisode {{data {}}} { - if {[llength $data]} { - set d [join $data ","] - } else { - set d "$seriesnum,$episodenum,$episodetot" - } - exec /mod/bin/hmt +setseries=$d $file -} - -ts method clearepdata {} { - set seriesnum 0 - set episodenum 0 - set episodetot 0 -} - -ts method flag {f} { - if {$f in $flags} {return 1} else {return 0} -} - -ts method unflag {f} { - lremove flags $f -} - -ts method unlock {} { - set cmd [list /mod/bin/hmt -lock $file] - exec {*}$cmd - lremove flags "Locked" - return 1 -} - -ts method lock {} { - set cmd [list /mod/bin/hmt +lock $file] - exec {*}$cmd - ladd flags "Locked" - return 1 -} - -set ::ts::flagmap { - detectads Addetection - dedup Deduped - encrypted ODEncrypted - protect Encrypted -} - -ts method setflag {flag {dummy 0}} { - if {!$dummy} { - set cmd [list /mod/bin/hmt +$flag $file] - if {[catch {exec {*}$cmd}]} { - throw 20 "Unknown flag." - } - } - if {[dict exists $::ts::flagmap $flag]} { - ladd flags $::ts::flagmap($flag) - } else { - ladd flags [string totitle $flag] - } - return 1 -} - -ts method unsetflag {flag {dummy 0}} { - if {!$dummy} { - set cmd [list /mod/bin/hmt -$flag $file] - if {[catch {exec {*}$cmd}]} { - throw 20 "Unknown flag." - } - } - if {[dict exists $::ts::flagmap $flag]} { - lremove flags $::ts::flagmap($flag) - } else { - lremove flags [string totitle $flag] - } - return 1 -} - -ts method set_shrunk {} { - set cmd [list /mod/bin/hmt +shrunk $file] - exec {*}$cmd - ladd flags "Shrunk" - return 1 -} - -ts method set_deduped {} { - set cmd [list /mod/bin/hmt +dedup $file] - exec {*}$cmd - ladd flags "Deduped" - return 1 -} - -ts method unset_deduped {} { - set cmd [list /mod/bin/hmt -dedup $file] - exec {*}$cmd - lremove flags "Deduped" - return 1 -} - -ts method unenc {} { - set cmd [list /mod/bin/hmt -protect $file] - exec {*}$cmd - lremove flags "Encrypted" - return 1 -} - -ts method enc {} { - set cmd [list /mod/bin/hmt +protect $file] - exec {*}$cmd - ladd flags "Encrypted" - return 1 -} - -ts method set_new {} { - set cmd [list /mod/bin/hmt +new $file] - exec {*}$cmd - ladd flags "New" - return 1 -} - -ts method set_watched {} { - set cmd [list /mod/bin/hmt -new $file] - exec {*}$cmd - lremove flags "New" - return 1 -} - -ts method setfile {f} { set file $f } - -proc {ts parse} {file line} { - set e [ts new] - $e setfile $file - $e _parse $line - return $e -} - -proc {ts exec} {file} { - set raw 0 - set cmd [list /mod/bin/hmt] - lappend cmd "-p" - lappend cmd $file - - #puts "CMD -$cmd-" - - return [exec {*}$cmd] -} - -ts method fileset {} { - global tsgroup - - set root [file rootname $file] - set fset {} - foreach ext $tsgroup { - if {[file exists "$root.$ext"]} { - lappend fset "$root.$ext" - } - } - return $fset -} - -proc {ts fetch_or_error} {file {checked 0}} { - if {[catch {set ts [ts fetch $file $checked]}] || $ts == 0} { - print "Could not load ts file $file" - return 0 - } - return $ts -} - -proc {ts fetch} {file {checked 0}} { - # Check that this is a .ts file which has at least one sidecar - # file (.hmt) - if {!$checked} { - if {[file extension $file] ne ".ts"} { return 0 } - if {![file exists "[file rootname $file].hmt"]} { return 0 } - } - - if {[file extension $file] ne ".ts"} { - set file "[file rootname $file].ts" - } - - return [ts parse $file [ts exec $file]] -} - -ts method delete {} { - foreach f [$self fileset] { - file tdelete $f - puts "Removed $f
" - } - return 1 -} - -ts method move {dst {touch 0} {force 0}} { - foreach f [$self fileset] { - set nf "$dst/[file tail $f]" - while {[file exists $nf]} { - set nf "$dst/_[file tail $nf]" - } - file rename $f $nf - if {$touch} { - exec /mod/bin/busybox/touch $nf - } - } - return 1 -} - -ts method copy {dst} { - foreach f [$self fileset] { - file copy $f "$dst/[file tail $f]" - } - return 1 -} - -ts method settitle {newtitle} { - if {[string length $newtitle] > 48} { return } - - exec /mod/bin/hmt "+settitle=${newtitle}" $file - set title $newtitle -} - -ts method setsynopsis {newsynopsis} { - if {[string length $newsynopsis] > 252} { return } - - exec /mod/bin/hmt "+setsynopsis=${newsynopsis}" $file - set synopsis $newsynopsis -} - -ts method setguidance {newguidance} { - if {[string length $newguidance] > 74} { return } - - if {$newguidance eq ""} { - exec /mod/bin/hmt "-guidance" $file - } else { - exec /mod/bin/hmt "+setguidance=${newguidance}" $file - } - set guidance $newguidance -} - -proc {ts genre} {genre} { - if {![string is integer $genre] || $genre < 0} { - set genre 0 - } - if {$genre <= 15} { - set genre $($genre << 4) - } - return $genre -} - -ts method setgenre {newgenre} { - set newgenre [ts genre $newgenre] - exec /mod/bin/hmt "+setgenre=-${newgenre}" $file - set genre $newgenre -} - -ts method dlnaloc {{urlbase ""}} { - return [system dlnaurl $file $urlbase] -} - -ts method cleanbmp {} { - set bfile [file rootname $file] - foreach f [glob -nocomplain "${bfile}*.bmp"] { - file delete $f - } -} - -ts method mkbmps {{offset 0}} { - set bfile [file rootname $file] - if {[catch { - exec /mod/bin/ffmpeg -loglevel fatal -ss $offset -i $file \ - -vf fps=fps=2 -frames 5 \ - -pix_fmt argb -vf vflip -s 140x78 "${bfile}%d.bmp" - } msg]} { - puts "ERROR: $msg" - return 0 - } - return 1 -} - -ts method mkbmp {{offset 0} {ext ""}} { - set bfile [file rootname $file] - set bmpfile "$bfile$ext.bmp" - set cmd [list /mod/bin/ffmpeg -loglevel fatal -ss $offset -i $file \ - -frames 1 -pix_fmt argb -vf vflip -s 140x78 -y $bmpfile] - catch { exec {*}$cmd } - if {![catch { file stat $bmpfile stbmp }]} { - if {[dict get $stbmp size] != 0} { return 1 } - } - return 0 -} - -ts method mkthm {{offset 0}} { - if {![$self mkbmp $offset]} { return 0 } - set bfile [file rootname $file] - # Trim the bitmap header from the start of the file - if {[catch { - exec /bin/dd if=$bfile.bmp of=$bfile.thm~ bs=54 skip=1 - } msg]} { - puts "ERROR: $msg" - return 0 - } - exec /bin/echo -n " " >> $bfile.thm~ - file rename -force $bfile.thm~ $bfile.thm - file tdelete $bfile.bmp - $self setflag thumbnail - return 1 -} - -# From MontysEvilTwin -# - https://hummy.tv/forum/threads/7787/page-2#post-106826 -# ffmpeg -i "File 1.ts" -c:a mp3 -b:a 128k "File 1.mp3" -# ffmpeg -i "File 1.ts" -c:a copy "File 1.mp2" -# ffmpeg -i "File 1.ts" -c:a copy "File 1.loas" -ts method mkmp3 {{slow false} {tmp ""} {v 0} {br 128}} { - set rfile [file rootname $file] - - if {$slow} { - set opts [list -c:a mp3 -b:a ${br}k] - set ext mp3 - } else { - set opts [list -c:a copy] - if {$definition eq "HD"} { - set ext loas - } else { - set ext mp2 - } - } - set cmd [list /mod/bin/ffmpeg \ - -y -benchmark -vn -v $v \ - -i $file {*}$opts \ - ] - - if {$tmp eq ""} { - lappend cmd "${rfile}.$ext" - } else { - lappend cmd "$tmp.$ext" - } - - set output [exec {*}$cmd] - - if {$tmp ne ""} { - file rename "$tmp.$ext" "${rfile}.mp3" - } elseif {$ext ne "mp3"} { - file rename "${rfile}.$ext" "${rfile}.mp3" - } - - exec /mod/bin/id3v2 \ - --song $title \ - --comment $synopsis \ - --album $channel_name \ - --year "[clock format $start -format {%Y}]" \ - "${rfile}.mp3" - - return $output -} - -ts method mkmpg {{tmp ""}} { - set rfile [file rootname $file] - - set cmd [list /mod/bin/ffmpeg \ - -y -benchmark -v 0 \ - -i $file \ - -map 0:0 -map 0:1 \ - -vcodec copy -acodec copy] - - if {$tmp eq ""} { - lappend cmd "${rfile}.mpg" - } else { - lappend cmd "$tmp.mpg" - } - - set output [exec {*}$cmd] - - if {$tmp ne ""} { - file rename "$tmp.mpg" "${rfile}.mpg" - } - - return $output -} - -proc {ts renamegroup} {from to} { - global tsgroup - - set dir [file dirname $from] - set root [file rootname $from] - - # Catch from string without a . character in it - if {$root eq $from} { return } - - foreach ext $tsgroup { - set f "$root.$ext" - if {![file exists $f]} continue - file rename $f "${dir}/${to}.${ext}" - } - - exec /mod/bin/hmt "+setfilename=$to" "${dir}/${to}.hmt" - -# set ndir [file normalize $dir] -# -# if {![catch {set db [sqlite3.open $::dmsfile]}]} { -# catch { -# set x [lindex [$db query {select mediaid from tblMedia -# where localUrl = '%s'} [file normalize $from]] 0] -# lassign $x key mediaid -# if {$mediaid ne ""} { -# $db query {update tblMedia set localUrl = '%s' -# where mediaid = %s} "${ndir}/{$to}.ts" $mediaid -# $db query {update tblMedia set title = '%s' -# where mediaid = %s} "{$to}.ts" $mediaid -# } -# } -# $db close -# } -} - -proc {ts touchgroup} {target ref} { - global tsgroup - - set dir [file dirname $target] - set root [file rootname $target] - - # Catch from string without a . character in it - if {$root eq $target} { return } - - foreach ext $tsgroup { - set f "$root.$ext" - if {![file exists $f]} continue - file touch $f $ref - } -} - -proc {ts resetnew} {dir} { - if {![file isdirectory $dir]} return - if {![file exists "$dir/.series"]} { - set fd [open "$dir/.series" "w"] - puts -nonewline $fd [string repeat "\x0" 276] - close $fd - } - - set tot 0 - set watched 0 - foreach file [readdir -nocomplain $dir] { - if {![string match {*.ts} $file]} { continue } - incr tot - if {[set ts [ts fetch "$dir/$file"]] != 0} { - if {![$ts flag "New"]} { incr watched } - } - } - - if {!$tot} { - file delete "$dir/.series" - return - } - - set fd [open "$dir/.series"] - set bytes [read $fd] - close $fd - set recs [unpack $bytes -uintle 0 32] - set played [unpack $bytes -uintle 32 32] - - #puts "Current: $played/$recs" - #hexdump $bytes - #puts "Calculated: $watched/$tot" - - pack bytes $tot -intle 32 0 - pack bytes $watched -intle 32 32 - - #hexdump $bytes - - set fd [open "$dir/.series" "w"] - puts -nonewline $fd $bytes - close $fd -} - -proc {ts iterate} {callback {verbose 0} {dir ""} {nospecial 0}} {{rootdev 0}} { - require system.class - if {$dir eq ""} { - set dir [system mediaroot] - file stat "$dir/" rootstat - set rootdev $rootstat(dev) - } - - if {$verbose} { puts "Scanning directory ($dir)" } - - if {$rootdev != 0} { - file stat "$dir/" st - if {$st(dev) != $rootdev} return - } - - if {$nospecial && [system specialdir $dir]} return - - foreach entry [readdir -nocomplain $dir] { - if {[file isdirectory "$dir/$entry"]} { - ts iterate $callback $verbose "$dir/$entry" $nospecial - continue - } - if {![string match {*.ts} $entry]} continue - if {[catch {set ts [ts fetch "$dir/$entry"]}]} continue - if {$ts == 0} continue - $callback $ts - } -} - -# -# Attempt to extract the series/episode names using a variety of techniques -# - -ts method series_name {} { - - # For recorded series, use the folder name - set dir [file dirname $file] - if {[file exists "$dir/.series"]} { - set s [file tail $dir] - } else { - set s $title - } - - foreach x { - {^new: *} - } { - regsub -nocase -all -- $x $s "" s - } - - return $s -} - -set ::ts::episode_prefixes { - {^new series\.* *} - {^cbeebies\.* *} - {^cbbc\.* *} - {^t4: *} - {^brand new series *[-:]* *} - {^\.+} - { *\(Part [0-9] of [0-9]\) *} - {, Part [0-9]} -} - -ts method _tvdb_resolve {seriesid} { - # See if we can find a TVDB series for this recording. - - set dir [file dirname $file] - - set tvdb_series [set v [tvdb series "" $seriesid]] - if {[$v get seriesid] == 0} { return } - - # Got one. - - # Easiest case - we can explicitly request the episode. - if {$seriesnum && $episodenum} { - if {$seriescached} { - set tvdb_method "cached values" - } else { - set tvdb_method "series and episode number" - } - return [$v episodebynum $seriesnum $episodenum] - } - - # Now try to find the episode using the current episode name - # (using series or episode number if available) - set k [$v episodebyname $episodename $seriesnum $episodenum] - if {[llength $k]} { - set tvdb_method "episode name ($episodename)" - return $k - } - - # More problematic but can at least narrow the list of candidates - # using the episode or series numbers if we have them. - - if {$episodenum} { - set tvdb_method "episode number" - return [$v episodebyepnum $episodenum $synopsis] - } - - if {$seriesnum} { - set tvdb_method "series and synopsis" - return [$v episodebyseries $seriesnum $synopsis] - } - - # Most difficult - try and match based on synopsis alone - set tvdb_method "synopsis text" - return [$v episodebysynopsis $synopsis] -} - -proc {ts serieslist} {dir} { - set idfile "$dir/.tvdbseriesid" - if {![file exists $idfile]} { return {} } - return [lmap i [split [file read $idfile] "\n"] { - string trim $i - }] -} - -ts method extract_numbers {} { - - ###################################################################### - # Check for embedded Series/Episode number. - # Thank you broadcasters for the variation! - # Least trustworthy first. - - # Episode 5 - regexp -nocase -- {Episode (\d+)} $synopsis x episodenum - - # ^23/27. - regexp -nocase -- {^\s*(\d+)/(\d+)} $synopsis x episodenum episodetot - - # (8/8) - regexp -nocase -- {\((\d+)/(\d+)\)} $synopsis x episodenum episodetot - - # (Episode 5/10) - # (Ep5/10) - # (Ep 3 of 3) - # (Ep3) - regexp -nocase -- {Epi?s?o?d?e?\s*(\d+)\s*(of|/)?\s*(\d+)?} $synopsis \ - x episodenum x episodetot - - # (S2 Ep1) - # S.02 Ep.002 - # S01 Ep52 - # (S4 Ep 7) - # (S1, ep 2) - # (S8, Ep2) - # (S4 Ep22/24) - regexp -nocase -- {S\.*(\d+),?\s*Ep\.?\s*(\d+)(/(\d+))?} $synopsis \ - x seriesnum episodenum x episodetot - - # (Part 5/10) - # (Pt. 5/10) - # (Part 5 of 10) - # (Pt. 5 of 10) - # (Pt5) - regexp -nocase -- {P(art|t\.?)\s*(\d+)\s*(of|/)?\s*(\d+)?} $synopsis \ - x x episodenum x episodetot - - foreach v {seriesnum episodenum episodetot} { - if {[set $v] eq ""} { - set $v 0 - } else { - incr $v 0 - } - } - -} - -ts method episode_name {} { - set s $synopsis - - ###################################################################### - # Attempt to determine the episode name from the synopsis - - # Strip common prefixes - foreach prefix $::ts::episode_prefixes { - regsub -nocase -all -- $prefix $s "" s - } - - # Strip anything following a colon. - regsub -all -- { *[:].*$} $s "" s - - # If the resulting string is longer than 40 characters then - # split around . and take the left hand side if appropriate. - if {[string length $s] > 40} { - lassign [split $s "."] v w - set s $v - if {[string length $s] < 6 && [string length $w] < 6} { - append s "_$w" - } - } - - # Shorten if too long. - if {[string length $s] > 40} { set s [string range $s 0 39] } - - set episodename $s - - if {$episodenum == 0} { - $self extract_numbers - set seriescached 0 - } - - # Now see if TVDB has anything to add - - set fbase "[file dirname $file]/.tvdb" - - if {![system has tvdb] || ![file exists "${fbase}seriesid"]} { - return $s - } - - if {!$seriesnum && [file exists "${fbase}series"]} { - set seriesnum [string trim [file read "${fbase}series"]] - } - foreach seriesid [ts serieslist [$self dir]] { - set tvdb_data [$self _tvdb_resolve $seriesid] - if {![dict exists $tvdb_data name]} continue - set flag 0 - if {!$seriesnum} { - set seriesnum $tvdb_data(series) - incr flag - } - if {!$episodenum} { - set episodenum $tvdb_data(episode) - incr flag - } - if {$flag} { $self storeepisode } - - return $tvdb_data(name) - } - - return $s -} - -ts method epstr {{format "s%se%E/%n"}} { - set map {} - if {$seriesnum eq 0} { - set map(%s) "?" - set map(%S) "??" - } else { - set map(%s) $seriesnum - set map(%S) [format "%02d" $seriesnum] - } - if {$episodenum eq 0} { - set map(%e) "?" - set map(%E) "??" - } else { - set map(%e) $episodenum - set map(%E) [format "%02d" $episodenum] - } - if {$episodetot eq 0} { - set map(%n) "?" - set map(%N) "??" - } else { - set map(%n) $episodetot - set map(%N) [format "%02d" $episodetot] - } - return [string map $map $format] -} - -ts method tsr {} { - set fd [open "[file rootname $file].nts"] - set bytes [read $fd 0x20] - close $fd - set tsr [unpack $bytes -uintle $(8 * 0x1f) 8] - return $tsr -} - -ts method genrenib {} { - if {[catch {set v $($genre >> 4)}]} { set v 0 } - return $v -} - -ts method genre_info {} { - set g [$self genrenib] - lassign $::epg::genrelist($g) txt img - if {$img eq "Unclassified"} { - set img "/images/173_3_26_G3_$img.png" - } else { - set img "/images/173_3_00_G3_$img.png" - } - return [list $txt $img] -} - -proc {ts genrelist} {} { - require epg.class - set glist {} - foreach {k v} $::epg::genrelist { - lappend glist $($k << 4) $v - } - return $glist -} - -# return the key that will decrypt the file in the mode, or nothing -ts method getkey {mode} { - # mode: dlna (active key), direct - - set rfile [file rootname $file] - - set keys {} - # the active key - set key [string range [system nugget cryptokey -key] 0 31] - if {$key ne ""} { - lappend keys $key - } - if { $mode ne "dlna" } { - # also try other keys, such as this - same as active? - set key [system customencryptionkey] - if {$key ne ""} { - ladd keys $key - } - - # the native key - if {![catch {set key [system encryptionkey]}]} { - ladd keys $key - } - - # support a file listing other keys in hex, one-per-line - # eg, for recordings imported from a broken box - try { - set fd [open "/mod/etc/keys" r] - foreach key [split [$fd read -nonewline] "\n"] { - ladd keys $key - } - } on error {} { - } finally { - catch {$fd close} - } - } - - foreach key $keys { - if {[catch { - set ret [exec /mod/bin/stripts -q/ $key $rfile] - }]} continue - if {$ret eq "1"} { - return $key - } - } - return -} -