You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

102 lines
2.4 KiB

package burnpaste
import (
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"golang.org/x/net/proxy"
)
func isOnion(someURL string) (bool, error) {
parsedURL, err := url.Parse(someURL)
if err != nil {
return true, err
}
urlParts := strings.Split(parsedURL.Host, ".")
tld := urlParts[len(urlParts)-1]
if tld == "onion" {
return true, err
} else {
return false, err
}
}
func Hash(data []byte) string {
hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:])
}
func onionHTTP() (client *http.Client, err error) {
torProxyURL, err := url.Parse("socks5://127.0.0.1:9050")
if err != nil {
return
}
torDialer, err := proxy.FromURL(torProxyURL, proxy.Direct)
if err != nil {
return
}
torTransport := &http.Transport{Dial: torDialer.Dial}
client = &http.Client{Transport: torTransport}
return
}
func clearnetOrOnionHTTP(url string) (client *http.Client, err error) {
// Returns a http.Client using a local Tor SOCKS proxy if .onion,
// plain old http.Client if not.
reallyIsOnion, err := isOnion(url)
if err != nil {
return
}
if reallyIsOnion {
client, err = onionHTTP()
} else {
client = &http.Client{}
}
return
}
func Write(endpoint string, paste []byte) (string, error) {
var burnpasteURL string
var err error
hash := Hash(paste)
ourURL := endpoint + "write"
ourHTTP, err := clearnetOrOnionHTTP(ourURL)
response, err := ourHTTP.PostForm(ourURL, url.Values{"data": {string(paste)}})
if err != nil {
return burnpasteURL, err
}
defer response.Body.Close()
// Returns just the hash in the response
body, err := ioutil.ReadAll(response.Body)
urlHash := string(body)
if urlHash != hash {
errorMsg := fmt.Sprintf("Hash mismatch. Ours: %s Theirs: %s", hash, urlHash)
return "", errors.New(errorMsg)
}
burnpasteURL = endpoint + "read/" + hash
return burnpasteURL, err
}
func Read(burnpasteURL string) ([]byte, error) {
urlParts := strings.Split(burnpasteURL, "/")
urlHash := urlParts[len(urlParts)-1]
ourHTTP, err := clearnetOrOnionHTTP(burnpasteURL)
response, err := ourHTTP.Get(burnpasteURL)
if err != nil {
return []byte(""), err
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
hash := Hash(body)
if hash != urlHash {
errorMsg := fmt.Sprintf("Returned hash %s does not match URL hash %s.", hash, urlHash)
return []byte(""), errors.New(errorMsg)
}
return body, err
}