You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
14 KiB
357 lines
14 KiB
2 years ago
|
namespace eval shellspy::callbacks {
|
||
|
package require shellfilter
|
||
|
|
||
|
|
||
|
#each member of args - ist not itself a list - and cannot be treated as one.
|
||
|
#things like [concat {*}args] will generall break things further down the line
|
||
|
proc cmdshellb {args} {
|
||
|
shellfilter::log::open callback_cmdb {-syslog 127.0.0.1:514}
|
||
|
shellfilter::log::write callback_cmdb "cmdshellb got [llength $args] arguments"
|
||
|
shellfilter::log::write callback_cmdb "cmdshellb got '$args'"
|
||
|
|
||
|
if {[lindex $args 0] eq "cmdb"} {
|
||
|
set curlyparts [lrange $args 1 end]
|
||
|
shellfilter::log::write callback_cmdb "cmdshellb curlyparts '$curlyparts'"
|
||
|
#we lose grouping info by joining like this..
|
||
|
#set tail [string trim [join $curlyparts " "]]
|
||
|
set tailinfo [shellfilter::list_element_info $curlyparts]
|
||
|
|
||
|
shellfilter::log::write callback_cmdb "cmdshellb tailinfo '$tailinfo'"
|
||
|
#e.g
|
||
|
#% set y {{"c:/test/etc"} true {'blah1'} {'blah 2'}}
|
||
|
#% lappend y \\\\\\
|
||
|
#{"c:/test/etc"} true {'blah1'} {'blah 2'} \\\\\\
|
||
|
#% foreach i [shellfilter::list_element_info $y] {puts $i}
|
||
|
# 0
|
||
|
# wouldbrace 1 wouldescape 0 has_braces 0 has_inner_braces 0 apparentwrap doublequotes head_tail_chars {{"} {"}} head_tail_names {dq dq} len 13 difflen 2
|
||
|
# 1
|
||
|
# wouldbrace 0 wouldescape 0 has_braces 0 has_inner_braces 0 apparentwrap not-determined head_tail_chars {t e} head_tail_names {t e} len 4 difflen 0
|
||
|
# 2
|
||
|
# wouldbrace 0 wouldescape 0 has_braces 0 has_inner_braces 0 apparentwrap singlequotes head_tail_chars {' '} head_tail_names {sqote sqote} len 7 difflen 0
|
||
|
# 3
|
||
|
# wouldbrace 1 wouldescape 0 has_braces 0 has_inner_braces 0 apparentwrap singlequotes head_tail_chars {' '} head_tail_names {sqote sqote} len 8 difflen 2
|
||
|
# 4
|
||
|
# wouldbrace 0 wouldescape 1 has_braces 0 has_inner_braces 0 apparentwrap not-determined head_tail_chars {\\ \\} head_tail_names {\\ \\} len 3 difflen 3
|
||
|
|
||
|
|
||
|
#sample arglist - 7 items
|
||
|
#((c:\lua\luajit.exe
|
||
|
#C:\Users\sleek\vimfiles\plugged\vim-flog/lua/flog/graph_bin.lua
|
||
|
#__START
|
||
|
#true
|
||
|
#git -C C:/repo/3p/ansi-to-html --literal-pathspecs log --parents --topo-order --no-color --pretty=format:__START\%n\%h\%n\%p\%n\%D\%n\%ad\ \[\%h\]\ \{\%an\}\%d\ \%s --date=iso --no-merges --max-count=2000 -- )
|
||
|
#>
|
||
|
#C:\Users\sleek\AppData\Local\Temp\VRR6A67.tmp)
|
||
|
|
||
|
|
||
|
#complex method.. lists at levels..
|
||
|
set taillist [list]
|
||
|
set level 0 ;#bracket depth.. incr each opening bracket "("
|
||
|
set leveldict [dict create]
|
||
|
dict set leveldict 0 [list]
|
||
|
|
||
|
#simpler method.. string
|
||
|
set output ""
|
||
|
dict for {idx info} $tailinfo {
|
||
|
set item [lindex $curlyparts $idx]
|
||
|
set itemlen [string length $item]
|
||
|
if {[dict get $info apparentwrap] eq "brackets"} {
|
||
|
set chars [split $item ""]
|
||
|
set opening [lsearch -all $chars "("]
|
||
|
set closing [lsearch -all $chars ")"]
|
||
|
if {[llength $opening] == [llength $closing]} {
|
||
|
#dict lappend leveldict 0 $item ;#element individually wrapped in brackets and balanced, pass through
|
||
|
append output "$item "
|
||
|
} else {
|
||
|
#robustness warning: we examine outer brackets only, and are ignoring that things like {((a)(b)} {((a)(b}
|
||
|
# are composed of multiple elements for now .. as there should have been a space between the (a) & (b) elements anyway,
|
||
|
# in which case we would only see things like {((a)} or {(a}
|
||
|
set ltrimmed [string trimleft $item "("]
|
||
|
set countleft [expr {$itemlen - [string length $ltrimmed]}]
|
||
|
|
||
|
set rtrimmed [string trimright $item ")"]
|
||
|
set countright [expr {$itemlen - [string length $rtrimmed]}]
|
||
|
|
||
|
#simpler method..
|
||
|
append output "$item "
|
||
|
|
||
|
}
|
||
|
} else {
|
||
|
set lcharname [lindex [dict get $info head_tail_names] 0]
|
||
|
set rcharname [lindex [dict get $info head_tail_names] 1]
|
||
|
|
||
|
if {$lcharname eq "lbracket"} {
|
||
|
set ltrimmed [string trimleft $item "("]
|
||
|
set countleft [expr {$itemlen - [string length $ltrimmed]}]
|
||
|
set braces [string repeat "(" $countleft]
|
||
|
|
||
|
set testlist [list]
|
||
|
lappend testlist $ltrimmed
|
||
|
set testinfo [shellfilter::list_element_info $testlist]
|
||
|
set testelement [dict get $testinfo 0]
|
||
|
if {[dict get $testelement wouldbrace]} {
|
||
|
#append output "${braces}\"$ltrimmed\" "
|
||
|
append output "${braces} $ltrimmed "
|
||
|
} else {
|
||
|
append output "${braces} $ltrimmed "
|
||
|
}
|
||
|
|
||
|
} elseif {$rcharname eq "rbracket"} {
|
||
|
set rtrimmed [string trimright $item ")" ]
|
||
|
set countright [expr {$itemlen - [string length $rtrimmed]}]
|
||
|
set braces [string repeat ")" $countright]
|
||
|
set testlist [list]
|
||
|
lappend testlist $rtrimmed
|
||
|
set testinfo [shellfilter::list_element_info $testlist]
|
||
|
set testelement [dict get $testinfo 0]
|
||
|
if {[dict get $testelement wouldbrace]} {
|
||
|
#append output "\"$rtrimmed\"${braces} "
|
||
|
if {[string first " " $rtrimmed] > 0} {
|
||
|
append output "\"$rtrimmed\" ${braces} "
|
||
|
} else {
|
||
|
append output "$rtrimmed ${braces} "
|
||
|
}
|
||
|
} else {
|
||
|
append output "${rtrimmed} ${braces} "
|
||
|
}
|
||
|
|
||
|
|
||
|
} else {
|
||
|
set testlist [list]
|
||
|
lappend testlist $item
|
||
|
set testinfo [shellfilter::list_element_info $testlist]
|
||
|
set testelement [dict get $testinfo 0]
|
||
|
if {[dict get $testelement wouldbrace]} {
|
||
|
#append output "\"$item\" "
|
||
|
if {[string first " " $item] > 0} {
|
||
|
append output "\"$item\" "
|
||
|
} else {
|
||
|
append output "$item "
|
||
|
}
|
||
|
} else {
|
||
|
append output "$item "
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
shellfilter::log::write callback_cmdb "cmdshellb about to parse_cmd_brackets '$output'"
|
||
|
#$output now has quoted all items that 'wouldbrace'
|
||
|
set curly_list [shellfilter::parse_cmd_brackets $output]
|
||
|
if {[llength $curly_list] == 1} {
|
||
|
#we expect the whole set of arguments was wrapped in a set of brackets
|
||
|
set curly_items [lindex $curly_list 0]
|
||
|
} else {
|
||
|
#unexpected.. root level of string had multiple bracketed sections
|
||
|
#try using the curly_list directly warn?
|
||
|
set curly_items $curly_list
|
||
|
}
|
||
|
#e.g
|
||
|
# ((c:\lua\luajit.exe -v) > C:\Users\sleek\AppData\Local\Temp\V7NCBF.tmp)
|
||
|
#=>
|
||
|
# {{{c:\lua\luajit.exe} -v} > {C:\Users\sleek\AppData\Local\Temp\V7NCBF.tmp}}
|
||
|
|
||
|
#what is the proper way to flatten?
|
||
|
|
||
|
set comspec [lindex $curly_items 0]
|
||
|
if {[llength $comspec] >1} {
|
||
|
set commandlist [concat $comspec [lrange $curly_items 1 end]]
|
||
|
} else {
|
||
|
set commandlist $curly_items
|
||
|
}
|
||
|
|
||
|
set commandlist [floghack_singlearg callback_cmdb {*}$commandlist]
|
||
|
return $commandlist
|
||
|
} else {
|
||
|
shellfilter::log::write callback_cmdb "first arg: [lindex $args 0] vs 'cmdb'"
|
||
|
error "first arg: [lindex $args 0] vs 'cmdb'"
|
||
|
#return $args
|
||
|
}
|
||
|
}
|
||
|
proc cmdshell {args} {
|
||
|
if {[catch {
|
||
|
set args [floghack_singlearg callback_cmdshell {*}$args]
|
||
|
} errMsg]} {
|
||
|
error "FLOGHACK callback_cmdshell error $errMsg"
|
||
|
}
|
||
|
|
||
|
|
||
|
#set args [concat [lindex $args 0] [lrange $args 1 end]]
|
||
|
return $args
|
||
|
}
|
||
|
proc cmdshelluc {args} {
|
||
|
if {[catch {
|
||
|
set args [floghack_singlearg callback_cmdshelluc {*}$args]
|
||
|
} errMsg]} {
|
||
|
error "FLOGHACK callback_cmdshelluc error $errMsg"
|
||
|
}
|
||
|
|
||
|
#set args [concat [lindex $args 0] [lrange $args 1 end]]
|
||
|
return $args
|
||
|
}
|
||
|
|
||
|
proc powershell {args} {
|
||
|
if {[catch {
|
||
|
set args [floghack "callback_powershell" {*}$args]
|
||
|
} errMsg]} {
|
||
|
error "FLOGHACK callback_powershell error $errMsg"
|
||
|
}
|
||
|
return $args
|
||
|
|
||
|
}
|
||
|
proc raw {args} {
|
||
|
if {[catch {
|
||
|
set args [floghack_singlearg "callback_raw" {*}$args]
|
||
|
} errMsg]} {
|
||
|
error "FLOGHACK callback_raw error $errMsg"
|
||
|
}
|
||
|
#set args [concat [split [lindex $args 0]] [lrange $args 1 end]] ;#definitely bad!
|
||
|
|
||
|
|
||
|
return $args
|
||
|
}
|
||
|
|
||
|
#hack for c: drive - extend as necessary
|
||
|
#todo - customize!
|
||
|
# various hacks may be necessary for home dirs temp files etc!
|
||
|
proc sh {args} {
|
||
|
if {[catch {
|
||
|
set args [floghack callback_sh {*}$args]
|
||
|
} errMsg]} {
|
||
|
error "FLOGHACK callback_sh error $errMsg"
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
set final [list]
|
||
|
foreach a $args {
|
||
|
if {[string match -nocase {*c:/*} $a]} {
|
||
|
set a [string map [list {c:/} {/c/}] $a]
|
||
|
lappend final $a
|
||
|
} elseif {[string match -nocase {*c:\\*} $a]} {
|
||
|
set a [string map [list \\ / ] $a]
|
||
|
set a [string map [list {c:/} {/c/} {C:/} {/C/}] $a]
|
||
|
lappend final $a
|
||
|
} else {
|
||
|
lappend final $a
|
||
|
}
|
||
|
}
|
||
|
return $final
|
||
|
}
|
||
|
proc wsl {args} {
|
||
|
set args [floghack_singlearg callback_wsl {*}$args]
|
||
|
#wsl bash-style /mnt/c paths to be convertd
|
||
|
set args [convert_mnt_win {*}$args]
|
||
|
|
||
|
#review - seems bad
|
||
|
#flatten first element which arrives wrapped
|
||
|
#set args [concat [lindex $args 0] [lrange $args 1 end]]
|
||
|
|
||
|
|
||
|
return $args
|
||
|
}
|
||
|
proc bash {args} {
|
||
|
set args [floghack callback_bash {*}$args]
|
||
|
return [convert_mnt_win {*}$args]
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#helper functions
|
||
|
proc convert_mnt_win {args} {
|
||
|
set final [list]
|
||
|
foreach a $args {
|
||
|
if {[string match -nocase {*c:\\*} $a]} {
|
||
|
set a [string map [list \\ / ] $a]
|
||
|
}
|
||
|
#bash seems to be strict about lowercase /mnt/c
|
||
|
if {[string match -nocase {*c:/*} $a]} {
|
||
|
set a [string map [list {c:/} {/mnt/c/} {C:/} {/mnt/c/}] $a]
|
||
|
}
|
||
|
lappend final $a
|
||
|
}
|
||
|
shellfilter::log::write callback_convert_mnt_win "convert_mnt_win commandlist '$final'"
|
||
|
return $final
|
||
|
}
|
||
|
|
||
|
#when we get the git command and args together as one element in the commandlist
|
||
|
proc floghack_singlearg {logtag args} {
|
||
|
#return $args
|
||
|
shellfilter::log::write $logtag "floghack_singlearg got $logtag '$args'"
|
||
|
set newargs [list]
|
||
|
foreach a $args {
|
||
|
if {[string match "*pretty=format:__START*" $a]} {
|
||
|
set a [string map [list "pretty=format:__" "pretty=format:\"__"] $a]
|
||
|
set a [string map [list " --date=" "\" --date="] $a]
|
||
|
set a [string map [list \\ ""] $a] ;# a bad idea?
|
||
|
lappend newargs $a
|
||
|
} else {
|
||
|
lappend newargs $a
|
||
|
}
|
||
|
}
|
||
|
shellfilter::log::write $logtag "floghack_singlearg hacked commandlist '$newargs'"
|
||
|
return $newargs
|
||
|
}
|
||
|
|
||
|
|
||
|
proc floghack {logtag args} {
|
||
|
|
||
|
#return $args
|
||
|
shellfilter::log::write $logtag "floghack got [llength $args] args: '$args'"
|
||
|
set indent " "
|
||
|
set i 0
|
||
|
foreach a $args {
|
||
|
shellfilter::log::write $logtag "floghack ${indent}$i $a"
|
||
|
incr i
|
||
|
}
|
||
|
|
||
|
#Flog/luajit hack
|
||
|
#wrong way
|
||
|
#if {[string first "pretty=format:__START" $args] > 0} {
|
||
|
# set args [string map [list "pretty=format:" "pretty=format:'" " --date=" "' --date=" ] $args]
|
||
|
#}
|
||
|
set newargs [list]
|
||
|
|
||
|
set pretty ""
|
||
|
set pstart [lsearch $args "--pretty=format:__START*"]
|
||
|
set pafter [lsearch $args "--date=*"]
|
||
|
if {$pstart > 0} {
|
||
|
set newargs [lrange $args 0 $pstart-1]
|
||
|
set parts [lrange $args $pstart $pafter-1]
|
||
|
set i 1
|
||
|
foreach p $parts {
|
||
|
if {$i == 1} {
|
||
|
set pretty [string map [list "format:__" "format:\"__"] $p]
|
||
|
#set pretty $p
|
||
|
} else {
|
||
|
append pretty " $p"
|
||
|
}
|
||
|
if {$i == [llength $parts]} {
|
||
|
append pretty "\""
|
||
|
}
|
||
|
incr i
|
||
|
}
|
||
|
set pretty [string map [list \\ ""] $pretty]
|
||
|
lappend newargs $pretty
|
||
|
#lappend newargs "--pretty=format:%h"
|
||
|
set newargs [concat $newargs [lrange $args $pafter end]] ;#concat of 2 lists.. should be ok
|
||
|
} else {
|
||
|
set newargs $args
|
||
|
}
|
||
|
|
||
|
|
||
|
shellfilter::log::write $logtag "floghack hacked commandlist '$newargs'"
|
||
|
|
||
|
|
||
|
return $newargs
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
}
|