// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "bytes" "flag" "fmt" "image/png" "io" "log" "net/http" "net/http/httptest" "net/url" "os" "strings" "github.com/davecgh/go-spew/spew" "github.com/mattn/go-isatty" "github.com/stapelberg/qrbill" _ "net/http/pprof" ) func ifEmpty(form url.Values, key, alternative string) string { if len(form[key]) == 0 { return alternative } return form[key][0] } func qrchFromRequest(r *http.Request) *qrbill.QRCH { return &qrbill.QRCH{ CdtrInf: qrbill.QRCHCdtrInf{ IBAN: ifEmpty(r.Form, "criban", "CH0209000000870913543"), Cdtr: qrbill.Address{ AdrTp: qrbill.AddressType(ifEmpty(r.Form, "craddrtype", string(qrbill.AddressTypeStructured))), Name: ifEmpty(r.Form, "crname", "Legalize it!"), StrtNmOrAdrLine1: ifEmpty(r.Form, "craddr1", "Quellenstrasse"), BldgNbOrAdrLine2: ifEmpty(r.Form, "craddr2", "25"), PstCd: ifEmpty(r.Form, "crpost", "8005"), TwnNm: ifEmpty(r.Form, "crcity", "Zürich"), Ctry: ifEmpty(r.Form, "crcountry", "CH"), }, }, CcyAmt: qrbill.QRCHCcyAmt{ Amt: ifEmpty(r.Form, "amount", ""), Ccy: "CHF", }, UltmtDbtr: qrbill.Address{ AdrTp: qrbill.AddressType(ifEmpty(r.Form, "udaddrtype", string(qrbill.AddressTypeCombined))), Name: ifEmpty(r.Form, "udname", "Michael Stapelberg"), StrtNmOrAdrLine1: ifEmpty(r.Form, "udaddr1", "Stauffacherstr 42"), BldgNbOrAdrLine2: ifEmpty(r.Form, "udaddr2", "8004 Zürich"), PstCd: ifEmpty(r.Form, "udpost", ""), TwnNm: ifEmpty(r.Form, "udcity", ""), Ctry: ifEmpty(r.Form, "udcountry", "CH"), }, RmtInf: qrbill.QRCHRmtInf{ Tp: "NON", // Reference type Ref: "", // Reference AddInf: qrbill.QRCHRmtInfAddInf{ Ustrd: ifEmpty(r.Form, "message", "Spende 420"), }, }, } } // Overridden in api_gokrazy.go var defaultListenAddress = "localhost:9933" func logic() error { var listen = flag.String("listen", defaultListenAddress, "[host]:port to listen on") flag.Parse() mux := http.NewServeMux() mux.HandleFunc("/qr", func(w http.ResponseWriter, r *http.Request) { prefix := "[" + r.RemoteAddr + "]" format := r.FormValue("format") log.Printf("%s handling request for %s, format=%s", prefix, r.URL.Path, format) defer log.Printf("%s request completed (%s)", prefix, r.URL.Path) if format == "" { msg := fmt.Sprintf("no ?format= parameter specified. Try %s", "http://"+*listen+"/qr?format=html") log.Printf("%s %s", prefix, msg) http.Error(w, msg, http.StatusBadRequest) return } if format != "png" && format != "svg" && format != "pdf" && format != "txt" && format != "html" && format != "wv" && format != "eps" { msg := fmt.Sprintf("format (%q) must be one of png, svg, pdf, eps, txt or html", format) log.Printf("%s %s", prefix, msg) http.Error(w, msg, http.StatusBadRequest) return } if err := r.ParseForm(); err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } qrch := qrchFromRequest(r) bill, err := qrch.Encode() if err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } var b []byte switch format { case "png": code, err := bill.EncodeToImage() if err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } var buf bytes.Buffer if err := png.Encode(&buf, code); err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } b = buf.Bytes() w.Header().Add("Content-Type", "image/png") case "svg": var err error b, err = bill.EncodeToSVG() if err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "image/svg+xml") case "pdf": var err error b, err = bill.EncodeToPDF() if err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/pdf") case "eps": var err error b, err = bill.EncodeToEPS() if err != nil { log.Printf("%s %s", prefix, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "image/eps") w.Header().Add("Content-Disposition", `attachment; filename="qr.eps"`) case "txt": w.Header().Add("Content-Type", "text/plain; charset=utf-8") spew.Fdump(w, qrch.Validate()) case "html": debugHTML(w, r, prefix, qrch) case "wv": w.Header().Add("Content-Type", "text/html; charset=utf-8") r.URL.Path = "/qr" v := r.URL.Query() v.Set("format", "png") r.URL.RawQuery = v.Encode() fmt.Fprintf(w, `