/** * Invites the user to a room for the given contact name and number if the user (or someone else) * writes to this room, a SMS is send to the number * * @param number * @return true if successful, otherwise false * @throws XMPPException */ public MultiUserChat inviteRoom(String number, String contact, int mode) throws Exception { MultiUserChat muc; if (!mRooms.containsKey(number)) { Log.i("No existing chat room with " + contact + ". Creating a new one..."); muc = createRoom(number, contact, mode); mRooms.put(number, muc); } else { muc = mRooms.get(number); Log.i("Opening existing room for " + contact); if (muc != null) { Collection<Occupant> occupants = muc.getParticipants(); // Logging participants for (Occupant occupant : occupants) { Log.d(occupant.getJid() + " already in the room"); } // Invite notified addresses if needed for (String notifiedAddress : mSettings.getNotifiedAddresses().getAll()) { boolean found = false; for (Occupant occupant : occupants) { if (occupant.getJid().startsWith(notifiedAddress + "/")) { found = true; break; } } if (!found) { Log.d("Inviting notified address '" + notifiedAddress + "' in the room for " + contact); muc.invite(notifiedAddress, "SMS conversation with " + contact); } } } } return muc; }
private void rejoinRooms() { String[][] mucDB = mMucHelper.getAllMUC(); if (mucDB == null) { return; } for (String[] aMucDB : mucDB) { if (!mConnection.isAuthenticated()) { return; } Log.i( "Trying to reconnect to the room with parameters: Muc=" + aMucDB[0] + ", Number=" + aMucDB[1] + ", Mode=" + aMucDB[2]); RoomInfo info = getRoomInfo(aMucDB[0]); // if info is not null, the room exists on the server, so lets check if we can reuse it if (info != null) { MultiUserChat muc = new MultiUserChat(mConnection, aMucDB[0]); int mode = Integer.parseInt(aMucDB[2]); // Hardcoded room name for shell String name = mode == MODE_SMS ? ContactsManager.getContactName(mCtx, aMucDB[1]) : "Shell " + aMucDB[1]; try { if (info.isPasswordProtected()) { muc.join(name, mSettings.roomPassword, mDiscussionHistory, JOIN_TIMEOUT); } else { muc.join(name, null, mDiscussionHistory, JOIN_TIMEOUT); // Openfire needs some time to collect the owners list try { Thread.sleep(REJOIN_ROOMS_SLEEP); } catch (InterruptedException e1) { /* Ignore */ } // check here if we are still owner of these room, in case somebody has taken over // ownership // sadly getOwners() throws sometimes a 403 on my openfire server try { if (!affiliateCheck(muc.getOwners())) { Log.i("rejoinRooms: leaving " + muc.getRoom() + " because affiliateCheck failed"); leaveRoom(muc); continue; } // TODO this shouldn't happen any more // catch the 403 that sometimes shows up and fall back to some easier check if the // room // is still under our control } catch (XMPPException e) { Log.d("rejoinRooms: Exception, falling back", e); if (!(info.isMembersOnly() || info.isPasswordProtected())) { Log.i( "rejoinRooms: leaving " + muc.getRoom() + " because of membersOnly=" + info.isMembersOnly() + " passwordProtected=" + info.isPasswordProtected()); leaveRoom(muc); continue; } } } // looks like there is no one in the room if (info.getOccupantsCount() == 0) { Log.i("rejoinRooms: leaving " + muc.getRoom() + " because there is no one there"); leaveRoom(muc); continue; } } catch (Exception e) { Log.i("rejoinRooms: leaving " + muc.getRoom() + " because of XMMPException", e); // TODO decide in which cases it would be the best to remove the room from the DB, // because of a persistent error // and in which cases the error will not be permanent if (mConnection.isAuthenticated()) { try { leaveRoom(muc); } catch (SmackException.NotConnectedException e1) { Log.i( "rejoinRooms: error when leaving " + muc.getRoom() + " because of Exception", e); } continue; } else { break; } } Log.i("Connected to the room '" + aMucDB[0]); // MUC has passed all tests and is fully usable registerRoom(muc, aMucDB[1], name, mode); } else { Log.i("The room '" + aMucDB[0] + "'is no more available"); mMucHelper.deleteMUC(aMucDB[0]); } } }
/** * Creates a new MUC AND invites the user room name will be extended with an random number for * security purposes * * @param number * @param name - the name of the contact to chat via SMS with * @return * @throws XMPPException */ private MultiUserChat createRoom(String number, String name, int mode) throws Exception { MultiUserChat multiUserChat; Integer randomInt; // With "@conference.jabber.org" messages are sent several times... // Jwchat seems to work fine and is the default final String roomJID; final String subjectInviteStr; do { randomInt = mRndGen.nextInt(); } while (mRoomNumbers.contains(randomInt)); String normalizedName = name.replaceAll(" ", "_").replaceAll("[\\W]|�", ""); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { normalizedName = Normalizer.normalize(normalizedName, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", ""); } String cleanLogin = mSettings.getLogin().replaceAll("@", "_"); String roomUID = normalizedName + "_" + ROOM_START_TAG + randomInt + "_" + cleanLogin; switch (mode) { case MODE_SMS: roomJID = roomUID + "_SMS_" + "@" + getMUCServer(); subjectInviteStr = mCtx.getString(R.string.xmpp_muc_sms) + name; break; case MODE_SHELL: roomJID = roomUID + "_Shell_" + number + "@" + getMUCServer(); subjectInviteStr = mCtx.getString(R.string.xmpp_muc_shell) + name + " " + number; name = "Shell " + number; break; default: roomJID = null; subjectInviteStr = null; break; } Log.i("Creating room " + roomJID + " " + getRoomInt(roomJID)); // See issue 136 try { multiUserChat = new MultiUserChat(mConnection, roomJID); } catch (Exception e) { Log.e("MUC creation failed: ", e); throw new Exception("MUC creation failed for " + roomJID + ": " + e.getLocalizedMessage(), e); } try { multiUserChat.createOrJoin(name); } catch (Exception e) { Log.e("MUC creation failed: ", e); throw new Exception("MUC creation failed for " + name + ": " + e.getLocalizedMessage(), e); } try { // Since this is a private room, make the room not public and set user as owner of the room. Form submitForm = multiUserChat.getConfigurationForm().createAnswerForm(); submitForm.setAnswer("muc#roomconfig_publicroom", false); submitForm.setAnswer("muc#roomconfig_roomname", name); try { submitForm.setAnswer("muc#roomconfig_roomdesc", name); } catch (Exception ex) { Log.w("Unable to configure room description to " + name, ex); } try { submitForm.setAnswer("muc#roomconfig_whois", "anyone"); } catch (Exception ex) { Log.w("Unable to configure setting whois"); } try { List<String> owners = new ArrayList<String>(); if (mConnection.getUser() != null) { owners.add(mConnection.getUser()); } else { owners.add(mSettings.getLogin()); } Collections.addAll(owners, mSettings.getNotifiedAddresses().getAll()); submitForm.setAnswer("muc#roomconfig_roomowners", owners); submitForm.setAnswer("muc#roomconfig_membersonly", true); } catch (Exception ex) { // Password protected MUC fallback code begins here Log.w( "Unable to configure room owners on Server " + getMUCServer() + ". Falling back to room passwords", ex); // See http://xmpp.org/registrar/formtypes.html#http:--jabber.org-protocol-mucroomconfig try { if (submitForm.getField("muc#roomconfig_passwordprotectedroom") != null) { submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", true); } submitForm.setAnswer("muc#roomconfig_roomsecret", mSettings.roomPassword); } catch (IllegalArgumentException iae) { // If a server doesn't provide even password protected MUC, the setAnswer // call will result in an IllegalArgumentException, which we wrap into an XMPPException // See also Issue 247 http://code.google.com/p/gtalksms/issues/detail?id=247 throw iae; } } Log.d(submitForm.getDataFormToSend().toXML().toString()); multiUserChat.sendConfigurationForm(submitForm); multiUserChat.changeSubject(subjectInviteStr); } catch (XMPPException e1) { Log.w("Unable to send conference room configuration form.", e1); send(mCtx.getString(R.string.chat_sms_muc_conf_error, e1.getMessage())); // then we also should not send an invite as the room will be locked throw e1; } for (String notifiedAddress : mSettings.getNotifiedAddresses().getAll()) { multiUserChat.invite(notifiedAddress, subjectInviteStr); } registerRoom(multiUserChat, number, name, randomInt, mode); return multiUserChat; }