コード例 #1
0
        private static bool SetupStreams(Process /*!*/ process, IDictionary /*!*/ descriptors)
        {
            foreach (DictionaryEntry entry in descriptors)
            {
                // key must be an integer:
                if (!(entry.Key is int))
                {
                    PhpException.Throw(PhpError.Warning, LibResources.GetString("argument_not_integer_indexed_array", "descriptors"));
                    return(false);
                }

                int desc_no = (int)entry.Key;

                switch (desc_no)
                {
                case 0: process.StartInfo.RedirectStandardInput = true; break;

                case 1: process.StartInfo.RedirectStandardOutput = true; break;

                case 2: process.StartInfo.RedirectStandardError = true; break;

                default:
                    PhpException.Throw(PhpError.Warning, LibResources.GetString("descriptor_unsupported", desc_no));
                    return(false);
                }
            }
            return(true);
        }
コード例 #2
0
        public static PhpArray ParseString(string ini, bool processSections, int scanner_mode)
        {
            if (scanner_mode != (int)ScannerMode.Normal)  // TODO: handle value 1
            {
                PhpException.ArgumentValueNotSupported("scanner_mode", scanner_mode);
            }

            if (string.IsNullOrEmpty(ini))
            {
                return(null);
            }

            ArrayBuilder builder = new ArrayBuilder(ScriptContext.CurrentContext, processSections);

            try
            {
                // parse the stream and let the builder build the resulting array
                Parse(ini, builder);
            }
            catch (ParseException e)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("ini_parse_error", e.LineNumber));
                return(null);
            }

            // return what we have read so far - even if a parse error occurred
            return(builder.Result);
        }
コード例 #3
0
ファイル: Serializers.CLR.cs プロジェクト: xmaxmex/Phalanger
        /// <summary>
        /// Serializes a graph of connected objects to a byte array using a given formatter.
        /// </summary>
        /// <param name="variable">The variable to serialize.</param>
        /// <param name="caller">DTypeDesc of the caller's class context if it is known or UnknownTypeDesc if it should be determined lazily.</param>
        /// <returns>
        /// The serialized representation of the <paramref name="variable"/> or a <B>null</B> reference on error.
        /// </returns>
        /// <exception cref="PhpException">Serialization failed (Notice).</exception>
        public PhpBytes Serialize(object variable, DTypeDesc caller)
        {
            MemoryStream stream = new MemoryStream();

            try
            {
                try
                {
                    // serialize the variable into the memory stream
                    GetFormatter(caller).Serialize(stream, variable);
                }
                catch (System.Reflection.TargetInvocationException e)
                {
                    throw e.InnerException;
                }
            }
            catch (SerializationException e)
            {
                PhpException.Throw(PhpError.Notice, LibResources.GetString("serialization_failed", e.Message));
                return(null);
            }

            // extract the serialized data
            return(new PhpBytes(stream.ToArray()));
        }
コード例 #4
0
        /// <summary>
        /// Merges the path with the current working directory
        /// to get a canonicalized absolute pathname representing the same path
        /// (local files only). If the provided <paramref name="path"/>
        /// is absolute (rooted local path or an URL) it is returned unchanged.
        /// </summary>
        /// <param name="path">An absolute or relative path to a directory or an URL.</param>
        /// <returns>Canonicalized absolute path in case of a local directory or the original
        /// <paramref name="path"/> in case of an URL.</returns>
        internal static string AbsolutePath(string path)
        {
            // Don't combine remote file paths with CWD.
            try
            {
                if (IsRemoteFile(path))
                {
                    return(path);
                }

                // Remove the file:// schema if any.
                path = GetFilename(path);

                // Combine the path and simplify it.
                string combinedPath = Path.Combine(PhpDirectory.GetWorking(), path);

                // Note: GetFullPath handles "C:" incorrectly
                if (combinedPath[combinedPath.Length - 1] == ':')
                {
                    combinedPath += '\\';
                }
                return(Path.GetFullPath(combinedPath));
            }
            catch (Exception)
            {
                PhpException.Throw(PhpError.Notice,
                                   LibResources.GetString("invalid_path", FileSystemUtils.StripPassword(path)));
                return(null);
            }
        }
コード例 #5
0
ファイル: TimeZones.cs プロジェクト: ikvm/Phalanger
        /// <summary>
        /// Gets/sets/resets legacy configuration setting "date.timezone".
        /// </summary>
        internal static object GsrTimeZone(LibraryConfiguration /*!*/ local, LibraryConfiguration /*!*/ @default, object value, IniAction action)
        {
            string result = (local.Date.TimeZone != null) ? local.Date.TimeZone.StandardName : null;

            switch (action)
            {
            case IniAction.Set:
            {
                string       name = Core.Convert.ObjectToString(value);
                TimeZoneInfo zone = GetTimeZone(name);

                if (zone == null)
                {
                    PhpException.Throw(PhpError.Warning, LibResources.GetString("unknown_timezone", name));
                }
                else
                {
                    local.Date.TimeZone = zone;
                }
                break;
            }

            case IniAction.Restore:
                local.Date.TimeZone = @default.Date.TimeZone;
                break;
            }
            return(result);
        }
コード例 #6
0
        public static PhpArray ParseFile(string fileName, bool processSections, int scanner_mode)
        {
            if (scanner_mode != (int)ScannerMode.Normal)  // TODO: handle value 1
            {
                PhpException.ArgumentValueNotSupported("scanner_mode", scanner_mode);
            }

            // we're using binary mode because CR/LF stuff should be preserved for multiline values
            using (PhpStream stream = PhpStream.Open(fileName, "rb", StreamOpenOptions.ReportErrors,
                                                     StreamContext.Default))
            {
                if (stream == null)
                {
                    return(null);               //new PhpArray();
                }
                ArrayBuilder builder = new ArrayBuilder(ScriptContext.CurrentContext, processSections);
                try
                {
                    // parse the stream and let the builder build the resulting array
                    Parse(stream, builder);
                }
                catch (ParseException e)
                {
                    PhpException.Throw(PhpError.Warning, LibResources.GetString("ini_parse_error", e.LineNumber));
                    return(null);
                }

                // return what we have read so far - even if a parse error occurred
                return(builder.Result);
            }
        }
コード例 #7
0
        /// <summary>
        /// Tries to get, set, or restore an option given its PHP name and value.
        /// </summary>
        /// <param name="name">The option name.</param>
        /// <param name="value">The option new value if applicable.</param>
        /// <param name="action">The action to be taken.</param>
        /// <param name="error"><B>true</B>, on failure.</param>
        /// <returns>The option old value.</returns>
        /// <exception cref="PhpException">The option not supported (Warning).</exception>
        /// <exception cref="PhpException">The option is read only but action demands write access (Warning).</exception>
        internal static object TryGetSetRestore(string name, object value, IniAction action, out bool error)
        {
            Debug.Assert(name != null);
            error = true;

            IniOptions.OptionDefinition option = GetOption(name);

            // option not found:
            if (option == null)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("unknown_option", name));
                return(null);
            }

            // the option is known but not supported:
            if ((option.Flags & IniFlags.Supported) == 0)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("option_not_supported", name));
                return(null);
            }

            // the option is global thus cannot be changed:
            if ((option.Flags & IniFlags.Local) == 0 && action != IniAction.Get)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("option_readonly", name));
                return(null);
            }

            error = false;
            return(option.Gsr(Configuration.Local, name, value, action));
        }
コード例 #8
0
ファイル: Locale.cs プロジェクト: xmaxmex/Phalanger
        public static string SetLocale(Category category, object locale, params object[] moreLocales)
        {
            CultureInfo new_culture;

            if (GetFirstExistingCulture(locale, moreLocales, out new_culture))
            {
                if ((int)category < 0 || (int)category > cultures.Length)
                {
                    PhpException.InvalidArgument("category", LibResources.GetString("arg:invalid_value"));
                    return(null);
                }

                // sets specific culture:
                SetCulture(category, new_culture);
            }
            else
            {
                new_culture = CultureInfo.CurrentCulture;
            }

            if (new_culture == CultureInfo.InvariantCulture)
            {
                return("C");
            }

            return(String.Format("{0}.{1}",
                                 new_culture.EnglishName.Replace(" (", "_").Replace(")", ""),
                                 new_culture.TextInfo.ANSICodePage));
        }
コード例 #9
0
ファイル: Serializers.CLR.cs プロジェクト: xmaxmex/Phalanger
        /// <summary>
        /// Deserializes a graph of connected object from a byte array using a given formatter.
        /// </summary>
        /// <param name="bytes">The byte array to deserialize the graph from.</param>
        /// <param name="caller">DTypeDesc of the caller's class context if it is known or UnknownTypeDesc if it should be determined lazily.</param>
        /// <returns>
        /// The deserialized object graph or an instance of <see cref="PhpReference"/> containing <B>false</B> on error.
        /// </returns>
        /// <exception cref="PhpException">Deserialization failed (Notice).</exception>
        public PhpReference Deserialize(PhpBytes bytes, DTypeDesc caller)
        {
            MemoryStream stream = new MemoryStream(bytes.ReadonlyData);
            object       result = null;

            try
            {
                try
                {
                    // deserialize the data
                    result = GetFormatter(caller).Deserialize(stream);
                }
                catch (System.Reflection.TargetInvocationException e)
                {
                    throw e.InnerException;
                }
            }
            catch (SerializationException e)
            {
                PhpException.Throw(PhpError.Notice, LibResources.GetString("deserialization_failed",
                                                                           e.Message, stream.Position, stream.Length));
                return(new PhpReference(false));
            }

            return(PhpVariable.MakeReference(result));
        }
コード例 #10
0
        public static bool AddRewriteVariable(string name, string value)
        {
            if (String.IsNullOrEmpty(name))
            {
                PhpException.InvalidArgument("name", LibResources.GetString("arg:null_or_empty"));
                return(false);
            }

            ScriptContext  context  = ScriptContext.CurrentContext;
            UrlRewriter    rewriter = UrlRewriter.GetOrCreate();
            BufferedOutput output   = context.BufferedOutput;

            // some output flush
            output.Flush();

            rewriter.Variables[name] = value;

            // start UrlRewriter filtering if not yet
            if (output.FindLevelByFilter(rewriter.filterCallback) < 0)
            {
                // create new output buffer level (URL-Rewriter is not started yet)
                int Level = output.IncreaseLevel();
                output.SetFilter(rewriter.GetOrCreateFilterCallback(context), Level);
                output.SetLevelName(Level, "URL-Rewriter");
            }

            context.IsOutputBuffered = true;    // turn on output buffering if not yet

            return(true);
        }
コード例 #11
0
ファイル: PhpJson.cs プロジェクト: jiahao42/weverca
            /// <summary>
            /// Push currently serialized array or object to the stack to prevent recursion.
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            private bool PushObject(object /*!*/ obj)
            {
                Debug.Assert(obj != null);

                if (recursionStack == null)
                {
                    recursionStack = new List <object>(8);
                }
                else
                {
                    // check recursion
                    int hits = 0;
                    for (int i = 0; i < recursionStack.Count; i++)
                    {
                        if (recursionStack[i] == obj)
                        {
                            hits++;
                        }
                    }

                    if (hits >= 2)
                    {
                        PhpException.Throw(PhpError.Warning, LibResources.GetString("recursion_detected"));
                        return(false);
                    }
                }

                recursionStack.Add(obj);
                return(true);
            }
コード例 #12
0
        public static bool Mail(string to, string subject, string message, string additionalHeaders, string additionalParameters)
        {
            // additional parameters are not supported while running windows
            if (!string.IsNullOrEmpty(additionalParameters))
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("additional_parameters_not_supported"));
            }

            return(Mail(to, subject, message, additionalHeaders));
        }
コード例 #13
0
        /// <summary>
        /// Casts the given resource handle to the <see cref="DirectoryListing"/> enumerator.
        /// Throw an exception when a wrong argument is supplied.
        /// </summary>
        /// <param name="dir_handle">The handle passed to a PHP function.</param>
        /// <returns>The enumerator over the files in the DirectoryListing.</returns>
        /// <exception cref="PhpException">When the supplied argument is not a valid <see cref="DirectoryListing"/> resource.</exception>
        private static System.Collections.IEnumerator ValidListing(PhpResource dir_handle)
        {
            DirectoryListing listing = dir_handle as DirectoryListing;

            if (listing != null)
            {
                return(listing.Enumerator);
            }

            PhpException.Throw(PhpError.Warning, LibResources.GetString("invalid_directory_resource"));
            return(null);
        }
コード例 #14
0
        public static int sleep(int seconds)
        {
            if (seconds < 0)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("sleep_seconds_less_zero"));
                return(-1);
            }

            Thread.Sleep(((long)seconds * 1000 > int.MaxValue) ? seconds = Timeout.Infinite : seconds * 1000);

            return(0);
        }
コード例 #15
0
ファイル: Objects.cs プロジェクト: jiahao42/weverca
        public static string ObjectHash(object obj)
        {
            DObject dobj = obj as DObject;

            if (dobj == null)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("unexpected_arg_given", 1, DObject.PhpTypeName, PhpVariable.GetTypeName(obj).ToLower()));
                return(null);
            }

            return(dobj.GetHashCode().ToString("x32"));
        }
コード例 #16
0
        /// <summary>
        /// Converts semicolon separated list of email addresses and names of email owners
        /// to semicolon separated list of only email addresses.
        /// </summary>
        /// <param name="emails">Semicolon separated list of email addresses and names.</param>
        /// <param name="max">Max number of emails returned.</param>
        /// <returns>Semicolon separated list of email addresses only.</returns>
        private static string ExtractMailAddressesOnly(string emails, int max)
        {
            StringBuilder mailsOnly   = new StringBuilder();
            Regex         regWithName = new Regex("^[ \t]*([^<>]*?)[ \t]*<[ \t]*([^<>]*?)[ \t]*>[ \t]*$");
            Regex         regEmail    = new Regex("^[ \t]*[^@ \t<>]+@[^@ \t<>]+.[^@ \t<>]+[ \t]*$");

            Match  m, m2;
            string toAppend = "";

            string[] mailsArray = emails.Split(';');
            foreach (string mail in mailsArray)
            {
                m = regWithName.Match(mail);
                if (m.Success)                 // mail with name
                {
                    Group gr;
                    for (int i = 1; i < m.Groups.Count; i++)
                    {
                        gr = m.Groups[i];
                        m2 = regEmail.Match(gr.Value);
                        if (m2.Success)
                        {
                            toAppend = m2.Value;
                        }
                    }
                    // if an e-mail is in <..> we forget previous email found out of <..> (the name looks like e-mail address)
                    mailsOnly.Append(toAppend);
                    mailsOnly.Append(';');
                }
                else
                {
                    m2 = regEmail.Match(mail);
                    if (m2.Success)                     // only email without name
                    {
                        mailsOnly.Append(m2.Value);
                        mailsOnly.Append(';');
                    }
                    else
                    {
                        // bad e-mail address
                        PhpException.Throw(PhpError.Warning, LibResources.GetString("invalid_email_address", mail));
                    }
                }
            }

            if (mailsOnly.Length == 0)
            {
                return("");
            }

            // return without last semicolon
            return(mailsOnly.ToString(0, mailsOnly.Length - 1));
        }
コード例 #17
0
        internal static PhpProcessHandle Validate(PhpResource resource)
        {
            PhpProcessHandle result = resource as PhpProcessHandle;

            if (result == null || !result.IsValid)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("invalid_process_resource"));
                return(null);
            }

            return(result);
        }
コード例 #18
0
ファイル: TimeZones.cs プロジェクト: ikvm/Phalanger
        public static bool SetCurrentTimeZone(string zoneName)
        {
            var zone = GetTimeZone(zoneName);

            if (zone == null)
            {
                PhpException.Throw(PhpError.Notice, LibResources.GetString("unknown_timezone", zoneName));
                return(false);
            }
            _default = zone;
            return(true);
        }
コード例 #19
0
        public static bool SetCurrentTimeZone(string zoneName)
        {
            var zone = GetTimeZone(zoneName);

            if (zone == null)
            {
                PhpException.Throw(PhpError.Notice, LibResources.GetString("unknown_timezone", zoneName));
                return(false);
            }

            ScriptContext.CurrentContext.Properties.SetProperty <TimeZoneInfo>(zone);
            return(true);
        }
コード例 #20
0
        public static bool Mail(string to, string subject, string message, string additionalHeaders)
        {
            // to and subject cannot contain newlines, replace with spaces
            to      = (to != null) ? to.Replace("\r\n", " ").Replace('\n', ' ') : "";
            subject = (subject != null) ? subject.Replace("\r\n", " ").Replace('\n', ' ') : "";

            Debug.WriteLine("MAILER", "mail('{0}','{1}','{2}','{3}')", to, subject, message, additionalHeaders);

            // get current configuration, we need some fields for mailing
            LibraryConfiguration config = LibraryConfiguration.Local;

            // set SMTP server we are using
            RawSmtpClient client = new RawSmtpClient(config.Mailer.SmtpServer, config.Mailer.SmtpPort);

            // X-PHP-Originating-Script
            if (config.Mailer.AddXHeader)
            {
                additionalHeaders = "X-PHP-Originating-Script: 1:" + ScriptContext.CurrentContext.MainScriptFile.RelativePath.Path + "\n" + additionalHeaders;
            }

            try
            {
                client.Connect();
                client.SendMessage(
                    config.Mailer.DefaultFromHeader, to,
                    subject,
                    additionalHeaders,
                    message);
                return(true);
            }
            catch (Exception e)
            {
                string    error_message = e.Message;
                Exception inner         = e;
                while ((inner = inner.InnerException) != null)
                {
                    error_message += "; " + inner.Message;
                }

                PhpException.Throw(PhpError.Warning, LibResources.GetString("cannot_send_email", error_message)
#if DEBUG
                                   + "\n\n" + e.StackTrace
#endif
                                   );
                return(false);
            }
            finally
            {
                client.Disconnect();
            }
        }
コード例 #21
0
        private static int CloseProcess(Process /*!*/ process)
        {
            try
            {
                process.WaitForExit();
            }
            catch (Exception e)
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("error_waiting_for_process_exit", e.Message));
                return(-1);
            }

            return(process.ExitCode);
        }
コード例 #22
0
ファイル: Errors.cs プロジェクト: jiahao42/weverca
        public static bool Log(string message, LogAction action, string destination, string extraHeaders)
        {
            switch (action)
            {
            case LogAction.Default:

                bool result = true;

                LocalConfiguration config = Configuration.Local;

                // adds a message to the default log file:
                if (config.ErrorControl.LogFile != null)
                {
                    try { Logger.AppendLine(config.ErrorControl.LogFile, message); }
                    catch (System.Exception) { result = false; }
                }

                // adds a message to an event log:
                if (config.ErrorControl.SysLog)
                {
                    try { Logger.AddToEventLog(message); }
                    catch (System.Exception) { result = false; }
                }

                return(result);

            case LogAction.SendByEmail:
                Mailer.Mail(destination, LibResources.GetString("error_report"), message, extraHeaders);
                return(true);

            case LogAction.ToDebuggingConnection:
                PhpException.ArgumentValueNotSupported("action", (int)action);
                return(false);

            case LogAction.AppendToFile:
                try
                {
                    PHP.Core.Logger.AppendLine(destination, message);
                }
                catch (System.Exception)
                {
                    return(false);
                }
                return(true);

            default:
                PhpException.InvalidArgument("action");
                return(false);
            }
        }
コード例 #23
0
 public static bool SetWorking(string directory)
 {
     if (directory != null)
     {
         string newPath = PhpPath.AbsolutePath(directory);
         if (System.IO.Directory.Exists(newPath))
         {
             // Note: open_basedir not applied here, URL will not pass through
             ScriptContext.CurrentContext.WorkingDirectory = newPath;
             return(true);
         }
     }
     PhpException.Throw(PhpError.Warning, LibResources.GetString("directory_not_found", directory));
     return(false);
 }
コード例 #24
0
 private static bool StartProcess(Process /*!*/ process, bool reportError)
 {
     try
     {
         process.Start();
         return(true);
     }
     catch (Exception e)
     {
         if (reportError)
         {
             PhpException.Throw(PhpError.Warning, LibResources.GetString("error_starting_process", e.Message));
         }
         return(false);
     }
 }
コード例 #25
0
        public static PhpBytes Decode(string data)
        {
            if (data == null)
            {
                data = "";
            }

            MemoryStream result = new MemoryStream((int)(data.Length * 0.75) + 2);

            if (!Decode(new StringReader(data), result))
            {
                PhpException.Throw(PhpError.Warning, LibResources.GetString("invalid_uuencoded_string"));
            }

            return(new PhpBytes(result.ToArray()));
        }
コード例 #26
0
ファイル: Variables.cs プロジェクト: xmaxmex/Phalanger
 private static void AddGpcVariables(PhpArray /*!*/ globals, PhpArray /*!*/ gpcArray, string prefix)
 {
     foreach (KeyValuePair <IntStringKey, object> entry in gpcArray)
     {
         string name = prefix + entry.Key.ToString();
         if (name == VariableName.GlobalsName)
         {
             PhpException.Throw(PhpError.Warning, LibResources.GetString("attempted_variable_override",
                                                                         VariableName.GlobalsName));
         }
         else
         {
             globals[name] = PhpVariable.DeepCopy(entry.Value);
         }
     }
 }
コード例 #27
0
ファイル: Variables.cs プロジェクト: xmaxmex/Phalanger
        public static int Extract(Dictionary <string, object> definedVariables, PhpArray vars, ExtractType type)
        {
            // GENERICS: IDictionary<string,object>

            switch (type & ExtractType.NonFlags)
            {
            case ExtractType.PrefixSame:
            case ExtractType.PrefixAll:
            case ExtractType.PrefixInvalid:
            case ExtractType.PrefixIfExists:
                PhpException.InvalidArgument("prefix", LibResources.GetString("should_be_specified", "prefix"));
                return(0);
            }

            return(Extract(definedVariables, vars, type, null));
        }
コード例 #28
0
ファイル: Web.cs プロジェクト: ikvm/Phalanger
 public static PhpBytes DecodeBase64(string encoded_data, bool strict /* = false*/)
 {
     if (encoded_data == null)
     {
         return(null);
     }
     try
     {
         return(new PhpBytes(System.Convert.FromBase64String(encoded_data)));
     }
     catch (FormatException)
     {
         PhpException.Throw(PhpError.Warning, LibResources.GetString("invalid_base64_encoded_data"));
         return(null);
     }
 }
コード例 #29
0
        /// <summary>
        /// Registeres a legacy configuration option. Not thread safe.
        /// </summary>
        /// <param name="name">A case-sensitive unique option name.</param>
        /// <param name="flags">Flags.</param>
        /// <param name="gsr">A delegate pointing to a method which will perform option's value getting, setting, and restoring.</param>
        /// <param name="extension">A case-sensitive name of the extension which the option belongs to. Can be a <B>null</B> reference.</param>
        /// <remarks>
        /// Registered options are known to <c>ini_get</c>, <c>ini_set</c>, and <c>ini_restore</c> PHP functions.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="name"/> is a <B>null</B> reference.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="gsr"/> is a <B>null</B> reference.</exception>
        /// <exception cref="ArgumentException">An option with specified name has already been registered.</exception>
        public static void Register(string name, IniFlags flags, GetSetRestoreDelegate gsr, string extension)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (gsr == null)
            {
                throw new ArgumentNullException("gsr");
            }
            if (options.ContainsKey(name))
            {
                throw new ArgumentException(LibResources.GetString("option_already_registered", name));
            }

            options.Add(name, new OptionDefinition(flags, gsr, extension));
        }
コード例 #30
0
ファイル: TimeZones.cs プロジェクト: ikvm/Phalanger
            /// <summary>
            /// Finds out the time zone in the way how PHP does.
            /// </summary>
            private static TimeZoneInfo DetermineTimeZone(out Func <TimeZoneInfo, bool> changedFunc)
            {
                TimeZoneInfo result;

                // check environment variable:
#if !SILVERLIGHT
                string env_tz = Environment.GetEnvironmentVariable(EnvVariableName);
                if (!String.IsNullOrEmpty(env_tz))
                {
                    result = GetTimeZone(env_tz);
                    if (result != null)
                    {
                        // recheck the timezone only if the environment variable changes
                        changedFunc = (timezone) => !String.Equals(timezone.StandardName, Environment.GetEnvironmentVariable(EnvVariableName), StringComparison.OrdinalIgnoreCase);
                        // return the timezone set in environment
                        return(result);
                    }

                    PhpException.Throw(PhpError.Notice, LibResources.GetString("unknown_timezone_env", env_tz));
                }
#endif

                // check configuration:
                LibraryConfiguration config = LibraryConfiguration.Local;
                if (config.Date.TimeZone != null)
                {
                    // recheck the timezone only if the local configuration changes, ignore the environment variable from this point at all
                    changedFunc = (timezone) => LibraryConfiguration.Local.Date.TimeZone != timezone;
                    return(config.Date.TimeZone);
                }

                // convert current system time zone to PHP zone:
                result = SystemToPhpTimeZone(TimeZoneInfo.Local);

                // UTC:
                if (result == null)
                {
                    result = DateTimeUtils.UtcTimeZone;// GetTimeZone("UTC");
                }
                PhpException.Throw(PhpError.Strict, LibResources.GetString("using_implicit_timezone", result.Id));

                // recheck the timezone when the TimeZone in local configuration is set
                changedFunc = (timezone) => LibraryConfiguration.Local.Date.TimeZone != null;
                return(result);
            }