예제 #1
0
        /// <summary>
        /// Convert raw uploaded data into the appropriate asset and item.
        /// </summary>
        /// <param name="assetID"></param>
        /// <param name="inventoryItem"></param>
        /// <param name="data"></param>
        public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
                                          UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
                                          string assetType, int cost,
                                          UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
                                          bool IsAtestUpload, ref string error,
                                          ref int nextOwnerMask, ref int groupMask, ref int everyoneMask)
        {
            lock (m_ModelCost)
                m_FileAgentInventoryState = FileAgentInventoryState.processUpload;

            m_log.DebugFormat(
                "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
                assetID, inventoryItem, inventoryType, assetType);

            sbyte assType = 0;
            sbyte inType = 0;

            IClientAPI client = null;

            UUID owner_id = m_HostCapsObj.AgentID;
            UUID creatorID;

            bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);

            bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;

            if (istest && m_testAssetsCreatorID != UUID.Zero)
                creatorID = m_testAssetsCreatorID;
            else
                creatorID = owner_id;

            string creatorIDstr = creatorID.ToString();

            IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
            if (mm != null)
            {
                // make sure client still has enougth credit
                if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
                {
                    error = "Insufficient funds.";
                    return;
                }
            }

            // strings to types
            if (inventoryType == "sound")
            {
                inType = (sbyte)InventoryType.Sound;
                assType = (sbyte)AssetType.Sound;
            }
            else if (inventoryType == "snapshot")
            {
                inType = (sbyte)InventoryType.Snapshot;
            }
            else if (inventoryType == "animation")
            {
                inType = (sbyte)InventoryType.Animation;
                assType = (sbyte)AssetType.Animation;
            }
            else if (inventoryType == "animset")
            {
                inType = (sbyte)CustomInventoryType.AnimationSet;
                assType = (sbyte)CustomAssetType.AnimationSet;
                m_log.Debug("got animset upload request");
            }
            else if (inventoryType == "wearable")
            {
                inType = (sbyte)InventoryType.Wearable;
                switch (assetType)
                {
                    case "bodypart":
                        assType = (sbyte)AssetType.Bodypart;
                        break;
                    case "clothing":
                        assType = (sbyte)AssetType.Clothing;
                        break;
                }
            }
            else if (inventoryType == "object")
            {
                if (assetType == "mesh") // this code for now is for mesh models uploads only
                {
                    inType = (sbyte)InventoryType.Object;
                    assType = (sbyte)AssetType.Object;

                    List<Vector3> positions = new List<Vector3>();
                    List<Quaternion> rotations = new List<Quaternion>();
                    OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);

                    // compare and get updated information
/* does nothing still we do need something to avoid special viewer to upload something diferent from the cost estimation
                    bool mismatchError = true;

                    while (mismatchError)
                    {
                        mismatchError = false;
                    }

                    if (mismatchError)
                    {
                        error = "Upload and fee estimation information don't match";
                        lock (m_ModelCost)
                            m_FileAgentInventoryState = FileAgentInventoryState.idle;

                        return;
                    }
*/
                    OSDArray instance_list = (OSDArray)request["instance_list"];
                    OSDArray mesh_list = (OSDArray)request["mesh_list"];
                    OSDArray texture_list = (OSDArray)request["texture_list"];
                    SceneObjectGroup grp = null;

                    // create and store texture assets
                    bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
                                    texturesFolder != UUID.Zero);


                    List<UUID> textures = new List<UUID>();

                   
//                    if (doTextInv)
                        m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);

                    if(client == null) // don't put textures in inventory if there is no client
                        doTextInv = false;

                    for (int i = 0; i < texture_list.Count; i++)
                    {
                        AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
                        textureAsset.Data = texture_list[i].AsBinary();
                        if (istest)
                            textureAsset.Local = true;
                        m_assetService.Store(textureAsset);
                        textures.Add(textureAsset.FullID);

                        if (doTextInv)
                        {
                            string name = assetName;
                            if (name.Length > 25)
                                name = name.Substring(0, 24);
                            name += "_Texture#" + i.ToString();
                            InventoryItemBase texitem = new InventoryItemBase();
                            texitem.Owner = m_HostCapsObj.AgentID;
                            texitem.CreatorId = creatorIDstr;
                            texitem.CreatorData = String.Empty;
                            texitem.ID = UUID.Random();
                            texitem.AssetID = textureAsset.FullID;
                            texitem.Description = "mesh model texture";
                            texitem.Name = name;
                            texitem.AssetType = (int)AssetType.Texture;
                            texitem.InvType = (int)InventoryType.Texture;
                            texitem.Folder = texturesFolder;

                            texitem.CurrentPermissions
                                = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);

                            texitem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
                            texitem.EveryOnePermissions = 0;
                            texitem.NextPermissions = (uint)PermissionMask.All;
                            texitem.CreationDate = Util.UnixTimeSinceEpoch();

                            m_Scene.AddInventoryItem(client, texitem);
                            texitem = null;
                        }
                    }

                    // create and store meshs assets
                    List<UUID> meshAssets = new List<UUID>();
                    List<bool> meshAvatarSkeletons = new List<bool>();
                    List<bool> meshAvatarColliders = new List<bool>();

                    bool curAvSkeleton;
                    bool curAvCollider;
                    for (int i = 0; i < mesh_list.Count; i++)
                    {
                        curAvSkeleton = false;
                        curAvCollider = false;

                        // we do need to parse the mesh now
                        OSD osd = OSDParser.DeserializeLLSDBinary(mesh_list[i]);
                        if (osd is OSDMap)
                        {
                            OSDMap mosd = (OSDMap)osd;
                            if (mosd.ContainsKey("skeleton"))
                            {
                                OSDMap skeleton = (OSDMap)mosd["skeleton"];
                                int sksize = skeleton["size"].AsInteger();
                                if (sksize > 0)
                                    curAvSkeleton = true;
                            }
                        }

                        AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
                        meshAsset.Data = mesh_list[i].AsBinary();
                        if (istest)
                            meshAsset.Local = true;
                        m_assetService.Store(meshAsset);
                        meshAssets.Add(meshAsset.FullID);
                        meshAvatarSkeletons.Add(curAvSkeleton);
                        meshAvatarColliders.Add(curAvCollider);

                        // test code 
                        if (curAvSkeleton && client != null)
                        {
                            string name = assetName;
                            if (name.Length > 25)
                                name = name.Substring(0, 24);
                            name += "_Mesh#" + i.ToString();
                            InventoryItemBase meshitem = new InventoryItemBase();
                            meshitem.Owner = m_HostCapsObj.AgentID;
                            meshitem.CreatorId = creatorIDstr;
                            meshitem.CreatorData = String.Empty;
                            meshitem.ID = UUID.Random();
                            meshitem.AssetID = meshAsset.FullID;
                            meshitem.Description = "mesh ";
                            meshitem.Name = name;
                            meshitem.AssetType = (int)AssetType.Mesh;
                            meshitem.InvType = (int)InventoryType.Mesh;
                            //                            meshitem.Folder = UUID.Zero; // send to default

                            meshitem.Folder = parentFolder; // dont let it go to folder Meshes that viewers dont show

                            // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
                            // (owner) permissions.  This becomes a problem if next permissions are changed.
                            meshitem.CurrentPermissions
                                = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);

                            meshitem.BasePermissions = (uint)PermissionMask.All;
                            meshitem.EveryOnePermissions = 0;
                            meshitem.NextPermissions = (uint)PermissionMask.All;
                            meshitem.CreationDate = Util.UnixTimeSinceEpoch();

                            m_Scene.AddInventoryItem(client, meshitem);
                            meshitem = null;
                        }
                    }

                    int skipedMeshs = 0;
                    // build prims from instances
                    for (int i = 0; i < instance_list.Count; i++)
                    {
                        OSDMap inner_instance_list = (OSDMap)instance_list[i];

                        // skip prims that are 2 small
                        Vector3 scale = inner_instance_list["scale"].AsVector3();

                        if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
                        {
                            skipedMeshs++;
                            continue;
                        }

                        PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();

                        Primitive.TextureEntry textureEntry
                            = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);


                        OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
                        for (uint face = 0; face < face_list.Count; face++)
                        {
                            OSDMap faceMap = (OSDMap)face_list[(int)face];
                            Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
                            if (faceMap.ContainsKey("fullbright"))
                                f.Fullbright = faceMap["fullbright"].AsBoolean();
                            if (faceMap.ContainsKey("diffuse_color"))
                                f.RGBA = faceMap["diffuse_color"].AsColor4();

                            int textureNum = faceMap["image"].AsInteger();
                            float imagerot = faceMap["imagerot"].AsInteger();
                            float offsets = (float)faceMap["offsets"].AsReal();
                            float offsett = (float)faceMap["offsett"].AsReal();
                            float scales = (float)faceMap["scales"].AsReal();
                            float scalet = (float)faceMap["scalet"].AsReal();

                            if (imagerot != 0)
                                f.Rotation = imagerot;

                            if (offsets != 0)
                                f.OffsetU = offsets;

                            if (offsett != 0)
                                f.OffsetV = offsett;

                            if (scales != 0)
                                f.RepeatU = scales;

                            if (scalet != 0)
                                f.RepeatV = scalet;

                            if (textures.Count > textureNum)
                                f.TextureID = textures[textureNum];
                            else
                                f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;

                            textureEntry.FaceTextures[face] = f;
                        }

                        pbs.TextureEntry = textureEntry.GetBytes();

                        bool hasmesh = false;
                        if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
                        {
                            int meshindx = inner_instance_list["mesh"].AsInteger();
                            if (meshAssets.Count > meshindx)
                            {
                                pbs.SculptEntry = true;
                                pbs.SculptType = (byte)SculptType.Mesh;
                                pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
                                // data will be requested from asset on rez (i hope)
                                hasmesh = true;
                            }
                        }

                        Vector3 position = inner_instance_list["position"].AsVector3();
                        Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();

                        // for now viwers do send fixed defaults
                        // but this may change
//                        int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
                        byte physicsShapeType = (byte)PhysShapeType.convex; // default is simple convex
//                        int material = inner_instance_list["material"].AsInteger();
                        byte material = (byte)Material.Wood;

// no longer used - begin ------------------------
//                    int mesh = inner_instance_list["mesh"].AsInteger();

//                    OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
//                    int base_mask = permissions["base_mask"].AsInteger();
//                    int everyone_mask = permissions["everyone_mask"].AsInteger();
//                    UUID creator_id = permissions["creator_id"].AsUUID();
//                    UUID group_id = permissions["group_id"].AsUUID();
//                    int group_mask = permissions["group_mask"].AsInteger();
//                    bool is_owner_group = permissions["is_owner_group"].AsBoolean();
//                    UUID last_owner_id = permissions["last_owner_id"].AsUUID();
//                    int next_owner_mask = permissions["next_owner_mask"].AsInteger();
//                    UUID owner_id = permissions["owner_id"].AsUUID();
//                    int owner_mask = permissions["owner_mask"].AsInteger();
// no longer used - end ------------------------
                       

                        SceneObjectPart prim
                            = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);

                        prim.Scale = scale;
                        rotations.Add(rotation);
                        positions.Add(position);
                        prim.UUID = UUID.Random();
                        prim.CreatorID = creatorID;
                        prim.OwnerID = owner_id;
                        prim.GroupID = UUID.Zero;
                        prim.LastOwnerID = creatorID;
                        prim.CreationDate = Util.UnixTimeSinceEpoch();
                        
                        if (grp == null)
                            prim.Name = assetName;
                        else
                            prim.Name = assetName + "#" + i.ToString();

                        prim.EveryoneMask = 0;
                        prim.GroupMask = 0;

                        if (restrictPerms)
                        {
                            prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
                            prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
                            prim.NextOwnerMask = 0;
                        }
                        else
                        {
                            prim.BaseMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
                            prim.OwnerMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
                            prim.GroupMask = prim.BaseMask & (uint)groupMask;
                            prim.EveryoneMask = prim.BaseMask & (uint)everyoneMask;
                            prim.NextOwnerMask = prim.BaseMask & (uint)nextOwnerMask;
                            // If the viewer gives us bogus permissions, revert to the SL
                            // default of transfer only.
                            if ((prim.NextOwnerMask & (uint)PermissionMask.All) == 0)
                                prim.NextOwnerMask = (uint)PermissionMask.Transfer;
                        }

                        if(istest)
                            prim.Description = "For testing only. Other uses are prohibited";
                        else
                            prim.Description = "";

                        prim.Material = material;
                        prim.PhysicsShapeType = physicsShapeType;

//                    prim.BaseMask = (uint)base_mask;
//                    prim.EveryoneMask = (uint)everyone_mask;
//                    prim.GroupMask = (uint)group_mask;
//                    prim.NextOwnerMask = (uint)next_owner_mask;
//                    prim.OwnerMask = (uint)owner_mask;

                        if (grp == null)
                        {
                            grp = new SceneObjectGroup(prim);
                            grp.LastOwnerID = creatorID;
                        }
                        else
                            grp.AddPart(prim);
                    }

                    Vector3 rootPos = positions[0];

                    if (grp.Parts.Length > 1)
                    {
                        // Fix first link number
                        grp.RootPart.LinkNum++;

                        Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
                        Quaternion tmprot;
                        Vector3 offset;

                        // fix children rotations and positions
                        for (int i = 1; i < rotations.Count; i++)
                        {
                            tmprot = rotations[i];
                            tmprot = rootRotConj * tmprot;

                            grp.Parts[i].RotationOffset = tmprot;

                            offset = positions[i] - rootPos;

                            offset *= rootRotConj;
                            grp.Parts[i].OffsetPosition = offset;
                        }

                        grp.AbsolutePosition = rootPos;
                        grp.UpdateGroupRotationR(rotations[0]);
                    }
                    else
                    {
                        grp.AbsolutePosition = rootPos;
                        grp.UpdateGroupRotationR(rotations[0]);
                    }

                    data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
                }

                else // not a mesh model
                {
                    m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
                    return;
                }
            }

            AssetBase asset;
            asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
            asset.Data = data;
            if (istest)
                asset.Local = true;
            if (AddNewAsset != null)
                AddNewAsset(asset);
            else if (m_assetService != null)
                m_assetService.Store(asset);

            InventoryItemBase item = new InventoryItemBase();
            item.Owner = m_HostCapsObj.AgentID;
            item.CreatorId = creatorIDstr;
            item.CreatorData = String.Empty;
            item.ID = inventoryItem;
            item.AssetID = asset.FullID;
            if (istest)
            {
                item.Description = "For testing only. Other uses are prohibited";
                item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
            }
            else
                item.Description = assetDescription;
            item.Name = assetName;
            item.AssetType = assType;
            item.InvType = inType;
            item.Folder = parentFolder;

            // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
            // (owner) permissions.  This becomes a problem if next permissions are changed.

            if (inType == (sbyte)CustomInventoryType.AnimationSet)
            {
                AnimationSet.setCreateItemPermitions(item);
            }

            else if (restrictPerms)
            {
                item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
                item.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
                item.GroupPermissions = 0;
                item.EveryOnePermissions = 0;
                item.NextPermissions = 0;
            }
            else
            {
                item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
                item.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
                item.GroupPermissions = item.BasePermissions & (uint)groupMask;
                item.EveryOnePermissions = item.BasePermissions & (uint)everyoneMask;
                item.NextPermissions = item.BasePermissions & (uint)nextOwnerMask;
                if ((item.NextPermissions & (uint)PermissionMask.All) == 0)
                    item.NextPermissions = (uint)PermissionMask.Transfer;
            }

            item.CreationDate = Util.UnixTimeSinceEpoch();

            everyoneMask = (int)item.EveryOnePermissions;
            groupMask = (int)item.GroupPermissions;
            nextOwnerMask = (int)item.NextPermissions;

            m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);

            if (AddNewInventoryItem != null)
            {
                if (istest)
                {
                    m_Scene.AddInventoryItem(client, item);
/*
                    AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
                    if (client != null)
                        client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true);
 */
                }
                else
                {
                    AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
//                    if (client != null)
//                    {
//                        // let users see anything..  i don't so far
//                        string str;
//                        if (cost > 0)
//                            // dont remember where is money unit name to put here
//                            str = "Upload complete. charged " + cost.ToString() + "$";
//                        else
//                            str = "Upload complete";
//                        client.SendAgentAlertMessage(str, true);
//                    }
                }
            }

            lock (m_ModelCost)
                m_FileAgentInventoryState = FileAgentInventoryState.idle;
        }
예제 #2
0
        public BunchOfCaps(Scene scene, Caps caps)
        {
            m_Scene = scene;
            m_HostCapsObj = caps;

            // create a model upload cost provider
            m_ModelCost = new ModelCost();
            // tell it about scene object limits
            m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
            m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
            m_ModelCost.ObjectLinkedPartsMax = m_Scene.m_linksetCapacity;
            
//            m_ModelCost.ObjectLinkedPartsMax = ??
//            m_ModelCost.PrimScaleMin = ??

            m_PrimScaleMin = m_ModelCost.PrimScaleMin;
            float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
            float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
            float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
            float modelPrimCreationCost = m_ModelCost.primCreationCost;
            float modelMeshByteCost = m_ModelCost.bytecost;

            IConfigSource config = m_Scene.Config;
            if (config != null)
            {
                IConfig sconfig = config.Configs["Startup"];
                if (sconfig != null)
                {
                    m_levelUpload = sconfig.GetInt("LevelUpload", 0);
                }

                IConfig appearanceConfig = config.Configs["Appearance"];
                if (appearanceConfig != null)
                {
                    m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
                }
                // economy for model upload
                IConfig EconomyConfig = config.Configs["Economy"];
                if (EconomyConfig != null)
                {
                    modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
                    modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
                    modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
                    // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
                    modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
                    modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);

                    m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);

                    m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
                    m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
                    m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
                    string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
                    if (testcreator != "")
                    {
                        UUID id;
                        UUID.TryParse(testcreator, out id);
                        if (id != null)
                            m_testAssetsCreatorID = id;
                    }

                    m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
                    m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
                    m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
                    m_ModelCost.primCreationCost = modelPrimCreationCost;
                    m_ModelCost.bytecost = modelMeshByteCost;
                }
            }

            m_assetService = m_Scene.AssetService;
            m_regionName = m_Scene.RegionInfo.RegionName;

            RegisterHandlers();

            AddNewInventoryItem = m_Scene.AddUploadedInventoryItem;
            ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
            TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
            GetClient = m_Scene.SceneGraph.GetControllingClient;

            m_FileAgentInventoryState = FileAgentInventoryState.idle;
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="llsdRequest"></param>
        /// <returns></returns>
        public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest)
        {
            //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
            //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);

            // start by getting the client
            IClientAPI client = null;
            m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);

            // check current state so we only have one service at a time
            lock (m_ModelCost)
            {
                switch (m_FileAgentInventoryState)
                {
                    case FileAgentInventoryState.processRequest:
                    case FileAgentInventoryState.processUpload:
                        LLSDAssetUploadError resperror = new LLSDAssetUploadError();
                        resperror.message = "Uploader busy processing previus request";
                        resperror.identifier = UUID.Zero;

                        LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
                        errorResponse.uploader = "";
                        errorResponse.state = "error";
                        errorResponse.error = resperror;
                        return errorResponse;
                        break;
                    case FileAgentInventoryState.waitUpload:
                        // todo stop current uploader server
                        break;
                    case FileAgentInventoryState.idle:
                    default:
                        break;
                }

                m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
            }

            int cost = 0;
            int nreqtextures = 0;
            int nreqmeshs= 0;
            int nreqinstances = 0;
            bool IsAtestUpload = false;

            string assetName = llsdRequest.name;

            LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();

            if (llsdRequest.asset_type == "texture" ||
                llsdRequest.asset_type == "animation" ||
                llsdRequest.asset_type == "animatn" ||    // this is the asset name actually used by viewers
                llsdRequest.asset_type == "mesh" ||
                llsdRequest.asset_type == "sound")
            {
                ScenePresence avatar = null;
                m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);

                // check user level
                if (avatar != null)
                {
                    if (avatar.UserLevel < m_levelUpload)
                    {
                        LLSDAssetUploadError resperror = new LLSDAssetUploadError();
                        resperror.message = "Insufficient permissions to upload";
                        resperror.identifier = UUID.Zero;

                        LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
                        errorResponse.uploader = "";
                        errorResponse.state = "error";
                        errorResponse.error = resperror;
                        lock (m_ModelCost)
                            m_FileAgentInventoryState = FileAgentInventoryState.idle;
                        return errorResponse;
                    }
                }

                // check test upload and funds
                if (client != null)
                {
                    IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();

                    int baseCost = 0;
                    if (mm != null)
                        baseCost = mm.UploadCharge;

                    string warning = String.Empty;

                    if (llsdRequest.asset_type == "mesh")
                    {
                        string error;
                        int modelcost;
                        
                        
                        if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
                            meshcostdata, out error, ref warning))
                        {
                            LLSDAssetUploadError resperror = new LLSDAssetUploadError();
                            resperror.message = error;
                            resperror.identifier = UUID.Zero;

                            LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
                            errorResponse.uploader = "";
                            errorResponse.state = "error";
                            errorResponse.error = resperror;

                            lock (m_ModelCost)
                                m_FileAgentInventoryState = FileAgentInventoryState.idle;
                            return errorResponse;
                        }
                        cost = modelcost;
                    }
                    else
                    {
                        cost = baseCost;
                    }

                    if (cost > 0 && mm != null)
                    {
                        // check for test upload

                        if (m_ForceFreeTestUpload) // all are test
                        {
                            if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
                                assetName = "TEST-" + assetName;

                            IsAtestUpload = true;
                        }

                        else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
                        {

                            IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
                        }


                        if(IsAtestUpload) // let user know, still showing cost estimation
                            warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions";

                        // check funds
                        else
                        {
                            if (!mm.UploadCovered(client.AgentId, (int)cost))
                            {
                                LLSDAssetUploadError resperror = new LLSDAssetUploadError();
                                resperror.message = "Insuficient funds";
                                resperror.identifier = UUID.Zero;

                                LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
                                errorResponse.uploader = "";
                                errorResponse.state = "error";
                                errorResponse.error = resperror;
                                lock (m_ModelCost)
                                    m_FileAgentInventoryState = FileAgentInventoryState.idle;
                                return errorResponse;
                            }
                        }
                    }

                    if (client != null && warning != String.Empty)
                        client.SendAgentAlertMessage(warning, true);
                }
            }
            
            string assetDes = llsdRequest.description;
            string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
            UUID newAsset = UUID.Random();
            UUID newInvItem = UUID.Random();
            UUID parentFolder = llsdRequest.folder_id;
            string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
            UUID texturesFolder = UUID.Zero;

            if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
                texturesFolder = llsdRequest.texture_folder_id;

            AssetUploader uploader =
                new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
                        llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
                        texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload,
                        llsdRequest.next_owner_mask, llsdRequest.group_mask, llsdRequest.everyone_mask);

            m_HostCapsObj.HttpListener.AddStreamHandler(
                new BinaryStreamHandler(
                    "POST",
                    capsBase + uploaderPath,
                    uploader.uploaderCaps,
                    "NewAgentInventoryRequest",
                    m_HostCapsObj.AgentID.ToString()));

            string protocol = "http://";

            if (m_HostCapsObj.SSLCaps)
                protocol = "https://";

            string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
                                 uploaderPath;


            LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
            uploadResponse.uploader = uploaderURL;
            uploadResponse.state = "upload";
            uploadResponse.upload_price = (int)cost;

            if (llsdRequest.asset_type == "mesh")
            {
                uploadResponse.data = meshcostdata;
            }

            uploader.OnUpLoad += UploadCompleteHandler;

            lock (m_ModelCost)
                m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;

            return uploadResponse;
        }