diff --git a/const.go b/const.go
index 0e97420b100fe027047fb424a6d6f1dd9929fb38..7194bef591fca588c10cbfd74064699721630841 100644
--- a/const.go
+++ b/const.go
@@ -18,6 +18,7 @@ package federation
//
const (
+ TIME_FORMAT = "2006-01-02T15:04:05Z"
XMLNS = "https://joindiaspora.com/protocol"
XMLNS_ME = "http://salmon-protocol.org/ns/magic-env"
APPLICATION_XML = "application/xml"
@@ -36,8 +37,4 @@ const (
// webfinger
WebFingerOstatus = "http://ostatus.org/schema/1.0/subscribe"
WebFingerHcard = "http://microformats.org/profile/hcard"
-
- // signature types
- AuthorSignatureType = iota
- ParentAuthorSignatureType
)
diff --git a/encryption.go b/encryption.go
index cb8c52ce4940eba8f3458830ea0232a0c0916e05..a4c0f9c4b7e33413f0d4232b56b36f2e382fcadd 100644
--- a/encryption.go
+++ b/encryption.go
@@ -78,6 +78,8 @@ func AuthorSignature(data interface{}, order string, privKey []byte) (string, er
if tag == o {
value := v.Field(i).Interface()
switch v := value.(type) {
+ case Time:
+ text += v.Format(TIME_FORMAT) + ";"
case string:
text += v + ";"
case bool:
diff --git a/entities.go b/entities.go
index b952c1c9352f8daefa1f2359da96096311d02a0a..24a76b6ab7df2c98f2749e897319ae77a1200631 100644
--- a/entities.go
+++ b/entities.go
@@ -20,6 +20,7 @@ package federation
import (
"errors"
"encoding/xml"
+ "time"
)
type Message struct {
@@ -49,6 +50,26 @@ type Entity struct {
Data interface{} `xml:"-"`
}
+type Time struct {
+ time.Time
+}
+
+func (t *Time) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ e.EncodeElement(t.Format(TIME_FORMAT), start)
+ return nil
+}
+
+func (t *Time) UnmarshalXML(decoder *xml.Decoder, start xml.StartElement) error {
+ var value string
+ decoder.DecodeElement(&value, &start)
+ parse, err := time.Parse(TIME_FORMAT, value)
+ if err != nil {
+ return err
+ }
+ *t = Time{parse}
+ return nil
+}
+
func (e *Entity) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// NOTE since the encoder ignores the interface type
// (see https://golang.org/src/encoding/xml/read.go#L377)
@@ -69,14 +90,19 @@ func (e *Entity) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
(*e).Type = local
(*e).Data = content
case StatusMessage:
- fallthrough
- case Reshare:
content := EntityStatusMessage{}
if err := d.DecodeElement(&content, &start); err != nil {
return err
}
(*e).Type = local
(*e).Data = content
+ case Reshare:
+ content := EntityReshare{}
+ if err := d.DecodeElement(&content, &start); err != nil {
+ return err
+ }
+ (*e).Type = local
+ (*e).Data = content
case Comment:
content := EntityComment{}
if err := d.DecodeElement(&content, &start); err != nil {
diff --git a/entities_test.go b/entities_test.go
index 6c6848120f517c7bb3c6093991d3367ee1f202c4..87f5cfd513039d8cb2d994c52e4b55c40f750760 100644
--- a/entities_test.go
+++ b/entities_test.go
@@ -28,7 +28,7 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
var retractionRaw = []byte(``)
var profileRaw = []byte(``)
var statusMessageRaw = []byte(``)
- //var reshareRaw = []byte(``)
+ var reshareRaw = []byte(``)
var commentRaw = []byte(``)
var likeRaw = []byte(``)
var contactRaw = []byte(``)
@@ -41,6 +41,10 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
if data, ok := entity.Data.(EntityRetraction); !ok {
t.Errorf("Expected to be 'like', got %v", data)
}
+ err = xml.Unmarshal(retractionRaw[:len(retractionRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
err = xml.Unmarshal(profileRaw, &entity)
if err != nil {
@@ -49,6 +53,10 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
if data, ok := entity.Data.(EntityProfile); !ok {
t.Errorf("Expected to be 'profile', got %v", data)
}
+ err = xml.Unmarshal(profileRaw[:len(profileRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
err = xml.Unmarshal(statusMessageRaw, &entity)
if err != nil {
@@ -57,14 +65,22 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
if data, ok := entity.Data.(EntityStatusMessage); !ok {
t.Errorf("Expected to be 'status_message', got %v", data)
}
+ err = xml.Unmarshal(statusMessageRaw[:len(statusMessageRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
- //err = xml.Unmarshal(reshareRaw, &entity)
- //if err != nil {
- // t.Errorf("Some error occured while parsing: %v", err)
- //}
- //if data, ok := entity.Data.(EntityStatusMessage); !ok {
- // t.Errorf("Expected to be 'reshare', got %v", data)
- //}
+ err = xml.Unmarshal(reshareRaw, &entity)
+ if err != nil {
+ t.Errorf("Some error occured while parsing: %v", err)
+ }
+ if data, ok := entity.Data.(EntityReshare); !ok {
+ t.Errorf("Expected to be 'reshare', got %v", data)
+ }
+ err = xml.Unmarshal(reshareRaw[:len(reshareRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
err = xml.Unmarshal(commentRaw, &entity)
if err != nil {
@@ -73,6 +89,10 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
if data, ok := entity.Data.(EntityComment); !ok {
t.Errorf("Expected to be 'comment', got %v", data)
}
+ err = xml.Unmarshal(commentRaw[:len(commentRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
err = xml.Unmarshal(likeRaw, &entity)
if err != nil {
@@ -81,6 +101,10 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
if data, ok := entity.Data.(EntityLike); !ok {
t.Errorf("Expected to be 'like', got %v", data)
}
+ err = xml.Unmarshal(likeRaw[:len(likeRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
err = xml.Unmarshal(contactRaw, &entity)
if err != nil {
@@ -89,9 +113,46 @@ func TestEntitiesUnmarshalXML(t *testing.T) {
if data, ok := entity.Data.(EntityContact); !ok {
t.Errorf("Expected to be 'contact', got %v", data)
}
+ err = xml.Unmarshal(contactRaw[:len(contactRaw)-1], &entity)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
err = xml.Unmarshal(notSupportedRaw, &entity)
if err == nil {
t.Errorf("Expected an error, got nil")
}
}
+
+func TestEntitiesTimeMarshalAndUnmarshal(t *testing.T) {
+ // federation time format
+ // 2006-01-02T15:04:05Z
+ var time = "2018-01-19T01:32:23Z"
+ var rawXml = "";
+ var origTime = struct {
+ XMLName xml.Name `xml:"time"`
+ CreatedAt Time
+ }{}
+
+ err := xml.Unmarshal([]byte(rawXml), &origTime)
+ if err != nil {
+ t.Errorf("Some error occured while parsing: %v", err)
+ }
+ if origTime.CreatedAt.Time.Format(TIME_FORMAT) != time {
+ t.Errorf("Expected to be '%s', got '%s'",
+ origTime.CreatedAt.Time.Format(TIME_FORMAT))
+ }
+
+ result, err := xml.Marshal(origTime)
+ if err != nil {
+ t.Errorf("Some error occured while parsing: %v", err)
+ }
+ if string(result) != rawXml {
+ t.Errorf("Expected to be '%s', got '%s'", result, rawXml)
+ }
+
+ err = xml.Unmarshal([]byte(""), &origTime)
+ if err == nil {
+ t.Errorf("Expected an error, got nil")
+ }
+}
diff --git a/entity_comment.go b/entity_comment.go
index 3f9dae3c8fce58aa25d027058698f8447df9b7f4..f52556e33e6189886a537a6d1a9ec5453b99ef42 100644
--- a/entity_comment.go
+++ b/entity_comment.go
@@ -17,38 +17,28 @@ package federation
// along with this program. If not, see .
//
-import (
- "encoding/xml"
- "errors"
-)
+import "encoding/xml"
type EntityComment struct {
XMLName xml.Name `xml:"comment"`
Author string `xml:"author"`
- CreatedAt string `xml:"created_at"`
+ CreatedAt Time `xml:"created_at"`
Guid string `xml:"guid"`
ParentGuid string `xml:"parent_guid"`
Text string `xml:"text"`
AuthorSignature string `xml:"author_signature"`
- ParentAuthorSignature string `xml:"parent_author_signature"`
}
func (e *EntityComment) SignatureOrder() string {
return "author created_at guid parent_guid text"
}
-func (e *EntityComment) AppendSignature(privKey []byte, order string, typ int) error {
+func (e *EntityComment) AppendSignature(privKey []byte, order string) error {
signature, err := AuthorSignature(*e, order, privKey)
if err != nil {
return err
}
+ (*e).AuthorSignature = signature
- if AuthorSignatureType == typ {
- (*e).AuthorSignature = signature
- } else if ParentAuthorSignatureType == typ {
- (*e).ParentAuthorSignature = signature
- } else {
- return errors.New("Unsupported author signature type!")
- }
return nil
}
diff --git a/entity_comment_test.go b/entity_comment_test.go
index 81854280b6bcd69093f69f0ec993c0b5199014b7..a259b5bea725acb6b2eb9d6e01b80643ac7f327d 100644
--- a/entity_comment_test.go
+++ b/entity_comment_test.go
@@ -17,7 +17,10 @@ package federation
// along with this program. If not, see .
//
-import "testing"
+import (
+ "testing"
+ "time"
+)
func TestCommentSignatureOrder(t *testing.T) {
var comment EntityComment
@@ -31,8 +34,8 @@ func TestCommentSignatureOrder(t *testing.T) {
func TestCommentAppendSignature(t *testing.T) {
comment := EntityComment{
Author: "author@localhost",
- CreatedAt: "01.01.1970",
Guid: "1234",
+ CreatedAt: Time{time.Now()},
ParentGuid: "4321",
Text: "hello world",
}
@@ -41,12 +44,7 @@ func TestCommentAppendSignature(t *testing.T) {
t.Errorf("Expected to be empty, got %s", comment.AuthorSignature)
}
- if comment.ParentAuthorSignature != "" {
- t.Errorf("Expected to be empty, got %s", comment.AuthorSignature)
- }
-
- err := comment.AppendSignature(TEST_PRIV_KEY,
- comment.SignatureOrder(), AuthorSignatureType)
+ err := comment.AppendSignature(TEST_PRIV_KEY, comment.SignatureOrder())
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
@@ -55,13 +53,8 @@ func TestCommentAppendSignature(t *testing.T) {
t.Errorf("Expected signature, was empty")
}
- err = comment.AppendSignature(TEST_PRIV_KEY,
- comment.SignatureOrder(), ParentAuthorSignatureType)
+ err = comment.AppendSignature(TEST_PRIV_KEY, comment.SignatureOrder())
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
-
- if comment.ParentAuthorSignature == "" {
- t.Errorf("Expected signature, was empty")
- }
}
diff --git a/entity_like.go b/entity_like.go
index 3aa4fce3d113cfe86382568de779ad8215701bc1..d0b4fb724788d1f12a5962c6dc12854cc198cce3 100644
--- a/entity_like.go
+++ b/entity_like.go
@@ -17,38 +17,28 @@ package federation
// along with this program. If not, see .
//
-import (
- "encoding/xml"
- "errors"
-)
+import "encoding/xml"
type EntityLike struct {
XMLName xml.Name `xml:"like"`
Positive bool `xml:"positive"`
Guid string `xml:"guid"`
ParentGuid string `xml:"parent_guid"`
- TargetType string `xml:"parent_type"`
+ ParentType string `xml:"parent_type"`
Author string `xml:"author"`
AuthorSignature string `xml:"author_signature"`
- ParentAuthorSignature string `xml:"parent_author_signature"`
}
func (e *EntityLike) SignatureOrder() string {
- return "positive guid parent_guid target_type author"
+ return "positive guid parent_guid parent_type author"
}
-func (e *EntityLike) AppendSignature(privKey []byte, order string, typ int) error {
+func (e *EntityLike) AppendSignature(privKey []byte, order string) error {
signature, err := AuthorSignature(*e, order, privKey)
if err != nil {
return err
}
+ (*e).AuthorSignature = signature
- if AuthorSignatureType == typ {
- (*e).AuthorSignature = signature
- } else if ParentAuthorSignatureType == typ {
- (*e).ParentAuthorSignature = signature
- } else {
- return errors.New("Unsupported author signature type!")
- }
return nil
}
diff --git a/entity_like_test.go b/entity_like_test.go
index 3be04e53e2f55de4ab5bd0246256caa7728c1b65..5ba53a5d9740dfa9641d3090cdde29166f7bea8a 100644
--- a/entity_like_test.go
+++ b/entity_like_test.go
@@ -23,7 +23,7 @@ import "testing"
func TestLikeSignatureOrder(t *testing.T) {
var like EntityLike
- expected := "positive guid parent_guid target_type author"
+ expected := "positive guid parent_guid parent_type author"
if expected != like.SignatureOrder() {
t.Errorf("Expected to be %s, got %s", expected, like.SignatureOrder())
}
@@ -34,7 +34,7 @@ func TestLikeAppendSignature(t *testing.T) {
Positive: true,
Guid: "1234",
ParentGuid: "4321",
- TargetType: "Post",
+ ParentType: "Post",
Author: "author@localhost",
}
@@ -42,12 +42,7 @@ func TestLikeAppendSignature(t *testing.T) {
t.Errorf("Expected to be empty, got %s", like.AuthorSignature)
}
- if like.ParentAuthorSignature != "" {
- t.Errorf("Expected to be empty, got %s", like.AuthorSignature)
- }
-
- err := like.AppendSignature(TEST_PRIV_KEY,
- like.SignatureOrder(), AuthorSignatureType)
+ err := like.AppendSignature(TEST_PRIV_KEY, like.SignatureOrder())
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
@@ -56,13 +51,8 @@ func TestLikeAppendSignature(t *testing.T) {
t.Errorf("Expected signature, was empty")
}
- err = like.AppendSignature(TEST_PRIV_KEY,
- like.SignatureOrder(), ParentAuthorSignatureType)
+ err = like.AppendSignature(TEST_PRIV_KEY, like.SignatureOrder())
if err != nil {
t.Errorf("Some error occured while parsing: %v", err)
}
-
- if like.ParentAuthorSignature == "" {
- t.Errorf("Expected signature, was empty")
- }
}
diff --git a/entity_post.go b/entity_post.go
index 6e83db2d24d61d44b9b5e86133e21eb89da733da..dc8ec03f6270fe600e1fb2777d0d9163f2b243b2 100644
--- a/entity_post.go
+++ b/entity_post.go
@@ -17,32 +17,36 @@ package federation
// along with this program. If not, see .
//
-import (
- "time"
- "encoding/xml"
-)
+import "encoding/xml"
type EntityStatusMessage struct {
XMLName xml.Name `xml:"status_message"`
Author string `xml:"author"`
Guid string `xml:"guid"`
- CreatedAt time.Time `xml:"created_at"`
+ CreatedAt Time `xml:"created_at"`
ProviderName string `xml:"provider_display_name"`
Text string `xml:"text,omitempty"`
Photo *EntityPhotos `xml:"photo,omitempty"`
Location *EntityLocation `xml:"location,omitempty"`
Poll *EntityPoll `xml:"poll,omitempty"`
Public bool `xml:"public"`
- // on reshare
- RootHandle string `xml:"root_diaspora_id,omitempty"`
- RootGuid string `xml:"root_guid,omitempty"`
+ Event *EntityEvent `xml:"event,omitempty"`
+}
+
+type EntityReshare struct {
+ XMLName xml.Name `xml:"reshare"`
+ Author string `xml:"author"`
+ Guid string `xml:"guid"`
+ CreatedAt Time `xml:"created_at"`
+ RootAuthor string `xml:"root_author"`
+ RootGuid string `xml:"root_guid"`
}
type EntityPhoto struct {
Guid string `xml:"guid"`
Author string `xml:"author"`
Public bool `xml:"public"`
- CreatedAt time.Time `xml:"created_at"`
+ CreatedAt Time `xml:"created_at"`
RemotePhotoPath string `xml:"remote_photo_path"`
RemotePhotoName string `xml:"remote_photo_name"`
Text string `xml:"text"`
@@ -70,6 +74,14 @@ type EntityPollAnswer struct {
Answer string `xml:"answer"`
}
-type PollParticipation struct {
- PollAnswerGuid string `xml:"poll_answer_guid"`
+type EntityEvent struct {
+ Author string `xml:"author"`
+ Guid string `xml:"guid"`
+ Summary string `xml:"summary"`
+ Start Time `xml:"start"`
+ End Time `xml:"end"`
+ AllDay bool `xml:"all_day"`
+ Timezone string `xml:"timezone"`
+ Description string `xml:"description"`
+ Location *EntityLocation `xml:"location,omitempty"`
}
diff --git a/http_client_test.go b/http_client_test.go
index 8dca08510f4b0cf6993432fc5af6f3610a3a7a9b..eb3435a3aad29c19397513ecaec390ec320a67a1 100644
--- a/http_client_test.go
+++ b/http_client_test.go
@@ -27,9 +27,9 @@ import (
)
type Test struct {
- XMLName xml.Name `xml:"AB";json:"-"`
- A string `xml:"A";json:"A"`
- B string `xml:"B";json:"B"`
+ XMLName xml.Name `xml:"AB" json:"-"`
+ A string `xml:"A" json:"A"`
+ B string `xml:"B" json:"B"`
}
func TestPushToPrivate(t *testing.T) {