func getRequestType(req *http.Request) (int, sys.Id) { hostparts := strings.Split(req.Host, ".", -1) hostparts = misc.ReverseHost(hostparts) if len(hostparts) < 2 { return feWWWReq, 0 } if hostparts[0] != "org" || hostparts[1] != "5ttt" { return feWWWReq, 0 } hostparts = hostparts[2:] if len(hostparts) == 0 || hostparts[0] == "www" { // 5ttt.org, www.5ttt.org return feWWWReq, 0 } if hostparts[0] == "a" { return feAdminReq, 0 } id, err := sys.ParseId(hostparts[0]) if err != nil { return feWWWReq, 0 } hostparts = hostparts[1:] if len(hostparts) == 0 { // xxxxxxxxx.5ttt.org return feTonikaReq, id } if hostparts[0] == "a" { // a.xxxxxxxxx.5ttt.org return feAdminReq, id } return feBadReq, 0 }
func parseURL(req *http.Request) (tid sys.Id, path, query string, err os.Error) { hostparts := strings.Split(req.Host, ".", -1) hostparts = misc.ReverseHost(hostparts) if len(hostparts) != 3 || hostparts[0] != sys.Host0 || hostparts[1] != sys.Host1 { return 0, "", "", os.EINVAL } tid, err = sys.ParseId(hostparts[2]) if err != nil { return 0, "", "", os.EINVAL } query = req.URL.RawQuery path = gopath.Clean(req.URL.Path) return tid, path, query, nil }
func ReadFriendDb(path string) (*buttress, os.Error) { // Read contents bytes, err := ioutil.ReadFile(path) if err != nil { log.Stderrf("Cannot read from friends file \"%s\"\n", path) return nil, &Error{ErrLoad, err} } // Unmarshal json book := jsonDb{} if err := json.Unmarshal(bytes, &book); err != nil { log.Stderrf("Error decoding friends file [%s] json. "+ "Offending token [%s].\n", path, err) return nil, &Error{ErrDecode, err} } db := &buttress{me: &sys.Me{}, recs: make(map[int]*friend), path: path} // Deep parse me-data db.me = &sys.Me{ Name: book.Me.Name, Addr: book.Me.Addr, ExtAddr: book.Me.ExtAddr, Email: book.Me.Email, } id, err := sys.ParseId(book.Me.Id) if err != nil { log.Stderrf("Error [%v] decoding my ID [%s]\n", err, book.Me.Id) return nil, &Error{ErrDecode, book.Me.Id} } db.me.Id = id pk, err := sys.ParseSigKey(book.Me.SigKey) if err != nil { log.Stderrf("Error [%v] decoding my signature key [%s]\n", err, book.Me.SigKey) return nil, &Error{ErrDecode, book.Me.SigKey} } db.me.SignatureKey = pk // Deep parse friends if book.Friends != nil { for i := 0; i < len(book.Friends); i++ { // slot slot, err := strconv.Atoi(book.Friends[i].Slot) if err != nil || slot < 0 { log.Stderrf("db, invalid slot number, skipping friends") continue } // id id1, err := sys.ParseId(book.Friends[i].Id) var id *sys.Id if err == nil { id = &id1 } // dial key dkey, _ := sys.ParseDialKey(book.Friends[i].DialKey) // accept key akey, _ := sys.ParseDialKey(book.Friends[i].AcceptKey) // sig key sigk, err := sys.ParseSigPubKey(book.Friends[i].SigKey) // hello key hellok, err := sys.ParseHelloKey(book.Friends[i].HelloKey) // make fr := &friend{ Friend: sys.Friend{ Slot: slot, Id: id, SignatureKey: sigk, HelloKey: hellok, DialKey: dkey, AcceptKey: akey, Name: book.Friends[i].Name, Email: book.Friends[i].Email, Addr: book.Friends[i].Addr, Rest: book.Friends[i].Rest, }, online: false, } _, present := db.recs[fr.Slot] if present { log.Stderrf("Duplicate friend, using latest\n") } db.recs[fr.Slot] = fr } // for } return db, nil }
func (s *Server) serve(q *http.Query) { q.Continue() req := q.GetRequest() if req.Body != nil { req.Body.Close() } s.log(req, q.RemoteAddr()) // Path cleanup path := path.Clean(req.URL.Path) if path == "" { path = "/" } // Host analysis hostport := strings.Split(req.Host, ":", 2) if len(hostport) == 0 { q.Write(newRespBadRequest()) return } hostparts := misc.ReverseHost(strings.Split(hostport[0], ".", -1)) // http://5ttt.org, http://www.5ttt.org if len(hostparts) < 3 || hostparts[2] == "www" { if path == "/" { path = "/index.html" } if isIndex(path) { s.lk.Lock() s.stats.Views++ s.lk.Unlock() } var resp *http.Response if isIndex(path) { resp = s.replyIndex() } else { resp = s.replyStatic(path) } if isDownload(path) && resp.Body != nil { resp.Body = http.NewRunOnClose(resp.Body, func() { // TODO: This also counts incomplete downloads, but for now // it's fine. s.lk.Lock() s.stats.Downloads++ s.lk.Unlock() }) } q.Write(resp) return } // Remove 5ttt.org from host hostparts = hostparts[2:] // http://*.a.5ttt.org/* if hostparts[0] == "a" { q.Write(s.replyStatic("/tadmin.html")) // Trying to access a Tonika Admin return } // http://*.[id].5ttt.org if _, err := sys.ParseId(hostparts[0]); err == nil { q.Write(s.replyStatic("/turl.html")) // Trying to access a Tonika URL return } // Otherwise q.Write(newRespNotFound()) }