-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfpasteCL.go
153 lines (144 loc) · 4.07 KB
/
fpasteCL.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
getopt "code.google.com/p/getopt"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
http "net/http"
url "net/url"
"os"
"strconv"
"time"
)
const FPASTE_URL = "http://fpaste.org"
func main() {
opts := initConfig(os.Args)
if *opts.help {
getopt.PrintUsage(os.Stdout)
} else {
/*Passing stdin for test mocking*/
files, errs := handleArgs(os.Stdin, getopt.CommandLine)
for _, file := range files {
if len(file) != 0 {
if err := copyPaste(file, opts); err != nil {
errs = append(errs, err)
}
}
}
for _, err := range errs {
log.Print(err)
}
if len(errs) > 0 {
os.Exit(-1)
}
}
}
type config struct {
help *bool
priv *bool
user *string
pass *string
lang *string
expire *string
}
func initConfig(args []string) *config {
getopt.CommandLine = getopt.New()
var flags config
flags.help = getopt.BoolLong("help", 'h', "Display this help")
flags.priv = getopt.BoolLong("private", 'P', "Private paste flag")
flags.user = getopt.StringLong("user", 'u', "", "An alphanumeric username of the paste author")
flags.pass = getopt.StringLong("pass", 'p', "", "Add a password")
flags.lang = getopt.StringLong("lang", 'l', "Text", "The development language used")
flags.expire = getopt.StringLong("expire", 'e', "0", "Seconds after which paste will be deleted from server")
getopt.SetParameters("[FILE...]")
getopt.CommandLine.Parse(args)
return &flags
}
func handleArgs(stdin io.Reader, commandLine *getopt.Set) (files [][]byte, errs []error) {
if commandLine.NArgs() > 0 {
for _, x := range commandLine.Args() {
file, err := os.Open(x)
if err != nil {
errs = append(errs, fmt.Errorf("Skipping [FILE: %s] since it cannot be opened (%s)", x, err))
continue
}
defer file.Close()
data, erread := ioutil.ReadAll(file)
if erread != nil {
errs = append(errs, fmt.Errorf("Skipping [FILE: %s] since it cannot be read (%s)", x, erread))
} else {
files = append(files, data)
}
}
} else {
data, erread := ioutil.ReadAll(stdin)
if erread != nil {
errs = append(errs, erread)
} else {
files = append(files, data)
}
}
return files, errs
}
/*
Handling API errors so we can know why the request did not went as expetected.
The resquest will not be resend to prevent the user from being banned.
*/
func handleAPIError(error string) error {
errorStr := make(map[string]string)
errorStr["err_nothing_to_do"] = "No POST request was received by the create API"
errorStr["err_author_numeric"] = "The paste author's alias should be alphanumeric"
errorStr["err_save_error"] = "An error occurred while saving the paste"
errorStr["err_spamguard_ipban"] = "Poster's IP address is banned"
errorStr["err_spamguard_stealth"] = "The paste triggered the spam filter"
errorStr["err_spamguard_noflood"] = "Poster is trying the flood"
errorStr["err_spamguard_php"] = "Poster's IP address is listed as malicious"
if err, ok := errorStr[error]; ok {
return fmt.Errorf("API error: %s", err)
}
return fmt.Errorf("API error: Unknown [%s]", error)
}
func copyPaste(src []byte, opts *config) error {
values := url.Values{
"paste_data": {string(src)},
"paste_lang": {*opts.lang},
"api_submit": {"true"},
"mode": {"json"},
"paste_user": {*opts.user},
"paste_password": {*opts.pass},
}
if duration, err := time.ParseDuration(*opts.expire); err != nil {
return err
} else if secs := duration.Seconds(); secs >= 1 {
values.Add("paste_expire", strconv.FormatFloat(secs, 'f', -1, 64))
}
if *opts.priv {
values.Add("paste_private", "yes")
}
resp, erreq := http.PostForm(FPASTE_URL, values)
if erreq != nil {
return erreq
}
defer resp.Body.Close()
type res struct {
Id string `json:"id"`
Hash string `json:"hash"`
Error string `json:"error"`
}
type pasteUrls struct {
Result res `json:"result"`
}
var m pasteUrls
slice, err := ioutil.ReadAll(resp.Body)
err = json.Unmarshal(slice, &m)
if err != nil {
return err
}
if m.Result.Error != "" {
return handleAPIError(m.Result.Error)
}
fmt.Fprintf(os.Stdout, "%s/%s/%s\n", FPASTE_URL, m.Result.Id, m.Result.Hash)
return nil
}