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
107 private Account account;
108 private List<User> users = new CopyOnWriteArrayList<User>();
109 private Conversation conversation;
110 private boolean isOnline = false;
111 private int error = ERROR_ROOM_NOT_FOUND;
112 private OnRenameListener renameListener = null;
113 private boolean aboutToRename = false;
114 private User self = new User();
115 private String subject = null;
116 private String joinnick;
117 private String password = null;
118 private boolean passwordChanged = false;
119
120 public MucOptions(Account account) {
121 this.account = account;
122 }
123
124 public void deleteUser(String name) {
125 for (int i = 0; i < users.size(); ++i) {
126 if (users.get(i).getName().equals(name)) {
127 users.remove(i);
128 return;
129 }
130 }
131 }
132
133 public void addUser(User user) {
134 for (int i = 0; i < users.size(); ++i) {
135 if (users.get(i).getName().equals(user.getName())) {
136 users.set(i, user);
137 return;
138 }
139 }
140 users.add(user);
141 }
142
143 public void processPacket(PresencePacket packet, PgpEngine pgp) {
144 String[] fromParts = packet.getFrom().split("/", 2);
145 if (fromParts.length >= 2) {
146 String name = fromParts[1];
147 String type = packet.getAttribute("type");
148 if (type == null) {
149 User user = new User();
150 Element item = packet.findChild("x",
151 "http://jabber.org/protocol/muc#user")
152 .findChild("item");
153 user.setName(name);
154 user.setAffiliation(item.getAttribute("affiliation"));
155 user.setRole(item.getAttribute("role"));
156 user.setJid(item.getAttribute("jid"));
157 user.setName(name);
158 if (name.equals(this.joinnick)) {
159 this.isOnline = true;
160 this.error = ERROR_NO_ERROR;
161 self = user;
162 if (aboutToRename) {
163 if (renameListener != null) {
164 renameListener.onRename(true);
165 }
166 aboutToRename = false;
167 }
168 if (conversation.getBookmark() != null) {
169 this.passwordChanged = false;
170 }
171 } else {
172 addUser(user);
173 }
174 if (pgp != null) {
175 Element x = packet.findChild("x", "jabber:x:signed");
176 if (x != null) {
177 Element status = packet.findChild("status");
178 String msg;
179 if (status != null) {
180 msg = status.getContent();
181 } else {
182 msg = "";
183 }
184 user.setPgpKeyId(pgp.fetchKeyId(account, msg,
185 x.getContent()));
186 }
187 }
188 } else if (type.equals("unavailable") && name.equals(this.joinnick)) {
189 Element status = packet.findChild("x",
190 "http://jabber.org/protocol/muc#user").findChild(
191 "status");
192 String code = status.getAttribute("code");
193 if (code.equals(STATUS_CODE_KICKED)) {
194 this.isOnline = false;
195 this.error = KICKED_FROM_ROOM;
196 } else if (code.equals(STATUS_CODE_BANNED)) {
197 this.isOnline = false;
198 this.error = ERROR_BANNED;
199 }
200 } else if (type.equals("unavailable")) {
201 deleteUser(packet.getAttribute("from").split("/", 2)[1]);
202 } else if (type.equals("error")) {
203 Element error = packet.findChild("error");
204 if (error.hasChild("conflict")) {
205 if (aboutToRename) {
206 if (renameListener != null) {
207 renameListener.onRename(false);
208 }
209 aboutToRename = false;
210 this.setJoinNick(getActualNick());
211 } else {
212 this.error = ERROR_NICK_IN_USE;
213 }
214 } else if (error.hasChild("not-authorized")) {
215 if (conversation.getBookmark() != null) {
216 this.passwordChanged = true;
217 }
218 this.error = ERROR_PASSWORD_REQUIRED;
219 } else if (error.hasChild("forbidden")) {
220 this.error = ERROR_BANNED;
221 } else if (error.hasChild("registration-required")) {
222 this.error = ERROR_MEMBERS_ONLY;
223 }
224 }
225 }
226 }
227
228 public List<User> getUsers() {
229 return this.users;
230 }
231
232 public String getProposedNick() {
233 String[] mucParts = conversation.getContactJid().split("/", 2);
234 if (conversation.getBookmark() != null
235 && conversation.getBookmark().getNick() != null) {
236 return conversation.getBookmark().getNick();
237 } else {
238 if (mucParts.length == 2) {
239 return mucParts[1];
240 } else {
241 return account.getUsername();
242 }
243 }
244 }
245
246 public String getActualNick() {
247 if (this.self.getName() != null) {
248 return this.self.getName();
249 } else {
250 return this.getProposedNick();
251 }
252 }
253
254 public void setJoinNick(String nick) {
255 this.joinnick = nick;
256 }
257
258 public void setConversation(Conversation conversation) {
259 this.conversation = conversation;
260 }
261
262 public boolean online() {
263 return this.isOnline;
264 }
265
266 public int getError() {
267 return this.error;
268 }
269
270 public void setOnRenameListener(OnRenameListener listener) {
271 this.renameListener = listener;
272 }
273
274 public OnRenameListener getOnRenameListener() {
275 return this.renameListener;
276 }
277
278 public void setOffline() {
279 this.users.clear();
280 this.error = 0;
281 this.isOnline = false;
282 }
283
284 public User getSelf() {
285 return self;
286 }
287
288 public void setSubject(String content) {
289 this.subject = content;
290 }
291
292 public String getSubject() {
293 return this.subject;
294 }
295
296 public void flagAboutToRename() {
297 this.aboutToRename = true;
298 }
299
300 public long[] getPgpKeyIds() {
301 List<Long> ids = new ArrayList<Long>();
302 for (User user : getUsers()) {
303 if (user.getPgpKeyId() != 0) {
304 ids.add(user.getPgpKeyId());
305 }
306 }
307 long[] primitivLongArray = new long[ids.size()];
308 for (int i = 0; i < ids.size(); ++i) {
309 primitivLongArray[i] = ids.get(i);
310 }
311 return primitivLongArray;
312 }
313
314 public boolean pgpKeysInUse() {
315 for (User user : getUsers()) {
316 if (user.getPgpKeyId() != 0) {
317 return true;
318 }
319 }
320 return false;
321 }
322
323 public boolean everybodyHasKeys() {
324 for (User user : getUsers()) {
325 if (user.getPgpKeyId() == 0) {
326 return false;
327 }
328 }
329 return true;
330 }
331
332 public String getJoinJid() {
333 return this.conversation.getContactJid().split("/", 2)[0] + "/"
334 + this.joinnick;
335 }
336
337 public String getTrueCounterpart(String counterpart) {
338 for (User user : this.getUsers()) {
339 if (user.getName().equals(counterpart)) {
340 return user.getJid();
341 }
342 }
343 return null;
344 }
345
346 public String getPassword() {
347 this.password = conversation
348 .getAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD);
349 if (this.password == null && conversation.getBookmark() != null
350 && conversation.getBookmark().getPassword() != null) {
351 return conversation.getBookmark().getPassword();
352 } else {
353 return this.password;
354 }
355 }
356
357 public void setPassword(String password) {
358 if (conversation.getBookmark() != null) {
359 conversation.getBookmark().setPassword(password);
360 } else {
361 this.password = password;
362 }
363 conversation
364 .setAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD, password);
365 }
366
367 public boolean isPasswordChanged2() {
368 return this.passwordChanged;
369 }
370
371}