Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC2787 Add support for splitting UPK IDs #301

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.*.swp
coverage.out
2 changes: 1 addition & 1 deletion authchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"testing"

"github.com/matrix-org/gomatrixserverlib"
"github.com/brianathere/gomatrixserverlib"
)

// A basic sanity check of a linear sequence of common events
Expand Down
138 changes: 135 additions & 3 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"reflect"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -1111,14 +1112,106 @@ func (er EventReference) MarshalJSON() ([]byte, error) {
return json.Marshal(&tuple)
}

const UserIDSigil = '@'
const RoomAliasSigil = '#'
const RoomIDSigil = '!'
const EventIDSigil = '$'
const GroupIDSigil = '+'
const UserPermanentKeySigil = '~'

//const UserDelegatedKeySigil = '^'

func GetSupportedSigils() []rune {
return []rune{UserIDSigil, RoomAliasSigil, RoomIDSigil, EventIDSigil, GroupIDSigil, UserPermanentKeySigil /* , UserDelegatedKeySigil */}
}
func GetUserSigils() []rune {
return []rune{UserIDSigil, UserPermanentKeySigil /*, UserDelegatedKeySigil */}
}
func GetRoomSigils() []rune {
return []rune{RoomAliasSigil, RoomIDSigil}
}

var IsValidMXID = regexp.MustCompile(`^[a-z0-9\_\-\.\/\=]+$`).MatchString

// Deprecated: Replaced with SplitXXXID functions
// SplitID splits a matrix ID into a local part and a server name.
func SplitID(sigil byte, id string) (local string, domain ServerName, err error) {
func SplitID(unusedSigil byte, id string) (local string, domain ServerName, err error) {
if len(id) == 0 {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q", id)
}
// IDs have the format: SIGIL LOCALPART ":" DOMAIN
// Split on the first ":" character since the domain can contain ":"
// characters.
sigil := id[0]
if unusedSigil != sigil {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q doesn't start with %q", id, unusedSigil)
}
return splitIDWithSigil(id)
}

// SplitUserID splits a matrix User ID into a local part and a server name.
func SplitUserID(id string) (local string, domain ServerName, err error) {
if len(id) == 0 {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q", id)
}
// IDs have the format: SIGIL LOCALPART ":" DOMAIN
// Split on the first ":" character since the domain can contain ":"
// characters.
sigil := id[0]
if !(UserIDSigil == sigil || UserPermanentKeySigil == sigil /*|| UserDelegatedKeySigil == sigil */) {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q doesn't start with valid sigil %q", id, sigil)
}
return splitIDWithSigil(id)
}

// SplitRoomID splits a matrix RoomID into a local part and a server name.
func SplitRoomID(id string) (local string, domain ServerName, err error) {
if len(id) == 0 {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q", id)
}
// IDs have the format: SIGIL LOCALPART ":" DOMAIN
// Split on the first ":" character since the domain can contain ":"
// characters.
if len(id) == 0 || id[0] != sigil {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q doesn't start with %q", id, sigil)
sigil := id[0]
if !(RoomIDSigil == sigil || RoomAliasSigil == sigil) {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q doesn't start with valid sigil %q", id, sigil)
}
return splitIDWithSigil(id)
}

// SplitEventID splits a matrix EventID into a local part and a server name.
func SplitEventID(id string) (local string, domain ServerName, err error) {
if len(id) == 0 {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q", id)
}
// IDs have the format: SIGIL LOCALPART ":" DOMAIN
// Split on the first ":" character since the domain can contain ":"
// characters.
sigil := id[0]
if !(EventIDSigil == sigil) {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q doesn't start with valid sigil %q", id, sigil)
}
return splitIDWithSigil(id)
}

// SplitGroupID splits a matrix GroupID into a local part and a server name.
func SplitGroupID(id string) (local string, domain ServerName, err error) {
if len(id) == 0 {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q", id)
}
// IDs have the format: SIGIL LOCALPART ":" DOMAIN
// Split on the first ":" character since the domain can contain ":"
// characters.
sigil := id[0]
if !(GroupIDSigil == sigil) {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q doesn't start with valid sigil %q", id, sigil)
}
return splitIDWithSigil(id)
}

func splitID(id string) (local string, domain ServerName, err error) {
// Split on the first ":" character since the domain can contain ":"
// characters.
parts := strings.SplitN(id, ":", 2)
if len(parts) != 2 {
// The ID must have a ":" character.
Expand All @@ -1127,6 +1220,45 @@ func SplitID(sigil byte, id string) (local string, domain ServerName, err error)
return parts[0][1:], ServerName(parts[1]), nil
}

// SplitID splits a matrix ID into a local part and a server name.
func splitIDWithSigil(id string) (local string, domain ServerName, err error) {
if len(id) == 0 {
return "", "", fmt.Errorf("gomatrixserverlib: invalid ID %q", id)
}

// IDs have the format: SIGIL LOCALPART ":" DOMAIN
sigil := id[0]
switch sigil {
case UserPermanentKeySigil:
{
version := id[1]
if version == '1' {
// UPK, the whole ID is the local portion
return id[2:], "", err

}
return "", "", fmt.Errorf("gomatrixserverlib: invalid UPK version %q", version)

}
case UserIDSigil:
{
local, domain, err = splitID(id)
if err == nil {
if IsValidMXID(local) {
return local, domain, nil
}
// The Local portion of the User must be only a valid characters.
return "", "", fmt.Errorf("gomatrixserverlib: invalid local ID %q", local)
}
return
}
case RoomAliasSigil, RoomIDSigil, EventIDSigil, GroupIDSigil:
return splitID(id)
default:
return "", "", fmt.Errorf("gomatrixserverlib: invalid sigil %q", sigil)
}
}

// fixNilSlices corrects cases where nil slices end up with "null" in the
// marshalled JSON because Go stupidly doesn't care about the type in this
// situation.
Expand Down
Loading