This commit is contained in:
Sol Fisher Romanoff
2023-09-09 16:44:24 +03:00
parent 017b205af9
commit 979be3c5c6
18 changed files with 361 additions and 447 deletions

View File

@@ -1,23 +0,0 @@
package cmd
import "github.com/charmbracelet/lipgloss"
var separator = lipgloss.NewStyle().
Border(lipgloss.ThickBorder(), true, false).
Bold(true)
var statusstyle = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#00ff1a"))
var directorystyle = lipgloss.NewStyle().
Bold(true).
Underline(true)
var dnsstyle = lipgloss.NewStyle().
Bold(true).
Underline(true)
var portstyle = lipgloss.NewStyle().
Bold(true).
Underline(true)

27
cmd/sif/main.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import (
"fmt"
"github.com/charmbracelet/log"
"github.com/pushfs/sif"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/config"
)
func main() {
fmt.Println(styles.Box.Render(" _____________\n__________(_)__ __/\n__ ___/_ /__ /_ \n_(__ )_ / _ __/ \n/____/ /_/ /_/ \n"))
fmt.Println(styles.Subheading.Render("\nhttps://sif.sh\nman's best friend\n\ncopyright (c) 2023 pushfs, sfr and contributors.\n\n"))
settings := config.Parse()
app, err := sif.New(settings)
if err != nil {
log.Fatal(err)
}
err = app.Run()
if err != nil {
log.Fatal(err)
}
}

21
go.mod
View File

@@ -3,8 +3,6 @@ module github.com/pushfs/sif
go 1.20
require (
github.com/charmbracelet/bubbles v0.16.1
github.com/charmbracelet/bubbletea v0.24.1
github.com/charmbracelet/lipgloss v0.8.0
github.com/charmbracelet/log v0.2.4
github.com/projectdiscovery/goflags v0.1.19
@@ -18,44 +16,41 @@ require (
github.com/antchfx/htmlquery v1.3.0 // indirect
github.com/antchfx/xmlquery v1.3.15 // indirect
github.com/antchfx/xpath v1.2.4 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gocolly/colly/v2 v2.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/kennygrant/sanitize v1.2.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/microcosm-cc/bluemonday v1.0.25 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/projectdiscovery/blackrock v0.0.1 // indirect
github.com/projectdiscovery/utils v0.0.52 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/temoto/robotstxt v1.1.2 // indirect
golang.org/x/exp v0.0.0-20221019170559-20944726eadf // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.6.0 // indirect
golang.org/x/tools v0.11.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)

51
go.sum
View File

@@ -19,19 +19,13 @@ github.com/antchfx/xpath v1.1.8/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNY
github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/antchfx/xpath v1.2.4 h1:dW1HB/JxKvGtJ9WyVGJ0sIoEcqftV3SqIstujI+B9XY=
github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY=
github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc=
github.com/charmbracelet/bubbletea v0.24.1 h1:LpdYfnu+Qc6XtvMz6d/6rRY71yttHTP5HtrjMgWvixc=
github.com/charmbracelet/bubbletea v0.24.1/go.mod h1:rK3g/2+T8vOSEkNHvtq40umJpeVYDn6bLaqbgzhL/hg=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.8.0 h1:IS00fk4XAHcf8uZKc3eHeMUTCxUH6NkaTrdyCQk84RU=
github.com/charmbracelet/lipgloss v0.8.0/go.mod h1:p4eYUZZJ/0oXTuCQKFF8mqyKCz0ja6y+7DniDDw5KKU=
github.com/charmbracelet/log v0.2.4 h1:3pKtq5/Y5QMKtcZt7kDqD1p9w7lICzHYQACBFY4ocHA=
@@ -39,8 +33,7 @@ github.com/charmbracelet/log v0.2.4/go.mod h1:nQGK8tvc4pS9cvVEH/pWJiZ50eUq1aoXUO
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -76,18 +69,24 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg=
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@@ -95,14 +94,11 @@ github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJ
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -120,6 +116,9 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rocketlaunchr/google-search v1.1.6 h1:DcSluQWDWEMqo6jp6OGllMTI9SBECpSmUZFntAX4j/o=
github.com/rocketlaunchr/google-search v1.1.6/go.mod h1:fk5J/qPpaRDjLWdFxT+dmuiqG7kxXArC7K8A+gj88Nk=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
@@ -135,14 +134,15 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20221019170559-20944726eadf h1:nFVjjKDgNY37+ZSYCJmtYf7tOlfQswHqplG2eosjOMg=
golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -169,8 +169,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -180,7 +180,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -194,8 +193,6 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -216,8 +213,9 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -245,8 +243,9 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -17,23 +17,14 @@ schema = 3
version = "v1.2.4"
hash = "sha256-rT5AtOv49/iGdR6X42Ho+ZEw6+YGQqfNUcYkSp1CU/g="
[mod."github.com/asaskevich/govalidator"]
version = "v0.0.0-20210307081110-f21760c49a8d"
hash = "sha256-5ZVRCOiNcvpmK3/mhtF1Iy0naPFVVhmXXQmC6eaJExk="
version = "v0.0.0-20230301143203-a9d515a09cc2"
hash = "sha256-UCENzt1c1tFgsAzK2TNq5s2g0tQMQ5PxFaQKe8hTL/A="
[mod."github.com/aymanbagabas/go-osc52/v2"]
version = "v2.0.1"
hash = "sha256-6Bp0jBZ6npvsYcKZGHHIUSVSTAMEyieweAX2YAKDjjg="
[mod."github.com/aymerick/douceur"]
version = "v0.2.0"
hash = "sha256-NiBX8EfOvLXNiK3pJaZX4N73YgfzdrzRXdiBFe3X3sE="
[mod."github.com/charmbracelet/bubbles"]
version = "v0.16.1"
hash = "sha256-Z/H2bliHQttBM1mJmY3umFGl+RAcN5MgXpDcr1e/1O4="
[mod."github.com/charmbracelet/bubbletea"]
version = "v0.24.1"
hash = "sha256-Lu0sgcvW7XzyHPJ/JxKn7MyulaOg1IDhMO+MfYsWU8w="
[mod."github.com/charmbracelet/harmonica"]
version = "v0.2.0"
hash = "sha256-fi5N0IXhSbbYHdSZFngCfpT4kdiEaKedqj8YpnlvX0o="
[mod."github.com/charmbracelet/lipgloss"]
version = "v0.8.0"
hash = "sha256-m+cRJCCJjNyxJKxCk1ftu32OMesYDIUw/EVUzTZjo9I="
@@ -43,9 +34,6 @@ schema = 3
[mod."github.com/cnf/structhash"]
version = "v0.0.0-20201127153200-e1b16c1ebc08"
hash = "sha256-hvJSTpbaPHgWnJ16B9a4cFVblplAgCw5OkGSUFmJBvg="
[mod."github.com/containerd/console"]
version = "v1.0.4-0.20230313162750-1ae8d489ac81"
hash = "sha256-Qus81DgpWHJ6RRqeKOKcUFvzCxvPzygJqBabvBsBuHU="
[mod."github.com/go-logfmt/logfmt"]
version = "v0.6.0"
hash = "sha256-RtIG2qARd5sT10WQ7F3LR8YJhS8exs+KiuUiVf75bWg="
@@ -61,21 +49,24 @@ schema = 3
[mod."github.com/golang/protobuf"]
version = "v1.5.3"
hash = "sha256-svogITcP4orUIsJFjMtp+Uv1+fKJv2Q5Zwf2dMqnpOQ="
[mod."github.com/google/go-cmp"]
version = "v0.5.9"
hash = "sha256-lQc4O00R3QSMGs9LP8Sy7A9kj0cqV5rrUdpnGeipIyg="
[mod."github.com/gorilla/css"]
version = "v1.0.0"
hash = "sha256-Mmt/IqHpgrtWpbr/AKcJyf/USQTqEuv1HVivY4eHzoQ="
[mod."github.com/kennygrant/sanitize"]
version = "v1.2.4"
hash = "sha256-PRNblaLosaB7tvUVgAOZORMZGUo+7Wy7h1Z1mpJLd5c="
[mod."github.com/kr/pretty"]
version = "v0.3.1"
hash = "sha256-DlER7XM+xiaLjvebcIPiB12oVNjyZHuJHoRGITzzpKU="
[mod."github.com/lucasb-eyer/go-colorful"]
version = "v1.2.0"
hash = "sha256-Gg9dDJFCTaHrKHRR1SrJgZ8fWieJkybljybkI9x0gyE="
[mod."github.com/mattn/go-isatty"]
version = "v0.0.19"
hash = "sha256-wYQqGxeqV3Elkmn26Md8mKZ/viw598R4Ych3vtt72YE="
[mod."github.com/mattn/go-localereader"]
version = "v0.0.1"
hash = "sha256-JlWckeGaWG+bXK8l8WEdZqmSiTwCA8b1qbmBKa/Fj3E="
[mod."github.com/mattn/go-runewidth"]
version = "v0.0.14"
hash = "sha256-O3QdxqAcJgQ+HL1v8oBA4iKBwJ2AlDN+F464027hWMU="
@@ -85,12 +76,6 @@ schema = 3
[mod."github.com/miekg/dns"]
version = "v1.1.55"
hash = "sha256-Jbii9veDSpqF7yIkdrzb/bEUM3wZG41mNEAYV3VEAJo="
[mod."github.com/muesli/ansi"]
version = "v0.0.0-20211018074035-2e021307bc4b"
hash = "sha256-v4zQmLl5Z6hoKtuH0Ry6hRwAKNWna4rXirK62LXNvbY="
[mod."github.com/muesli/cancelreader"]
version = "v0.2.2"
hash = "sha256-uEPpzwRJBJsQWBw6M71FDfgJuR7n55d/7IV8MO+rpwQ="
[mod."github.com/muesli/reflow"]
version = "v0.3.0"
hash = "sha256-Pou2ybE9SFSZG6YfZLVV1Eyfm+X4FuVpDPLxhpn47Cc="
@@ -115,6 +100,9 @@ schema = 3
[mod."github.com/rocketlaunchr/google-search"]
version = "v1.1.6"
hash = "sha256-2BMD4RXtrxMKC8AaxyeU/p1i92MvGIQjv4KOA4giXfk="
[mod."github.com/rogpeppe/go-internal"]
version = "v1.10.0"
hash = "sha256-vR7+d0aoKTuKeTYSgZxsGhH9e5Zvxix3Zrq9SPm5+NQ="
[mod."github.com/saintfish/chardet"]
version = "v0.0.0-20230101081208-5e3ef4b5456d"
hash = "sha256-JXlHMCbXB8iRQ9wQBGCeTjDSfgaBwUVOpvcjj0iVn5A="
@@ -122,23 +110,17 @@ schema = 3
version = "v1.1.2"
hash = "sha256-/0zXEWCnvefGjU2RNxoyZu15KU6WYe9C4m58kyLU6zo="
[mod."golang.org/x/exp"]
version = "v0.0.0-20221019170559-20944726eadf"
hash = "sha256-ZGE8wyukPJFrXBptHnB8/CtJQvVM/TZ8NsL52mZI4pc="
version = "v0.0.0-20230626212559-97b1e661b5df"
hash = "sha256-aoesDZqls2sBtDmZ/ZSLzIudLuD8GDtGEEucyiqbCjY="
[mod."golang.org/x/mod"]
version = "v0.8.0"
hash = "sha256-cgtmxQA937+MdXUiPrVeDvRoqhxD4hvIbtXAjK2SM8U="
version = "v0.12.0"
hash = "sha256-M/oXnzm7odpJdQzEnG6W0pNYtl0uhOM/l7qgfGVpU2M="
[mod."golang.org/x/net"]
version = "v0.14.0"
hash = "sha256-QScKgO7lBWOsd0Y31wLRzFETv3tjqdB/eRQWW5q7aV4="
[mod."golang.org/x/sync"]
version = "v0.1.0"
hash = "sha256-Hygjq9euZ0qz6TvHYQwOZEjNiTbTh1nSLRAWZ6KFGR8="
[mod."golang.org/x/sys"]
version = "v0.11.0"
hash = "sha256-g/LjhABK2c/u6v7M2aAIrHvZjmx/ikGHkef86775N38="
[mod."golang.org/x/term"]
version = "v0.11.0"
hash = "sha256-muSv/d8Qpl+NXiOB01n6LeFEzC+hrlGviDdfu+6QdQ4="
[mod."golang.org/x/text"]
version = "v0.12.0"
hash = "sha256-aNQaW3EgCK9ehpnBzIAkZX6TmiUU1S175YlJUH7P5Qg="
@@ -146,14 +128,17 @@ schema = 3
version = "v0.3.0"
hash = "sha256-/hmc9skIswMYbivxNS7R8A6vCTUF9k2/7tr/ACkcEaM="
[mod."golang.org/x/tools"]
version = "v0.6.0"
hash = "sha256-J0q+C3WDTK9yyHX90FV6qr6n9H07YglYg1p4H3MqyH4="
version = "v0.11.0"
hash = "sha256-3fNsrCbUnbI5kwZRTx/olHLxR2DJhfvEQ3x0yeeZ8JY="
[mod."google.golang.org/appengine"]
version = "v1.6.7"
hash = "sha256-zIxGRHiq4QBvRqkrhMGMGCaVL4iM4TtlYpAi/hrivS4="
[mod."google.golang.org/protobuf"]
version = "v1.31.0"
hash = "sha256-UdIk+xRaMfdhVICvKRk1THe3R1VU+lWD8hqoW/y8jT0="
[mod."gopkg.in/check.v1"]
version = "v1.0.0-20201130134442-10cb98267c6c"
hash = "sha256-VlIpM2r/OD+kkyItn6vW35dyc0rtkJufA93rjFyzncs="
[mod."gopkg.in/yaml.v3"]
version = "v3.0.1"
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="

33
internal/styles/styles.go Normal file
View File

@@ -0,0 +1,33 @@
package styles
import "github.com/charmbracelet/lipgloss"
var (
Separator = lipgloss.NewStyle().
Border(lipgloss.ThickBorder(), true, false).
Bold(true)
Status = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#00ff1a"))
Highlight = lipgloss.NewStyle().
Bold(true).
Underline(true)
Box = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#fafafa")).
BorderStyle(lipgloss.RoundedBorder()).
Align(lipgloss.Center).
PaddingRight(15).
PaddingLeft(15).
Width(60)
Subheading = lipgloss.NewStyle().
Bold(true).
Align(lipgloss.Center).
PaddingRight(15).
PaddingLeft(15).
Width(60)
)

125
main.go
View File

@@ -1,125 +0,0 @@
package main
import (
"fmt"
"os"
"strings"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
"github.com/pushfs/sif/cmd"
)
var style = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#FAFAFA")).
BorderStyle(lipgloss.RoundedBorder()).
Align(lipgloss.Center).
PaddingRight(15).
PaddingLeft(15).
Width(60)
var subline = lipgloss.NewStyle().
Bold(true).
Align(lipgloss.Center).
PaddingRight(15).
PaddingLeft(15).
Width(60)
var subtext = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#FAFAFA")).
BorderStyle(lipgloss.RoundedBorder()).
PaddingTop(5).
PaddingLeft(15).
PaddingBottom(5).
Width(60)
func main() {
fmt.Println(style.Render(" _____________\n__________(_)__ __/\n__ ___/_ /__ /_ \n_(__ )_ / _ __/ \n/____/ /_/ /_/ \n"))
fmt.Println(subline.Render("\nhttps://sif.sh\nman's best friend\n\ncopyright (c) 2023 pushfs, sfr and contributors.\n\n"))
settings := parseURLs()
if settings.Debug {
log.SetLevel(log.DebugLevel)
}
if settings.LogDir != "" {
if _, err := os.Stat(settings.LogDir); os.IsNotExist(err) {
os.Mkdir(settings.LogDir, 0755)
}
}
// initialize array to store all the log file names
logFiles := make([]string, 0)
for _, url := range settings.URLs {
if !strings.Contains(url, "://") {
log.Warnf("URL %s must contain leading protocol. Skipping...", url)
continue
}
log.Infof("📡Starting scan on %s...", url)
if settings.LogDir != "" {
sanitizedURL := strings.Split(url, "://")[1]
if _, err := os.Stat(settings.LogDir + "/" + sanitizedURL + ".log"); os.IsNotExist(err) {
f, err := os.OpenFile(settings.LogDir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
}
f, err := os.OpenFile(settings.LogDir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf(" _____________\n__________(_)__ __/\n__ ___/_ /__ /_ \n_(__ )_ / _ __/ \n/____/ /_/ /_/ \n\nsif log file for %s\nhttps://sif.sh\n\n", url))
logFiles = append(logFiles, settings.LogDir+"/"+sanitizedURL+".log")
}
if !settings.NoScan {
cmd.Scan(url, settings.Timeout, settings.Threads, settings.LogDir)
}
if settings.Dirlist != "none" {
cmd.Dirlist(settings.Dirlist, url, settings.Timeout, settings.Threads, settings.LogDir)
}
if settings.Dnslist != "none" {
cmd.Dnslist(settings.Dnslist, url, settings.Timeout, settings.Threads, settings.LogDir)
}
if settings.Ports != "none" {
cmd.Ports(settings.Ports, url, settings.Timeout, settings.Threads, settings.LogDir)
}
if settings.Dorking {
cmd.Dork(url, settings.Timeout, settings.Threads, settings.LogDir)
}
if settings.Git {
cmd.Git(url, settings.Timeout, settings.Threads, settings.LogDir)
}
if settings.Nuclei {
cmd.Nuclei(url, settings.Threads, settings.LogDir)
}
// TODO: WHOIS
fmt.Println()
}
if settings.LogDir != "" {
fmt.Println(style.Render(fmt.Sprintf("🌿 All scans completed!\n📂 Output saved to files: %s\n", strings.Join(logFiles, ", "))))
} else {
fmt.Println(style.Render(fmt.Sprintf("🌿 All scans completed!\n")))
}
}

View File

@@ -1,8 +1,6 @@
package main
package config
import (
"bufio"
"os"
"time"
"github.com/charmbracelet/log"
@@ -10,7 +8,6 @@ import (
)
type Settings struct {
URLs []string
Dirlist string
Dnslist string
Debug bool
@@ -22,6 +19,8 @@ type Settings struct {
Threads int
Nuclei bool
Timeout time.Duration
URLs goflags.StringSlice
File string
}
const (
@@ -37,17 +36,15 @@ const (
Full
)
func parseURLs() Settings {
func Parse() *Settings {
settings := &Settings{}
flagSet := goflags.NewFlagSet()
flagSet.SetDescription("a blazing-fast pentesting (recon/exploitation) suite")
var urls goflags.StringSlice
var file string
flagSet.CreateGroup("target", "Targets",
flagSet.StringSliceVarP(&urls, "urls", "u", nil, "List of URLs to check (comma-separated)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringVarP(&file, "file", "f", "", "File that includes URLs to check"),
flagSet.StringSliceVarP(&settings.URLs, "urls", "u", nil, "List of URLs to check (comma-separated)", goflags.FileCommaSeparatedStringSliceOptions),
flagSet.StringVarP(&settings.File, "file", "f", "", "File that includes URLs to check"),
)
listSizes := goflags.AllowdTypes{"small": Small, "medium": Medium, "large": Large, "none": Nil}
@@ -73,28 +70,5 @@ func parseURLs() Settings {
log.Fatalf("Could not parse flags: %s", err)
}
if len(urls) > 0 {
settings.URLs = urls
} else if file != "" {
if _, err := os.Stat(file); err != nil {
log.Fatal(err)
}
log.Infof("Reading file %s", file)
data, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer data.Close()
scanner := bufio.NewScanner(data)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
settings.URLs = append(settings.URLs, scanner.Text())
}
} else {
log.Fatal("Please specify either a URL or a file containing URLs, as well as options.\nSee -help for more information.")
}
return *settings
return settings
}

55
pkg/logger/logger.go Normal file
View File

@@ -0,0 +1,55 @@
package logger
import (
"fmt"
"os"
"strings"
)
func Init(dir string) error {
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err = os.Mkdir(dir, 0755); err != nil {
return err
}
}
return nil
}
func CreateFile(logFiles []string, url string, dir string) error {
sanitizedURL := strings.Split(url, "://")[1]
if _, err := os.Stat(dir + "/" + sanitizedURL + ".log"); os.IsNotExist(err) {
f, err := os.OpenFile(dir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return err
}
defer f.Close()
}
f, err := os.OpenFile(dir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return err
}
defer f.Close()
f.WriteString(fmt.Sprintf(" _____________\n__________(_)__ __/\n__ ___/_ /__ /_ \n_(__ )_ / _ __/ \n/____/ /_/ /_/ \n\nsif log file for %s\nhttps://sif.sh\n\n", url))
logFiles = append(logFiles, dir+"/"+sanitizedURL+".log")
return nil
}
func Write(url string, dir string, text string) error {
f, err := os.OpenFile(dir+"/"+url+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return err
}
defer f.Close()
f.WriteString(text)
return nil
}
func WriteHeader(url string, dir string, scan string) error {
return Write(url, dir, fmt.Sprintf("\n\n--------------\nStarting %s\n--------------\n", scan))
}

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -11,7 +11,8 @@ import (
"time"
"github.com/charmbracelet/log"
// "github.com/pushfs/sif/util"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
)
const (
@@ -23,24 +24,20 @@ const (
func Dirlist(size string, url string, timeout time.Duration, threads int, logdir string) {
fmt.Println(separator.Render("📂 Starting " + statusstyle.Render("directory fuzzing") + "..."))
fmt.Println(styles.Separator.Render("📂 Starting " + styles.Status.Render("directory fuzzing") + "..."))
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, size+" directory fuzzing"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("\n\n--------------\nStarting %s directory fuzzing\n--------------\n", size))
}
logger := log.NewWithOptions(os.Stderr, log.Options{
dirlog := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "Dirlist 📂",
})
dirlog := logger.With("url", url)
}).With("url", url)
var list string
@@ -68,7 +65,6 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
directories = append(directories, scanner.Text())
}
// util.InitProgressBar()
client := &http.Client{
Timeout: timeout,
}
@@ -93,15 +89,9 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
if resp.StatusCode != 404 {
// log url, directory, and status code
dirlog.Infof("%s [%s]", statusstyle.Render(strconv.Itoa(resp.StatusCode)), directorystyle.Render(directory))
dirlog.Infof("%s [%s]", styles.Status.Render(strconv.Itoa(resp.StatusCode)), styles.Highlight.Render(directory))
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("%s [%s]\n", strconv.Itoa(resp.StatusCode), directory))
logger.Write(sanitizedURL, logdir, fmt.Sprintf("%s [%s]\n", strconv.Itoa(resp.StatusCode), directory))
}
}
}

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -10,7 +10,8 @@ import (
"time"
"github.com/charmbracelet/log"
// "github.com/pushfs/sif/util"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
)
const (
@@ -22,13 +23,11 @@ const (
func Dnslist(size string, url string, timeout time.Duration, threads int, logdir string) {
fmt.Println(separator.Render("📡 Starting " + statusstyle.Render("DNS fuzzing") + "..."))
fmt.Println(styles.Separator.Render("📡 Starting " + styles.Status.Render("DNS fuzzing") + "..."))
logger := log.NewWithOptions(os.Stderr, log.Options{
dnslog := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "Dnslist 📡",
})
dnslog := logger.With("url", url)
}).With("url", url)
var list string
@@ -56,18 +55,13 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
dns = append(dns, scanner.Text())
}
// util.InitProgressBar()
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, size+" subdomain fuzzing"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("\n\n--------------\nStarting %s DNS listing\n--------------\n", size))
}
client := &http.Client{
@@ -90,7 +84,7 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
if err != nil {
log.Debugf("Error %s: %s", domain, err)
} else {
dnslog.Infof("%s %s.%s", statusstyle.Render("[http]"), dnsstyle.Render(domain), sanitizedURL)
dnslog.Infof("%s %s.%s", styles.Status.Render("[http]"), styles.Highlight.Render(domain), sanitizedURL)
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
@@ -107,15 +101,9 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
if err != nil {
log.Debugf("Error %s: %s", domain, err)
} else {
dnslog.Infof("%s %s.%s", statusstyle.Render("[https]"), dnsstyle.Render(domain), sanitizedURL)
dnslog.Infof("%s %s.%s", styles.Status.Render("[https]"), styles.Highlight.Render(domain), sanitizedURL)
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("[https] %s.%s\n", domain, sanitizedURL))
logger.Write(sanitizedURL, logdir, fmt.Sprintf("[https] %s.%s\n", domain, sanitizedURL))
}
}
}

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -11,8 +11,9 @@ import (
"time"
"github.com/charmbracelet/log"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
googlesearch "github.com/rocketlaunchr/google-search"
// "github.com/pushfs/sif/util"
)
const (
@@ -22,24 +23,20 @@ const (
func Dork(url string, timeout time.Duration, threads int, logdir string) {
fmt.Println(separator.Render("🤓 Starting " + statusstyle.Render("URL Dorking") + "..."))
fmt.Println(styles.Separator.Render("🤓 Starting " + styles.Status.Render("URL Dorking") + "..."))
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, "URL dorking"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("\n\n--------------\nStarting URL dorking...\n--------------\n"))
}
logger := log.NewWithOptions(os.Stderr, log.Options{
dorklog := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "Dorking 🤓",
})
dorklog := logger.With("url", url)
}).With("url", url)
dorklog.Infof("Starting URL dorking...")
@@ -70,15 +67,9 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) {
results, _ := googlesearch.Search(nil, fmt.Sprintf("%s %s", dork, sanitizedURL))
if len(results) > 0 {
dorklog.Infof("%s dork results found for dork [%s]", statusstyle.Render(strconv.Itoa(len(results))), directorystyle.Render(dork))
dorklog.Infof("%s dork results found for dork [%s]", styles.Status.Render(strconv.Itoa(len(results))), styles.Highlight.Render(dork))
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("%s dork results found for dork [%s]\n", strconv.Itoa(len(results)), dork))
logger.Write(sanitizedURL, logdir, fmt.Sprintf("%s dork results found for dork [%s]\n", strconv.Itoa(len(results)), dork))
}
}
}

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -11,7 +11,8 @@ import (
"time"
"github.com/charmbracelet/log"
// "github.com/pushfs/sif/util"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
)
const (
@@ -21,24 +22,20 @@ const (
func Git(url string, timeout time.Duration, threads int, logdir string) {
fmt.Println(separator.Render("🌿 Starting " + statusstyle.Render("git repository scanning") + "..."))
fmt.Println(styles.Separator.Render("🌿 Starting " + styles.Status.Render("git repository scanning") + "..."))
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, "git directory fuzzing"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString("\n\n--------------\nStarting git repository scanning\n--------------\n")
}
logger := log.NewWithOptions(os.Stderr, log.Options{
gitlog := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "Git 🌿",
})
gitlog := logger.With("url", url)
}).With("url", url)
gitlog.Infof("Starting repository scanning")
@@ -79,15 +76,9 @@ func Git(url string, timeout time.Duration, threads int, logdir string) {
if resp.StatusCode != 404 {
// log url, directory, and status code
gitlog.Infof("%s git found at [%s]", statusstyle.Render(strconv.Itoa(resp.StatusCode)), directorystyle.Render(repourl))
gitlog.Infof("%s git found at [%s]", styles.Status.Render(strconv.Itoa(resp.StatusCode)), styles.Highlight.Render(repourl))
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("%s git found at [%s]\n", strconv.Itoa(resp.StatusCode), repourl))
logger.Write(sanitizedURL, logdir, fmt.Sprintf("%s git found at [%s]\n", strconv.Itoa(resp.StatusCode), repourl))
}
}
}

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -10,6 +10,8 @@ import (
"sync"
"github.com/charmbracelet/log"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
"gopkg.in/yaml.v3"
)
@@ -135,18 +137,15 @@ type Template struct {
}
func Nuclei(url string, threads int, logdir string) {
fmt.Println(separator.Render("⚛️ Starting " + statusstyle.Render("nuclei template scanning") + "..."))
fmt.Println(styles.Separator.Render("⚛️ Starting " + styles.Status.Render("nuclei template scanning") + "..."))
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, "nuclei port scanning"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("\n\n--------------\nStarting nuclei template scanning...\n--------------\n"))
}
logger := log.NewWithOptions(os.Stderr, log.Options{

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -12,22 +12,21 @@ import (
"time"
"github.com/charmbracelet/log"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
)
const commonPorts = "https://raw.githubusercontent.com/pushfs/sif-runtime/main/ports/top-ports.txt"
func Ports(scope string, url string, timeout time.Duration, threads int, logdir string) {
fmt.Println(separator.Render("🚪 Starting " + statusstyle.Render("port scanning") + "..."))
fmt.Println(styles.Separator.Render("🚪 Starting " + styles.Status.Render("port scanning") + "..."))
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, scope+" port scanning"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("\n\n--------------\nStarting %s port scanning\n--------------\n", scope))
}
portlog := log.NewWithOptions(os.Stderr, log.Options{
@@ -77,7 +76,7 @@ func Ports(scope string, url string, timeout time.Duration, threads int, logdir
log.Debugf("Error %d: %v", port, err)
} else {
openPorts = append(openPorts, strconv.Itoa(port))
portlog.Infof("%s %s:%s", statusstyle.Render("[tcp]"), sanitizedURL, portstyle.Render(strconv.Itoa(port)))
portlog.Infof("%s %s:%s", styles.Status.Render("[tcp]"), sanitizedURL, styles.Highlight.Render(strconv.Itoa(port)))
tcp.Close()
}
}

View File

@@ -1,4 +1,4 @@
package cmd
package scan
import (
"bufio"
@@ -11,29 +11,26 @@ import (
"time"
"github.com/charmbracelet/log"
// "github.com/pushfs/sif/util"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/logger"
)
func Scan(url string, timeout time.Duration, threads int, logdir string) {
fmt.Println(separator.Render("🐾 Starting " + statusstyle.Render("base url scanning") + "..."))
fmt.Println(styles.Separator.Render("🐾 Starting " + styles.Status.Render("base url scanning") + "..."))
sanitizedURL := strings.Split(url, "://")[1]
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
if err := logger.WriteHeader(sanitizedURL, logdir, "URL scanning"); err != nil {
log.Errorf("Error creating log file: %v", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("\n\n--------------\nStarting URL scanning\n--------------\n"))
}
logger := log.NewWithOptions(os.Stderr, log.Options{
scanlog := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "Scan 👁️‍🗨️",
})
scanlog := logger.With("url", url)
}).With("url", url)
client := &http.Client{
Timeout: timeout,
@@ -48,7 +45,7 @@ func Scan(url string, timeout time.Duration, threads int, logdir string) {
}
defer resp.Body.Close()
if resp.StatusCode != 404 && resp.StatusCode != 301 && resp.StatusCode != 302 && resp.StatusCode != 307 {
scanlog.Infof("file [%s] found", statusstyle.Render("robots.txt"))
scanlog.Infof("file [%s] found", styles.Status.Render("robots.txt"))
var robotsData []string
scanner := bufio.NewScanner(resp.Body)
@@ -81,15 +78,9 @@ func Scan(url string, timeout time.Duration, threads int, logdir string) {
}
if resp.StatusCode != 404 {
scanlog.Infof("%s from robots: [%s]", statusstyle.Render(strconv.Itoa(resp.StatusCode)), directorystyle.Render(sanitizedRobot))
scanlog.Infof("%s from robots: [%s]", styles.Status.Render(strconv.Itoa(resp.StatusCode)), styles.Highlight.Render(sanitizedRobot))
if logdir != "" {
f, err := os.OpenFile(logdir+"/"+sanitizedURL+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("Error creating log file: %s", err)
return
}
defer f.Close()
f.WriteString(fmt.Sprintf("%s from robots: [%s]\n", strconv.Itoa(resp.StatusCode), sanitizedRobot))
logger.Write(sanitizedURL, logdir, fmt.Sprintf("%s from robots: [%s]\n", strconv.Itoa(resp.StatusCode), sanitizedRobot))
}
}
}

121
sif.go Normal file
View File

@@ -0,0 +1,121 @@
package sif
import (
"bufio"
"errors"
"fmt"
"os"
"strings"
"github.com/charmbracelet/log"
"github.com/pushfs/sif/internal/styles"
"github.com/pushfs/sif/pkg/config"
"github.com/pushfs/sif/pkg/logger"
"github.com/pushfs/sif/pkg/scan"
)
// App is a client instance. It is first initialised using New and then ran
// using Run, which starts the whole app process.
type App struct {
settings *config.Settings
targets []string
logFiles []string
}
// New creates a new App struct by parsing the configuration options,
// figuring out the targets from list or file, etc.
//
// Errors if no targets are supplied through URLs or File.
func New(settings *config.Settings) (*App, error) {
app := &App{settings: settings}
if len(settings.URLs) > 0 {
app.targets = settings.URLs
} else if settings.File != "" {
if _, err := os.Stat(settings.File); err != nil {
return app, err
}
data, err := os.Open(settings.File)
if err != nil {
return app, err
}
defer data.Close()
scanner := bufio.NewScanner(data)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
app.targets = append(app.targets, scanner.Text())
}
} else {
return app, errors.New("target(s) must be supplied with -u or -f")
}
return app, nil
}
// Run runs the pentesting suite, with the targets specified, according to the
// settings specified.
func (app *App) Run() error {
if app.settings.Debug {
log.SetLevel(log.DebugLevel)
}
if app.settings.LogDir != "" {
if err := logger.Init(app.settings.LogDir); err != nil {
return err
}
}
for _, url := range app.targets {
if !strings.Contains(url, "://") {
return errors.New(fmt.Sprintf("URL %s must include leading protocol", url))
}
log.Infof("📡Starting scan on %s...", url)
if app.settings.LogDir != "" {
if err := logger.CreateFile(app.logFiles, url, app.settings.LogDir); err != nil {
return err
}
}
if !app.settings.NoScan {
scan.Scan(url, app.settings.Timeout, app.settings.Threads, app.settings.LogDir)
}
if app.settings.Dirlist != "none" {
scan.Dirlist(app.settings.Dirlist, url, app.settings.Timeout, app.settings.Threads, app.settings.LogDir)
}
if app.settings.Dnslist != "none" {
scan.Dnslist(app.settings.Dnslist, url, app.settings.Timeout, app.settings.Threads, app.settings.LogDir)
}
if app.settings.Ports != "none" {
scan.Ports(app.settings.Ports, url, app.settings.Timeout, app.settings.Threads, app.settings.LogDir)
}
if app.settings.Dorking {
scan.Dork(url, app.settings.Timeout, app.settings.Threads, app.settings.LogDir)
}
if app.settings.Git {
scan.Git(url, app.settings.Timeout, app.settings.Threads, app.settings.LogDir)
}
if app.settings.Nuclei {
scan.Nuclei(url, app.settings.Threads, app.settings.LogDir)
}
// TODO: WHOIS
}
if app.settings.LogDir != "" {
fmt.Println(styles.Box.Render(fmt.Sprintf("🌿 All scans completed!\n📂 Output saved to files: %s\n", strings.Join(app.logFiles, ", "))))
} else {
fmt.Println(styles.Box.Render(fmt.Sprintf("🌿 All scans completed!\n")))
}
return nil
}

View File

@@ -1,76 +0,0 @@
package util
import (
"fmt"
"os"
"strings"
"time"
"github.com/charmbracelet/bubbles/progress"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
const (
padding = 2
maxWidth = 80
)
var helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262")).Render
func InitProgressBar() {
m := model{
progress: progress.New(progress.WithDefaultGradient()),
}
if _, err := tea.NewProgram(m).Run(); err != nil {
fmt.Println("Oh no!", err)
os.Exit(1)
}
}
type tickMsg time.Time
type model struct {
progress progress.Model
}
func (m model) Init() tea.Cmd {
return tickCmd()
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tickMsg:
if m.progress.Percent() == 1.0 {
return m, tea.Quit
}
// Note that you can also use progress.Model.SetPercent to set the
// percentage value explicitly, too.
cmd := m.progress.IncrPercent(0.25)
return m, tea.Batch(tickCmd(), cmd)
// FrameMsg is sent when the progress bar wants to animate itself
case progress.FrameMsg:
progressModel, cmd := m.progress.Update(msg)
m.progress = progressModel.(progress.Model)
return m, cmd
default:
return m, nil
}
}
func (m model) View() string {
pad := strings.Repeat(" ", padding)
return "\n" +
pad + m.progress.View() + "\n\n" +
pad + helpStyle("Press any key to quit")
}
func tickCmd() tea.Cmd {
return tea.Tick(time.Second*1, func(t time.Time) tea.Msg {
return tickMsg(t)
})
}