1package eu.siacs.conversations.entities;
2
3import java.util.ArrayList;
4import java.util.List;
5import java.util.concurrent.CopyOnWriteArrayList;
6
7import eu.siacs.conversations.crypto.PgpEngine;
8import eu.siacs.conversations.xml.Element;
9import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
10import android.annotation.SuppressLint;
11
12@SuppressLint("DefaultLocale")
13public class MucOptions {
14 public static final int ERROR_NO_ERROR = 0;
15 public static final int ERROR_NICK_IN_USE = 1;
16 public static final int ERROR_ROOM_NOT_FOUND = 2;
17 public static final int ERROR_PASSWORD_REQUIRED = 3;
18 public static final int ERROR_BANNED = 4;
19 public static final int ERROR_MEMBERS_ONLY = 5;
20
21 public static final int KICKED_FROM_ROOM = 9;
22
23 public static final String STATUS_CODE_BANNED = "301";
24 public static final String STATUS_CODE_KICKED = "307";
25
26 public interface OnRenameListener {
27 public void onRename(boolean success);
28 }
29
30 public class User {
31 public static final int ROLE_MODERATOR = 3;
32 public static final int ROLE_NONE = 0;
33 public static final int ROLE_PARTICIPANT = 2;
34 public static final int ROLE_VISITOR = 1;
35 public static final int AFFILIATION_ADMIN = 4;
36 public static final int AFFILIATION_OWNER = 3;
37 public static final int AFFILIATION_MEMBER = 2;
38 public static final int AFFILIATION_OUTCAST = 1;
39 public static final int AFFILIATION_NONE = 0;
40
41 private int role;
42 private int affiliation;
43 private String name;
44 private String jid;
45 private long pgpKeyId = 0;
46
47 public String getName() {
48 return name;
49 }
50
51 public void setName(String user) {
52 this.name = user;
53 }
54
55 public void setJid(String jid) {
56 this.jid = jid;
57 }
58
59 public String getJid() {
60 return this.jid;
61 }
62
63 public int getRole() {
64 return this.role;
65 }
66
67 public void setRole(String role) {
68 role = role.toLowerCase();
69 if (role.equals("moderator")) {
70 this.role = ROLE_MODERATOR;
71 } else if (role.equals("participant")) {
72 this.role = ROLE_PARTICIPANT;
73 } else if (role.equals("visitor")) {
74 this.role = ROLE_VISITOR;
75 } else {
76 this.role = ROLE_NONE;
77 }
78 }
79
80 public int getAffiliation() {
81 return this.affiliation;
82 }
83
84 public void setAffiliation(String affiliation) {
85 if (affiliation.equalsIgnoreCase("admin")) {
86 this.affiliation = AFFILIATION_ADMIN;
87 } else if (affiliation.equalsIgnoreCase("owner")) {
88 this.affiliation = AFFILIATION_OWNER;
89 } else if (affiliation.equalsIgnoreCase("member")) {
90 this.affiliation = AFFILIATION_MEMBER;
91 } else if (affiliation.equalsIgnoreCase("outcast")) {
92 this.affiliation = AFFILIATION_OUTCAST;
93 } else {
94 this.affiliation = AFFILIATION_NONE;
95 }
96 }
97
98 public void setPgpKeyId(long id) {
99 this.pgpKeyId = id;
100 }
101
102 public long getPgpKeyId() {
103 return this.pgpKeyId;
104 }
105
106 public Contact getContact() {
107 return account.getRoster().getContactFromRoster(getJid());
108 }
109 }
110
111 private Account account;
112 private List<User> users = new CopyOnWriteArrayList<User>();
113 private Conversation conversation;
114 private boolean isOnline = false;
115 private int error = ERROR_ROOM_NOT_FOUND;
116 private OnRenameListener renameListener = null;
117 private boolean aboutToRename = false;
118 private User self = new User();
119 private String subject = null;
120 private String joinnick;
121 private String password = null;
122
123 public MucOptions(Conversation conversation) {
124 this.account = conversation.getAccount();
125 this.conversation = conversation;
126 }
127
128 public void deleteUser(String name) {
129 for (int i = 0; i < users.size(); ++i) {
130 if (users.get(i).getName().equals(name)) {
131 users.remove(i);
132 return;
133 }
134 }
135 }
136
137 public void addUser(User user) {
138 for (int i = 0; i < users.size(); ++i) {
139 if (users.get(i).getName().equals(user.getName())) {
140 users.set(i, user);
141 return;
142 }
143 }
144 users.add(user);
145 }
146
147 public void processPacket(PresencePacket packet, PgpEngine pgp) {
148 String[] fromParts = packet.getFrom().split("/", 2);
149 if (fromParts.length >= 2) {
150 String name = fromParts[1];
151 String type = packet.getAttribute("type");
152 if (type == null) {
153 User user = new User();
154 Element x = packet.findChild("x","http://jabber.org/protocol/muc#user");
155 if (x != null) {
156 Element item = x.findChild("item");
157 if (item != null) {
158 user.setName(name);
159 user.setAffiliation(item.getAttribute("affiliation"));
160 user.setRole(item.getAttribute("role"));
161 user.setJid(item.getAttribute("jid"));
162 user.setName(name);
163 if (name.equals(this.joinnick)) {
164 this.isOnline = true;
165 this.error = ERROR_NO_ERROR;
166 self = user;
167 if (aboutToRename) {
168 if (renameListener != null) {
169 renameListener.onRename(true);
170 }
171 aboutToRename = false;
172 }
173 } else {
174 addUser(user);
175 }
176 if (pgp != null) {
177 Element signed = packet.findChild("x", "jabber:x:signed");
178 if (signed != null) {
179 Element status = packet.findChild("status");
180 String msg;
181 if (status != null) {
182 msg = status.getContent();
183 } else {
184 msg = "";
185 }
186 user.setPgpKeyId(pgp.fetchKeyId(account, msg,
187 signed.getContent()));
188 }
189 }
190 }
191 }
192 } else if (type.equals("unavailable") && name.equals(this.joinnick)) {
193 Element x = packet.findChild("x",
194 "http://jabber.org/protocol/muc#user");
195 if (x != null) {
196 Element status = x.findChild("status");
197 if (status != null) {
198 String code = status.getAttribute("code");
199 if (STATUS_CODE_KICKED.equals(code)) {
200 this.isOnline = false;
201 this.error = KICKED_FROM_ROOM;
202 } else if (STATUS_CODE_BANNED.equals(code)) {
203 this.isOnline = false;
204 this.error = ERROR_BANNED;
205 }
206 }
207 }
208 } else if (type.equals("unavailable")) {
209 deleteUser(packet.getAttribute("from").split("/", 2)[1]);
210 } else if (type.equals("error")) {
211 Element error = packet.findChild("error");
212 if (error != null && error.hasChild("conflict")) {
213 if (aboutToRename) {
214 if (renameListener != null) {
215 renameListener.onRename(false);
216 }
217 aboutToRename = false;
218 this.setJoinNick(getActualNick());
219 } else {
220 this.error = ERROR_NICK_IN_USE;
221 }
222 } else if (error != null && error.hasChild("not-authorized")) {
223 this.error = ERROR_PASSWORD_REQUIRED;
224 } else if (error != null && error.hasChild("forbidden")) {
225 this.error = ERROR_BANNED;
226 } else if (error != null
227 && error.hasChild("registration-required")) {
228 this.error = ERROR_MEMBERS_ONLY;
229 }
230 }
231 }
232 }
233
234 public List<User> getUsers() {
235 return this.users;
236 }
237
238 public String getProposedNick() {
239 String[] mucParts = conversation.getContactJid().split("/", 2);
240 if (conversation.getBookmark() != null
241 && conversation.getBookmark().getNick() != null) {
242 return conversation.getBookmark().getNick();
243 } else {
244 if (mucParts.length == 2) {
245 return mucParts[1];
246 } else {
247 return account.getUsername();
248 }
249 }
250 }
251
252 public String getActualNick() {
253 if (this.self.getName() != null) {
254 return this.self.getName();
255 } else {
256 return this.getProposedNick();
257 }
258 }
259
260 public void setJoinNick(String nick) {
261 this.joinnick = nick;
262 }
263
264 public boolean online() {
265 return this.isOnline;
266 }
267
268 public int getError() {
269 return this.error;
270 }
271
272 public void setOnRenameListener(OnRenameListener listener) {
273 this.renameListener = listener;
274 }
275
276 public OnRenameListener getOnRenameListener() {
277 return this.renameListener;
278 }
279
280 public void setOffline() {
281 this.users.clear();
282 this.error = 0;
283 this.isOnline = false;
284 }
285
286 public User getSelf() {
287 return self;
288 }
289
290 public void setSubject(String content) {
291 this.subject = content;
292 }
293
294 public String getSubject() {
295 return this.subject;
296 }
297
298 public void flagAboutToRename() {
299 this.aboutToRename = true;
300 }
301
302 public long[] getPgpKeyIds() {
303 List<Long> ids = new ArrayList<Long>();
304 for (User user : getUsers()) {
305 if (user.getPgpKeyId() != 0) {
306 ids.add(user.getPgpKeyId());
307 }
308 }
309 long[] primitivLongArray = new long[ids.size()];
310 for (int i = 0; i < ids.size(); ++i) {
311 primitivLongArray[i] = ids.get(i);
312 }
313 return primitivLongArray;
314 }
315
316 public boolean pgpKeysInUse() {
317 for (User user : getUsers()) {
318 if (user.getPgpKeyId() != 0) {
319 return true;
320 }
321 }
322 return false;
323 }
324
325 public boolean everybodyHasKeys() {
326 for (User user : getUsers()) {
327 if (user.getPgpKeyId() == 0) {
328 return false;
329 }
330 }
331 return true;
332 }
333
334 public String getJoinJid() {
335 return this.conversation.getContactJid().split("/", 2)[0] + "/"
336 + this.joinnick;
337 }
338
339 public String getTrueCounterpart(String counterpart) {
340 for (User user : this.getUsers()) {
341 if (user.getName().equals(counterpart)) {
342 return user.getJid();
343 }
344 }
345 return null;
346 }
347
348 public String getPassword() {
349 this.password = conversation
350 .getAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD);
351 if (this.password == null && conversation.getBookmark() != null
352 && conversation.getBookmark().getPassword() != null) {
353 return conversation.getBookmark().getPassword();
354 } else {
355 return this.password;
356 }
357 }
358
359 public void setPassword(String password) {
360 if (conversation.getBookmark() != null) {
361 conversation.getBookmark().setPassword(password);
362 } else {
363 this.password = password;
364 }
365 conversation
366 .setAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD, password);
367 }
368
369 public Conversation getConversation() {
370 return this.conversation;
371 }
372}