예제 #1
0
파일: reqtype.go 프로젝트: fedgrant/tonika
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
}
예제 #2
0
파일: httputil.go 프로젝트: fedgrant/tonika
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
}
예제 #3
0
파일: db.go 프로젝트: fedgrant/tonika
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
}
예제 #4
0
파일: server.go 프로젝트: fedgrant/tonika
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())
}