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