···11+package randomart22+33+/*44+ * Draw an ASCII-Art representing the fingerprint so human brain can55+ * profit from its built-in pattern recognition ability.66+ * This technique is called "random art" and can be found in some77+ * scientific publications like this original paper:88+ *99+ * "Hash Visualization: a New Technique to improve Real-World Security",1010+ * Perrig A. and Song D., 1999, International Workshop on Cryptographic1111+ * Techniques and E-Commerce (CrypTEC '99)1212+ * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf1313+ *1414+ * The subject came up in a talk by Dan Kaminsky, too.1515+ *1616+ * If you see the picture is different, the key is different.1717+ * If the picture looks the same, you still know nothing.1818+ *1919+ * The algorithm used here is a worm crawling over a discrete plane,2020+ * leaving a trace (augmenting the field) everywhere it goes.2121+ * Movement is taken from dgst_raw 2bit-wise. Bumping into walls2222+ * makes the respective movement vector be ignored for this turn.2323+ * Graphs are not unambiguous, because circles in graphs can be2424+ * walked in either direction.2525+ */2626+2727+import (2828+ "os"2929+)3030+3131+func MAX(a, b int) int {3232+ if a > b {3333+ return a3434+ }3535+ return b3636+}3737+3838+func MIN(a, b int) int {3939+ if a < b {4040+ return a4141+ }4242+ return b4343+}4444+4545+/*4646+ * Field sizes for the random art. Have to be odd, so the starting point4747+ * can be in the exact middle of the picture, and FLDBASE should be >=8 .4848+ * Else pictures would be too dense, and drawing the frame would4949+ * fail, too, because the key type would not fit in anymore.5050+ */5151+const (5252+ FLDBASE = 85353+ FLDSIZE_Y = (FLDBASE + 1)5454+ FLDSIZE_X = (FLDBASE*2 + 1)5555+)5656+5757+func FromString(str string) string {5858+ ch := make(chan byte)5959+6060+ go func() {6161+ defer close(ch)6262+ for _, v := range []byte(str) {6363+ ch <- v6464+ }6565+ }()6666+ return key_fingerprint_randomart(ch)6767+}6868+6969+func FromFile(file *os.File) string {7070+ ch := make(chan byte)7171+7272+ go func() {7373+ defer close(ch)7474+ // TODO make input a 1 element byte array7575+ input := make([]byte, 1)7676+ nread, err := file.Read(input)7777+ for err == nil && nread > 0 {7878+ ch <- input[0]7979+ nread, err = file.Read(input)8080+ }8181+ }()8282+ return key_fingerprint_randomart(ch)8383+}8484+8585+func key_fingerprint_randomart(ch chan byte) string {8686+ /*8787+ * Chars to be used after each other every time the worm8888+ * intersects with itself. Matter of taste.8989+ */9090+ augment_string := " .o+=*BOX@%&#/^SE"9191+ var field [FLDSIZE_X][FLDSIZE_Y]byte9292+ len_aug := len(augment_string) - 19393+ var retval [(FLDSIZE_X + 3) * (FLDSIZE_Y + 2)]byte9494+9595+ /* initialize field */9696+ x := FLDSIZE_X / 29797+ y := FLDSIZE_Y / 29898+9999+ /* process raw key */100100+ for input, ok := <-ch; ok; input, ok = <-ch {101101+ /* each byte conveys four 2-bit move commands */102102+ for b := 0; b < 4; b++ {103103+ /* evaluate 2 bit, rest is shifted later */104104+ if input&0x1 > 0 {105105+ x += 1106106+ } else {107107+ x += -1108108+ }109109+110110+ if input&0x2 > 0 {111111+ y++112112+ } else {113113+ y--114114+ }115115+116116+ /* assure we are still in bounds */117117+ x = MAX(x, 0)118118+ y = MAX(y, 0)119119+ x = MIN(x, FLDSIZE_X-1)120120+ y = MIN(y, FLDSIZE_Y-1)121121+122122+ /* augment the field */123123+ if int(field[x][y]) < len_aug-2 {124124+ field[x][y]++125125+ }126126+ input = input >> 2127127+ }128128+ }129129+130130+ /* mark starting point and end point*/131131+ field[FLDSIZE_X/2][FLDSIZE_Y/2] = byte(len_aug - 1)132132+ field[x][y] = byte(len_aug)133133+134134+ i := 0135135+ retval[i] = '+'136136+ i++137137+138138+ /* output upper border */139139+ for x := 0; x < FLDSIZE_X; x++ {140140+ retval[i] = '-'141141+ i++142142+ }143143+ retval[i] = '+'144144+ i++145145+ retval[i] = '\n'146146+ i++147147+148148+ /* output content */149149+ for y := 0; y < FLDSIZE_Y; y++ {150150+ retval[i] = '|'151151+ i++152152+ for x := 0; x < FLDSIZE_X; x++ {153153+ retval[i] = augment_string[MIN(int(field[x][y]), len_aug)]154154+ i++155155+ }156156+ retval[i] = '|'157157+ i++158158+ retval[i] = '\n'159159+ i++160160+ }161161+162162+ /* output lower border */163163+ retval[i] = '+'164164+ i++165165+ for j := 0; j < FLDSIZE_X; j++ {166166+ retval[i] = '-'167167+ i++168168+ }169169+ retval[i] = '+'170170+ i++171171+172172+ return string(retval[0:i])173173+}
+42-13
appview/state/repo.go
···3535 log.Println("failed to fully resolve repo", err)3636 return3737 }3838- protocol := "http"3939- if !s.config.Dev {4040- protocol = "https"3838+3939+ us, err := NewUnsignedClient(f.Knot, s.config.Dev)4040+ if err != nil {4141+ log.Printf("failed to create unsigned client for %s", f.Knot)4242+ s.pages.Error503(w)4343+ return4144 }42454343- var reqUrl string4444- if ref != "" {4545- reqUrl = fmt.Sprintf("%s://%s/%s/%s/tree/%s", protocol, f.Knot, f.OwnerDid(), f.RepoName, ref)4646- } else {4747- reqUrl = fmt.Sprintf("%s://%s/%s/%s", protocol, f.Knot, f.OwnerDid(), f.RepoName)4848- }4949-5050- resp, err := http.Get(reqUrl)4646+ resp, err := us.Index(f.OwnerDid(), f.RepoName, ref)5147 if err != nil {5248 s.pages.Error503(w)5349 log.Println("failed to reach knotserver", err)···299303300304 switch r.Method {301305 case http.MethodGet:306306+ us, err := NewUnsignedClient(f.Knot, s.config.Dev)307307+ if err != nil {308308+ log.Printf("failed to create unsigned client for %s", f.Knot)309309+ s.pages.Error503(w)310310+ return311311+ }312312+313313+ resp, err := us.Branches(f.OwnerDid(), f.RepoName)314314+ if err != nil {315315+ log.Println("failed to reach knotserver", err)316316+ return317317+ }318318+319319+ body, err := io.ReadAll(resp.Body)320320+ if err != nil {321321+ log.Printf("Error reading response body: %v", err)322322+ return323323+ }324324+325325+ var result types.RepoBranchesResponse326326+ err = json.Unmarshal(body, &result)327327+ if err != nil {328328+ log.Println("failed to parse response:", err)329329+ return330330+ }331331+302332 s.pages.RepoNewPull(w, pages.RepoNewPullParams{303333 LoggedInUser: user,304334 RepoInfo: f.RepoInfo(s, user),335335+ Branches: result.Branches,305336 })306337 case http.MethodPost:307338 title := r.FormValue("title")···370347 return371348 }372349 client, _ := s.auth.AuthorizedClient(r)373373- pullId, err := db.GetPullId(s.db, f.RepoAt)350350+ pullId, err := db.NextPullId(s.db, f.RepoAt)374351 if err != nil {375352 log.Println("failed to get pull id", err)376353 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.")···627604 return628605 }629606630630- resp, err := http.Get(fmt.Sprintf("http://%s/%s/%s/branches", f.Knot, f.OwnerDid(), f.RepoName))607607+ us, err := NewUnsignedClient(f.Knot, s.config.Dev)608608+ if err != nil {609609+ log.Println("failed to create unsigned client", err)610610+ return611611+ }612612+613613+ resp, err := us.Branches(f.OwnerDid(), f.RepoName)631614 if err != nil {632615 log.Println("failed to reach knotserver", err)633616 return