Core class created by unserialize if an undefined class should be created.
Esempio n. 1
0
        /// <summary>
        /// Returns an unitialized instance of the specified type or <see cref="__PHP_Incomplete_Class"/>.
        /// </summary>
        /// <param name="typeName">The type name.</param>
        /// <param name="context">Current <see cref="ScriptContext"/>.</param>
        /// <returns>The newly created instance or <B>null</B> if <paramref name="typeName"/> denotes
        /// a primitive type.</returns>
        /// <remarks>
        /// If the <paramref name="typeName"/> denotes a CLR type, no constructor is executed. If the
        /// <paramref name="typeName"/> denotes a PHP type, no user constructor (e.g. <c>__construct</c>)
        /// is executed.
        /// </remarks>
        public static DObject GetUninitializedInstance(string /*!*/ typeName, ScriptContext /*!*/ context)
        {
            // resolve the specified type
            DTypeDesc type = context.ResolveType(typeName);

            if (type == null || type.IsAbstract)
            {
                PhpCallback callback = context.Config.Variables.DeserializationCallback;
                if (callback != null && !callback.IsInvalid)
                {
                    callback.Invoke(typeName);
                    type = context.ResolveType(typeName);

                    if (type == null || type.IsAbstract)
                    {
                        // unserialize_callback_func failed
                        PhpException.Throw(PhpError.Warning, CoreResources.GetString("unserialize_callback_failed",
                                                                                     ((IPhpConvertible)callback).ToString()));
                    }
                }
            }

            if (type == null || type.IsAbstract)
            {
                // type not found -> create __PHP_Incomplete_Class
                __PHP_Incomplete_Class pic = new __PHP_Incomplete_Class(context, false);
                pic.__PHP_Incomplete_Class_Name.Value = typeName;
                pic.__PHP_Incomplete_Class_Name.IsSet = true;

                return(pic);
            }
            else
            {
                // create the instance
                return(type.New(context) as DObject);
            }
        }
Esempio n. 2
0
                /// <summary>
                /// Parses the <B>O</B> and <B>C</B> tokens.
                /// </summary>
                /// <param name="serializable">If <B>true</B>, the last token eaten was <B>C</B>, otherwise <B>O</B>.</param>
                object ParseObject(bool serializable)
                {
                    Debug.Assert(_ctx != null);

                    var seq = AddSeq();

                    // :{length}:"{classname}":
                    Consume(Tokens.Colon);                       // :
                    string class_name = ReadString().AsString(); // <length>:"classname"
                    var    tinfo      = _ctx?.GetDeclaredType(class_name, true);

                    // :{count}:
                    Consume(Tokens.Colon);  // :
                    var count = (unchecked ((int)ReadInteger()));

                    if (count < 0)
                    {
                        ThrowInvalidLength();
                    }
                    Consume(Tokens.Colon);

                    // bind to the specified class
                    object obj;

                    if (tinfo != null)
                    {
                        obj = tinfo.CreateUninitializedInstance(_ctx);
                        if (obj == null)
                        {
                            throw new ArgumentException(string.Format(LibResources.class_instantiation_failed, class_name));
                        }
                    }
                    else
                    {
                        // TODO: DeserializationCallback
                        // __PHP_Incomplete_Class
                        obj = new __PHP_Incomplete_Class();
                        throw new NotImplementedException("__PHP_Incomplete_Class");
                    }

                    // {
                    Consume(Tokens.BraceOpen);

                    if (serializable)
                    {
                        // check whether the instance is PHP5.1 Serializable
                        if (!(obj is global::Serializable))
                        {
                            throw new ArgumentException(string.Format(LibResources.class_has_no_unserializer, class_name));
                        }

                        PhpString serializedBytes;
                        if (count > 0)
                        {
                            // add serialized representation to be later passed to unserialize
                            var buffer = new byte[count];
                            if (_stream.Read(buffer, 0, count) < count)
                            {
                                ThrowEndOfStream();
                            }

                            serializedBytes = new PhpString(buffer);
                        }
                        else
                        {
                            serializedBytes = PhpString.Empty;
                        }

                        // Template: Serializable::unserialize(data)
                        ((global::Serializable)obj).unserialize(serializedBytes);
                    }
                    else
                    {
                        var __unserialize       = tinfo.RuntimeMethods[TypeMethods.MagicMethods.__unserialize];
                        var __unserialize_array = __unserialize != null ? new PhpArray(count) : null;

                        // parse properties
                        while (--count >= 0)
                        {
                            var key   = Parse();
                            var value = Parse();

                            //
                            if (key.TryToIntStringKey(out var iskey))
                            {
                                if (__unserialize_array != null)
                                {
                                    __unserialize_array[iskey] = value;
                                }
                                else
                                {
                                    // set property
                                    SetProperty(obj, tinfo, iskey.ToString(), value, _ctx);
                                }
                            }
                            else
                            {
                                this.ThrowInvalidDataType();
                            }
                        }

                        if (__unserialize != null)
                        {
                            __unserialize.Invoke(_ctx, obj, __unserialize_array);
                        }
                        else
                        {
                            // __wakeup
                            var __wakeup = tinfo.RuntimeMethods[TypeMethods.MagicMethods.__wakeup];
                            if (__wakeup != null)
                            {
                                __wakeup.Invoke(_ctx, obj);
                            }
                        }
                    }

                    // }
                    Consume(Tokens.BraceClose);

                    //
                    seq.Value = PhpValue.FromClass(obj);
                    return(obj);
                }
Esempio n. 3
0
                /// <summary>
                /// Parses the <B>O</B> and <B>C</B> tokens.
                /// </summary>
                /// <param name="serializable">If <B>true</B>, the last token eaten was <B>C</B>, otherwise <B>O</B>.</param>
                object ParseObject(bool serializable)
                {
                    // :{length}:"{classname}":
                    Consume(Tokens.Colon);                       // :
                    string class_name = ReadString().AsString(); // <length>:"classname"
                    var    tinfo      = _ctx.GetDeclaredType(class_name, true);

                    // :{count}:
                    Consume(Tokens.Colon);  // :
                    var count = (unchecked ((int)ReadInteger()));

                    if (count < 0)
                    {
                        ThrowInvalidLength();
                    }
                    Consume(Tokens.Colon);

                    // bind to the specified class
                    object obj;

                    if (tinfo != null)
                    {
                        obj = tinfo.GetUninitializedInstance(_ctx);
                        if (obj == null)
                        {
                            throw new ArgumentException(string.Format(LibResources.class_instantiation_failed, class_name));
                        }
                    }
                    else
                    {
                        // TODO: DeserializationCallback
                        // __PHP_Incomplete_Class
                        obj = new __PHP_Incomplete_Class();
                        throw new NotImplementedException("__PHP_Incomplete_Class");
                    }

                    Consume(Tokens.BraceOpen);

                    if (serializable)
                    {
                        // check whether the instance is PHP5.1 Serializable
                        if (!(obj is global::Serializable))
                        {
                            throw new ArgumentException(string.Format(LibResources.class_has_no_unserializer, class_name));
                        }

                        PhpString serializedBytes;
                        if (count > 0)
                        {
                            // add serialized representation to be later passed to unserialize
                            var buffer = new byte[count];
                            if (_stream.Read(buffer, 0, count) < count)
                            {
                                ThrowEndOfStream();
                            }

                            serializedBytes = new PhpString(buffer);
                        }
                        else
                        {
                            serializedBytes = PhpString.Empty;
                        }

                        // Template: Serializable::unserialize(data)
                        ((global::Serializable)obj).unserialize(serializedBytes);
                    }
                    else
                    {
                        // parse properties
                        while (--count >= 0)
                        {
                            // parse property name
                            var nameval = Parse();
                            var pname   = nameval.ToStringOrNull();
                            if (pname == null)
                            {
                                if (!nameval.IsInteger())
                                {
                                    ThrowInvalidDataType();
                                }
                                pname = nameval.ToStringOrThrow(_ctx);
                            }

                            // parse property value
                            var pvalue = Parse();

                            // set property
                            SetProperty(obj, tinfo, pname, pvalue, _ctx);
                        }

                        // __wakeup
                        var __wakeup = tinfo.RuntimeMethods[TypeMethods.MagicMethods.__wakeup];
                        if (__wakeup != null)
                        {
                            __wakeup.Invoke(_ctx, obj);
                        }
                    }

                    Consume(Tokens.BraceClose);

                    //
                    return(obj);
                }
Esempio n. 4
0
		/// <summary>
		/// Returns an unitialized instance of the specified type or <see cref="__PHP_Incomplete_Class"/>.
		/// </summary>
		/// <param name="typeName">The type name.</param>
		/// <param name="context">Current <see cref="ScriptContext"/>.</param>
		/// <returns>The newly created instance or <B>null</B> if <paramref name="typeName"/> denotes
		/// a primitive type.</returns>
		/// <remarks>
		/// If the <paramref name="typeName"/> denotes a CLR type, no constructor is executed. If the
		/// <paramref name="typeName"/> denotes a PHP type, no user constructor (e.g. <c>__construct</c>)
		/// is executed.
		/// </remarks>
		public static DObject GetUninitializedInstance(string/*!*/ typeName, ScriptContext/*!*/ context)
		{
			// resolve the specified type
			DTypeDesc type = context.ResolveType(typeName);
			if (type == null || type.IsAbstract)
			{
				PhpCallback callback = context.Config.Variables.DeserializationCallback;
				if (callback != null && !callback.IsInvalid)
				{
					callback.Invoke(typeName);
					type = context.ResolveType(typeName);

					if (type == null || type.IsAbstract)
					{
						// unserialize_callback_func failed
						PhpException.Throw(PhpError.Warning, CoreResources.GetString("unserialize_callback_failed",
							((IPhpConvertible)callback).ToString()));
					}
				}
			}

			if (type == null || type.IsAbstract)
			{
				// type not found -> create __PHP_Incomplete_Class
				__PHP_Incomplete_Class pic = new __PHP_Incomplete_Class(context, false);
				pic.__PHP_Incomplete_Class_Name.Value = typeName;
				pic.__PHP_Incomplete_Class_Name.IsSet = true;

				return pic;
			}
			else
			{
				// create the instance
				return type.New(context) as DObject;
			}
		}