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 && conversation.getBookmark().isProvidePassword()) {
170 this.passwordChanged = false;
171 }
172 } else {
173 addUser(user);
174 }
175 if (pgp != null) {
176 Element x = packet.findChild("x", "jabber:x:signed");
177 if (x != null) {
178 Element status = packet.findChild("status");
179 String msg;
180 if (status != null) {
181 msg = status.getContent();
182 } else {
183 msg = "";
184 }
185 user.setPgpKeyId(pgp.fetchKeyId(account, msg,
186 x.getContent()));
187 }
188 }
189 } else if (type.equals("unavailable") && name.equals(this.joinnick)) {
190 Element status = packet.findChild("x",
191 "http://jabber.org/protocol/muc#user").findChild(
192 "status");
193 String code = status.getAttribute("code");
194 if (code.equals(STATUS_CODE_KICKED)) {
195 this.isOnline = false;
196 this.error = KICKED_FROM_ROOM;
197 } else if (code.equals(STATUS_CODE_BANNED)) {
198 this.isOnline = false;
199 this.error = ERROR_BANNED;
200 }
201 } else if (type.equals("unavailable")) {
202 deleteUser(packet.getAttribute("from").split("/", 2)[1]);
203 } else if (type.equals("error")) {
204 Element error = packet.findChild("error");
205 if (error.hasChild("conflict")) {
206 if (aboutToRename) {
207 if (renameListener != null) {
208 renameListener.onRename(false);
209 }
210 aboutToRename = false;
211 this.setJoinNick(getActualNick());
212 } else {
213 this.error = ERROR_NICK_IN_USE;
214 }
215 } else if (error.hasChild("not-authorized")) {
216 if (conversation.getBookmark() != null
217 && conversation.getBookmark().isProvidePassword()) {
218 this.passwordChanged = true;
219 }
220 this.error = ERROR_PASSWORD_REQUIRED;
221 } else if (error.hasChild("forbidden")) {
222 this.error = ERROR_BANNED;
223 } else if (error.hasChild("registration-required")) {
224 this.error = ERROR_MEMBERS_ONLY;
225 }
226 }
227 }
228 }
229
230 public List<User> getUsers() {
231 return this.users;
232 }
233
234 public String getProposedNick() {
235 String[] mucParts = conversation.getContactJid().split("/", 2);
236 if (conversation.getBookmark() != null
237 && conversation.getBookmark().getNick() != null) {
238 return conversation.getBookmark().getNick();
239 } else {
240 if (mucParts.length == 2) {
241 return mucParts[1];
242 } else {
243 return account.getUsername();
244 }
245 }
246 }
247
248 public String getActualNick() {
249 if (this.self.getName() != null) {
250 return this.self.getName();
251 } else {
252 return this.getProposedNick();
253 }
254 }
255
256 public void setJoinNick(String nick) {
257 this.joinnick = nick;
258 }
259
260 public void setConversation(Conversation conversation) {
261 this.conversation = conversation;
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().isProvidePassword()) {
362 conversation.getBookmark().setPassword(password);
363 } else {
364 this.password = password;
365 }
366 conversation
367 .setAttribute(Conversation.ATTRIBUTE_MUC_PASSWORD, password);
368 }
369
370 public boolean isPasswordChanged() {
371 return this.passwordChanged;
372 }
373
374}