1 package org.cacert.gigi.dbObjects;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import java.util.HashMap;
11 import java.util.Properties;
13 import org.cacert.gigi.database.GigiPreparedStatement;
14 import org.cacert.gigi.database.GigiResultSet;
16 public class CertificateProfile implements IdCachable {
20 private final String keyName;
22 private final String visibleName;
24 private static final Map<String, CertificateProfile> byName;
26 private static final Map<Integer, CertificateProfile> byId;
28 private final Map<String, PropertyTemplate> pt;
30 private final List<String> req;
32 private CertificateProfile(int id, String keyName, String visibleName, String requires, String include) {
34 this.keyName = keyName;
35 this.visibleName = visibleName;
36 req = parseConditions(requires);
37 pt = parsePropertyTemplates(include);
40 public static class PropertyTemplate implements Comparable<PropertyTemplate> {
42 private boolean required = true;
44 private boolean multiple = false;
48 public PropertyTemplate(String inc) {
49 if (inc.endsWith("?") || inc.endsWith("*") || inc.endsWith("+")) {
50 char sfx = inc.charAt(inc.length() - 1);
53 } else if (sfx == '*') {
59 inc = inc.substring(0, inc.length() - 1);
64 public String getBase() {
68 public boolean isMultiple() {
72 public boolean isRequired() {
77 public int hashCode() {
80 result = prime * result + ((base == null) ? 0 : base.hashCode());
81 result = prime * result + (multiple ? 1231 : 1237);
82 result = prime * result + (required ? 1231 : 1237);
87 public boolean equals(Object obj) {
94 if (getClass() != obj.getClass()) {
97 PropertyTemplate other = (PropertyTemplate) obj;
99 if (other.base != null) {
102 } else if ( !base.equals(other.base)) {
105 if (multiple != other.multiple) {
108 if (required != other.required) {
115 public String toString() {
116 return base + (multiple ? (required ? "+" : "*") : (required ? "" : "?"));
120 public int compareTo(PropertyTemplate o) {
121 return toString().compareTo(o.toString());
126 private CertificateProfile(File f) throws IOException {
127 Properties p = new Properties();
128 try (FileInputStream inStream = new FileInputStream(f)) {
131 String[] parts = f.getName().split("\\.")[0].split("-", 2);
132 id = Integer.parseInt(parts[0]);
135 pt = parsePropertyTemplates(p.getProperty("include"));
136 req = parseConditions(p.getProperty("requires", ""));
139 private List<String> parseConditions(String property) {
140 String[] split2 = property.split(",");
141 if (split2.length == 1 && split2[0].equals("")) {
142 split2 = new String[0];
144 return Collections.unmodifiableList(Arrays.asList(split2));
147 private Map<String, PropertyTemplate> parsePropertyTemplates(String property) {
148 String[] split = property.split(",");
149 HashMap<String, PropertyTemplate> map = new HashMap<>(split.length);
150 for (int i = 0; i < split.length; i++) {
152 PropertyTemplate value = new PropertyTemplate(split[i]);
154 map.put(value.getBase(), value);
156 return Collections.unmodifiableMap(map);
163 public String getKeyName() {
167 public String getVisibleName() {
171 public Map<String, PropertyTemplate> getTemplates() {
175 public List<String> getReqireds() {
180 final HashMap<String, CertificateProfile> myName = new HashMap<String, CertificateProfile>();
181 final HashMap<Integer, CertificateProfile> myId = new HashMap<Integer, CertificateProfile>();
183 for (File f : new File("config/profiles").listFiles()) {
184 Properties p = new Properties();
185 try (FileInputStream inStream = new FileInputStream(f)) {
187 } catch (IOException e) {
188 throw new Error("Unable to load profile from " + f.getName(), e);
191 String[] parts = f.getName().split("\\.")[0].split("-", 2);
192 try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `keyname`, `include`, `requires`, `name` FROM `profiles` WHERE `id`=?")) {
193 ps.setInt(1, Integer.parseInt(parts[0]));
194 GigiResultSet rs = ps.executeQuery();
197 if ( !rs.getString("keyname").equals(parts[1])) {
198 throw new Error("Config error. Certificate Profile mismatch");
200 if ( !rs.getString("include").equals(p.getProperty("include"))) {
201 throw new Error("Config error. Certificate Profile mismatch");
203 if ( !rs.getString("requires").equals(p.getProperty("requires", ""))) {
204 throw new Error("Config error. Certificate Profile mismatch");
207 try (GigiPreparedStatement insert = new GigiPreparedStatement("INSERT INTO `profiles` SET `keyname`=?, `include`=?, `requires`=?, `name`=?, `id`=?")) {
208 insert.setString(1, parts[1]);
209 insert.setString(2, p.getProperty("include"));
210 insert.setString(3, p.getProperty("requires", ""));
211 insert.setString(4, p.getProperty("name"));
212 insert.setInt(5, Integer.parseInt(parts[0]));
219 try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `id`, `keyname`, `name`, `requires`, `include` FROM `profiles`")) {
220 GigiResultSet rs = ps.executeQuery();
222 CertificateProfile cp = new CertificateProfile(rs.getInt("id"), rs.getString("keyName"), rs.getString("name"), rs.getString("requires"), rs.getString("include"));
223 myId.put(cp.getId(), cp);
224 myName.put(cp.getKeyName(), cp);
227 byName = Collections.unmodifiableMap(myName);
228 byId = Collections.unmodifiableMap(myId);
231 public static CertificateProfile getById(int id) {
235 public static CertificateProfile getByName(String name) {
236 return byName.get(name);
239 public static CertificateProfile[] getAll() {
240 return byId.values().toArray(new CertificateProfile[byId.size()]);
243 public boolean canBeIssuedBy(CertificateOwner owner, User actor) {
244 if (pt.containsKey("orga")) {
245 if ( !(owner instanceof Organisation)) {
249 if (owner instanceof Organisation) {
253 for (String s : req) {
254 if (s.equals("points>=50")) {
255 if (actor.getAssurancePoints() < 50) {
258 } else if (s.equals("points>=100")) {
259 if (actor.getAssurancePoints() < 100) {
262 } else if (s.equals("codesign")) {
263 if (actor.isInGroup(Group.CODESIGNING)) {