package main
import (
"bufio"
"fmt"
"html/template"
//"net/http"
// "net/http/cgi"
"os"
"os/exec"
"strings"
"time"
)
type Result struct {
Name string
Version string
URL string
Suite string
}
type ResultPage struct {
Query string
Release string
NumResults int
Time string
Results []Result
}
var resTempl = `
i | _) _| Err pkginfo.devuan.org 70
i __ \ | / _' | | __ \ | _ \ Err pkginfo.devuan.org 70
i | | < ( | | | | __| ( | Err pkginfo.devuan.org 70
i .__/ _|\_\ \__, | _| _| _| _| \___/ Err pkginfo.devuan.org 70
i _| |___/ Err pkginfo.devuan.org 70
i Err pkginfo.devuan.org 70
i Devuan Package information Err pkginfo.devuan.org 70
i Err pkginfo.devuan.org 70
i {{.NumResults}} results for "{{.Query}}" (in {{.Time}}) Err pkginfo.devuan.org 70
i -------------------------- Err pkginfo.devuan.org 70
{{range .Results}}
1 {{.Suite}}] {{.Name}}-{{.Version}} {{URL}} pkginfo.devuan.org 70
{{end}}
`
var releaseMap = map[string]string{
"jessie": "index_jessie.txt",
"ascii": "index_ascii.txt",
"beowulf": "index_beowulf.txt",
"ceres": "index_ceres.txt",
"experimental": "index_experimental.txt",
"any": "index.txt"}
func printError(errCode int, errMsg string) {
fmt.Printf("Status:%d %s\r\n", errCode, errMsg)
fmt.Printf("Content-Type: text/plain\r\n")
fmt.Printf("\r\n%s\r\n", errMsg)
}
func parseLines(s string) []Result {
results := make([]Result, 0, 10)
scanner := bufio.NewScanner(strings.NewReader(s))
for scanner.Scan() {
URL := scanner.Text()
URLParts := strings.Split(URL, "/")[1:]
pkgNameVer := strings.Split(URLParts[len(URLParts)-1], ".html")[0]
Name := strings.Split(pkgNameVer, "_")[0]
Version := strings.Split(pkgNameVer, "_")[1]
Suite := URLParts[2]
results = append(results, Result{URL: URL, Name: Name, Version: Version, Suite: Suite})
}
//fmt.Printf("len(results): %d\n", resSize)
return results
}
func pipeComands(commands []*exec.Cmd) ([]byte, error) {
for i, command := range commands[:len(commands)-1] {
out, err := command.StdoutPipe()
if err != nil {
return nil, err
}
command.Start()
commands[i+1].Stdin = out
}
final, err := commands[len(commands)-1].Output()
if err != nil {
return nil, err
}
return final, nil
}
func getResults() (ResultPage, error) {
var res ResultPage
var release string
searchQuery := os.Getenv("X_GOPHER_SEARCH")
if len(searchQuery) < 1 {
printError(503, fmt.Sprintf("Something went wrong in parsing query...\r\n"))
os.Exit(0)
}
res.Query = searchQuery
QueryTerms := strings.Split(res.Query, " ")
res.Release = "any"
fmt.Printf("QueryTerms: %s\n", QueryTerms)
startTime := time.Now()
commands := make([]*exec.Cmd, 0)
cmd := "grep"
args := []string{QueryTerms[0], releaseMap[release]}
commands = append(commands, exec.Command(cmd, args...))
for _, word := range QueryTerms[1:] {
args = []string{word}
fmt.Printf("word: %s\r\n", word)
commands = append(commands, exec.Command(cmd, args...))
}
//if cmdOut, err := exec.Command(cmd, args...).Output(); err != nil {
if cmdOut, err := pipeComands(commands); err != nil {
fmt.Printf("error executing command: %s %s", commands, err)
res.Time = fmt.Sprintf("%s", time.Since(startTime))
return res, nil
} else {
res.Results = parseLines(string(cmdOut[:len(cmdOut)]))
res.NumResults = len(res.Results)
res.Time = fmt.Sprintf("%s", time.Since(startTime))
}
return res, nil
}
func printResults(results ResultPage) {
t, err := template.New("webpage").Parse(resTempl)
if err != nil {
printError(502, "Something went wrong...")
return
}
//fmt.Printf("Status: 200 OK\r\n")
//fmt.Printf("Content-Type: text/html\r\n")
t.Execute(os.Stdout, results)
}
func main() {
var err error
res, err := getResults()
if err != nil {
printError(404, fmt.Sprintf("%s", err))
} else {
printResults(res)
}
}