public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
        {
            object remoteValue = DoRemote(requestingAgentID, noticeID);
            if (remoteValue != null || m_doRemoteOnly)
                return (GroupNoticeInfo) remoteValue;

            QueryFilter filter = new QueryFilter();
            filter.andFilters["NoticeID"] = noticeID;
            string[] fields = new string[9]
                                  {
                                      "GroupID",
                                      "Timestamp",
                                      "FromName",
                                      "Subject",
                                      "ItemID",
                                      "HasAttachment",
                                      "Message",
                                      "AssetType",
                                      "ItemName"
                                  };
            List<string> notice = data.Query(fields, "osgroupnotice", filter, null, null, null);

            if (notice.Count != fields.Length)
            {
                return null;
            }

            GroupNoticeData GND = new GroupNoticeData
                                      {
                                          NoticeID = noticeID,
                                          Timestamp = uint.Parse(notice[1]),
                                          FromName = notice[2],
                                          Subject = notice[3],
                                          HasAttachment = int.Parse(notice[5]) == 1
                                      };
            if (GND.HasAttachment)
            {
                GND.ItemID = UUID.Parse(notice[4]);
                GND.AssetType = (byte) int.Parse(notice[7]);
                GND.ItemName = notice[8];
            }

            GroupNoticeInfo info = new GroupNoticeInfo
                                       {
                                           BinaryBucket = new byte[0],
                                           GroupID = UUID.Parse(notice[0]),
                                           Message = notice[6],
                                           noticeData = GND
                                       };

            return (!agentsCanBypassGroupNoticePermsCheck.Contains(requestingAgentID) &&
                    !CheckGroupPermissions(requestingAgentID, info.GroupID, (ulong) GroupPowers.ReceiveNotices))
                       ? null
                       : info;
        }
        public void SendGroupNoticeToUsers(IClientAPI remoteClient, GroupNoticeInfo notice, bool localOnly)
        {
            // Send notice out to everyone that wants notices
            foreach (
                GroupMembersData member in
                    m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), notice.GroupID))
            {
                if (m_debugEnabled)
                {
                    UserAccount targetUser =
                        m_scene.UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.AllScopeIDs,
                                                                  member.AgentID);
                    if (targetUser != null)
                    {
                        MainConsole.Instance.DebugFormat(
                            "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
                            notice.noticeData.NoticeID, targetUser.FirstName + " " + targetUser.LastName,
                            member.AcceptNotices);
                    }
                    else
                    {
                        MainConsole.Instance.DebugFormat(
                            "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
                            notice.noticeData.NoticeID, member.AgentID, member.AcceptNotices);
                    }
                }

                if (member.AcceptNotices)
                {
                    // Build notice IIM
                    GridInstantMessage msg = CreateGroupNoticeIM(GetRequestingAgentID(remoteClient), notice,
                                                                 (byte) InstantMessageDialog.GroupNotice);

                    msg.ToAgentID = member.AgentID;
                    OutgoingInstantMessage(msg, member.AgentID, localOnly);
                }
            }
        }
        private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
        {
            if (m_debugEnabled)
                MainConsole.Instance.DebugFormat("[GROUPS]: {0} called", MethodBase.GetCurrentMethod().Name);

            // Group invitations
            if ((im.Dialog == (byte) InstantMessageDialog.GroupInvitationAccept) ||
                (im.Dialog == (byte) InstantMessageDialog.GroupInvitationDecline))
            {
                UUID inviteID = im.SessionID;
                GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient),
                                                                               inviteID);

                if (inviteInfo == null)
                {
                    if (m_debugEnabled)
                        MainConsole.Instance.WarnFormat(
                            "[GROUPS]: Received an Invite IM for an invite that does not exist {0}.",
                            inviteID);
                    return;
                }

                if (m_debugEnabled)
                    MainConsole.Instance.DebugFormat("[GROUPS]: Invite is for Agent {0} to Group {1}.",
                                                     inviteInfo.AgentID,
                                                     inviteInfo.GroupID);

                UUID fromAgentID = im.FromAgentID;
                if ((inviteInfo != null) && (fromAgentID == inviteInfo.AgentID))
                {
                    // Accept
                    if (im.Dialog == (byte) InstantMessageDialog.GroupInvitationAccept)
                    {
                        if (m_debugEnabled)
                            MainConsole.Instance.DebugFormat("[GROUPS]: Received an accept invite notice.");

                        // and the sessionid is the role
                        UserAccount account = m_scene.UserAccountService.GetUserAccount(remoteClient.AllScopeIDs,
                                                                                        inviteInfo.FromAgentName);
                        if (account != null)
                        {
                            m_groupData.AddAgentToGroup(account.PrincipalID, inviteInfo.AgentID, inviteInfo.GroupID,
                                                        inviteInfo.RoleID);

                            GridInstantMessage msg = new GridInstantMessage
                                                         {
                                                             SessionID = UUID.Zero,
                                                             FromAgentID = UUID.Zero,
                                                             ToAgentID = inviteInfo.AgentID,
                                                             Timestamp = (uint) Util.UnixTimeSinceEpoch(),
                                                             FromAgentName = "Groups",
                                                             Message =
                                                                 string.Format("You have been added to the group."),
                                                             Dialog = (byte) InstantMessageDialog.MessageBox,
                                                             FromGroup = false,
                                                             Offline = 0,
                                                             ParentEstateID = 0,
                                                             Position = Vector3.Zero,
                                                             RegionID = UUID.Zero,
                                                             BinaryBucket = new byte[0]
                                                         };

                            OutgoingInstantMessage(msg, inviteInfo.AgentID);

                            GroupMembershipData gmd =
                                AttemptFindGroupMembershipData(inviteInfo.AgentID, inviteInfo.AgentID,
                                                               inviteInfo.GroupID);
                            m_cachedGroupTitles[inviteInfo.AgentID] = gmd;
                            m_cachedGroupMemberships.Remove(remoteClient.AgentId);
                            RemoveFromGroupPowersCache(inviteInfo.AgentID, inviteInfo.GroupID);
                            UpdateAllClientsWithGroupInfo(inviteInfo.AgentID, gmd.GroupTitle);
                            SendAgentGroupDataUpdate(remoteClient);

                            m_groupData.RemoveAgentInvite(GetRequestingAgentID(remoteClient), inviteID);
                        }
                    }

                    // Reject
                    if (im.Dialog == (byte) InstantMessageDialog.GroupInvitationDecline)
                    {
                        if (m_debugEnabled)
                            MainConsole.Instance.DebugFormat("[GROUPS]: Received a reject invite notice.");
                        m_groupData.RemoveAgentInvite(GetRequestingAgentID(remoteClient), inviteID);
                    }
                    RemoveFromGroupPowersCache(remoteClient.AgentId, inviteInfo.GroupID);
                }
            }

            // Group notices
            switch (im.Dialog)
            {
                case (byte) InstantMessageDialog.GroupNotice:
                    {
                        if (!m_groupNoticesEnabled)
                            return;

                        UUID GroupID = im.ToAgentID;
                        if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null)
                        {
                            UUID NoticeID = UUID.Random();
                            string Subject = im.Message.Substring(0, im.Message.IndexOf('|'));
                            string Message = im.Message.Substring(Subject.Length + 1);

                            byte[] bucket;
                            UUID ItemID = UUID.Zero;
                            int AssetType = 0;
                            string ItemName = "";

                            if ((im.BinaryBucket.Length == 1) && (im.BinaryBucket[0] == 0))
                            {
                                bucket = new byte[19];
                                bucket[0] = 0;
                                bucket[1] = 0;
                                GroupID.ToBytes(bucket, 2);
                                bucket[18] = 0;
                            }
                            else
                            {
                                bucket = im.BinaryBucket;
                                string binBucket = Utils.BytesToString(im.BinaryBucket);
                                binBucket = binBucket.Remove(0, 14).Trim();

                                OSDMap binBucketOSD = (OSDMap) OSDParser.DeserializeLLSDXml(binBucket);
                                if (binBucketOSD.ContainsKey("item_id"))
                                {
                                    ItemID = binBucketOSD["item_id"].AsUUID();

                                    InventoryItemBase item =
                                        m_scene.InventoryService.GetItem(GetRequestingAgentID(remoteClient), ItemID);
                                    if (item != null)
                                    {
                                        AssetType = item.AssetType;
                                        ItemName = item.Name;
                                    }
                                    else
                                        ItemID = UUID.Zero;
                                }
                            }

                            m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID,
                                                       im.FromAgentName,
                                                       Subject, Message, ItemID, AssetType, ItemName);
                            if (OnNewGroupNotice != null)
                                OnNewGroupNotice(GroupID, NoticeID);
                            GroupNoticeInfo notice = new GroupNoticeInfo()
                                                         {
                                                             BinaryBucket = im.BinaryBucket,
                                                             GroupID = GroupID,
                                                             Message = Message,
                                                             noticeData = new GroupNoticeData()
                                                                              {
                                                                                  AssetType = (byte) AssetType,
                                                                                  FromName = im.FromAgentName,
                                                                                  GroupID = GroupID,
                                                                                  HasAttachment = ItemID != UUID.Zero,
                                                                                  ItemID = ItemID,
                                                                                  ItemName = ItemName,
                                                                                  NoticeID = NoticeID,
                                                                                  Subject = Subject,
                                                                                  Timestamp = im.Timestamp
                                                                              }
                                                         };

                            SendGroupNoticeToUsers(remoteClient, notice, false);
                        }
                    }
                    break;
                case (byte) InstantMessageDialog.GroupNoticeInventoryDeclined:
                    break;
                case (byte) InstantMessageDialog.GroupNoticeInventoryAccepted:
                    {
                        UUID FolderID = new UUID(im.BinaryBucket, 0);
                        remoteClient.Scene.InventoryService.GiveInventoryItemAsync(remoteClient.AgentId, UUID.Zero,
                                                                                   im.SessionID, FolderID, false,
                                                                                   (item) =>
                                                                                       {
                                                                                           if (item != null)
                                                                                               remoteClient
                                                                                                   .SendBulkUpdateInventory
                                                                                                   (item);
                                                                                       });
                    }
                    break;
                case 210:
                    {
                        // This is sent from the region that the ejectee was ejected from
                        // if it's being delivered here, then the ejectee is here
                        // so we need to send local updates to the agent.

                        UUID ejecteeID = im.ToAgentID;

                        im.Dialog = (byte) InstantMessageDialog.MessageFromAgent;
                        OutgoingInstantMessage(im, ejecteeID);

                        IClientAPI ejectee = GetActiveClient(ejecteeID);
                        if (ejectee != null)
                        {
                            UUID groupID = im.SessionID;
                            ejectee.SendAgentDropGroup(groupID);
                            if (ejectee.ActiveGroupId == groupID)
                                GroupTitleUpdate(ejectee, UUID.Zero, UUID.Zero);
                            RemoveFromGroupPowersCache(ejecteeID, groupID);
                        }
                    }
                    break;
                case 211:
                    {
                        im.Dialog = (byte) InstantMessageDialog.GroupNotice;

                        //In offline group notices, imSessionID is replaced with the NoticeID so that we can rebuild the packet here
                        GroupNoticeInfo GND = m_groupData.GetGroupNotice(im.ToAgentID, im.SessionID);

                        //Rebuild the binary bucket
                        if (GND.noticeData.HasAttachment)
                        {
                            im.BinaryBucket = CreateBitBucketForGroupAttachment(GND.noticeData, GND.GroupID);
                            //Save the sessionID for the callback by the client (reject or accept)
                            //Only save if has attachment
                            im.SessionID = GND.noticeData.ItemID;
                        }
                        else
                        {
                            byte[] bucket = new byte[19];
                            bucket[0] = 0; //Attachment enabled == false so 0
                            bucket[1] = 0; //No attachment, so no asset type
                            GND.GroupID.ToBytes(bucket, 2);
                            bucket[18] = 0; //dunno
                            im.BinaryBucket = bucket;
                        }

                        OutgoingInstantMessage(im, im.ToAgentID);

                        //You MUST reset this, otherwise the client will get it twice,
                        // as it goes through OnGridInstantMessage
                        // which will check and then reresent the notice
                        im.Dialog = 211;
                    }
                    break;
            }
        }
        public GridInstantMessage CreateGroupNoticeIM(UUID agentID, GroupNoticeInfo info, byte dialog)
        {
            if (m_debugEnabled)
                MainConsole.Instance.DebugFormat("[GROUPS]: {0} called", MethodBase.GetCurrentMethod().Name);

            GridInstantMessage msg = new GridInstantMessage
                                         {
                                             ToAgentID = agentID,
                                             Dialog = dialog,
                                             FromGroup = true,
                                             Offline = 1,
                                             ParentEstateID = 0,
                                             Position = Vector3.Zero,
                                             RegionID = UUID.Zero,
                                             SessionID = UUID.Random()
                                         };

            // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
            // Allow this message to be stored for offline use

            msg.FromAgentID = info.GroupID;
            msg.Timestamp = info.noticeData.Timestamp;
            msg.FromAgentName = info.noticeData.FromName;
            msg.Message = info.noticeData.Subject + "|" + info.Message;
            if (info.noticeData.HasAttachment)
            {
                msg.BinaryBucket = CreateBitBucketForGroupAttachment(info.noticeData, info.GroupID);
                //Save the sessionID for the callback by the client (reject or accept)
                //Only save if has attachment
                msg.SessionID = info.noticeData.ItemID;
            }
            else
            {
                byte[] bucket = new byte[19];
                bucket[0] = 0; //Attachment enabled == false so 0
                bucket[1] = 0; //No attachment, so no asset type
                info.GroupID.ToBytes(bucket, 2);
                bucket[18] = 0; //dunno
                msg.BinaryBucket = bucket;
            }

            return msg;
        }
        private GridInstantMessage BuildGroupNoticeIM(GroupNoticeInfo data, UUID groupNoticeID, UUID AgentID)
        {
            GridInstantMessage msg = new GridInstantMessage
                                         {
                                             FromAgentID = data.GroupID,
                                             ToAgentID = AgentID,
                                             Timestamp = data.noticeData.Timestamp,
                                             FromAgentName = data.noticeData.FromName,
                                             Message = data.noticeData.Subject + "|" + data.Message,
                                             Dialog = (byte) InstantMessageDialog.GroupNoticeRequested,
                                             FromGroup = true,
                                             Offline = 1,
                                             ParentEstateID = 0,
                                             Position = Vector3.Zero,
                                             RegionID = UUID.Zero,
                                             SessionID = UUID.Random()
                                         };

            //Allow offline

            if (data.noticeData.HasAttachment)
            {
                msg.BinaryBucket = CreateBitBucketForGroupAttachment(data.noticeData, data.GroupID);
                //Save the sessionID for the callback by the client (reject or accept)
                //Only save if has attachment
                msg.SessionID = data.noticeData.ItemID;
            }
            else
            {
                byte[] bucket = new byte[19];
                bucket[0] = 0; //Attachment enabled == false so 0
                bucket[1] = 0; //No attachment, so no asset type
                data.GroupID.ToBytes(bucket, 2);
                bucket[18] = 0; //dunno
                msg.BinaryBucket = bucket;
            }
            return msg;
        }