grumble/json.go

190 lines
4.3 KiB
Go

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
}