forked from External/grumble
Add support for importing a server from a Murmur SQLite database. Add support for seralizing a server to disk 'freezing' (currently zlib-JSON based).
This commit is contained in:
parent
2eb5516d31
commit
3ae9881d91
11 changed files with 130730 additions and 55 deletions
190
json.go
Normal file
190
json.go
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"json"
|
||||
"os"
|
||||
"compress/zlib"
|
||||
)
|
||||
|
||||
type jsonServer struct {
|
||||
Id int "id"
|
||||
MaxUsers int "max_user"
|
||||
Channels []jsonChannel "channels"
|
||||
}
|
||||
|
||||
type jsonChannel struct {
|
||||
Id int "id"
|
||||
Name string "name"
|
||||
ParentId int "parent_id"
|
||||
Position int64 "position"
|
||||
InheritACL bool "inherit_acl"
|
||||
ACL []jsonACL "acl"
|
||||
Groups []jsonGroup "groups"
|
||||
Description string "description"
|
||||
DescriptionHash []byte "description_hash"
|
||||
}
|
||||
|
||||
type jsonACL struct {
|
||||
UserId int "user_id"
|
||||
Group string "group"
|
||||
ApplyHere bool "apply_here"
|
||||
ApplySubs bool "apply_subs"
|
||||
Allow uint32 "allow"
|
||||
Deny uint32 "deny"
|
||||
}
|
||||
|
||||
type jsonGroup struct {
|
||||
Name string "name"
|
||||
Inherit bool "inherit"
|
||||
Inheritable bool "inheritable"
|
||||
Add []int "add"
|
||||
Remove []int "remove"
|
||||
}
|
||||
|
||||
// Marshal a server into a JSON object
|
||||
func (server *Server) MarshalJSON() (buf []byte, err os.Error) {
|
||||
obj := make(map[string]interface{})
|
||||
obj["id"] = server.Id
|
||||
obj["max_user"] = server.MaxUsers
|
||||
|
||||
channels := []interface{}{}
|
||||
for _, c := range server.Channels {
|
||||
channels = append(channels, c)
|
||||
}
|
||||
obj["channels"] = channels
|
||||
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
// Marshal a Channel into a JSON object
|
||||
func (channel *Channel) MarshalJSON() (buf []byte, err os.Error) {
|
||||
obj := make(map[string]interface{})
|
||||
|
||||
obj["id"] = channel.Id
|
||||
obj["name"] = channel.Name
|
||||
if channel.parent != nil {
|
||||
obj["parent_id"] = channel.parent.Id
|
||||
} else {
|
||||
obj["parent_id"] = -1
|
||||
}
|
||||
|
||||
obj["position"] = channel.Position
|
||||
obj["inherit_acl"] = channel.InheritACL
|
||||
obj["description"] = channel.Description
|
||||
obj["description_hash"] = channel.DescriptionHash
|
||||
|
||||
obj["acl"] = channel.ACL
|
||||
|
||||
groups := []*Group{}
|
||||
for _, grp := range channel.Groups {
|
||||
groups = append(groups, grp)
|
||||
}
|
||||
obj["groups"] = groups
|
||||
links := []int{}
|
||||
for cid, _ := range channel.Links {
|
||||
links = append(links, cid)
|
||||
}
|
||||
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
func (acl *ChannelACL) MarshalJSON() (buf []byte, err os.Error) {
|
||||
obj := make(map[string]interface{})
|
||||
obj["user_id"] = acl.UserId
|
||||
obj["group"] = acl.Group
|
||||
obj["apply_here"] = acl.ApplyHere
|
||||
obj["apply_subs"] = acl.ApplySubs
|
||||
obj["allow"] = acl.Allow
|
||||
obj["deny"] = acl.Deny
|
||||
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
func (group *Group) MarshalJSON() (buf []byte, err os.Error) {
|
||||
obj := make(map[string]interface{})
|
||||
obj["name"] = group.Name
|
||||
obj["inherit"] = group.Inherit
|
||||
obj["inheritable"] = group.Inheritable
|
||||
obj["add"] = group.AddUsers()
|
||||
obj["remove"] = group.RemoveUsers()
|
||||
|
||||
return json.Marshal(obj)
|
||||
}
|
||||
|
||||
// Create a new Server from a Grumble zlib-compressed JSON description
|
||||
func NewServerFromGrumbleDesc(filename string) (s *Server, err os.Error) {
|
||||
descFile, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer descFile.Close()
|
||||
|
||||
zr, err := zlib.NewReader(descFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srv := new(jsonServer)
|
||||
decoder := json.NewDecoder(zr)
|
||||
decoder.Decode(&srv)
|
||||
|
||||
s, err = NewServer(int64(srv.Id), "", int(DefaultPort+srv.Id-1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add all channels, but don't hook up parent/child relationships
|
||||
// until all of them are loaded.
|
||||
for _, jc := range srv.Channels {
|
||||
c := NewChannel(jc.Id, jc.Name)
|
||||
c.Position = int(jc.Position)
|
||||
c.InheritACL = jc.InheritACL
|
||||
c.Description = jc.Description
|
||||
c.DescriptionHash = jc.DescriptionHash
|
||||
|
||||
for _, jacl := range jc.ACL {
|
||||
acl := NewChannelACL(c)
|
||||
acl.ApplyHere = jacl.ApplyHere
|
||||
acl.ApplySubs = jacl.ApplySubs
|
||||
acl.UserId = jacl.UserId
|
||||
acl.Group = jacl.Group
|
||||
acl.Deny = Permission(jacl.Deny)
|
||||
acl.Allow = Permission(jacl.Allow)
|
||||
c.ACL = append(c.ACL, acl)
|
||||
}
|
||||
for _, jgrp := range jc.Groups {
|
||||
g := NewGroup(c, jgrp.Name)
|
||||
g.Inherit = jgrp.Inherit
|
||||
g.Inheritable = jgrp.Inheritable
|
||||
for _, uid := range jgrp.Add {
|
||||
g.Add[uid] = true
|
||||
}
|
||||
for _, uid := range jgrp.Remove {
|
||||
g.Remove[uid] = true
|
||||
}
|
||||
c.Groups[g.Name] = g
|
||||
}
|
||||
|
||||
s.Channels[c.Id] = c
|
||||
}
|
||||
|
||||
// Hook up children with their parents.
|
||||
for _, jc := range srv.Channels {
|
||||
if jc.Id == 0 {
|
||||
continue
|
||||
}
|
||||
childChan, exists := s.Channels[jc.Id]
|
||||
if !exists {
|
||||
return nil, os.NewError("Non-existant child channel")
|
||||
}
|
||||
parentChan, exists := s.Channels[jc.ParentId]
|
||||
if !exists {
|
||||
return nil, os.NewError("Non-existant parent channel")
|
||||
}
|
||||
parentChan.AddChild(childChan)
|
||||
}
|
||||
|
||||
s.root = s.Channels[0]
|
||||
|
||||
return s, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue