1 package org.cacert.gigi.dbObjects;
3 import java.awt.Desktop;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.PrintWriter;
8 import java.util.Arrays;
9 import java.util.HashMap;
10 import java.util.LinkedList;
11 import java.util.Properties;
12 import java.util.TreeSet;
14 import org.cacert.gigi.database.DatabaseConnection;
15 import org.cacert.gigi.database.GigiPreparedStatement;
16 import org.cacert.gigi.database.GigiResultSet;
18 public class CertificateProfile {
22 private final String keyName;
24 private final String visibleName;
26 private static HashMap<String, CertificateProfile> byName = new HashMap<>();
28 private static HashMap<Integer, CertificateProfile> byId = new HashMap<>();
30 private final PropertyTemplate[] pt;
32 private final String[] req;
34 private CertificateProfile(int id, String keyName, String visibleName, String requires, String include) {
36 this.keyName = keyName;
37 this.visibleName = visibleName;
38 req = parseConditions(requires);
39 pt = parsePropertyTemplates(include);
42 private static class PropertyTemplate implements Comparable<PropertyTemplate> {
44 boolean required = true;
46 boolean multiple = false;
50 public PropertyTemplate(String inc) {
51 if (inc.endsWith("?") || inc.endsWith("*") || inc.endsWith("+")) {
52 char sfx = inc.charAt(inc.length() - 1);
55 } else if (sfx == '*') {
61 inc = inc.substring(0, inc.length() - 1);
67 public int hashCode() {
70 result = prime * result + ((inc == null) ? 0 : inc.hashCode());
71 result = prime * result + (multiple ? 1231 : 1237);
72 result = prime * result + (required ? 1231 : 1237);
77 public boolean equals(Object obj) {
84 if (getClass() != obj.getClass()) {
87 PropertyTemplate other = (PropertyTemplate) obj;
89 if (other.inc != null) {
92 } else if ( !inc.equals(other.inc)) {
95 if (multiple != other.multiple) {
98 if (required != other.required) {
105 public String toString() {
106 return inc + (multiple ? (required ? "+" : "*") : (required ? "" : "?"));
110 public int compareTo(PropertyTemplate o) {
111 return toString().compareTo(o.toString());
116 private CertificateProfile(File f) throws IOException {
117 Properties p = new Properties();
118 p.load(new FileInputStream(f));
119 String[] parts = f.getName().split("\\.")[0].split("-", 2);
120 id = Integer.parseInt(parts[0]);
123 pt = parsePropertyTemplates(p.getProperty("include"));
124 req = parseConditions(p.getProperty("requires", ""));
127 private String[] parseConditions(String property) {
128 String[] split2 = property.split(",");
129 if (split2.length == 1 && split2[0].equals("")) {
130 split2 = new String[0];
135 private PropertyTemplate[] parsePropertyTemplates(String property) {
136 String[] split = property.split(",");
137 PropertyTemplate[] pt = new PropertyTemplate[split.length];
138 for (int i = 0; i < split.length; i++) {
139 pt[i] = new PropertyTemplate(split[i]);
148 public String getKeyName() {
152 public String getVisibleName() {
157 for (File f : new File("config/profiles").listFiles()) {
158 Properties p = new Properties();
160 p.load(new FileInputStream(f));
161 } catch (IOException e) {
164 String[] parts = f.getName().split("\\.")[0].split("-", 2);
165 GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT keyname, include, requires, name FROM `profiles` WHERE id=?");
166 ps.setInt(1, Integer.parseInt(parts[0]));
167 GigiResultSet rs = ps.executeQuery();
170 if ( !rs.getString("keyname").equals(parts[1])) {
171 throw new Error("Config error. Certificate Profile mismatch");
173 if ( !rs.getString("include").equals(p.getProperty("include"))) {
174 throw new Error("Config error. Certificate Profile mismatch");
176 if ( !rs.getString("requires").equals(p.getProperty("requires", ""))) {
177 throw new Error("Config error. Certificate Profile mismatch");
180 GigiPreparedStatement insert = DatabaseConnection.getInstance().prepare("INSERT INTO `profiles` SET keyname=?, include=?, requires=?, name=?, id=?");
181 insert.setString(1, parts[1]);
182 insert.setString(2, p.getProperty("include"));
183 insert.setString(3, p.getProperty("requires", ""));
184 insert.setString(4, p.getProperty("name"));
185 insert.setInt(5, Integer.parseInt(parts[0]));
190 GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id, keyname, name, requires, include FROM `profiles`");
191 GigiResultSet rs = ps.executeQuery();
193 CertificateProfile cp = new CertificateProfile(rs.getInt("id"), rs.getString("keyName"), rs.getString("name"), rs.getString("requires"), rs.getString("include"));
194 byId.put(cp.getId(), cp);
195 byName.put(cp.getKeyName(), cp);
200 public static CertificateProfile getById(int id) {
204 public static CertificateProfile getByName(String name) {
205 return byName.get(name);
208 public static CertificateProfile[] getAll() {
209 return byId.values().toArray(new CertificateProfile[byId.size()]);
212 public static void main(String[] args) throws IOException {
213 TreeSet<String> pt = new TreeSet<>();
214 TreeSet<String> req = new TreeSet<>();
215 LinkedList<CertificateProfile> cps = new LinkedList<>();
216 for (CertificateProfile cp : byId.values()) {
218 for (PropertyTemplate p : cp.pt) {
221 req.addAll(Arrays.asList(cp.req));
223 PrintWriter pw = new PrintWriter("profiles.html");
224 pw.println("<!DOCTYPE html><html><head><title>Profiles</title>");
225 pw.println("<style>.split{background-color:#000;margin:0;cell-spacing:0}td{text-align:center}</style>");
226 pw.println("</head>");
227 pw.println("<body><table border='1'>");
228 pw.println("<tr><td>id</td><td> </td>");
229 for (String p : pt) {
230 pw.println("<th>" + p + "</th>");
232 pw.println("<th class='split'></th>");
233 for (String p : req) {
234 pw.println("<th class='req'>" + p + "</th>");
237 for (CertificateProfile certificateProfile : cps) {
239 pw.println("<td>" + certificateProfile.id + "</td>");
240 pw.println("<td>" + certificateProfile.keyName + "</td>");
242 for (String p : pt) {
243 for (PropertyTemplate t : certificateProfile.pt) {
244 if (t.inc.equals(p)) {
245 pw.println("<td>" + (t.required ? (t.multiple ? "+" : "y") : (t.multiple ? "*" : "?")) + "</td>");
249 pw.println("<td></td>");
251 pw.println("<td class='split'></td>");
253 for (String p : req) {
254 for (String t : certificateProfile.req) {
256 pw.println("<td class='req'>y</td>");
260 pw.println("<td></td>");
264 pw.println("</table></body></html>");
265 Desktop.getDesktop().browse(new File("profiles.html").toURI());
269 public boolean canBeIssuedBy(User u) {
270 for (String s : req) {
271 if (s.equals("points>=50")) {
272 if (u.getAssurancePoints() < 50) {
275 } else if (s.equals("points>=100")) {
276 if (u.getAssurancePoints() < 100) {
279 } else if (s.equals("codesign")) {
280 if (u.isInGroup(Group.CODESIGNING)) {