@@ -24,7 +24,6 @@ import (
2424 "io"
2525 "net/url"
2626 "os"
27- "path"
2827 "path/filepath"
2928 "strings"
3029
@@ -82,12 +81,12 @@ var (
8281 }
8382
8483 if cfgPath == "" {
85- homeDir , err := os . UserHomeDir ()
84+ p , err := locateConfigFile ()
8685 if err != nil {
87- return fmt . Errorf ( "cannot get user home directory: %w" , err )
86+ return err
8887 }
8988
90- cfgPath = path . Join ( homeDir , ".config" , "privatebin" , "config.json" )
89+ cfgPath = p
9190 }
9291
9392 cfg , err := loadCfgFile (cfgPath )
@@ -225,18 +224,18 @@ var (
225224 )
226225 }
227226
228- _ = json .NewEncoder (os .Stdout ).Encode (
229- map [string ]any {
230- "paste_id" : result .PasteID ,
231- "paste" : map [string ]string {
232- "attachment_name" : result .Paste .AttachmentName ,
233- "attachment" : base64 .StdEncoding .EncodeToString (result .Paste .Attachment ),
234- "data" : base64 .StdEncoding .EncodeToString (result .Paste .Data ),
227+ _ = json .NewEncoder (os .Stdout ).Encode (
228+ map [string ]any {
229+ "paste_id" : result .PasteID ,
230+ "paste" : map [string ]string {
231+ "attachment_name" : result .Paste .AttachmentName ,
232+ "attachment" : base64 .StdEncoding .EncodeToString (result .Paste .Attachment ),
233+ "data" : base64 .StdEncoding .EncodeToString (result .Paste .Data ),
234+ },
235+ "comment_count" : result .CommentCount ,
236+ "comments" : comments ,
235237 },
236- "comment_count" : result .CommentCount ,
237- "comments" : comments ,
238- },
239- )
238+ )
240239 }
241240 return nil
242241 },
@@ -323,15 +322,15 @@ var (
323322
324323 switch output {
325324 case "" :
326- _ , _ = fmt .Fprintf (os .Stdout , "%s\n " , result .PasteURL .String ())
325+ _ , _ = fmt .Fprintf (os .Stdout , "%s\n " , result .PasteURL .String ())
327326 case "json" :
328- _ = json .NewEncoder (os .Stdout ).Encode (
329- map [string ]any {
330- "paste_id" : result .PasteID ,
331- "paste_url" : result .PasteURL .String (),
332- "delete_token" : result .DeleteToken ,
333- },
334- )
327+ _ = json .NewEncoder (os .Stdout ).Encode (
328+ map [string ]any {
329+ "paste_id" : result .PasteID ,
330+ "paste_url" : result .PasteURL .String (),
331+ "delete_token" : result .DeleteToken ,
332+ },
333+ )
335334 }
336335
337336 return nil
@@ -344,12 +343,12 @@ var (
344343 SilenceUsage : true ,
345344 PersistentPreRunE : func (cmd * cobra.Command , args []string ) error {
346345 if cfgPath == "" {
347- homeDir , err := os . UserHomeDir ()
346+ p , err := locateConfigFile ()
348347 if err != nil {
349- return fmt . Errorf ( "cannot get user home directory: %w" , err )
348+ return err
350349 }
351350
352- cfgPath = path . Join ( homeDir , ".config" , "privatebin" , "config.json" )
351+ cfgPath = p
353352 }
354353
355354 return nil
@@ -396,9 +395,69 @@ var (
396395 }
397396)
398397
398+ func configFileCandidates () ([]string , error ) {
399+ var candidates []string
400+ seen := make (map [string ]bool )
401+
402+ add := func (p string ) {
403+ if ! seen [p ] {
404+ seen [p ] = true
405+ candidates = append (candidates , p )
406+ }
407+ }
408+
409+ // $HOME/.config: conventional location for CLI tools.
410+ if home , err := os .UserHomeDir (); err == nil {
411+ add (filepath .Join (home , ".config" , "privatebin" , "config.json" ))
412+ }
413+
414+ // XDG_CONFIG_HOME: user-specific config directory override.
415+ if dir := os .Getenv ("XDG_CONFIG_HOME" ); dir != "" {
416+ add (filepath .Join (dir , "privatebin" , "config.json" ))
417+ }
418+
419+ // Platform-native user config directory.
420+ if dir , err := os .UserConfigDir (); err == nil {
421+ add (filepath .Join (dir , "privatebin" , "config.json" ))
422+ }
423+
424+ // XDG_CONFIG_DIRS: system-wide config directories (default /etc/xdg).
425+ xdgDirs := os .Getenv ("XDG_CONFIG_DIRS" )
426+ if xdgDirs == "" {
427+ xdgDirs = "/etc/xdg"
428+ }
429+ for _ , dir := range filepath .SplitList (xdgDirs ) {
430+ if dir != "" {
431+ add (filepath .Join (dir , "privatebin" , "config.json" ))
432+ }
433+ }
434+
435+ if len (candidates ) == 0 {
436+ return nil , fmt .Errorf ("cannot determine configuration file location" )
437+ }
438+
439+ return candidates , nil
440+ }
441+
442+ func locateConfigFile () (string , error ) {
443+ candidates , err := configFileCandidates ()
444+ if err != nil {
445+ return "" , err
446+ }
447+
448+ for _ , path := range candidates {
449+ if _ , err := os .Stat (path ); err == nil {
450+ return path , nil
451+ }
452+ }
453+
454+ // No existing file found; return the preferred default for creation.
455+ return candidates [0 ], nil
456+ }
457+
399458func init () {
400459 rootCmd .PersistentFlags ().StringVarP (& output , "output" , "o" , "" , "the command output format" )
401- rootCmd .PersistentFlags ().StringVarP (& cfgPath , "config" , "c" , "" , "the config file (default is $HOME /.config/privatebin/config.json)" )
460+ rootCmd .PersistentFlags ().StringVarP (& cfgPath , "config" , "c" , "" , "the config file (default is ~ /.config/privatebin/config.json)" )
402461 rootCmd .PersistentFlags ().StringVarP (& binName , "bin" , "b" , "" , "the name of the privatebin instance to use (default \" \" )" )
403462 rootCmd .PersistentFlags ().StringSliceVarP (& extraHeaderFields , "header" , "H" , []string {}, "extra HTTP header fields to include in the request sent" )
404463 rootCmd .PersistentFlags ().StringVar (& proxy , "proxy" , "" , "proxy URL to use for requests (e.g. socks5://127.0.0.1:9050 for TOR)" )
0 commit comments