Update of /cvsroot/hcoop/portal In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv8920
Modified Files: cert.mlt cert.sml money.mlt money.sig money.sml tables.sql Added Files: chooseDomain.mlt chooseDomain.sig chooseDomain.sml sign.mlt sign.sml Log Message: Reports for figuring out which accounts to freeze or boot; most of new SSL request forms; change name of contact kind for non-HCoop e-mail --- NEW FILE: sign.sml --- structure Sign = Request(struct val table = "Sign" val adminGroup = "server" fun subject _ = "SSL certificate signing request" val template = "sign" val descr = "SSL certificate signing" fun body (mail, data) = (Mail.mwrite (mail, " Request: "); Mail.mwrite (mail, data); Mail.mwrite (mail, "\n")) end) Index: money.mlt =================================================================== RCS file: /cvsroot/hcoop/portal/money.mlt,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** money.mlt 1 Mar 2008 19:30:52 -0000 1.24 --- money.mlt 9 Apr 2008 13:45:02 -0000 1.25 *************** *** 477,481 **** %><h3>Pledges reset.</h3><% ! end %> <% if showNormal then --- 477,501 ---- %><h3>Pledges reset.</h3><% ! elseif $"cmd" = "freezeworthy" then ! showNormal := false; ! val dqs = Money.freezeworthyPledgers () %> ! <table> ! <tr> <th>Member</th> <th>Balance</th> </tr> ! <% foreach dq in dqs do %> ! <tr> <td><a href="user?id=<% #id dq %>"><% #name dq %></a></td> <td>$<% #balance dq %></td> </tr> ! <% end %> ! </table> ! ! <% elseif $"cmd" = "bootworthy" then ! showNormal := false; ! val dqs = Money.bootworthyPledgers () %> ! <table> ! <tr> <th>Member</th> <th>Balance</th> </tr> ! <% foreach dq in dqs do %> ! <tr> <td><a href="user?id=<% #id dq %>"><% #name dq %></a></td> <td>$<% #balance dq %></td> </tr> ! <% end %> ! </table> ! ! <% end %> <% if showNormal then *************** *** 494,497 **** --- 514,519 ---- <a href="money?cmd=bals">List active balances</a><br> <a href="money?cmd=nbals">List negative active balances</a><br> + <a href="money?cmd=freezeworthy">List members who deserve account freezing</a><br> + <a href="money?cmd=bootworthy">List members who deserve to be kicked out</a><br> <a href="money?cmd=deadbals">List retired balances</a><br> Index: tables.sql =================================================================== RCS file: /cvsroot/hcoop/portal/tables.sql,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** tables.sql 24 Feb 2008 17:41:23 -0000 1.31 --- tables.sql 9 Apr 2008 13:45:02 -0000 1.32 *************** *** 348,351 **** --- 348,363 ---- CREATE SEQUENCE CertSeq START 1; + CREATE TABLE Sign( + id INTEGER PRIMARY KEY, + usr INTEGER NOT NULL, + data TEXT NOT NULL, + msg TEXT NOT NULL, + status INTEGER NOT NULL, + stamp TIMESTAMP NOT NULL, + cstamp TIMESTAMP, + FOREIGN KEY (usr) REFERENCES WebUser(id) ON DELETE CASCADE); + + CREATE SEQUENCE SignSeq START 1; + CREATE TABLE Quota( id INTEGER PRIMARY KEY, Index: money.sig =================================================================== RCS file: /cvsroot/hcoop/portal/money.sig,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** money.sig 24 Feb 2008 17:11:02 -0000 1.6 --- money.sig 9 Apr 2008 13:45:02 -0000 1.7 *************** *** 37,39 **** --- 37,42 ---- val delinquentPledgers : unit -> { id : int, name : string, shares : int, balance : real } list val resetPledges : int list -> unit + + val freezeworthyPledgers : unit -> { id : int, name : string, balance : real } list + val bootworthyPledgers : unit -> { id : int, name : string, balance : real } list end --- NEW FILE: chooseDomain.mlt --- <select name="domain"> <% foreach dom in ChooseDomain.domains (Init.getUserName ()) do %> <option><% dom %></option> <% end %> </select> --- NEW FILE: sign.mlt --- <% @header [("title", ["SSL certificate signing requests"])]; val admin = Group.inGroupName "server"; if $"new" <> "" then val req = $"req"; val key = $"key"; val days = Web.stoi ($"days"); val domain = $"domain"; val msg = $"msg"; if req = "" then %><h3>Please fill in a path to a certificate request.</h3><% elseif key = "" then %><h3>Please fill in a path to a key.</h3><% elseif days <= 0 then %><h3>Please give a positive number of days for the certificate to live.</h3><% elseif not (ChooseDomain.yourDomain {user = Init.getUserName (), domain = domain}) then %><h3>You don't have permissions on domain <tt><% Web.html domain %></tt>.</h3><% else %>Are you sure you want to ask for permissions on an SSL certificate <li> with request <tt><% Web.html req %></tt>,</li> <li> with key <tt><% Web.html key %></tt>,</li> <li> for domain <tt><% domain %></tt>,</li> <li> lasting <% days %> days?</li> <a href="?cmd=request&req=<% Web.html req %>&key=<% Web.html key %>&days=<% days %>&domain=<% Web.html domain %>&msg=<% Web.urlEncode msg %>">Yes, I want to request that.</a><% end elseif $"cmd" = "request" then val req = $"req"; val key = $"key"; val days = Web.stoi ($"days"); val domain = $"domain"; val msg = $"msg"; if req = "" then %><h3>Please fill in a path to a certificate request.</h3><% elseif key = "" then %><h3>Please fill in a path to a key.</h3><% elseif days <= 0 then %><h3>Please give a positive number of days for the certificate to live.</h3><% elseif not (ChooseDomain.yourDomain {user = Init.getUserName (), domain = domain}) then %><h3>You don't have permissions on domain <tt><% Web.html domain %></tt>.</h3><% else val gen = req; val text = "/afs/hcoop.net/common/etc/scripts/ca-sign " ^ Int.toString days ^ " " ^ req ^ " " ^ key ^ " " ^ gen ^ " " ^ domain; val id = Sign.add (Init.getUserId (), text, msg); if not (Sign.notifyNew id) then %><h3>Error sending e-mail notification</h3><% end %><h3>Request added</h3><% end elseif $"cmd" = "open" then %><h3>Open requests</h3> <a href="?cmd=list">List all requests</a><% foreach (name, req) in Sign.listOpen () do %> <br><hr><br> <table class="blanks"> <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> <tr> <td>Request:</td> <td><tt><% #data req %></tt></td> </tr> <tr> <td>Reason:</td> <td><% Web.html (#msg req) %></td> </tr> </table> <% if admin then %> <br> <a href="?mod=<% #id req %>">[Modify]</a> <a href="?del=<% #id req %>">[Delete]</a><br> <% end %> <% end elseif $"cmd" = "list" then %><h3>All requests</h3><% foreach (name, req) in Sign.list () do %> <br><hr><br> <table class="blanks"> <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> <tr> <td>Request:</td> <td><tt><% #data req %></tt></td> </tr> <tr> <td>Reason:</td> <td><% Web.html (#msg req) %></td> </tr> </table> <% if admin then %> <br> <a href="?mod=<% #id req %>">[Modify]</a> <a href="?del=<% #id req %>">[Delete]</a> <% end %> <% end elseif $"mod" <> "" then Group.requireGroupName "server"; val id = Web.stoi ($"mod"); val req = Sign.lookup id; val user = Init.lookupUser (#usr req) %> <h3>Handle request</h3> <form method="post"> <input type="hidden" name="save" value="<% id %>"> <table class="blanks"> <tr> <td>Requestor:</td> <td><a href="user?id=<% #usr req %>"><% #name user %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> <tr> <td>Status:</td> <td><select name="status"> <option value="0"<% if #status req = Sign.NEW then %> selected<% end %>>New</option> <option value="1"<% if #status req = Sign.INSTALLED then %> selected<% end %>>Installed</option> <option value="2"<% if #status req = Sign.REJECTED then %> selected<% end %>>Rejected</option> </select></td> </tr> <tr> <td>Request:</td> <td><input name="req" size="60" value="<% Web.html (#data req) %>"></td> </tr> <tr> <td>Message:</td> <td><textarea name="msg" rows="10" cols="80" wrap="soft"><% Web.html (#msg req) %></textarea></td> </tr> <tr> <td><input type="submit" value="Save"></td> </tr> </table> </form> <% elseif $"save" <> "" then Group.requireGroupName "server"; val id = Web.stoi ($"save"); val req = Sign.lookup id; val oldStatus = #status req; val newStatus = Sign.statusFromInt (Web.stoi ($"status")); Sign.modify {req with data = $"req", msg = $"msg", status = newStatus}; if oldStatus <> newStatus then if not (Sign.notifyMod (oldStatus, newStatus, Init.getUserName(), id)) then %><h3>Error sending e-mail notification</h3><% end end %><h3>Request modified</h3> Back to: <a href="?cmd=open">open requests</a>, <a href="?cmd=list">all requests</a> <% elseif $"del" <> "" then Group.requireGroupName "server"; val id = Web.stoi ($"del"); val req = Sign.lookup id; val user = Init.lookupUser (#usr req) %><h3>Are you sure you want to delete request by <% #name user %> for <tt><% #data req %></tt>?</h3> <a href="?del2=<% id %>">Yes, I'm sure!</a> <% elseif $"del2" <> "" then Group.requireGroupName "server"; val id = Web.stoi ($"del2"); Sign.delete id %><h3>Request deleted</b><h3> Back to: <a href="?cmd=open">open requests</a>, <a href="?cmd=list">all requests</a> <% else %> <h3>Request SSL certificate signing</h3> <p>Use this form to request that we sign an an SSL certificate with our certificate authority. Give the location of your certificate request (<tt>.csr</tt> file) and key (<tt>.key</tt> file) within <tt>/afs/hcoop.net</tt>.</p> <p>The <a href="http://wiki.hcoop.net/MemberManual/ServingWebsites/SslCert">instructions on our wiki for creating SSL certificates</a> may be helpful.</p> <form method="post"> <input type="hidden" name="new" value="1"> <table class="blanks"> <tr> <td>Domain:</td> <td><% @chooseDomain[] %></td> </tr> <tr> <td>OpenSSL request file:</td> <td><input name="req" size="60"></td> </tr> <tr> <td>OpenSSL key file:</td> <td><input name="key" size="60"></td> </tr> <tr> <td>Certificate lifetime, in days:</td> <td><input name="days" size="5" value="3650"></td></tr> <tr> <td>Additional comments:</td> <td><textarea name="msg" rows="5" cols="80" wrap="soft"></textarea></td> </tr> <tr> <td><input type="submit" value="Request"></td> </tr> </table> </form> <% end %> <% @footer[] %> Index: cert.mlt =================================================================== RCS file: /cvsroot/hcoop/portal/cert.mlt,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** cert.mlt 19 Jan 2008 20:57:32 -0000 1.7 --- cert.mlt 9 Apr 2008 13:45:02 -0000 1.8 *************** *** 4,43 **** if $"new" <> "" then ! if $"kind" = "cert" then ! if $"req" <> "" then ! %><h3>You filled data in next to a textbox but didn't check the radio button next to it.</h3><% ! elseif $"cert" = "" then ! %><h3>Please fill in a path to a certificate.</h3><% ! else ! val cert = $"cert"; ! val msg = $"msg"; ! ! %>Are you sure you want to ask for permissions on an SSL certificate at <% cert %>?<br><br> ! <a href="cert?cmd=request&req=Certificate+<% cert %>&msg=<% Web.urlEncode msg %>">Yes, I want to request that.</a><% ! end ! else ! if $"cert" <> "" then ! %><h3>You filled data in next to a textbox but didn't check the radio button next to it.</h3><% ! elseif $"req" = "" then ! %><h3>Please fill in a path to an OpenSSL request.</h3><% ! else ! val req = $"req"; ! val msg = $"msg"; ! ! %>Are you sure you want to ask for permissions on an SSL certificate to be created from an OpenSSL request at <% req %>?<br><br> ! <a href="cert?cmd=request&req=OpenSSL+request+<% req %>&msg=<% Web.urlEncode msg %>">Yes, I want to request that.</a><% ! end ! end elseif $"cmd" = "request" then ! val id = Cert.add (Init.getUserId (), $"req", $"msg"); ! if not (Cert.notifyNew id) then ! %><h3>Error sending e-mail notification</h3><% ! end ! %><h3>Request added</h3><% elseif $"cmd" = "open" then %><h3>Open requests</h3> ! <a href="cert?cmd=list">List all requests</a><% foreach (name, req) in Cert.listOpen () do %> --- 4,45 ---- if $"new" <> "" then ! val cert = $"cert"; ! val domain = $"domain"; ! val msg = $"msg"; + if cert = "" then + %><h3>Please fill in a path to a certificate.</h3><% + elseif not (ChooseDomain.yourDomain {user = Init.getUserName (), domain = domain}) then + %><h3>You don't have permissions on domain <tt><% Web.html domain %></tt>.</h3><% + else + %>Are you sure you want to ask for permissions on an SSL certificate + <li> at <tt><% Web.html cert %></tt>,</li> + <li> for domain <tt><% domain %></tt>?</li> + <a href="?cmd=request&cert=<% Web.html cert %>&domain=<% Web.html domain %>&msg=<% Web.urlEncode msg %>">Yes, I want to request that.</a><% + end elseif $"cmd" = "request" then ! val cert = $"cert"; ! val domain = $"domain"; ! val msg = $"msg"; + if cert = "" then + %><h3>Please fill in a path to a certificate.</h3><% + elseif not (ChooseDomain.yourDomain {user = Init.getUserName (), domain = domain}) then + %><h3>You don't have permissions on domain <tt><% Web.html domain %></tt>.</h3><% + else + val text = "/afs/hcoop.net/common/etc/scripts/ca-install " + ^ Init.getUserName () ^ " " + ^ domain ^ " " + ^ cert + + val id = Cert.add (Init.getUserId (), text, msg); + if not (Cert.notifyNew id) then + %><h3>Error sending e-mail notification</h3><% + end + %><h3>Request added</h3><% + end elseif $"cmd" = "open" then %><h3>Open requests</h3> ! <a href="?cmd=list">List all requests</a><% foreach (name, req) in Cert.listOpen () do %> *************** *** 46,50 **** <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> ! <tr> <td>Request:</td> <td><% #data req %></td> </tr> <tr> <td>Reason:</td> <td><% Web.html (#msg req) %></td> </tr> </table> --- 48,52 ---- <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> ! <tr> <td>Request:</td> <td><tt><% #data req %></tt></td> </tr> <tr> <td>Reason:</td> <td><% Web.html (#msg req) %></td> </tr> </table> *************** *** 52,58 **** <% if admin then %> <br> ! <a href="cert?mod=<% #id req %>">[Modify]</a> ! <a href="cert?del=<% #id req %>">[Delete]</a><br> ! To install, run: <i>tell adamc what text to put here</i>. <% end %> --- 54,59 ---- <% if admin then %> <br> ! <a href="?mod=<% #id req %>">[Modify]</a> ! <a href="?del=<% #id req %>">[Delete]</a><br> <% end %> *************** *** 67,71 **** <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> ! <tr> <td>Request:</td> <td><% #data req %></td> </tr> <tr> <td>Reason:</td> <td><% Web.html (#msg req) %></td> </tr> </table> --- 68,72 ---- <tr> <td>By:</td> <td><a href="user?id=<% #usr req %>"><% name %></a></td> </tr> <tr> <td>Time:</td> <td><% #stamp req %> (<% Util.diffFromNow (#stamp req) %> ago)</td> </tr> ! <tr> <td>Request:</td> <td><tt><% #data req %></tt></td> </tr> <tr> <td>Reason:</td> <td><% Web.html (#msg req) %></td> </tr> </table> *************** *** 73,78 **** <% if admin then %> <br> ! <a href="cert?mod=<% #id req %>">[Modify]</a> ! <a href="cert?del=<% #id req %>">[Delete]</a> <% end %> --- 74,79 ---- <% if admin then %> <br> ! <a href="?mod=<% #id req %>">[Modify]</a> ! <a href="?del=<% #id req %>">[Delete]</a> <% end %> *************** *** 115,119 **** end %><h3>Request modified</h3> ! Back to: <a href="cert?cmd=open">open requests</a>, <a href="cert?cmd=list">all requests</a> <% elseif $"del" <> "" then --- 116,120 ---- end %><h3>Request modified</h3> ! Back to: <a href="?cmd=open">open requests</a>, <a href="?cmd=list">all requests</a> <% elseif $"del" <> "" then *************** *** 123,127 **** val user = Init.lookupUser (#usr req) %><h3>Are you sure you want to delete request by <% #name user %> for <tt><% #data req %></tt>?</h3> ! <a href="cert?del2=<% id %>">Yes, I'm sure!</a> <% elseif $"del2" <> "" then --- 124,128 ---- val user = Init.lookupUser (#usr req) %><h3>Are you sure you want to delete request by <% #name user %> for <tt><% #data req %></tt>?</h3> ! <a href="?del2=<% id %>">Yes, I'm sure!</a> <% elseif $"del2" <> "" then *************** *** 130,144 **** Cert.delete id %><h3>Request deleted</b><h3> ! Back to: <a href="cert?cmd=open">open requests</a>, <a href="cert?cmd=list">all requests</a> <% else %> ! <h3>Request permissions on an SSL certificate</h3> ! ! <p>Use this form to request use Domtool permissions to use an SSL certificate. Give the location of your certificate request or certificate within <tt>/afs/hcoop.net</tt>.</p> ! <p>If you have your own certificate signed by an outside provider like Verisign, then choose the second option and give the path to that certificate.</p> ! <p>If you want your certificate authenticated by chaining through HCoop's root certificate, then choose the first option and give the path to an OpenSSL certificate request. In the comments field, be sure to specify the number of days that you would like the certificate to be valid. If you do not specify a value, we will use 3650 days. Make sure that the key file is in the same directory as the certificate request, and that it has a "<tt>.key</tt>" extension.</p> <p>Note that you can't use SSL certificates very well over HTTPS without an IP address assigned to your web virtual host. You can request one separately on <a href="ip">the IP address request page</a>.</p> --- 131,143 ---- Cert.delete id %><h3>Request deleted</b><h3> ! Back to: <a href="?cmd=open">open requests</a>, <a href="?cmd=list">all requests</a> <% else %> ! <h3>Request installation of an SSL certificate</h3> ! <p>Use this form to request Domtool permissions to use an SSL certificate. Give the location of your certificate/key (<tt>.pem</tt>) file within <tt>/afs/hcoop.net</tt>.</p> ! <p>If you want your certificate authenticated by chaining through HCoop's root certificate, then <a href="sign">get it signed</a> before submitting this form.</p> <p>Note that you can't use SSL certificates very well over HTTPS without an IP address assigned to your web virtual host. You can request one separately on <a href="ip">the IP address request page</a>.</p> *************** *** 149,154 **** <input type="hidden" name="new" value="1"> <table class="blanks"> ! <tr> <td>OpenSSL request: <input type="radio" name="kind" value="req" checked></td> <td><input name="req" size="60"></td> </tr> ! <tr> <td>OpenSSL certificate: <input type="radio" name="kind" value="cert"></td> <td><input name="cert" size="60"></td> </tr> <tr> <td>Additional comments:</td> <td><textarea name="msg" rows="5" cols="80" wrap="soft"></textarea></td> </tr> <tr> <td><input type="submit" value="Request"></td> </tr> --- 148,153 ---- <input type="hidden" name="new" value="1"> <table class="blanks"> ! <tr> <td>Domain:</td> <td><% @chooseDomain[] %></td> </tr> ! <tr> <td>OpenSSL certificate:</td> <td><input name="cert" size="60"></td> </tr> <tr> <td>Additional comments:</td> <td><textarea name="msg" rows="5" cols="80" wrap="soft"></textarea></td> </tr> <tr> <td><input type="submit" value="Request"></td> </tr> --- NEW FILE: chooseDomain.sig --- signature CHOOSE_DOMAIN = sig val domains : string -> string list val yourDomain : {user : string, domain : string} -> bool end Index: money.sml =================================================================== RCS file: /cvsroot/hcoop/portal/money.sml,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** money.sml 24 Feb 2008 17:11:02 -0000 1.13 --- money.sml 9 Apr 2008 13:45:02 -0000 1.14 *************** *** 295,297 **** --- 295,326 ---- raise Fail ($`UPDATE WebUser SET shares = 1 WHERE id IN (^(String.concatWith ", " (List.map C.intToSql ids)))`) + fun freezeworthyPledgers () = + let + val costBase = costBase monthlyCost + + fun makeRow [id, name, amount] = {id = C.intFromSql id, name = C.stringFromSql name, + balance = C.realFromSql amount} + | makeRow row = Init.rowError ("Bad freezeworthyPledgers", row) + in + C.map (getDb ()) makeRow ($`SELECT WebUserPaying.id, WebUserPaying.name, amount + FROM WebUserPaying JOIN Balance ON Balance.id = bal + WHERE amount >= ^(C.realToSql costBase) * ^(C.intToSql graceMonths) + AND amount < ^(C.realToSql costBase) * ^(C.intToSql (graceMonths + 1)) + ORDER BY name`) + end + + fun bootworthyPledgers () = + let + val costBase = costBase monthlyCost + + fun makeRow [id, name, amount] = {id = C.intFromSql id, name = C.stringFromSql name, + balance = C.realFromSql amount} + | makeRow row = Init.rowError ("Bad bootworthyPledgers", row) + in + C.map (getDb ()) makeRow ($`SELECT WebUserPaying.id, WebUserPaying.name, amount + FROM WebUserPaying JOIN Balance ON Balance.id = bal + WHERE amount < ^(C.realToSql costBase) * ^(C.intToSql graceMonths) + ORDER BY name`) + end + end Index: cert.sml =================================================================== RCS file: /cvsroot/hcoop/portal/cert.sml,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** cert.sml 11 Nov 2007 20:34:39 -0000 1.1 --- cert.sml 9 Apr 2008 13:45:02 -0000 1.2 *************** *** 2,6 **** val table = "Cert" val adminGroup = "server" ! fun subject _ = "SSL certificate request" val template = "cert" val descr = "SSL certificate" --- 2,6 ---- val table = "Cert" val adminGroup = "server" ! fun subject _ = "SSL certificate installation request" val template = "cert" val descr = "SSL certificate" --- NEW FILE: chooseDomain.sml --- structure ChooseDomain :> CHOOSE_DOMAIN = struct fun domains user = let val proc = Unix.execute ("/bin/sh", ["-c", "DOMTOOL_USER=hcoop /usr/local/bin/domtool-admin perms " ^ user]) val inf = Unix.textInstreamOf proc fun loop () = case TextIO.inputLine inf of NONE => [] | SOME line => case String.tokens (fn ch => ch = #":") line of ["domain", domains] => String.tokens Char.isSpace domains | _ => loop () in loop () before ignore (Unix.reap proc) end fun yourDomain {user, domain} = List.exists (fn x => x = domain) (domains user) end ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ hcoop-cvs mailing list hcoop-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/hcoop-cvs