(* HCoop Domtool (http://hcoop.sourceforge.net/) * Copyright (c) 2006, Adam Chlipala * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) (* Network messages *) structure Msg :> MSG = struct open OpenSSL MsgTypes Slave val a2i = fn Add => 0 | Delete => 1 | Modify => 2 val i2a = fn 0 => Add | 1 => Delete | 2 => Modify | _ => raise OpenSSL.OpenSSL "Bad action number to deserialize" fun sendAcl (bio, {user, class, value}) = (OpenSSL.writeString (bio, user); OpenSSL.writeString (bio, class); OpenSSL.writeString (bio, value)) fun recvAcl bio = case (OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of (SOME user, SOME class, SOME value) => SOME {user = user, class = class, value = value} | _ => NONE fun send (bio, m) = case m of MsgOk => OpenSSL.writeInt (bio, 1) | MsgError s => (OpenSSL.writeInt (bio, 2); OpenSSL.writeString (bio, s)) | MsgConfig s => (OpenSSL.writeInt (bio, 3); OpenSSL.writeString (bio, s)) | MsgFile {action, domain, dir, file} => (OpenSSL.writeInt (bio, 4); OpenSSL.writeInt (bio, a2i action); OpenSSL.writeString (bio, domain); OpenSSL.writeString (bio, dir); OpenSSL.writeString (bio, file)) | MsgDoFiles => OpenSSL.writeInt (bio, 5) | MsgGrant acl => (OpenSSL.writeInt (bio, 6); sendAcl (bio, acl)) | MsgRevoke acl => (OpenSSL.writeInt (bio, 7); sendAcl (bio, acl)) | MsgListPerms user => (OpenSSL.writeInt (bio, 8); OpenSSL.writeString (bio, user)) | MsgPerms classes => (OpenSSL.writeInt (bio, 9); app (fn (class, values) => (OpenSSL.writeInt (bio, 1); OpenSSL.writeString (bio, class); app (fn value => (OpenSSL.writeInt (bio, 1); OpenSSL.writeString (bio, value))) values; OpenSSL.writeInt (bio, 0))) classes; OpenSSL.writeInt (bio, 0)) fun checkIt v = case v of NONE => raise OpenSSL.OpenSSL "Bad Msg format" | _ => v fun recv bio = case OpenSSL.readInt bio of NONE => NONE | SOME n => checkIt (case n of 1 => SOME MsgOk | 2 => Option.map MsgError (OpenSSL.readString bio) | 3 => Option.map MsgConfig (OpenSSL.readString bio) | 4 => (case (OpenSSL.readInt bio, OpenSSL.readString bio, OpenSSL.readString bio, OpenSSL.readString bio) of (SOME action, SOME domain, SOME dir, SOME file) => SOME (MsgFile {action = i2a action, domain = domain, dir = dir, file = file}) | _ => NONE) | 5 => SOME MsgDoFiles | 6 => (case recvAcl bio of SOME acl => SOME (MsgGrant acl) | _ => NONE) | 7 => (case recvAcl bio of SOME acl => SOME (MsgRevoke acl) | _ => NONE) | 8 => (case OpenSSL.readString bio of SOME user => SOME (MsgListPerms user) | _ => NONE) | 9 => let fun loop classes = case OpenSSL.readInt bio of SOME 0 => SOME (MsgPerms (rev classes)) | SOME 1 => (case OpenSSL.readString bio of SOME class => let fun loop' values = case OpenSSL.readInt bio of SOME 0 => loop ((class, rev values) :: classes) | SOME 1 => (case OpenSSL.readString bio of SOME value => loop' (value :: values) | NONE => NONE) | _ => NONE in loop' [] end | NONE => NONE) | _ => NONE in loop [] end | _ => NONE) end