/// <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)); } }
/// <summary> /// Initializes the script context for a web request. /// </summary> /// <param name="appContext">Application context.</param> /// <param name="context">HTTP context of the request.</param> /// <returns>A instance of <see cref="ScriptContext"/> to be used by the request.</returns> /// <exception cref="System.Configuration.ConfigurationErrorsException"> /// Web configuration is invalid. The context is not initialized then. /// </exception> internal static ScriptContext /*!*/ InitWebRequest(ApplicationContext /*!*/ appContext, HttpContext /*!*/ context) { Debug.Assert(appContext != null && context != null); // reloads configuration of the current thread from ASP.NET caches or web.config files; // cached configuration is reused; Configuration.Reload(appContext, false); // takes a writable copy of a global configuration (may throw ConfigurationErrorsException): LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy(); // following initialization statements shouldn't throw an exception: // can throw on Integrated Pipeline, events must be attached within HttpApplication.Init() ScriptContext result = new ScriptContext(appContext, config, context.Response.Output, context.Response.OutputStream); result.IsOutputBuffered = config.OutputControl.OutputBuffering; result.ThrowExceptionOnError = true; result.WorkingDirectory = Path.GetDirectoryName(context.Request.PhysicalPath); if (config.OutputControl.ContentType != null) { context.Response.ContentType = config.OutputControl.ContentType; } if (config.OutputControl.CharSet != null) { context.Response.Charset = config.OutputControl.CharSet; } result.AutoGlobals.Initialize(config, context); ScriptContext.CurrentContext = result; Externals.BeginRequest(); return(result); }
/// <summary> /// Loads $_COOKIE arrays from HttpRequest.Cookies. /// </summary> /// <param name="config">Local configuration.</param> /// <param name="request">HTTP request instance or a <B>null</B> reference.</param> /// <param name="cookieArray">Resulting $_COOKIE array.</param> /// <exception cref="ArgumentNullException"><paranref name="config"/> is a <B>null</B> reference.</exception> public static void InitializeCookieVariables(LocalConfiguration /*!*/ config, HttpRequest request, out PhpArray cookieArray) { Debug.Assert(config != null); if (request != null) { var cookies = request.Cookies; Debug.Assert(cookies != null, "cookies == null"); int count = cookies.Count; cookieArray = new PhpArray(0, count); for (int i = 0; i < count; i++) { HttpCookie cookie = cookies.Get(i); AddVariable(cookieArray, cookie.Name, UrlDecodeValue(cookie.Value), null); // adds a copy of cookie with the same key as the session name; // the name gets encoded and so $_COOKIE[session_name()] doesn't work then: if (cookie.Name == AspNetSessionHandler.AspNetSessionName) { cookieArray[AspNetSessionHandler.AspNetSessionName] = UrlDecodeValue(cookie.Value); } } } else { cookieArray = new PhpArray(0, 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, Func <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(new LazyStackInfo(info, true)), new PhpReference(new LazyStackInfo(info, false)), 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); }
/// <summary> /// Initializes the script context for a PHP console application. /// </summary> /// <param name="appContext">Application context.</param> /// <param name="mainScript">The main script's type or a <B>null</B> reference for a pure application.</param> /// <param name="relativeSourcePath">A path to the main script source file.</param> /// <param name="sourceRoot">A source root within which an application has been compiler.</param> /// <returns> /// A new instance of <see cref="ScriptContext"/> with its own copy of local configuration /// to be used by the application. /// </returns> /// <exception cref="System.Configuration.ConfigurationErrorsException"> /// Web configuration is invalid. The context is not initialized then. /// </exception> /// <remarks> /// Use this method if you want to initialize application in the same way the PHP console/Windows /// application is initialized. The returned script context is initialized as follows: /// <list type="bullet"> /// <term>The application's source root is set.</term> /// <term>The main script of the application is defined.</term> /// <term>Output and input streams are set to standard output and input, respectively.</term> /// <term>Current culture it set to <see cref="CultureInfo.InvariantCulture"/>.</term> /// <term>Auto-global variables ($_GET, $_SET, etc.) are initialized.</term> /// <term>Working directory is set tothe current working directory.</term> /// </list> /// </remarks> public static ScriptContext /*!*/ InitApplication(ApplicationContext /*!*/ appContext, Type mainScript, string relativeSourcePath, string sourceRoot) { // loads configuration into the given application context // (applies only if the config has not been loaded yet by the current thread): Configuration.Load(appContext); ApplicationConfiguration app_config = Configuration.Application; if (mainScript != null) { if (relativeSourcePath == null) { throw new ArgumentNullException("relativeSourcePath"); } if (sourceRoot == null) { throw new ArgumentNullException("sourceRoot"); } // overrides source root configuration if not explicitly specified in config file: if (!app_config.Compiler.SourceRootSet) { app_config.Compiler.SourceRoot = new FullPath(sourceRoot); } } // takes a writable copy of a global configuration: LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy(); // sets invariant culture as a default one: Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; ScriptContext result = new ScriptContext(appContext, config, Console.Out, Console.OpenStandardOutput()); result.IsOutputBuffered = result.config.OutputControl.OutputBuffering; result.AutoGlobals.Initialize(config, null); result.WorkingDirectory = Directory.GetCurrentDirectory(); result.ThrowExceptionOnError = true; result.config.ErrorControl.HtmlMessages = false; if (mainScript != null) { // converts relative path of the script source to full canonical path using source root from the configuration: PhpSourceFile main_source_file = new PhpSourceFile( app_config.Compiler.SourceRoot, new FullPath(relativeSourcePath, app_config.Compiler.SourceRoot) ); result.DefineMainScript(new ScriptInfo(mainScript), main_source_file); } ScriptContext.CurrentContext = result; Externals.BeginRequest(); return(result); }
/// <summary> /// Creates an instance of <see cref="LocalConfiguration"/> initialized by values /// copied from the specified instance. /// </summary> /// <param name="source"></param> private LocalConfiguration(LocalConfiguration source) { this.OutputControl = source.OutputControl.DeepCopy(); this.ErrorControl = source.ErrorControl.DeepCopy(); this.RequestControl = source.RequestControl.DeepCopy(); this.FileSystem = source.FileSystem.DeepCopy(); this.Assertion = source.Assertion.DeepCopy(); this.Variables = source.Variables.DeepCopy(); this.Session = source.Session.DeepCopy(); this.Library = source.Library.DeepCopy(); LastConfigurationModifiedTimeUtc = source.LastConfigurationModifiedTimeUtc; }
/// <summary> /// Loads $_ENV from Environment.GetEnvironmentVariables(). /// </summary> private void InitializeEnvironmentVariables(LocalConfiguration /*!*/ config) { Debug.Assert(config != null); IDictionary env_vars = Environment.GetEnvironmentVariables(); PhpArray array = new PhpArray(0, env_vars.Count); foreach (DictionaryEntry entry in env_vars) { AddVariable(array, entry.Key as string, entry.Value as string, null); } Env.Value = array; }
/// <summary> /// Loads $_GET, $_POST arrays from HttpRequest.QueryString and HttpRequest.Form. /// </summary> /// <param name="config">Local configuration.</param> /// <param name="request">HTTP request instance or a <B>null</B> reference.</param> /// <param name="getArray">Resulting $_GET array.</param> /// <param name="postArray">Resulting $_POST array.</param> /// <param name="httprawpostdataBytes">$HTTP_RAW_POST_DATA variable.</param> /// <exception cref="ArgumentNullException"><paranref name="config"/> is a <B>null</B> reference.</exception> public static void InitializeGetPostVariables(LocalConfiguration /*!*/ config, HttpRequest request, out PhpArray getArray, out PhpArray postArray, out string httprawpostdataBytes) { if (config == null) { throw new ArgumentNullException("config"); } if (request != null) { if (request.RequestType == "GET") { getArray = new PhpArray(0, request.QueryString.Count + request.Form.Count); postArray = new PhpArray(0, 0); // loads Form variables to GET array: LoadFromCollection(getArray, request.Form); } else { getArray = new PhpArray(0, request.QueryString.Count); postArray = new PhpArray(0, request.Form.Count); // loads Form variables to POST array: LoadFromCollection(postArray, request.Form); } // loads Query variables to GET array: LoadFromCollection(getArray, request.QueryString); // HTTP_RAW_POST_DATA // when always_populate_raw_post_data option is TRUE, however using "php://input" is preferred. For "multipart/form-data" it is not available. try { httprawpostdataBytes = (config.Variables.AlwaysPopulateRawPostData && !request.ContentType.StartsWith("multipart/form-data")) ? new StreamReader(request.InputStream).ReadToEnd() : null; } catch { httprawpostdataBytes = null; // unable to read the input stream, unreachable } } else { getArray = new PhpArray(0, 0); postArray = new PhpArray(0, 0); httprawpostdataBytes = null; } }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { PDOSQLServerLocalConfig local = (PDOSQLServerLocalConfig)config.GetLibraryConfig(PDOSQLServerLibraryDescriptor.Singleton); PDOSQLServerLocalConfig @default = DefaultLocal; PDOSQLServerGlobalConfig global = Global; //switch (option) //{ // // local: // // global: //} Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
/// <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); } }
/// <summary> /// Loads $_GET, $_POST, $_COOKIE, $HTTP_RAW_POST_DATA, and $_REQUEST arrays. /// </summary> private void InitializeGetPostCookieRequestVariables(LocalConfiguration /*!*/ config, HttpRequest request) { Debug.Assert(config != null); PhpArray get_array, post_array, cookie_array, request_array; string httprawpostdata_bytes; InitializeGetPostVariables(config, request, out get_array, out post_array, out httprawpostdata_bytes); InitializeCookieVariables(config, request, out cookie_array); InitializeRequestVariables(request, config.Variables.RegisteringOrder, get_array, post_array, cookie_array, out request_array); Get.Value = get_array; Post.Value = post_array; Cookie.Value = cookie_array; Request.Value = request_array; HttpRawPostData.Value = httprawpostdata_bytes; }
public static ScriptContext /*!*/ InitApplication(ApplicationContext /*!*/ appContext) { // loads configuration into the given application context // (applies only if the config has not been loaded yet by the current thread): Configuration.Load(appContext); ApplicationConfiguration app_config = Configuration.Application; // takes a writable copy of a global configuration: LocalConfiguration config = (LocalConfiguration)Configuration.DefaultLocal.DeepCopy(); ScriptContext result = new ScriptContext(appContext, config, TextWriter.Null, Stream.Null); result.IsOutputBuffered = result.config.OutputControl.OutputBuffering; result.AutoGlobals.Initialize(); result.ThrowExceptionOnError = true; result.config.ErrorControl.HtmlMessages = false; return(ScriptContext.CurrentContext = result); }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { SQLiteLocalConfig local = (SQLiteLocalConfig)config.GetLibraryConfig(SQLiteLibraryDescriptor.Singleton); SQLiteLocalConfig @default = DefaultLocal; SQLiteGlobalConfig global = Global; switch (option) { // local: // global: case "sqlite.assoc_case": Debug.Assert(action == IniAction.Get); return PhpIni.GSR(ref global.AssocCase, 0, value, action); } Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
/// <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); } }
/// <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 + "()"); } }
/// <summary> /// Initializes all auto-global variables. /// </summary> internal void Initialize(LocalConfiguration config /*!*/, HttpContext context) { Debug.Assert(config != null); HttpRequest request = (context != null) ? context.Request : null; // $_ENV: InitializeEnvironmentVariables(config); // $_SERVER: InitializeServerVariables(config, context); // $_GET, $_POST, $_COOKIE, $_REQUEST, $HTTP_RAW_POST_DATA: InitializeGetPostCookieRequestVariables(config, request); // $_SESSION (initialized by session_start) // $_FILE: InitializeFileVariables(config, request, context); // $GLOBALS: InitializeGlobals(config, request); }
/// <summary> /// Loads $GLOBALS from $_ENV, $_REQUEST, $_SERVER and $_FILES. /// </summary> private void InitializeGlobals(LocalConfiguration /*!*/ config, HttpRequest /*!*/ request) { Debug.Assert(config != null && Request.Value != null && Env.Value != null && Server.Value != null && Files.Value != null); PhpArray globals; GlobalConfiguration global = Configuration.Global; // estimates the initial capacity of $GLOBALS array: int count = EstimatedUserGlobalVariableCount + AutoGlobals.MaxCount; if (global.GlobalVariables.RegisterLongArrays) { count += AutoGlobals.MaxCount; } // adds EGPCS variables as globals: if (global.GlobalVariables.RegisterGlobals) { PhpArray env_array = (PhpArray)Env.Value; PhpArray get_array = (PhpArray)Get.Value; PhpArray post_array = (PhpArray)Post.Value; PhpArray files_array = (PhpArray)Files.Value; PhpArray cookie_array = (PhpArray)Cookie.Value; PhpArray server_array = (PhpArray)Server.Value; PhpArray request_array = (PhpArray)Request.Value; if (request != null) { globals = new PhpArray(0, count + env_array.Count + request_array.Count + server_array.Count + files_array.Count * 4); // adds items in the order specified by RegisteringOrder config option (overwrites existing): string order = config.Variables.RegisteringOrder; for (int i = 0; i < order.Length; i++) { switch (order[i]) { case 'E': AddVariables(globals, env_array); break; case 'G': AddVariables(globals, get_array); break; case 'P': AddVariables(globals, post_array); AddFileVariablesToGlobals(globals, files_array); break; case 'C': AddVariables(globals, cookie_array); break; case 'S': AddVariables(globals, server_array); break; } } } else { globals = new PhpArray(0, count + env_array.Count); AddVariables(globals, env_array); } } else { globals = new PhpArray(0, count); } // command line argc, argv: if (request == null) { string[] args = Environment.GetCommandLineArgs(); PhpArray argv = new PhpArray(0, args.Length); // adds all arguments to the array (the 0-th argument is not '-' as in PHP but the program file): for (int i = 0; i < args.Length; i++) { argv.Add(i, args[i]); } globals["argv"] = argv; globals["argc"] = args.Length; } // adds auto-global variables (overwrites potential existing variables in $GLOBALS): globals[GlobalsName] = Globals; globals[EnvName] = Env; globals[GetName] = Get; globals[PostName] = Post; globals[CookieName] = Cookie; globals[RequestName] = Request; globals[ServerName] = Server; globals[FilesName] = Files; globals[SessionName] = Session; globals[HttpRawPostDataName] = HttpRawPostData; // adds long arrays: if (Configuration.Global.GlobalVariables.RegisterLongArrays) { globals.Add("HTTP_ENV_VARS", new PhpReference(((PhpArray)Env.Value).DeepCopy())); globals.Add("HTTP_GET_VARS", new PhpReference(((PhpArray)Get.Value).DeepCopy())); globals.Add("HTTP_POST_VARS", new PhpReference(((PhpArray)Post.Value).DeepCopy())); globals.Add("HTTP_COOKIE_VARS", new PhpReference(((PhpArray)Cookie.Value).DeepCopy())); globals.Add("HTTP_SERVER_VARS", new PhpReference(((PhpArray)Server.Value).DeepCopy())); globals.Add("HTTP_POST_FILES", new PhpReference(((PhpArray)Files.Value).DeepCopy())); // both session array references the same array: globals.Add("HTTP_SESSION_VARS", Session); } Globals.Value = globals; }
/// <summary> /// Loads $_GET, $_POST, $_COOKIE, $HTTP_RAW_POST_DATA, and $_REQUEST arrays. /// </summary> private void InitializeGetPostCookieRequestVariables(LocalConfiguration/*!*/ config, HttpRequest request) { Debug.Assert(config != null); PhpArray get_array, post_array, cookie_array, request_array; string httprawpostdata_bytes; InitializeGetPostVariables(config, request, out get_array, out post_array, out httprawpostdata_bytes); InitializeCookieVariables(config, request, out cookie_array); InitializeRequestVariables(request, config.Variables.RegisteringOrder, get_array, post_array, cookie_array, out request_array); Get.Value = get_array; Post.Value = post_array; Cookie.Value = cookie_array; Request.Value = request_array; HttpRawPostData.Value = httprawpostdata_bytes; }
/// <summary> /// Gets, sets or restores "variables_order" option. /// </summary> private static object GsrVariablesOrder(LocalConfiguration local, LocalConfiguration @default, object value, IniAction action) { object result = local.Variables.RegisteringOrder; switch (action) { case IniAction.Set: string svalue = Convert.ObjectToString(value); if (!LocalConfiguration.VariablesSection.ValidateRegisteringOrder(svalue)) PhpException.Throw(PhpError.Warning, CoreResources.GetString("invalid_registering_order")); else local.Variables.RegisteringOrder = svalue; break; case IniAction.Restore: local.Variables.RegisteringOrder = @default.Variables.RegisteringOrder; break; } return result; }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { GdLocalConfig local = (GdLocalConfig)config.GetLibraryConfig(GdLibraryDescriptor.Singleton); GdLocalConfig @default = DefaultLocal; GdGlobalConfig global = Global; //switch (option) //{ //// local: //case "mssql.connect_timeout": //return PhpIni.GSR(ref local.ConnectTimeout, @default.ConnectTimeout, value, action); //case "mssql.timeout": //return PhpIni.GSR(ref local.Timeout, @default.Timeout, value, action); //case "mssql.batchsize": //return PhpIni.GSR(ref local.BatchSize, @default.BatchSize, value, action); //// global: //case "mssql.max_links": //Debug.Assert(action == IniAction.Get); //return PhpIni.GSR(ref global.MaxConnections, 0, null, action); //case "mssql.secure_connection": //Debug.Assert(action == IniAction.Get); //return PhpIni.GSR(ref global.NTAuthentication, false, null, action); //} Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { IconvLocalConfig local = (IconvLocalConfig)config.GetLibraryConfig(IconvLibraryDescriptor.Singleton); IconvLocalConfig @default = DefaultLocal; IconvGlobalConfig global = Global; //[iconv] //;iconv.input_encoding = ISO-8859-1 //;iconv.internal_encoding = ISO-8859-1 //;iconv.output_encoding = ISO-8859-1 switch (option) { //// local: case "iconv.input_encoding": return PhpIni.GSR(ref local.InputEncoding, @default.InputEncoding, value, action); case "iconv.internal_encoding": return PhpIni.GSR(ref local.InternalEncoding, @default.InternalEncoding, value, action); case "iconv.output_encoding": return PhpIni.GSR(ref local.OutputEncoding, @default.OutputEncoding, value, action); } Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
/// <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); }
/// <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); } }
/// <summary> /// Loads $GLOBALS from $_ENV, $_REQUEST, $_SERVER and $_FILES. /// </summary> private void InitializeGlobals(LocalConfiguration/*!*/ config, HttpRequest/*!*/ request) { Debug.Assert(config != null && Request.Value != null && Env.Value != null && Server.Value != null && Files.Value != null); PhpArray globals; GlobalConfiguration global = Configuration.Global; // estimates the initial capacity of $GLOBALS array: int count = EstimatedUserGlobalVariableCount + AutoGlobals.MaxCount; if (global.GlobalVariables.RegisterLongArrays) count += AutoGlobals.MaxCount; // adds EGPCS variables as globals: if (global.GlobalVariables.RegisterGlobals) { PhpArray env_array = (PhpArray)Env.Value; PhpArray get_array = (PhpArray)Get.Value; PhpArray post_array = (PhpArray)Post.Value; PhpArray files_array = (PhpArray)Files.Value; PhpArray cookie_array = (PhpArray)Cookie.Value; PhpArray server_array = (PhpArray)Server.Value; PhpArray request_array = (PhpArray)Request.Value; if (request != null) { globals = new PhpArray(0, count + env_array.Count + request_array.Count + server_array.Count + files_array.Count * 4); // adds items in the order specified by RegisteringOrder config option (overwrites existing): string order = config.Variables.RegisteringOrder; for (int i = 0; i < order.Length; i++) { switch (order[i]) { case 'E': AddVariables(globals, env_array); break; case 'G': AddVariables(globals, get_array); break; case 'P': AddVariables(globals, post_array); AddFileVariablesToGlobals(globals, files_array); break; case 'C': AddVariables(globals, cookie_array); break; case 'S': AddVariables(globals, server_array); break; } } } else { globals = new PhpArray(0, count + env_array.Count); AddVariables(globals, env_array); } } else { globals = new PhpArray(0, count); } // command line argc, argv: if (request == null) { string[] args = Environment.GetCommandLineArgs(); PhpArray argv = new PhpArray(0, args.Length); // adds all arguments to the array (the 0-th argument is not '-' as in PHP but the program file): for (int i = 0; i < args.Length; i++) argv.Add(i, args[i]); globals["argv"] = argv; globals["argc"] = args.Length; } // adds auto-global variables (overwrites potential existing variables in $GLOBALS): globals[GlobalsName] = Globals; globals[EnvName] = Env; globals[GetName] = Get; globals[PostName] = Post; globals[CookieName] = Cookie; globals[RequestName] = Request; globals[ServerName] = Server; globals[FilesName] = Files; globals[SessionName] = Session; globals[HttpRawPostDataName] = HttpRawPostData; // adds long arrays: if (Configuration.Global.GlobalVariables.RegisterLongArrays) { globals.Add("HTTP_ENV_VARS", new PhpReference(((PhpArray)Env.Value).DeepCopy())); globals.Add("HTTP_GET_VARS", new PhpReference(((PhpArray)Get.Value).DeepCopy())); globals.Add("HTTP_POST_VARS", new PhpReference(((PhpArray)Post.Value).DeepCopy())); globals.Add("HTTP_COOKIE_VARS", new PhpReference(((PhpArray)Cookie.Value).DeepCopy())); globals.Add("HTTP_SERVER_VARS", new PhpReference(((PhpArray)Server.Value).DeepCopy())); globals.Add("HTTP_POST_FILES", new PhpReference(((PhpArray)Files.Value).DeepCopy())); // both session array references the same array: globals.Add("HTTP_SESSION_VARS", Session); } Globals.Value = globals; }
/// <summary> /// Gets, sets or restores "session.save_handler" option. /// </summary> internal static object GsrHandler(LocalConfiguration local, LocalConfiguration @default, object value, IniAction action) { string result = local.Session.Handler.Name; switch (action) { case IniAction.Set: { string name = Core.Convert.ObjectToString(value); SessionHandler handler = SessionHandlers.GetHandler(name); if (handler == null) { PhpException.Throw(PhpError.Warning, PhpException.ToErrorMessage(CoreResources.GetString("unknown_session_handler", name))); } else { local.Session.Handler = handler; } break; } case IniAction.Restore: local.Session.Handler = @default.Session.Handler; break; } return result; }
/// <summary> /// Loads $_FILES from HttpRequest.Files. /// </summary> /// <remarks> /// <list type="bullet"> /// <item>$_FILES[{var_name}]['name'] - The original name of the file on the client machine.</item> /// <item>$_FILES[{var_name}]['type'] - The mime type of the file, if the browser provided this information. An example would be "image/gif".</item> /// <item>$_FILES[{var_name}]['size'] - The size, in bytes, of the uploaded file.</item> /// <item>$_FILES[{var_name}]['tmp_name'] - The temporary filename of the file in which the uploaded file was stored on the server.</item> /// <item>$_FILES[{var_name}]['error'] - The error code associated with this file upload.</item> /// </list> /// </remarks> private void InitializeFileVariables(LocalConfiguration/*!*/ config, HttpRequest request, HttpContext context) { Debug.Assert(config != null); PhpArray files; int count; GlobalConfiguration global_config = Configuration.Global; if (request != null && global_config.PostedFiles.Accept && (count = request.Files.Count) > 0) { Debug.Assert(context != null); Debug.Assert(RequestContext.CurrentContext != null, "PHP.Core.RequestContext not initialized!"); files = new PhpArray(0, count); // gets a path where temporary files are stored: var temppath = global_config.PostedFiles.GetTempPath(global_config.SafeMode); // temporary file name (first part) var basetempfilename = string.Concat("php_", context.Timestamp.Ticks.ToString("x"), "-"); var basetempfileid = this.GetHashCode(); for (int i = 0; i < count; i++) { string name = request.Files.GetKey(i); string file_path, type, file_name; HttpPostedFile file = request.Files[i]; PostedFileError error = PostedFileError.None; if (!string.IsNullOrEmpty(file.FileName)) { type = file.ContentType; var tempfilename = string.Concat(basetempfilename, (basetempfileid++).ToString("X"), ".tmp"); file_path = Path.Combine(temppath, tempfilename); file_name = Path.GetFileName(file.FileName); // registers the temporary file for deletion at request end: RequestContext.CurrentContext.AddTemporaryFile(file_path); // saves uploaded content to the temporary file: file.SaveAs(file_path); } else { file_path = type = file_name = String.Empty; error = PostedFileError.NoFile; } AddVariable(files, name, file_name, "name"); AddVariable(files, name, type, "type"); AddVariable(files, name, file_path, "tmp_name"); AddVariable(files, name, (int)error, "error"); AddVariable(files, name, file.ContentLength, "size"); } } else { files = new PhpArray(0, 0); } Files.Value = files; }
/// <summary> /// Loads $_COOKIE arrays from HttpRequest.Cookies. /// </summary> /// <param name="config">Local configuration.</param> /// <param name="request">HTTP request instance or a <B>null</B> reference.</param> /// <param name="cookieArray">Resulting $_COOKIE array.</param> /// <exception cref="ArgumentNullException"><paranref name="config"/> is a <B>null</B> reference.</exception> public static void InitializeCookieVariables(LocalConfiguration/*!*/ config, HttpRequest request, out PhpArray cookieArray) { Debug.Assert(config != null); if (request != null) { var cookies = request.Cookies; Debug.Assert(cookies != null, "cookies == null"); int count = cookies.Count; cookieArray = new PhpArray(0, count); for (int i = 0; i < count; i++) { HttpCookie cookie = cookies.Get(i); AddVariable(cookieArray, cookie.Name, UrlDecodeValue(cookie.Value), null); // adds a copy of cookie with the same key as the session name; // the name gets encoded and so $_COOKIE[session_name()] doesn't work then: if (cookie.Name == AspNetSessionHandler.AspNetSessionName) cookieArray[AspNetSessionHandler.AspNetSessionName] = UrlDecodeValue(cookie.Value); } } else { cookieArray = new PhpArray(0, 0); } }
/// <summary> /// Loads $_GET, $_POST arrays from HttpRequest.QueryString and HttpRequest.Form. /// </summary> /// <param name="config">Local configuration.</param> /// <param name="request">HTTP request instance or a <B>null</B> reference.</param> /// <param name="getArray">Resulting $_GET array.</param> /// <param name="postArray">Resulting $_POST array.</param> /// <param name="httprawpostdataBytes">$HTTP_RAW_POST_DATA variable.</param> /// <exception cref="ArgumentNullException"><paranref name="config"/> is a <B>null</B> reference.</exception> public static void InitializeGetPostVariables(LocalConfiguration/*!*/ config, HttpRequest request, out PhpArray getArray, out PhpArray postArray, out string httprawpostdataBytes) { if (config == null) throw new ArgumentNullException("config"); if (request != null) { if (request.RequestType == "GET") { getArray = new PhpArray(0, request.QueryString.Count + request.Form.Count); postArray = new PhpArray(0, 0); // loads Form variables to GET array: LoadFromCollection(getArray, request.Form); } else { getArray = new PhpArray(0, request.QueryString.Count); postArray = new PhpArray(0, request.Form.Count); // loads Form variables to POST array: LoadFromCollection(postArray, request.Form); } // loads Query variables to GET array: LoadFromCollection(getArray, request.QueryString); // HTTP_RAW_POST_DATA // when always_populate_raw_post_data option is TRUE, however using "php://input" is preferred. For "multipart/form-data" it is not available. try { httprawpostdataBytes = (config.Variables.AlwaysPopulateRawPostData && !request.ContentType.StartsWith("multipart/form-data")) ? new StreamReader(request.InputStream).ReadToEnd() : null; } catch { httprawpostdataBytes = null; // unable to read the input stream, unreachable } } else { getArray = new PhpArray(0, 0); postArray = new PhpArray(0, 0); httprawpostdataBytes = null; } }
private Configuration(GlobalConfiguration /*!*/ global, LocalConfiguration /*!*/ defaultLocal) { this.global = global; this.defaultLocal = defaultLocal; }
/// <summary> /// Loads $_ENV from Environment.GetEnvironmentVariables(). /// </summary> private void InitializeEnvironmentVariables(LocalConfiguration/*!*/ config) { Debug.Assert(config != null); IDictionary env_vars = Environment.GetEnvironmentVariables(); PhpArray array = new PhpArray(0, env_vars.Count); foreach (DictionaryEntry entry in env_vars) AddVariable(array, entry.Key as string, entry.Value as string, null); Env.Value = array; }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { MySqlLocalConfig local = (MySqlLocalConfig)config.GetLibraryConfig(MySqlLibraryDescriptor.Singleton); MySqlLocalConfig @default = DefaultLocal; MySqlGlobalConfig global = Global; switch (option) { // local: case "mysql.connect_timeout": return PhpIni.GSR(ref local.ConnectTimeout, @default.ConnectTimeout, value, action); case "mysql.default_port": return PhpIni.GSR(ref local.Port, @default.Port, value, action); case "mysql.default_host": return PhpIni.GSR(ref local.Server, @default.Server, value, action); case "mysql.default_user": return PhpIni.GSR(ref local.User, @default.User, value, action); case "mysql.default_password": return PhpIni.GSR(ref local.Password, @default.Password, value, action); case "mysql.default_command_timeout": return PhpIni.GSR(ref local.DefaultCommandTimeout, @default.DefaultCommandTimeout, value, action); case "mysql.connection_string": return PhpIni.GSR(ref local.ConnectionString, null, value, action); // global: case "mysql.max_links": Debug.Assert(action == IniAction.Get); return PhpIni.GSR(ref global.MaxConnections, -1, null, action); case "mysql.max_pool_size": return PhpIni.GSR(ref global.MaxPoolSize, 100, value, action); } Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
/// <summary> /// Loads $_SERVER from HttpRequest.ServerVariables. /// </summary> private void InitializeServerVariables(LocalConfiguration /*!*/ config, HttpContext context) { if (context == null) { Server.Value = new PhpArray(); return; } Debug.Assert(config != null); PhpArray array, argv; var request = context.Request; var serverVariables = request.ServerVariables; Server.Value = array = new PhpArray(0, /*serverVariables.Count*/ 64); // adds variables defined by ASP.NET and IIS: LoadFromCollection(array, serverVariables); // adds argv, argc variables: if (Configuration.Global.GlobalVariables.RegisterArgcArgv) { array["argv"] = argv = new PhpArray(1) { request.QueryString }; array["argc"] = 0; } // additional variables defined in PHP manual: array["PHP_SELF"] = request.Path; try { array["DOCUMENT_ROOT"] = request.MapPath("/"); // throws exception under mod_aspdotnet } catch { array["DOCUMENT_ROOT"] = null; } array["SERVER_ADDR"] = serverVariables["LOCAL_ADDR"]; array["REQUEST_URI"] = request.RawUrl; array["REQUEST_TIME"] = DateTimeUtils.UtcToUnixTimeStamp(context.Timestamp.ToUniversalTime()); array["SCRIPT_FILENAME"] = request.PhysicalPath; //IPv6 is the default in IIS7, convert to an IPv4 address (store the IPv6 as well) if (request.UserHostAddress.Contains(":")) { array["REMOTE_ADDR_IPV6"] = request.UserHostAddress; if (request.UserHostAddress == "::1") { array["REMOTE_ADDR"] = array["SERVER_ADDR"] = "127.0.0.1"; } else { foreach (IPAddress IPA in Dns.GetHostAddresses(request.UserHostAddress)) { if (IPA.AddressFamily.ToString() == "InterNetwork") { array["REMOTE_ADDR"] = IPA.ToString(); break; } } } } // PATH_INFO // should contain partial path information only // note: IIS has AllowPathInfoForScriptMappings property that do the thing ... but ISAPI does not work then // hence it must be done here manually if (array.ContainsKey("PATH_INFO")) { string path_info = (string)array["PATH_INFO"]; string script_name = (string)array["SCRIPT_NAME"]; // 'ORIG_PATH_INFO' // Original version of 'PATH_INFO' before processed by PHP. array["ORIG_PATH_INFO"] = path_info; // 'PHP_INFO' // Contains any client-provided pathname information trailing the actual script filename // but preceding the query string, if available. For instance, if the current script was // accessed via the URL http://www.example.com/php/path_info.php/some/stuff?foo=bar, // then $_SERVER['PATH_INFO'] would contain /some/stuff. // php-5.3.2\sapi\isapi\php5isapi.c: // // strncpy(path_info_buf, static_variable_buf + scriptname_len - 1, sizeof(path_info_buf) - 1); // PATH_INFO = PATH_INFO.SubString(SCRIPT_NAME.Length); array["PATH_INFO"] = (script_name.Length <= path_info.Length) ? path_info.Substring(script_name.Length) : string.Empty; } }
/// <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 + "()"; } }
/// <summary> /// Initializes all auto-global variables. /// </summary> internal void Initialize(LocalConfiguration config/*!*/, HttpContext context) { Debug.Assert(config != null); HttpRequest request = (context != null) ? context.Request : null; // $_ENV: InitializeEnvironmentVariables(config); // $_SERVER: InitializeServerVariables(config, context); // $_GET, $_POST, $_COOKIE, $_REQUEST, $HTTP_RAW_POST_DATA: InitializeGetPostCookieRequestVariables(config, request); // $_SESSION (initialized by session_start) // $_FILE: InitializeFileVariables(config, request, context); // $GLOBALS: InitializeGlobals(config, request); }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { LibraryConfiguration local = (LibraryConfiguration)config.GetLibraryConfig(LibraryDescriptor.Singleton); LibraryConfiguration @default = DefaultLocal; switch (option) { case "sendmail_from": return PhpIni.GSR(ref local.Mailer.DefaultFromHeader, @default.Mailer.DefaultFromHeader, value, action); case "SMTP": return PhpIni.GSR(ref local.Mailer.SmtpServer, @default.Mailer.SmtpServer, value, action); case "smtp_port": return PhpIni.GSR(ref local.Mailer.SmtpPort, @default.Mailer.SmtpPort, value, action); case "mail.add_x_header": return PhpIni.GSR(ref local.Mailer.AddXHeader, @default.Mailer.AddXHeader, value, action); case "highlight.bg": return PhpIni.GSR(ref local.Highlighting.Background, @default.Highlighting.Background, value, action); case "highlight.comment": return PhpIni.GSR(ref local.Highlighting.Comment, @default.Highlighting.Comment, value, action); case "highlight.default": return PhpIni.GSR(ref local.Highlighting.Default, @default.Highlighting.Default, value, action); case "highlight.html": return PhpIni.GSR(ref local.Highlighting.Html, @default.Highlighting.Html, value, action); case "highlight.keyword": return PhpIni.GSR(ref local.Highlighting.Keyword, @default.Highlighting.Keyword, value, action); case "highlight.string": return PhpIni.GSR(ref local.Highlighting.String, @default.Highlighting.String, value, action); case "session.serialize_handler": return PhpSession.GsrSerializer(local, @default, value, action); case "session.cache_expire": return PhpSession.GsrCacheExpire(value, action); case "session.cache_limiter": return PhpSession.GsrCacheLimiter(value, action); case "session.save_path": return PhpIni.GSR(ref local.Session.SavePath, @default.Session.SavePath, value, action); case "session.gc_maxlifetime": return PhpIni.GSR(ref local.Session.GcMaxLifetime, @default.Session.GcMaxLifetime, value, action); case "session.gc_probability": return PhpIni.GSR(ref local.Session.GcProbability, @default.Session.GcProbability, value, action); case "session.gc_divisor": return PhpIni.GSR(ref local.Session.GcDivisor, @default.Session.GcDivisor, value, action); case "session.cookie_lifetime": return PhpSession.GsrCookieLifetime(value, action); case "session.cookie_path": return PhpSession.GsrCookiePath(value, action); case "session.cookie_domain": return PhpSession.GsrCookieDomain(value, action); case "session.cookie_secure": return PhpSession.GsrCookieSecure(value, action); case "date.default_latitude": return PhpIni.GSR(ref local.Date.Latitude, @default.Date.Latitude, value, action); case "date.default_longitude": return PhpIni.GSR(ref local.Date.Longitude, @default.Date.Longitude, value, action); case "date.sunrise_zenith": return PhpIni.GSR(ref local.Date.SunriseZenith, @default.Date.SunriseZenith, value, action); case "date.sunset_zenith": return PhpIni.GSR(ref local.Date.SunsetZenith, @default.Date.SunsetZenith, value, action); case "date.timezone": return PhpTimeZone.GsrTimeZone(local, @default, value, action); } Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
internal static object GetSetRestoreCoreOption(LocalConfiguration local, string option, object value, IniAction action) { LocalConfiguration @default = Configuration.DefaultLocal; GlobalConfiguration global = Configuration.Global; ApplicationConfiguration app = Configuration.Application; switch (option) { #region <paths> case "extension_dir": Debug.Assert(action == IniAction.Get); return app.Paths.Libraries; #endregion #region <compiler> case "short_open_tag": Debug.Assert(action == IniAction.Get); return app.Compiler.ShortOpenTags; case "asp_tags": Debug.Assert(action == IniAction.Get); return app.Compiler.AspTags; #endregion #region <error-control> case "html_errors": return GSR(ref local.ErrorControl.HtmlMessages, @default.ErrorControl.HtmlMessages, value, action); case "display_errors": return GSR(ref local.ErrorControl.DisplayErrors, @default.ErrorControl.DisplayErrors, value, action); case "error_append_string": return GSR(ref local.ErrorControl.ErrorAppendString, @default.ErrorControl.ErrorAppendString, value, action); case "error_prepend_string": return GSR(ref local.ErrorControl.ErrorPrependString, @default.ErrorControl.ErrorPrependString, value, action); case "log_errors": return GSR(ref local.ErrorControl.EnableLogging, @default.ErrorControl.EnableLogging, value, action); case "error_log": return GsrErrorLog(local, @default, value, action); case "error_reporting": switch (action) { case IniAction.Get: return ErrorReporting(); case IniAction.Set: return ErrorReporting(Convert.ObjectToInteger(value)); case IniAction.Restore: return ErrorReporting((int)@default.ErrorControl.ReportErrors); } break; #endregion #region <output-control> case "implicit_flush": Debug.Assert(action == IniAction.Get); return @default.OutputControl.ImplicitFlush; case "output_handler": Debug.Assert(action == IniAction.Get); IPhpConvertible handler = @default.OutputControl.OutputHandler; return (handler != null) ? handler.ToString() : null; case "output_buffering": Debug.Assert(action == IniAction.Get); return @default.OutputControl.OutputBuffering; #endregion #region <request-control> case "max_execution_time": { object result = GSR(ref local.RequestControl.ExecutionTimeout, @default.RequestControl.ExecutionTimeout, value, action); // applies the timeout: if (action != IniAction.Get) ScriptContext.CurrentContext.ApplyExecutionTimeout(local.RequestControl.ExecutionTimeout); return result; } case "ignore_user_abort": { object result = GSR(ref local.RequestControl.IgnoreUserAbort, @default.RequestControl.IgnoreUserAbort, value, action); // enables/disables disconnection tracking: if (action != IniAction.Get) RequestContext.CurrentContext.TrackClientDisconnection = !local.RequestControl.IgnoreUserAbort; return result; } #endregion #region <file-system> case "allow_url_fopen": return GSR(ref local.FileSystem.AllowUrlFopen, @default.FileSystem.AllowUrlFopen, value, action); case "user_agent": return GSR(ref local.FileSystem.UserAgent, @default.FileSystem.UserAgent, value, action); case "from": return GSR(ref local.FileSystem.AnonymousFtpPassword, @default.FileSystem.AnonymousFtpPassword, value, action); case "default_socket_timeout": return GSR(ref local.FileSystem.DefaultSocketTimeout, @default.FileSystem.DefaultSocketTimeout, value, action); case "include_path": return GSR(ref local.FileSystem.IncludePaths, @default.FileSystem.IncludePaths, value, action); #endregion #region <variables> case "zend.ze1_compatibility_mode": Debug.Assert(action != IniAction.Set || OptionValueToBoolean(value) == false); return false;// GSR(ref local.Variables.ZendEngineV1Compatible, @default.Variables.ZendEngineV1Compatible, value, action); case "magic_quotes_runtime": return GSR(ref local.Variables.QuoteRuntimeVariables, @default.Variables.QuoteRuntimeVariables, value, action); case "magic_quotes_sybase": Debug.Assert(action == IniAction.Get || OptionValueToBoolean(value) == local.Variables.QuoteInDbManner); return local.Variables.QuoteInDbManner; //GSR(ref local.Variables.QuoteInDbManner, @default.Variables.QuoteInDbManner, value, action); case "magic_quotes_gpc": Debug.Assert(action == IniAction.Get || OptionValueToBoolean(value) == global.GlobalVariables.QuoteGpcVariables); return global.GlobalVariables.QuoteGpcVariables; case "register_argc_argv": Debug.Assert(action == IniAction.Get); return global.GlobalVariables.RegisterArgcArgv; case "register_globals": Debug.Assert(action == IniAction.Get); return global.GlobalVariables.RegisterGlobals; case "register_long_arrays": Debug.Assert(action == IniAction.Get); return global.GlobalVariables.RegisterLongArrays; case "variables_order": return GsrVariablesOrder(local, @default, value, action); case "unserialize_callback_func": return GSR(ref local.Variables.DeserializationCallback, @default.Variables.DeserializationCallback, value, action); case "always_populate_raw_post_data": switch (action) { case IniAction.Restore: local.Variables.AlwaysPopulateRawPostData = false; break; case IniAction.Set: local.Variables.AlwaysPopulateRawPostData = Convert.ObjectToBoolean(value); break; } return local.Variables.AlwaysPopulateRawPostData; #endregion #region <posted-files> case "file_uploads": Debug.Assert(action == IniAction.Get); return global.PostedFiles.Accept; case "upload_tmp_dir": Debug.Assert(action == IniAction.Get); return global.PostedFiles.TempPath; case "post_max_size": case "upload_max_filesize": { Debug.Assert(action == IniAction.Get); HttpContext context; if (!Web.EnsureHttpContext(out context)) return null; HttpRuntimeSection http_runtime_section = (HttpRuntimeSection)context.GetSection("system.web/httpRuntime"); return (http_runtime_section != null) ? http_runtime_section.MaxRequestLength * 1024 : 0;// values in config are in kB, PHP's in B } #endregion #region <assert> case "assert.active": return GSR(ref local.Assertion.Active, @default.Assertion.Active, value, action); case "assert.bail": return GSR(ref local.Assertion.Terminate, @default.Assertion.Terminate, value, action); case "assert.quiet_eval": return GSR(ref local.Assertion.Quiet, @default.Assertion.Quiet, value, action); case "assert.warning": return GSR(ref local.Assertion.ReportWarning, @default.Assertion.ReportWarning, value, action); case "assert.callback": return GSR(ref local.Assertion.Callback, @default.Assertion.Callback, value, action); #endregion #region <safe-mode> case "safe_mode": Debug.Assert(action == IniAction.Get); return global.SafeMode.Enabled; case "open_basedir": Debug.Assert(action == IniAction.Get); return global.SafeMode.GetAllowedPathPrefixesJoin(); case "safe_mode_exec_dir": Debug.Assert(action == IniAction.Get); return global.SafeMode.ExecutionDirectory; #endregion #region <session> case "session.save_handler": return PhpSession.GsrHandler(local, @default, value, action); case "session.auto_start": Debug.Assert(action == IniAction.Get); return local.Session.AutoStart; case "session.name": Debug.Assert(action == IniAction.Get); return PhpSession.Name(); #endregion #region others case "default_charset": return GsrDefaultCharset(value, action); case "default_mimetype": return GsrDefaultMimetype(value, action); case "memory_limit": return GsrMemoryLimit(value, action); case "disable_functions": return GsrDisableFunctions(value, action); #endregion } Debug.Fail("Option '" + option + "' is supported but not implemented."); return null; }
/// <summary> /// Creates an instance of <see cref="LocalConfiguration"/> initialized by values /// copied from the specified instance. /// </summary> /// <param name="source"></param> private LocalConfiguration(LocalConfiguration source) { this.OutputControl = source.OutputControl.DeepCopy(); this.ErrorControl = source.ErrorControl.DeepCopy(); this.RequestControl = source.RequestControl.DeepCopy(); this.FileSystem = source.FileSystem.DeepCopy(); this.Assertion = source.Assertion.DeepCopy(); this.Variables = source.Variables.DeepCopy(); this.Session = source.Session.DeepCopy(); this.Library = source.Library.DeepCopy(); LastConfigurationModificationTime = source.LastConfigurationModificationTime; }
/// <summary> /// Makes a copy (child) of this instance (parent) deeply copying the confgiuration fields. /// </summary> internal PhpConfigurationContext(ApplicationContext/*!*/ applicationContext, string virtualPath, PhpConfigurationContext parent) { Debug.Assert(applicationContext != null); this.virtualPath = virtualPath; this.applicationContext = applicationContext; // section tables are shared: this.sections = parent.sections; this.sealedSections = parent.sealedSections; this.librariesList = parent.librariesList; // configuration records are copied: this.local = (LocalConfiguration)parent.local.DeepCopy(); this.global = (GlobalConfiguration)parent.global.DeepCopy(); }
/// <summary> /// Writes Core legacy options and their values to XML text stream. /// Skips options whose values are the same as default values of Phalanger. /// </summary> /// <param name="writer">XML writer.</param> /// <param name="options">A hashtable containing PHP names and option values. Consumed options are removed from the table.</param> /// <param name="writePhpNames">Whether to add "phpName" attribute to option nodes.</param> public static void CoreOptionsToXml(XmlTextWriter writer, Hashtable options, bool writePhpNames) // GENERICS: <string,string> { if (writer == null) throw new ArgumentNullException("writer"); if (options == null) throw new ArgumentNullException("options"); ApplicationConfiguration app = new ApplicationConfiguration(); GlobalConfiguration global = new GlobalConfiguration(); LocalConfiguration local = new LocalConfiguration(); PhpIniXmlWriter ow = new PhpIniXmlWriter(writer, options, writePhpNames); ow.StartSection("compiler"); ow.WriteOption("short_open_tag", "ShortOpenTag", true, app.Compiler.ShortOpenTags); ow.WriteOption("asp_tags", "AspTags", false, app.Compiler.AspTags); ow.StartSection("variables"); //ow.WriteOption("zend.ze1_compatibility_mode", "ZendEngineV1Compatible", false, local.Variables.ZendEngineV1Compatible); ow.WriteOption("register_globals", "RegisterGlobals", false, global.GlobalVariables.RegisterGlobals); ow.WriteOption("register_argc_argv", "RegisterArgcArgv", true, global.GlobalVariables.RegisterArgcArgv); ow.WriteOption("register_long_arrays", "RegisterLongArrays", true, global.GlobalVariables.RegisterLongArrays); ow.WriteOption("variables_order", "RegisteringOrder", "EGPCS", local.Variables.RegisteringOrder); //ow.WriteOption("magic_quotes_gpc", "QuoteGpcVariables", true, global.GlobalVariables.QuoteGpcVariables); ow.WriteOption("magic_quotes_runtime", "QuoteRuntimeVariables", false, local.Variables.QuoteRuntimeVariables); //ow.WriteOption("magic_quotes_sybase", "QuoteInDbManner", false, local.Variables.QuoteInDbManner); ow.WriteOption("unserialize_callback_func", "DeserializationCallback", null, local.Variables.DeserializationCallback); ow.StartSection("output-control"); ow.WriteOption("output_buffering", "OutputBuffering", false, local.OutputControl.OutputBuffering); ow.WriteOption("output_handler", "OutputHandler", null, local.OutputControl.OutputHandler); ow.WriteOption("implicit_flush", "ImplicitFlush", false, local.OutputControl.ImplicitFlush); ow.WriteOption("default_mimetype", "ContentType", "text/html", DefaultMimetype); ow.WriteOption("default_charset", "Charset", "", DefaultCharset); ow.StartSection("request-control"); ow.WriteOption("max_execution_time", "ExecutionTimeout", 30, local.RequestControl.ExecutionTimeout); ow.WriteOption("ignore_user_abort", "IgnoreUserAbort", false, local.RequestControl.IgnoreUserAbort); ow.StartSection("error-control"); ow.WriteEnumOption("error_reporting", "ReportErrors", (int)PhpErrorSet.AllButStrict, (int)local.ErrorControl.ReportErrors, typeof(PhpError)); ow.WriteOption("display_errors", "DisplayErrors", true, local.ErrorControl.DisplayErrors); ow.WriteOption("html_errors", "HtmlMessages", true, local.ErrorControl.HtmlMessages); ow.WriteOption("docref_root", "DocRefRoot", null, local.ErrorControl.DocRefRoot.ToString()); ow.WriteOption("docref_ext", "DocRefExtension", null, local.ErrorControl.DocRefExtension); ow.WriteErrorLog("error_log", null, local.ErrorControl.SysLog, local.ErrorControl.LogFile); ow.WriteOption("log_errors", "EnableLogging", false, local.ErrorControl.EnableLogging); ow.WriteOption("error_prepend_string", "ErrorPrependString", null, local.ErrorControl.ErrorPrependString); ow.WriteOption("error_append_string", "ErrorAppendString", null, local.ErrorControl.ErrorAppendString); ow.StartSection("session-control"); ow.WriteOption("session.auto_start", "AutoStart", false, local.Session.AutoStart); ow.WriteOption("session.save_handler", "Handler", "files", local.Session.Handler.Name); ow.StartSection("assertion"); ow.WriteOption("assert.active", "Active", true, local.Assertion.Active); ow.WriteOption("assert.warning", "ReportWarning", true, local.Assertion.ReportWarning); ow.WriteOption("assert.bail", "Terminate", false, local.Assertion.Terminate); ow.WriteOption("assert.quiet_eval", "Quiet", false, local.Assertion.Quiet); ow.WriteOption("assert.callback", "Callback", null, local.Assertion.Callback); ow.StartSection("safe-mode"); ow.WriteOption("safe_mode", "Enabled", false, global.SafeMode.Enabled); ow.WriteOption("open_basedir", "AllowedPathPrefixes", null, global.SafeMode.GetAllowedPathPrefixesJoin()); ow.WriteOption("safe_mode_exec_dir", "ExecutionDirectory", null, global.SafeMode.ExecutionDirectory); ow.StartSection("posted-files"); ow.WriteOption("file_uploads", "Accept", true, global.PostedFiles.Accept); ow.WriteOption("upload_tmp_dir", "TempPath", null, global.PostedFiles.TempPath); ow.StartSection("file-system"); ow.WriteOption("allow_url_fopen", "AllowUrlFopen", true, local.FileSystem.AllowUrlFopen); ow.WriteOption("default_socket_timeout", "DefaultSocketTimeout", 60, local.FileSystem.DefaultSocketTimeout); ow.WriteOption("user_agent", "UserAgent", null, local.FileSystem.UserAgent); ow.WriteOption("from", "AnonymousFtpPassword", null, local.FileSystem.AnonymousFtpPassword); ow.WriteOption("include_path", "IncludePaths", ".", local.FileSystem.IncludePaths); ow.WriteEnd(); }
/// <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); } }
/// <summary> /// Gets, sets or restores "error_log" option. /// </summary> private static object GsrErrorLog(LocalConfiguration local, LocalConfiguration @default, object value, IniAction action) { if (action == IniAction.Restore) { local.ErrorControl.LogFile = @default.ErrorControl.LogFile; local.ErrorControl.SysLog = @default.ErrorControl.SysLog; return null; } string result = (local.ErrorControl.SysLog) ? ErrorLogSysLog : local.ErrorControl.LogFile; if (action == IniAction.Set) { string svalue = Convert.ObjectToString(value); local.ErrorControl.SysLog = (string.Compare(svalue, ErrorLogSysLog, StringComparison.InvariantCultureIgnoreCase) == 0); local.ErrorControl.LogFile = (local.ErrorControl.SysLog) ? svalue : null; } return result; }
/// <summary> /// Loads $_SERVER from HttpRequest.ServerVariables. /// </summary> private void InitializeServerVariables(LocalConfiguration/*!*/ config, HttpContext context) { if (context == null) { Server.Value = new PhpArray(); return; } Debug.Assert(config != null); PhpArray array, argv; var request = context.Request; var serverVariables = request.ServerVariables; Server.Value = array = new PhpArray(0, /*serverVariables.Count*/64); // adds variables defined by ASP.NET and IIS: LoadFromCollection(array, serverVariables); // adds argv, argc variables: if (Configuration.Global.GlobalVariables.RegisterArgcArgv) { array["argv"] = argv = new PhpArray(1) { request.QueryString }; array["argc"] = 0; } // additional variables defined in PHP manual: array["PHP_SELF"] = request.Path; try { array["DOCUMENT_ROOT"] = request.MapPath("/"); // throws exception under mod_aspdotnet } catch { array["DOCUMENT_ROOT"] = null; } array["SERVER_ADDR"] = serverVariables["LOCAL_ADDR"]; array["REQUEST_URI"] = request.RawUrl; array["REQUEST_TIME"] = DateTimeUtils.UtcToUnixTimeStamp(context.Timestamp.ToUniversalTime()); array["SCRIPT_FILENAME"] = request.PhysicalPath; //IPv6 is the default in IIS7, convert to an IPv4 address (store the IPv6 as well) if (request.UserHostAddress.Contains(":")) { array["REMOTE_ADDR_IPV6"] = request.UserHostAddress; if (request.UserHostAddress == "::1") { array["REMOTE_ADDR"] = array["SERVER_ADDR"] = "127.0.0.1"; } else foreach (IPAddress IPA in Dns.GetHostAddresses(request.UserHostAddress)) { if (IPA.AddressFamily.ToString() == "InterNetwork") { array["REMOTE_ADDR"] = IPA.ToString(); break; } } } // PATH_INFO // should contain partial path information only // note: IIS has AllowPathInfoForScriptMappings property that do the thing ... but ISAPI does not work then // hence it must be done here manually if (array.ContainsKey("PATH_INFO")) { string path_info = (string)array["PATH_INFO"]; string script_name = (string)array["SCRIPT_NAME"]; // 'ORIG_PATH_INFO' // Original version of 'PATH_INFO' before processed by PHP. array["ORIG_PATH_INFO"] = path_info; // 'PHP_INFO' // Contains any client-provided pathname information trailing the actual script filename // but preceding the query string, if available. For instance, if the current script was // accessed via the URL http://www.example.com/php/path_info.php/some/stuff?foo=bar, // then $_SERVER['PATH_INFO'] would contain /some/stuff. // php-5.3.2\sapi\isapi\php5isapi.c: // // strncpy(path_info_buf, static_variable_buf + scriptname_len - 1, sizeof(path_info_buf) - 1); // PATH_INFO = PATH_INFO.SubString(SCRIPT_NAME.Length); array["PATH_INFO"] = (script_name.Length <= path_info.Length) ? path_info.Substring(script_name.Length) : string.Empty; } }
/// <summary> /// Creates an empty configuration context used as a root context. /// </summary> internal PhpConfigurationContext(ApplicationContext/*!*/ applicationContext, string virtualPath) { Debug.Assert(applicationContext != null); this.virtualPath = virtualPath; this.applicationContext = applicationContext; this.sections = new Dictionary<string, LibrarySection>(); this.sealedSections = new Dictionary<string, string>(); this.librariesList = new LibrariesConfigurationList(); this.local = new LocalConfiguration(); this.global = new GlobalConfiguration(); }
/// <summary> /// Gets, sets, or restores a value of a legacy configuration option. /// </summary> private static object GetSetRestore(LocalConfiguration config, string option, object value, IniAction action) { ZlibLocalConfig local = (ZlibLocalConfig)config.GetLibraryConfig(ZlibLibraryDescriptor.Singleton); ZlibLocalConfig @default = DefaultLocal; ZlibGlobalConfig global = Global; switch (option) { //// local: //case "mssql.connect_timeout": //return PhpIni.GSR(ref local.ConnectTimeout, @default.ConnectTimeout, value, action); //case "mssql.timeout": //return PhpIni.GSR(ref local.Timeout, @default.Timeout, value, action); //case "mssql.batchsize": //return PhpIni.GSR(ref local.BatchSize, @default.BatchSize, value, action); // global: case "zlib.output_compression": Debug.Assert(action == IniAction.Get, "Setting zlib.output_compression is not currently implemented."); return false; case "zlib.output_compression_level": Debug.Assert(action == IniAction.Get, "Setting zlib.output_compression_level is not currently implemented."); return -1; case "zlib.output_handler": Debug.Assert(action == IniAction.Get, "Setting zlib.output_handler is not currently implemented."); return ""; } Debug.Fail("Option '" + option + "' is not currently supported."); return null; }
private Configuration(GlobalConfiguration/*!*/ global, LocalConfiguration/*!*/ defaultLocal) { this.global = global; this.defaultLocal = defaultLocal; }
/// <summary> /// Loads $_FILES from HttpRequest.Files. /// </summary> /// <remarks> /// <list type="bullet"> /// <item>$_FILES[{var_name}]['name'] - The original name of the file on the client machine.</item> /// <item>$_FILES[{var_name}]['type'] - The mime type of the file, if the browser provided this information. An example would be "image/gif".</item> /// <item>$_FILES[{var_name}]['size'] - The size, in bytes, of the uploaded file.</item> /// <item>$_FILES[{var_name}]['tmp_name'] - The temporary filename of the file in which the uploaded file was stored on the server.</item> /// <item>$_FILES[{var_name}]['error'] - The error code associated with this file upload.</item> /// </list> /// </remarks> private void InitializeFileVariables(LocalConfiguration /*!*/ config, HttpRequest request, HttpContext context) { Debug.Assert(config != null); PhpArray files; int count; GlobalConfiguration global_config = Configuration.Global; if (request != null && global_config.PostedFiles.Accept && (count = request.Files.Count) > 0) { Debug.Assert(context != null); Debug.Assert(RequestContext.CurrentContext != null, "PHP.Core.RequestContext not initialized!"); files = new PhpArray(0, count); // gets a path where temporary files are stored: var temppath = global_config.PostedFiles.GetTempPath(global_config.SafeMode); // temporary file name (first part) var basetempfilename = string.Concat("php_", context.Timestamp.Ticks.ToString("x"), "-"); var basetempfileid = this.GetHashCode(); for (int i = 0; i < count; i++) { string name = request.Files.GetKey(i); string file_path, type, file_name; HttpPostedFile file = request.Files[i]; PostedFileError error = PostedFileError.None; if (!string.IsNullOrEmpty(file.FileName)) { type = file.ContentType; var tempfilename = string.Concat(basetempfilename, (basetempfileid++).ToString("X"), ".tmp"); file_path = Path.Combine(temppath, tempfilename); file_name = Path.GetFileName(file.FileName); // registers the temporary file for deletion at request end: RequestContext.CurrentContext.AddTemporaryFile(file_path); // saves uploaded content to the temporary file: file.SaveAs(file_path); } else { file_path = type = file_name = String.Empty; error = PostedFileError.NoFile; } AddVariable(files, name, file_name, "name"); AddVariable(files, name, type, "type"); AddVariable(files, name, file_path, "tmp_name"); AddVariable(files, name, (int)error, "error"); AddVariable(files, name, file.ContentLength, "size"); } } else { files = new PhpArray(0, 0); } Files.Value = files; }