148 lines
2.9 KiB
Go
148 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/url"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// SpartanURL parses u and calls SpartanParsedURL with the parsed url
|
|
func SpartanURL(u, input string) bool {
|
|
parsed, err := url.Parse(u)
|
|
if err != nil {
|
|
fmt.Println("invalid url")
|
|
fmt.Println(err.Error())
|
|
return false
|
|
}
|
|
if parsed.Host == "" {
|
|
parsed, err = url.Parse("spartan://" + u)
|
|
// this is repeated, ugh!
|
|
if err != nil {
|
|
fmt.Println("invalid url")
|
|
fmt.Println(err.Error())
|
|
return false
|
|
}
|
|
}
|
|
if parsed.Scheme != "spartan" {
|
|
fmt.Println("Unsupported scheme")
|
|
return false
|
|
}
|
|
return SpartanParsedURL(parsed, input)
|
|
}
|
|
|
|
// SpartanParsedURL fetches u and displays the page
|
|
func SpartanParsedURL(u *url.URL, input string) bool {
|
|
host := u.Host
|
|
if u.Port() == "" {
|
|
host += ":300"
|
|
}
|
|
// Connect to server
|
|
conn, err := net.Dial("tcp", host)
|
|
if err != nil {
|
|
fmt.Println("unable to connect to " + u.Host)
|
|
fmt.Println(err.Error())
|
|
return false
|
|
}
|
|
defer conn.Close()
|
|
// Send request
|
|
path := u.Path
|
|
if u.Path == "" {
|
|
path = "/"
|
|
}
|
|
conn.Write([]byte(fmt.Sprintf("%s %s %d\r\n", u.Hostname(), path, len(input))))
|
|
conn.Write([]byte(input))
|
|
// Receive and parse response header
|
|
reader := bufio.NewReader(conn)
|
|
header, err := reader.ReadString(byte('\n'))
|
|
if err != nil {
|
|
fmt.Println("Error reading response header")
|
|
return false
|
|
}
|
|
// Parse header
|
|
statusParts := strings.SplitN(header, " ", 2)
|
|
status, err := strconv.Atoi(statusParts[0])
|
|
if err != nil {
|
|
fmt.Println("invalid status code:" + statusParts[0])
|
|
return false
|
|
}
|
|
meta := strings.Trim(statusParts[1], "\r\n")
|
|
|
|
// Handle status
|
|
switch status {
|
|
case 1:
|
|
fmt.Println("[INPUT]")
|
|
fmt.Println(meta)
|
|
case 2:
|
|
// TODO: handle mime type
|
|
bodyBytes, err := ioutil.ReadAll(reader)
|
|
if err != nil {
|
|
fmt.Println("Error reading body")
|
|
return false
|
|
}
|
|
body := string(bodyBytes)
|
|
fmt.Print(body)
|
|
case 3:
|
|
SpartanURL("spartan://"+host+meta, "")
|
|
case 4:
|
|
fmt.Println("Error: " + meta)
|
|
case 5:
|
|
fmt.Println("Server error: " + meta)
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func Usage() {
|
|
fmt.Fprintln(os.Stderr, `
|
|
Usage: sparte [--help] [URL] [-i INPUT] [-f FILE]
|
|
|
|
--help usage
|
|
-i send INPUT to URL
|
|
-f send contents of FILE as input to UR
|
|
|
|
`)
|
|
return
|
|
}
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
if len(args) == 0 {
|
|
Usage()
|
|
return
|
|
}
|
|
url := args[0]
|
|
input := ""
|
|
for i, arg := range args {
|
|
if arg == "--help" {
|
|
Usage()
|
|
return
|
|
}
|
|
if arg == "-i" || arg == "-f" {
|
|
if len(args) < i+2 || (i == 0 && len(args) < i+3) {
|
|
fmt.Println("input arument or URL missing")
|
|
return
|
|
}
|
|
url = args[i-1]
|
|
if arg == "-i" {
|
|
input = args[i+1]
|
|
break
|
|
}
|
|
// arg must be -f
|
|
inputBytes, err := ioutil.ReadFile(args[i+1])
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "Error reading file")
|
|
os.Exit(1)
|
|
}
|
|
input = string(inputBytes)
|
|
break
|
|
// ignoring other args if any
|
|
}
|
|
}
|
|
SpartanURL(url, input)
|
|
}
|