184 lines
3.6 KiB
Go
184 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"html/template"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"io"
|
|
"strings"
|
|
"bytes"
|
|
"errors"
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
type Config struct {
|
|
Port uint
|
|
SiteName string
|
|
}
|
|
|
|
type page struct {
|
|
Title string
|
|
}
|
|
|
|
type xmlDomain struct {
|
|
authority string
|
|
registryType string
|
|
entityClass string
|
|
entityName string
|
|
}
|
|
|
|
var C = Config{}
|
|
var db *sql.DB
|
|
|
|
func main() {
|
|
var err error
|
|
|
|
domain := "snuff.fi"
|
|
av, err := checkDomainAvailability(domain)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf("Domain '%s' available: %t\n", domain, av)
|
|
return
|
|
|
|
// Load config
|
|
fmt.Println("Loading config.json")
|
|
cfgfile, err := os.Open("config.json")
|
|
if err != nil {
|
|
log.Fatal("Error reading config.json!")
|
|
os.Exit(1)
|
|
}
|
|
defer cfgfile.Close()
|
|
|
|
decoder := json.NewDecoder(cfgfile)
|
|
//Config := Config{}
|
|
err = decoder.Decode(&C)
|
|
if err != nil {
|
|
log.Fatal("Can't decode config.json!")
|
|
os.Exit(1)
|
|
}
|
|
|
|
|
|
|
|
|
|
db, err = sql.Open("sqlite", "database.db")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Printf("Starting listener on :%v", C.Port)
|
|
http.Handle("/static/", http.FileServer(http.Dir("./")))
|
|
http.HandleFunc("/", httpRootHandler)
|
|
err = http.ListenAndServe(fmt.Sprintf(":%v", C.Port), nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
db.Close()
|
|
}
|
|
|
|
func httpRootHandler(w http.ResponseWriter, r *http.Request) {
|
|
t, _ := template.ParseFiles("index.html")
|
|
// var err := do_get_stuff()
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// http.Error(w, http.StatusText(500), 500)
|
|
// return
|
|
// }
|
|
|
|
|
|
|
|
var p page
|
|
p.Title = C.SiteName;
|
|
t.Execute(w, p)
|
|
}
|
|
|
|
func checkDomainAvailability(domain string) (bool, error) {
|
|
dasHost := "das.domain.fi";
|
|
dasPort := 715
|
|
dasAddr := fmt.Sprintf("%s:%d", dasHost, dasPort)
|
|
request := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
|
<iris1:request xmlns:iris1="urn:ietf:params:xml:ns:iris1">
|
|
<iris1:searchSet>
|
|
<iris1:lookupEntity registryType="dchk1" entityClass="domain-name" entityName="%s"/>
|
|
</iris1:searchSet>
|
|
</iris1:request>`, domain)
|
|
|
|
conn, err := net.Dial("udp", dasAddr)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return false, err
|
|
}
|
|
defer conn.Close()
|
|
|
|
fmt.Fprintf(conn, request)
|
|
response := make([]byte, 1024)
|
|
_, err = conn.Read(response)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
response = bytes.Trim(response, "\x00")
|
|
|
|
// Response can be:
|
|
// - active: already in use
|
|
// - available: go ahead and grab it while you can
|
|
// - invalid: malformed request: maybe check domain has .fi in the end
|
|
isAvailable, err := xmlCheckTag(string(response), "available")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return false, err
|
|
} else if isAvailable {
|
|
// Domain is available
|
|
return true, nil
|
|
}
|
|
|
|
isActive, err := xmlCheckTag(string(response), "active")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return false, err
|
|
} else if isActive {
|
|
// Domain is already registered taken
|
|
return false, nil
|
|
}
|
|
|
|
isInvalid, err := xmlCheckTag(string(response), "invalid")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return false, err
|
|
} else if isInvalid {
|
|
// We got bonked for our request
|
|
return false, errors.New("Request or domain invalid")
|
|
}
|
|
|
|
// Execution should not lead here but hey might as well error it out
|
|
return false, errors.New("Error: Status field not found")
|
|
}
|
|
|
|
func xmlCheckTag(src, tag string) (bool, error) {
|
|
// Thanks icza for your stackoverflow
|
|
// https://stackoverflow.com/a/51649834
|
|
decoder := xml.NewDecoder(strings.NewReader(src))
|
|
for {
|
|
t, err := decoder.Token()
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
if se, ok := t.(xml.StartElement); ok {
|
|
if se.Name.Local == tag {
|
|
return true, nil
|
|
}
|
|
}
|
|
}
|
|
}
|