diff --git a/modules/paste/fpaste.go b/modules/paste/fpaste.go index c2a476a..a475a92 100644 --- a/modules/paste/fpaste.go +++ b/modules/paste/fpaste.go @@ -2,18 +2,30 @@ package paste import ( + "bytes" "fmt" + "io" + "net/http" + "net/url" + "os" "os/user" + "strings" ) var ( + // paste.centos.org does things in minutes fpasteTimeMap = map[string]string{ "1hour": "60", "1day": "1440", "1week": "10080", } + rawSlug = "view/raw" + // I'll ask the maintainer of the paste site if I could potentially obtain + // our own API key instead of using the one from the fpaste script + fpasteBaseURL = "https://paste.centos.org" fpasteAPIKey = "5uZ30dTZE1a5V0WYhNwcMddBRDpk6UzuzMu-APKM38iMHacxdA0n4vCqA34avNyt" - fpasteUserAgent = "fpaste/0.4.0.0" + fpasteURL = "https://paste.centos.org/api/create" + fpasteUserAgent = "rpaste/0.2.0" fpasteTitle = "UNTITLED" // we'll need to make this changeable in the future fpastePrivate = "1" fpasteUserName = "user" @@ -27,5 +39,47 @@ func Fpaste(life string, lexer string, fileContent string) error { } else { fpasteUserName = user.Name } + + // Stikkit doesn't seem to take in json data. It takes in form data and + // general headers. + form := url.Values{} + form.Add("title", fpasteTitle) + form.Add("expire", fpasteTimeMap[life]) + form.Add("private", fpastePrivate) + form.Add("lang", lexer) + form.Add("name", fpasteUserName) + form.Add("text", fileContent) + + rurl, err := url.Parse(fpasteURL) + if err != nil { + fmt.Println("Failed to construct URL") + os.Exit(1) + } + + // This helps us do a proper urlencode for the API key, instead of just + // stashing it in the var itself. + vs := rurl.Query() + vs.Add("apikey", fpasteAPIKey) + rurl.RawQuery = vs.Encode() + + fmt.Println("Uploading...") + resp, err := http.PostForm(rurl.String(), form) + + // The response comes back as bytes, so we copy the response buffer into io + // and string it out + buf := &bytes.Buffer{} + io.Copy(buf, resp.Body) + pasteURL := buf.String() + + if resp.StatusCode == 200 { + urlish := strings.Replace(pasteURL, "\n", "", -1) + ss := strings.Split(urlish, "/") + slug := ss[len(ss)-1] + fmt.Printf("Paste URL: %s", pasteURL) + fmt.Printf("Raw URL: %s/%s/%s\n", fpasteBaseURL, rawSlug, slug) + } else { + fmt.Printf("%s", http.StatusText(resp.StatusCode)) + } + return nil } diff --git a/modules/paste/method.go b/modules/paste/method.go index fe4f596..d3f0832 100644 --- a/modules/paste/method.go +++ b/modules/paste/method.go @@ -24,6 +24,7 @@ func runPaste(ctx *cli.Context) error { // check stdMethod := utility.StdInChecker() sysInfoMethod := ctx.Bool("sysinfo") + pasteBinGoTo := ctx.String("pastebin") // Check sysinfo is enabled and run through all the required stuff if sysInfoMethod { @@ -60,9 +61,12 @@ func runPaste(ctx *cli.Context) error { // Check that PasteData is text, and not binary // fmt.Println("You cannot upload binary data.") - //fmt.Println(PasteData) - - Rpaste(ctx.String("life"), ctx.String("type"), PasteData) + switch pasteBinGoTo { + case "rpaste": + Rpaste(ctx.String("life"), ctx.String("type"), PasteData) + case "fpaste": + Fpaste(ctx.String("life"), ctx.String("type"), PasteData) + } return nil } diff --git a/modules/paste/rpaste.go b/modules/paste/rpaste.go index 4b9037d..2525f25 100644 --- a/modules/paste/rpaste.go +++ b/modules/paste/rpaste.go @@ -16,9 +16,12 @@ var ( "1day": "1day", "1week": "1week", } + baseURL = "https://rpa.st" + rpasteURL = "https://rpa.st/api/v1/paste" ) func Rpaste(life string, lexer string, fileContent string) error { + // Payload to be pushed into json payload := map[string]interface{}{ "expiry": rpasteTimeMap[life], "files": []map[string]string{ @@ -36,13 +39,15 @@ func Rpaste(life string, lexer string, fileContent string) error { os.Exit(1) } + // Push in the paste fmt.Println("Uploading...") - resp, err := http.Post("https://rpa.st/api/v1/paste", "application/json", bytes.NewBuffer(payloadJson)) + resp, err := http.Post(rpasteURL, "application/json", bytes.NewBuffer(payloadJson)) if err != nil { - fmt.Println("Could not contact rpaste endpoint (https://rpa.st/api/v1)") + fmt.Printf("Could not contact rpaste endpoint (%s)\n", rpasteURL) os.Exit(1) } + // Response is in json var response map[string]interface{} if resp.StatusCode == 200 { json.NewDecoder(resp.Body).Decode(&response) @@ -51,7 +56,7 @@ func Rpaste(life string, lexer string, fileContent string) error { slug := ss[len(ss)-1] fmt.Printf("Paste URL: %s\n", response["link"]) - fmt.Printf("Raw URL: https://rpa.st/raw/%s\n", slug) + fmt.Printf("Raw URL: %s/raw/%s\n", baseURL, slug) fmt.Printf("Removal URL: %s\n", response["removal"]) } else { json.NewDecoder(resp.Body).Decode(&response) diff --git a/modules/utility/system.go b/modules/utility/system.go index c5398ae..23569dd 100644 --- a/modules/utility/system.go +++ b/modules/utility/system.go @@ -21,6 +21,7 @@ var ( VendorName string SystemVersion string SystemPrettyName string + pasteBin string ) func SetPasteOnOS() string { @@ -36,15 +37,15 @@ func SetPasteOnOS() string { } } - // default is set to rpaste elsewhere + // The order should be: config -> this switch VendorName { case "rocky": - return "rpaste" - //setting.PasteBinService = "rpaste" + pasteBin = "rpaste" case "redhat", "fedora", "centos", "almalinux", "scientific": - return "fpaste" - //setting.PasteBinService = "fpaste" + pasteBin = "fpaste" + default: + pasteBin = "rpaste" } - return "rpaste" + return pasteBin } diff --git a/rpaste.go b/rpaste.go index 3b97525..be13891 100644 --- a/rpaste.go +++ b/rpaste.go @@ -36,6 +36,7 @@ func init() { setting.LifeTime = DefaultLifeTime setting.PasteBinService = DefaultPasteBin setting.SysInfo = DefaultSysInfo + // read config? } func main() { @@ -57,8 +58,11 @@ func main() { It can collect system information and forward it to a pastebin or simply send regular text files. This utility is primarily used for asking for assistance in the Rocky Linux community support venue. It can also be used on -other systems like Fedora and other Enterprise Linux distributions.`, - // list all commands below +other systems like Fedora and other Enterprise Linux distributions. + +See rpaste(1)`, + // list all commands below - For now it's only the method to paste, which + // isn't callable, it's the default. The flags dictate what happens next. Commands: []*cli.Command{ paste.PasteMethod, }, @@ -68,6 +72,8 @@ other systems like Fedora and other Enterprise Linux distributions.`, cli.AppHelpTemplate = setting.HelpTemplate cli.VersionPrinter = setting.VersionTemplate + // Supported flags - This controls the life, syntax, or paste bin that it + // the data is sent to. It also allows running a full sysinfo call. defaultFlags := []cli.Flag{ &cli.StringFlag{ Name: "life", @@ -90,6 +96,13 @@ other systems like Fedora and other Enterprise Linux distributions.`, Usage: "Collects general system information (disables stdin and file input)", Required: false, }, + &cli.StringFlag{ + Name: "pastebin", + Aliases: []string{"p"}, + Value: setting.PasteBinService, + Usage: "Sets the paste bin service to send to", + Required: false, + }, } // append the default flags to both the main and paste method