1package eu.siacs.conversations.entities;
2
3import android.content.ContentValues;
4import android.util.Base64;
5import java.io.UnsupportedEncodingException;
6import java.lang.Comparable;
7import java.security.MessageDigest;
8import java.security.NoSuchAlgorithmException;
9import java.util.ArrayList;
10import java.util.Collections;
11import java.util.List;
12
13import eu.siacs.conversations.xml.Element;
14import eu.siacs.conversations.xmpp.stanzas.IqPacket;
15
16public class ServiceDiscoveryResult {
17
18 protected static String blankNull(String s) {
19 return s == null ? "" : s;
20 }
21
22 public static class Identity implements Comparable {
23 protected final String category;
24 protected final String type;
25 protected final String lang;
26 protected final String name;
27
28 public Identity(final String category, final String type, final String lang, final String name) {
29 this.category = category;
30 this.type = type;
31 this.lang = lang;
32 this.name = name;
33 }
34
35 public Identity(final Element el) {
36 this.category = el.getAttribute("category");
37 this.type = el.getAttribute("type");
38 this.lang = el.getAttribute("xml:lang");
39 this.name = el.getAttribute("name");
40 }
41
42 public String getCategory() {
43 return this.category;
44 }
45
46 public String getType() {
47 return this.type;
48 }
49
50 public String getLang() {
51 return this.lang;
52 }
53
54 public String getName() {
55 return this.name;
56 }
57
58 public int compareTo(Object other) {
59 Identity o = (Identity)other;
60 int r = blankNull(this.getCategory()).compareTo(blankNull(o.getCategory()));
61 if(r == 0) {
62 r = blankNull(this.getType()).compareTo(blankNull(o.getType()));
63 }
64 if(r == 0) {
65 r = blankNull(this.getLang()).compareTo(blankNull(o.getLang()));
66 }
67 if(r == 0) {
68 r = blankNull(this.getName()).compareTo(blankNull(o.getName()));
69 }
70
71 return r;
72 }
73 }
74
75 protected final List<Identity> identities;
76 protected final List<String> features;
77
78 public ServiceDiscoveryResult(final List<Identity> identities, final List<String> features) {
79 this.identities = identities;
80 this.features = features;
81 }
82
83 public ServiceDiscoveryResult(final IqPacket packet) {
84 this.identities = new ArrayList<>();
85 this.features = new ArrayList<>();
86
87 final List<Element> elements = packet.query().getChildren();
88
89 for (final Element element : elements) {
90 if (element.getName().equals("identity")) {
91 Identity id = new Identity(element);
92 if (id.getType() != null && id.getCategory() != null) {
93 identities.add(id);
94 }
95 } else if (element.getName().equals("feature")) {
96 if (element.getAttribute("var") != null) {
97 features.add(element.getAttribute("var"));
98 }
99 }
100 }
101 }
102
103 public List<Identity> getIdentities() {
104 return this.identities;
105 }
106
107 public List<String> getFeatures() {
108 return this.features;
109 }
110
111 public boolean hasIdentity(String category, String type) {
112 for(Identity id : this.getIdentities()) {
113 if((category == null || id.getCategory().equals(category)) &&
114 (type == null || id.getType().equals(type))) {
115 return true;
116 }
117 }
118
119 return false;
120 }
121
122 public byte[] getCapHash() {
123 StringBuilder s = new StringBuilder();
124
125 List<Identity> identities = this.getIdentities();
126 Collections.sort(identities);
127
128 for(Identity id : identities) {
129 s.append(
130 blankNull(id.getCategory()) + "/" +
131 blankNull(id.getType()) + "/" +
132 blankNull(id.getLang()) + "/" +
133 blankNull(id.getName()) + "<"
134 );
135 }
136
137 List<String> features = this.getFeatures();
138 Collections.sort(features);
139
140 for (String feature : features) {
141 s.append(feature + "<");
142 }
143
144 // TODO: data forms?
145
146 MessageDigest md;
147 try {
148 md = MessageDigest.getInstance("SHA-1");
149 } catch (NoSuchAlgorithmException e) {
150 return null;
151 }
152
153 try {
154 return md.digest(s.toString().getBytes("UTF-8"));
155 } catch(UnsupportedEncodingException e) {
156 return null;
157 }
158 }
159
160}