package main import ( "fmt" "io/ioutil" "net" "net/url" "path" "strings" "time" ) var GopherTimeout time.Duration = time.Duration(settings.TimeOutSeconds) * time.Second func RetrieveGopher(u *url.URL) (string, error) { conn, err := net.DialTimeout("tcp", u.Host, time.Duration(settings.TimeOutSeconds) * time.Second) if err != nil { return ConvertErrorToHTML(50, "Unable to connect to host"), nil } gophertype := '1' send := "/" if len(u.Path) > 2 { send = u.Path[2:] gophertype = rune(u.Path[1]) } else if len(u.Path) == 2 { gophertype = rune(u.Path[1]) } if u.RawQuery != "" { send = send + "?" + u.RawQuery } _, err = conn.Write([]byte(send+"\n")) if err != nil { return ConvertErrorToHTML(50, "Unable to make request to host; connection closed"), nil } result, err := ioutil.ReadAll(conn) if err != nil { return ConvertErrorToHTML(50, "Unable to read response from host"), nil } return ParseGopherBody(string(result), u, gophertype) } func EditHTMLFile(html string) string { bodyStart := strings.Index(html, " -1 { html = html[bodyStart:] bodyStartEnd := strings.Index(html, ">") if bodyStartEnd > -1 { html = html[bodyStartEnd+1:] } } bodyEnd := strings.Index(html, "") if bodyEnd > -1 { html = html[:bodyEnd] } html = strings.ReplaceAll(html, "\n"), nil case '1': return ParseGopherMap(body), nil case '7': return RenderSearchForm("Search/query?", u) case 'g': return MakeImage(body, "image/gif"), nil case 'I': ft := strings.ToLower(path.Ext(u.Path)) mime := "image/jpeg" switch ft { case ".png": mime = "image/png" case ".tif", ".tiff": mime = "image/tiff" case ".bmp": mime = "image/bmp" case ".gif": mime = "image/gif" case ".ico": mime = "image/vnd.microsoft.icon" case ".webp": mime = "image/webp" } return MakeImage(body, mime), nil // Make this more robust/support png at least default: appCtrl.SaveFile(body) return "", fmt.Errorf("File Saved") } return "", nil } func ParseGopherMap(gophermap string) string { var out strings.Builder linkFormat := "%s
\n" urlLinkFormat := "%s
\n" splitMap := strings.Split(gophermap, "\n") for _, ln := range splitMap { ln = strings.TrimSpace(ln) lnSplit := strings.Split(ln, "\t") if len(lnSplit) < 4 { continue } gophertype := rune(lnSplit[0][0]) msg := " " if len(lnSplit[0]) > 1 { msg = lnSplit[0][1:] } // Once query support is added to the client remove '7' if gophertype == 't' || gophertype == '2' || gophertype == 'T' { continue } if gophertype == 'i' { out.WriteString(`
`)
			out.WriteString(msg)
			out.WriteString("
\n") } else { if strings.HasPrefix(strings.ToUpper(lnSplit[1]), "URL:") && len(lnSplit[1]) > 4 { out.WriteString(fmt.Sprintf(urlLinkFormat, lnSplit[1][4:], msg)) } else { out.WriteString(fmt.Sprintf(linkFormat, lnSplit[2], lnSplit[3], gophertype, lnSplit[1], gophertype, msg)) } } } return out.String() }