Ejemplo n.º 1
0
        /// <summary>
        /// Extracts debug information from an eval trace and returns it in a form of extended file name:
        /// {full canonical file name of the inner most eval source file}
        /// { inside {eval|assert|...|run-time funcion} (on line #, column #) }*
        /// </summary>
        private static string EvalTraceToFileName(List <ErrorStackInfo> /*!*/ trace, string sourceRoot, bool html)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = trace.Count - 1; i > 0; i--)
            {
                ErrorStackInfo info = trace[i];

                if (sb.Length == 0)
                {
                    sb.Append(Path.GetFullPath(Path.Combine(sourceRoot, info.File)));
                }

                if (info.Caller != null)
                {
                    sb.Append(' ');

                    if (info.Line >= 0 && info.Column >= 0)
                    {
                        sb.Append(CoreResources.GetString(html ? "error_message_html_eval_debug" : "error_message_plain_eval_debug",
                                                          info.Caller, info.Line, info.Column));
                    }
                    else
                    {
                        sb.Append(CoreResources.GetString(html ? "error_message_html_eval" : "error_message_plain_eval",
                                                          info.Caller));
                    }
                }
            }

            return(sb.ToString());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Modifies a specified eval trace such that all transparent evals get hidden.
        /// The others will have updated line numbers.
        /// </summary>
        private static void HideTransparentEvals(List <ErrorStackInfo> /*!*/ trace)
        {
            int add_line = 0;

            for (int i = trace.Count - 1; i >= 0; i--)
            {
                ErrorStackInfo info = trace[i];

                if (info.Caller == null)
                {
                    // skips the frame if there is no debug info:
                    if (info.Line > 0)
                    {
                        add_line += info.Line - 1;
                    }
                }
                else if (add_line > 0)
                {
                    // skips the frame if there is no debug info:
                    if (info.Line > 0)
                    {
                        info.Line += add_line;
                        // replace struct:
                        trace[i] = info;
                    }

                    add_line = 0;
                }
            }

            Debug.Assert(add_line == 0);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a new PHP stack frame.
        /// </summary>
        /// <param name="context">A script context.</param>
        /// <param name="frame">The respective CLR frame.</param>
        /// <param name="kind">A kind of the frame.</param>
        internal PhpStackFrame(ScriptContext /*!*/ context, StackFrame /*!*/ frame, FrameKinds kind)
        {
            Debug.Assert(context != null && frame != null && kind != FrameKinds.Invisible);

            this.frame = frame;
            this.kind  = kind;

            MethodBase method = frame.GetMethod();

            if (kind == FrameKinds.ClassLibraryFunction)
            {
                this.name = ImplementsFunctionAttribute.Reflect(method).Name;

                SetDebugInfo(frame);
            }
            else
            {
                Type type = method.DeclaringType;

                int eval_id = TransientAssembly.InvalidEvalId;

                if (type != null && context.ApplicationContext.IsTransientRealType(type))
                {
                    // gets [PhpEvalId] attribute defined on the type:
                    object[] attrs = type.GetCustomAttributes(typeof(PhpEvalIdAttribute), false);
                    eval_id = ((PhpEvalIdAttribute)attrs[0]).Id;

                    ErrorStackInfo info = new ErrorStackInfo();

                    PhpStackTrace.FillEvalStackInfo(context, eval_id, ref info, false);

                    this.line   = info.Line;
                    this.column = info.Column;
                    this.file   = info.File;
                    this.name   = info.Caller;
                }
                else
                {
                    SetDebugInfo(frame);
                }

                // the caller has already been set by FillEvalStackInfo
                // if it is not an eval main:
                if (!(eval_id != TransientAssembly.InvalidEvalId && PhpScript.IsScriptType(type) && kind == FrameKinds.Main))
                {
                    if (this.name == ScriptModule.MainHelperName)
                    {
                        this.name = "{main}";
                    }
                    else
                    {
                        int j;
                        PhpScript.ParseMDeclName(method.Name, out this.name, out j);
                    }
                }
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Initializes a new instance of the PhpException class with serialized data. This constructor is used
 /// when an exception is thrown in a remotely called method. Such an exceptions needs to be serialized,
 /// transferred back to the caller and then rethrown using this constructor.
 /// </summary>
 /// <param name="info">The SerializationInfo that holds the serialized object data about the exception
 /// being thrown.</param>
 /// <param name="context">The StreamingContext that contains contextual information about the source or
 /// destination.</param>
 protected PhpException(SerializationInfo info, StreamingContext context)
     : base(info, context)
 {
     this.error = (PhpError)info.GetValue("error", typeof(PhpError));
     this.info  = new ErrorStackInfo(
         (string)info.GetString("file"),
         (string)info.GetString("caller"),
         (int)info.GetInt32("line"),
         (int)info.GetInt32("column"),
         (bool)info.GetBoolean("libraryCaller"));
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Reports error thrown by compiler.
        /// </summary>
        internal static void ThrowByWebCompiler(PhpError error, int id, string sourceFile, int line, int column, string message)
        {
            ErrorStackInfo info = new ErrorStackInfo(sourceFile, null, line, column, false);

            // gets the current script context and config:
            LocalConfiguration config = Configuration.Local;

#if !SILVERLIGHT
            ReportError(config, HttpContext.Current.Response.Output, error, id, info, message);
#else
            ReportError(config, new StreamWriter(ScriptContext.CurrentContext.OutputStream), error, id, info, message);
#endif

            if (((PhpErrorSet)error & PhpErrorSet.Fatal) != 0)
            {
                throw new PhpException(error, message, info);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Reports an error to log file, event log and to output (as configured).
        /// </summary>
        private static void ReportError(LocalConfiguration config, TextWriter output, PhpError error, int id,
                                        ErrorStackInfo info, string message)
        {
            string formatted_message = FormatErrorMessageOutput(config, error, id, info, message);

            // logs error if logging is enabled:
            if (config.ErrorControl.EnableLogging)
            {
#if SILVERLIGHT
                throw new NotSupportedException("Logging is not supported on Silverlight. Set EnableLogging to false.");
#else
                // adds a message to log file:
                if (config.ErrorControl.LogFile != null)
                {
                    try
                    {
                        // <error>: <caller>(): <message> in <file> on line <line>
                        string caller = (info.Caller != null) ? (info.Caller + "(): ") : null;
                        string place  = (info.Line > 0 && info.Column > 0) ? CoreResources.GetString("error_place", info.File, info.Line, info.Column) : null;

                        Logger.AppendLine(config.ErrorControl.LogFile, string.Concat(error, ": ", caller, message, place));
                    }
                    catch (Exception) { }
                }

                // adds a message to event log:
                if (config.ErrorControl.SysLog)
                {
                    try { Logger.AddToEventLog(message); }
                    catch (Exception) { }
                }
#endif
            }

            // displays an error message if desired:
            if (config.ErrorControl.DisplayErrors)
            {
                output.Write(config.ErrorControl.ErrorPrependString);
                output.Write(formatted_message);
                output.Write(config.ErrorControl.ErrorAppendString);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="info"></param>
        /// <param name="config"></param>
        /// <returns>Returns caller name with () or null. Formatted for the current output capabilities.</returns>
        internal static string FormatErrorCallerName(ErrorStackInfo info, LocalConfiguration config)
        {
            if (info.Caller == null)
            {
                return(null);
            }

            if (config.ErrorControl.HtmlMessages && config.ErrorControl.DocRefRoot != null && info.LibraryCaller)
            {   // able to display HTML
                return(String.Format("<a href='{0}/function.{1}{2}'>{3}()</a>",
                                     config.ErrorControl.DocRefRoot,
                                     info.Caller.Replace('_', '-').ToLower(),
                                     config.ErrorControl.DocRefExtension,
                                     info.Caller));
            }
            else
            {
                return(info.Caller + "()");
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Fills an instance of <see cref="ErrorStackInfo"/> with information gathered from eval transient debug info.
        /// </summary>
        /// <param name="context">Script context.</param>
        /// <param name="evalId">An id of the inner-most eval where an error occured.</param>
        /// <param name="result">The resulting error stack info.</param>
        /// <param name="html">Whether the message is used in HTML.</param>
        internal static void FillEvalStackInfo(ScriptContext /*!*/ context, int evalId, ref ErrorStackInfo result, bool html)
        {
            Debug.Assert(context != null);

            FullPath source_root = Configuration.Application.Compiler.SourceRoot;

            // stack info about the error position (with respect to inner most eval):
            result.Line   = context.EvalLine;
            result.Column = context.EvalColumn;
            result.Caller = "<error>";
            result.File   = null;

            List <ErrorStackInfo> infos = new List <ErrorStackInfo>();

            infos.Add(result);

            // fills "infos" with full eval error trace:
            context.ApplicationContext.TransientAssemblyBuilder.TransientAssembly.GetEvalFullTrace(evalId, infos);

            Debug.WriteLine("EVAL ERROR", "");
            foreach (ErrorStackInfo info in infos)
            {
                Debug.WriteLine("EVAL ERROR", "info: {0}({1})", info.File, info.Line, info.Caller);
            }

            // hides transparent evals and modifies the others accordingly:
            HideTransparentEvals(infos);

            // refresh inner most error info:
            result      = infos[0];
            result.File = EvalTraceToFileName(infos, source_root, html);
        }
Ejemplo n.º 9
0
		/// <summary>
		/// Exception constructor.
		/// </summary>
		/// <param name="error">The type of PHP error.</param>
		/// <param name="message">The error message.</param>
		/// <param name="info">Information about an error gained from a stack.</param>
		private PhpException(PhpError error, string message, ErrorStackInfo info)
			: base(message)
		{
			this.info = info;
			this.error = error;
		}
Ejemplo n.º 10
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="info"></param>
        /// <param name="config"></param>
        /// <returns>Returns caller name with () or null. Formatted for the current output capabilities.</returns>
        internal static string FormatErrorCallerName(ErrorStackInfo info, LocalConfiguration config)
        {
            if (info.Caller == null)
                return null;

            if (config.ErrorControl.HtmlMessages && config.ErrorControl.DocRefRoot != null && info.LibraryCaller)
            {   // able to display HTML
                return String.Format("<a href='{0}/function.{1}{2}'>{3}()</a>",
                      config.ErrorControl.DocRefRoot,
                      info.Caller.Replace('_', '-').ToLower(),
                      config.ErrorControl.DocRefExtension,
                      info.Caller);
            }
            else
            {
                return info.Caller + "()";
            }
        }
Ejemplo n.º 11
0
		/// <summary>
		/// Calls user error handler. 
		/// </summary>
		/// <returns>Whether to report error by default handler (determined by handler's return value).</returns>
		/// <exception cref="ScriptDiedException">Error handler dies.</exception>
		private static bool CallUserErrorHandler(ScriptContext context, PhpError error, ErrorStackInfo info, string message)
		{
			LocalConfiguration config = context.Config;

			try
			{
				object result = PhpVariable.Dereference(config.ErrorControl.UserHandler.Invoke(new PhpReference[] 
        { 
          new PhpReference((int)error),
          new PhpReference(message),
          new PhpReference(info.File),
          new PhpReference(info.Line),
          new PhpReference() // global variables list is not supported
        }));

				// since PHP5 an error is reported by default error handler if user handler returns false:
				return result is bool && (bool)result == false;
			}
			catch (ScriptDiedException)
			{
				// user handler has cancelled the error via script termination:
				throw;
			}
			catch (PhpUserException)
			{
				// rethrow user exceptions:
				throw;
			}
			catch (Exception)
			{
			}
			return false;
		}
Ejemplo n.º 12
0
		/// <summary>
		/// Creates a new PHP stack frame.
		/// </summary>
		/// <param name="context">A script context.</param>
		/// <param name="frame">The respective CLR frame.</param>
		/// <param name="kind">A kind of the frame.</param>
		internal PhpStackFrame(ScriptContext/*!*/ context, StackFrame/*!*/ frame, FrameKinds kind)
		{
			Debug.Assert(context != null && frame != null && kind != FrameKinds.Invisible);

			this.frame = frame;
			this.kind = kind;

			MethodBase method = frame.GetMethod();

			if (kind == FrameKinds.ClassLibraryFunction)
			{
				this.name = ImplementsFunctionAttribute.Reflect(method).Name;

				SetDebugInfo(frame);
			}
			else
			{
				Type type = method.DeclaringType;

				int eval_id = TransientAssembly.InvalidEvalId;

				if (type != null && context.ApplicationContext.IsTransientRealType(type))
				{
					// gets [PhpEvalId] attribute defined on the type:
					object[] attrs = type.GetCustomAttributes(typeof(PhpEvalIdAttribute), false);
					eval_id = ((PhpEvalIdAttribute)attrs[0]).Id;

					ErrorStackInfo info = new ErrorStackInfo();

					PhpStackTrace.FillEvalStackInfo(context, eval_id, ref info, false);

					this.line = info.Line;
					this.column = info.Column;
					this.file = info.File;
					this.name = info.Caller;
				}
				else
				{
					SetDebugInfo(frame);
				}

				// the caller has already been set by FillEvalStackInfo 
				// if it is not an eval main:
				if (!(eval_id != TransientAssembly.InvalidEvalId && PhpScript.IsScriptType(type) && method.Name == ScriptModule.MainHelperName))
				{
					int j;
					PhpScript.ParseMDeclName(method.Name, out this.name, out j);
				}
			}
		}
Ejemplo n.º 13
0
 /// <summary>
 /// Exception constructor.
 /// </summary>
 /// <param name="error">The type of PHP error.</param>
 /// <param name="message">The error message.</param>
 /// <param name="info">Information about an error gained from a stack.</param>
 private PhpException(PhpError error, string message, ErrorStackInfo info)
     : base(message)
 {
     this.info  = info;
     this.error = error;
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Formats error message.
        /// </summary>
        /// <param name="config">A configuration.</param>
        /// <param name="error">A type of the error.</param>
        /// <param name="id">Error id or -1.</param>
        /// <param name="info">A stack information about the error.</param>
        /// <param name="message">A message.</param>
        /// <returns>A formatted plain text or HTML message depending on settings in <paramref name="config"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramren name="config"/> is a <B>null</B> reference.</exception>
        public static string FormatErrorMessageOutput(LocalConfiguration config, PhpError error, int id, ErrorStackInfo info, string message)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            string error_str  = PhpErrorText(error, id);             // the error type (Warning, Error, ...)
            bool   show_place = info.Line > 0 && info.Column > 0;    // we are able to report error position
            string caller     = FormatErrorCallerName(info, config); // current function name "foo()" or null

            // change the message or caller, based on the error type
            FormatErrorMessageText(error, ref message, ref caller);

            // error message
            string ErrorFormatString =
                config.ErrorControl.HtmlMessages ?
                (show_place ? CoreResources.error_message_html_debug : CoreResources.error_message_html) :
                (show_place ? CoreResources.error_message_plain_debug : CoreResources.error_message_plain);

            if (show_place)
            {
                return(string.Format(ErrorFormatString,
                                     error_str, caller, message, info.File, info.Line, info.Column));
            }
            else
            {
                return(string.Format(ErrorFormatString,
                                     error_str, caller, message));
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Reports a PHP error.
        /// </summary>
        /// <param name="error">The error type</param>
        /// <param name="message">The error message.</param>
        public static void Throw(PhpError error, string message)
        {
            if (ThrowCallbackOverride != null)
            {
                ThrowCallbackOverride(error, message);
                return;
            }

            ErrorStackInfo info        = new ErrorStackInfo();
            bool           info_loaded = false;

            // gets the current script context and config:
            ScriptContext      context = ScriptContext.CurrentContext;
            LocalConfiguration config  = context.Config;

            // determines whether the error will be reported and whether it is handleable:
            bool is_error_reported   = ((PhpErrorSet)error & config.ErrorControl.ReportErrors) != 0 && !context.ErrorReportingDisabled;
            bool is_error_handleable = ((PhpErrorSet)error & PhpErrorSet.Handleable & (PhpErrorSet)config.ErrorControl.UserHandlerErrors) != 0;
            bool is_error_fatal      = ((PhpErrorSet)error & PhpErrorSet.Fatal) != 0;
            bool do_report           = true;

            // remember last error info
            context.LastErrorType    = error;
            context.LastErrorMessage = message;
            context.LastErrorFile    = null; // only if we are getting ErrorStackInfo, see PhpStackTrace.TraceErrorFrame
            context.LastErrorLine    = 0;    // only if we are getting ErrorStackInfo, see PhpStackTrace.TraceErrorFrame

            // calls a user defined handler if available:
            if (is_error_handleable && config.ErrorControl.UserHandler != null)
            {
                // loads stack info:
                Func <ErrorStackInfo> func = () =>
                {
                    if (!info_loaded)
                    {
                        info        = PhpStackTrace.TraceErrorFrame(context, true);
                        info_loaded = true;
                    }
                    return(info);
                };

                do_report = CallUserErrorHandler(context, error, func, message);
            }

            // reports error to output and logs:
            if (do_report && is_error_reported &&
                (config.ErrorControl.DisplayErrors || config.ErrorControl.EnableLogging))   // check if the error will be displayed to avoid stack trace loading
            {
                // loads stack info:
                if (!info_loaded)
                {
                    info = PhpStackTrace.TraceErrorFrame(context, false); info_loaded = true;
                }

                ReportError(config, context.Output, error, -1, info, message);
            }

            // Throws an exception if the error is fatal and throwing is enabled.
            // PhpError.UserError is also fatal, but can be cancelled by user handler => handler call must precede this line.
            // Error displaying must also precede this line because the error should be displayed before an exception is thrown.
            if (is_error_fatal && context.ThrowExceptionOnError)
            {
                // loads stack info:
                if (!info_loaded)
                {
                    info = PhpStackTrace.TraceErrorFrame(context, false); info_loaded = true;
                }

                throw new PhpException(error, message, info);
            }
        }
Ejemplo n.º 16
0
        /// <summary>
		/// Reports a PHP error. 
		/// </summary>
		/// <param name="error">The error type</param>
		/// <param name="message">The error message.</param>    
		public static void Throw(PhpError error, string message)
		{
            if (ThrowCallbackOverride != null)
            {
                ThrowCallbackOverride(error, message);
                return;
            }

			ErrorStackInfo info = new ErrorStackInfo();
			bool info_loaded = false;

			// gets the current script context and config:
			ScriptContext context = ScriptContext.CurrentContext;
			LocalConfiguration config = context.Config;

			// determines whether the error will be reported and whether it is handleable:
			bool is_error_reported = ((PhpErrorSet)error & config.ErrorControl.ReportErrors) != 0 && !context.ErrorReportingDisabled;
			bool is_error_handleable = ((PhpErrorSet)error & PhpErrorSet.Handleable & (PhpErrorSet)config.ErrorControl.UserHandlerErrors) != 0;
			bool is_error_fatal = ((PhpErrorSet)error & PhpErrorSet.Fatal) != 0;
			bool do_report = true;

            // remember last error info
            context.LastErrorType = error;
            context.LastErrorMessage = message;
            context.LastErrorFile = null;   // only if we are getting ErrorStackInfo, see PhpStackTrace.TraceErrorFrame
            context.LastErrorLine = 0;     // only if we are getting ErrorStackInfo, see PhpStackTrace.TraceErrorFrame

			// calls a user defined handler if available:
			if (is_error_handleable && config.ErrorControl.UserHandler != null)
			{
				// loads stack info:
				if (!info_loaded) { info = PhpStackTrace.TraceErrorFrame(context); info_loaded = true; }

				do_report = CallUserErrorHandler(context, error, info, message);
			}

			// reports error to output and logs:
            if (do_report && is_error_reported &&
                (config.ErrorControl.DisplayErrors || config.ErrorControl.EnableLogging))   // check if the error will be displayed to avoid stack trace loading
			{
				// loads stack info:
				if (!info_loaded) { info = PhpStackTrace.TraceErrorFrame(context); info_loaded = true; }

				ReportError(config, context.Output, error, -1, info, message);
			}

			// Throws an exception if the error is fatal and throwing is enabled.
			// PhpError.UserError is also fatal, but can be cancelled by user handler => handler call must precede this line.
			// Error displaying must also precede this line because the error should be displayed before an exception is thrown.
			if (is_error_fatal && context.ThrowExceptionOnError)
			{
				// loads stack info:
				if (!info_loaded) { info = PhpStackTrace.TraceErrorFrame(context); info_loaded = true; }

				throw new PhpException(error, message, info);
			}
		}
Ejemplo n.º 17
0
		/// <summary>
		/// Reports an error to log file, event log and to output (as configured).
		/// </summary>
		private static void ReportError(LocalConfiguration config, TextWriter output, PhpError error, int id,
			ErrorStackInfo info, string message)
		{
            string formatted_message = FormatErrorMessageOutput(config, error, id, info, message);

			// logs error if logging is enabled:
			if (config.ErrorControl.EnableLogging)
			{
#if SILVERLIGHT
				throw new NotSupportedException("Logging is not supported on Silverlight. Set EnableLogging to false.");
#else
				// adds a message to log file:
				if (config.ErrorControl.LogFile != null)
                    try
                    {
                        // <error>: <caller>(): <message> in <file> on line <line>
                        string caller = (info.Caller != null) ? (info.Caller + "(): ") : null;
                        string place = (info.Line > 0 && info.Column > 0) ? CoreResources.GetString("error_place", info.File, info.Line, info.Column) : null;

                        Logger.AppendLine(config.ErrorControl.LogFile, string.Concat(error, ": ", caller, message, place));
                    }
                    catch (Exception) { }

				// adds a message to event log:
				if (config.ErrorControl.SysLog)
					try { Logger.AddToEventLog(message); }
					catch (Exception) { }
#endif
			}

			// displays an error message if desired:
			if (config.ErrorControl.DisplayErrors)
			{
				output.Write(config.ErrorControl.ErrorPrependString);
				output.Write(formatted_message);
				output.Write(config.ErrorControl.ErrorAppendString);
			}
		}
Ejemplo n.º 18
0
		/// <summary>
		/// Traces up the stack frame containing the method call that has caused an error.
		/// </summary>
		/// <returns>Found stack info.</returns>
		/// <remarks>
		/// Starts with a frame of a calling method and ends with the first frame belonging to user routine.
		/// If there was <see cref="ImplementsFunctionAttribute"/> found during the walk the last one's value
		/// is considered as the caller.
		/// If there was not such attribute found (error occured in an operator, directly in the code etc.) 
		/// the last inspected method's debug info is returned.
		/// If the trace ends up with a function or method inside transient assembly an eval hierarchy is inspected
		/// and added to the resulting source position information.
		/// </remarks>
		internal static ErrorStackInfo TraceErrorFrame(ScriptContext/*!*/ context)
		{
			Debug.Assert(context != null);

			ErrorStackInfo result = new ErrorStackInfo();
			int cl_function_idx = -1;
			string cl_function_name = null;
			StackFrame frame;
			int eval_id = TransientAssembly.InvalidEvalId;

			// stack trace without debug info is constructed:
#if !SILVERLIGHT
			StackTrace trace = new StackTrace(1, false);

			// note: method stack frame contains a debug info about the call to the callee
			// hence if we find a method that reported the error we should look the next frame 
			// to obtain a debug info

			int i = 0;
			for (; ; )
			{
				// gets frame:
				frame = trace.GetFrame(i++);

				// error has been thrown directly by Core without intermediary user code (all frames are invisible):
				if (frame == null)
				{
					// cl_function_idx can be non-minus-one here because a callback can be called directly from Core 
					// (e.g. output buffer filter targeting class library function):
					if (cl_function_idx != -1)
					{
						result.Caller = cl_function_name;
						result.LibraryCaller = true;
					}

					return result;
				}

				FrameKinds frame_kind = GetFrameKind(frame);

				if (frame_kind == FrameKinds.Visible)
				{
					MethodBase method = frame.GetMethod();

					int eid = TransientModule.GetEvalId(context.ApplicationContext, method);

					if (eval_id == TransientAssembly.InvalidEvalId)
						eval_id = eid;

					if (eid == TransientAssembly.InvalidEvalId)
						break;
				}
				else if (frame_kind == FrameKinds.ClassLibraryFunction)
				{
					MethodBase method = frame.GetMethod();

					cl_function_idx = i;
					cl_function_name = ImplementsFunctionAttribute.Reflect(method).Name;
				}
			}

			// skips i frames (the very first frame has been skipped in the previous 
			// trace construction and we want to skip i-1 frames from that trace => i frames totally):
			frame = new StackFrame(1 + i - 1, true);

			// extracts a source info (file & position):
			if (eval_id != TransientAssembly.InvalidEvalId)
			{
				FillEvalStackInfo(context, eval_id, ref result, false);
			}
			else
			{
				result.Line = frame.GetFileLineNumber();
				result.Column = frame.GetFileColumnNumber();
				result.File = frame.GetFileName();
			}

			// determines a caller (either a library function or a user function/method):
			if (cl_function_idx >= 0)
			{
				result.Caller = cl_function_name;
				result.LibraryCaller = true;
			}
			//else
			//{
			//  MethodBase method = frame.GetMethod();
			//  Type type = method.DeclaringType;

			//  // the caller has already been set by FillEvalStackInfo 
			//  // if we are in eval and the function is Main helper of the script type:
			//  if (eval_id == TransientAssembly.InvalidEvalId)
			//  {
			//    result.LibraryCaller = false;

			//    if (type != null)
			//    {
			//      result.Caller = String.Concat(DTypeDesc.MakeFullName(type), "::", DRoutineDesc.MakeFullName(method));
			//    }
			//    else
			//    {
			//      result.Caller = DRoutineDesc.MakeFullName(method);
			//    }  
			//  } 
			//}
#endif

            // add missing info about file and line
            context.LastErrorLine = result.Line;
            context.LastErrorFile = result.File;

            //
			return result;
		}
Ejemplo n.º 19
0
		/// <summary>
		/// Reports error thrown by compiler.
		/// </summary>
		internal static void ThrowByWebCompiler(PhpError error, int id, string sourceFile, int line, int column, string message)
		{
			ErrorStackInfo info = new ErrorStackInfo(sourceFile, null, line, column, false);

			// gets the current script context and config:
			LocalConfiguration config = Configuration.Local;

#if !SILVERLIGHT
			ReportError(config, HttpContext.Current.Response.Output, error, id, info, message);
#else
			ReportError(config, new StreamWriter(ScriptContext.CurrentContext.OutputStream), error, id, info, message);
#endif

			if (((PhpErrorSet)error & PhpErrorSet.Fatal) != 0)
				throw new PhpException(error, message, info);
		}
Ejemplo n.º 20
0
		/// <summary>
		/// Fills an instance of <see cref="ErrorStackInfo"/> with information gathered from eval transient debug info.
		/// </summary>
		/// <param name="context">Script context.</param>
		/// <param name="evalId">An id of the inner-most eval where an error occured.</param>
		/// <param name="result">The resulting error stack info.</param>
		/// <param name="html">Whether the message is used in HTML.</param>
		internal static void FillEvalStackInfo(ScriptContext/*!*/ context, int evalId, ref ErrorStackInfo result, bool html)
		{
			Debug.Assert(context != null);

			FullPath source_root = Configuration.Application.Compiler.SourceRoot;

			// stack info about the error position (with respect to inner most eval):
			result.Line = context.EvalLine;
			result.Column = context.EvalColumn;
			result.Caller = "<error>";
			result.File = null;

			List<ErrorStackInfo> infos = new List<ErrorStackInfo>();
			infos.Add(result);

			// fills "infos" with full eval error trace:
			context.ApplicationContext.TransientAssemblyBuilder.TransientAssembly.GetEvalFullTrace(evalId, infos);

			Debug.WriteLine("EVAL ERROR", "");
			foreach (ErrorStackInfo info in infos)
			{
				Debug.WriteLine("EVAL ERROR", "info: {0}({1})", info.File, info.Line, info.Caller);
			}

			// hides transparent evals and modifies the others accordingly:
			HideTransparentEvals(infos);

			// refresh inner most error info:
			result = infos[0];
			result.File = EvalTraceToFileName(infos, source_root, html);
		}
Ejemplo n.º 21
0
        /// <summary>
		/// Formats error message.
		/// </summary>
		/// <param name="config">A configuration.</param>
		/// <param name="error">A type of the error.</param>
		/// <param name="id">Error id or -1.</param>
		/// <param name="info">A stack information about the error.</param>
		/// <param name="message">A message.</param>
		/// <returns>A formatted plain text or HTML message depending on settings in <paramref name="config"/>.</returns>
		/// <exception cref="ArgumentNullException"><paramren name="config"/> is a <B>null</B> reference.</exception>
		public static string FormatErrorMessageOutput(LocalConfiguration config, PhpError error, int id, ErrorStackInfo info, string message)
		{
			if (config == null)
				throw new ArgumentNullException("config");

            string error_str = PhpErrorText(error, id); // the error type (Warning, Error, ...)
            bool show_place = info.Line > 0 && info.Column > 0; // we are able to report error position
            string caller = FormatErrorCallerName(info, config);    // current function name "foo()" or null

            // change the message or caller, based on the error type
            FormatErrorMessageText(error, ref message, ref caller);

            // error message
            string ErrorFormatStringId =
                config.ErrorControl.HtmlMessages ?
                (show_place ? "error_message_html_debug" : "error_message_html") :
                (show_place ? "error_message_plain_debug" : "error_message_plain");

			if (show_place)
                return CoreResources.GetString(ErrorFormatStringId,
					error_str, caller, message, info.File, info.Line, info.Column);
			else
                return CoreResources.GetString(ErrorFormatStringId,
                    error_str, caller, message);
		}
Ejemplo n.º 22
0
        /// <summary>
        /// Traces up the stack frame containing the method call that has caused an error.
        /// </summary>
        /// <returns>Found stack info.</returns>
        /// <remarks>
        /// Starts with a frame of a calling method and ends with the first frame belonging to user routine.
        /// If there was <see cref="ImplementsFunctionAttribute"/> found during the walk the last one's value
        /// is considered as the caller.
        /// If there was not such attribute found (error occured in an operator, directly in the code etc.)
        /// the last inspected method's debug info is returned.
        /// If the trace ends up with a function or method inside transient assembly an eval hierarchy is inspected
        /// and added to the resulting source position information.
        /// </remarks>
        internal static ErrorStackInfo TraceErrorFrame(ScriptContext /*!*/ context, bool lazy)
        {
            Debug.Assert(context != null);

            ErrorStackInfo result           = new ErrorStackInfo();
            int            cl_function_idx  = -1;
            string         cl_function_name = null;
            StackFrame     frame;
            int            eval_id = TransientAssembly.InvalidEvalId;

            // stack trace without debug info is constructed:
#if !SILVERLIGHT
            StackTrace trace = new StackTrace(1, false);

            // note: method stack frame contains a debug info about the call to the callee
            // hence if we find a method that reported the error we should look the next frame
            // to obtain a debug info

            int i = 0;
            for (; ;)
            {
                // gets frame:
                frame = trace.GetFrame(i++);

                // error has been thrown directly by Core without intermediary user code (all frames are invisible):
                if (frame == null)
                {
                    // cl_function_idx can be non-minus-one here because a callback can be called directly from Core
                    // (e.g. output buffer filter targeting class library function):
                    if (cl_function_idx != -1)
                    {
                        result.Caller        = cl_function_name;
                        result.LibraryCaller = true;
                    }

                    return(result);
                }

                MethodBase method = frame.GetMethod();
                if (lazy)
                {
                    if (method.Name == "Throw" && method.DeclaringType == typeof(PhpException))
                    {
                        lazy = false;
                    }
                    continue;
                }

                FrameKinds frame_kind = GetFrameKind(frame);

                if (frame_kind == FrameKinds.Visible || frame_kind == FrameKinds.Main)
                {
                    int eid = TransientModule.GetEvalId(context.ApplicationContext, method);

                    if (eval_id == TransientAssembly.InvalidEvalId)
                    {
                        eval_id = eid;
                    }

                    if (eid == TransientAssembly.InvalidEvalId)
                    {
                        break;
                    }
                }
                else if (frame_kind == FrameKinds.ClassLibraryFunction)
                {
                    cl_function_idx  = i;
                    cl_function_name = ImplementsFunctionAttribute.Reflect(method).Name;
                }
            }

            // skips i frames (the very first frame has been skipped in the previous
            // trace construction and we want to skip i-1 frames from that trace => i frames totally):
            frame = new StackFrame(1 + i - 1, true);

            // extracts a source info (file & position):
            if (eval_id != TransientAssembly.InvalidEvalId)
            {
                FillEvalStackInfo(context, eval_id, ref result, false);
            }
            else
            {
                result.Line   = frame.GetFileLineNumber();
                result.Column = frame.GetFileColumnNumber();
                result.File   = frame.GetFileName();
            }

            // determines a caller (either a library function or a user function/method):
            if (cl_function_idx >= 0)
            {
                result.Caller        = cl_function_name;
                result.LibraryCaller = true;
            }
            //else
            //{
            //  MethodBase method = frame.GetMethod();
            //  Type type = method.DeclaringType;

            //  // the caller has already been set by FillEvalStackInfo
            //  // if we are in eval and the function is Main helper of the script type:
            //  if (eval_id == TransientAssembly.InvalidEvalId)
            //  {
            //    result.LibraryCaller = false;

            //    if (type != null)
            //    {
            //      result.Caller = String.Concat(DTypeDesc.MakeFullName(type), "::", DRoutineDesc.MakeFullName(method));
            //    }
            //    else
            //    {
            //      result.Caller = DRoutineDesc.MakeFullName(method);
            //    }
            //  }
            //}
#endif

            // add missing info about file and line
            context.LastErrorLine = result.Line;
            context.LastErrorFile = result.File;

            //
            return(result);
        }
Ejemplo n.º 23
0
		/// <summary>
		/// Initializes a new instance of the PhpException class with serialized data. This constructor is used
		/// when an exception is thrown in a remotely called method. Such an exceptions needs to be serialized,
		/// transferred back to the caller and then rethrown using this constructor.
		/// </summary>
		/// <param name="info">The SerializationInfo that holds the serialized object data about the exception 
		/// being thrown.</param>
		/// <param name="context">The StreamingContext that contains contextual information about the source or 
		/// destination.</param>
		protected PhpException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
			this.error = (PhpError)info.GetValue("error", typeof(PhpError));
			this.info = new ErrorStackInfo(
			  (string)info.GetString("file"),
              (string)info.GetString("caller"),
              (int)info.GetInt32("line"),
			  (int)info.GetInt32("column"),
			  (bool)info.GetBoolean("libraryCaller"));
		}
Ejemplo n.º 24
0
        /// <summary>
        /// Calls user error handler.
        /// </summary>
        /// <returns>Whether to report error by default handler (determined by handler's return value).</returns>
        /// <exception cref="ScriptDiedException">Error handler dies.</exception>
        private static bool CallUserErrorHandler(ScriptContext context, PhpError error, ErrorStackInfo info, string message)
        {
            LocalConfiguration config = context.Config;

            try
            {
                object result = PhpVariable.Dereference(config.ErrorControl.UserHandler.Invoke(new PhpReference[]
                {
                    new PhpReference((int)error),
                    new PhpReference(message),
                    new PhpReference(info.File),
                    new PhpReference(info.Line),
                    new PhpReference() // global variables list is not supported
                }));

                // since PHP5 an error is reported by default error handler if user handler returns false:
                return(result is bool && (bool)result == false);
            }
            catch (ScriptDiedException)
            {
                // user handler has cancelled the error via script termination:
                throw;
            }
            catch (PhpUserException)
            {
                // rethrow user exceptions:
                throw;
            }
            catch (Exception)
            {
            }
            return(false);
        }