+val okChars = [#" ", #"-", #".", #"!", #"?", #":", #",", #";", #"'", #"\"", #"/", #"(", #")", #"{", #"}", #"[", #"]"]
+
+fun validTitle s = CharVector.exists (fn ch => not (Char.isSpace ch)) s
+ andalso CharVector.all (fn ch => Char.isAlphaNum ch orelse List.exists (fn ch' => ch = ch') okChars) s
+
+fun allowedToSee iss =
+ let
+ val iss = lookupIssue iss
+ val cat = lookupCategory (#cat iss)
+ in
+ not (#priv iss) orelse Group.inGroupNum (#grp cat) orelse (Init.getUserId () = #usr iss)
+ end
+
+fun allowedToEdit iss =
+ let
+ val iss = lookupIssue iss
+ val cat = lookupCategory (#cat iss)
+ in
+ Group.inGroupNum (#grp cat) orelse (Init.getUserId () = #usr iss)
+ end
+
+fun writeRecipients (mail, iss : issue, cat : category, noName) =
+ let
+ val query =
+ if #priv iss then
+ $`SELECT name
+ FROM WebUser JOIN Membership ON (usr = id AND grp = ^(C.intToSql (#grp cat)))`
+ else
+ $`SELECT name
+ FROM WebUser JOIN SupSubscription ON (usr = id AND cat = ^(C.intToSql (#id cat)))
+ UNION SELECT name
+ FROM WebUser JOIN Membership ON (usr = id AND grp = ^(C.intToSql (#grp cat)))`
+
+ fun doOne [name] =
+ let
+ val name = C.stringFromSql name
+ in
+ if name = noName then
+ ()
+ else
+ (Mail.mwrite (mail, name);
+ Mail.mwrite (mail, emailSuffix);
+ Mail.mwrite (mail, ","))
+ end
+ in
+ Mail.mwrite (mail, "Bcc: ");
+ C.app (getDb ()) doOne query;
+ Mail.mwrite (mail, "\n")
+ end
+
+fun notify (prefix, f) iss =
+ let
+ val iss = lookupIssue iss
+ val cat = lookupCategory (#cat iss)
+ val user = Init.lookupUser (#usr iss)
+
+ val mail = Mail.mopen ()
+ in
+ Mail.mwrite (mail, "From: Hcoop Support System <support");
+ Mail.mwrite (mail, emailSuffix);
+ Mail.mwrite (mail, ">\nTo: ");
+ Mail.mwrite (mail, #name user);
+ Mail.mwrite (mail, emailSuffix);
+ Mail.mwrite (mail, "\n");
+ writeRecipients (mail, iss, cat, #name user);
+ Mail.mwrite (mail, "Subject: ");
+ Mail.mwrite (mail, prefix);
+ Mail.mwrite (mail, #title iss);
+ Mail.mwrite (mail, "\n\nURL: ");
+ Mail.mwrite (mail, Init.urlPrefix);
+ Mail.mwrite (mail, "issue?cat=");
+ Mail.mwrite (mail, C.intToSql (#id cat));
+ Mail.mwrite (mail, "&id=");
+ Mail.mwrite (mail, C.intToSql (#id iss));
+ Mail.mwrite (mail, "\n\nSubmitted by: ");
+ Mail.mwrite (mail, #name user);
+ Mail.mwrite (mail, "\n Category: ");
+ Mail.mwrite (mail, #name cat);
+ Mail.mwrite (mail, "\n Issue: ");
+ Mail.mwrite (mail, #title iss);
+ Mail.mwrite (mail, "\n Private: ");
+ Mail.mwrite (mail, if #priv iss then "yes" else "no");
+ Mail.mwrite (mail, "\n\n");
+
+ f (iss, cat, user, mail);
+
+ OS.Process.isSuccess (Mail.mclose mail)
+ end