diff --git a/client.go b/client.go index aa5860b..382fa7e 100644 --- a/client.go +++ b/client.go @@ -10,6 +10,7 @@ import ( "io" "net" "os" + "strconv" "strings" "sync" "unicode" @@ -82,6 +83,8 @@ func (c *Client) handleMessage(m Envelope) error { switch m.Kind { case "meta": return c.handleMeta(m.Body) + case "note": + return c.handleNote(m.Body) default: return fmt.Errorf("received message of unsupported type: %v", m.Kind) } @@ -97,6 +100,24 @@ func (c *Client) handleMeta(body json.RawMessage) error { return nil } +func (c *Client) handleNote(body json.RawMessage) error { + var ctxt []byte + if err := json.Unmarshal(body, &ctxt); err != nil { + return fmt.Errorf("unable to read note response: %v", err) + } + ptxt, err := rsa.DecryptPKCS1v15(rand.Reader, c.key, ctxt) + if err != nil { + return fmt.Errorf("unable to decrypt note response: %v", err) + } + var note NoteData + if err := json.Unmarshal(ptxt, ¬e); err != nil { + return fmt.Errorf("unable to unmarshal note response: %v", err) + } + c.info("title: %s", note.Title) + c.info("body: %s", string(note.Body)) + return nil +} + func (c *Client) handshake() error { r := &Auth{Nick: c.nick, Key: c.key.PublicKey} c.info("authenticating as %s", c.nick) @@ -198,6 +219,8 @@ func (c *Client) exec(line string) { switch parts[0] { case "notes/create": c.createNote(parts[1:]) + case "notes/get": + c.getNote(parts[1:]) default: c.err("unrecognized client command: %s", parts[0]) } @@ -225,6 +248,22 @@ func (c *Client) createNote(args []string) { } } +func (c *Client) getNote(args []string) { + if len(args) != 1 { + c.err("ok notes/get takes exactly 1 argument") + return + } + id, err := strconv.Atoi(args[0]) + if err != nil { + c.err("that doesn't look like an int: %v", err) + return + } + if err := c.sendRequest(GetNoteRequest(id)); err != nil { + c.err("couldn't request note: %v", err) + return + } +} + func (c *Client) encryptNote(title string, note []rune) (NoteRequest, error) { obj := &NoteData{ Title: title, diff --git a/note.go b/note.go index d656ce6..60d7dd2 100644 --- a/note.go +++ b/note.go @@ -8,6 +8,12 @@ func (n NoteRequest) Kind() string { return "note" } +type GetNoteRequest int + +func (g GetNoteRequest) Kind() string { + return "get-note" +} + type NoteData struct { Title string Body []byte diff --git a/server.go b/server.go index 5650dd9..529f663 100644 --- a/server.go +++ b/server.go @@ -53,6 +53,8 @@ func (s *serverConnection) handleRequest(request Envelope) error { return s.handleAuthRequest(request.Body) case "note": return s.handleNoteRequest(request.Body) + case "get-note": + return s.handleGetNoteRequest(request.Body) default: return fmt.Errorf("no such request type: %v", request.Kind) } @@ -78,6 +80,11 @@ func (s *serverConnection) handleNoteRequest(body json.RawMessage) error { it := s.db.NewIterator(r, nil) defer it.Release() + var ctxt []byte + if err := json.Unmarshal(body, &ctxt); err != nil { + return fmt.Errorf("unable to unmarshal ciphertext: %v", err) + } + id := 0 if it.Last() { k := it.Key() @@ -89,13 +96,29 @@ func (s *serverConnection) handleNoteRequest(body json.RawMessage) error { id = lastId + 1 } key := fmt.Sprintf("notes/%d", id) - if err := s.db.Put([]byte(key), body, nil); err != nil { + if err := s.db.Put([]byte(key), ctxt, nil); err != nil { return fmt.Errorf("unable to write note to db: %v", err) } info_log.Printf("stored new note at %s", key) return nil } +func (s *serverConnection) handleGetNoteRequest(body json.RawMessage) error { + var req GetNoteRequest + if err := json.Unmarshal(body, &req); err != nil { + return fmt.Errorf("bad getnote request: %v", err) + } + key := fmt.Sprintf("notes/%d", req) + b, err := s.db.Get([]byte(key), nil) + if err != nil { + return fmt.Errorf("couldn't retrieve note: %v", err) + } + if err := s.sendRequest(NoteRequest(b)); err != nil { + return fmt.Errorf("couldn't send note back to client: %v", err) + } + return nil +} + func (s *serverConnection) openDB() error { path := fmt.Sprintf("./%s.db", s.nick) db, err := leveldb.OpenFile(path, nil)