示例#1
0
 public void WriteUUID(UUID val)
 {
     if (IsZeroEncoded)
     {
         byte[] buf = new byte[16];
         val.ToBytes(buf, 0);
         WriteZeroEncoded(buf);
     }
     else
     {
         val.ToBytes(Data, DataPos);
         DataPos   += 16;
         DataLength = DataPos;
     }
 }
示例#2
0
        private static UUID deMoronize(UUID id)
        {
            byte[] data = new byte[16];
            id.ToBytes(data, 0);
            for (int i = 0; i < 16; ++i)
            {
                data[i] ^= moronize[i];
            }

            return(new UUID(data, 0));
        }
示例#3
0
            public override void ToBytes(byte[] bytes, ref int i)
            {
                Position.ToBytes(bytes, i); i      += sizeof(float) * 3;
                PositionDelta.ToBytes(bytes, i); i += sizeof(float) * 3;
                LookAt.ToBytes(bytes, i); i        += sizeof(float) * 3;
                LookAtDelta.ToBytes(bytes, i); i   += sizeof(float) * 3;
                Up.ToBytes(bytes, i); i            += sizeof(float) * 3;

                Utils.UIntToBytes(TickLength, bytes, i); i += sizeof(int);

                Source.ToBytes(bytes, i);
            }
        public static bool SaveCachedImage(byte[] tgaData, UUID textureID, bool hasAlpha, bool fullAlpha, bool isMask)
        {
            try
            {
                string fname = System.IO.Path.Combine(Login.Client.Settings.ASSET_CACHE_DIR, string.Format("{0}.rzi", textureID));
                //string fname = System.IO.Path.Combine(".", string.Format("{0}.rzi", textureID));

                using (var f = File.Open(fname, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    int i = 0;
                    // magic header
                    f.Write(Utils.StringToBytes(RAD_IMG_MAGIC), 0, RAD_IMG_MAGIC.Length);
                    i += RAD_IMG_MAGIC.Length;

                    // version
                    f.WriteByte((byte)1);
                    i++;

                    // texture info
                    f.WriteByte(hasAlpha ? (byte)1 : (byte)0);
                    f.WriteByte(fullAlpha ? (byte)1 : (byte)0);
                    f.WriteByte(isMask ? (byte)1 : (byte)0);
                    i += 3;

                    // texture size
                    byte[] uncompressedSize = Utils.IntToBytes(tgaData.Length);
                    f.Write(uncompressedSize, 0, uncompressedSize.Length);
                    i += uncompressedSize.Length;

                    // texture id
                    byte[] id = new byte[16];
                    textureID.ToBytes(id, 0);
                    f.Write(id, 0, 16);
                    i += 16;

                    // compressed texture data
                    using (var compressed = new DeflateStream(f, CompressionMode.Compress))
                    {
                        compressed.Write(tgaData, 0, tgaData.Length);
                    }
                }
                return(true);
            }
            catch (Exception ex)
            {
                Logger.DebugLog(string.Format("Failed to save radegast cache file {0}: {1}", textureID, ex.Message));
                return(false);
            }
        }
示例#5
0
        private void TransferNotFound(LLAgent agent, UUID transferID, UUID assetID, AssetType type)
        {
            m_log.Info("TransferNotFound for asset " + assetID + " with type " + type);

            TransferInfoPacket response = new TransferInfoPacket();

            response.TransferInfo            = new TransferInfoPacket.TransferInfoBlock();
            response.TransferInfo.TransferID = transferID;

            // Set the response channel type
            response.TransferInfo.ChannelType = (int)ChannelType.Asset;

            // Params
            response.TransferInfo.Params = new byte[20];
            assetID.ToBytes(response.TransferInfo.Params, 0);
            Utils.IntToBytes((int)type, response.TransferInfo.Params, 16);

            response.TransferInfo.Size       = 0;
            response.TransferInfo.Status     = (int)StatusCode.UnknownSource;
            response.TransferInfo.TargetType = (int)TargetType.Unknown;

            m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false);
        }
示例#6
0
        private void TransferDownload(LLAgent agent, UUID transferID, UUID assetID, AssetType type, Asset asset)
        {
            const int MAX_CHUNK_SIZE = 1000;

            string contentType = LLUtil.LLAssetTypeToContentType((int)type);

            if (contentType == asset.ContentType)
            {
                m_log.Debug(String.Format("Transferring asset {0} ({1})", asset.ID, asset.ContentType));

                TransferInfoPacket response = new TransferInfoPacket();
                response.TransferInfo            = new TransferInfoPacket.TransferInfoBlock();
                response.TransferInfo.TransferID = transferID;

                // Set the response channel type
                response.TransferInfo.ChannelType = (int)ChannelType.Asset;

                // Params
                response.TransferInfo.Params = new byte[20];
                assetID.ToBytes(response.TransferInfo.Params, 0);
                Utils.IntToBytes((int)type, response.TransferInfo.Params, 16);

                response.TransferInfo.Size       = asset.Data.Length;
                response.TransferInfo.Status     = (int)StatusCode.OK;
                response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client

                m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false);

                // Transfer system does not wait for ACKs, just sends all of the
                // packets for this transfer out
                int processedLength = 0;
                int packetNum       = 0;
                while (processedLength < asset.Data.Length)
                {
                    TransferPacketPacket transfer = new TransferPacketPacket();
                    transfer.TransferData.ChannelType = (int)ChannelType.Asset;
                    transfer.TransferData.TransferID  = transferID;
                    transfer.TransferData.Packet      = packetNum++;

                    int chunkSize = Math.Min(asset.Data.Length - processedLength, MAX_CHUNK_SIZE);
                    transfer.TransferData.Data = new byte[chunkSize];
                    Buffer.BlockCopy(asset.Data, processedLength, transfer.TransferData.Data, 0, chunkSize);
                    processedLength += chunkSize;

                    if (processedLength >= asset.Data.Length)
                    {
                        transfer.TransferData.Status = (int)StatusCode.Done;
                    }
                    else
                    {
                        transfer.TransferData.Status = (int)StatusCode.OK;
                    }

                    m_udp.SendPacket(agent, transfer, ThrottleCategory.Asset, false);
                }
            }
            else
            {
                m_log.WarnFormat("Request for asset {0} with type {1} does not match actual asset type {2}",
                                 assetID, type, asset.ContentType);

                TransferNotFound(agent, transferID, assetID, type);
            }
        }
示例#7
0
文件: Assets.cs 项目: thoys/simian
        private void TransferDownload(LLAgent agent, UUID transferID, UUID assetID, AssetType type, Asset asset)
        {
            const int MAX_CHUNK_SIZE = 1000;

            string contentType = LLUtil.LLAssetTypeToContentType((int)type);

            if (contentType == asset.ContentType)
            {
                m_log.Debug(String.Format("Transferring asset {0} ({1})", asset.ID, asset.ContentType));

                TransferInfoPacket response = new TransferInfoPacket();
                response.TransferInfo = new TransferInfoPacket.TransferInfoBlock();
                response.TransferInfo.TransferID = transferID;

                // Set the response channel type
                response.TransferInfo.ChannelType = (int)ChannelType.Asset;

                // Params
                response.TransferInfo.Params = new byte[20];
                assetID.ToBytes(response.TransferInfo.Params, 0);
                Utils.IntToBytes((int)type, response.TransferInfo.Params, 16);

                response.TransferInfo.Size = asset.Data.Length;
                response.TransferInfo.Status = (int)StatusCode.OK;
                response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client

                m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false);

                // Transfer system does not wait for ACKs, just sends all of the
                // packets for this transfer out
                int processedLength = 0;
                int packetNum = 0;
                while (processedLength < asset.Data.Length)
                {
                    TransferPacketPacket transfer = new TransferPacketPacket();
                    transfer.TransferData.ChannelType = (int)ChannelType.Asset;
                    transfer.TransferData.TransferID = transferID;
                    transfer.TransferData.Packet = packetNum++;

                    int chunkSize = Math.Min(asset.Data.Length - processedLength, MAX_CHUNK_SIZE);
                    transfer.TransferData.Data = new byte[chunkSize];
                    Buffer.BlockCopy(asset.Data, processedLength, transfer.TransferData.Data, 0, chunkSize);
                    processedLength += chunkSize;

                    if (processedLength >= asset.Data.Length)
                        transfer.TransferData.Status = (int)StatusCode.Done;
                    else
                        transfer.TransferData.Status = (int)StatusCode.OK;

                    m_udp.SendPacket(agent, transfer, ThrottleCategory.Asset, false);
                }
            }
            else
            {
                m_log.WarnFormat("Request for asset {0} with type {1} does not match actual asset type {2}",
                    assetID, type, asset.ContentType);

                TransferNotFound(agent, transferID, assetID, type);
            }
        }
示例#8
0
文件: Assets.cs 项目: thoys/simian
        private void TransferNotFound(LLAgent agent, UUID transferID, UUID assetID, AssetType type)
        {
            m_log.Info("TransferNotFound for asset " + assetID + " with type " + type);

            TransferInfoPacket response = new TransferInfoPacket();
            response.TransferInfo = new TransferInfoPacket.TransferInfoBlock();
            response.TransferInfo.TransferID = transferID;

            // Set the response channel type
            response.TransferInfo.ChannelType = (int)ChannelType.Asset;

            // Params
            response.TransferInfo.Params = new byte[20];
            assetID.ToBytes(response.TransferInfo.Params, 0);
            Utils.IntToBytes((int)type, response.TransferInfo.Params, 16);

            response.TransferInfo.Size = 0;
            response.TransferInfo.Status = (int)StatusCode.UnknownSource;
            response.TransferInfo.TargetType = (int)TargetType.Unknown;

            m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false);
        }
 public void AddUUID(UUID v)
 {
     v.ToBytes(m_tmp, 0);
     AddBytes(m_tmp, 16);
 }
示例#10
0
        public string compressUUID(UUID input)
        {
            byte[] compressed = new byte[16];
            char[] compressedC = new char[16];
            input.ToBytes(compressed, 0);

            for (int x = 0; x < 16; x++)
            {
                compressedC[x] = (char)compressed[x];
            }

            return (new string(compressedC, 0, 16));
        }
示例#11
0
        private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
        {
            if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);

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

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

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

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

                        // and the sessionid is the role
                        m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID);

                        GridInstantMessage msg = new GridInstantMessage();
                        msg.imSessionID = UUID.Zero.Guid;
                        msg.fromAgentID = UUID.Zero.Guid;
                        msg.toAgentID = inviteInfo.AgentID.Guid;
                        msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
                        msg.fromAgentName = "Groups";
                        msg.message = string.Format("You have been added to the group.");
                        msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox;
                        msg.fromGroup = false;
                        msg.offline = (byte)0;
                        msg.ParentEstateID = 0;
                        msg.Position = Vector3.Zero;
                        msg.RegionID = UUID.Zero.Guid;
                        msg.binaryBucket = new byte[0];

                        OutgoingInstantMessage(msg, inviteInfo.AgentID);

                        //WTH??? noone but the invitee needs to know
                        //UpdateAllClientsWithGroupInfo(inviteInfo.AgentID);
                        SendAgentGroupDataUpdate(remoteClient);
                        // XTODO: If the inviter is still online, they need an agent dataupdate 
                        // and maybe group membership updates for the invitee
                        // Reply: why do they need that? they will get told about the new user when they reopen the groups panel

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

                    // Reject
                    if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
                    {
                        if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice.");
                        m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID);
                    }
                }
            }

            // Group notices
            if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
            {
                if (!m_groupNoticesEnabled)
                    return;

                UUID GroupID = new UUID(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 = OpenMetaverse.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 = new InventoryItemBase(ItemID, GetRequestingAgentID(remoteClient));
                            item = m_sceneList[0].InventoryService.GetItem(item);
                            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);

                    // Send notice out to everyone that wants notices
                    foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
                    {
                        if (m_debugEnabled)
                        {
                            UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID);
                            if (targetUser != null)
                            {
                                m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices);
                            }
                            else
                            {
                                m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices);
                            }
                        }

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

                            msg.toAgentID = member.AgentID.Guid;
                            OutgoingInstantMessage(msg, member.AgentID);
                        }
                    }
                }
            }
            if ((im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryDeclined) || (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryDeclined))
            {
                GroupAttachmentCache.Remove(im.imSessionID);
            }
            if ((im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted) || (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted))
            {
                UUID FolderID = new UUID(im.binaryBucket, 0);
                InventoryItemBase item = new InventoryItemBase(GroupAttachmentCache[im.imSessionID]);
                item = ((Scene)remoteClient.Scene).InventoryService.GetItem(item);
                
                ILLClientInventory inventoryModule = remoteClient.Scene.RequestModuleInterface<ILLClientInventory>();
                if (inventoryModule != null)
                    item = inventoryModule.GiveInventoryItem(remoteClient.AgentId, item.Owner, GroupAttachmentCache[im.imSessionID], FolderID);

                if (item != null)
                    remoteClient.SendBulkUpdateInventory(item);
                GroupAttachmentCache.Remove(im.imSessionID);
            }
            
            if ((im.dialog == 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 = new UUID(im.toAgentID);

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

                IClientAPI ejectee = GetActiveClient(ejecteeID);
                if (ejectee != null)
                {
                    UUID groupID = new UUID(im.imSessionID);
                    ejectee.SendAgentDropGroup(groupID);
                }
            }

            // Interop, received special 211 code for offline group notice
            if ((im.dialog == 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(new UUID(im.toAgentID), new UUID(im.imSessionID));

                //We reset the ID so that if this was set before, it won't be misadded or anything to the cache
                im.imSessionID = UUID.Random().Guid; 

                //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
                    GroupAttachmentCache[im.imSessionID] = 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, new UUID(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;
            }
        }
示例#12
0
        // This bucket format is the longer database-stored format for binary notice data.
        private byte[] FormatBucketForStorage(bool HasAttachment, byte AssetType, UUID GroupID, UUID ItemID, UUID NoticeID, string AttachmentName)
        {
            byte[] bucket = null;
            if (HasAttachment)
            {
                byte[] nameBytes = OpenMetaverse.Utils.StringToBytes(AttachmentName);
                int nameLen = nameBytes.GetLength(0);

                // old bucket byte buffer is bool,invtype,[2]ownerID,[18]itemID,[34]name
                // new bucket byte buffer is bool,invtype,[2]ownerID,[18]itemID,[34]0x01,[35]version,[36]noticeID,[52]name
                bucket = new byte[1 + 1 + 16 + 16 + 16 + 1 + 1 + nameLen];
                bucket[0] = 1;                          // HasAttachment boolean
                bucket[1] = AssetType;                  // attachment asset/inventory type
                GroupID.ToBytes(bucket, 2);             // 16-byte UUID
                ItemID.ToBytes(bucket, 18);             // 16-byte UUID
                bucket[34] = (byte)1;                   // sign of new extended format
                bucket[35] = (byte)0;                   // version number of new format
                NoticeID.ToBytes(bucket, 36);           // 16-byte UUID
                Array.Copy(nameBytes, 0, bucket, ATTACH_NAME_OFFSET, nameLen);  //  name
            }
            else
            {
                bucket = new byte[1 + 1 + 16 + 16 + 16 + 1 + 1 + 1];
                bucket[0] = 0;                          // HasAttachment boolean
                bucket[1] = 0;                          // attachment type
                UUID.Zero.ToBytes(bucket, 2);           // 16-byte UUID
                UUID.Zero.ToBytes(bucket, 18);          // 16-byte UUID
                bucket[34] = (byte)1;                   // sign of new extended format
                bucket[35] = (byte)0;                   // version number of new format
                NoticeID.ToBytes(bucket, 36);           // 16-byte UUID
                bucket[ATTACH_NAME_OFFSET] = 0;         //  name
            }
            return bucket;
        }
示例#13
0
        // This bucket format is the NOT database-stored format for binary notice data, but rather the data sent to the viewer in the IM packet.
        public byte[] FormatBucketForIM(bool HasAttachment, byte AttType, UUID GroupID, string AttName)
        {
            byte[] nameBytes = OpenMetaverse.Utils.StringToBytes(" "+AttName);
            int nameLen = nameBytes.GetLength(0);
            byte[] bucket = new byte[18+nameLen];

            // bucket byte buffer is HasAttachment, invtype, ownerID, name
            bucket[0] = HasAttachment ? (byte)0x01 : (byte)0x00;
            bucket[1] = AttType;
            GroupID.ToBytes(bucket, 2); // 16-byte UUID
            Array.Copy(nameBytes, 0, bucket, 18, nameLen);  //  name
            return bucket;
        }
示例#14
0
        public static bool SaveCachedImage(byte[] tgaData, UUID textureID, bool hasAlpha, bool fullAlpha, bool isMask)
        {
            try
            {
                string fname = System.IO.Path.Combine(RadegastInstance.GlobalInstance.Client.Settings.ASSET_CACHE_DIR, string.Format("{0}.rzi", textureID));
                //string fname = System.IO.Path.Combine(".", string.Format("{0}.rzi", textureID));

                using (var f = File.Open(fname, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    int i = 0;
                    // magic header
                    f.Write(Utils.StringToBytes(RAD_IMG_MAGIC), 0, RAD_IMG_MAGIC.Length);
                    i += RAD_IMG_MAGIC.Length;

                    // version
                    f.WriteByte((byte)1);
                    i++;

                    // texture info
                    f.WriteByte(hasAlpha ? (byte)1 : (byte)0);
                    f.WriteByte(fullAlpha ? (byte)1 : (byte)0);
                    f.WriteByte(isMask ? (byte)1 : (byte)0);
                    i += 3;

                    // texture size
                    byte[] uncompressedSize = Utils.IntToBytes(tgaData.Length);
                    f.Write(uncompressedSize, 0, uncompressedSize.Length);
                    i += uncompressedSize.Length;

                    // texture id
                    byte[] id = new byte[16];
                    textureID.ToBytes(id, 0);
                    f.Write(id, 0, 16);
                    i += 16;

                    // compressed texture data
                    using (var compressed = new DeflateStream(f, CompressionMode.Compress))
                    {
                        compressed.Write(tgaData, 0, tgaData.Length);
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                Logger.DebugLog(string.Format("Failed to save radegast cache file {0}: {1}", textureID, ex.Message));
                return false;
            }
        }
示例#15
0
 public override void ToBytes(byte[] bytes, ref int i)
 {
     ObjectID.ToBytes(bytes, i); i += 16;
 }
示例#16
0
        private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
        {
            if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);

            // Group invitations
            if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
            {
                UUID inviteID = new UUID(im.imSessionID);
                GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID);

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

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

                        // and the sessionid is the role
                        m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID, false);

                        GridInstantMessage msg = new GridInstantMessage();
                        msg.imSessionID = UUID.Zero.Guid;
                        msg.fromAgentID = UUID.Zero.Guid;
                        msg.toAgentID = inviteInfo.AgentID.Guid;
                        msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
                        msg.fromAgentName = "Groups";
                        msg.message = string.Format("You have been added to the group.");
                        msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox;
                        msg.fromGroup = false;
                        msg.offline = (byte)0;  // don't bother storing this one to fetch on login if user offline
                        msg.ParentEstateID = 0;
                        msg.Position = Vector3.Zero;
                        msg.RegionID = UUID.Zero.Guid;
                        msg.binaryBucket = new byte[0];

                        OutgoingInstantMessage(msg, inviteInfo.AgentID);

                        UpdateAllClientsWithGroupInfo(inviteInfo.AgentID);

                        // TODO: If the inviter is still online, they need an agent dataupdate 
                        // and maybe group membership updates for the invitee

                        m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID);
                    }

                    // Reject
                    if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
                    {
                        if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice.");
                        m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID);
                    }
                }
            }

            // Group notices
            if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
            {
                if (!m_groupNoticesEnabled)
                {
                    return;
                }
                if (im.offline != 0)
                {
                    // Delivery of stored (offline) IMs is handled by the caller
                    return;
                }

                UUID GroupID = new UUID(im.toAgentID);
                GroupRecord group = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null);
                if (group == null)
                {
                    m_log.ErrorFormat("[GROUPS]: Failed to find notice group {0}", GroupID);
                    return;
                }

                UUID NoticeID = UUID.Random();
                string Subject = im.message.Substring(0, im.message.IndexOf('|'));
                string Message = im.message.Substring(Subject.Length + 1);

                byte[] bucket;

                if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0))
                {
                    // Sending a notice without an attachment
                    bucket = new byte[19];
                    bucket[0] = 0; // HasAttachment boolean
                    bucket[1] = 0; // attachment type
                    GroupID.ToBytes(bucket, 2);
                    bucket[18] = 0; // attachment name
                }
                else
                {
                    // Sending a notice with an attachment
                    string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
                    binBucket = binBucket.Remove(0, 14).Trim();
                    OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
                    UUID itemId = binBucketOSD["item_id"].AsUUID();
                    UUID ownerID = binBucketOSD["owner_id"].AsUUID();
                    if (ownerID != remoteClient.AgentId)
                    {
                        m_log.ErrorFormat("[GROUPS]: Notice attachment in group {0} not owned {1} by the user sending it {2}", GroupID.ToString(), ownerID.ToString(), remoteClient.AgentId);
                        return;
                    }

                    CachedUserInfo ownerUserInfo = m_sceneList[0].CommsManager.UserService.GetUserDetails(ownerID);
                    if (ownerUserInfo == null)
                    {
                        m_log.ErrorFormat("[GROUPS]: Failed to find notice sender {0} for item {1}", ownerID, itemId);
                        return;
                    }

                    InventoryItemBase item = ownerUserInfo.FindItem(itemId);
                    if (item == null)
                    {
                        m_log.ErrorFormat("[GROUPS]: Item {0} not found for notice sender {1}", itemId, ownerID);
                        return;
                    }

                    if (!m_sceneList[0].Permissions.BypassPermissions())
                    {
                        if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) ||
                            ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0))
                        {
                            remoteClient.SendAgentAlertMessage("Notice attachments must be copyable and transferable.", false);
                            return;
                        }
                    }

                    // Clone the item for storage as a group-owned item in the db that is NOT in any user's inventory.
                    InventoryItemBase groupItem = AddToGroupInventory(remoteClient, group, item);

                    // format for database storage
                    bucket = FormatBucketForStorage(true, (byte)groupItem.AssetType, GroupID, groupItem.ID, NoticeID, item.Name);
                }
                if (m_groupData.AddGroupNotice(GetClientGroupRequestID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket))
                {
                    // Once added to the DB above with owner ID, replace that with the GroupID that the viewers need
                    GroupID.ToBytes(bucket, 2);         // 16-byte UUID
                    if (OnNewGroupNotice != null)
                    {
                        OnNewGroupNotice(GroupID, NoticeID);
                    }

                    // Get the list of users who have this sender muted.
                    List<UUID> muters;
                    m_muteListModule = m_sceneList[0].RequestModuleInterface<IMuteListModule>();
                    if (m_muteListModule != null)
                        muters = m_muteListModule.GetInverseMuteList(remoteClient.AgentId);
                    else
                        muters = new List<UUID>();
                    // Send notice out to everyone that wants notices
                    foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), GroupID, false))
                    {
                        if (member.AcceptNotices && !muters.Contains(member.AgentID))
                        {
                            SendGroupNoticeIM(NoticeID, member.AgentID, OpenMetaverse.InstantMessageDialog.GroupNotice, false);
                        }
                    }
                }
            }
            if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryDeclined)
            {
                if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: Declined - removing session {0}", im.imSessionID);
                lock (GroupAttachmentCache) {
                    GroupAttachmentCache.Remove(im.imSessionID);
                }
            }
            if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
            {
                UUID NoticeID = UUID.Zero;
                lock (GroupAttachmentCache) {
                    if (GroupAttachmentCache.ContainsKey(im.imSessionID))
                    {
                        // Retrieve the notice ID and remove it from the cache.
                        NoticeID = GroupAttachmentCache[im.imSessionID];
                        GroupAttachmentCache.Remove(im.imSessionID);
                    }
                }
                if (NoticeID == UUID.Zero)
                {
                    m_log.ErrorFormat("[GROUPS]: Accepted attachment for session {0} - NOT FOUND", im.imSessionID);
                    remoteClient.SendAgentAlertMessage("Attachment not saved - specified group notice not found.", false);
                    return;
                }

                if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: Accepted attachment for session {0} notice {1}", im.imSessionID, NoticeID);

                GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetClientGroupRequestID(remoteClient), NoticeID);
                if (notice == null)
                {
                    remoteClient.SendAgentAlertMessage("Could not find the required group notice.", false);
                    return;
                }
                InitializeNoticeFromBucket(notice);

                UUID groupId = notice.GroupID;
                UUID itemId = notice.noticeData.ItemID;

                // we need a userInfo structure to get the sessionID to use in case the inventory service needs a secure service connection
                CachedUserInfo userInfo = m_sceneList[0].CommsManager.UserService.GetUserDetails(remoteClient.AgentId);
                if (userInfo == null)
                {
                    m_log.ErrorFormat("[GROUPS]: Failed to find notice recipient {0} for item {1}", remoteClient.AgentId, itemId);
                    remoteClient.SendAgentAlertMessage("Attachment not saved - user profile not found.", false);
                    return;
                }
                
                InventoryItemBase groupItem = FetchGroupItem(groupId, itemId);
                if (groupItem == null)  // For now support fallback to the legacy inventory system.
                    groupItem = FindLegacyInventoryItem(groupId, itemId);

                if (groupItem != null) {
                    InventoryItemBase deliveredItem = DeliverGroupInventory(remoteClient, groupId, groupItem);
                    if (deliveredItem != null)
                    {
                        remoteClient.SendInventoryItemCreateUpdate(deliveredItem, 0);
                        remoteClient.SendAgentAlertMessage("Group notice attachment '"+groupItem.Name+"' saved to inventory.", false);
                    }
                    else
                    {
                        remoteClient.SendAgentAlertMessage("Attachment not saved - delivery failed.", false);
                        m_log.ErrorFormat("[GROUPS]: Failed to deliver notice attachment {0} for {1}", itemId, remoteClient.AgentId);
                    }
                }
                else
                {
                    remoteClient.SendAgentAlertMessage("Attachment not saved - item not found.", false);
                    m_log.ErrorFormat("[GROUPS]: Missing notice attachment {0} for {1}", itemId, remoteClient.AgentId);
                }
                if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: Accepted and completed for session {0}", im.imSessionID);
            }
            
            // Interop, received special 210 code for ejecting a group member
            // this only works within the comms servers domain, and won't work hypergrid
            // TODO:FIXME: Use a presense server of some kind to find out where the 
            // client actually is, and try contacting that region directly to notify them,
            // or provide the notification via xmlrpc update queue
            if ((im.dialog == 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 = new UUID(im.toAgentID);

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

                IClientAPI ejectee = GetActiveClient(ejecteeID);
                if (ejectee != null)
                {
                    UUID groupID = new UUID(im.fromAgentID);
                    ejectee.SendAgentDropGroup(groupID);
                }
            }
        }
示例#17
0
        private void SendGroupNoticeIM(UUID NoticeID, UUID AgentID, OpenMetaverse.InstantMessageDialog dialog, bool checkMuted)
        {
            // Build notice IIM
            GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)dialog);
            if (msg == null)
                return;     // old bad one stored from offlines?
            UUID sender = new UUID(msg.fromAgentID);

            if (checkMuted)
            {
                m_muteListModule = m_sceneList[0].RequestModuleInterface<IMuteListModule>();
                if (m_muteListModule != null)
                    if (m_muteListModule.IsMuted(sender, AgentID))
                        return;
            }

            bool HasAttachment = (msg.binaryBucket[0] != 0);
            if (HasAttachment)  // save the notice with the session ID
            {
                lock (GroupAttachmentCache) {
                    GroupAttachmentCache[msg.imSessionID] = NoticeID;
                }
            }

            msg.toAgentID = AgentID.Guid;

            IClientAPI localClient = GetActiveClient(AgentID);
            if (localClient != null)
            {
                if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: Recipient ({0}) is local, delivering group notice directly", localClient.Name);
                localClient.SendInstantMessage(msg);
            }
            else
            {
                // send for offline storage
                if (HasAttachment)  // clean up the cache item added above
                {
                    lock (GroupAttachmentCache) {
                        GroupAttachmentCache.Remove(msg.imSessionID);
                    }
                }
                // need to reformat this with db storage bucket, not the viewer IM bucket
                // format for database storage
                int bucketLen = msg.binaryBucket.Length;
                byte[] OfflineBucket = new byte[bucketLen + 4 + 16];
                OfflineBucket[0] = 0xFF; // sign, would be 00 or 01 here in a normal viewer IM bucket
                OfflineBucket[1] = 0x00; OfflineBucket[2] = 0x00; OfflineBucket[3] = 0x00; // Spare bytes
                NoticeID.ToBytes(OfflineBucket, 4);    // 16-byte UUID
                msg.binaryBucket.CopyTo(OfflineBucket, 20);
                msg.binaryBucket = OfflineBucket;
                if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: Recipient ({0}) is not local, delivering group notice via TransferModule", msg.toAgentID);
                m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Message Sent: {0}", success ? "Succeeded" : "Failed"); });
            }
        }
示例#18
0
 private byte[] CreateBitBucketForGroupAttachment(GroupNoticeData groupNoticeData, UUID groupID)
 {
     int i = 20;
     i += groupNoticeData.ItemName.Length;
     byte[] bitbucket = new byte[i];
     groupID.ToBytes(bitbucket, 2);
     byte[] name = Utils.StringToBytes(" " + groupNoticeData.ItemName);
     Array.ConstrainedCopy(name, 0, bitbucket, 18, name.Length);
     //Utils.Int16ToBytes((short)item.AssetType, bitbucket, 0);
     bitbucket[0] = 1; // 0 for no attachment, 1 for attachment
     bitbucket[1] = (byte)groupNoticeData.AssetType; // Asset type
     
     return bitbucket;
 }
 private void AddToCompiledWL(UUID v, ref byte[] mBlock, ref int pos)
 {
     v.ToBytes(mBlock, pos);
     pos += 16;
 }
示例#20
0
        private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
        {
            if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);

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

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

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

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

                        // and the sessionid is the role
                        m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID);

                        GridInstantMessage msg = new GridInstantMessage();
                        msg.imSessionID = UUID.Zero.Guid;
                        msg.fromAgentID = UUID.Zero.Guid;
                        msg.toAgentID = inviteInfo.AgentID.Guid;
                        msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
                        msg.fromAgentName = "Groups";
                        msg.message = string.Format("You have been added to the group.");
                        msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox;
                        msg.fromGroup = false;
                        msg.offline = (byte)0;
                        msg.ParentEstateID = 0;
                        msg.Position = Vector3.Zero;
                        msg.RegionID = UUID.Zero.Guid;
                        msg.binaryBucket = new byte[0];

                        OutgoingInstantMessage(msg, inviteInfo.AgentID);

                        UpdateAllClientsWithGroupInfo(inviteInfo.AgentID);

                        // TODO: If the inviter is still online, they need an agent dataupdate 
                        // and maybe group membership updates for the invitee

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

                    // Reject
                    if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
                    {
                        if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice.");
                        m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID);
                    }
                }
            }

            // Group notices
            if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
            {
                if (!m_groupNoticesEnabled)
                {
                    return;
                }

                UUID GroupID = new UUID(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;

                    if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0))
                    {
                        bucket = new byte[19];
                        bucket[0] = 0; //dunno
                        bucket[1] = 0; //dunno
                        GroupID.ToBytes(bucket, 2);
                        bucket[18] = 0; //dunno
                    }
                    else
                    {
                        string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
                        binBucket = binBucket.Remove(0, 14).Trim();
                        if (m_debugEnabled)
                        {
                            m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket);

                            OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
                            
                            foreach (string key in binBucketOSD.Keys)
                            {
                                if (binBucketOSD.ContainsKey(key))
                                {
                                    m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
                                }
                            }
                        }
   
                        // treat as if no attachment
                        bucket = new byte[19];
                        bucket[0] = 0; //dunno
                        bucket[1] = 0; //dunno
                        GroupID.ToBytes(bucket, 2);
                        bucket[18] = 0; //dunno
                    }

                    
                    m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
                    if (OnNewGroupNotice != null)
                    {
                        OnNewGroupNotice(GroupID, NoticeID);
                    }

                    // Send notice out to everyone that wants notices
                    foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
                    {
                         if (m_debugEnabled)
                        {
                            UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID);
                            if (targetUser != null)
                            {
                                m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices);
                            }
                            else
                            {
                                m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices);
                            }
                        }

                       if (member.AcceptNotices)
                        {
                            // Build notice IIM
                            GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);

                            msg.toAgentID = member.AgentID.Guid;
                            OutgoingInstantMessage(msg, member.AgentID);
                        }
                    }
                }
            }
            
            // Interop, received special 210 code for ejecting a group member
            // this only works within the comms servers domain, and won't work hypergrid
            // TODO:FIXME: Use a presense server of some kind to find out where the 
            // client actually is, and try contacting that region directly to notify them,
            // or provide the notification via xmlrpc update queue
            if ((im.dialog == 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 = new UUID(im.toAgentID);

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

                IClientAPI ejectee = GetActiveClient(ejecteeID);
                if (ejectee != null)
                {
                    UUID groupID = new UUID(im.imSessionID);
                    ejectee.SendAgentDropGroup(groupID);
                }
            }
        }
示例#21
0
        private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
        {
            if (m_debugEnabled) 
                m_log.DebugFormat(
                    "[GROUPS]: {0} called for {1}, message type {2}", 
                    System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name, (InstantMessageDialog)im.dialog);

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

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

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

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

                        // and the sessionid is the role
                        m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID);

                        GridInstantMessage msg = new GridInstantMessage();
                        msg.imSessionID = UUID.Zero.Guid;
                        msg.fromAgentID = UUID.Zero.Guid;
                        msg.toAgentID = inviteInfo.AgentID.Guid;
                        msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
                        msg.fromAgentName = "Groups";
                        msg.message = string.Format("You have been added to the group.");
                        msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox;
                        msg.fromGroup = false;
                        msg.offline = (byte)0;
                        msg.ParentEstateID = 0;
                        msg.Position = Vector3.Zero;
                        msg.RegionID = UUID.Zero.Guid;
                        msg.binaryBucket = new byte[0];

                        OutgoingInstantMessage(msg, inviteInfo.AgentID);

                        IClientAPI client = GetActiveClient(inviteInfo.AgentID);
                        if (client != null)
                            SendDataUpdate(remoteClient, true);

                        // TODO: If the inviter is still online, they need an agent dataupdate 
                        // and maybe group membership updates for the invitee

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

                    // Reject
                    if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
                    {
                        if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice.");
                        m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID);
                    }
                }
            }

            // Group notices
            if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
            {
                if (!m_groupNoticesEnabled)
                {
                    return;
                }

                UUID GroupID = new UUID(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);

                    InventoryItemBase item = null;
                    bool hasAttachment = false;
                    UUID itemID = UUID.Zero;    //Assignment to quiet compiler
                    UUID ownerID = UUID.Zero;   //Assignment to quiet compiler
                    byte[] bucket;

                    if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
                    {
                        string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
                        binBucket = binBucket.Remove(0, 14).Trim();

                        OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
                        if (binBucketOSD is OSD)
                        {
                            OSDMap binBucketMap = (OSDMap)binBucketOSD;

                            itemID = binBucketMap["item_id"].AsUUID();
                            ownerID = binBucketMap["owner_id"].AsUUID();

                            //Attempt to get the details of the attached item.
                            //If sender doesn't own the attachment, the item
                            //variable will be set to null and attachment will
                            //not be included with the group notice.
                            Scene scene = (Scene)remoteClient.Scene;
                            item = new InventoryItemBase(itemID, ownerID);
                            item = scene.InventoryService.GetItem(item);

                            if (item != null)
                            {
                                //Got item details so include the attachment.
                                hasAttachment = true;
                            }
                        }
                        else
                        {
                            m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
                        }
                    }

                    if (hasAttachment)
                    {
                        //Bucket contains information about attachment.
                        //
                        //Byte offset and description of bucket data:
                        //0:  1 byte indicating if attachment is present
                        //1:  1 byte indicating the type of attachment
                        //2:  16 bytes - Group UUID
                        //18: 16 bytes - UUID of the attachment owner
                        //34: 16 bytes - UUID of the attachment
                        //50: variable - Name of the attachment
                        //??: NUL byte to terminate the attachment name
                        byte[] name = Encoding.UTF8.GetBytes(item.Name);
                        bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name
                        bucket[0] = 1;                      //Has attachment flag
                        bucket[1] = (byte)item.InvType;     //Type of Attachment
                        GroupID.ToBytes(bucket, 2);
                        ownerID.ToBytes(bucket, 18);
                        itemID.ToBytes(bucket, 34);
                        name.CopyTo(bucket, 50);
                    }
                    else
                    {
                        bucket = new byte[19];
                        bucket[0] = 0;  //Has attachment flag
                        bucket[1] = 0;  //Type of attachment
                        GroupID.ToBytes(bucket, 2);
                        bucket[18] = 0; //NUL terminate name of attachment
                    }

                    m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
                    if (OnNewGroupNotice != null)
                    {
                        OnNewGroupNotice(GroupID, NoticeID);
                    }

                    if (m_debugEnabled)
                    {
                        foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
                        {
                            if (m_debugEnabled)
                            {
                                UserAccount targetUser
                                    = m_sceneList[0].UserAccountService.GetUserAccount(
                                        remoteClient.Scene.RegionInfo.ScopeID, member.AgentID);

                                if (targetUser != null)
                                {
                                    m_log.DebugFormat(
                                        "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", 
                                        NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices);
                                }
                                else
                                {
                                    m_log.DebugFormat(
                                        "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", 
                                        NoticeID, member.AgentID, member.AcceptNotices);
                                }
                            }
                        }
                    }

                    GridInstantMessage msg 
                        = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);

                    if (m_groupsMessagingModule != null)
                        m_groupsMessagingModule.SendMessageToGroup(
                            msg, GroupID, remoteClient.AgentId, gmd => gmd.AcceptNotices);
                }
            }

            if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
            {
                //Is bucket large enough to hold UUID of the attachment?
                if (im.binaryBucket.Length < 16)
                    return;

                UUID noticeID = new UUID(im.imSessionID);

                if (m_debugEnabled) 
                    m_log.DebugFormat("[GROUPS]: Requesting notice {0} for {1}", noticeID, remoteClient.AgentId);

                GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
                if (notice != null)
                {
                    UUID giver = new UUID(notice.BinaryBucket, 18);
                    UUID attachmentUUID = new UUID(notice.BinaryBucket, 34);

                    if (m_debugEnabled)
                        m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);

                    string message;
                    InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
                        giver, attachmentUUID, out message);

                    if (itemCopy == null)
                    {
                        remoteClient.SendAgentAlertMessage(message, false);
                        return;
                    }

                    remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
                }
                else
                {
                    if (m_debugEnabled) 
                        m_log.DebugFormat(
                            "[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.", 
                            noticeID, remoteClient.AgentId);                   
                }
            }

            // Interop, received special 210 code for ejecting a group member
            // this only works within the comms servers domain, and won't work hypergrid
            // TODO:FIXME: Use a presence server of some kind to find out where the
            // client actually is, and try contacting that region directly to notify them,
            // or provide the notification via xmlrpc update queue
            if ((im.dialog == 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 = new UUID(im.toAgentID);

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

                IClientAPI ejectee = GetActiveClient(ejecteeID);
                if (ejectee != null)
                {
                    UUID groupID = new UUID(im.imSessionID);
                    ejectee.SendAgentDropGroup(groupID);
                }
            }
        }