Simple FI-domain availability checking
This commit is contained in:
commit
d40bfca474
8 changed files with 267 additions and 0 deletions
183
main.go
Normal file
183
main.go
Normal file
|
@ -0,0 +1,183 @@
|
|||
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)
|
||||
return
|
||||
}
|
||||
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!")
|
||||
return
|
||||
}
|
||||
defer cfgfile.Close()
|
||||
|
||||
decoder := json.NewDecoder(cfgfile)
|
||||
//Config := Config{}
|
||||
err = decoder.Decode(&C)
|
||||
if err != nil {
|
||||
log.Fatal("Can't decode config.json!")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
db, err = sql.Open("sqlite", "database.db")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue