Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: follow XDG Base Directory Specification #105

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"path"

vt "github.com/VirusTotal/vt-go"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -51,7 +50,7 @@ func NewInitCmd() *cobra.Command {

Run: func(cmd *cobra.Command, args []string) {

fmt.Printf(vtBanner)
fmt.Print(vtBanner)

apiKey := cmd.Flags().Lookup("apikey").Value.String()

Expand All @@ -68,13 +67,15 @@ func NewInitCmd() *cobra.Command {
os.Exit(1)
}

dir, err := homedir.Dir()
cacheDir, err := os.UserCacheDir()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

relCacheFile, err := os.Create(path.Join(dir, ".vt.relationships.cache"))
relCache := path.Join(cacheDir, "vt-cli", "relationships")

relCacheFile, err := os.Create(relCache)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
Expand All @@ -88,7 +89,13 @@ func NewInitCmd() *cobra.Command {
os.Exit(1)
}

configFilePath := path.Join(dir, ".vt.toml")
configDir, err := os.UserConfigDir()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

configFilePath := path.Join(configDir, "vt-cli", "vt.toml")
configFile, err := os.Create(configFilePath)
if err != nil {
fmt.Fprintln(os.Stderr, err)
Expand Down
21 changes: 10 additions & 11 deletions cmd/privileges.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func NewPrivilegeCmd(target string) *cobra.Command {
cmd := &cobra.Command{
Use: "privileges",
Use: "privileges",
Short: fmt.Sprintf("Change %s privileges", target),
}

Expand All @@ -21,23 +21,22 @@ func NewPrivilegeCmd(target string) *cobra.Command {
return cmd
}


type Privilege struct {
Granted bool `json:"granted"`
Granted bool `json:"granted"`
ExpirationDate int64 `json:"expiration_date"`
}

type Privileges map[string]Privilege

func NewPrivilegeGrantCmd(target string) *cobra.Command {
cmd := &cobra.Command{
Use: fmt.Sprintf("grant [%sname] [privilege]...", target),
Short: fmt.Sprintf("Grant privileges to a %s", target),
Use: fmt.Sprintf("grant [%sname] [privilege]...", target),
Short: fmt.Sprintf("Grant privileges to a %s", target),
Example: fmt.Sprintf(" vt %s privileges grant my%s intelligence downloads-tier-2", target, target),
Args: cobra.MinimumNArgs(2),
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
var expirationDate int64
if expiration:= viper.GetString("expiration"); expiration != "" {
if expiration := viper.GetString("expiration"); expiration != "" {
var err error
expirationDate, err = strconv.ParseInt(expiration, 10, 64)
if err != nil {
Expand Down Expand Up @@ -68,18 +67,18 @@ func NewPrivilegeGrantCmd(target string) *cobra.Command {
},
}

cmd.Flags().StringP("" +
cmd.Flags().StringP(""+
"expiration", "e", "",
"expiration time for the granted privileges (UNIX timestamp or YYYY-MM-DD)")
return cmd
}

func NewPrivilegeRevokeCmd(target string) *cobra.Command {
return &cobra.Command{
Use: fmt.Sprintf("revoke [%sname] [privilege]...", target),
Short: fmt.Sprintf("Revoke privileges from a %s", target),
Use: fmt.Sprintf("revoke [%sname] [privilege]...", target),
Short: fmt.Sprintf("Revoke privileges from a %s", target),
Example: fmt.Sprintf(" vt %s privileges revoke my%s intelligence downloads-tier-2", target, target),
Args: cobra.MinimumNArgs(2),
Args: cobra.MinimumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
privileges := Privileges{}
for _, arg := range args[1:] {
Expand Down
10 changes: 7 additions & 3 deletions cmd/relationship.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,20 @@ import (
"sync"

vt "github.com/VirusTotal/vt-go"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var objectRelationshipsMap map[string][]vt.RelationshipMeta

func init() {
home, _ := homedir.Dir()
f, err := os.Open(path.Join(home, ".vt.relationships.cache"))
cacheDir, err := os.UserCacheDir()
if err != nil {
return
}

cachePath := path.Join(cacheDir, "vt-cli", "relationships")
f, err := os.Open(cachePath)
if err == nil {
defer f.Close()
dec := gob.NewDecoder(f)
Expand Down
3 changes: 1 addition & 2 deletions cmd/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ var urlCmdExample = ` vt url https://www.virustotal.com
vt url f1177df4692356280844e1d5af67cc4a9eccecf77aa61c229d483b7082c70a8e
cat list_of_urls | vt url -`


// Regular expressions used for validating a URL identifier.
var urlID = regexp.MustCompile(`[0-9a-fA-F]{64}`)

Expand All @@ -55,7 +54,7 @@ func NewURLCmd() *cobra.Command {
}
r := utils.NewMappedStringReader(
utils.StringReaderFromCmdArgs(args),
func (url string) string {
func(url string) string {
if urlID.MatchString(url) {
// The user provided a URL identifier as returned by
// VirusTotal's API, which consists in the URL's SHA-256.
Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ require (
github.com/gobwas/glob v0.2.3
github.com/gosuri/uitable v0.0.4
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213
github.com/mitchellh/go-homedir v1.1.0
github.com/plusvic/go-ansi v0.0.0-20180516115420-9879244c4340
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
Expand Down Expand Up @@ -45,7 +44,7 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
Expand Down Expand Up @@ -101,8 +99,8 @@ golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
Expand Down
21 changes: 10 additions & 11 deletions utils/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,18 @@ import (
// excluding keys matching any of the patterns in "exclude". The logic for
// determining if a key matches the pattern goes as follow:
//
// * The path for the key is computed. If the key is in the top-level map its
// path is the key itself, if the key is contained within a nested map its
// path is the concatenation of the parent's path and the key, using a dot (.)
// as a separator. The path for "key" in {a:{b:{key:val}}} is a.b.key.
// - The path for the key is computed. If the key is in the top-level map its
// path is the key itself, if the key is contained within a nested map its
// path is the concatenation of the parent's path and the key, using a dot (.)
// as a separator. The path for "key" in {a:{b:{key:val}}} is a.b.key.
//
// * The path is matched against the pattern, which can contain asterisks (*)
// as a placeholder for any character different from a dot (.) and ** as a
// placeholder for any character including a dot. For more information go to:
// https://godoc.org/github.com/gobwas/glob#Compile
//
// * If the path matches any pattern in "include" the key is included in the
// resulting map, as long as it doesn't match a pattern in "exclude".
// - The path is matched against the pattern, which can contain asterisks (*)
// as a placeholder for any character different from a dot (.) and ** as a
// placeholder for any character including a dot. For more information go to:
// https://godoc.org/github.com/gobwas/glob#Compile
//
// - If the path matches any pattern in "include" the key is included in the
// resulting map, as long as it doesn't match a pattern in "exclude".
func FilterMap(m map[string]interface{}, include, exclude []string) map[string]interface{} {
includeGlob := make([]glob.Glob, len(include))
excludeGlob := make([]glob.Glob, len(exclude))
Expand Down
6 changes: 2 additions & 4 deletions utils/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
Expand Down Expand Up @@ -77,9 +77,7 @@ var testCases = []testCase{
include: []string{"foo"},
exclude: []string{"**.quux"},
input: testMap,
output: map[string]interface{}{

},
output: map[string]interface{}{},
},

testCase{
Expand Down
2 changes: 1 addition & 1 deletion utils/pqueue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
49 changes: 38 additions & 11 deletions vt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,55 @@ package main
import (
"fmt"
"os"
"path"

"github.com/VirusTotal/vt-cli/cmd"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// Migrate old ~/.vt.* configuration files.
func migrateConfig(configDir string) {
home, err := os.UserHomeDir()
if err != nil {
return
}

for _, ext := range viper.SupportedExts {
oldPath := path.Join(home, ".vt."+ext)

f, err := os.Open(oldPath)
if f != nil {
f.Close()
}
if err != nil {
continue
}

newPath := path.Join(configDir, path.Base(oldPath))
err = os.Rename(oldPath, newPath)
if err != nil {
fmt.Printf("Migrated %s to %s\n", oldPath, newPath)
} else {
fmt.Printf("Failed to migrate %s to %s: %v\n", oldPath, newPath, err)
}
}
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
// Find config directory.
configDir, err := os.UserConfigDir()
if err == nil {
configDir = path.Join(configDir, "vt-cli")
migrateConfig(configDir)

// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
viper.AddConfigPath(configDir)
}

// Search config in home directory and current directory
viper.AddConfigPath(home)
// Search config in current directory
viper.AddConfigPath(".")
// Config file must be named .vt + format extension (.toml, .json, etc)
viper.SetConfigName(".vt")
// Config file must be named vt + format extension (.toml, .json, etc)
viper.SetConfigName("vt")

// The prefix for all environment variables will be VTCLI_. Examples:
// VTCLI_PROXY, VTCLI_APIKEY.
Expand Down
2 changes: 1 addition & 1 deletion yaml/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (enc *Encoder) encodeMap(m reflect.Value, indent int, prefix string) (err e
// If the key is an empty string or starts with some non-letter character
// let's enclose the key in double quotes.
firstChar, kLen := utf8.DecodeRuneInString(k.String())
if kLen == 0 || (firstChar != '_' && !unicode.IsLetter(firstChar)) {
if kLen == 0 || (firstChar != '_' && !unicode.IsLetter(firstChar)) {
keyPrinter(enc.w, "\"%s\": ", k)
} else {
keyPrinter(enc.w, "%s: ", k)
Expand Down
10 changes: 5 additions & 5 deletions yaml/yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
Expand Down Expand Up @@ -98,7 +98,7 @@ var tests = []T{
"uno": "1",
"dos": "2",
"tres": "3",
"": "",
"": "",
"#foo": "foo",
"|foo": "foo",
"_foo": "foo",
Expand Down Expand Up @@ -180,7 +180,7 @@ var tests = []T{
},
yaml: Y(fmt.Sprintf(`
Foo_date: 10000 # %v
`, time.Unix(10000, 0))),
`, time.Unix(10000, 0))),
},
{
data: struct {
Expand All @@ -190,7 +190,7 @@ var tests = []T{
},
yaml: Y(fmt.Sprintf(`
Bar_date: 10000 # %v
`, time.Unix(10000, 0))),
`, time.Unix(10000, 0))),
},
{
data: struct {
Expand All @@ -200,7 +200,7 @@ var tests = []T{
},
yaml: Y(fmt.Sprintf(`
Baz_date: 1.618312811e+09 # %v
`, time.Unix(1618312811, 0))),
`, time.Unix(1618312811, 0))),
},
}

Expand Down