entry in ScriptContext.CurrentContext.DeclaredFunctions)
{
result.Add(entry.Key, entry.Value.MakeFullName());
}
return result;
}
[ImplementsFunction("__type", FunctionImplOptions.Internal)]
public static string PhpNetType(object o)
{
return o == null ? "null" : o.GetType().FullName;
}
[ImplementsFunction("__assemblies", FunctionImplOptions.Internal)]
public static PhpArray GetAssemblies()
{
PhpArray result = new PhpArray();
foreach (PhpLibraryAssembly a in ScriptContext.CurrentContext.ApplicationContext.GetLoadedLibraries())
result.Add(a.RealAssembly.FullName);
return result;
}
[ImplementsFunction("__descriptors", FunctionImplOptions.Internal)]
public static PhpArray GetDescriptors()
{
PhpArray result = new PhpArray();
foreach (PhpLibraryAssembly a in ScriptContext.CurrentContext.ApplicationContext.GetLoadedLibraries())
result.Add(a.Descriptor.GetType().FullName);
return result;
}
public sealed class Remoter : MarshalByRefObject
{
public string[] GetLoadedAssemblies()
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
string[] result = new string[assemblies.Length];
for (int i = 0; i < assemblies.Length; i++)
result[i] = assemblies[i].FullName;
return result;
}
public static Remoter CreateRemoteInstance(AppDomain domain)
{
Type t = typeof(Remoter);
return (Remoter)domain.CreateInstanceAndUnwrap(t.Assembly.FullName, t.FullName);
}
}
private static void AppDomainInfo(AppDomain domain, TextWriter output)
{
if (domain == null) return;
output.WriteLine("AppDomain info ");
output.WriteLine("FriendlyName = {0}", domain.FriendlyName);
output.WriteLine("ApplicationBase = {0}", domain.SetupInformation.ApplicationBase);
output.WriteLine("ConfigurationFile = {0}", domain.SetupInformation.ConfigurationFile);
output.WriteLine("DynamicBase = {0}", domain.SetupInformation.DynamicBase);
output.WriteLine("PrivateBinPath = {0}", domain.SetupInformation.PrivateBinPath);
output.WriteLine("CachePath = {0}", domain.SetupInformation.CachePath);
output.WriteLine("ShadowCopyDirectories = {0}", domain.SetupInformation.ShadowCopyDirectories);
output.WriteLine("ShadowCopyFiles = {0}", domain.SetupInformation.ShadowCopyFiles);
if (domain == AppDomain.CurrentDomain)
{
foreach (Assembly assembly in domain.GetAssemblies())
output.WriteLine(" Assembly: {0}", assembly.FullName);
}
else
{
foreach (string name in Remoter.CreateRemoteInstance(domain).GetLoadedAssemblies())
output.WriteLine(" Assembly: {0}", name);
}
}
[ImplementsFunction("__info", FunctionImplOptions.Internal)]
public static void Info()
{
Info(ScriptContext.CurrentContext);
}
public static void Info(ScriptContext/*!*/ scriptContext)
{
TextWriter output = scriptContext.Output;
HttpContext ctx = HttpContext.Current;
output.WriteLine("Phalanger debug info: ");
output.WriteLine(" HttpRuntime ");
output.WriteLine("AppDomainAppId = {0}", HttpRuntime.AppDomainAppId);
output.WriteLine("AppDomainAppPath = {0}", HttpRuntime.AppDomainAppPath);
output.WriteLine("AppDomainAppVirtualPath = {0}", HttpRuntime.AppDomainAppVirtualPath);
output.WriteLine("AppDomainId = {0}", HttpRuntime.AppDomainId);
output.WriteLine("AspInstallDirectory = {0}", HttpRuntime.AspInstallDirectory);
output.WriteLine("BinDirectory = {0}", HttpRuntime.BinDirectory);
output.WriteLine("ClrInstallDirectory = {0}", HttpRuntime.ClrInstallDirectory);
try
{
output.WriteLine("CodegenDir = {0}", HttpRuntime.CodegenDir);
}
catch (Exception)
{
output.WriteLine("CodegenDir = N/A");
}
output.WriteLine("MachineConfigurationDirectory = {0}", HttpRuntime.MachineConfigurationDirectory);
output.WriteLine(" Worker Process ");
output.Write("Worker processes: ");
if (ctx != null)
{
foreach (ProcessInfo pi in ProcessModelInfo.GetHistory(20))
output.Write(pi.ProcessID + ";");
output.WriteLine();
output.WriteLine("Current Worker Process start time: {0}", ProcessModelInfo.GetCurrentProcessInfo().StartTime);
}
else
{
output.WriteLine("N/A");
}
Process proc = Process.GetCurrentProcess();
output.WriteLine("Current process: Id = {0}", proc.Id);
output.WriteLine("Current PrivateMemorySize: {0} MB", proc.PrivateMemorySize64 / (1024 * 1024));
output.WriteLine("Current WorkingSet: {0} MB", proc.WorkingSet64 / (1024 * 1024));
output.WriteLine("Current VirtualMemorySize: {0} MB", proc.VirtualMemorySize64 / (1024 * 1024));
output.WriteLine("Current thread: HashCode = {0}", Thread.CurrentThread.GetHashCode());
output.WriteLine("Current domain: {0}", Thread.GetDomain().FriendlyName);
AppDomainInfo(AppDomain.CurrentDomain, output);
if (ctx != null) AppDomainInfo(AppDomain.CurrentDomain, output);
output.WriteLine(" Libraries ");
foreach (PhpLibraryAssembly a in scriptContext.ApplicationContext.GetLoadedLibraries())
a.Descriptor.Dump(output);
//output.WriteLine(" Invalidated Precompiled Scripts ");
//foreach (string item in WebServerManagersDebug.GetInvalidatedScripts())
// output.WriteLine(item);
output.WriteLine(" Cache ");
foreach (DictionaryEntry item in HttpRuntime.Cache)
if (item.Value is string)
output.WriteLine("{0} => '{1}'", item.Key, item.Value);
else
output.WriteLine("{0} => instance of {1}", item.Key, item.Value.GetType().FullName);
if (ctx != null)
{
output.WriteLine(" Query Variables ");
String[] keys;
keys = ctx.Request.QueryString.AllKeys;
for (int i = 0; i < keys.Length; i++)
output.WriteLine("{0} = \"{1}\"", keys[i], ctx.Request.QueryString.GetValues(keys[i])[0]);
if (ctx.Session != null)
{
output.WriteLine(" Session Variables ");
output.WriteLine("IsCookieless = {0}", ctx.Session.IsCookieless);
output.WriteLine("IsNewSession = {0}", ctx.Session.IsNewSession);
output.WriteLine("SessionID = {0}", ctx.Session.SessionID);
foreach (string name in ctx.Session)
{
output.Write("{0} = ", name);
PhpVariable.Dump(ctx.Session[name]);
}
}
output.WriteLine(" Cookies ");
foreach (string cookie_name in ctx.Request.Cookies)
{
HttpCookie cookie = ctx.Request.Cookies[cookie_name];
Console.WriteLine("{0} = {1}", cookie.Name, cookie.Value);
}
output.WriteLine(" Server Variables ");
keys = ctx.Request.ServerVariables.AllKeys;
for (int i = 0; i < keys.Length; i++)
output.WriteLine("{0} = \"{1}\"", keys[i], ctx.Request.ServerVariables.GetValues(keys[i])[0]);
}
else
{
output.WriteLine(" Missing HttpContext ");
}
output.WriteLine(" ");
}
}
#endif
}
================================================
FILE: Source/ClassLibrary/Doc/Arrays.xml
================================================
If the enumerator has been moved behind the last (or before the first)
item of array it is blocked until
or is called or a new item is added to the array.
================================================
FILE: Source/ClassLibrary/Doc/RootPage.html
================================================
Phalanger Class Library Reference
Phalanger Class Library Reference
Phalanger Class Library Reference
This section contains reference documentation of the public classes that constitute the Phalanger Class Library.
================================================
FILE: Source/ClassLibrary/Doc/Streams.xml
================================================
Processes the (either of type
or ) data through this filter
and returns the filtered data in one of these formats or null .
A filter may hold data in its own buffers when it's unable
to process whole the input. However, when closing is true ,
it should pass as much data as possible because it is the last call
to Filter.
A or containing
the data to be filtered.
true if this is the last call to this filter.
A or containing
the filtered data or null if no output is available yet.
Appends a filter to the chain of stream-filters of the .
The filter is attached to the read filter chain if the file was opened for reading
(i.e. File Mode: r , and/or + ); attached to the write filter chain if the file
was opened for writing (i.e. File Mode: w , a , and/or + ).
The name of the filter - either built-in or previously
defined using .
The stream which filter-chain is to be extended with the .
True if successful.
Prepends a filter to the chain of stream-filters of the .
The filter is attached to the read filter chain if the file was opened for reading
(i.e. File Mode: r , and/or + ); attached to the write filter chain if the file
was opened for writing (i.e. File Mode: w , a , and/or + ).
The name of the filter - either built-in or previously
defined using .
The stream which filter-chain is to be extended with the .
True if successful.
================================================
FILE: Source/ClassLibrary/Doc/Strings.xml
================================================
Adds backslashes before specified characters.
The string to be processed.
The list of characters to backslash. May contain intervals "a..b" where
a , b are characters and a is less than or equal to b .
The string in which all characters contained in list are backslashed
and each backslashed character which isn't between '\u0032' and '\u007f'
is converted in its octal representation (e.g. "\\123") except of '\a', '\b', '\f', '\n', '\r', '\t', '\v'
characters which are converted into their string form (e.g. '\n' -> "\\n", '\t' -> "\\t" etc.).
Converts a string from one Cyrillic character set to another.
The string to convert.
The source character set. Can be one of 'k', 'w', 'i', 'a', 'd', 'm'.
The destination character set. Can be one of 'k', 'w', 'i', 'a', 'd', 'm'.
The converted string.
================================================
FILE: Source/ClassLibrary/Doc/Variables.xml
================================================
A variable name can be used as it is or prefixed by according to
(see the following table). Regardless which name is used (prefixed or not) it is always tested by
method before the extraction is made.
Value of the &
The action taken
-
If a variable doesn't exist yet it is created otherwise its value is overwritten.
-
If a variable already exists it is skipped (its value is left untouched).
Otherwise, a new variable is created.
-
If a variable already exists its value is overwritten. Otherwise, the variable is skipped
(i.e. no new variables are created).
-
A variable name is prefixed and if a variable with that name doesn't
exists it is created and, otherwise its value is overwritten.
-
If a variable already exists its name is prefixed and a new variable
with that name is created. Otherwise, the variable's value is overwritten.
-
If a variable already exists its name is prefixed and a new variable
with that name is created. Otherwise, the variable is skipped.
Moreover, can be OR'ed by
which causes that refereces preserved - if there is a reference in
the target variable will be referencing the same thing.
================================================
FILE: Source/ClassLibrary/Errors.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Reflection;
using System.Collections;
using System.Text;
using System.ComponentModel;
using PHP.Core;
using System.Diagnostics;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
///
/// Implementation of PHP error control functions.
///
///
[ImplementsExtension(LibraryDescriptor.ExtCore)]
public static class Errors
{
#region Enumerations
///
/// Set of error types.
///
[Flags, EditorBrowsable(EditorBrowsableState.Never)]
public enum _PhpErrorSet
{
/// Error.
[ImplementsConstant("E_ERROR")]
E_ERROR = PhpError.Error,
/// Warning.
[ImplementsConstant("E_WARNING")]
E_WARNING = PhpError.Warning,
/// Parse error.
[ImplementsConstant("E_PARSE")]
E_PARSE = PhpError.ParseError,
/// Notice.
[ImplementsConstant("E_NOTICE")]
E_NOTICE = PhpError.Notice,
/// Core error.
[ImplementsConstant("E_CORE_ERROR")]
E_CORE_ERROR = PhpError.CoreError,
/// Core warning.
[ImplementsConstant("E_CORE_WARNING")]
E_CORE_WARNING = PhpError.CoreWarning,
/// Compile error.
[ImplementsConstant("E_COMPILE_ERROR")]
E_COMPILE_ERROR = PhpError.CompileError,
/// Compile warning.
[ImplementsConstant("E_COMPILE_WARNING")]
E_COMPILE_WARNING = PhpError.CompileWarning,
/// User error.
[ImplementsConstant("E_USER_ERROR")]
E_USER_ERROR = PhpError.UserError,
/// User warning.
[ImplementsConstant("E_USER_WARNING")]
E_USER_WARNING = PhpError.UserWarning,
/// User notice.
[ImplementsConstant("E_USER_NOTICE")]
E_USER_NOTICE = PhpError.UserNotice,
/// All errors but strict.
[ImplementsConstant("E_ALL")]
E_ALL = PhpErrorSet.AllButStrict,
/// Strict error.
[ImplementsConstant("E_STRICT")]
E_STRICT = PhpError.Strict,
/// E_RECOVERABLE_ERROR error.
[ImplementsConstant("E_RECOVERABLE_ERROR")]
E_RECOVERABLE_ERROR = PhpError.RecoverableError,
/// Deprecated error.
[ImplementsConstant("E_DEPRECATED")]
E_DEPRECATED = PhpError.Deprecated,
/// Deprecated error.
[ImplementsConstant("E_USER_DEPRECATED")]
E_USER_DEPRECATED = PhpError.UserDeprecated,
}
///
/// An action performed by the method.
///
public enum LogAction
{
///
/// A message to be logged is appended to log file or sent to system log depending on the
/// current value of .
///
Default,
///
/// A message is sent by an e-mail.
///
SendByEmail,
///
/// Not supported.
///
ToDebuggingConnection,
///
/// A message is appended to a specified file.
///
AppendToFile
}
#endregion
#region error_log (CLR only)
#if !SILVERLIGHT
///
/// Logs a message to a log file or the system event log.
///
/// The message to be logged.
/// Whether the message has been logged successfully.
[ImplementsFunction("error_log")]
public static bool Log(string message)
{
return Log(message, 0);
}
///
/// Performs specific with a given message and default options.
///
/// The message to be logged.
/// The to be performed.
/// Whether the message has been logged successfully.
[ImplementsFunction("error_log")]
public static bool Log(string message, LogAction action)
{
return Log(message, action, null, null);
}
///
/// Performs specific with a given message and name of the log file.
///
/// The message to be logged.
/// The name of the log file.
/// The to be performed.
/// Whether the message has been logged successfully.
[ImplementsFunction("error_log")]
public static bool Log(string message, LogAction action, string destination)
{
return Log(message, action, destination, null);
}
///
/// Performs specific with a given message, name of the log file and additional headers.
///
/// The message to be logged.
/// The name of the log file.
/// Additional headers which are sent along the e-mail.
/// The to be performed.
/// Whether the message has been logged successfully.
[ImplementsFunction("error_log")]
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;
}
}
#endif
#endregion
#region error_get_last
[ImplementsFunction("error_get_last")]
public static PhpArray GetLastError(ScriptContext/*!*/context)
{
Debug.Assert(context != null);
if (context.LastErrorType != 0)
{
PhpArray result = new PhpArray(0, 5);
result.Add("type", (int)context.LastErrorType);
result.Add("message", context.LastErrorMessage);
result.Add("file", context.LastErrorFile);
result.Add("line", context.LastErrorLine);
//result.Add("column", context.LastErrorColumn);
return result;
}
return null;
}
#endregion
#region trigger_error, user_error
///
/// Triggers user notice with a specified message.
///
/// The message.
[ImplementsFunction("trigger_error")]
public static bool TriggerError(string message)
{
PhpException.Throw(PhpError.UserNotice, message);
return true;
}
///
/// Triggers user error of an arbitrary type and specified message.
///
/// The message.
/// The type of an error. The type should be one of the user error types.
/// User specified error.
/// The argument has an invalid value.
[ImplementsFunction("trigger_error")]
public static bool TriggerError(string message, PhpError error)
{
if (((PhpErrorSet)error & PhpErrorSet.User) == 0)
return false;// PhpException.InvalidArgument("error");
PhpException.Throw(error, message);
return true;
}
///
/// Alias of trigger_error().
///
/// The message.
[ImplementsFunction("user_error")]
public static bool UserError(string message)
{
PhpException.Throw(PhpError.UserNotice, message);
return true;
}
///
/// Alias of trigger_error().
///
/// The message.
/// The type of an error. The type should be one of the user error types.
/// User specified error.
/// The argument has an invalid value.
[ImplementsFunction("user_error")]
public static bool UserError(string message, PhpError error)
{
if (((PhpErrorSet)error & PhpErrorSet.User) == 0)
return false;// PhpException.InvalidArgument("error");
return TriggerError(message, error);
}
#endregion
#region debug_backtrace, debug_print_backtrace
///
/// Returns array containing current stack state. Each item is an array representing one stack frame.
///
/// The stack trace.
///
/// The resulting array contains the following items (their keys are stated):
///
/// "file" - a source file where the function/method has been called
/// "line" - a line in a source code where the function/method has been called
/// "column" - a column in a source code where the function/method has been called
/// "function" - a name of the function/method
/// "class" - a name of a class where the method is declared (if any)
/// "object" - an object which metod has been called
/// "type" - either "::" for static methods or "->" for instance methods
///
/// PHP adds one more item - "args" containing values of arguments and object which metod has been called. This is not supported.
///
[ImplementsFunction("debug_backtrace")]
public static PhpArray Backtrace()
{
return new PhpStackTrace(ScriptContext.CurrentContext, 1).GetUserTrace();
}
///
/// Returns array containing current stack state. Each item is an array representing one stack frame.
///
/// The stack trace.
///
/// The resulting array contains the following items (their keys are stated):
///
/// "file" - a source file where the function/method has been called
/// "line" - a line in a source code where the function/method has been called
/// "column" - a column in a source code where the function/method has been called
/// "function" - a name of the function/method
/// "class" - a name of a class where the method is declared (if any)
/// "object" - an object which metod has been called
/// "type" - either "::" for static methods or "->" for instance methods
///
/// PHP adds two more item - "args" containing values of arguments and object which metod has been called. This is not supported.
///
/// Recipient e-mail address.
/// has an invalid or unsupported value. (Warning)
[ImplementsFunction("debug_backtrace")]
public static PhpArray Backtrace(bool provideObject)
{
if (provideObject == true)
PhpException.ArgumentValueNotSupported("provideObject", provideObject);
return Backtrace();
}
///
/// Prints string representation of the stack trace.
/// No value is returned.
///
[ImplementsFunction("debug_print_backtrace")]
public static void PrintBacktrace()
{
ScriptContext context = ScriptContext.CurrentContext;
context.Output.Write(new PhpStackTrace(context, 1).FormatUserTrace());
}
///
/// Prints string representation of the stack trace.
/// No value is returned.
///
[ImplementsFunction("debug_print_backtrace")]
public static void PrintBacktrace(bool provideObject)
{
if (provideObject == true)
PhpException.ArgumentValueNotSupported("provideObject", provideObject);
ScriptContext context = ScriptContext.CurrentContext;
context.Output.Write(new PhpStackTrace(context, 1).FormatUserTrace());
}
#endregion
}
#region NS: PhpLogger
/*
///
/// Not supported.
///
///
[EditorBrowsable(EditorBrowsableState.Never)]
public sealed class PhpLogger
{
/// Prevents from creating instances of this class.
private PhpLogger() { }
///
/// Not supported.
///
public enum Facility
{
[ImplementsConstant("LOG_KERN")] Kern = 0,
[ImplementsConstant("LOG_USER")] User = 8,
[ImplementsConstant("LOG_MAIL")] Mail = 16,
[ImplementsConstant("LOG_DAEMON")] Daemon = 24,
[ImplementsConstant("LOG_AUTH")] Auth = 32,
[ImplementsConstant("LOG_SYSLOG")] SysLog = 40,
[ImplementsConstant("LOG_LPR")] Lpr = 48,
[ImplementsConstant("LOG_NEWS")] News = 56,
[ImplementsConstant("LOG_UUCP")] Uucp = 64,
[ImplementsConstant("LOG_CRON")] Cron = 72,
[ImplementsConstant("LOG_AUTHPRIV")] AuthPriv = 80
}
///
/// Not supported.
///
public enum Options
{
[ImplementsConstant("LOG_PID")] PID = 1,
[ImplementsConstant("LOG_CONS")] Console = 2,
[ImplementsConstant("LOG_ODELAY")] Delay = 4,
[ImplementsConstant("LOG_NDELAY")] NoDelay = 8,
[ImplementsConstant("LOG_NOWAIT")] NoWait = 16,
[ImplementsConstant("LOG_PERROR")] PrintError = 32,
}
///
/// Not supported.
///
public enum Priority
{
[ImplementsConstant("LOG_EMERG")] Emergency = 1,
[ImplementsConstant("LOG_ALERT")] Alert = 1,
[ImplementsConstant("LOG_CRIT")] Critical = 1,
[ImplementsConstant("LOG_ERR")] Error = 4,
[ImplementsConstant("LOG_WARNING")] Warning = 5,
[ImplementsConstant("LOG_NOTICE")] Notice = 6,
[ImplementsConstant("LOG_INFO")] Info = 6,
[ImplementsConstant("LOG_DEBUG")] Debug = 6
}
///
/// Not supported.
///
[ImplementsFunction("closelog")]
public static int CloseLog()
{
return 0;
}
///
/// Not supported.
///
[ImplementsFunction("define_syslog_variables",FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static void DefineSyslogVariables()
{
PhpException.FunctionNotSupported();
}
///
/// Not supported.
///
[ImplementsFunction("openlog",FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static int OpenLog(string prefix,Options option,Facility facility)
{
PhpException.FunctionNotSupported();
return 0;
}
///
/// Not supported.
///
[ImplementsFunction("syslog",FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static int SysLog(Priority priority,string message)
{
PhpException.FunctionNotSupported();
return 0;
}
}
*/
#endregion
}
================================================
FILE: Source/ClassLibrary/FileSystem.CLR.cs
================================================
/*
Copyright (c) 2004-2006 Jan Benda and Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO:
- Added support for LOCK_EX flag for file_put_contents(). (PHP 5.1.0)
- Added lchown() and lchgrp() to change user/group ownership of symlinks. (PHP 5.1.3)
- Fixed safe_mode check for source argument of the copy() function. (PHP 5.1.3)
*/
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using PHP.Core;
using System.Security.AccessControl;
using System.Security.Principal;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
///
/// Provides PHP I/O operations using the set of StreamWrappers.
///
///
public static partial class PhpFile
{
#region Constructors and Thread Static Stuff
/// The most recent stat() result (stat() of the file).
[ThreadStatic]
private static StatStruct statCache;
/// The absolute path of the last stat() operation.
[ThreadStatic]
private static string statCacheUrl = null;
private static void Clear()
{
statCache = new StatStruct();
statCacheUrl = null;
}
#endregion
#region Stat Basics (BuildStatArray, StatInternal, lstat, stat, fstat, clearstatcache; exists, touch)
///
/// Creates a from the
/// copying the structure members into the array.
///
///
/// The resulting PhpArray has following associative keys in the given order
/// (each has a corresponding numeric index starting from zero).
/// As of ordering, first come all the numeric indexes and then come all the associative indexes.
///
/// dev Drive number of the disk containing the file (same as st_rdev).
/// ino Number of the information node (the inode) for the file (UNIX-specific). On UNIX file systems, the inode describes the file date and time stamps, permissions, and content. When files are hard-linked to one another, they share the same inode. The inode, and therefore st_ino, has no meaning in the FAT, HPFS, or NTFS file systems.
/// mode Bit mask for file-mode information. The _S_IFDIR bit is set if path specifies a directory; the _S_IFREG bit is set if path specifies an ordinary file or a device. User read/write bits are set according to the file's permission mode; user execute bits are set according to the path extension.
/// nlink Always 1 on non-NTFS file systems.
/// uid Numeric identifier of user who owns file (UNIX-specific). This field will always be zero on Windows NT systems. A redirected file is classified as a Windows NT file.
/// gid Numeric identifier of group that owns file (UNIX-specific) This field will always be zero on Windows NT systems. A redirected file is classified as a Windows NT file.
/// rdev Drive number of the disk containing the file (same as st_dev).
/// size Size of the file in bytes; a 64-bit integer for _stati64 and _wstati64
/// atime Time of last access of file. Valid on NTFS but not on FAT formatted disk drives. Gives the same
/// mtime Time of last modification of file.
/// ctime Time of creation of file. Valid on NTFS but not on FAT formatted disk drives.
/// blksize Always -1 on non-NTFS file systems.
/// blocks Always -1 on non-NTFS file systems.
///
///
/// A returned by a stream wrapper.
/// A in the format of the stat() PHP function.
internal static PhpArray BuildStatArray(StatStruct stat)
{
// An unitialized StatStruct means an error.
if (stat.st_ctime == 0) return null;
PhpArray result = new PhpArray(13, 13);
result.Add(0, (int)stat.st_dev); // device number
result.Add(1, (int)stat.st_ino); // inode number
result.Add(2, (int)stat.st_mode); // inode protection mode
result.Add(3, (int)stat.st_nlink); // number of links
result.Add(4, (int)stat.st_uid); // userid of owner
result.Add(5, (int)stat.st_gid); // groupid of owner
result.Add(6, (int)stat.st_rdev); // device type, if inode device -1
result.Add(7, (int)stat.st_size); // size in bytes (reset by caller)
result.Add(8, unchecked((int)stat.st_atime)); // time of last access (unix timestamp)
result.Add(9, unchecked((int)stat.st_mtime)); // time of last modification (unix timestamp)
result.Add(10, unchecked((int)stat.st_ctime)); // time of last change (unix timestamp)
result.Add(11, (int)-1); // blocksize of filesystem IO (-1)
result.Add(12, (int)-1); // number of blocks allocated (-1)
result.Add("dev", (int)stat.st_dev); // device number
result.Add("ino", (int)stat.st_ino); // inode number
result.Add("mode", (int)stat.st_mode); // inode protection mode
result.Add("nlink", (int)stat.st_nlink); // number of links
result.Add("uid", (int)stat.st_uid); // userid of owner
result.Add("gid", (int)stat.st_gid); // groupid of owner
result.Add("rdev", (int)stat.st_rdev); // device type, if inode device -1
result.Add("size", (int)stat.st_size); // size in bytes (reset by caller)
result.Add("atime", unchecked((int)stat.st_atime)); // time of last access (unix timestamp)
result.Add("mtime", unchecked((int)stat.st_mtime)); // time of last modification (unix timestamp)
result.Add("ctime", unchecked((int)stat.st_ctime)); // time of last change (unix timestamp)
result.Add("blksize", (int)-1); // blocksize of filesystem IO (-1)
result.Add("blocks", (int)-1); // number of blocks allocated (-1)
return result;
}
///
/// Check StatInternal input parameters.
///
/// The path passed to stat().
/// Wheter to suppress warning message if argument is empty.
/// If passed, it will contain valid StremWrapper to the given .
/// True if check passed.
private static bool StatInternalCheck(ref string path, bool quiet, out StreamWrapper wrapper)
{
wrapper = null;
if (String.IsNullOrEmpty(path))
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:empty", "path"));
return false;
}
CheckAccessOptions options = CheckAccessOptions.Empty;
if (quiet) options |= CheckAccessOptions.Quiet;
if (!PhpStream.ResolvePath(ref path, out wrapper, CheckAccessMode.FileOrDirectory, options))
return false;
// check passed
return true;
}
///
/// Check the cache for given .
///
/// Path to lookup in the cache.
/// Url of .
/// True if given is in the cache currently.
private static bool StatInternalTryCache(string path, out string url)
{
// Try to hit the cache first
url = PhpPath.GetUrl(path);
return (url == statCacheUrl);
}
///
/// Stat the path coming from ResolvePath (file:// wrapper expects path w/o the scheme).
///
///
///
///
///
/// True if stat was successfuly added into cache.
private static bool StatInternalStat(string path, string url, StreamWrapper wrapper, bool quiet)
{
StatStruct stat = wrapper.Stat(path, quiet ? StreamStatOptions.Quiet : StreamStatOptions.Empty, StreamContext.Default, false);
if (stat.st_size >= 0)
{
statCacheUrl = url;
statCache = stat;
return true;
}
else
return false;
}
///
/// Stat the given file or directory using stream-wrappers and return the stat structure
/// using the stat-cache for repetitive calls.
///
/// The path (absolute or relative or an URL) to the file or directory to stat.
/// true to suppress the display of error messages (for example for exists() ).
/// true if the contains a valid
/// stat structure for the given URL, false on an error.
internal static bool StatInternal(string path, bool quiet)
{
StreamWrapper wrapper;
if (StatInternalCheck(ref path, quiet, out wrapper))
{
string url;
if (StatInternalTryCache(path, out url))
return true;
return StatInternalStat(path, url, wrapper, quiet);
}
return false;
}
///
/// Gives information about a file or symbolic link.
///
///
/// Behaves just like a since there are no symbolic links on Windows.
///
/// Path to a file to stat .
/// A containing the stat information.
[ImplementsFunction("lstat")]
[return: CastToFalse]
public static PhpArray LinkStat(string path)
{
return Stat(path);
}
///
/// Gives information about a file.
///
/// Path to a file to stat .
/// A containing the stat information.
[ImplementsFunction("stat")]
[return: CastToFalse]
public static PhpArray Stat(string path)
{
if (StatInternal(path, false))
{
return BuildStatArray(statCache);
}
return null;
}
///
/// Gets information about a file using an open file pointer.
///
///
///
[ImplementsFunction("fstat")]
public static PhpArray Stat(PhpResource handle)
{
// Note: no cache here.
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return null;
return BuildStatArray(stream.Stat());
}
///
/// Remove all the cached stat() entries.
/// Function has no return value.
///
///
/// The intermediary used in the last stat-related function call
/// is cached together with the absolute path or URL to the resource.
/// The next call to one of the following functions will use the cached
/// structure unless is called.
///
/// The affected functions are:
/// stat() , lstat() , file_exists() , is_writable() , is_readable() ,
/// is_executable() , is_file() , is_dir() , is_link() , filectime() ,
/// fileatime() , filemtime() , fileinode() , filegroup() , fileowner() ,
/// filesize() , filetype() and fileperms() .
///
///
[ImplementsFunction("clearstatcache")]
public static void ClearStatCache()
{
Clear();
}
[ImplementsFunction("clearstatcache")]
public static void ClearStatCache( bool clear_realpath_cache )
{
Clear(); // note: arguments ignored, Phalanger does not cache a lot, caches of .NET and OS are used transparently
}
[ImplementsFunction("clearstatcache")]
public static void ClearStatCache(bool clear_realpath_cache, string filename )
{
if (!string.IsNullOrEmpty(filename) && !clear_realpath_cache)
{
// TODO: throw warning
}
Clear(); // note: arguments ignored, Phalanger does not cache a lot, caches of .NET and OS are used transparently
}
///
/// Checks whether a file exists
///
/// The file to be checked.
/// True if the file exists.
[ImplementsFunction("file_exists")]
public static bool Exists(string path)
{
if (String.IsNullOrEmpty(path)) return false;
StreamWrapper wrapper;
if (StatInternalCheck(ref path, true, out wrapper))
{
string url;
if (StatInternalTryCache(path, out url))
return true;
// we can't just call {Directory|File}.Exists since we have to throw warnings
// also we are not calling full stat(), it is slow
return FileStreamWrapper.HandleNewFileSystemInfo(false, path, (p) =>
new FileInfo(p).Exists || new DirectoryInfo(p).Exists);
}
return false;
}
///
/// Sets access and modification time of file.
///
/// The file to touch.
/// true on success, false on failure.
[ImplementsFunction("touch")]
public static bool Touch(string path)
{
return Touch(path, 0, 0);
}
///
/// Sets access and modification time of file.
///
/// The file to touch.
/// The new modification time.
/// true on success, false on failure.
[ImplementsFunction("touch")]
public static bool Touch(string path, int mtime)
{
return Touch(path, mtime, 0);
}
///
/// Sets access and modification time of file.
///
///
/// Attempts to set the access and modification time of the file named by
/// path to the value given by time. If the option time is not given,
/// uses the present time. If the third option atime is present, the access
/// time of the given path is set to the value of atime. Note that
/// the access time is always modified, regardless of the number of parameters.
/// If the file does not exist, it is created.
///
/// The file to touch.
/// The new modification time.
/// The desired access time.
/// true on success, false on failure.
[ImplementsFunction("touch")]
public static bool Touch(string path, int mtime, int atime)
{
// Create the file if it does not already exist (performs all checks).
//PhpStream file = (PhpStream)Open(path, "ab");
//if (file == null) return false;
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref path, out wrapper, CheckAccessMode.FileMayExist, CheckAccessOptions.Quiet))
return false;
if (!Exists(path))
{
// Open and close => create new.
Close(wrapper.Open(ref path, "wb", StreamOpenOptions.Empty, StreamContext.Default));
}
DateTime access_time = (atime > 0) ? DateTimeUtils.UnixTimeStampToUtc(atime) : DateTime.UtcNow;
DateTime modification_time = (mtime > 0) ? DateTimeUtils.UnixTimeStampToUtc(mtime) : DateTime.UtcNow;
access_time -= DateTimeUtils.GetDaylightTimeDifference(access_time, DateTime.UtcNow);
modification_time -= DateTimeUtils.GetDaylightTimeDifference(modification_time, DateTime.UtcNow);
try
{
File.SetLastWriteTimeUtc(path, modification_time);
File.SetLastAccessTimeUtc(path, access_time);
// Clear the cached stat values
ClearStatCache();
return true;
}
catch (UnauthorizedAccessException)
{
PhpException.Throw(PhpError.Warning, CoreResources.GetString("stream_file_access_denied",
FileSystemUtils.StripPassword(path)));
}
catch (System.Exception e)
{
PhpException.Throw(PhpError.Warning, CoreResources.GetString("stream_error",
FileSystemUtils.StripPassword(path), e.Message));
}
return false;
}
#endregion
#region Disk Stats (disk_free_space/diskfreespace, disk_total_space)
///
/// Given a string containing a directory, this function will return
/// the number of free bytes on the corresponding filesystem or disk partition.
///
/// The directory specifying the filesystem or disk partition to be examined.
/// Nuber of free bytes available or FALSE on an error.
[ImplementsFunction("disk_free_space")]
public static object GetDiskFreeSpace(string directory)
{
return GetDiskFreeSpaceInternal(directory, false);
}
///
/// Given a string containing a directory, this function will return
/// the number of free bytes on the corresponding filesystem or disk partition.
///
/// The directory specifying the filesystem or disk partition to be examined.
/// Nuber of free bytes available or FALSE on an error.
[ImplementsFunction("diskfreespace")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static object GetFreeSpace(string directory)
{
return GetDiskFreeSpaceInternal(directory, false);
}
///
/// Given a string containing a directory, this function will return
/// the number of total bytes on the corresponding filesystem or disk partition.
///
/// The directory specifying the filesystem or disk partition to be examined.
/// Total nuber of bytes on the specified filesystem or disk partition or FALSE on an error.
[ImplementsFunction("disk_total_space")]
public static object GetDiskTotalSpace(string directory)
{
return GetDiskFreeSpaceInternal(directory, true);
}
///
/// Given a string containing a directory, this function will return
/// the number of bytes (total or free depending on
/// on the corresponding filesystem or disk partition.
///
/// The directory specifying the filesystem or disk partition to be examined.
/// true to return total space available, false to return free space only.
/// Nuber of bytes available or FALSE on an error.
internal static object GetDiskFreeSpaceInternal(string directory, bool total)
{
long user_free_bytes, total_bytes, total_free_bytes;
if (!FileSystemUtils.GetDiskFreeSpace(directory, out user_free_bytes, out total_bytes, out total_free_bytes))
{
// TODO: Warning: disk_free_space(): Systm neme nalzt uvedenou cestu.\n on line....
return false;
}
else
{
return total ? (double)total_bytes : (double)user_free_bytes;
}
}
#endregion
#region Stat Values (file* functions)
///
/// Gets file type.
///
///
/// Returns the type of the file. Possible values are fifo , char ,
/// dir , block , link , file , and unknown .
/// Returns null if an error occurs.
///
///
///
[ImplementsFunction("filetype")]
[return: CastToFalse]
public static string GetType(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return null;
FileModeFlags mode = (FileModeFlags)statCache.st_mode & FileModeFlags.FileTypeMask;
switch (mode)
{
case FileModeFlags.Directory:
return "dir";
case FileModeFlags.File:
return "file";
default:
PhpException.Throw(PhpError.Notice, LibResources.GetString("unknown_file_type"));
return "unknown";
}
}
///
/// Returns the time the file was last accessed, or false in case
/// of an error. The time is returned as a Unix timestamp.
///
///
/// The results of this call are cached.
/// See for more details.
///
/// The file to be probed.
/// The file access time or -1 in case of failure.
[ImplementsFunction("fileatime")]
[return: CastToFalse]
public static int GetAccessTime(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return unchecked((int)statCache.st_atime);
}
///
/// Returns the time the file was created, or false in case
/// of an error. The time is returned as a Unix timestamp.
///
///
/// The results of this call are cached.
/// See for more details.
///
/// On UNIX systems the filectime value represents
/// the last change of the I-node.
///
///
/// The file to be stat() ed.
/// The file size or -1 in case of failure.
[ImplementsFunction("filectime")]
[return: CastToFalse]
public static int GetCreationTime(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return unchecked((int)statCache.st_ctime);
}
///
/// Gets file group.
///
///
/// Always returns 0 for Windows filesystem files.
///
/// The file to be stat() ed.
/// The file size or false in case of failure.
[ImplementsFunction("filegroup")]
[return: CastToFalse]
public static int GetGroup(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return (int)statCache.st_gid;
}
///
/// Gets file inode.
///
///
/// Always returns 0 for Windows filesystem files.
///
/// The file to be stat() ed.
/// The file size or false in case of failure.
[ImplementsFunction("fileinode")]
[return: CastToFalse]
public static int GetINode(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return (int)statCache.st_ino;
}
///
/// Returns the time the file was last modified, or false in case
/// of an error. The time is returned as a Unix timestamp.
///
///
/// The results of this call are cached.
/// See for more details.
///
/// The file to be stat() ed.
/// The file modification time or false in case of failure.
[ImplementsFunction("filemtime")]
[return: CastToFalse]
public static int GetModificationTime(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return unchecked((int)statCache.st_mtime);
}
///
/// Gets file owner.
///
/// The file to be stat() ed.
/// The user ID of the owner of the file, or false in case of an error.
[ImplementsFunction("fileowner")]
[return: CastToFalse]
public static int GetOwner(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return (int)statCache.st_uid;
}
///
/// Gets file permissions.
///
/// The file to be stat() ed.
/// Returns the permissions on the file, or false in case of an error.
[ImplementsFunction("fileperms")]
[return: CastToFalse]
public static int GetPermissions(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return -1;
return (int)statCache.st_mode;
}
///
/// Gets the file size.
///
///
/// The results of this call are cached.
/// See for more details.
///
/// The file to be probed.
/// The file size or false in case of failure.
[ImplementsFunction("filesize")]
[return: CastToFalse]
public static int GetSize(string path)
{
StreamWrapper wrapper;
if (StatInternalCheck(ref path, false, out wrapper))
{
string url;
if (StatInternalTryCache(path, out url))
return statCache.st_size;
// we are not calling full stat(), it is slow
return FileStreamWrapper.HandleNewFileSystemInfo(-1, path, (p) => FileSystemUtils.FileSize(new FileInfo(p)));
}
return -1;
//bool ok = StatInternal(path, false);
//if (!ok) return -1;
//return statCache.st_size;
}
#endregion
#region Stat Flags (is_* functions)
///
/// Tells whether the path is a directory.
///
///
///
[ImplementsFunction("is_dir")]
public static bool IsDirectory(string path)
{
StreamWrapper wrapper;
if (!string.IsNullOrEmpty(path) && StatInternalCheck(ref path, false, out wrapper)) // do not throw warning if path is null or empty
{
string url;
if (StatInternalTryCache(path, out url))
return ((FileModeFlags)statCache.st_mode & FileModeFlags.Directory) != 0;
// we can't just call Directory.Exists since we have to throw warnings
// also we are not calling full stat(), it is slow
return FileStreamWrapper.HandleNewFileSystemInfo(false, path, (p) => new DirectoryInfo(p).Exists);
}
return false;
//bool ok = !string.IsNullOrEmpty(path) && StatInternal(path, false); // do not throw warning if path is null or empty
//if (!ok) return false;
//return ((FileModeFlags)statCache.st_mode & FileModeFlags.Directory) > 0;
}
///
/// Tells whether the path is executable.
///
///
///
[ImplementsFunction("is_executable")]
public static bool IsExecutable(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return false;
return ((FileModeFlags)statCache.st_mode & FileModeFlags.Execute) > 0;
}
///
/// Tells whether the path is a regular file and if it exists.
///
///
///
[ImplementsFunction("is_file")]
public static bool IsFile(string path)
{
StreamWrapper wrapper;
if (StatInternalCheck(ref path, false, out wrapper))
{
string url;
if (StatInternalTryCache(path, out url))
return ((FileModeFlags)statCache.st_mode & FileModeFlags.File) != 0;
// we can't just call File.Exists since we have to throw warnings
// also we are not calling full stat(), it is slow
return FileStreamWrapper.HandleNewFileSystemInfo(false, path, (p) => new FileInfo(p).Exists);
}
return false;
}
///
/// Tells whether the path is a symbolic link.
///
///
/// Returns always false .
///
///
/// Always false
[ImplementsFunction("is_link")]
public static bool IsLink(string path)
{
return false; // OK
}
///
/// Tells whether the path is readable.
///
///
///
[ImplementsFunction("is_readable")]
public static bool IsReadable(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return false;
return ((FileModeFlags)statCache.st_mode & FileModeFlags.Read) > 0;
}
///
/// Tells whether the path is writable.
///
/// The path argument may be a directory name allowing you to check if a directory is writeable.
/// Returns TRUE if the path exists and is writable.
[ImplementsFunction("is_writeable")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool IsWriteable(string path)
{
return IsWritable(path);
}
///
/// Tells whether the path is writable.
///
/// The path argument may be a directory name allowing you to check if a directory is writeable.
/// Returns TRUE if the path exists and is writable.
[ImplementsFunction("is_writable")]
public static bool IsWritable(string path)
{
bool ok = StatInternal(path, false);
if (!ok) return false;
return ((FileModeFlags)statCache.st_mode & FileModeFlags.Write) > 0;
}
#endregion
}
#region NS: Unix Functions
///
/// Unix-specific PHP functions. Not supported. Implementations are empty.
///
///
public static class UnixFile
{
#region Owners, Mode (chgrp, chmod, chown, umask)
///
/// Changes a group. Not supported.
///
/// Path to the file to change group.
/// A or
/// identifier of the target group.
/// Always false .
[ImplementsFunction("chgrp")]
public static bool ChangeFileGroup(string path, object group)
{
PhpException.FunctionNotSupported(PhpError.Warning);
return false;
}
#region chmod helpers
///
/// Add or revoke specified permission for a given role
///
/// an equivalent to UNIX's owner, group or public
/// ~ read, write, search
///
static FileSystemAccessRule GetAccessRule(
WellKnownSidType role,
FileSystemRights permission,
bool add)
{
//http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/dc841874-b71b-4e1c-9052-06eb4a87d08f
IdentityReference identity = new SecurityIdentifier(role, null).Translate(typeof(NTAccount)) as IdentityReference;
return new FileSystemAccessRule(
identity,
permission,
add ? AccessControlType.Allow : AccessControlType.Deny);
}
///
/// Attempt to populate a set of Windows access rules, calculated from a UNIX mode flags
///
///
///
static FileSystemAccessRule[] ResolveAccessRules(int mode)
{
//http://support.microsoft.com/kb/243330
WellKnownSidType[] roles = new WellKnownSidType[] {
WellKnownSidType.WorldSid,
WellKnownSidType.CreatorGroupSid,
WellKnownSidType.CreatorOwnerSid
};
//http://en.wikipedia.org/wiki/File_system_permissions#Octal_notation
FileSystemRights[] permissions = new FileSystemRights[] {
FileSystemRights.ReadAndExecute,
FileSystemRights.Write,
FileSystemRights.Read
};
var rules = new System.Collections.Generic.List();
//Walk all combinations of roles and permissions
for (int r = 0; r < roles.Length; r++) {
WellKnownSidType role = roles[r];
for (int p = 0; p < permissions.Length; p++) {
rules.Add(GetAccessRule(role, permissions[p], ((mode >> (r * 3)) & (1 << p)) != 0));
}
}
return rules.ToArray();
}
#endregion chmod helpers
///
/// Changes file permissions.
///
///
/// On Windows platform this function supports only the
/// _S_IREAD (0400) and _S_IWRITE (0200)
/// options (set read / write permissions for the file owner).
/// Note that the constants are octal numbers.
///
/// Path to the file to change group.
/// New file permissions (see remarks).
/// true on success, false on failure.
[ImplementsFunction("chmod")]
public static bool ChangeFileMode(string path, int mode)
{
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref path, out wrapper, CheckAccessMode.FileOrDirectory, CheckAccessOptions.Empty))
return false;
bool isDir = PhpFile.IsDirectory(path);
FileSystemInfo fInfo = isDir ? (FileSystemInfo)new DirectoryInfo(path) : new FileInfo(path);
if (!fInfo.Exists)
{
PhpException.Throw(PhpError.Warning, CoreResources.GetString("invalid_path", path));
return false;
}
//Directories has no equivalent of a readonly flag,
//instead, their content permission should be adjusted accordingly
//[http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.directorysecurity.aspx]
if (isDir)
{
//DirectoryInfo dInfo = (DirectoryInfo)fInfo;
//DirectorySecurity dSecurity = dInfo.GetAccessControl();
//foreach(FileSystemAccessRule rule in ResolveAccessRules(mode))
// dSecurity.AddAccessRule(rule);
//try
//{
// dInfo.SetAccessControl(dSecurity);
//}
//catch
{
return false;
}
}
else
{
// according to and from C libraries in Visual Studio 2008
// and PHP 5.3 source codes, which are using standard _chmod() function in C
// on Windows it only changes the ReadOnly flag of the file
//
// see for more details
/*
#define _S_IREAD 0x0100 // read permission, owner
#define _S_IWRITE 0x0080 // write permission, owner
#define _S_IEXEC 0x0040 // execute/search permission, owner
*/
((FileInfo)fInfo).IsReadOnly = ((mode & 0x0080) == 0);
}
return true;
}
///
/// Unix-specific function. Not supported.
///
/// Path to the file to change owner.
/// A or
/// identifier of the target group.
/// Always false .
[ImplementsFunction("chown")]
public static bool ChangeFileOwner(string path, object user)
{
PhpException.FunctionNotSupported(PhpError.Warning);
return false;
}
///
/// Unix-specific function. Not supported.
///
///
///
[ImplementsFunction("umask")]
public static int UMask(int mask)
{
return UMask();
}
///
/// Unix-specific function. Not supported.
///
///
[ImplementsFunction("umask")]
public static int UMask()
{
return 0;
}
#endregion
#region Links (link, symlink, readlink, linkinfo)
///
/// Unix-specific function. Not supported.
///
///
///
///
[ImplementsFunction("link")]
public static bool MakeHardLink(string target, string link)
{
// Creates a hard link.
PhpException.FunctionNotSupported(PhpError.Warning);
return false;
}
///
/// Unix-specific function. Not supported.
///
///
///
///
[ImplementsFunction("symlink")]
public static bool MakeSymbolicLink(string target, string link)
{
// Creates a symbolic link.
PhpException.FunctionNotSupported(PhpError.Warning);
return false;
}
///
/// Unix-specific function. Not supported.
///
///
///
[ImplementsFunction("readlink", FunctionImplOptions.NotSupported)]
public static string ReadLink(string path)
{
// Returns the target of a symbolic link.
PhpException.FunctionNotSupported(PhpError.Warning);
return null;
}
///
/// Unix-specific function. Not supported.
///
///
///
[ImplementsFunction("linkinfo")]
public static int GetLinkInfo(string path)
{
// Gets information about a link.
PhpException.FunctionNotSupported(PhpError.Warning);
return 0;
}
#endregion
}
#endregion
}
================================================
FILE: Source/ClassLibrary/FileSystem.Directory.cs
================================================
/*
Copyright (c) 2004-2006 Jan Benda and Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using PHP.Core;
using PHP.Core.Reflection;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
#region Directory user-class
///
/// User-like class encapsulating enumeration of a Directory.
/// Uses the PhpDiretory implementation upon PhpWrapper streams.
///
#if !SILVERLIGHT
[Serializable]
#endif
[ImplementsType]
public class Directory : PhpObject
{
#region Fields
///
/// Reference to the directory listing resource.
///
public PhpReference handle = new PhpSmartReference();
///
/// The opened path (accessible from the PHP script).
///
public PhpReference path = new PhpSmartReference();
#endregion
#region Construction
///
/// Start listing of a directory (intended to be used from C#).
///
/// The path to the directory.
public Directory(string directory)
: this(ScriptContext.CurrentContext, true)
{
this.path = new PhpReference(directory);
this.handle = new PhpReference(PhpDirectory.Open(directory));
}
///
/// For internal purposes only.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Directory(ScriptContext context, bool newInstance)
: base(context, newInstance)
{ }
///
/// For internal purposes only.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public Directory(ScriptContext context, DTypeDesc caller)
: base(context, caller)
{ }
#if !SILVERLIGHT
/// Deserializing constructor.
protected Directory(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
#endif
#endregion
#region read
///
/// Read next directory entry.
///
/// Filename of a contained file (including . and ..).
[ImplementsMethod]
[return:CastToFalse]
public object read(ScriptContext context, [Optional]object handle)
{
PhpResource res = (handle == Arg.Default ? this.handle.Value : handle) as PhpResource;
if (res == null)
{
PhpException.InvalidImplicitCast("handle", PhpResource.PhpTypeName, "read");
return null;
}
return PhpDirectory.Read(res);
}
#endregion
#region rewind
///
/// Restart the directory listing.
///
[ImplementsMethod]
public object rewind(ScriptContext context, [Optional]object handle)
{
PhpResource res = (handle == Arg.Default ? this.handle.Value : handle) as PhpResource;
if (res == null)
{
PhpException.InvalidImplicitCast("handle", PhpResource.PhpTypeName, "rewind");
return null;
}
PhpDirectory.Rewind(res);
return null;
}
#endregion
#region close
///
/// Finish the directory listing.
///
[ImplementsMethod]
public object close(ScriptContext context, [Optional]object handle)
{
PhpResource res = (handle == Arg.Default ? this.handle.Value : handle) as PhpResource;
if (res == null)
{
PhpException.InvalidImplicitCast("handle", PhpResource.PhpTypeName, "close");
return null;
}
PhpDirectory.Close(res);
return null;
}
#endregion
#region Implementation Details
///
/// Populates the provided with this class's methods and properties.
///
/// The type desc to populate.
private static void __PopulateTypeDesc(PhpTypeDesc typeDesc)
{
typeDesc.AddMethod("read", PhpMemberAttributes.Public, read);
typeDesc.AddMethod("rewind", PhpMemberAttributes.Public, rewind);
typeDesc.AddMethod("close", PhpMemberAttributes.Public, close);
typeDesc.AddProperty("handle", PhpMemberAttributes.Public,
(instance) => ((Directory)instance).handle,
(instance, value) => ((Directory)instance).handle = (PhpReference)value);
typeDesc.AddProperty("path", PhpMemberAttributes.Public,
(instance) => ((Directory)instance).path,
(instance, value) => ((Directory)instance).path = (PhpReference)value);
}
/// Arg-less overload.
[EditorBrowsable(EditorBrowsableState.Never)]
public static object read(object instance, PhpStack stack)
{
switch (stack.ArgCount)
{
case 0:
{
stack.RemoveFrame();
return ((Directory)instance).read(stack.Context, Arg.Default) ?? false;
}
case 1:
{
stack.CalleeName = "read";
object arg = stack.PeekValue(1);
stack.RemoveFrame();
return ((Directory)instance).read(stack.Context, arg) ?? false;
}
default:
{
stack.RemoveFrame();
PhpException.InvalidArgumentCount(null, "read");
return null;
}
}
}
/// Arg-less overload.
[EditorBrowsable(EditorBrowsableState.Never)]
public static object rewind(object instance, PhpStack stack)
{
switch (stack.ArgCount)
{
case 0:
{
stack.RemoveFrame();
((Directory)instance).rewind(stack.Context, Arg.Default);
break;
}
case 1:
{
stack.CalleeName = "rewind";
object arg = stack.PeekValue(1);
stack.RemoveFrame();
((Directory)instance).rewind(stack.Context, arg);
break;
}
default:
{
stack.RemoveFrame();
PhpException.InvalidArgumentCount(null, "rewind");
break;
}
}
return null;
}
/// Arg-less overload.
[EditorBrowsable(EditorBrowsableState.Never)]
public static object close(object instance, PhpStack stack)
{
switch (stack.ArgCount)
{
case 0:
{
stack.RemoveFrame();
((Directory)instance).close(stack.Context, Arg.Default);
break;
}
case 1:
{
stack.CalleeName = "close";
object arg = stack.PeekValue(1);
stack.RemoveFrame();
((Directory)instance).close(stack.Context, arg);
break;
}
default:
{
stack.RemoveFrame();
PhpException.InvalidArgumentCount(null, "close");
break;
}
}
return null;
}
#endregion
}
#endregion
#region DirectoryListing
///
/// Enumeration class used for PhpDirectory listings - serves as a PhpResource.
/// Uses the PhpWrapper stream wrappers only to generate the list of contained files.
/// No actual resources to be released explicitly.
///
internal sealed class DirectoryListing : PhpResource
{
public DirectoryListing(string[] listing)
: base(DirectoryListingName)
{
this.Listing = listing;
if (listing != null)
{
this.Enumerator = listing.GetEnumerator();
this.Enumerator.Reset();
}
else
{
this.Close();
// Invalid resource
}
}
protected override void FreeManaged()
{
if (object.ReferenceEquals(this, PhpDirectory.lastDirHandle))
PhpDirectory.lastDirHandle = null;
}
public readonly string[] Listing;
public readonly System.Collections.IEnumerator Enumerator;
private const string DirectoryListingName = "stream";
//private static int DirectoryListingType = PhpResource.RegisterType(DirectoryListingName);
// Note: PHP uses the stream mechanism listings (opendir etc.)
// this is the same but a) faster, b) more memory expensive for large directories
// (and unfinished listings in script)
}
#endregion
///
/// Gives access to the directory manipulation and itereation.
///
///
public static class PhpDirectory
{
#region Browsing (getcwd, chdir, NS: chroot)
/// Gets the virtual working directory of the current script.
///
/// Absolute path to the current directory.
[ImplementsFunction("getcwd")]
public static string GetWorking()
{
string result = ScriptContext.CurrentContext.WorkingDirectory;
return (result != null) ? result : "";
}
/// Changes the virtual working directory for the current script.
/// Absolute or relative path to the new working directory.
/// Returns true on success or false on failure.
/// If the specified directory does not exist.
[ImplementsFunction("chdir")]
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;
}
///
/// Changes the root directory of the current process to .
/// Not supported.
///
///
/// This function is only available if your system supports it
/// and you're using the CLI, CGI or Embed SAPI.
/// Note: This function is not implemented on Windows platforms.
///
/// The new value of the root directory.
/// Returns TRUE on success or FALSE on failure.
[ImplementsFunction("chroot", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool SetRoot(string directory)
{
PhpException.FunctionNotSupported();
return false;
}
#endregion
#region Iterating (dir, opendir, readdir, rewinddir, closedir, scandir)
/// Returns an object encapsulating the directory listing mechanism on a given
/// .
/// A pseudo-object oriented mechanism for reading a directory. The given directory is opened.
/// Two properties are available once the directory has been opened. The handle property
/// can be used with other directory functions such as readdir() , rewinddir() and closedir() .
/// The path property is set to path the directory that was opened.
/// Three methods are available: ,
/// and .
/// The path to open for listing.
/// An instance of .
[ImplementsFunction("dir")]
public static Directory GetIterator(string directory)
{
return new Directory(directory);
}
///
/// Last handle opened by opendir .
///
[ThreadStatic]
internal static PhpResource lastDirHandle;
/// Returns a directory handle to be used in subsequent
/// readdir() , rewinddir() and closedir() calls.
///
///
/// If path is not a valid directory or the directory can not
/// be opened due to permission restrictions or filesystem errors,
/// opendir() returns false and generates a PHP error of level E_WARNING .
///
///
/// As of PHP 4.3.0 path can also be any URL which supports directory listing,
/// however only the file:// url wrapper supports this in PHP 4.3.
/// As of PHP 5.0.0, support for the ftp:// url wrapper is included as well.
///
///
/// The path of the directory to be listed.
/// A resource containing the listing.
/// In case the specified stream wrapper can not be found
/// or the desired directory can not be opened.
[ImplementsFunction("opendir")]
[return: CastToFalse]
public static PhpResource Open(string directory)
{
lastDirHandle = null;
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref directory, out wrapper, CheckAccessMode.Directory, CheckAccessOptions.Empty))
return null;
string[] listing = wrapper.Listing(directory, 0, null);
return (listing != null) ? (lastDirHandle = new DirectoryListing(listing)) : null;
}
///
/// Reads an entry from a directory handle. Uses last handle opened by opendir .
///
[ImplementsFunction("readdir")]
[return: CastToFalse]
public static string Read()
{
return Read(PhpDirectory.lastDirHandle);
}
///
/// Reads an entry from a directory handle.
///
/// A returned by .
///
/// Returns the path of the next file from the directory.
/// The filenames (including . and ..) are returned in the order
/// in which they are stored by the filesystem.
///
[ImplementsFunction("readdir")]
[return: CastToFalse]
public static string Read(PhpResource dirHandle)
{
IEnumerator enumerator = ValidListing(dirHandle);
if (enumerator != null && enumerator.MoveNext())
return enumerator.Current.ToString();
else
return null;
}
///
/// Rewinds a directory handle. Uses last handle opened by opendir .
///
[ImplementsFunction("rewinddir")]
public static void Rewind()
{
Rewind(PhpDirectory.lastDirHandle);
}
///
/// Rewinds a directory handle.
/// Function has no return value.
///
/// A returned by .
///
/// Resets the directory stream indicated by to the
/// beginning of the directory.
///
[ImplementsFunction("rewinddir")]
public static void Rewind(PhpResource dirHandle)
{
IEnumerator enumerator = ValidListing(dirHandle);
if (enumerator == null) return;
enumerator.Reset();
}
///
/// Closes a directory handle. Uses last handle opened by opendir .
///
[ImplementsFunction("closedir")]
public static void Close()
{
Close(PhpDirectory.lastDirHandle);
}
///
/// Closes a directory handle.
/// Function has no return value.
///
/// A returned by .
///
/// Closes the directory stream indicated by .
/// The stream must have previously been opened by by .
///
[ImplementsFunction("closedir")]
public static void Close(PhpResource dirHandle)
{
// Note: PHP allows other all stream resources to be closed with closedir().
IEnumerator enumerator = ValidListing(dirHandle);
if (enumerator == null) return;
dirHandle.Close(); // releases the DirectoryListing and sets to invalid.
}
/// Lists files and directories inside the specified .
///
/// Returns an array of files and directories from the .
/// If is not a directory, then boolean false is returned,
/// and an error of level E_WARNING is generated.
///
/// The directory to be listed.
/// A of filenames or false in case of failure.
[ImplementsFunction("scandir")]
[return: CastToFalse]
public static PhpArray Scan(string directory)
{
return Scan(directory, 0);
}
/// Lists files and directories inside the specified path.
///
/// Returns an array of files and directories from the .
/// If is not a directory, then boolean false is returned,
/// and an error of level E_WARNING is generated.
///
/// The directory to be listed.
///
/// By default, the listing is sorted in ascending alphabetical order.
/// If the optional sorting_order is used (set to 1 ),
/// then sort order is alphabetical in descending order.
/// A of filenames or false in case of failure.
/// In case the specified stream wrapper can not be found
/// or the desired directory can not be opened.
[ImplementsFunction("scandir")]
[return: CastToFalse]
public static PhpArray Scan(string directory, int sorting_order)
{
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref directory, out wrapper, CheckAccessMode.Directory, CheckAccessOptions.Empty))
return null;
string[] listing = wrapper.Listing(directory, 0, null);
if (listing != null)
{
PhpArray ret = new PhpArray(listing); // create the array from the system one
if (sorting_order == 1)
{
PhpArrays.ReverseSort(ret, ComparisonMethod.String);
}
else
{
PhpArrays.Sort(ret, ComparisonMethod.String);
}
return ret;
}
return null; // false
}
///
/// Casts the given resource handle to the enumerator.
/// Throw an exception when a wrong argument is supplied.
///
/// The handle passed to a PHP function.
/// The enumerator over the files in the DirectoryListing.
/// When the supplied argument is not a valid resource.
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;
}
#endregion
#region Manipulating (mkdir, rmdir)
///
/// Makes a new directory.
///
/// The directory to create.
/// true if successful, false otherwise.
[ImplementsFunction("mkdir")]
public static bool MakeDirectory(string pathname)
{
return MakeDirectory(pathname, (int)FileModeFlags.ReadWriteExecute, false, StreamContext.Default);
}
///
/// Makes a directory or a branch of directories using the specified wrapper.
///
/// The path to create.
/// A combination of .
/// true if successful, false otherwise.
[ImplementsFunction("mkdir")]
public static bool MakeDirectory(string pathname, int mode)
{
return MakeDirectory(pathname, mode, false, StreamContext.Default);
}
///
///
///
///
///
///
///
[ImplementsFunction("mkdir")]
public static bool MakeDirectory(string pathname, int mode, bool recursive)
{
return MakeDirectory(pathname, mode, recursive, StreamContext.Default);
}
///
///
///
///
///
///
///
///
[ImplementsFunction("mkdir")]
public static bool MakeDirectory(string pathname, int mode, bool recursive, PhpResource context)
{
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref pathname, out wrapper, CheckAccessMode.Directory, CheckAccessOptions.Empty))
return false;
return wrapper.MakeDirectory(pathname, mode, recursive ?
StreamMakeDirectoryOptions.Recursive : StreamMakeDirectoryOptions.Empty, StreamContext.Default);
}
///
/// Removes a directory.
///
///
/// true if successful, false otherwise.
[ImplementsFunction("rmdir")]
public static bool RemoveDirectory(string dirname)
{
return RemoveDirectory(dirname, StreamContext.Default);
}
///
/// Removes a directory.
///
///
///
/// true if successful, false otherwise.
[ImplementsFunction("rmdir")]
public static bool RemoveDirectory(string dirname, StreamContext context)
{
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref dirname, out wrapper, CheckAccessMode.Directory, CheckAccessOptions.Empty))
return false;
return wrapper.RemoveDirectory(dirname, StreamRemoveDirectoryOptions.Empty, StreamContext.Default);
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/FileSystem.Glob.cs
================================================
/*
Copyright (c) 2012 DEVSENSE
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PHP.Core;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace PHP.Library
{
//TODO: try to output slashes in a not uniform and ugly way as PHP does
public static class PhpGlob
{
#region Enums: GlobOptions, FnMatchOptions
///
/// Flags used in call to glob() .
///
[Flags]
public enum GlobOptions
{
///
/// No flags.
///
None = 0,
///
/// Append system directory separator (slash) to matching directories.
///
[ImplementsConstant("GLOB_MARK")]
Mark = 0x0008,
///
/// Return pattern itself if nothing matches.
///
[ImplementsConstant("GLOB_NOCHECK")]
NoCheck = 0x0010,
///
/// Don't sort.
///
[ImplementsConstant("GLOB_NOSORT")]
NoSort = 0x0020,//TODO: support this somehow
///
/// Expand braces ala csh.
///
[ImplementsConstant("GLOB_BRACE")]
Brace = 0x0080,
///
/// Disable backslash escaping.
///
[ImplementsConstant("GLOB_NOESCAPE")]
NoEscape = 0x1000,
///
/// List directories only.
///
[ImplementsConstant("GLOB_ONLYDIR")]
OnlyDir = 0x40000000,
///
/// List directories only.
///
[ImplementsConstant("GLOB_ERR")]
StopOnError = 0x4
}
///
/// Flags used in call to fnmatch() .
///
public enum FnMatchOptions
{
///
/// No flags.
///
None = 0,
///
/// Caseless match. Part of the GNU extension.
///
[ImplementsConstant("FNM_CASEFOLD")]
CaseFold = 0x0010,
///
/// Leading period in string must be exactly matched by period in the given pattern.
///
[ImplementsConstant("FNM_PERIOD")]
Period = 0x0004,
///
/// Disable backslash escaping.
///
[ImplementsConstant("FNM_NOESCAPE")]
NoEscape = 0x0001,
///
/// Slash in string only matches slash in the given pattern.
///
[ImplementsConstant("FNM_PATHNAME")]
PathName = 0x0002
}
#endregion
private class CharClass
{
private readonly StringBuilder/*!*/ _chars = new StringBuilder();
internal void Add(char c)
{
if (c == ']' || c == '\\')
{
_chars.Append('\\');
}
_chars.Append(c);
}
internal string MakeString()
{
if (_chars.Length == 0)
{
return null;
}
if (_chars.Length == 1 && _chars[0] == '^')
{
_chars.Insert(0, "\\");
}
_chars.Insert(0, "[");
_chars.Append(']');
return _chars.ToString();
}
}
///
/// Replaces all slashes with / .
///
/// Path pattern.
/// Canonized pattern.
private static string CanonizePattern(string/*!*/pattern)
{
Debug.Assert(pattern != null);
return pattern.Replace('\\', '/');
}
private static void AppendExplicitRegexChar(StringBuilder/*!*/ builder, char c)
{
builder.Append('[');
if (c == '^' || c == '\\')
{
builder.Append('\\');
}
builder.Append(c);
builder.Append(']');
}
internal static string/*!*/ PatternToRegex(string/*!*/ pattern, bool pathName, bool noEscape)
{
StringBuilder result = new StringBuilder(pattern.Length);
result.Append("\\G");
bool inEscape = false;
CharClass charClass = null;
foreach (char c in pattern)
{
if (inEscape)
{
if (charClass != null)
{
charClass.Add(c);
}
else
{
AppendExplicitRegexChar(result, c);
}
inEscape = false;
continue;
}
else if (c == '\\' && !noEscape)
{
inEscape = true;
continue;
}
if (charClass != null)
{
if (c == ']')
{
string set = charClass.MakeString();
if (set == null)
{
// PHP regex "[]" matches nothing
// CLR regex "[]" throws exception
return String.Empty;
}
result.Append(set);
charClass = null;
}
else
{
charClass.Add(c);
}
continue;
}
switch (c)
{
case '*':
result.Append(pathName ? "[^/]*" : ".*");
break;
case '?':
result.Append('.');
break;
case '[':
charClass = new CharClass();
break;
default:
AppendExplicitRegexChar(result, c);
break;
}
}
return (charClass == null) ? result.ToString() : String.Empty;
}
private sealed class GlobMatcher
{
private readonly string/*!*/ _pattern;
private readonly GlobOptions _flags;
private readonly List/*!*/ _result;
private readonly bool _dirOnly;
private bool _stripTwo;
private bool _relative;
private FnMatchOptions _fnMatchFlags;
private bool NoEscapes
{
get { return ((_flags & GlobOptions.NoEscape) != 0); }
}
private bool StopOnError
{
get { return ((_flags & GlobOptions.StopOnError) != 0); }
}
private bool Mark
{
get { return ((_flags & GlobOptions.Mark) != 0); }
}
public GlobMatcher(string/*!*/ pattern, GlobOptions flags)
{
_pattern = CanonizePattern(pattern);
_flags = flags;
_result = new List();
_dirOnly = _pattern.LastCharacter() == '/' || (flags & GlobOptions.OnlyDir) != 0;
_fnMatchFlags = NoEscapes ? FnMatchOptions.NoEscape : FnMatchOptions.None;
}
private static string/*!*/ Unescape(string/*!*/ path, int start)
{
StringBuilder unescaped = new StringBuilder();
bool inEscape = false;
for (int i = start; i < path.Length; i++)
{
char c = path[i];
if (inEscape)
{
inEscape = false;
}
else if (c == '\\')
{
inEscape = true;
continue;
}
unescaped.Append(c);
}
if (inEscape)
{
unescaped.Append('\\');
}
return unescaped.ToString();
}
private void TestPath(string path, int patternEnd, bool isLastPathSegment)
{
if (!isLastPathSegment)
{
DoGlob(path, patternEnd);
return;
}
if (!NoEscapes)
{
path = Unescape(path, _stripTwo ? 2 : 0);
}
else if (_stripTwo)
{
path = path.Substring(2);
}
string resultPath = path;
if (_relative)//we have to remove CWD before adding to results list
{
resultPath = path.Substring(ScriptContext.CurrentContext.WorkingDirectory.Length + 1);
}
if (System.IO.Directory.Exists(path))
{
if (Mark)
_result.Add(resultPath + FullPath.DirectorySeparatorString);
else
_result.Add(resultPath);
}
else if (!_dirOnly && File.Exists(path))
{
_result.Add(resultPath);
}
}
internal IList/*!*/ DoGlob()
{
if (_pattern.Length == 0)
{
return ArrayUtils.EmptyStrings;
}
int pos = 0;
string baseDirectory = ".";
if (_pattern[0] == '/' || (_pattern.Length >= 2 && _pattern[1] == ':'))//is pattern rooted?
{
bool containsWildcard;
pos = FindNextSeparator(0, false, out containsWildcard);
if (pos == _pattern.Length)
{
TestPath(_pattern, pos, true);
return _result;
}
if (pos > 0 || _pattern[0] == '/')
{
baseDirectory = _pattern.Substring(0, pos);
}
}
else
{
_relative = true;
baseDirectory = CanonizePattern(ScriptContext.CurrentContext.WorkingDirectory);
}
_stripTwo = (baseDirectory == ".");
try
{
DoGlob(baseDirectory, pos);
}
catch (ArgumentNullException)
{
throw;
}
catch (Exception)
{
}
return _result;
}
private void DoGlob(string/*!*/ baseDirectory, int position)
{
if (!System.IO.Directory.Exists(baseDirectory))
{
return;
}
bool containsWildcard;
int patternEnd = FindNextSeparator(position, true, out containsWildcard);
bool isLastPathSegment = (patternEnd == _pattern.Length);
string dirSegment = _pattern.Substring(position, patternEnd - position);
if (!isLastPathSegment)
{
patternEnd++;
}
if (!containsWildcard)
{
string path = baseDirectory + "/" + dirSegment;
TestPath(path, patternEnd, isLastPathSegment);
return;
}
try
{
foreach (string file in FileSystemUtils.GetFileSystemEntries(baseDirectory, "*"))
{
string objectName = Path.GetFileName(file);
if (FnMatch(dirSegment, objectName, _fnMatchFlags))
{
TestPath(CanonizePattern(file), patternEnd, isLastPathSegment);
}
}
}
catch (ArgumentNullException)
{
throw;
}
catch(Exception)
{
if (StopOnError)
throw;
}
if (isLastPathSegment && dirSegment[0] == '.')
{
if (FnMatch(dirSegment, ".", _fnMatchFlags))
{
string directory = baseDirectory + "/.";
if (_dirOnly)
{
directory += '/';
}
TestPath(directory, patternEnd, true);
}
if (FnMatch(dirSegment, "..", _fnMatchFlags))
{
string directory = baseDirectory + "/..";
if (_dirOnly)
{
directory += '/';
}
TestPath(directory, patternEnd, true);
}
}
}
private int FindNextSeparator(int position, bool allowWildcard, out bool containsWildcard)
{
int lastSlash = -1;
bool inEscape = false;
containsWildcard = false;
for (int i = position; i < _pattern.Length; i++)
{
if (inEscape)
{
inEscape = false;
continue;
}
char c = _pattern[i];
if (c == '\\')
{
inEscape = true;
continue;
}
else if (c == '*' || c == '?' || c == '[')
{
if (!allowWildcard)
{
return lastSlash + 1;
}
else if (lastSlash >= 0)
{
return lastSlash;
}
containsWildcard = true;
}
else if (c == '/' || c == ':')
{
if (containsWildcard)
{
return i;
}
lastSlash = i;
}
}
return _pattern.Length;
}
}
private class GlobUngrouper
{
internal abstract class GlobNode
{
internal readonly GlobNode/*!*/ _parent;
protected GlobNode(GlobNode parentNode)
{
_parent = parentNode ?? this;
}
abstract internal GlobNode/*!*/ AddChar(char c);
abstract internal GlobNode/*!*/ StartLevel();
abstract internal GlobNode/*!*/ AddGroup();
abstract internal GlobNode/*!*/ FinishLevel();
abstract internal List/*!*/ Flatten();
}
internal class TextNode : GlobNode
{
private readonly StringBuilder/*!*/ _builder;
internal TextNode(GlobNode/*!*/ parentNode)
: base(parentNode)
{
_builder = new StringBuilder();
}
internal override GlobNode/*!*/ AddChar(char c)
{
if (c != 0)
{
_builder.Append(c);
}
return this;
}
internal override GlobNode/*!*/ StartLevel()
{
return _parent.StartLevel();
}
internal override GlobNode/*!*/ AddGroup()
{
return _parent.AddGroup();
}
internal override GlobNode/*!*/ FinishLevel()
{
return _parent.FinishLevel();
}
internal override List/*!*/ Flatten()
{
List result = new List(1);
result.Add(_builder);
return result;
}
}
internal class ChoiceNode : GlobNode
{
private readonly List/*!*/ _nodes;
internal ChoiceNode(GlobNode/*!*/ parentNode)
: base(parentNode)
{
_nodes = new List();
}
internal override GlobNode/*!*/ AddChar(char c)
{
SequenceNode node = new SequenceNode(this);
_nodes.Add(node);
return node.AddChar(c);
}
internal override GlobNode/*!*/ StartLevel()
{
SequenceNode node = new SequenceNode(this);
_nodes.Add(node);
return node.StartLevel();
}
internal override GlobNode/*!*/ AddGroup()
{
AddChar('\0');
return this;
}
internal override GlobNode/*!*/ FinishLevel()
{
AddChar('\0');
return _parent;
}
internal override List/*!*/ Flatten()
{
List result = new List();
foreach (GlobNode node in _nodes)
{
foreach (StringBuilder builder in node.Flatten())
{
result.Add(builder);
}
}
return result;
}
}
internal class SequenceNode : GlobNode
{
private readonly List/*!*/ _nodes;
internal SequenceNode(GlobNode parentNode)
: base(parentNode)
{
_nodes = new List();
}
internal override GlobNode/*!*/ AddChar(char c)
{
TextNode node = new TextNode(this);
_nodes.Add(node);
return node.AddChar(c);
}
internal override GlobNode/*!*/ StartLevel()
{
ChoiceNode node = new ChoiceNode(this);
_nodes.Add(node);
return node;
}
internal override GlobNode/*!*/ AddGroup()
{
return _parent;
}
internal override GlobNode/*!*/ FinishLevel()
{
return _parent._parent;
}
internal override List/*!*/ Flatten()
{
List result = new List();
result.Add(new StringBuilder());
foreach (GlobNode node in _nodes)
{
List tmp = new List();
foreach (StringBuilder builder in node.Flatten())
{
foreach (StringBuilder sb in result)
{
StringBuilder newsb = new StringBuilder(sb.ToString());
newsb.Append(builder.ToString());
tmp.Add(newsb);
}
}
result = tmp;
}
return result;
}
}
private readonly SequenceNode/*!*/ _rootNode;
private GlobNode/*!*/ _currentNode;
private int _level;
internal GlobUngrouper(int patternLength)
{
_rootNode = new SequenceNode(null);
_currentNode = _rootNode;
_level = 0;
}
internal void AddChar(char c)
{
_currentNode = _currentNode.AddChar(c);
}
internal void StartLevel()
{
_currentNode = _currentNode.StartLevel();
_level++;
}
internal void AddGroup()
{
_currentNode = _currentNode.AddGroup();
}
internal void FinishLevel()
{
_currentNode = _currentNode.FinishLevel();
_level--;
}
internal int Level
{
get { return _level; }
}
internal string[]/*!*/ Flatten()
{
if (_level != 0)
{
return ArrayUtils.EmptyStrings;
}
List list = _rootNode.Flatten();
string[] result = new string[list.Count];
for (int i = 0; i < list.Count; i++)
{
result[i] = list[i].ToString();
}
return result;
}
}
private static string[] UngroupGlobs(string/*!*/ pattern, bool noEscape, bool brace)
{
GlobUngrouper ungrouper = new GlobUngrouper(pattern.Length);
bool inEscape = false;
foreach (char c in pattern)
{
if (inEscape)
{
if (c != ',' && c != '{' && c != '}')
{
ungrouper.AddChar('\\');
}
ungrouper.AddChar(c);
inEscape = false;
continue;
}
else if (c == '\\' && !noEscape)
{
inEscape = true;
continue;
}
switch (c)
{
case '{':
if (!brace)
return ArrayUtils.EmptyStrings;
ungrouper.StartLevel();
break;
case ',':
if (ungrouper.Level < 1)
{
ungrouper.AddChar(c);
}
else
{
ungrouper.AddGroup();
}
break;
case '}':
if (ungrouper.Level < 1)
{
// Unbalanced closing bracket matches nothing
return ArrayUtils.EmptyStrings;
}
ungrouper.FinishLevel();
break;
default:
ungrouper.AddChar(c);
break;
}
}
return ungrouper.Flatten();
}
internal static IEnumerable/*!*/ GetMatches(string/*!*/ pattern, GlobOptions flags)
{
if (pattern.Length == 0) {
yield break;
}
bool noEscape = ((flags & GlobOptions.NoEscape) != 0);
bool brace = ((flags & GlobOptions.Brace) != 0);
string[] groups = UngroupGlobs(pattern, noEscape, brace);
if (groups.Length == 0) {
yield break;
}
foreach (string group in groups) {
GlobMatcher matcher = new GlobMatcher(group, flags);
foreach (string filename in matcher.DoGlob()) {
yield return filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
}
}
}
#region fnmatch, glob
///
/// Matches the given path against a pattern.
///
/// A containing a wildcard.
/// The to be matched.
/// Additional flags.
/// true if the matches with the given
/// wildcard .
[ImplementsFunction("fnmatch")]
public static bool FnMatch(string/*!*/ pattern, string/*!*/ path, FnMatchOptions flags)
{
if (pattern.Length == 0)
{
return path.Length == 0;
}
bool pathName = ((flags & FnMatchOptions.PathName) != 0);
bool noEscape = ((flags & FnMatchOptions.NoEscape) != 0);
string regexPattern = PatternToRegex(pattern, pathName, noEscape);
if (regexPattern.Length == 0)
{
return false;
}
if (((flags & FnMatchOptions.Period) == 0) && path.Length > 0 && path[0] == '.')
{
// Starting dot requires an explicit dot in the pattern
if (regexPattern.Length < 4 || regexPattern[2] != '[' || regexPattern[3] != '.')
{
return false;
}
}
RegexOptions options = RegexOptions.None;
if ((flags & FnMatchOptions.CaseFold) != 0)
{
options |= RegexOptions.IgnoreCase;
}
Match match = Regex.Match(path, regexPattern, options);
return match != null && match.Success && (match.Length == path.Length);
}
///
/// Matches the given path against a pattern.
///
/// A containing a wildcard.
/// The to be matched.
/// true if the matches with the given
/// wildcard .
[ImplementsFunction("fnmatch")]
public static bool Match(string pattern, string path)
{
return FnMatch(pattern, path, 0);
}
///
/// Find pathnames matching a pattern.
///
[ImplementsFunction("glob")]
public static PhpArray Glob(string pattern)
{
return Glob(pattern, GlobOptions.None);
}
///
/// Find pathnames matching a pattern.
///
[ImplementsFunction("glob")]
public static PhpArray Glob(string pattern, GlobOptions flags)
{
if (pattern == null)
return new PhpArray(0, 0);
PhpArray result = new PhpArray();
foreach (var fileName in GetMatches(pattern, flags))
{
result.Add(fileName);
}
if (result.Count == 0 && (flags & GlobOptions.NoCheck) != 0)
result.Add(pattern);
return result;
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/FileSystem.Path.cs
================================================
/*
Copyright (c) 2004-2006 Jan Benda and Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO:
- Fixed tempnam() 2nd parameter to be checked against path components. (PHP 5.1.3)
*/
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Threading;
using System.ComponentModel;
using PHP.Core;
using System.Collections.Generic;
using System.Text.RegularExpressions;
#if SILVERLIGHT
using DirectoryEx = PHP.CoreCLR.DirectoryEx;
#else
using DirectoryEx = System.IO.Directory;
using System.Diagnostics;
#endif
namespace PHP.Library
{
///
/// Provides path strings manipulation.
///
///
public static class PhpPath
{
#region Scheme, Url, Absolute Path
///
/// Wrapper-safe method of getting the schema portion from an URL.
///
/// A containing an URL or a local filesystem path.
///
/// The schema portion of the given or "file"
/// for a local filesystem path.
///
/// Invalid path.
internal static string GetScheme(string/*!*/ path)
{
int colon_index = path.IndexOf(':');
// When there is not scheme present (or it's a local path) return "file".
if (colon_index == -1 || Path.IsPathRooted(path))
return "file";
// Otherwise assume that it's the string before first ':'.
return path.Substring(0, colon_index);
}
///
/// Concatenates a scheme with the given absolute path if necessary.
///
/// Absolute path.
/// The given url or absolute path preceded by a file:// .
/// Invalid path.
internal static string GetUrl(string/*!*/ absolutePath)
{
// Assert that the path is absolute
Debug.Assert(
!string.IsNullOrEmpty(absolutePath) &&
(absolutePath.IndexOf(':') > 0 || // there is a protocol (http://) or path is rooted (c:\)
(Path.VolumeSeparatorChar != ':' && // or on linux, if there is no protocol, file path is rooted
(absolutePath[0] == Path.DirectorySeparatorChar || absolutePath[0] == Path.AltDirectorySeparatorChar)))
);
if (Path.IsPathRooted(absolutePath))
return String.Concat("file://", absolutePath);
// Otherwise assume that it's the string before first ':'.
return absolutePath;
}
///
/// Returns the given filesystem url without the scheme.
///
/// A path or url of a local filesystem file.
/// The filesystem path or null if the is not a local file.
/// Invalid path.
internal static string GetFilename(string/*!*/ path)
{
if (path.IndexOf(':') == -1 || Path.IsPathRooted(path)) return path;
if (path.IndexOf("file://") == 0) return path.Substring("file://".Length);
return null;
}
///
/// Check if the given path is a path to a local file.
///
/// The path to test.
/// true if it's not a fully qualified name of a remote resource.
/// Invalid path.
internal static bool IsLocalFile(string/*!*/ url)
{
return GetScheme(url) == "file";
}
///
/// Check if the given path is a remote url.
///
/// The path to test.
/// true if it's a fully qualified name of a remote resource.
/// Invalid path.
internal static bool IsRemoteFile(string/*!*/ url)
{
return GetScheme(url) != "file";
}
///
/// Merges the path with the current working directory
/// to get a canonicalized absolute pathname representing the same path
/// (local files only). If the provided
/// is absolute (rooted local path or an URL) it is returned unchanged.
///
/// An absolute or relative path to a directory or an URL.
/// Canonicalized absolute path in case of a local directory or the original
/// in case of an URL.
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;
}
}
#endregion
#region basename, dirname, pathinfo
///
/// Returns path component of path.
///
/// A containing a path to a file.
/// The path conponent of the given .
/// Invalid path.
[ImplementsFunction("basename")]
[PureFunction]
public static string GetBase(string path)
{
return GetBase(path, null);
}
///
/// Returns path component of path.
///
///
/// Given a containing a path to a file, this function will return the base name of the file.
/// If the path ends in this will also be cut off.
/// On Windows, both slash (/) and backslash (\) are used as path separator character.
/// In other environments, it is the forward slash (/).
///
/// A containing a path to a file.
/// A containing suffix to be cut off the path if present.
/// The path conponent of the given .
[ImplementsFunction("basename")]
[PureFunction]
public static string GetBase(string path, string suffix)
{
if (String.IsNullOrEmpty(path)) return string.Empty;
int end = path.Length - 1;
while (end >= 0 && IsDirectorySeparator(path[end])) end--;
int start = end;
while (start >= 0 && !IsDirectorySeparator(path[start])) start--;
start++;
int name_length = end - start + 1;
if (!string.IsNullOrEmpty(suffix) &&
suffix.Length < name_length &&
String.Compare(path, end - suffix.Length + 1, suffix, 0, suffix.Length, StringComparison.CurrentCultureIgnoreCase) == 0)
{
name_length -= suffix.Length;
}
return path.Substring(start, name_length);
}
private static bool IsDirectorySeparator(char c)
{
return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
}
///
/// Returns directory name component of path.
///
/// The full path.
/// The directory portion of the given path.
[ImplementsFunction("dirname")]
[PureFunction]
public static string GetDirectory(string path)
{
if (String.IsNullOrEmpty(path)) return null;
int start = 0;
int end = path.Length - 1;
// advance start position beyond drive specifier:
if (path.Length >= 2 && path[1] == ':' && (path[0] >= 'a' && path[0] <= 'z' || path[0] >= 'A' && path[0] <= 'Z'))
{
start = 2;
if (path.Length == 2)
return path;
}
// strip slashes from the end:
while (end >= start && IsDirectorySeparator(path[end])) end--;
if (end < start)
return path.Substring(0, end + 1) + Path.DirectorySeparatorChar;
// strip file name:
while (end >= start && !IsDirectorySeparator(path[end])) end--;
if (end < start)
return path.Substring(0, end + 1) + '.';
// strip slashes from the end:
while (end >= start && IsDirectorySeparator(path[end])) end--;
if (end < start)
return path.Substring(0, end + 1) + Path.DirectorySeparatorChar;
return path.Substring(0, end + 1);
}
///
/// Extracts parts from a specified path.
///
/// The path to be parsed.
/// Array keyed by "dirname" , "basename" , and "extension" .
///
[ImplementsFunction("pathinfo")]
public static object GetInfo(string path)
{
return GetInfo(path, PathInfoOptions.All);
}
///
/// Extracts part(s) from a specified path.
///
/// The path to be parsed.
/// Flags determining the result.
///
/// If is then returns array
/// keyed by "dirname" , "basename" , and "extension" . Otherwise,
/// it returns string value containing a single part of the path.
///
[ImplementsFunction("pathinfo")]
public static object GetInfo(string path, PathInfoOptions options)
{
// collect strings
string dirname = null, basename = null, extension = null, filename = null;
if ((options & PathInfoOptions.BaseName) != 0 ||
(options & PathInfoOptions.Extension) != 0 ||
(options & PathInfoOptions.FileName) != 0 )
basename = GetBase(path);
if ((options & PathInfoOptions.DirName) != 0)
dirname = GetDirectory(path);
if ((options & PathInfoOptions.Extension) != 0)
{
int last_dot = basename.LastIndexOf('.');
if (last_dot >= 0)
extension = basename.Substring(last_dot + 1);
}
if ((options & PathInfoOptions.FileName) != 0)
{
int last_dot = basename.LastIndexOf('.');
if (last_dot >= 0)
filename = basename.Substring(0, last_dot);
else
filename = basename;
}
// return requested value or all of them in an associative array
if (options == PathInfoOptions.All)
{
PhpArray result = new PhpArray(0, 4);
result.Add("dirname", dirname);
result.Add("basename", basename);
result.Add("extension", extension);
result.Add("filename", filename);
return result;
}
if ((options & PathInfoOptions.DirName) != 0)
return dirname;
if ((options & PathInfoOptions.BaseName) != 0)
return basename;
if ((options & PathInfoOptions.Extension) != 0)
return extension;
if ((options & PathInfoOptions.FileName) != 0)
return filename;
return null;
}
#endregion
#region tempnam, realpath, sys_get_temp_dir
///
/// Creates a file with a unique path in the specified directory.
/// If the directory does not exist, tempnam() may generate
/// a file in the system's temporary directory, and return the name of that.
///
/// The directory where the temporary file should be created.
/// The prefix of the unique path.
/// A unique path for a temporary file
/// in the given .
[ImplementsFunction("tempnam")]
public static string GetTemporaryFilename(string dir, string prefix)
{
// makes "dir" a valid directory:
if (string.IsNullOrEmpty(dir) || !System.IO.Directory.Exists(dir))
dir = Path.GetTempPath();
// makes "prefix" a valid file prefix:
if (prefix == null || prefix.Length == 0 || prefix.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
prefix = "tmp_";
string path = Path.Combine(dir, prefix);
string result;
for (; ; )
{
result = String.Concat(path, Interlocked.Increment(ref tempCounter), ".tmp");
if (!File.Exists(result))
{
try
{
File.Open(result, FileMode.CreateNew).Close();
break;
}
catch (UnauthorizedAccessException)
{
// try system temp directory:
dir = Path.GetTempPath();
path = Path.Combine(dir, prefix);
}
catch (PathTooLongException e)
{
PhpException.Throw(PhpError.Notice, PhpException.ToErrorMessage(e.Message));
return Path.GetTempFileName();
}
catch (Exception)
{
}
}
}
return result;
}
///
/// Returns the path of the directory PHP stores temporary files in by default.
///
/// Returns the path of the temporary directory.
/// Path ends with "\"
[ImplementsFunction("sys_get_temp_dir")]
public static string GetTempDirectoryName()
{
return Path.GetTempPath();
}
///
/// A counter used to generate unique filenames for .
///
private static int tempCounter = 0;
///
/// Returns canonicalized absolute path name.
///
/// Arbitrary path.
///
/// The given combined with the current working directory or
/// null (false in PHP) if the path is invalid or doesn't exists.
///
[ImplementsFunction("realpath")]
[return: CastToFalse]
public static string RealPath(string path)
{
if (String.IsNullOrEmpty(path)) return null;
// string ending slash
if (IsDirectorySeparator(path[path.Length - 1]))
path = path.Substring(0, path.Length - 1);
string realpath = PhpPath.AbsolutePath(path);
if (!File.Exists(realpath) && !System.IO.Directory.Exists(realpath))
{
return null;
}
return realpath;
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/FileSystem.cs
================================================
/*
Copyright (c) 2004-2006 Jan Benda and Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO:
- Added support for LOCK_EX flag for file_put_contents(). (PHP 5.1.0)
- Added lchown() and lchgrp() to change user/group ownership of symlinks. (PHP 5.1.3)
- Fixed safe_mode check for source argument of the copy() function. (PHP 5.1.3)
*/
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Collections;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using PHP.Core;
using System.Diagnostics;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
#region Enums (FileOptions, WriteContentsOptions, ...)
///
/// Options used in the flags argument of the 'fopen' function.
///
[Flags]
public enum FileOpenOptions
{
/// Default option for the flags argument.
Empty = 0,
/// Search for the file in the include_path too (1).
[ImplementsConstant("FILE_USE_INCLUDE_PATH")]
UseIncludePath = 0x1
// UNUSED /// Do not create a default context if none is provided (16).
// UNUSED [ImplementsConstant("FILE_NO_DEFAULT_CONTEXT")] NoDefaultContext = 0x10
}
///
/// Options used in the flags argument of PHP Filesystem functions.
///
[Flags]
public enum FileOptions
{
///
/// Default.
///
Empty = 0,
///
/// Search for the file in the include_path too (1).
///
UseIncludePath = FileOpenOptions.UseIncludePath,
///
/// Do not include the line break characters to the result in file() (2).
///
[ImplementsConstant("FILE_IGNORE_NEW_LINES")]
TrimLineEndings = 2,
///
/// Do not include empty lines to the resulting in file() (4).
///
[ImplementsConstant("FILE_SKIP_EMPTY_LINES")]
SkipEmptyLines = 4
}
///
/// The options used as the flag argument of .
///
[Flags]
public enum WriteContentsOptions
{
///
/// Empty option (default).
///
Empty = 0,
///
/// Search for the file in the include_path too (1).
///
UseIncludePath = FileOptions.UseIncludePath,
///
/// Append the given data at the end of the file in file_put_contents (8).
///
[ImplementsConstant("FILE_APPEND")]
AppendContents = 8,
///
/// Acquire an exclusive lock on the file.
///
LockExclusive = StreamLockOptions.Exclusive
}
///
/// The flags indicating which fields the
/// method should fill in the result array.
///
[Flags]
public enum PathInfoOptions
{
///
/// Fill the "dirname" field in results.
///
[ImplementsConstant("PATHINFO_DIRNAME")]
DirName = 1,
///
/// Fill the "basename" field in results.
///
[ImplementsConstant("PATHINFO_BASENAME")]
BaseName = 2,
///
/// Fill the "extension" field in results.
///
[ImplementsConstant("PATHINFO_EXTENSION")]
Extension = 4,
///
/// Fill the "filename" field in results. Since PHP 5.2.0.
///
[ImplementsConstant("PATHINFO_FILENAME")]
FileName = 8,
///
/// All the four options result in an array returned by .
///
All = DirName | BaseName | Extension | FileName
}
#endregion
///
/// Provides PHP I/O operations using the set of StreamWrappers.
///
///
public static partial class PhpFile
{
///
/// Name of variable that is filled with response headers in case of file_get_contents and http protocol.
///
internal const string HttpResponseHeaderName = "http_response_header";
#region Constructors
///
/// Registers the ClassLibrary filters for the Core streams API.
///
static PhpFile()
{
#if !SILVERLIGHT
RequestContext.RequestEnd += new Action(Clear);
#endif
PhpFilter.AddSystemFilter(new StringFilterFactory());
PhpFilter.AddSystemFilter(new EncodingFilterFactory());
PhpFilter.AddSystemFilter(new DecodingFilterFactory());
}
#endregion
#region make_absolute (Silverlight utility)
#if SILVERLIGHT
[ImplementsFunction("sl_mkabsolute")]
public static string MakeAbsoluteUrl(string relative)
{
return HttpPathUtils.Combine(System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri, "../" + relative);
}
#endif
#endregion
#region fopen, tmpfile, fclose, feof, fflush
///
/// Opens filename or URL using a registered StreamWrapper.
///
/// The file to be opened. The schema part of the URL specifies the wrapper to be used.
/// The read/write and text/binary file open mode.
/// The file resource or false in case of failure.
[ImplementsFunction("fopen")]
[return: CastToFalse]
public static PhpResource Open(string path, string mode)
{
return Open(path, mode, FileOpenOptions.Empty, StreamContext.Default);
}
///
/// Opens filename or URL using a registered StreamWrapper.
///
/// The file to be opened. The schema part of the URL specifies the wrapper to be used.
/// The read/write and text/binary file open mode.
/// If set to true, then the include path is searched for relative filenames too.
/// The file resource or false in case of failure.
[ImplementsFunction("fopen")]
[return: CastToFalse]
public static PhpResource Open(string path, string mode, FileOpenOptions flags)
{
return Open(path, mode, flags, StreamContext.Default);
}
///
/// Opens filename or URL using a registered StreamWrapper.
///
/// The file to be opened. The schema part of the URL specifies the wrapper to be used.
/// The read/write and text/binary file open mode.
/// If set to true, then the include path is searched for relative filenames too.
/// A script context to be provided to the StreamWrapper.
/// The file resource or false in case of failure.
[ImplementsFunction("fopen")]
[return: CastToFalse]
public static PhpResource Open(string path, string mode, FileOpenOptions flags, PhpResource context)
{
StreamContext sc = StreamContext.GetValid(context);
if (sc == null) return null;
if (String.IsNullOrEmpty(path))
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:empty", "path"));
return null;
}
if (String.IsNullOrEmpty(mode))
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:empty", "mode"));
return null;
}
return PhpStream.Open(path, mode, ProcessOptions(flags), sc);
}
///
/// Prevents invalid options from the the options argument for StreamWrapper.Open().
///
/// Flags passed to stream opening functions.
/// The StreamOpenFlags combination for the given arguments.
internal static StreamOpenOptions ProcessOptions(FileOpenOptions flags)
{
StreamOpenOptions options = 0;
if ((flags & FileOpenOptions.UseIncludePath) > 0)
options |= StreamOpenOptions.UseIncludePath;
if (!ScriptContext.CurrentContext.ErrorReportingDisabled)
options |= StreamOpenOptions.ReportErrors;
return options;
}
///
/// Creates a temporary file.
///
///
/// Creates a temporary file with an unique name in write mode,
/// returning a file handle similar to the one returned by fopen().
/// The file is automatically removed when closed (using fclose()),
/// or when the script ends.
///
///
[ImplementsFunction("tmpfile")]
public static PhpResource OpenTemporary()
{
string path = PhpPath.GetTemporaryFilename(string.Empty, "php");
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref path, out wrapper, CheckAccessMode.FileMayExist, CheckAccessOptions.Empty))
return null;
return wrapper.Open(ref path, "w+b", StreamOpenOptions.Temporary, StreamContext.Default);
}
///
/// Close an open file pointer.
///
/// A PhpResource passed to the PHP function.
/// True if successful.
[ImplementsFunction("fclose")]
public static bool Close(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return false;
if (stream.IsPersistent)
{
// Do not close persisten streams (incl. for example STDOUT).
stream.Flush();
return true;
}
stream.Close();
return true;
}
///
/// Tests for end-of-file on a file pointer.
///
/// A PhpResource passed to the PHP function.
/// True if successful.
[ImplementsFunction("feof")]
public static bool Eof(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return false;
return stream.Eof;
}
///
/// Flushes the output to a file.
///
/// A PhpResource passed to the PHP function.
/// True if successful.
[ImplementsFunction("fflush")]
public static bool Flush(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return false;
return stream.Flush();
}
#endregion
#region fprintf, fscanf
///
/// Writes the string formatted using sprintf to the given stream.
///
/// A stream opened for writing.
/// The format string. For details, see PHP manual.
/// The arguments.
/// See PHP manual for details.
/// Besides, a type specifier "%C" is applicable. It converts an integer value to Unicode character.
/// Number of characters written of false in case of an error.
[ImplementsFunction("fprintf")]
[return: CastToFalse]
public static int WriteFormatted(PhpResource handle, string format, params object[] arguments)
{
string formatted = PhpStrings.Format(format, arguments);
if (formatted == String.Empty) return 0;
return WriteInternal(handle, formatted, -1);
}
///
/// Parses input from a file according to a format.
///
///
///
/// A containing the parsed values.
[ImplementsFunction("fscanf")]
[return: CastToFalse]
public static PhpArray ReadLineFormat(PhpResource handle, string format)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return null;
string line = stream.ReadLine(-1, null);
return PhpStrings.ScanFormat(line, format);
}
///
/// Parses input from a file according to a format.
///
///
///
///
///
/// The number of assigned values.
[ImplementsFunction("fscanf")]
[return: CastToFalse]
public static int ReadLineFormat(PhpResource handle, string format, PhpReference arg, params PhpReference[] arguments)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return -1;
string line = stream.ReadLine(-1, null);
return PhpStrings.ScanFormat(line, format, arg, arguments);
}
#endregion
#region fgetcsv, fputcsv, str_getcsv
private const char DefaultCsvDelimiter = ',';
private const char DefaultCsvEnclosure = '"';
private const char DefaultCsvEscape = '\\';
[ImplementsFunction("str_getcsv")]
public static PhpArray ReadStrLineCsv( string input )
{
return ReadStrLineCsv(input, DefaultCsvDelimiter, DefaultCsvEnclosure, DefaultCsvEscape);
}
[ImplementsFunction("str_getcsv")]
public static PhpArray ReadStrLineCsv(string input, char delimiter)
{
return ReadStrLineCsv(input, delimiter, DefaultCsvEnclosure, DefaultCsvEscape);
}
[ImplementsFunction("str_getcsv")]
public static PhpArray ReadStrLineCsv(string input, char delimiter, char enclosure)
{
return ReadStrLineCsv(input, delimiter, enclosure, DefaultCsvEscape);
}
[ImplementsFunction("str_getcsv")]
public static PhpArray ReadStrLineCsv(string input, char delimiter, char enclosure, char escape)
{
bool firstLine = true;
return ReadLineCsv(delegate()
{
if (!firstLine)
return null;
firstLine = false;
return input;
},
delimiter, enclosure, escape);
}
[ImplementsFunction("fgetcsv")]
public static object ReadLineCsv(PhpResource handle)
{
return ReadLineCsv(handle, 0, DefaultCsvDelimiter, DefaultCsvEnclosure, DefaultCsvEscape);
}
[ImplementsFunction("fgetcsv")]
public static object ReadLineCsv(PhpResource handle, int length)
{
return ReadLineCsv(handle, length, DefaultCsvDelimiter, DefaultCsvEnclosure, DefaultCsvEscape);
}
[ImplementsFunction("fgetcsv")]
public static object ReadLineCsv(PhpResource handle, int length, char delimiter)
{
return ReadLineCsv(handle, length, delimiter, DefaultCsvEnclosure, DefaultCsvEscape);
}
[ImplementsFunction("fgetcsv")]
public static object ReadLineCsv(PhpResource handle, int length, char delimiter, char enclosure)
{
return ReadLineCsv(handle, length, delimiter, enclosure, DefaultCsvEscape);
}
///
///
///
///
///
///
///
/// The escape character used in the CSV string.
/// Returns an indexed array containing the fields read.
/// fgetcsv() returns NULL if an invalid handle is supplied or FALSE on other errors, including end of file.
[ImplementsFunction("fgetcsv")]
public static object ReadLineCsv(PhpResource handle, int length, char delimiter/*=','*/, char enclosure/*='"'*/, char escape_char /*= '\\'*/ )
{
// check arguments
PhpStream stream = PhpStream.GetValid(handle, FileAccess.Read);
if (stream == null) return null;
if (length < 0) PhpException.InvalidArgument("length", LibResources.GetString("arg:negative"));
if (length <= 0) length = -1; // no length limit
if (stream.Eof) return false;
return ReadLineCsv(() => (stream.Eof ? null : stream.ReadLine(length, null)), delimiter, enclosure, escape_char);
}
///
/// CSV data line reader.
/// In case of stream, it returns stream.GetLine() or null in case of EOF.
/// In case of string input, it returns string for the first time, then null.
/// ...
///
/// Next line of CSV data or NULL in case of EOF.
private delegate string CsvLineReader();
private static PhpArray ReadLineCsv( CsvLineReader reader, char delimiter/*=','*/, char enclosure/*='"'*/, char escape_char /*= '\\'*/ )
{
// collect results
PhpArray result = new PhpArray();
int i = 0; // index of currently scanned char
string line = reader(); // currently scanned string
bool eof = false;
if (line == null)
{
result.Add(null);
return result;
}
for (; ; )
{
Debug.Assert(i - 1 < line.Length);
bool previous_field_delimited = (i == 0 || line[i - 1] == delimiter);
// skip initial whitespace:
while (i < line.Length && Char.IsWhiteSpace(line[i]) && line[i] != delimiter)
++i;
if (i >= line.Length)
{
if (result.Count == 0)
result.Add(null);
else if (previous_field_delimited)
result.Add(string.Empty);
break;
}
else if (line[i] == delimiter)
{
if (previous_field_delimited)
result.Add(string.Empty);
++i;
}
else if (line[i] == enclosure)
{
// enclosed string follows:
int start = ++i;
StringBuilder field_builder = new StringBuilder();
for (; ; )
{
// read until enclosure character found:
while (i < line.Length && line[i] != enclosure)
{
if (i + 1 < line.Length && line[i] == escape_char)
++i;// skip escape char
++i; // skip following char
}
// end of line:
if (i == line.Length)
{
// append including eoln:
field_builder.Append(line, start, line.Length - start);
// field continues on the next line:
string nextLine = reader();
if (nextLine == null)
{
eof = true;
break;
}
line = nextLine;
start = i = 0;
}
else
{
Debug.Assert(line[i] == enclosure);
i++;
if (i < line.Length && line[i] == enclosure)
{
// escaped enclosure; add previous text including enclosure:
field_builder.Append(line, start, i - start);
start = ++i;
}
else
{
// end of enclosure:
field_builder.Append(line, start, i - 1 - start);
start = i;
break;
}
}
}
if (!eof)//if (!stream.Eof)
{
Debug.Assert(start == i && line.Length > 0);
int end = GetCsvDisclosedTextEnd(line, delimiter, ref i, escape_char);
field_builder.Append(line, start, end - start);
}
//result.Add(Core.Convert.Quote(field_builder.ToString(), context));
//result.Add(StringUtils.EscapeStringCustom(field_builder.ToString(), charsToEscape, escape));
result.Add(field_builder.ToString());
}
else
{
// disclosed text:
int start = i;
int end = GetCsvDisclosedTextEnd(line, delimiter, ref i, escape_char);
//result.Add( Core.Convert.Quote(line.Substring(start, end - start), context));
//result.Add(StringUtils.EscapeStringCustom(line.Substring(start, end - start), charsToEscape, escape));
result.Add(line.Substring(start, end - start));
}
}
return result;
}
private static int GetCsvDisclosedTextEnd(string line, char delimiter, ref int i, char escape_char)
{
// disclosed text follows enclosed one:
while (i < line.Length && line[i] != delimiter)
{
i++;
}
// field ended by eoln or delimiter:
if (i == line.Length)
{
// do not add eoln to the field:
int dec = 0;
if (line[i - 1] == '\n')
{
dec++;
if (i > 1 && line[i - 2] == '\r')
dec++;
}
return i - dec;
}
else
{
Debug.Assert(line[i] == delimiter);
// skip delimiter:
return i++;
}
}
[ImplementsFunction("fputcsv")]
public static int WriteLineCsv(PhpResource handle, PhpArray fields)
{
return WriteLineCsv(handle, fields, DefaultCsvDelimiter, DefaultCsvEnclosure);
}
[ImplementsFunction("fputcsv")]
public static int WriteLineCsv(PhpResource handle, PhpArray fields, char delimiter)
{
return WriteLineCsv(handle, fields, delimiter, DefaultCsvEnclosure);
}
///
/// Affected by run-time quoting (data are unqouted before written)
/// ( ).
///
[ImplementsFunction("fputcsv")]
public static int WriteLineCsv(PhpResource handle, PhpArray fields, char delimiter, char enclosure)
{
PhpStream stream = PhpStream.GetValid(handle, FileAccess.Write);
if (stream == null || !stream.CanWrite) return -1;
ScriptContext context = ScriptContext.CurrentContext;
char[] special_chars = { delimiter, ' ', '\\', '\t', '\r', '\n' };
string str_enclosure = enclosure.ToString();
string str_delimiter = delimiter.ToString();
int initial_position = stream.WritePosition;
foreach (object field in fields.Values)
{
string str_field = Core.Convert.Unquote(Core.Convert.ObjectToString(field), context);
if (stream.WritePosition > initial_position)
stream.WriteString(str_delimiter);
int special_char_index = str_field.IndexOfAny(special_chars);
int enclosure_index = str_field.IndexOf(enclosure);
if (special_char_index >= 0 || enclosure_index >= 0)
{
stream.WriteString(str_enclosure);
if (enclosure_index >= 0)
{
// escapes enclosure characters:
int start = 0;
for (; ; )
{
// writes string starting after the last enclosure and ending by the next one:
stream.WriteString(str_field.Substring(start, enclosure_index - start + 1));
stream.WriteString(str_enclosure);
start = enclosure_index + 1;
if (start >= str_field.Length) break;
enclosure_index = str_field.IndexOf(enclosure, start);
if (enclosure_index < 0)
{
// remaining substring:
stream.WriteString(str_field.Substring(start));
break;
}
}
}
else
{
stream.WriteString(str_field);
}
stream.WriteString(str_enclosure);
}
else
{
stream.WriteString(str_field);
}
}
stream.WriteString("\n");
return (initial_position == -1) ? stream.WritePosition : stream.WritePosition - initial_position;
}
#endregion
#region fread, fgetc, fwrite, fputs, fpassthru, readfile
///
/// Binary-safe file read.
///
/// A file stream opened for reading.
/// Number of bytes to be read.
///
/// The or
/// of the specified length depending on file access mode.
///
///
/// Result is affected by run-time quoting
/// ( ).
///
[ImplementsFunction("fread")]
public static object Read(PhpResource handle, int length)
{
// returns an object (string or PhpBytes depending on fopen mode)
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return null;
if (stream.IsText)
return Core.Convert.Quote(stream.ReadString(length), ScriptContext.CurrentContext);
else
return Core.Convert.Quote(stream.ReadBytes(length), ScriptContext.CurrentContext);
}
///
/// Gets character from file pointer.
///
/// A file stream opened for reading.
/// A or containing one character from the
/// given stream or false on EOF.
[ImplementsFunction("fgetc")]
[return: CastToFalse]
public static object ReadChar(PhpResource handle)
{
if (Eof(handle)) return null;
return Read(handle, 1);
}
///
/// Binary-safe file write.
///
/// The file stream (opened for writing).
/// The data to be written.
/// Returns the number of bytes written, or FALSE on error.
///
/// Affected by run-time quoting (data are unqouted before written)
/// ( ).
///
[ImplementsFunction("fwrite")]
[return: CastToFalse]
public static int Write(PhpResource handle, object data)
{
return Write(handle, data, -1);
}
///
/// Binary-safe file write.
///
/// The file stream (opened for writing).
/// The data to be written.
///
/// If the length argument is given, writing will stop after length bytes
/// have been written or the end of string is reached, whichever comes first.
///
/// Returns the number of bytes written, or FALSE on error.
///
/// Affected by run-time quoting (data are unqouted before written)
/// ( ).
///
[ImplementsFunction("fwrite")]
[return: CastToFalse]
public static int Write(PhpResource handle, object data, int length)
{
data = Core.Convert.Unquote(data, ScriptContext.CurrentContext);
return WriteInternal(handle, data, length);
}
///
/// Binary-safe file write. Alias for .
///
/// The file stream (opened for writing).
/// The data to be written.
/// Returns the number of bytes written, or FALSE on error.
[ImplementsFunction("fputs")]
[return: CastToFalse]
public static int Write2(PhpResource handle, object data)
{
return Write(handle, data);
}
///
/// Binary-safe file write. Alias for .
///
/// The file stream (opened for writing).
/// The data to be written.
/// If the length argument is given, writing will stop after length bytes
/// have been written or the end of string is reached, whichever comes first.
/// Returns the number of bytes written, or FALSE on error.
[ImplementsFunction("fputs")]
[return: CastToFalse]
public static int Write2(PhpResource handle, object data, int length)
{
return Write(handle, data, length);
}
///
/// Binary-safe file write implementation.
///
/// The file stream (opened for writing).
/// The data to be written.
/// The number of characters to write or -1 to use the whole .
/// Returns the number of bytes written, or FALSE on error.
internal static int WriteInternal(PhpResource handle, object data, int length)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return -1;
if (data == null) return 0;
// Note: Any data type is converted using implicit conversion in AsText/AsBinary.
if (stream.IsText)
{
// If file OpenMode is text then use string access methods.
string sub;
if (length > 0) sub = PhpStream.AsText(data, length);
else sub = PhpStream.AsText(data);
return stream.WriteString(sub);
}
else
{
// File OpenMode is binary.
PhpBytes sub;
if (length > 0) sub = PhpStream.AsBinary(data, length);
else sub = PhpStream.AsBinary(data);
return stream.WriteBytes(sub);
}
}
///
/// Outputs all remaining data on a file pointer.
///
/// The file stream (opened for reading).
/// Number of bytes written.
[ImplementsFunction("fpassthru")]
[return: CastToFalse]
public static int PassThrough(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return -1;
if (stream.IsText)
{
// Use the text output buffers.
int rv = 0;
while (!stream.Eof)
{
string str = stream.ReadMaximumString();
ScriptContext.CurrentContext.Output.Write(str);
rv += str.Length;
}
return rv;
}
else
{
// Write directly to the binary output buffers.
return PhpStreams.Copy(stream, InputOutputStreamWrapper.ScriptOutput);
}
}
///
/// Reads a file and writes it to the output buffer.
///
/// The file to open.
/// Returns the number of bytes read from the file. If an error occurs, false is returned.
[ImplementsFunction("readfile")]
[return: CastToFalse]
public static int ReadFile(string path)
{
return ReadFile(path, FileOpenOptions.Empty, StreamContext.Default);
}
///
/// Reads a file and writes it to the output buffer.
///
/// The file to open.
/// Searches for the file in the include_path if set to true .
/// Returns the number of bytes read from the file. If an error occurs, false is returned.
[ImplementsFunction("readfile")]
[return: CastToFalse]
public static int ReadFile(string path, FileOpenOptions flags)
{
return ReadFile(path, flags, StreamContext.Default);
}
///
/// Reads a file and writes it to the output buffer.
///
/// The file to open.
/// Searches for the file in the include_path if set to 1 .
/// A resource with additional information for the stream.
/// Returns the number of bytes read from the file. If an error occurs, false is returned.
[ImplementsFunction("readfile")]
[return: CastToFalse]
public static int ReadFile(string path, FileOpenOptions flags, PhpResource context)
{
StreamContext sc = StreamContext.GetValid(context, true);
if (sc == null) return -1;
using (PhpStream res = PhpStream.Open(path, "rb", ProcessOptions(flags), sc))
{
if (res == null) return -1;
// Note: binary file access is the most efficient (no superfluous filtering
// and no conversions - PassThrough will write directly to the OutputStream).
return PassThrough(res);
}
}
#endregion
#region fgets, fgetss
///
/// Gets one line of text from file pointer including the end-of-line character.
///
/// The file stream opened for reading.
/// A or containing the line of text or false in case of an error.
///
///
/// Result is affected by run-time quoting
/// ( ).
///
///
[ImplementsFunction("fgets")]
[return: CastToFalse]
public static object ReadLine(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return null;
// Use the default accessor to the stream breaking at \n, no superfluous conversion.
return Core.Convert.Quote(stream.ReadData(-1, true), ScriptContext.CurrentContext);
}
///
/// Gets one line of text from file pointer including the end-of-line character.
///
/// Maximum length of the returned text.
/// The file stream opened for reading.
/// A or containing the line of text or false in case of an error.
///
///
/// Returns a string of up to - 1 bytes read from
/// the file pointed to by .
///
///
/// The parameter became optional in PHP 4.2.0, if omitted, it would
/// assume 1024 as the line length. As of PHP 4.3, omitting will keep
/// reading from the stream until it reaches the end of the line.
/// If the majority of the lines in the file are all larger than 8KB,
/// it is more resource efficient for your script to specify the maximum line length.
///
///
/// Result is affected by run-time quoting
/// ( ).
///
///
[ImplementsFunction("fgets")]
[return: CastToFalse]
public static object ReadLine(PhpResource handle, int length)
{
if (length <= 0)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:negative", "Length"));
return null;
}
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return null;
// Use the default accessor to the stream breaking at \n, no superfluous conversion.
return Core.Convert.Quote(stream.ReadData(length, true), ScriptContext.CurrentContext);
}
///
/// Gets a whole line from file pointer and strips HTML tags.
///
[ImplementsFunction("fgetss")]
[return: CastToFalse]
public static string ReadLineStripTags(PhpResource handle)
{
return ReadLineStripTagsInternal(handle, -1, null);
}
///
/// Gets a line from file pointer and strips HTML tags.
///
[ImplementsFunction("fgetss")]
[return: CastToFalse]
public static string ReadLineStripTags(PhpResource handle, int length)
{
return ReadLineStripTags(handle, length, null);
}
///
/// Gets one line from file pointer and strips HTML tags.
///
///
///
///
///
[ImplementsFunction("fgetss")]
[return: CastToFalse]
public static string ReadLineStripTags(PhpResource handle, int length, string allowableTags)
{
if (length <= 0)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:negative", "Length"));
return null;
}
return ReadLineStripTagsInternal(handle, length, allowableTags);
}
internal static string ReadLineStripTagsInternal(PhpResource handle, int length, string allowableTags)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return null;
string line = PhpStream.AsText(stream.ReadLine(length, null));
if (line != null)
{
int state = stream.StripTagsState;
line = PhpStrings.StripTags(line, allowableTags, ref state);
stream.StripTagsState = state;
}
return line;
}
#endregion
#region file, file_get_contents, file_put_contents
///
/// Reads entire file into an array.
///
///
///
[ImplementsFunction("file")]
[return: CastToFalse]
public static PhpArray ReadArray(string path)
{
return ReadArray(path, 0, StreamContext.Default);
}
///
/// Reads entire file into an array.
///
///
///
///
[ImplementsFunction("file")]
[return: CastToFalse]
public static PhpArray ReadArray(string path, FileOptions flags)
{
return ReadArray(path, flags, StreamContext.Default);
}
///
/// Reads entire file into an array.
///
///
///
///
/// The input file is split at '\n' and the separator is included in every line.
///
///
/// Result is affected by run-time quoting
/// ( ).
///
[ImplementsFunction("file")]
[return: CastToFalse]
public static PhpArray ReadArray(string path, FileOptions flags, PhpResource context)
{
StreamContext sc = StreamContext.GetValid(context, true);
if (sc == null) return null;
ScriptContext script_context = ScriptContext.CurrentContext;
using (PhpStream stream = PhpStream.Open(path, "rt", ProcessOptions((FileOpenOptions)flags), sc))
{
if (stream == null) return null;
PhpArray rv = new PhpArray();
while (!stream.Eof)
{
// Note: The last line does not contain the \n delimiter, but may be empty
string line = PhpStream.AsText(stream.ReadData(-1, true));
if ((flags & FileOptions.TrimLineEndings) > 0)
{
int len = line.Length;
if ((len > 0) && (line[len - 1] == '\n'))
line = line.Substring(0, len - 1);
}
if ((flags & FileOptions.SkipEmptyLines) > 0)
{
if (line.Length == 0) continue;
}
rv.Add(Core.Convert.Quote(line, script_context));
}
return rv;
}
}
///
/// Reads entire file into a string.
///
[ImplementsFunction("file_get_contents", FunctionImplOptions.NeedsVariables)]
[return: CastToFalse]
public static object ReadContents(ScriptContext scriptcontext, System.Collections.Generic.Dictionary definedVariables, string path)
{
return ReadContents(scriptcontext, definedVariables, path, FileOpenOptions.Empty, StreamContext.Default, -1, -1);
}
///
/// Reads entire file into a string.
///
[ImplementsFunction("file_get_contents", FunctionImplOptions.NeedsVariables)]
[return: CastToFalse]
public static object ReadContents(ScriptContext scriptcontext, System.Collections.Generic.Dictionary definedVariables, string path, FileOpenOptions flags)
{
return ReadContents(scriptcontext, definedVariables, path, flags, StreamContext.Default, -1, -1);
}
///
/// Reads entire file into a string.
///
[ImplementsFunction("file_get_contents", FunctionImplOptions.NeedsVariables)]
[return: CastToFalse]
public static object ReadContents(ScriptContext scriptcontext, System.Collections.Generic.Dictionary definedVariables, string path, FileOpenOptions flags, PhpResource context)
{
return ReadContents(scriptcontext, definedVariables, path, flags, context, -1, -1);
}
///
/// Reads entire file into a string.
///
[ImplementsFunction("file_get_contents", FunctionImplOptions.NeedsVariables)]
[return: CastToFalse]
public static object ReadContents(ScriptContext scriptcontext, System.Collections.Generic.Dictionary definedVariables, string path, FileOpenOptions flags, PhpResource context,
int offset)
{
return ReadContents(scriptcontext, definedVariables, path, flags, context, offset, -1);
}
///
/// Reads entire file into a string.
///
///
/// Result is affected by run-time quoting
/// ( ).
///
[ImplementsFunction("file_get_contents", FunctionImplOptions.NeedsVariables)]
[return: CastToFalse]
public static object ReadContents(ScriptContext scriptcontext, System.Collections.Generic.Dictionary definedVariables, string path, FileOpenOptions flags, PhpResource context,
int offset, int maxLength)
{
StreamContext sc = StreamContext.GetValid(context, true);
if (sc == null)
return null;
using (PhpStream stream = PhpStream.Open(path, "rb", ProcessOptions(flags), sc))
{
if (stream == null) return null;
// when HTTP protocol requested, store responded headers into local variable $http_response_header:
// NOTE: (J) this should be applied by HTTP wrapper itself, not only by this function.
if (string.Compare(stream.Wrapper.Scheme, "http", StringComparison.OrdinalIgnoreCase) == 0)
{
var headers = stream.WrapperSpecificData as PhpArray;
Operators.SetVariable(scriptcontext, definedVariables, HttpResponseHeaderName, headers);
}
//
return Core.Convert.Quote(stream.ReadContents(maxLength, offset), ScriptContext.CurrentContext);
}
}
[ImplementsFunction("file_put_contents")]
[return: CastToFalse]
public static int WriteContents(string path, object data)
{
return WriteContents(path, data, 0, StreamContext.Default);
}
[ImplementsFunction("file_put_contents")]
[return: CastToFalse]
public static int WriteContents(string path, object data, WriteContentsOptions flags)
{
return WriteContents(path, data, flags, StreamContext.Default);
}
[ImplementsFunction("file_put_contents")]
[return: CastToFalse]
public static int WriteContents(string path, object data, WriteContentsOptions flags, PhpResource context)
{
StreamContext sc = StreamContext.GetValid(context, true);
if (sc == null) return -1;
string mode = (flags & WriteContentsOptions.AppendContents) > 0 ? "ab" : "wb";
using (PhpStream to = PhpStream.Open(path, mode, ProcessOptions((FileOpenOptions)flags), sc))
{
if (to == null) return -1;
// passing array is equivalent to file_put_contents($filename, join('', $array))
PhpArray array = data as PhpArray;
if (array != null)
{
int total = 0;
foreach (object o in array.Values)
{
int written = to.WriteBytes(Core.Convert.ObjectToPhpBytes(o));
if (written == -1) return total;
total += written;
}
return total;
}
// as of PHP 5.1.0, you may also pass a stream resource to the data parameter
PhpResource resource = data as PhpResource;
if (resource != null)
{
PhpStream from = PhpStream.GetValid(resource);
if (from == null) return -1;
return PhpStreams.Copy(from, to);
}
return to.WriteBytes(Core.Convert.ObjectToPhpBytes(data));
}
}
#endregion
#region Seek (fseek, rewind, ftell, ftruncate)
///
/// Seeks on a file pointer.
///
/// The file stream resource.
/// The number of bytes to seek.
/// Upon success, returns 0; otherwise, returns -1.
/// Note that seeking past EOF is not considered an error.
[ImplementsFunction("fseek")]
public static int Seek(PhpResource handle, int offset)
{
return Seek(handle, offset, (int)SeekOptions.Set);
}
///
/// Seeks on a file pointer.
///
/// A file stream resource.
/// The number of bytes to seek.
/// The position in stream to seek from.
/// May be one of the SeekOptions flags.
/// Upon success, returns 0; otherwise, returns -1.
/// Note that seeking past EOF is not considered an error.
[ImplementsFunction("fseek")]
public static int Seek(PhpResource handle, int offset, int whence)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return -1;
return stream.Seek(offset, (SeekOrigin)whence) ? 0 : -1;
}
///
/// Rewind the position of a file pointer.
///
///
///
[ImplementsFunction("rewind")]
public static bool Rewind(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return false;
return stream.Seek(0, SeekOrigin.Begin);
}
///
/// Tells file pointer read/write position.
///
/// A file stream resource.
///
[ImplementsFunction("ftell")]
[return: CastToFalse]
public static int Tell(PhpResource handle)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return -1;
return stream.Tell();
}
///
/// Truncates a file to a given length.
///
///
///
///
[ImplementsFunction("ftruncate")]
public static bool Truncate(PhpResource handle, int size)
{
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null) return false;
if (stream.RawStream != null && stream.RawStream.CanWrite && stream.RawStream.CanSeek)
{
stream.RawStream.SetLength(size);
return true;
}
return false;
}
#endregion
#region FileSystem Access (copy, rename, unlink, mkdir, rmdir, flock)
///
/// Copies a file (even accross different stream wrappers).
///
///
/// If the destination file already exists, it will be overwritten.
///
/// Note: As of PHP 4.3.0, both source and dest may be URLs if the
/// "fopen wrappers" have been enabled. See fopen() for more details.
/// If dest is an URL, the copy operation may fail if the wrapper does
/// not support overwriting of existing files.
///
///
/// Source URL.
/// Destination URL.
/// true on success or false on failure.
[ImplementsFunction("copy")]
public static bool Copy(string source, string dest)
{
StreamWrapper reader, writer;
if ((!PhpStream.ResolvePath(ref source, out reader, CheckAccessMode.FileExists, CheckAccessOptions.Empty))
|| (!PhpStream.ResolvePath(ref dest, out writer, CheckAccessMode.FileExists, CheckAccessOptions.Empty)))
return false;
if ((reader.Scheme == "file") && (writer.Scheme == "file"))
{
// Copy the file.
try
{
File.Copy(source, dest, true);
return true;
}
catch (System.Exception)
{
return false;
}
}
else
{
// Copy the two files using the appropriate stream wrappers.
using (PhpResource from = reader.Open(ref source, "rb", StreamOpenOptions.Empty, StreamContext.Default))
{
if (from == null) return false;
using (PhpResource to = writer.Open(ref dest, "wb", StreamOpenOptions.Empty, StreamContext.Default))
{
if (to == null) return false;
int copied = PhpStreams.Copy(from, to);
return copied >= 0;
}
}
}
}
///
/// Renames a file.
///
///
/// Both the and the
/// must be handled by the same wrapper.
///
///
///
///
[ImplementsFunction("rename")]
public static bool Rename(string oldpath, string newpath)
{
StreamWrapper oldwrapper, newwrapper;
if ((!PhpStream.ResolvePath(ref oldpath, out oldwrapper, CheckAccessMode.FileExists, CheckAccessOptions.Empty))
|| (!PhpStream.ResolvePath(ref newpath, out newwrapper, CheckAccessMode.FileMayExist, CheckAccessOptions.Empty)))
return false;
if (oldwrapper != newwrapper)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("wrappers_must_match"));
}
return oldwrapper.Rename(oldpath, newpath, StreamRenameOptions.Empty, StreamContext.Default);
}
///
/// Deletes a file using a StreamWrapper corresponding to the given URL.
///
/// An URL of a file to be deleted.
/// True in case of success.
[ImplementsFunction("unlink")]
public static bool Delete(string path)
{
return Delete(path, null);
}
///
/// Deletes a file using a StreamWrapper corresponding to the given URL.
///
/// An URL of a file to be deleted.
/// StreamContext.
/// True in case of success.
[ImplementsFunction("unlink")]
public static bool Delete(string path, PhpResource context)
{
if (String.IsNullOrEmpty(path))
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:empty", "path"));
return false;
}
StreamContext sc = StreamContext.GetValid(context, true);
if (sc == null) // PHP warning is thrown by StreamContext.GetValid
return false;
StreamWrapper wrapper;
if (!PhpStream.ResolvePath(ref path, out wrapper, CheckAccessMode.FileExists, CheckAccessOptions.Empty))
return false;
// Clear the cache (the currently deleted file may have been cached)
#if !SILVERLIGHT
ClearStatCache();
#endif
return wrapper.Unlink(path, 0, sc);
}
///
///
///
///
///
///
[ImplementsFunction("flock")]
public static bool Lock(PhpResource handle, int operation)
{
int dummy = 0;
return Lock(handle, operation, ref dummy);
}
///
/// Portable advisory file locking.
///
/// A file system pointer resource that is typically created using fopen().
/// Operation is one of the following:
/// LOCK_SH to acquire a shared lock (reader).
/// LOCK_EX to acquire an exclusive lock (writer).
/// LOCK_UN to release a lock (shared or exclusive).
///
/// It is also possible to add LOCK_NB as a bitmask to one of the above operations if you don't want flock() to block while locking. (not supported on Windows)
///
/// The optional third argument is set to TRUE if the lock would block (EWOULDBLOCK errno condition). (not supported on Windows)
/// Returns true on success or false on failure.
[ImplementsFunction("flock")]
public static bool Lock(PhpResource handle, int operation, ref int wouldblock)
{
// Get the native file handle for the PHP resource
var phpStream = PhpStream.GetValid(handle);
if (phpStream == null) return false;
var fileStream = phpStream.RawStream as FileStream;
if (fileStream == null) return false;
//
if (EnvironmentUtils.IsDotNetFramework)
{
return Lock_dotNET(fileStream, (StreamLockOptions)operation);
}
else
{
PhpException.FunctionNotSupported();
return false;
}
}
#region flock (Windows)
// Constants passed to LockFileEx for the flags
private const uint LOCKFILE_FAIL_IMMEDIATELY = 0x00000001;
private const uint LOCKFILE_EXCLUSIVE_LOCK = 0x00000002;
[DllImport("kernel32.dll")]
static extern bool LockFileEx(SafeFileHandle hFile, uint dwFlags, uint dwReserved, uint nNumberOfBytesToLockLow, uint nNumberOfBytesToLockHigh, [In] ref NativeOverlapped lpOverlapped);
[DllImport("kernel32.dll")]
static extern bool UnlockFileEx(SafeFileHandle hFile, uint dwReserved, uint nNumberOfBytesToUnlockLow, uint nNumberOfBytesToUnlockHigh, [In] ref NativeOverlapped lpOverlapped);
private static bool Lock_dotNET(FileStream/*!*/fileStream, StreamLockOptions op)
{
Debug.Assert(fileStream != null);
var hFile = fileStream.SafeFileHandle;
// Set up some parameters
uint low = 1, high = 0;
var offset = new NativeOverlapped();
bool noBlocking = (op & StreamLockOptions.NoBlocking) != 0;
// bug for bug compatible with Unix
UnlockFileEx(hFile, 0, low, high, ref offset);
//
switch (op & ~StreamLockOptions.NoBlocking)
{
case StreamLockOptions.Exclusive:
// Exclusive lock
return LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK + (noBlocking ? LOCKFILE_FAIL_IMMEDIATELY : 0), 0, low, high, ref offset);
case StreamLockOptions.Shared:
// Shared lock
return LockFileEx(hFile, (noBlocking ? LOCKFILE_FAIL_IMMEDIATELY : 0), 0, low, high, ref offset);
case StreamLockOptions.Unlock:
// Unlock always succeeds
return true;
}
// Bad call
return false;
}
#endregion
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Filter.cs
================================================
/*
Copyright (c) 2012 Jakub Misek
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using PHP.Core;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.ComponentModel;
#if SILVERLIGHT
using PHP.CoreCLR;
using System.Windows.Browser;
#else
using System.Web;
using System.Diagnostics;
#endif
namespace PHP.Library
{
#region Constants
public enum FilterInput : int
{
[ImplementsConstant("INPUT_POST")]
Post = 0,
[ImplementsConstant("INPUT_GET")]
Get = 1,
[ImplementsConstant("INPUT_COOKIE")]
Cookie = 2,
[ImplementsConstant("INPUT_ENV")]
Env = 4,
[ImplementsConstant("INPUT_SERVER")]
Server = 5,
[ImplementsConstant("INPUT_SESSION")]
Session = 6,
[ImplementsConstant("INPUT_REQUEST")]
Request = 99
}
///
/// Other filter ids.
///
public enum FilterIds : int
{
///
/// Flag used to require scalar as input
///
[ImplementsConstant("FILTER_REQUIRE_SCALAR")]
FILTER_REQUIRE_SCALAR = 33554432,
///
/// Require an array as input.
///
[ImplementsConstant("FILTER_REQUIRE_ARRAY")]
FILTER_REQUIRE_ARRAY = 16777216,
///
/// Always returns an array.
///
[ImplementsConstant("FILTER_FORCE_ARRAY")]
FILTER_FORCE_ARRAY = 67108864,
///
/// Use NULL instead of FALSE on failure.
///
[ImplementsConstant("FILTER_NULL_ON_FAILURE")]
FILTER_NULL_ON_FAILURE = 134217728,
///
/// ID of "callback" filter.
///
[ImplementsConstant("FILTER_CALLBACK")]
FILTER_CALLBACK = 1024,
}
///
/// Validation filters.
///
public enum FilterValidate : int
{
///
/// ID of "int" filter.
///
[ImplementsConstant("FILTER_VALIDATE_INT")]
INT = 257,
///
/// ID of "boolean" filter.
///
[ImplementsConstant("FILTER_VALIDATE_BOOLEAN")]
BOOLEAN = 258,
///
/// ID of "float" filter.
///
[ImplementsConstant("FILTER_VALIDATE_FLOAT")]
FLOAT = 259,
///
/// ID of "validate_regexp" filter.
///
[ImplementsConstant("FILTER_VALIDATE_REGEXP")]
REGEXP = 272,
///
/// ID of "validate_url" filter.
///
[ImplementsConstant("FILTER_VALIDATE_URL")]
URL = 273,
///
/// ID of "validate_email" filter.
///
[ImplementsConstant("FILTER_VALIDATE_EMAIL")]
EMAIL = 274,
///
/// ID of "validate_ip" filter.
///
[ImplementsConstant("FILTER_VALIDATE_IP")]
IP = 275,
}
///
/// Sanitize filters.
///
public enum FilterSanitize : int
{
///
/// ID of "string" filter.
///
[ImplementsConstant("FILTER_SANITIZE_STRING")]
STRING = 513,
///
/// ID of "stripped" filter.
///
[ImplementsConstant("FILTER_SANITIZE_STRIPPED")]
STRIPPED = STRING, // alias of FILTER_SANITIZE_STRING
///
/// ID of "encoded" filter.
///
[ImplementsConstant("FILTER_SANITIZE_ENCODED")]
ENCODED = 514,
///
/// ID of "special_chars" filter.
///
[ImplementsConstant("FILTER_SANITIZE_SPECIAL_CHARS")]
SPECIAL_CHARS = 515,
///
/// ID of "unsafe_raw" filter.
///
[ImplementsConstant("FILTER_UNSAFE_RAW")]
FILTER_UNSAFE_RAW = 516,
///
/// ID of default ("string") filter.
///
[ImplementsConstant("FILTER_DEFAULT")]
FILTER_DEFAULT = FILTER_UNSAFE_RAW, // alias of FILTER_UNSAFE_RAW
///
/// ID of "email" filter.
/// Remove all characters except letters, digits and !#$%&'*+-/=?^_`{|}~@.[].
///
[ImplementsConstant("FILTER_SANITIZE_EMAIL")]
EMAIL = 517,
///
/// ID of "url" filter.
///
[ImplementsConstant("FILTER_SANITIZE_URL")]
URL = 518,
///
/// ID of "number_int" filter.
///
[ImplementsConstant("FILTER_SANITIZE_NUMBER_INT")]
NUMBER_INT = 519,
///
/// ID of "number_float" filter.
///
[ImplementsConstant("FILTER_SANITIZE_NUMBER_FLOAT")]
NUMBER_FLOAT = 520,
///
/// ID of "magic_quotes" filter.
///
[ImplementsConstant("FILTER_SANITIZE_MAGIC_QUOTES")]
MAGIC_QUOTES = 521,
}
[Flags]
public enum FilterFlag : int
{
///
/// No flags.
///
[ImplementsConstant("FILTER_FLAG_NONE")]
NONE = 0,
///
/// Allow octal notation (0[0-7]+) in "int" filter.
///
[ImplementsConstant("FILTER_FLAG_ALLOW_OCTAL")]
ALLOW_OCTAL = 1,
///
/// Allow hex notation (0x[0-9a-fA-F]+) in "int" filter.
///
[ImplementsConstant("FILTER_FLAG_ALLOW_HEX")]
ALLOW_HEX = 2,
///
/// Strip characters with ASCII value less than 32.
///
[ImplementsConstant("FILTER_FLAG_STRIP_LOW")]
STRIP_LOW = 4,
///
/// Strip characters with ASCII value greater than 127.
///
[ImplementsConstant("FILTER_FLAG_STRIP_HIGH")]
STRIP_HIGH = 8,
///
/// Encode characters with ASCII value less than 32.
///
[ImplementsConstant("FILTER_FLAG_ENCODE_LOW")]
ENCODE_LOW = 16,
///
/// Encode characters with ASCII value greater than 127.
///
[ImplementsConstant("FILTER_FLAG_ENCODE_HIGH")]
ENCODE_HIGH = 32,
///
/// Encode &.
///
[ImplementsConstant("FILTER_FLAG_ENCODE_AMP")]
ENCODE_AMP = 64,
///
/// Don't encode ' and ".
///
[ImplementsConstant("FILTER_FLAG_NO_ENCODE_QUOTES")]
NO_ENCODE_QUOTES = 128,
///
/// ?
///
[ImplementsConstant("FILTER_FLAG_EMPTY_STRING_NULL")]
EMPTY_STRING_NULL = 256,
///
/// Allow fractional part in "number_float" filter.
///
[ImplementsConstant("FILTER_FLAG_ALLOW_FRACTION")]
ALLOW_FRACTION = 4096,
///
/// Allow thousand separator (,) in "number_float" filter.
///
[ImplementsConstant("FILTER_FLAG_ALLOW_THOUSAND")]
ALLOW_THOUSAND = 8192,
///
/// Allow scientific notation (e, E) in "number_float" filter.
///
[ImplementsConstant("FILTER_FLAG_ALLOW_SCIENTIFIC")]
ALLOW_SCIENTIFIC = 16384,
///
/// Require path in "validate_url" filter.
///
[ImplementsConstant("FILTER_FLAG_PATH_REQUIRED")]
PATH_REQUIRED = 262144,
///
/// Require query in "validate_url" filter.
///
[ImplementsConstant("FILTER_FLAG_QUERY_REQUIRED")]
QUERY_REQUIRED = 524288,
///
/// Allow only IPv4 address in "validate_ip" filter.
///
[ImplementsConstant("FILTER_FLAG_IPV4")]
IPV4 = 1048576,
///
/// Allow only IPv6 address in "validate_ip" filter.
///
[ImplementsConstant("FILTER_FLAG_IPV6")]
IPV6 = 2097152,
///
/// Deny reserved addresses in "validate_ip" filter.
///
[ImplementsConstant("FILTER_FLAG_NO_RES_RANGE")]
NO_RES_RANGE = 4194304,
///
/// Deny private addresses in "validate_ip" filter.
///
[ImplementsConstant("FILTER_FLAG_NO_PRIV_RANGE")]
NO_PRIV_RANGE = 8388608
}
#endregion
[ImplementsExtension("filter")]
public static class PhpFiltering
{
#region (NS) filter_input_array, filter_var_array, filter_id, filter_list
[ImplementsFunction("filter_input_array", FunctionImplOptions.NotSupported)]
public static object filter_input_array(int type)
{
return filter_input_array(type, null);
}
///
/// Gets external variables and optionally filters them.
///
[ImplementsFunction("filter_input_array", FunctionImplOptions.NotSupported)]
public static object filter_input_array(int type, object definition)
{
return false;
}
///
/// Returns the filter ID belonging to a named filter.
///
[ImplementsFunction("filter_id", FunctionImplOptions.NotSupported)]
[return: CastToFalse]
public static int filter_id(string filtername)
{
return -1;
}
///
/// Returns a list of all supported filters.
///
[ImplementsFunction("filter_list", FunctionImplOptions.NotSupported)]
public static PhpArray/*!*/filter_list()
{
return new PhpArray();
}
[ImplementsFunction("filter_var_array", FunctionImplOptions.NotSupported)]
public static object filter_var_array(PhpArray data)
{
return filter_var_array(data, null);
}
///
/// Gets multiple variables and optionally filters them.
///
///
[ImplementsFunction("filter_var_array", FunctionImplOptions.NotSupported)]
public static object filter_var_array(PhpArray data, object definition)
{
return null;
}
#endregion
#region filter_input
[ImplementsFunction("filter_input")]
public static object filter_input(ScriptContext/*!*/context, FilterInput type, string variable_name)
{
return filter_input(context, type, variable_name, (int)FilterSanitize.FILTER_DEFAULT, null);
}
[ImplementsFunction("filter_input")]
public static object filter_input(ScriptContext/*!*/context, FilterInput type, string variable_name, int filter)
{
return filter_input(context, type, variable_name, filter, null);
}
///
/// Gets a specific external variable by name and optionally filters it.
///
[ImplementsFunction("filter_input")]
public static object filter_input(ScriptContext/*!*/context, FilterInput type, string variable_name, int filter /*= FILTER_DEFAULT*/ , object options)
{
var arrayobj = GetArrayByInput(context, type);
object value;
if (arrayobj == null || !arrayobj.TryGetValue(variable_name, out value))
return null;
return filter_var(value, filter, options);
}
#endregion
#region filter_var, filter_has_var
///
/// Checks if variable of specified type exists
///
[ImplementsFunction("filter_has_var")]
public static bool filter_has_var(ScriptContext/*!*/context, FilterInput type, string variable_name)
{
var arrayobj = GetArrayByInput(context, type);
if (arrayobj != null)
return arrayobj.ContainsKey(variable_name);
else
return false;
}
///
/// Returns containing required input.
///
/// CUrrent .
/// value.
/// An instance of or null if there is no such input.
private static PhpArray GetArrayByInput(ScriptContext/*!*/context, FilterInput type)
{
object arrayobj = null;
switch (type)
{
case FilterInput.Get:
arrayobj = context.AutoGlobals.Get.Value; break;
case FilterInput.Post:
arrayobj = context.AutoGlobals.Post.Value; break;
case FilterInput.Server:
arrayobj = context.AutoGlobals.Server.Value; break;
case FilterInput.Request:
arrayobj = context.AutoGlobals.Request.Value; break;
case FilterInput.Env:
arrayobj = context.AutoGlobals.Env.Value; break;
case FilterInput.Cookie:
arrayobj = context.AutoGlobals.Cookie.Value; break;
case FilterInput.Session:
arrayobj = context.AutoGlobals.Session.Value; break;
default:
return null;
}
// cast arrayobj to PhpArray if possible:
return PhpArray.AsPhpArray(arrayobj);
}
[ImplementsFunction("filter_var")]
public static object filter_var(object variable)
{
return filter_var(variable, (int)FilterSanitize.FILTER_DEFAULT, null);
}
[ImplementsFunction("filter_var")]
public static object filter_var(object variable, int filter)
{
return filter_var(variable, filter, null);
}
///
/// Filters a variable with a specified filter.
///
/// Value to filter.
/// The ID of the filter to apply.
/// Associative array of options or bitwise disjunction of flags. If filter accepts options, flags can be provided in "flags" field of array. For the "callback" filter, callback type should be passed. The callback must accept one argument, the value to be filtered, and return the value after filtering/sanitizing it.
/// Returns the filtered data, or false if the filter fails.
[ImplementsFunction("filter_var")]
public static object filter_var(object variable, int filter /*= FILTER_DEFAULT*/ , object options)
{
switch (filter)
{
//
// SANITIZE
//
case (int)FilterSanitize.FILTER_DEFAULT:
return Core.Convert.ObjectToString(variable);
case (int)FilterSanitize.EMAIL:
// Remove all characters except letters, digits and !#$%&'*+-/=?^_`{|}~@.[].
return FilterSanitizeString(PHP.Core.Convert.ObjectToString(variable), (c) =>
(int)c <= 0x7f && (Char.IsLetterOrDigit(c) ||
c == '!' || c == '#' || c == '$' || c == '%' || c == '&' || c == '\'' ||
c == '*' || c == '+' || c == '-' || c == '/' || c == '=' || c == '!' ||
c == '?' || c == '^' || c == '_' || c == '`' || c == '{' || c == '|' ||
c == '}' || c == '~' || c == '@' || c == '.' || c == '[' || c == ']'));
//
// VALIDATE
//
case (int)FilterValidate.EMAIL:
{
var str = PHP.Core.Convert.ObjectToString(variable);
return RegexUtilities.IsValidEmail(str) ? str : (object)false;
}
case (int)FilterValidate.INT:
{
int result;
if (int.TryParse((PhpVariable.AsString(variable) ?? string.Empty).Trim(), out result))
{
if (options != null) PhpException.ArgumentValueNotSupported("options", "!null");
return result; // TODO: options: min_range, max_range
}
else
return false;
}
case (int)FilterValidate.REGEXP:
{
PhpArray optarray;
// options = options['options']['regexp']
if ((optarray = PhpArray.AsPhpArray(options)) != null &&
optarray.TryGetValue("options", out options) && (optarray = PhpArray.AsPhpArray(options)) != null &&
optarray.TryGetValue("regexp", out options))
{
if (PerlRegExp.Match(options, variable) > 0)
return variable;
}
else
PhpException.InvalidArgument("options", LibResources.GetString("option_missing", "regexp"));
return false;
}
default:
PhpException.ArgumentValueNotSupported("filter", filter);
break;
}
return false;
}
#endregion
#region Helper filter methods
private static class RegexUtilities
{
private static readonly Regex ValidEmailRegex = new Regex(
@"^(?("")(""[^""]+?""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,17}))$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static bool IsValidEmail(string strIn)
{
if (String.IsNullOrEmpty(strIn) || strIn.Length > 320)
return false;
// Use IdnMapping class to convert Unicode domain names.
try
{
strIn = Regex.Replace(strIn, @"(@)(.+)$", DomainMapper);
}
catch (ArgumentException)
{
return false;
}
// Return true if strIn is in valid e-mail format.
return ValidEmailRegex.IsMatch(strIn);
}
private static string DomainMapper(Match match)
{
// IdnMapping class with default property values.
var idn = new System.Globalization.IdnMapping();
string domainName = match.Groups[2].Value;
//try
//{
domainName = idn.GetAscii(domainName);
//}
//catch (ArgumentException)
//{
// invalid = true;
//}
return match.Groups[1].Value + domainName;
}
}
///
/// Remove all characters not valid by given .
///
private static string FilterSanitizeString(string str, Predicate/*!*/predicate)
{
Debug.Assert(predicate != null);
// nothing to sanitize:
if (string.IsNullOrEmpty(str)) return string.Empty;
// check if all the characters are valid first:
bool allvalid = true;
foreach (var c in str)
if (!predicate(c))
{
allvalid = false;
break;
}
if (allvalid)
{
return str;
}
else
{
// remove not allowed characters:
StringBuilder newstr = new StringBuilder(str.Length);
foreach (char c in str)
if (predicate(c))
newstr.Append(c);
return newstr.ToString();
}
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Functions.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Reflection;
using System.ComponentModel;
using System.Collections.Generic;
using PHP.Core;
using PHP.Core.Reflection;
using System.Diagnostics;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
///
/// Provides means for PHP functions handling.
///
///
public static class PhpFunctions
{
#region call_user_func, call_user_func_array, create_function
///
/// Calls a function or a method defined by callback with given arguments.
///
/// DTypeDesc of the caller's class context. Can be UnknownTypeDesc.
/// The function or metod designation.
/// The arguments.
/// The return value.
[ImplementsFunction("call_user_func", FunctionImplOptions.NeedsClassContext)]
public static object CallUserFunction(DTypeDesc caller, PhpCallback function, params object[] args)
{
if (function == null)
{
PhpException.ArgumentNull("function");
return null;
}
if (function.IsInvalid) return null;
// invoke the callback:
return PhpVariable.Dereference(function.Invoke(caller, args));
}
///
/// Calls a function or a method defined by callback with arguments stored in an array.
///
/// DTypeDesc of the caller's class context. Can be UnknownTypeDesc.
/// The function or method designation.
/// The arguments. Can be null.
/// The returned value.
[ImplementsFunction("call_user_func_array", FunctionImplOptions.NeedsClassContext)]
public static object CallUserFunctionArray(DTypeDesc caller, PhpCallback function, PhpArray args)
{
object[] args_array;
if (args != null)
{
args_array = new object[args.Count];
args.CopyValuesTo(args_array, 0);
}
else
{
args_array = ArrayUtils.EmptyObjects;
}
return CallUserFunction(caller, function, args_array);
}
///
/// Creates a new lambda function given its arguments and body.
///
/// A source code defining function signature, e.g. "$a,MyClass $b,$c = null".
/// A source code defining function body, e.g. "return $a + $b->x + $c;"
/// A name of the created function.
[ImplementsFunction("create_function", FunctionImplOptions.CaptureEvalInfo /*| FunctionImplOptions.Special*/)]
[PureFunction(typeof(PhpFunctions), "CreateFunction_Analyze")]
public static string CreateFunction(string args, string body)
{
var context = ScriptContext.CurrentContext;
return DynamicCode.CreateLambdaFunction(args, body, context, context.GetCapturedSourceCodeDescriptor());
}
#region analyzer of create_function
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo CreateFunction_Analyze(
Analyzer analyzer,
PHP.Core.AST.CallSignature callSignature,
string args, string body)
{
if (analyzer.IsInsideIncompleteClass())
return null; // in this case, the DirectFnCall will not be Emitted. Therefore the lambda routine will not be declared and compilation will fail when emitting not fully declared lambda FunctionDecl.
// has to be a valid identifier:
// actually this name is never used then
string function_name = "__" + Guid.NewGuid().ToString().Replace('-', '_'); //DynamicCode.GenerateLambdaName(args, body);
string prefix1, prefix2;
DynamicCode.GetLamdaFunctionCodePrefixes(function_name, args, out prefix1, out prefix2);
var pos_args = new PHP.Core.Text.TextSpan(analyzer.SourceUnit.LineBreaks, callSignature.Parameters[0].Span);
var pos_body = new PHP.Core.Text.TextSpan(analyzer.SourceUnit.LineBreaks, callSignature.Parameters[1].Span);
// function __XXXXXX(){}
string fill = GetInlinedLambdaCodeFill(pos_args, pos_body);
string code = String.Concat(prefix2, fill, body, "}");
// parses function source code:
// the position of the first character of the parsed code:
// (note that escaped characters distort position a little bit, which cannot be eliminated so easily)
var counter = new PHP.Core.Parsers.Parser.ReductionsCounter();
var ast = analyzer.BuildAst(pos_args.Start.Position - prefix1.Length + 1, code, counter);
if (ast == null || ast.Statements == null)
return null; // the function cannot be parsed
Debug.Assert(counter.FunctionCount == 1);
var decl_node = (PHP.Core.AST.FunctionDecl)ast.Statements[0];
// adds declaration to the end of the global code statement list:
analyzer.AddLambdaFcnDeclaration(decl_node);
//
return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo()
{
//.inlined = InlinedFunction.CreateFunction;
emitDeclareLamdaFunction = true,
// modify declaration:
newRoutine = Core.Compiler.AST.FunctionDeclCompilerHelper.ConvertToLambda(decl_node, analyzer),
};
}
///
/// Gets a string which is used as a fill in the code to be parsed in order to maintain
/// correct token positioning.
///
/// A position of string literal holding source code for lambda function arguments.
/// A position of string literal holding source code for the body.
/// A string containing spaces and end-of-line characters '\n'.
private static string GetInlinedLambdaCodeFill(PHP.Core.Text.TextSpan args, PHP.Core.Text.TextSpan body)
{
int delta_lines = body.FirstLine - args.LastLine;
if (delta_lines == 0)
{
// ....args.......'_____,_______________'.......body.....
// ...............)_________fill________{................
return new String(' ', body.FirstColumn - args.LastColumn - 1);
}
else
{
// source:
// .....args.....'_____\r\n
// _________,_____\r\n
// ____________'......body.....
// code to parse:
// .....args....'\n
// \n
// ____fill____{.....body......
// the same number of lines as it is in the source file + leading columns:
return new System.Text.StringBuilder(delta_lines + body.FirstColumn).
Append('\n', delta_lines).Append(' ', body.FirstColumn).ToString();
}
}
#endregion
#endregion
#region assert, assert_options
///
/// Assertion options.
///
public enum AssertOption : int
{
[ImplementsConstant("ASSERT_ACTIVE")]
ASSERT_ACTIVE,
[ImplementsConstant("ASSERT_WARNING")]
ASSERT_WARNING,
[ImplementsConstant("ASSERT_BAIL")]
ASSERT_BAIL,
[ImplementsConstant("ASSERT_QUIET_EVAL")]
ASSERT_QUIET_EVAL,
[ImplementsConstant("ASSERT_CALLBACK")]
ASSERT_CALLBACK,
}
[ImplementsFunction("assert", FunctionImplOptions.CaptureEvalInfo /*| FunctionImplOptions.Special*/)]
public static bool Assert(object assertion)
{
return Assert(assertion, null);
}
[ImplementsFunction("assert", FunctionImplOptions.CaptureEvalInfo /*| FunctionImplOptions.Special*/)]
public static bool Assert(object assertion, string description)
{
ScriptContext context = ScriptContext.CurrentContext;
var descriptor = context.GetCapturedSourceCodeDescriptor();
return DynamicCode.CheckAssertion(assertion, null, context, descriptor.ContainingSourcePath, descriptor.Line, descriptor.Column, null);
}
[ImplementsFunction("assert_options", FunctionImplOptions.NotSupported)]
public static object AssertOptions(int what, object value)
{
return value;
}
#endregion
#region func_num_args, func_get_arg, func_get_args
///
/// Retrieves the number of arguments passed to the current user-function.
///
///
[ImplementsFunction("func_num_args", FunctionImplOptions.NeedsFunctionArguments)]
public static int GetArgsNumber()
{
int arg_count, type_arg_count;
return ScriptContext.CurrentContext.Stack.GetArgCount(out arg_count, out type_arg_count) ? arg_count : -1;
}
///
/// Retrieves an argument passed to the current user-function.
///
///
[ImplementsFunction("func_get_arg", FunctionImplOptions.NeedsFunctionArguments)]
[return: PhpDeepCopy]
public static object GetArg(int index)
{
return ScriptContext.CurrentContext.Stack.GetArgument(index);
}
///
/// Returns an array of arguments of the current user-defined function.
///
///
/// Also throws warning if called from global scope.
[ImplementsFunction("func_get_args", FunctionImplOptions.NeedsFunctionArguments)]
[return: PhpDeepCopy]
[return: CastToFalse]
public static PhpArray GetArgs()
{
PhpArray result = ScriptContext.CurrentContext.Stack.GetArguments();
if (result != null)
{
result.InplaceCopyOnReturn = true;
}
return result;
}
#endregion
#region func_num_generic_args, func_get_generic_arg, func_get_generic_args (PHP/CLR)
///
/// Retrieves the number of generic type arguments passed to the current user-function.
///
[ImplementsFunction("func_num_generic_args", FunctionImplOptions.NeedsFunctionArguments)]
public static int GetGenericArgsNumber()
{
int arg_count, type_arg_count;
return ScriptContext.CurrentContext.Stack.GetArgCount(out arg_count, out type_arg_count) ? type_arg_count : -1;
}
///
/// Retrieves a fully qualified name of the generic type argument passed to the current user-function.
///
[ImplementsFunction("func_get_generic_arg", FunctionImplOptions.NeedsFunctionArguments)]
[return: PhpDeepCopy]
public static string GetGenericArg(int index)
{
DTypeDesc type_desc = ScriptContext.CurrentContext.Stack.GetTypeArgument(index);
return (type_desc != null) ? type_desc.MakeFullName() : null;
}
///
/// Returns an array of names of generic type arguments of the current user-defined function.
///
[ImplementsFunction("func_get_generic_args", FunctionImplOptions.NeedsFunctionArguments)]
[return: PhpDeepCopy]
public static PhpArray GetGenericArgs()
{
DTypeDesc[] type_descs = ScriptContext.CurrentContext.Stack.GetTypeArguments();
if (type_descs == null) return null;
PhpArray result = new PhpArray(type_descs.Length, 0);
foreach (DTypeDesc type_desc in type_descs)
result.Add(type_desc.MakeFullName());
result.InplaceCopyOnReturn = true;
return result;
}
#endregion
#region function_exists, get_defined_functions
///
/// Determines whether a function with a specified name exists.
///
/// The name of the function.
/// Wheter the function exists.
/// User functions which are declared conditionally and was not declared yet is considered as not existent.
[ImplementsFunction("function_exists"/*, FunctionImplOptions.Special*/)]
[PureFunction(typeof(PhpFunctions), "Exists_Analyze")]
public static bool Exists(string name)
{
return ScriptContext.CurrentContext.ResolveFunction(name, null, true) != null;
}
#region analyzer of function_exists
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo Exists_Analyze(Analyzer analyzer, string name)
{
QualifiedName? alias;
DRoutine routine = analyzer.SourceUnit.ResolveFunctionName(
new QualifiedName(new Name(name)),
analyzer.CurrentScope,
out alias,
null,
Core.Text.Span.Invalid,
false);
if (routine == null || routine.IsUnknown)
return null; // function is not known at the compilation time. However it can be defined at the runtime (dynamic include, script library, etc).
return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo()
{
value = true // function is definitely known the the compilation time
};
}
#endregion
///
/// Retrieves defined functions.
///
///
/// The containing two entries with keys "internal" and "user".
/// The former's value is a containing PHP library functions as values.
/// The latter's value is a containing user defined functions as values.
/// Keys of both these arrays are integers starting from 0.
///
/// User functions which are declared conditionally and was not declared yet is considered as not existent.
[ImplementsFunction("get_defined_functions")]
public static PhpArray GetDefinedFunctions()
{
PhpArray result = new PhpArray(0, 2);
PhpArray library = new PhpArray(0, 500);
PhpArray user = new PhpArray();
ScriptContext.CurrentContext.GetDeclaredFunctions(user, library);
result["internal"] = library;
result["user"] = user;
return result;
}
#endregion
#region register_shutdown_function
///
/// Registers callback which will be called when script processing is complete but before the request
/// has been complete.
/// Function has no return value.
///
/// The function which is called after main code of the script is finishes execution.
/// Parameters for the function.
///
/// Although, there is explicitly written in the PHP manual that it is not possible
/// to send an output to a browser via echo or another output handling functions you can actually do so.
/// There is no such limitation with Phalanger.
///
[ImplementsFunction("register_shutdown_function")]
public static void RegisterShutdownFunction(PhpCallback/*!*/ function, params object[] parameters)
{
if (function == null)
{
PhpException.ArgumentNull("function");
return;
}
ScriptContext.CurrentContext.RegisterShutdownCallback(function, parameters);
}
#endregion
#region NS: register_tick_function, unregister_tick_function
///
/// Not supported.
///
[ImplementsFunction("register_tick_function", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static void RegisterTickFunction(PhpCallback function)
{
PhpException.FunctionNotSupported();
}
///
/// Not supported.
///
[ImplementsFunction("register_tick_function", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static void RegisterTickFunction(PhpCallback function, object arg)
{
PhpException.FunctionNotSupported();
}
///
/// Not supported.
///
[ImplementsFunction("unregister_tick_function", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static void UnregisterTickFunction(PhpCallback function)
{
PhpException.FunctionNotSupported();
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Generated/StrToTimeScanner.cs
================================================
namespace PHP.Library.StrToTime
{
#region User Code
using System;
using System.Collections.Generic;
/*
Copyright (c) 2005-2006 Tomas Matousek. Based on PHP5 implementation by Derick Rethans .
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
#endregion
internal class Scanner
{
public enum LexicalStates
{
YYINITIAL = 0,
}
[Flags]
private enum AcceptConditions : byte
{
NotAccept = 0,
AcceptOnStart = 1,
AcceptOnEnd = 2,
Accept = 4
}
private const int NoState = -1;
private const char BOL = (char)128;
private const char EOF = (char)129;
private Tokens yyreturn;
internal DateInfo Time { get { return time; } }
private DateInfo time = new DateInfo();
internal int Errors { get { return errors; } }
private int errors = 0;
internal int Position { get { return pos; } }
private int pos = 0;
private string str;
void INIT()
{
str = new string(buffer, token_start, token_end - token_start);
pos = 0;
}
void DEINIT()
{
}
private System.IO.TextReader reader;
private char[] buffer = new char[512];
// whether the currently parsed token is being expanded (yymore has been called):
private bool expanding_token;
// offset in buffer where the currently parsed token starts:
private int token_start;
// offset in buffer where the currently parsed token chunk starts:
private int token_chunk_start;
// offset in buffer one char behind the currently parsed token (chunk) ending character:
private int token_end;
// offset of the lookahead character (number of characters parsed):
private int lookahead_index;
// number of characters read into the buffer:
private int chars_read;
private bool yy_at_bol = false;
public LexicalStates CurrentLexicalState { get { return current_lexical_state; } set { current_lexical_state = value; } }
private LexicalStates current_lexical_state;
public Scanner(System.IO.TextReader reader)
{
Initialize(reader, LexicalStates.YYINITIAL);
}
public void Initialize(System.IO.TextReader reader, LexicalStates lexicalState, bool atBol)
{
this.expanding_token = false;
this.token_start = 0;
this.chars_read = 0;
this.lookahead_index = 0;
this.token_chunk_start = 0;
this.token_end = 0;
this.reader = reader;
this.yy_at_bol = atBol;
this.current_lexical_state = lexicalState;
}
public void Initialize(System.IO.TextReader reader, LexicalStates lexicalState)
{
Initialize(reader, lexicalState, false);
}
#region Accept
#pragma warning disable 162
Tokens Accept0(int state,out bool accepted)
{
accepted = true;
switch(state)
{
case 1:
// #line 698
{
break;
}
break;
case 2:
// #line 702
{
return Tokens.ERROR;
}
break;
case 3:
// #line 644
{
INIT();
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.TIMEZONE;
}
break;
case 4:
// #line 435
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DateInfo.SkipDaySuffix(str, ref pos);
time.m = DateInfo.ParseMonth(str, ref pos);
DEINIT();
return Tokens.DATE_TEXT;
}
break;
case 5:
// #line 198
{
INIT();
time.HAVE_RELATIVE();
time.UNHAVE_DATE();
time.UNHAVE_TIME();
int i = DateInfo.ParseSignedInt(str, ref pos, 24);
time.y = 1970;
time.m = 1;
time.d = 1;
time.h = time.i = time.s = 0;
time.f = 0.0;
time.relative.s += i;
time.z = 0;
time.HAVE_TZ();
DEINIT();
return Tokens.RELATIVE;
}
break;
case 6:
// #line 421
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_TEXT;
}
break;
case 7:
// #line 243
{
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && (str[pos] == ':' || str[pos] == '.'))
{
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '.')
time.f = DateInfo.ParseFraction(str, ref pos, 8);
}
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.TIME24_WITH_ZONE;
}
break;
case 8:
// #line 306
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '/')
{
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
}
DEINIT();
return Tokens.AMERICAN;
}
break;
case 9:
// #line 336
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR;}
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DateInfo.SkipDaySuffix(str, ref pos);
time.m = DateInfo.ParseMonth(str, ref pos);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_FULL;
}
break;
case 10:
// #line 219
{
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && (str[pos] == ':' || str[pos] == '.'))
{
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && (str[pos] == ':' || str[pos] == '.'))
{
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
}
}
if (!time.SetMeridian(str, ref pos))
{
return Tokens.ERROR;
}
DEINIT();
return Tokens.TIME12;
}
break;
case 11:
// #line 597
{
INIT();
time.relative.y = -time.relative.y;
time.relative.m = -time.relative.m;
time.relative.d = -time.relative.d;
time.relative.h = -time.relative.h;
time.relative.i = -time.relative.i;
time.relative.s = -time.relative.s;
time.relative.weekday = -time.relative.weekday;
DEINIT();
return Tokens.AGO;
}
break;
case 12:
// #line 630
{
INIT();
time.HAVE_RELATIVE();
time.HAVE_WEEKDAY_RELATIVE();
time.UNHAVE_TIME();
time.SetWeekDay(DateInfo.ReadToSpace(str,ref pos));
time.relative.weekday_behavior = 1;
DEINIT();
return Tokens.WEEKDAY;
}
break;
case 13:
// #line 163
{
INIT();
DEINIT();
return Tokens.RELATIVE;
}
break;
case 14:
// #line 266
{
INIT();
switch (time.have_time)
{
case 0:
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = 0;
break;
case 1:
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
break;
default:
DEINIT();
return Tokens.ERROR;
}
time.have_time++;
DEINIT();
return Tokens.GNU_NOCOLON;
}
break;
case 15:
// #line 588
{
INIT();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
DEINIT();
return Tokens.CLF;
}
break;
case 16:
// #line 682
{
INIT();
time.HAVE_RELATIVE();
while(pos < str.Length)
{
int amount = DateInfo.ParseSignedInt(str, ref pos, 24);
while (pos < str.Length && str[pos] == ' ') pos++;
time.SetRelative(DateInfo.ReadToSpace(str, ref pos), amount, 0);
}
DEINIT();
return Tokens.RELATIVE;
}
break;
case 17:
// #line 170
{
INIT();
time.UNHAVE_TIME();
time.HAVE_TIME();
time.h = 12;
DEINIT();
return Tokens.RELATIVE;
}
break;
case 18:
// #line 351
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.ISO_DATE;
}
break;
case 19:
// #line 406
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = 1;
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_NO_DAY;
}
break;
case 20:
// #line 392
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.d = 1;
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_NO_DAY;
}
break;
case 21:
// #line 653
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == ':')
{
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '.')
time.f = DateInfo.ParseFraction(str, ref pos, 8);
}
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.SHORTDATE_WITH_TIME;
}
break;
case 22:
// #line 180
{
INIT();
time.UNHAVE_TIME();
DEINIT();
return Tokens.RELATIVE;
}
break;
case 23:
// #line 378
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR;}
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_FULL_POINTED;
}
break;
case 24:
// #line 290
{
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.ISO_NOCOLON;
}
break;
case 25:
// #line 486
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 3);
time.m = 1;
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.PG_YEARDAY;
}
break;
case 26:
// #line 519
{
{
int w, d;
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.HAVE_RELATIVE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
w = DateInfo.ParseUnsignedInt(str, ref pos, 2);
d = 1;
time.m = 1;
time.d = 1;
time.relative.d = DateInfo.WeekToDay(time.y, w, d);
DEINIT();
return Tokens.ISO_WEEK;
}
}
break;
case 27:
// #line 612
{
INIT();
time.HAVE_RELATIVE();
while (pos < str.Length)
{
int behavior;
int amount = DateInfo.ParseRelativeText(str, ref pos, out behavior);
while (pos < str.Length && str[pos] == ' ') pos++;
time.SetRelative(DateInfo.ReadToSpace(str,ref pos), amount, behavior);
}
DEINIT();
return Tokens.RELATIVE;
}
break;
case 28:
// #line 365
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR;}
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
DEINIT();
return Tokens.DATE_FULL_POINTED;
}
break;
case 29:
// #line 448
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DEINIT();
return Tokens.DATE_NOCOLON;
}
break;
case 30:
// #line 500
{
int week, day;
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.HAVE_RELATIVE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
week = DateInfo.ParseUnsignedInt(str, ref pos, 2);
day = DateInfo.ParseUnsignedInt(str, ref pos, 1);
time.m = 1;
time.d = 1;
time.relative.d = DateInfo.WeekToDay(time.y, week, day);
DEINIT();
return Tokens.ISO_WEEK;
}
break;
case 31:
// #line 540
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.PG_TEXT;
}
break;
case 32:
// #line 188
{
INIT();
time.HAVE_RELATIVE();
time.UNHAVE_TIME();
time.relative.d = 1;
DEINIT();
return Tokens.RELATIVE;
}
break;
case 33:
// #line 554
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.PG_TEXT;
}
break;
case 34:
// #line 153
{
INIT();
time.HAVE_RELATIVE();
time.UNHAVE_TIME();
time.relative.d = -1;
DEINIT();
return Tokens.RELATIVE;
}
break;
case 35:
// #line 323
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DEINIT();
return Tokens.ISO_DATE;
}
break;
case 36:
// #line 461
{
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '.')
{
time.f = DateInfo.ParseFraction(str, ref pos, 9);
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
}
DEINIT();
return Tokens.XMLRPC_SOAP;
}
break;
case 37:
// #line 568
{
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.m = DateInfo.ParseMonth(str, ref pos);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.CLF;
}
break;
case 39: goto case 1;
case 40: goto case 2;
case 41: goto case 3;
case 42: goto case 4;
case 43: goto case 6;
case 44: goto case 7;
case 45: goto case 8;
case 46: goto case 9;
case 47: goto case 10;
case 48: goto case 12;
case 49: goto case 16;
case 50: goto case 18;
case 51: goto case 19;
case 52: goto case 20;
case 53: goto case 21;
case 54: goto case 24;
case 55: goto case 25;
case 56: goto case 27;
case 57: goto case 31;
case 58: goto case 35;
case 59: goto case 36;
case 60: goto case 37;
case 62: goto case 2;
case 63: goto case 3;
case 64: goto case 4;
case 65: goto case 6;
case 66: goto case 7;
case 67: goto case 8;
case 68: goto case 10;
case 69: goto case 16;
case 70: goto case 18;
case 71: goto case 19;
case 72: goto case 21;
case 73: goto case 24;
case 74: goto case 25;
case 75: goto case 27;
case 76: goto case 35;
case 77: goto case 36;
case 78: goto case 37;
case 80: goto case 2;
case 81: goto case 3;
case 82: goto case 4;
case 83: goto case 6;
case 84: goto case 7;
case 85: goto case 8;
case 86: goto case 10;
case 87: goto case 16;
case 88: goto case 18;
case 89: goto case 19;
case 90: goto case 21;
case 91: goto case 24;
case 92: goto case 25;
case 93: goto case 27;
case 94: goto case 36;
case 96: goto case 2;
case 97: goto case 3;
case 98: goto case 4;
case 99: goto case 6;
case 100: goto case 7;
case 101: goto case 8;
case 102: goto case 16;
case 103: goto case 18;
case 104: goto case 19;
case 105: goto case 21;
case 106: goto case 24;
case 107: goto case 25;
case 108: goto case 27;
case 109: goto case 36;
case 111: goto case 2;
case 112: goto case 3;
case 113: goto case 4;
case 114: goto case 6;
case 115: goto case 7;
case 116: goto case 8;
case 117: goto case 16;
case 118: goto case 18;
case 119: goto case 19;
case 120: goto case 21;
case 121: goto case 27;
case 122: goto case 36;
case 124: goto case 3;
case 125: goto case 4;
case 126: goto case 6;
case 127: goto case 7;
case 128: goto case 16;
case 129: goto case 18;
case 130: goto case 19;
case 131: goto case 21;
case 132: goto case 27;
case 133: goto case 36;
case 135: goto case 3;
case 136: goto case 4;
case 137: goto case 6;
case 138: goto case 7;
case 139: goto case 16;
case 140: goto case 18;
case 141: goto case 19;
case 142: goto case 21;
case 143: goto case 27;
case 144: goto case 36;
case 146: goto case 3;
case 147: goto case 4;
case 148: goto case 6;
case 149: goto case 7;
case 150: goto case 16;
case 151: goto case 18;
case 152: goto case 19;
case 153: goto case 21;
case 154: goto case 27;
case 155: goto case 36;
case 157: goto case 3;
case 158: goto case 4;
case 159: goto case 6;
case 160: goto case 7;
case 161: goto case 16;
case 162: goto case 18;
case 163: goto case 19;
case 164: goto case 21;
case 165: goto case 27;
case 166: goto case 36;
case 168: goto case 3;
case 169: goto case 4;
case 170: goto case 6;
case 171: goto case 7;
case 172: goto case 18;
case 173: goto case 19;
case 174: goto case 21;
case 175: goto case 27;
case 176: goto case 36;
case 178: goto case 3;
case 179: goto case 4;
case 180: goto case 6;
case 181: goto case 7;
case 182: goto case 18;
case 183: goto case 19;
case 184: goto case 21;
case 185: goto case 27;
case 186: goto case 36;
case 188: goto case 3;
case 189: goto case 6;
case 190: goto case 7;
case 191: goto case 18;
case 192: goto case 19;
case 193: goto case 21;
case 195: goto case 3;
case 196: goto case 6;
case 197: goto case 7;
case 198: goto case 19;
case 199: goto case 21;
case 201: goto case 3;
case 202: goto case 6;
case 203: goto case 7;
case 204: goto case 19;
case 205: goto case 21;
case 207: goto case 3;
case 208: goto case 6;
case 209: goto case 7;
case 210: goto case 19;
case 211: goto case 21;
case 213: goto case 3;
case 214: goto case 6;
case 215: goto case 7;
case 216: goto case 19;
case 217: goto case 21;
case 219: goto case 3;
case 220: goto case 6;
case 221: goto case 7;
case 222: goto case 19;
case 223: goto case 21;
case 225: goto case 3;
case 226: goto case 6;
case 227: goto case 7;
case 228: goto case 19;
case 229: goto case 21;
case 231: goto case 3;
case 232: goto case 6;
case 233: goto case 7;
case 234: goto case 19;
case 235: goto case 21;
case 237: goto case 3;
case 238: goto case 6;
case 239: goto case 7;
case 240: goto case 19;
case 241: goto case 21;
case 243: goto case 3;
case 244: goto case 7;
case 245: goto case 19;
case 246: goto case 21;
case 248: goto case 3;
case 249: goto case 7;
case 250: goto case 21;
case 252: goto case 3;
case 253: goto case 7;
case 254: goto case 21;
case 256: goto case 3;
case 257: goto case 7;
case 258: goto case 21;
case 260: goto case 3;
case 261: goto case 7;
case 262: goto case 21;
case 264: goto case 3;
case 265: goto case 7;
case 267: goto case 3;
case 268: goto case 7;
case 270: goto case 7;
case 272: goto case 7;
case 274: goto case 7;
case 276: goto case 7;
case 278: goto case 7;
case 280: goto case 7;
case 282: goto case 7;
case 284: goto case 7;
case 623: goto case 3;
case 624: goto case 6;
case 625: goto case 9;
case 626: goto case 31;
case 627: goto case 37;
case 628: goto case 3;
case 629: goto case 4;
case 630: goto case 7;
case 631: goto case 19;
case 632: goto case 20;
case 633: goto case 27;
case 634: goto case 37;
case 636: goto case 3;
case 637: goto case 10;
case 638: goto case 18;
case 639: goto case 21;
case 640: goto case 7;
case 641: goto case 8;
case 642: goto case 2;
case 643: goto case 3;
case 644: goto case 4;
case 645: goto case 7;
case 646: goto case 19;
case 647: goto case 4;
case 648: goto case 6;
case 649: goto case 7;
case 650: goto case 18;
case 651: goto case 19;
case 652: goto case 21;
case 653: goto case 7;
case 654: goto case 21;
case 655: goto case 7;
case 656: goto case 21;
case 657: goto case 6;
case 658: goto case 7;
case 660: goto case 7;
case 661: goto case 21;
case 663: goto case 7;
case 664: goto case 19;
case 665: goto case 21;
case 667: goto case 7;
case 668: goto case 19;
case 669: goto case 3;
case 670: goto case 6;
case 671: goto case 21;
case 673: goto case 7;
case 674: goto case 6;
case 675: goto case 3;
case 676: goto case 21;
case 679: goto case 3;
case 680: goto case 3;
case 681: goto case 21;
case 682: goto case 7;
case 683: goto case 7;
case 731: goto case 3;
case 732: goto case 6;
case 733: goto case 9;
case 734: goto case 37;
case 735: goto case 7;
case 737: goto case 3;
case 738: goto case 2;
case 739: goto case 3;
case 740: goto case 6;
case 741: goto case 7;
case 742: goto case 21;
case 743: goto case 21;
case 744: goto case 7;
case 746: goto case 7;
case 747: goto case 21;
case 748: goto case 7;
case 749: goto case 6;
case 750: goto case 3;
case 752: goto case 3;
case 765: goto case 3;
case 766: goto case 6;
case 768: goto case 2;
case 769: goto case 3;
case 770: goto case 6;
case 771: goto case 7;
case 772: goto case 21;
case 773: goto case 21;
case 774: goto case 7;
case 775: goto case 7;
case 776: goto case 21;
case 777: goto case 7;
case 778: goto case 3;
case 780: goto case 3;
case 785: goto case 3;
case 787: goto case 3;
case 788: goto case 6;
case 789: goto case 21;
case 790: goto case 7;
case 791: goto case 7;
case 792: goto case 3;
case 794: goto case 3;
case 798: goto case 3;
case 799: goto case 3;
case 800: goto case 6;
case 801: goto case 7;
case 802: goto case 3;
case 804: goto case 3;
case 808: goto case 3;
case 809: goto case 3;
case 810: goto case 7;
case 812: goto case 3;
case 815: goto case 3;
case 816: goto case 3;
case 820: goto case 3;
case 821: goto case 3;
case 824: goto case 3;
case 825: goto case 3;
case 828: goto case 3;
case 829: goto case 3;
case 832: goto case 3;
case 833: goto case 3;
case 836: goto case 3;
case 839: goto case 3;
case 841: goto case 3;
case 843: goto case 3;
case 845: goto case 3;
case 853: goto case 7;
case 854: goto case 9;
case 855: goto case 12;
case 856: goto case 27;
case 857: goto case 31;
case 858: goto case 4;
case 859: goto case 7;
case 860: goto case 19;
case 861: goto case 27;
case 862: goto case 7;
case 863: goto case 8;
case 864: goto case 3;
case 865: goto case 3;
case 866: goto case 7;
case 867: goto case 21;
case 868: goto case 21;
case 869: goto case 7;
case 870: goto case 6;
case 871: goto case 7;
case 872: goto case 3;
case 873: goto case 3;
case 879: goto case 3;
case 880: goto case 3;
case 881: goto case 4;
case 882: goto case 4;
case 883: goto case 3;
case 884: goto case 7;
case 885: goto case 9;
case 886: goto case 12;
case 887: goto case 27;
case 888: goto case 27;
case 889: goto case 7;
case 890: goto case 3;
case 891: goto case 6;
case 892: goto case 3;
case 893: goto case 3;
case 896: goto case 3;
case 897: goto case 3;
case 898: goto case 9;
case 899: goto case 3;
case 900: goto case 3;
case 901: goto case 3;
case 904: goto case 9;
case 905: goto case 3;
case 906: goto case 3;
case 908: goto case 3;
case 910: goto case 3;
case 912: goto case 3;
case 919: goto case 4;
case 920: goto case 4;
case 921: goto case 3;
case 922: goto case 4;
case 923: goto case 4;
case 924: goto case 4;
case 925: goto case 4;
case 926: goto case 4;
case 927: goto case 4;
case 928: goto case 4;
case 929: goto case 4;
case 930: goto case 3;
case 947: goto case 3;
case 948: goto case 12;
case 949: goto case 27;
case 950: goto case 3;
case 952: goto case 3;
case 954: goto case 3;
case 955: goto case 12;
case 956: goto case 27;
case 957: goto case 3;
case 958: goto case 3;
case 960: goto case 3;
case 961: goto case 3;
case 963: goto case 3;
case 964: goto case 3;
case 966: goto case 3;
case 968: goto case 3;
case 970: goto case 3;
case 973: goto case 3;
case 977: goto case 3;
case 979: goto case 3;
case 980: goto case 3;
case 981: goto case 27;
case 982: goto case 3;
case 983: goto case 3;
case 985: goto case 3;
case 986: goto case 3;
case 987: goto case 3;
case 989: goto case 3;
case 991: goto case 3;
case 992: goto case 3;
case 993: goto case 3;
case 995: goto case 3;
case 996: goto case 3;
case 997: goto case 3;
case 998: goto case 3;
case 999: goto case 3;
}
accepted = false;
return yyreturn;
}
#pragma warning restore 162
#endregion
private void BEGIN(LexicalStates state)
{
current_lexical_state = state;
}
private char Advance()
{
if (lookahead_index >= chars_read)
{
if (token_start > 0)
{
// shift buffer left:
int length = chars_read - token_start;
System.Buffer.BlockCopy(buffer, token_start << 1, buffer, 0, length << 1);
token_end -= token_start;
token_chunk_start -= token_start;
token_start = 0;
chars_read = lookahead_index = length;
// populate the remaining bytes:
int count = reader.Read(buffer, chars_read, buffer.Length - chars_read);
if (count <= 0) return EOF;
chars_read += count;
}
while (lookahead_index >= chars_read)
{
if (lookahead_index >= buffer.Length)
buffer = ResizeBuffer(buffer);
int count = reader.Read(buffer, chars_read, buffer.Length - chars_read);
if (count <= 0) return EOF;
chars_read += count;
}
}
return buffer[lookahead_index++];
}
private char[] ResizeBuffer(char[] buf)
{
char[] result = new char[buf.Length << 1];
System.Buffer.BlockCopy(buf, 0, result, 0, buf.Length << 1);
return result;
}
protected static bool IsNewLineCharacter(char ch)
{
return ch == '\r' || ch == '\n' || ch == (char)0x2028 || ch == (char)0x2029;
}
private void TrimTokenEnd()
{
if (token_end > token_chunk_start && buffer[token_end - 1] == '\n')
token_end--;
if (token_end > token_chunk_start && buffer[token_end - 1] == '\r')
token_end--;
}
private void MarkTokenChunkStart()
{
token_chunk_start = lookahead_index;
}
private void MarkTokenEnd()
{
token_end = lookahead_index;
}
private void MoveToTokenEnd()
{
lookahead_index = token_end;
yy_at_bol = (token_end > token_chunk_start) && (buffer[token_end - 1] == '\r' || buffer[token_end - 1] == '\n');
}
public int TokenLength
{
get { return token_end - token_start; }
}
public int TokenChunkLength
{
get { return token_end - token_chunk_start; }
}
private void yymore()
{
if (!expanding_token)
{
token_start = token_chunk_start;
expanding_token = true;
}
}
private void yyless(int count)
{
lookahead_index = token_end = token_chunk_start + count;
}
private Stack stateStack = new Stack(20);
private void yy_push_state(LexicalStates state)
{
stateStack.Push(current_lexical_state);
current_lexical_state = state;
}
private bool yy_pop_state()
{
if (stateStack.Count == 0) return false;
current_lexical_state = stateStack.Pop();
return true;
}
private LexicalStates yy_top_state()
{
return stateStack.Peek();
}
#region Tables
private static AcceptConditions[] acceptCondition = new AcceptConditions[]
{
AcceptConditions.NotAccept, // 0
AcceptConditions.Accept, // 1
AcceptConditions.Accept, // 2
AcceptConditions.Accept, // 3
AcceptConditions.Accept, // 4
AcceptConditions.Accept, // 5
AcceptConditions.Accept, // 6
AcceptConditions.Accept, // 7
AcceptConditions.Accept, // 8
AcceptConditions.Accept, // 9
AcceptConditions.Accept, // 10
AcceptConditions.Accept, // 11
AcceptConditions.Accept, // 12
AcceptConditions.Accept, // 13
AcceptConditions.Accept, // 14
AcceptConditions.Accept, // 15
AcceptConditions.Accept, // 16
AcceptConditions.Accept, // 17
AcceptConditions.Accept, // 18
AcceptConditions.Accept, // 19
AcceptConditions.Accept, // 20
AcceptConditions.Accept, // 21
AcceptConditions.Accept, // 22
AcceptConditions.Accept, // 23
AcceptConditions.Accept, // 24
AcceptConditions.Accept, // 25
AcceptConditions.Accept, // 26
AcceptConditions.Accept, // 27
AcceptConditions.Accept, // 28
AcceptConditions.Accept, // 29
AcceptConditions.Accept, // 30
AcceptConditions.Accept, // 31
AcceptConditions.Accept, // 32
AcceptConditions.Accept, // 33
AcceptConditions.Accept, // 34
AcceptConditions.Accept, // 35
AcceptConditions.Accept, // 36
AcceptConditions.Accept, // 37
AcceptConditions.NotAccept, // 38
AcceptConditions.Accept, // 39
AcceptConditions.Accept, // 40
AcceptConditions.Accept, // 41
AcceptConditions.Accept, // 42
AcceptConditions.Accept, // 43
AcceptConditions.Accept, // 44
AcceptConditions.Accept, // 45
AcceptConditions.Accept, // 46
AcceptConditions.Accept, // 47
AcceptConditions.Accept, // 48
AcceptConditions.Accept, // 49
AcceptConditions.Accept, // 50
AcceptConditions.Accept, // 51
AcceptConditions.Accept, // 52
AcceptConditions.Accept, // 53
AcceptConditions.Accept, // 54
AcceptConditions.Accept, // 55
AcceptConditions.Accept, // 56
AcceptConditions.Accept, // 57
AcceptConditions.Accept, // 58
AcceptConditions.Accept, // 59
AcceptConditions.Accept, // 60
AcceptConditions.NotAccept, // 61
AcceptConditions.Accept, // 62
AcceptConditions.Accept, // 63
AcceptConditions.Accept, // 64
AcceptConditions.Accept, // 65
AcceptConditions.Accept, // 66
AcceptConditions.Accept, // 67
AcceptConditions.Accept, // 68
AcceptConditions.Accept, // 69
AcceptConditions.Accept, // 70
AcceptConditions.Accept, // 71
AcceptConditions.Accept, // 72
AcceptConditions.Accept, // 73
AcceptConditions.Accept, // 74
AcceptConditions.Accept, // 75
AcceptConditions.Accept, // 76
AcceptConditions.Accept, // 77
AcceptConditions.Accept, // 78
AcceptConditions.NotAccept, // 79
AcceptConditions.Accept, // 80
AcceptConditions.Accept, // 81
AcceptConditions.Accept, // 82
AcceptConditions.Accept, // 83
AcceptConditions.Accept, // 84
AcceptConditions.Accept, // 85
AcceptConditions.Accept, // 86
AcceptConditions.Accept, // 87
AcceptConditions.Accept, // 88
AcceptConditions.Accept, // 89
AcceptConditions.Accept, // 90
AcceptConditions.Accept, // 91
AcceptConditions.Accept, // 92
AcceptConditions.Accept, // 93
AcceptConditions.Accept, // 94
AcceptConditions.NotAccept, // 95
AcceptConditions.Accept, // 96
AcceptConditions.Accept, // 97
AcceptConditions.Accept, // 98
AcceptConditions.Accept, // 99
AcceptConditions.Accept, // 100
AcceptConditions.Accept, // 101
AcceptConditions.Accept, // 102
AcceptConditions.Accept, // 103
AcceptConditions.Accept, // 104
AcceptConditions.Accept, // 105
AcceptConditions.Accept, // 106
AcceptConditions.Accept, // 107
AcceptConditions.Accept, // 108
AcceptConditions.Accept, // 109
AcceptConditions.NotAccept, // 110
AcceptConditions.Accept, // 111
AcceptConditions.Accept, // 112
AcceptConditions.Accept, // 113
AcceptConditions.Accept, // 114
AcceptConditions.Accept, // 115
AcceptConditions.Accept, // 116
AcceptConditions.Accept, // 117
AcceptConditions.Accept, // 118
AcceptConditions.Accept, // 119
AcceptConditions.Accept, // 120
AcceptConditions.Accept, // 121
AcceptConditions.Accept, // 122
AcceptConditions.NotAccept, // 123
AcceptConditions.Accept, // 124
AcceptConditions.Accept, // 125
AcceptConditions.Accept, // 126
AcceptConditions.Accept, // 127
AcceptConditions.Accept, // 128
AcceptConditions.Accept, // 129
AcceptConditions.Accept, // 130
AcceptConditions.Accept, // 131
AcceptConditions.Accept, // 132
AcceptConditions.Accept, // 133
AcceptConditions.NotAccept, // 134
AcceptConditions.Accept, // 135
AcceptConditions.Accept, // 136
AcceptConditions.Accept, // 137
AcceptConditions.Accept, // 138
AcceptConditions.Accept, // 139
AcceptConditions.Accept, // 140
AcceptConditions.Accept, // 141
AcceptConditions.Accept, // 142
AcceptConditions.Accept, // 143
AcceptConditions.Accept, // 144
AcceptConditions.NotAccept, // 145
AcceptConditions.Accept, // 146
AcceptConditions.Accept, // 147
AcceptConditions.Accept, // 148
AcceptConditions.Accept, // 149
AcceptConditions.Accept, // 150
AcceptConditions.Accept, // 151
AcceptConditions.Accept, // 152
AcceptConditions.Accept, // 153
AcceptConditions.Accept, // 154
AcceptConditions.Accept, // 155
AcceptConditions.NotAccept, // 156
AcceptConditions.Accept, // 157
AcceptConditions.Accept, // 158
AcceptConditions.Accept, // 159
AcceptConditions.Accept, // 160
AcceptConditions.Accept, // 161
AcceptConditions.Accept, // 162
AcceptConditions.Accept, // 163
AcceptConditions.Accept, // 164
AcceptConditions.Accept, // 165
AcceptConditions.Accept, // 166
AcceptConditions.NotAccept, // 167
AcceptConditions.Accept, // 168
AcceptConditions.Accept, // 169
AcceptConditions.Accept, // 170
AcceptConditions.Accept, // 171
AcceptConditions.Accept, // 172
AcceptConditions.Accept, // 173
AcceptConditions.Accept, // 174
AcceptConditions.Accept, // 175
AcceptConditions.Accept, // 176
AcceptConditions.NotAccept, // 177
AcceptConditions.Accept, // 178
AcceptConditions.Accept, // 179
AcceptConditions.Accept, // 180
AcceptConditions.Accept, // 181
AcceptConditions.Accept, // 182
AcceptConditions.Accept, // 183
AcceptConditions.Accept, // 184
AcceptConditions.Accept, // 185
AcceptConditions.Accept, // 186
AcceptConditions.NotAccept, // 187
AcceptConditions.Accept, // 188
AcceptConditions.Accept, // 189
AcceptConditions.Accept, // 190
AcceptConditions.Accept, // 191
AcceptConditions.Accept, // 192
AcceptConditions.Accept, // 193
AcceptConditions.NotAccept, // 194
AcceptConditions.Accept, // 195
AcceptConditions.Accept, // 196
AcceptConditions.Accept, // 197
AcceptConditions.Accept, // 198
AcceptConditions.Accept, // 199
AcceptConditions.NotAccept, // 200
AcceptConditions.Accept, // 201
AcceptConditions.Accept, // 202
AcceptConditions.Accept, // 203
AcceptConditions.Accept, // 204
AcceptConditions.Accept, // 205
AcceptConditions.NotAccept, // 206
AcceptConditions.Accept, // 207
AcceptConditions.Accept, // 208
AcceptConditions.Accept, // 209
AcceptConditions.Accept, // 210
AcceptConditions.Accept, // 211
AcceptConditions.NotAccept, // 212
AcceptConditions.Accept, // 213
AcceptConditions.Accept, // 214
AcceptConditions.Accept, // 215
AcceptConditions.Accept, // 216
AcceptConditions.Accept, // 217
AcceptConditions.NotAccept, // 218
AcceptConditions.Accept, // 219
AcceptConditions.Accept, // 220
AcceptConditions.Accept, // 221
AcceptConditions.Accept, // 222
AcceptConditions.Accept, // 223
AcceptConditions.NotAccept, // 224
AcceptConditions.Accept, // 225
AcceptConditions.Accept, // 226
AcceptConditions.Accept, // 227
AcceptConditions.Accept, // 228
AcceptConditions.Accept, // 229
AcceptConditions.NotAccept, // 230
AcceptConditions.Accept, // 231
AcceptConditions.Accept, // 232
AcceptConditions.Accept, // 233
AcceptConditions.Accept, // 234
AcceptConditions.Accept, // 235
AcceptConditions.NotAccept, // 236
AcceptConditions.Accept, // 237
AcceptConditions.Accept, // 238
AcceptConditions.Accept, // 239
AcceptConditions.Accept, // 240
AcceptConditions.Accept, // 241
AcceptConditions.NotAccept, // 242
AcceptConditions.Accept, // 243
AcceptConditions.Accept, // 244
AcceptConditions.Accept, // 245
AcceptConditions.Accept, // 246
AcceptConditions.NotAccept, // 247
AcceptConditions.Accept, // 248
AcceptConditions.Accept, // 249
AcceptConditions.Accept, // 250
AcceptConditions.NotAccept, // 251
AcceptConditions.Accept, // 252
AcceptConditions.Accept, // 253
AcceptConditions.Accept, // 254
AcceptConditions.NotAccept, // 255
AcceptConditions.Accept, // 256
AcceptConditions.Accept, // 257
AcceptConditions.Accept, // 258
AcceptConditions.NotAccept, // 259
AcceptConditions.Accept, // 260
AcceptConditions.Accept, // 261
AcceptConditions.Accept, // 262
AcceptConditions.NotAccept, // 263
AcceptConditions.Accept, // 264
AcceptConditions.Accept, // 265
AcceptConditions.NotAccept, // 266
AcceptConditions.Accept, // 267
AcceptConditions.Accept, // 268
AcceptConditions.NotAccept, // 269
AcceptConditions.Accept, // 270
AcceptConditions.NotAccept, // 271
AcceptConditions.Accept, // 272
AcceptConditions.NotAccept, // 273
AcceptConditions.Accept, // 274
AcceptConditions.NotAccept, // 275
AcceptConditions.Accept, // 276
AcceptConditions.NotAccept, // 277
AcceptConditions.Accept, // 278
AcceptConditions.NotAccept, // 279
AcceptConditions.Accept, // 280
AcceptConditions.NotAccept, // 281
AcceptConditions.Accept, // 282
AcceptConditions.NotAccept, // 283
AcceptConditions.Accept, // 284
AcceptConditions.NotAccept, // 285
AcceptConditions.NotAccept, // 286
AcceptConditions.NotAccept, // 287
AcceptConditions.NotAccept, // 288
AcceptConditions.NotAccept, // 289
AcceptConditions.NotAccept, // 290
AcceptConditions.NotAccept, // 291
AcceptConditions.NotAccept, // 292
AcceptConditions.NotAccept, // 293
AcceptConditions.NotAccept, // 294
AcceptConditions.NotAccept, // 295
AcceptConditions.NotAccept, // 296
AcceptConditions.NotAccept, // 297
AcceptConditions.NotAccept, // 298
AcceptConditions.NotAccept, // 299
AcceptConditions.NotAccept, // 300
AcceptConditions.NotAccept, // 301
AcceptConditions.NotAccept, // 302
AcceptConditions.NotAccept, // 303
AcceptConditions.NotAccept, // 304
AcceptConditions.NotAccept, // 305
AcceptConditions.NotAccept, // 306
AcceptConditions.NotAccept, // 307
AcceptConditions.NotAccept, // 308
AcceptConditions.NotAccept, // 309
AcceptConditions.NotAccept, // 310
AcceptConditions.NotAccept, // 311
AcceptConditions.NotAccept, // 312
AcceptConditions.NotAccept, // 313
AcceptConditions.NotAccept, // 314
AcceptConditions.NotAccept, // 315
AcceptConditions.NotAccept, // 316
AcceptConditions.NotAccept, // 317
AcceptConditions.NotAccept, // 318
AcceptConditions.NotAccept, // 319
AcceptConditions.NotAccept, // 320
AcceptConditions.NotAccept, // 321
AcceptConditions.NotAccept, // 322
AcceptConditions.NotAccept, // 323
AcceptConditions.NotAccept, // 324
AcceptConditions.NotAccept, // 325
AcceptConditions.NotAccept, // 326
AcceptConditions.NotAccept, // 327
AcceptConditions.NotAccept, // 328
AcceptConditions.NotAccept, // 329
AcceptConditions.NotAccept, // 330
AcceptConditions.NotAccept, // 331
AcceptConditions.NotAccept, // 332
AcceptConditions.NotAccept, // 333
AcceptConditions.NotAccept, // 334
AcceptConditions.NotAccept, // 335
AcceptConditions.NotAccept, // 336
AcceptConditions.NotAccept, // 337
AcceptConditions.NotAccept, // 338
AcceptConditions.NotAccept, // 339
AcceptConditions.NotAccept, // 340
AcceptConditions.NotAccept, // 341
AcceptConditions.NotAccept, // 342
AcceptConditions.NotAccept, // 343
AcceptConditions.NotAccept, // 344
AcceptConditions.NotAccept, // 345
AcceptConditions.NotAccept, // 346
AcceptConditions.NotAccept, // 347
AcceptConditions.NotAccept, // 348
AcceptConditions.NotAccept, // 349
AcceptConditions.NotAccept, // 350
AcceptConditions.NotAccept, // 351
AcceptConditions.NotAccept, // 352
AcceptConditions.NotAccept, // 353
AcceptConditions.NotAccept, // 354
AcceptConditions.NotAccept, // 355
AcceptConditions.NotAccept, // 356
AcceptConditions.NotAccept, // 357
AcceptConditions.NotAccept, // 358
AcceptConditions.NotAccept, // 359
AcceptConditions.NotAccept, // 360
AcceptConditions.NotAccept, // 361
AcceptConditions.NotAccept, // 362
AcceptConditions.NotAccept, // 363
AcceptConditions.NotAccept, // 364
AcceptConditions.NotAccept, // 365
AcceptConditions.NotAccept, // 366
AcceptConditions.NotAccept, // 367
AcceptConditions.NotAccept, // 368
AcceptConditions.NotAccept, // 369
AcceptConditions.NotAccept, // 370
AcceptConditions.NotAccept, // 371
AcceptConditions.NotAccept, // 372
AcceptConditions.NotAccept, // 373
AcceptConditions.NotAccept, // 374
AcceptConditions.NotAccept, // 375
AcceptConditions.NotAccept, // 376
AcceptConditions.NotAccept, // 377
AcceptConditions.NotAccept, // 378
AcceptConditions.NotAccept, // 379
AcceptConditions.NotAccept, // 380
AcceptConditions.NotAccept, // 381
AcceptConditions.NotAccept, // 382
AcceptConditions.NotAccept, // 383
AcceptConditions.NotAccept, // 384
AcceptConditions.NotAccept, // 385
AcceptConditions.NotAccept, // 386
AcceptConditions.NotAccept, // 387
AcceptConditions.NotAccept, // 388
AcceptConditions.NotAccept, // 389
AcceptConditions.NotAccept, // 390
AcceptConditions.NotAccept, // 391
AcceptConditions.NotAccept, // 392
AcceptConditions.NotAccept, // 393
AcceptConditions.NotAccept, // 394
AcceptConditions.NotAccept, // 395
AcceptConditions.NotAccept, // 396
AcceptConditions.NotAccept, // 397
AcceptConditions.NotAccept, // 398
AcceptConditions.NotAccept, // 399
AcceptConditions.NotAccept, // 400
AcceptConditions.NotAccept, // 401
AcceptConditions.NotAccept, // 402
AcceptConditions.NotAccept, // 403
AcceptConditions.NotAccept, // 404
AcceptConditions.NotAccept, // 405
AcceptConditions.NotAccept, // 406
AcceptConditions.NotAccept, // 407
AcceptConditions.NotAccept, // 408
AcceptConditions.NotAccept, // 409
AcceptConditions.NotAccept, // 410
AcceptConditions.NotAccept, // 411
AcceptConditions.NotAccept, // 412
AcceptConditions.NotAccept, // 413
AcceptConditions.NotAccept, // 414
AcceptConditions.NotAccept, // 415
AcceptConditions.NotAccept, // 416
AcceptConditions.NotAccept, // 417
AcceptConditions.NotAccept, // 418
AcceptConditions.NotAccept, // 419
AcceptConditions.NotAccept, // 420
AcceptConditions.NotAccept, // 421
AcceptConditions.NotAccept, // 422
AcceptConditions.NotAccept, // 423
AcceptConditions.NotAccept, // 424
AcceptConditions.NotAccept, // 425
AcceptConditions.NotAccept, // 426
AcceptConditions.NotAccept, // 427
AcceptConditions.NotAccept, // 428
AcceptConditions.NotAccept, // 429
AcceptConditions.NotAccept, // 430
AcceptConditions.NotAccept, // 431
AcceptConditions.NotAccept, // 432
AcceptConditions.NotAccept, // 433
AcceptConditions.NotAccept, // 434
AcceptConditions.NotAccept, // 435
AcceptConditions.NotAccept, // 436
AcceptConditions.NotAccept, // 437
AcceptConditions.NotAccept, // 438
AcceptConditions.NotAccept, // 439
AcceptConditions.NotAccept, // 440
AcceptConditions.NotAccept, // 441
AcceptConditions.NotAccept, // 442
AcceptConditions.NotAccept, // 443
AcceptConditions.NotAccept, // 444
AcceptConditions.NotAccept, // 445
AcceptConditions.NotAccept, // 446
AcceptConditions.NotAccept, // 447
AcceptConditions.NotAccept, // 448
AcceptConditions.NotAccept, // 449
AcceptConditions.NotAccept, // 450
AcceptConditions.NotAccept, // 451
AcceptConditions.NotAccept, // 452
AcceptConditions.NotAccept, // 453
AcceptConditions.NotAccept, // 454
AcceptConditions.NotAccept, // 455
AcceptConditions.NotAccept, // 456
AcceptConditions.NotAccept, // 457
AcceptConditions.NotAccept, // 458
AcceptConditions.NotAccept, // 459
AcceptConditions.NotAccept, // 460
AcceptConditions.NotAccept, // 461
AcceptConditions.NotAccept, // 462
AcceptConditions.NotAccept, // 463
AcceptConditions.NotAccept, // 464
AcceptConditions.NotAccept, // 465
AcceptConditions.NotAccept, // 466
AcceptConditions.NotAccept, // 467
AcceptConditions.NotAccept, // 468
AcceptConditions.NotAccept, // 469
AcceptConditions.NotAccept, // 470
AcceptConditions.NotAccept, // 471
AcceptConditions.NotAccept, // 472
AcceptConditions.NotAccept, // 473
AcceptConditions.NotAccept, // 474
AcceptConditions.NotAccept, // 475
AcceptConditions.NotAccept, // 476
AcceptConditions.NotAccept, // 477
AcceptConditions.NotAccept, // 478
AcceptConditions.NotAccept, // 479
AcceptConditions.NotAccept, // 480
AcceptConditions.NotAccept, // 481
AcceptConditions.NotAccept, // 482
AcceptConditions.NotAccept, // 483
AcceptConditions.NotAccept, // 484
AcceptConditions.NotAccept, // 485
AcceptConditions.NotAccept, // 486
AcceptConditions.NotAccept, // 487
AcceptConditions.NotAccept, // 488
AcceptConditions.NotAccept, // 489
AcceptConditions.NotAccept, // 490
AcceptConditions.NotAccept, // 491
AcceptConditions.NotAccept, // 492
AcceptConditions.NotAccept, // 493
AcceptConditions.NotAccept, // 494
AcceptConditions.NotAccept, // 495
AcceptConditions.NotAccept, // 496
AcceptConditions.NotAccept, // 497
AcceptConditions.NotAccept, // 498
AcceptConditions.NotAccept, // 499
AcceptConditions.NotAccept, // 500
AcceptConditions.NotAccept, // 501
AcceptConditions.NotAccept, // 502
AcceptConditions.NotAccept, // 503
AcceptConditions.NotAccept, // 504
AcceptConditions.NotAccept, // 505
AcceptConditions.NotAccept, // 506
AcceptConditions.NotAccept, // 507
AcceptConditions.NotAccept, // 508
AcceptConditions.NotAccept, // 509
AcceptConditions.NotAccept, // 510
AcceptConditions.NotAccept, // 511
AcceptConditions.NotAccept, // 512
AcceptConditions.NotAccept, // 513
AcceptConditions.NotAccept, // 514
AcceptConditions.NotAccept, // 515
AcceptConditions.NotAccept, // 516
AcceptConditions.NotAccept, // 517
AcceptConditions.NotAccept, // 518
AcceptConditions.NotAccept, // 519
AcceptConditions.NotAccept, // 520
AcceptConditions.NotAccept, // 521
AcceptConditions.NotAccept, // 522
AcceptConditions.NotAccept, // 523
AcceptConditions.NotAccept, // 524
AcceptConditions.NotAccept, // 525
AcceptConditions.NotAccept, // 526
AcceptConditions.NotAccept, // 527
AcceptConditions.NotAccept, // 528
AcceptConditions.NotAccept, // 529
AcceptConditions.NotAccept, // 530
AcceptConditions.NotAccept, // 531
AcceptConditions.NotAccept, // 532
AcceptConditions.NotAccept, // 533
AcceptConditions.NotAccept, // 534
AcceptConditions.NotAccept, // 535
AcceptConditions.NotAccept, // 536
AcceptConditions.NotAccept, // 537
AcceptConditions.NotAccept, // 538
AcceptConditions.NotAccept, // 539
AcceptConditions.NotAccept, // 540
AcceptConditions.NotAccept, // 541
AcceptConditions.NotAccept, // 542
AcceptConditions.NotAccept, // 543
AcceptConditions.NotAccept, // 544
AcceptConditions.NotAccept, // 545
AcceptConditions.NotAccept, // 546
AcceptConditions.NotAccept, // 547
AcceptConditions.NotAccept, // 548
AcceptConditions.NotAccept, // 549
AcceptConditions.NotAccept, // 550
AcceptConditions.NotAccept, // 551
AcceptConditions.NotAccept, // 552
AcceptConditions.NotAccept, // 553
AcceptConditions.NotAccept, // 554
AcceptConditions.NotAccept, // 555
AcceptConditions.NotAccept, // 556
AcceptConditions.NotAccept, // 557
AcceptConditions.NotAccept, // 558
AcceptConditions.NotAccept, // 559
AcceptConditions.NotAccept, // 560
AcceptConditions.NotAccept, // 561
AcceptConditions.NotAccept, // 562
AcceptConditions.NotAccept, // 563
AcceptConditions.NotAccept, // 564
AcceptConditions.NotAccept, // 565
AcceptConditions.NotAccept, // 566
AcceptConditions.NotAccept, // 567
AcceptConditions.NotAccept, // 568
AcceptConditions.NotAccept, // 569
AcceptConditions.NotAccept, // 570
AcceptConditions.NotAccept, // 571
AcceptConditions.NotAccept, // 572
AcceptConditions.NotAccept, // 573
AcceptConditions.NotAccept, // 574
AcceptConditions.NotAccept, // 575
AcceptConditions.NotAccept, // 576
AcceptConditions.NotAccept, // 577
AcceptConditions.NotAccept, // 578
AcceptConditions.NotAccept, // 579
AcceptConditions.NotAccept, // 580
AcceptConditions.NotAccept, // 581
AcceptConditions.NotAccept, // 582
AcceptConditions.NotAccept, // 583
AcceptConditions.NotAccept, // 584
AcceptConditions.NotAccept, // 585
AcceptConditions.NotAccept, // 586
AcceptConditions.NotAccept, // 587
AcceptConditions.NotAccept, // 588
AcceptConditions.NotAccept, // 589
AcceptConditions.NotAccept, // 590
AcceptConditions.NotAccept, // 591
AcceptConditions.NotAccept, // 592
AcceptConditions.NotAccept, // 593
AcceptConditions.NotAccept, // 594
AcceptConditions.NotAccept, // 595
AcceptConditions.NotAccept, // 596
AcceptConditions.NotAccept, // 597
AcceptConditions.NotAccept, // 598
AcceptConditions.NotAccept, // 599
AcceptConditions.NotAccept, // 600
AcceptConditions.NotAccept, // 601
AcceptConditions.NotAccept, // 602
AcceptConditions.NotAccept, // 603
AcceptConditions.NotAccept, // 604
AcceptConditions.NotAccept, // 605
AcceptConditions.NotAccept, // 606
AcceptConditions.NotAccept, // 607
AcceptConditions.NotAccept, // 608
AcceptConditions.NotAccept, // 609
AcceptConditions.NotAccept, // 610
AcceptConditions.NotAccept, // 611
AcceptConditions.NotAccept, // 612
AcceptConditions.NotAccept, // 613
AcceptConditions.NotAccept, // 614
AcceptConditions.NotAccept, // 615
AcceptConditions.NotAccept, // 616
AcceptConditions.NotAccept, // 617
AcceptConditions.NotAccept, // 618
AcceptConditions.NotAccept, // 619
AcceptConditions.NotAccept, // 620
AcceptConditions.NotAccept, // 621
AcceptConditions.NotAccept, // 622
AcceptConditions.Accept, // 623
AcceptConditions.Accept, // 624
AcceptConditions.Accept, // 625
AcceptConditions.Accept, // 626
AcceptConditions.Accept, // 627
AcceptConditions.Accept, // 628
AcceptConditions.Accept, // 629
AcceptConditions.Accept, // 630
AcceptConditions.Accept, // 631
AcceptConditions.Accept, // 632
AcceptConditions.Accept, // 633
AcceptConditions.Accept, // 634
AcceptConditions.NotAccept, // 635
AcceptConditions.Accept, // 636
AcceptConditions.Accept, // 637
AcceptConditions.Accept, // 638
AcceptConditions.Accept, // 639
AcceptConditions.Accept, // 640
AcceptConditions.Accept, // 641
AcceptConditions.Accept, // 642
AcceptConditions.Accept, // 643
AcceptConditions.Accept, // 644
AcceptConditions.Accept, // 645
AcceptConditions.Accept, // 646
AcceptConditions.Accept, // 647
AcceptConditions.Accept, // 648
AcceptConditions.Accept, // 649
AcceptConditions.Accept, // 650
AcceptConditions.Accept, // 651
AcceptConditions.Accept, // 652
AcceptConditions.Accept, // 653
AcceptConditions.Accept, // 654
AcceptConditions.Accept, // 655
AcceptConditions.Accept, // 656
AcceptConditions.Accept, // 657
AcceptConditions.Accept, // 658
AcceptConditions.NotAccept, // 659
AcceptConditions.Accept, // 660
AcceptConditions.Accept, // 661
AcceptConditions.NotAccept, // 662
AcceptConditions.Accept, // 663
AcceptConditions.Accept, // 664
AcceptConditions.Accept, // 665
AcceptConditions.NotAccept, // 666
AcceptConditions.Accept, // 667
AcceptConditions.Accept, // 668
AcceptConditions.Accept, // 669
AcceptConditions.Accept, // 670
AcceptConditions.Accept, // 671
AcceptConditions.NotAccept, // 672
AcceptConditions.Accept, // 673
AcceptConditions.Accept, // 674
AcceptConditions.Accept, // 675
AcceptConditions.Accept, // 676
AcceptConditions.NotAccept, // 677
AcceptConditions.NotAccept, // 678
AcceptConditions.Accept, // 679
AcceptConditions.Accept, // 680
AcceptConditions.Accept, // 681
AcceptConditions.Accept, // 682
AcceptConditions.Accept, // 683
AcceptConditions.NotAccept, // 684
AcceptConditions.NotAccept, // 685
AcceptConditions.NotAccept, // 686
AcceptConditions.NotAccept, // 687
AcceptConditions.NotAccept, // 688
AcceptConditions.NotAccept, // 689
AcceptConditions.NotAccept, // 690
AcceptConditions.NotAccept, // 691
AcceptConditions.NotAccept, // 692
AcceptConditions.NotAccept, // 693
AcceptConditions.NotAccept, // 694
AcceptConditions.NotAccept, // 695
AcceptConditions.NotAccept, // 696
AcceptConditions.NotAccept, // 697
AcceptConditions.NotAccept, // 698
AcceptConditions.NotAccept, // 699
AcceptConditions.NotAccept, // 700
AcceptConditions.NotAccept, // 701
AcceptConditions.NotAccept, // 702
AcceptConditions.NotAccept, // 703
AcceptConditions.NotAccept, // 704
AcceptConditions.NotAccept, // 705
AcceptConditions.NotAccept, // 706
AcceptConditions.NotAccept, // 707
AcceptConditions.NotAccept, // 708
AcceptConditions.NotAccept, // 709
AcceptConditions.NotAccept, // 710
AcceptConditions.NotAccept, // 711
AcceptConditions.NotAccept, // 712
AcceptConditions.NotAccept, // 713
AcceptConditions.NotAccept, // 714
AcceptConditions.NotAccept, // 715
AcceptConditions.NotAccept, // 716
AcceptConditions.NotAccept, // 717
AcceptConditions.NotAccept, // 718
AcceptConditions.NotAccept, // 719
AcceptConditions.NotAccept, // 720
AcceptConditions.NotAccept, // 721
AcceptConditions.NotAccept, // 722
AcceptConditions.NotAccept, // 723
AcceptConditions.NotAccept, // 724
AcceptConditions.NotAccept, // 725
AcceptConditions.NotAccept, // 726
AcceptConditions.NotAccept, // 727
AcceptConditions.NotAccept, // 728
AcceptConditions.NotAccept, // 729
AcceptConditions.NotAccept, // 730
AcceptConditions.Accept, // 731
AcceptConditions.Accept, // 732
AcceptConditions.Accept, // 733
AcceptConditions.Accept, // 734
AcceptConditions.Accept, // 735
AcceptConditions.NotAccept, // 736
AcceptConditions.Accept, // 737
AcceptConditions.Accept, // 738
AcceptConditions.Accept, // 739
AcceptConditions.Accept, // 740
AcceptConditions.Accept, // 741
AcceptConditions.Accept, // 742
AcceptConditions.Accept, // 743
AcceptConditions.Accept, // 744
AcceptConditions.NotAccept, // 745
AcceptConditions.Accept, // 746
AcceptConditions.Accept, // 747
AcceptConditions.Accept, // 748
AcceptConditions.Accept, // 749
AcceptConditions.Accept, // 750
AcceptConditions.NotAccept, // 751
AcceptConditions.Accept, // 752
AcceptConditions.NotAccept, // 753
AcceptConditions.NotAccept, // 754
AcceptConditions.NotAccept, // 755
AcceptConditions.NotAccept, // 756
AcceptConditions.NotAccept, // 757
AcceptConditions.NotAccept, // 758
AcceptConditions.NotAccept, // 759
AcceptConditions.NotAccept, // 760
AcceptConditions.NotAccept, // 761
AcceptConditions.NotAccept, // 762
AcceptConditions.NotAccept, // 763
AcceptConditions.NotAccept, // 764
AcceptConditions.Accept, // 765
AcceptConditions.Accept, // 766
AcceptConditions.NotAccept, // 767
AcceptConditions.Accept, // 768
AcceptConditions.Accept, // 769
AcceptConditions.Accept, // 770
AcceptConditions.Accept, // 771
AcceptConditions.Accept, // 772
AcceptConditions.Accept, // 773
AcceptConditions.Accept, // 774
AcceptConditions.Accept, // 775
AcceptConditions.Accept, // 776
AcceptConditions.Accept, // 777
AcceptConditions.Accept, // 778
AcceptConditions.NotAccept, // 779
AcceptConditions.Accept, // 780
AcceptConditions.NotAccept, // 781
AcceptConditions.NotAccept, // 782
AcceptConditions.NotAccept, // 783
AcceptConditions.NotAccept, // 784
AcceptConditions.Accept, // 785
AcceptConditions.NotAccept, // 786
AcceptConditions.Accept, // 787
AcceptConditions.Accept, // 788
AcceptConditions.Accept, // 789
AcceptConditions.Accept, // 790
AcceptConditions.Accept, // 791
AcceptConditions.Accept, // 792
AcceptConditions.NotAccept, // 793
AcceptConditions.Accept, // 794
AcceptConditions.NotAccept, // 795
AcceptConditions.NotAccept, // 796
AcceptConditions.NotAccept, // 797
AcceptConditions.Accept, // 798
AcceptConditions.Accept, // 799
AcceptConditions.Accept, // 800
AcceptConditions.Accept, // 801
AcceptConditions.Accept, // 802
AcceptConditions.NotAccept, // 803
AcceptConditions.Accept, // 804
AcceptConditions.NotAccept, // 805
AcceptConditions.NotAccept, // 806
AcceptConditions.NotAccept, // 807
AcceptConditions.Accept, // 808
AcceptConditions.Accept, // 809
AcceptConditions.Accept, // 810
AcceptConditions.NotAccept, // 811
AcceptConditions.Accept, // 812
AcceptConditions.NotAccept, // 813
AcceptConditions.NotAccept, // 814
AcceptConditions.Accept, // 815
AcceptConditions.Accept, // 816
AcceptConditions.NotAccept, // 817
AcceptConditions.NotAccept, // 818
AcceptConditions.NotAccept, // 819
AcceptConditions.Accept, // 820
AcceptConditions.Accept, // 821
AcceptConditions.NotAccept, // 822
AcceptConditions.NotAccept, // 823
AcceptConditions.Accept, // 824
AcceptConditions.Accept, // 825
AcceptConditions.NotAccept, // 826
AcceptConditions.NotAccept, // 827
AcceptConditions.Accept, // 828
AcceptConditions.Accept, // 829
AcceptConditions.NotAccept, // 830
AcceptConditions.NotAccept, // 831
AcceptConditions.Accept, // 832
AcceptConditions.Accept, // 833
AcceptConditions.NotAccept, // 834
AcceptConditions.NotAccept, // 835
AcceptConditions.Accept, // 836
AcceptConditions.NotAccept, // 837
AcceptConditions.NotAccept, // 838
AcceptConditions.Accept, // 839
AcceptConditions.NotAccept, // 840
AcceptConditions.Accept, // 841
AcceptConditions.NotAccept, // 842
AcceptConditions.Accept, // 843
AcceptConditions.NotAccept, // 844
AcceptConditions.Accept, // 845
AcceptConditions.NotAccept, // 846
AcceptConditions.NotAccept, // 847
AcceptConditions.NotAccept, // 848
AcceptConditions.NotAccept, // 849
AcceptConditions.NotAccept, // 850
AcceptConditions.NotAccept, // 851
AcceptConditions.NotAccept, // 852
AcceptConditions.Accept, // 853
AcceptConditions.Accept, // 854
AcceptConditions.Accept, // 855
AcceptConditions.Accept, // 856
AcceptConditions.Accept, // 857
AcceptConditions.Accept, // 858
AcceptConditions.Accept, // 859
AcceptConditions.Accept, // 860
AcceptConditions.Accept, // 861
AcceptConditions.Accept, // 862
AcceptConditions.Accept, // 863
AcceptConditions.Accept, // 864
AcceptConditions.Accept, // 865
AcceptConditions.Accept, // 866
AcceptConditions.Accept, // 867
AcceptConditions.Accept, // 868
AcceptConditions.Accept, // 869
AcceptConditions.Accept, // 870
AcceptConditions.Accept, // 871
AcceptConditions.Accept, // 872
AcceptConditions.Accept, // 873
AcceptConditions.NotAccept, // 874
AcceptConditions.NotAccept, // 875
AcceptConditions.NotAccept, // 876
AcceptConditions.NotAccept, // 877
AcceptConditions.NotAccept, // 878
AcceptConditions.Accept, // 879
AcceptConditions.Accept, // 880
AcceptConditions.Accept, // 881
AcceptConditions.Accept, // 882
AcceptConditions.Accept, // 883
AcceptConditions.Accept, // 884
AcceptConditions.Accept, // 885
AcceptConditions.Accept, // 886
AcceptConditions.Accept, // 887
AcceptConditions.Accept, // 888
AcceptConditions.Accept, // 889
AcceptConditions.Accept, // 890
AcceptConditions.Accept, // 891
AcceptConditions.Accept, // 892
AcceptConditions.Accept, // 893
AcceptConditions.NotAccept, // 894
AcceptConditions.NotAccept, // 895
AcceptConditions.Accept, // 896
AcceptConditions.Accept, // 897
AcceptConditions.Accept, // 898
AcceptConditions.Accept, // 899
AcceptConditions.Accept, // 900
AcceptConditions.Accept, // 901
AcceptConditions.NotAccept, // 902
AcceptConditions.NotAccept, // 903
AcceptConditions.Accept, // 904
AcceptConditions.Accept, // 905
AcceptConditions.Accept, // 906
AcceptConditions.NotAccept, // 907
AcceptConditions.Accept, // 908
AcceptConditions.NotAccept, // 909
AcceptConditions.Accept, // 910
AcceptConditions.NotAccept, // 911
AcceptConditions.Accept, // 912
AcceptConditions.NotAccept, // 913
AcceptConditions.NotAccept, // 914
AcceptConditions.NotAccept, // 915
AcceptConditions.NotAccept, // 916
AcceptConditions.NotAccept, // 917
AcceptConditions.NotAccept, // 918
AcceptConditions.Accept, // 919
AcceptConditions.Accept, // 920
AcceptConditions.Accept, // 921
AcceptConditions.Accept, // 922
AcceptConditions.Accept, // 923
AcceptConditions.Accept, // 924
AcceptConditions.Accept, // 925
AcceptConditions.Accept, // 926
AcceptConditions.Accept, // 927
AcceptConditions.Accept, // 928
AcceptConditions.Accept, // 929
AcceptConditions.Accept, // 930
AcceptConditions.NotAccept, // 931
AcceptConditions.NotAccept, // 932
AcceptConditions.NotAccept, // 933
AcceptConditions.NotAccept, // 934
AcceptConditions.NotAccept, // 935
AcceptConditions.NotAccept, // 936
AcceptConditions.NotAccept, // 937
AcceptConditions.NotAccept, // 938
AcceptConditions.NotAccept, // 939
AcceptConditions.NotAccept, // 940
AcceptConditions.NotAccept, // 941
AcceptConditions.NotAccept, // 942
AcceptConditions.NotAccept, // 943
AcceptConditions.NotAccept, // 944
AcceptConditions.NotAccept, // 945
AcceptConditions.NotAccept, // 946
AcceptConditions.Accept, // 947
AcceptConditions.Accept, // 948
AcceptConditions.Accept, // 949
AcceptConditions.Accept, // 950
AcceptConditions.NotAccept, // 951
AcceptConditions.Accept, // 952
AcceptConditions.NotAccept, // 953
AcceptConditions.Accept, // 954
AcceptConditions.Accept, // 955
AcceptConditions.Accept, // 956
AcceptConditions.Accept, // 957
AcceptConditions.Accept, // 958
AcceptConditions.NotAccept, // 959
AcceptConditions.Accept, // 960
AcceptConditions.Accept, // 961
AcceptConditions.NotAccept, // 962
AcceptConditions.Accept, // 963
AcceptConditions.Accept, // 964
AcceptConditions.NotAccept, // 965
AcceptConditions.Accept, // 966
AcceptConditions.NotAccept, // 967
AcceptConditions.Accept, // 968
AcceptConditions.NotAccept, // 969
AcceptConditions.Accept, // 970
AcceptConditions.NotAccept, // 971
AcceptConditions.NotAccept, // 972
AcceptConditions.Accept, // 973
AcceptConditions.NotAccept, // 974
AcceptConditions.NotAccept, // 975
AcceptConditions.NotAccept, // 976
AcceptConditions.Accept, // 977
AcceptConditions.NotAccept, // 978
AcceptConditions.Accept, // 979
AcceptConditions.Accept, // 980
AcceptConditions.Accept, // 981
AcceptConditions.Accept, // 982
AcceptConditions.Accept, // 983
AcceptConditions.NotAccept, // 984
AcceptConditions.Accept, // 985
AcceptConditions.Accept, // 986
AcceptConditions.Accept, // 987
AcceptConditions.NotAccept, // 988
AcceptConditions.Accept, // 989
AcceptConditions.NotAccept, // 990
AcceptConditions.Accept, // 991
AcceptConditions.Accept, // 992
AcceptConditions.Accept, // 993
AcceptConditions.NotAccept, // 994
AcceptConditions.Accept, // 995
AcceptConditions.Accept, // 996
AcceptConditions.Accept, // 997
AcceptConditions.Accept, // 998
AcceptConditions.Accept, // 999
AcceptConditions.NotAccept, // 1000
};
private static int[] colMap = new int[]
{
4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 5, 5, 4, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1, 5, 5, 5, 5, 5, 5, 5, 6, 7, 5, 8, 3, 9, 2, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 5, 5, 5, 5, 5,
21, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22,
5, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 39, 5, 5, 5, 5, 5,
5, 5
};
private static int[] rowMap = new int[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 11, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 2, 27, 2, 28,
21, 2, 21, 29, 30, 31, 1, 2, 32, 33, 34, 35, 36, 37, 2, 2,
21, 38, 39, 40, 41, 42, 43, 44, 45, 2, 46, 47, 48, 24, 49, 50,
51, 52, 53, 54, 55, 56, 57, 2, 58, 59, 60, 61, 2, 2, 2, 62,
63, 2, 64, 65, 66, 67, 10, 68, 69, 70, 71, 72, 73, 74, 30, 75,
76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 24, 2, 86, 87, 88, 89,
90, 91, 92, 93, 2, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
105, 2, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 2, 118,
119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
135, 2, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 2, 159, 160, 161, 162, 2, 163,
164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
19, 180, 181, 182, 183, 184, 41, 185, 186, 187, 188, 189, 190, 191, 192, 193,
194, 24, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 2, 207,
208, 177, 209, 210, 22, 211, 212, 213, 16, 214, 193, 215, 216, 217, 198, 218,
219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
235, 236, 196, 237, 238, 239, 240, 241, 242, 243, 228, 244, 231, 245, 246, 247,
248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 51, 260, 261, 262,
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 21,
358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373,
374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389,
390, 391, 392, 393, 394, 23, 43, 59, 72, 395, 396, 397, 398, 399, 400, 401,
402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417,
418, 419, 420, 421, 422, 423, 424, 233, 425, 426, 427, 428, 429, 430, 431, 432,
433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 400, 479,
480, 481, 482, 483, 484, 485, 158, 486, 487, 488, 489, 490, 491, 492, 493, 494,
495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510,
511, 512, 139, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 117,
525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 502,
540, 513, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554,
30, 47, 555, 556, 546, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567,
568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583,
584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599,
600, 601, 602, 603, 604, 507, 605, 606, 607, 608, 609, 610, 611, 612, 576, 212,
613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628,
629, 630, 631, 632, 633, 634, 203, 635, 636, 637, 447, 638, 639, 640, 641, 642,
643, 644, 449, 645, 646, 647, 648, 203, 649, 447, 650, 651, 652, 653, 499, 654,
655, 500, 656, 657, 533, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668,
669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 191, 681, 682, 683,
684, 685, 308, 22, 686, 687, 688, 443, 689, 690, 691, 692, 693, 694, 144, 695,
696, 697, 698, 699, 198, 700, 701, 702, 171, 703, 704, 705, 706, 707, 708, 709,
710, 711, 712, 713, 714, 676, 715, 679, 716, 717, 718, 719, 720, 721, 722, 723,
724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 231, 734, 735, 736, 737, 738,
739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 11, 752, 753,
754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769,
770, 771, 772, 773, 774, 775, 666, 776, 777, 778, 779, 780, 781, 782, 783, 784,
785, 786, 787, 788, 680, 789, 790, 703, 791, 792, 793, 794, 795, 796, 797, 798,
799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814,
815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830,
831, 832, 833, 834, 835, 45, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845,
846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861,
862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877,
878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 807, 889, 890, 891, 892,
893, 894, 895, 896, 897, 21, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907,
908, 909, 910, 911, 912, 913, 914, 915, 916
};
private static int[,] nextState = new int[,]
{
{ -1, 1, 39, 39, 39, 2, 40, 2, 62, 62, 2, 80, 96, 642, 738, 768, 768, 768, 768, 768, 2, 111, 2, 3, 623, 623, 731, 879, 765, 623, 623, 41, 785, 623, 896, 798, 808, 815, 995, 623, 623, 820, 824, 623, 628, 828, 880, 998 },
{ -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 61, 61, 61, 61, 61, 61, 61, 61, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 97, 97, 112, 97, 97, 97, 97, 97, 97, 97, 97, 643, 97, 97, 97, 97, 739, 97, 97, 97, 97 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 629, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, 64, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 43, 43, 43, 43, 43, 43, 43, 43, 43, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, 323, 324, -1, -1, -1, 325, -1, 326, 875, -1, 44, 44, 44, 44, 44, 44, 44, 44, 44, 327, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 331, 67, 67, 67, 67, 67, 67, 67, 67, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 332, -1, -1, -1, 332, 333, 334, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 854, 854, 854, 854, 854, 854, 854, 854, 854, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 794, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, 363, 364, -1, -1, -1, -1, -1, -1, 365, 366, 367, 368, 369, 370, 371, 371, 372, 61, 61, -1, -1, -1, 695, -1, -1, 373, -1, 374, -1, 194, 19, 697, -1, -1, 375, 699, 376, -1, -1, -1, 377, 677, -1, 51, 378, 860, 678 },
{ -1, 363, 364, -1, -1, -1, -1, -1, -1, 365, 366, 635, 736, 767, 786, 61, 61, 61, 61, 61, -1, -1, -1, 695, -1, -1, 373, -1, 374, -1, 194, 19, 697, -1, -1, 375, 699, 376, -1, -1, -1, 377, 677, -1, 51, 378, 860, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 638, 638, 638, 638, 638, 638, 638, 638, 638, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 631, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, 71, -1 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 670, 670, 670, 670, 670, 670, 670, 670, 670, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 453, 457, -1, -1, -1, 455, -1, 456, 456, -1, 53, 53, 53, 53, 53, 53, 53, 53, 53, 457, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 471, 471, 471, 471, 471, 471, 471, 471, 471, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 25, 25, 25, 25, 25, 25, 25, 25, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 61, 61, 61, 61, 61, 61, 61, 61, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, 30, 30, 30, 30, 30, 30, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 981, 399, 399, 399, 399, 399, 399 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 61, 61, 61, 61, 61, 61, 61, 61, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 546, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 857, 857, 857, 857, 857, 857, 857, 857, 857, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 588, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 77, 77, 77, 77, 77, 77, 77, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 734, 734, 734, 734, 734, 734, 734, 734, 734, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832, 832 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, -1, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, -1, 97, 97, 97, 97, 97, 97, 97, 97, 135, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 146, 97, 146, 97 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 858, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 766, 126, 766, -1, -1, -1, -1, -1, -1, -1, 137, 137, 148, 159, 159, 159, 159, 159, 159, 360, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, 323, 324, -1, -1, -1, 325, -1, 326, 875, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 327, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 331, 67, 67, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 332, -1, -1, -1, 332, 333, 334, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 698, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 638, 638, 755, 755, 755, 755, 755, 755, 755, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 860, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 670, 670, 670, 670, 670, 670, 670, 670, 670, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 453, 457, -1, -1, -1, 455, -1, 456, 456, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 457, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 55, 74, 74, 92, 25, 25, 25, 25, 25, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 29, 29, 29, 29, 29, 29, 29, 29, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 849, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 76, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 634, 634, 634, 634, 634, 634, 78, 78, 78, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63, 63, 636, 737, 737, 737, 737, 737, 737, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 737, 737, 737, 737, 737, 737, 737, 737, 737, 213, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 770, 770, 788, 800, 800, 800, 800, 800, 800, -1, -1, -1, -1, -1, -1, 170, -1, -1, -1, 766, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, 766, 766, -1, -1, -1, -1, -1 },
{ -1, 323, 327, -1, -1, -1, 325, -1, 326, 326, -1, 630, 630, 630, 630, 630, 630, 630, 630, 630, 327, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 332, -1, -1, -1, 332, 333, 334, -1, -1, -1, -1, -1 },
{ -1, -1, 47, -1, -1, -1, -1, 190, -1, -1, 408, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161, -1, 385, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 755, 755, 755, 755, 755, 755, 755, 755, 755, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 25, 25, 25, 25, 25, 25, 25, 25, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 29, 29, 29, 29, 29, 29, 29, 29, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185, -1, -1, -1, -1, -1, -1 },
{ -1, 79, 286, -1, -1, -1, -1, -1, -1, 286, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 167, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 662, 218, -1, -1, -1, 685, 677, -1, 42, 242, 858, 678 },
{ -1, 79, 95, -1, -1, -1, -1, -1, -1, 110, 123, 134, 145, 145, 145, 145, 145, 145, 145, 145, 156, -1, -1, 167, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, -1, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 770, 770, 788, 800, 800, 800, 800, 800, 800, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, 766, 170, -1, -1, -1, -1, -1 },
{ -1, 323, 688, -1, -1, -1, 325, -1, 326, 875, -1, 115, 115, 115, 115, 115, 115, 115, 115, 115, 689, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 863, 863, 863, 863, 863, 863, 863, 863, 863, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 698, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 386, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 118, 118, 118, 118, 118, 118, 118, 118, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 521, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 530, 457, -1, -1, -1, 531, -1, 532, 532, -1, 652, 652, 652, 652, 652, 652, 652, 652, 652, 457, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 25, 25, 25, 25, 25, 25, 61, 61, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 29, 61, 61, 61, 61, 61, 61, 61, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 724, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 286, 286, -1, -1, -1, -1, -1, -1, 286, -1, 7, 853, 884, 884, 884, 884, 44, 44, 44, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, -1, 42, -1, 858, -1 },
{ -1, 247, 251, -1, -1, -1, -1, -1, -1, 110, 123, 145, 145, 145, 255, 255, 255, 255, 255, 255, 259, -1, -1, 263, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, 266, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, -1, -1, -1, -1 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 770, 770, 788, 800, 800, 800, 800, 800, 800, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 170, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, 766, 766, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 331, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 389, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 118, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 522, -1, -1, -1, -1 },
{ -1, 530, 457, -1, -1, -1, 531, -1, 532, 532, -1, 661, -1, -1, -1, -1, -1, -1, -1, -1, 457, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185, -1, 559, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 133, 133, 133, 133, 133, 133, 133, 133, 133, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 286, 286, -1, -1, -1, -1, -1, -1, 286, -1, 287, 288, 289, 289, 289, 289, 289, 289, 289, -1, -1, -1, 974, -1, -1, 944, -1, 945, -1, -1, 4, 975, -1, -1, 943, 942, 976, -1, -1, -1, 946, -1, -1, 42, -1, 858, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 273, -1, -1, 5, 5, 5, 5, 5, 5, 5, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 11, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 657, 657, 657, 657, 657, 180, 180, 180, 180, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 392, 688, -1, -1, -1, 325, -1, 326, 875, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 689, -1, -1, 203, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 203, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 390, -1, -1, -1, 161, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 523, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 530, 457, -1, -1, -1, 531, -1, 532, 532, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 457, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 724, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 560, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 133, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, 8, 8, 45, 67, 67, 67, 67, 67, -1, -1, -1, 659, -1, -1, 803, -1, 811, -1, -1, -1, 666, -1, -1, 753, 745, 672, -1, -1, -1, 817, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 12, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 382, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 220, 220, 870, 891, 891, 891, 226, 226, 226, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, 766, 766, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 209, 209, 209, 209, 209, 209, 209, 209, 209, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 701, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 720, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 742, 742, 742, 742, 742, 742, 742, 742, 742, 205, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 725, -1, -1, -1, -1 },
{ -1, -1, 620, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 79, 95, -1, -1, -1, -1, -1, -1, 110, 123, 290, 290, 290, 290, 290, 290, 291, 291, 291, 156, -1, -1, 167, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, -1, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 675, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 209, 23, 23, 23, 23, 23, 23, 23, 23, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 391, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 650, 650, 650, 650, 650, 650, 650, 650, 650, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 542, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 561, -1, -1, -1, 185, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, 622, 622, -1, 144, 144, 144, 144, 144, 144, 144, 144, 144, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 247, 251, -1, -1, -1, -1, -1, -1, 110, 123, 290, 290, 290, 290, 290, 290, 291, 291, 291, 259, -1, -1, 263, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, 266, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 20, 20, 20, 20, 20, 52, 52, 52, 52, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 23, 23, 23, 23, 23, 23, 23, 23, 23, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 782, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 650, 650, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 542, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, 533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 562, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 176, 176, 176, 176, 176, 176, 176, 176, 176, 186, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, 66, 66, 66, 66, 66, 630, 630, 630, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 12, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, 384, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 52, 52, 52, 52, 52, 52, 52, 52, 52, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 744, 744, 744, 744, 744, 744, 744, 744, 744, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 650, 35, 35, 35, 35, 35, 35, 35, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 542, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 524, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 534, -1, -1, -1, -1, 722, -1, 723, 723, -1, 661, 661, 661, 661, 661, 661, 661, 661, 661, -1, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 563, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 176, 176, 176, 176, 176, 94, 77, 77, 77, 186, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 292, -1, -1, -1, -1, 293, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 237, 829, 829, 829, 829, 829, 829, 892, 13, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 770, 770, 788, 800, 800, 800, 800, 800, 800, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, 766, 766, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 181, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 35, 35, 35, 35, 35, 35, 35, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 542, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 718, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 534, -1, -1, -1, -1, 722, -1, 723, 723, -1, 661, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 726, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 94, 94, 94, 94, 94, 77, 77, 77, 186, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 294, -1, -1, -1, 295, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 855, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 647, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 632, 632, 632, 632, 632, 632, 632, 632, 632, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 542, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 651, -1, -1, -1, -1, -1 },
{ -1, 534, -1, -1, -1, -1, 722, -1, 723, 723, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 94, 94, 94, 94, 94, 77, 77, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 296, -1, -1, -1, -1, -1, -1, -1, -1, -1, 297, -1, -1, 298, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 843, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 948, 829, 829, 829, 829 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 43, 232, 232, 232, 232, 232, 232, 232, 232, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 587, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 521, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743, 743 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 299, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 886, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 232, 232, 232, 232, 232, 232, 232, 232, 232, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, 408, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 522, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665, 665 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 301, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 302, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 955, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 232, 232, 114, 648, 648, 648, 648, 648, 648, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, -1, 450, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 68, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 523, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 211, 211, 211, 211, 211, 211, 142, 142, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 303, -1, -1, -1, -1, -1, -1, -1, 304, -1, -1, -1, -1, -1, 305, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669, 669 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 471, 471, 471, 471, 471, 471, 471, 471, 471, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 720, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 142, 142, 142, 142, 142, 142, 142, 142, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 306, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 307, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 243, 243, 243, 243, 243, 243, 81, 81, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 229, 229, 229, 229, 229, 229, 229, 229, 229, 241, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 308, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 225, 225, 225, 225, 225, 225, 225, 225, 225, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 453, 454, -1, -1, -1, 455, -1, 456, 456, -1, 674, 674, 674, 674, 674, 674, 674, 674, 674, 454, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 772, 772, 772, 772, 772, 211, 142, 142, 142, 241, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 306, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 453, 454, -1, -1, -1, 455, -1, 456, 456, -1, 214, 214, 214, 214, 214, 214, 214, 214, 214, 454, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 233, 233, 233, 233, 233, 233, 190, 190, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 524, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 211, 211, 211, 211, 211, 211, 142, 142, 142, 241, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 309, -1, -1, -1, 310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 306, 311, -1, -1, -1, -1 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 679, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, 766, 126, 766, -1, -1, -1, -1, -1, 499, -1, 137, 137, 148, 159, 159, 159, 159, 159, 159, 360, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 190, 190, 190, 190, 190, 190, 190, 190, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, 533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 312, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 17, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 270, 270, 270, 270, 270, 270, 270, 270, 270, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 718, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, 81, 81, 81, 81, 81, 81, 81, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 668, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 254, 254, 254, 254, 254, 254, 254, 254, 254, 241, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 247, 286, -1, -1, -1, -1, -1, -1, 286, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 263, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 662, 218, 266, -1, -1, 685, 677, -1, 42, 242, 858, 678 },
{ -1, 497, 405, -1, -1, -1, 406, -1, 407, 407, -1, 471, 471, 471, 471, 471, 471, 471, 471, 471, -1, -1, -1, 667, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 667, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, 286, 286, -1, -1, -1, -1, -1, -1, 286, -1, 84, 862, 889, 889, 889, 889, 859, 859, 859, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, -1, 42, -1, 858, -1 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 497, 405, -1, -1, -1, 406, -1, 407, 407, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 667, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 667, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, 79, 95, -1, -1, -1, -1, -1, -1, 110, 316, 290, 290, 290, 290, 290, 290, 291, 291, 291, 156, -1, -1, 167, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, -1, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, 403, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 783, 399, 796, 399, 895, 399, 399, 399, 399, 806, 399, 399, 399, 399, 399, 814, 819, 399, 399, 823, 399, 903 },
{ -1, 516, -1, -1, -1, -1, 708, -1, 517, 517, -1, 257, 257, 257, 257, 257, 257, 257, 257, 257, -1, -1, -1, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 640, 640, 640, 640, 640, 640, 735, 735, 735, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 22 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 268, 268, 268, 268, 268, 268, 268, 268, 268, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262 },
{ -1, -1, 317, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, 292, -1, -1, -1, -1, 293, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 810, 810, 810, 810, 810, 233, 190, 190, 190, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 317, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 233, 233, 233, 233, 233, 233, 190, 190, 190, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 79, 318, -1, -1, -1, -1, -1, -1, 110, 316, 291, 291, 291, 291, 291, 291, 291, 291, 291, -1, -1, -1, 167, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, -1, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, 28, 28, 28, 28, 28, 28, 28, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, 319, -1, 291, 291, 291, 291, 291, 291, 291, 291, 291, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, 408, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, 5, 5, 5, 5, 5, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 275, 275, -1, -1, -1, -1, -1, -1, 275, -1, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 284, 284, 284, 284, 284, 284, 284, 284, 284, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 297, -1, -1, 298, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 304, -1, -1, -1, -1, -1, 305, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 309, -1, -1, -1, 321, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 311, -1, -1, -1, -1 },
{ -1, 286, 286, -1, -1, -1, -1, -1, -1, 286, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, -1, 42, -1, 858, -1 },
{ -1, -1, 329, -1, -1, -1, -1, -1, -1, 330, -1, 289, 289, 289, 289, 289, 289, 289, 289, 289, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 329, -1, -1, -1, -1, -1, -1, 330, -1, 289, 289, 289, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 329, -1, -1, -1, -1, -1, -1, 330, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, 319, -1, 14, 14, 14, 14, 14, 14, 14, 14, 14, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, 319, -1, 15, 15, 15, 15, 15, 15, 15, 15, 15, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 98, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 113, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 692, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 344, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 644, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 136, -1, 147, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158, -1, -1, -1, -1, -1, -1, 64 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 69, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 286, 318, -1, -1, -1, -1, -1, -1, 345, 316, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, -1, 42, -1, 858, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 113, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 102, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 117, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 179, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 286, 318, -1, -1, -1, -1, -1, -1, 345, 316, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, 128, 42, -1, 858, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 139, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 150, 346, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 344, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 659, -1, -1, 803, -1, 811, -1, -1, -1, 666, -1, -1, 753, 745, 672, -1, -1, -1, 817, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 286, 286, -1, -1, -1, -1, -1, -1, 286, -1, 347, 348, 349, 349, 349, 349, 349, 349, 349, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, -1, 42, -1, 858, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 350, 351, 352, 352, 352, 352, 352, 352, 352, -1, -1, -1, 353, -1, -1, 354, -1, 696, -1, -1, -1, 355, -1, -1, 356, 357, 691, -1, -1, -1, 756, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 117, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 128, -1, -1, -1, -1 },
{ -1, 323, -1, -1, -1, -1, 325, -1, 326, 326, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 127, 127, 127, 127, 127, 127, 138, 149, 149, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645, 645 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160, 160, 658, 744, 744, 744, 744, 744, 744, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 653, 653, 653, 653, 653, 653, 171, 181, 181, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 179, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 876, 876, 876, 876, 876, 876, 876, 876, 876, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 18, 18, 18, 50, 70, 70, 70, 70, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 85, 85, 85, 85, 85, 85, 85, 85, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 101, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, 361, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1, -1, 361 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 286, 286, -1, -1, -1, -1, -1, -1, 286, -1, 387, 693, 686, 686, 686, 686, 686, 686, 686, -1, -1, -1, 167, -1, -1, 751, -1, 779, -1, -1, 4, 200, -1, -1, 684, 662, 218, -1, -1, -1, 793, -1, -1, 42, -1, 858, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 690, -1, -1, -1, -1, -1, -1, 329, -1, 349, 349, 349, 349, 349, 349, 349, 349, 349, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 690, -1, -1, -1, -1, -1, -1, 329, -1, 754, 754, 754, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 690, -1, -1, -1, -1, -1, -1, 329, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 393, -1, 352, 352, 352, 352, 352, 352, 352, 352, 352, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 393, -1, 352, 352, 352, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 704, -1, -1, -1, -1, 394, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 700, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 705, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 395, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 396, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 397, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267 },
{ -1, 275, 275, -1, -1, -1, -1, -1, -1, 275, -1, 189, 196, 196, 202, 732, 732, 732, 732, 732, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, 21, 21, 21, 21, 21, 53, 53, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 894, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 894, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1 },
{ -1, 363, 412, -1, -1, -1, -1, -1, -1, 412, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 695, -1, -1, 373, -1, 374, -1, 194, 19, 697, -1, -1, 375, 699, 376, -1, -1, -1, 377, 677, -1, 51, 242, 860, 678 },
{ -1, 412, 412, -1, -1, -1, -1, -1, -1, 412, -1, 781, 795, 795, 413, -1, -1, -1, -1, -1, -1, -1, -1, 695, -1, -1, 414, -1, 709, -1, -1, 19, 697, -1, -1, 415, 699, 376, -1, -1, -1, 762, -1, -1, 51, -1, 860, -1 },
{ -1, 412, 412, -1, -1, -1, -1, -1, -1, 412, -1, 416, 417, 418, 418, 418, 418, 418, 418, 418, -1, -1, -1, 419, -1, -1, 784, -1, 797, -1, -1, 19, 420, -1, -1, 710, 421, 758, -1, -1, -1, 807, -1, -1, 51, -1, 860, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 422, 423, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 54, 54, 54, 54, 54, 54, 54, 54, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 54, 54, 54, 73, 73, 73, 73, 73, 73, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, 73, 73, 73, 73, 73, 73, 73, 73, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, 73, 73, 73, 73, 73, 91, 106, 106, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 106, 106, 106, 106, 106, 106, 106, 106, 106, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 106, 61, 61, 61, 61, 61, 61, 61, 61, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 294, -1, -1, -1, 426, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 427, -1, -1, -1, -1, -1, -1, -1, -1, -1, 297, -1, -1, 298, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 430, -1, -1, -1, -1, -1, -1, -1, 304, -1, -1, -1, -1, -1, 305, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 432, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 309, -1, -1, -1, 433, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 311, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 434, 435, 435, 435, 435, 436, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 441, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 442, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 760, -1, -1, -1, -1, -1, 443, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 445, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 329, -1, -1, -1, -1, -1, -1, 329, -1, 686, 686, 686, 686, 686, 686, 686, 686, 686, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 446, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 706, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 447, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 713, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 392, -1, -1, -1, -1, 325, -1, 326, 326, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 203, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 203, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, 88, 88, 103, 118, 118, 118, 118, 118, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, 711, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1, -1, 711 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 452, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 275, 275, -1, -1, -1, -1, -1, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 403, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 783, 399, 796, 399, 895, 399, 399, 399, 399, 806, 399, 399, 399, 399, 399, 814, 819, 399, 399, 823, 399, 903 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 48 },
{ -1, 403, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 763, -1, 458, -1, 712, -1, -1, -1, -1, 459, -1, -1, -1, -1, -1, 460, 461, -1, -1, 714, -1, 764 },
{ -1, 404, -1, -1, -1, -1, 406, -1, 407, 407, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 257, 257, 257, 257, 257, 257, 257, 257, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871, 871 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 261, 261, 265, 268, 268, 268, 268, 268, 268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 129, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 412, 412, -1, -1, -1, -1, -1, -1, 412, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 695, -1, -1, 414, -1, 709, -1, -1, 19, 697, -1, -1, 415, 699, 376, -1, -1, -1, 762, -1, -1, 51, -1, 860, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 474, 474, 474, 474, 474, 474, 475, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 426, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 430, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 477, -1, 418, 478, 478, 478, 478, 478, 478, 478, 478, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 477, -1, 478, 478, 478, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 477, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 479, -1, -1, -1, -1, 480, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 483, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 484, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 486, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 489, 489, 489, 489, 489, 489, 489, 489, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 489, 489, 489, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 89, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 119, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 130, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 646, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 141, -1, 152, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 163, -1, -1, -1, -1, -1, -1, 71 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 119, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 173, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 117, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 183, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 26, 26, 26, 26, 26, 26, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 26, 26, 26, 26, 26, 26, 26, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 26, 26, 26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 490, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 491, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 161 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 493, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 495, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 496, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, 23, 23, 23, 23, 23, 23, 23, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 694, -1, -1, -1, -1, -1 },
{ -1, 453, -1, -1, -1, -1, 455, -1, 456, 456, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 90, 90, 90, 90, 90, 105, 120, 120, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639, 639 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 131, 131, 654, 742, 742, 742, 742, 742, 742, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 164, 164, 164, 164, 164, 164, 174, 184, 184, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 717, -1, -1, 501, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 503, -1, -1, -1, -1, -1, 504, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 505, -1, -1, -1, 506, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 507, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 508, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 509, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 27 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 56, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 856, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 633, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 861, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 887, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 949, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 888, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 956, 513, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 107, 107, 107, 107, 107, 107, 107, 107, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 107, 107, 107, 107, 107, 107, 107, 107, 107, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 107, 107, 107, 107, 107, 107, 107, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 183, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 140, 140, 140, 151, 650, 650, 650, 650, 650, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 520, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 192, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 198, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 204, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 664, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 216, -1, 222, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 228, -1, -1, -1, -1, -1, -1, 234 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 204, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 240, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 245, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 719, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 492, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 525, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 444, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 526, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 494, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 497, -1, -1, -1, -1, 406, -1, 407, 407, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 667, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 667, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 527, 528, 528, 529, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, 31, 31, 31, 31, 31, 31, 31, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 536, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 121, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 132, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 143, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 154, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 165, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 175, 537, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 536, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 27, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 27, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 22, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 32, 399, 399 },
{ -1, 516, -1, -1, -1, -1, 708, -1, 517, 517, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, 869 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 280, 280, 282, 284, 284, 284, 284, 284, 284, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716, 716 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 162, 172, 172, 182, 650, 650, 650, 650, 650, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 547, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 548, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 553, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 33, 33, 33, 33, 33, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 33, 33, 33, 33, 33, 33, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 530, -1, -1, -1, -1, 531, -1, 532, 532, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868, 868 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 217, 217, 223, 229, 229, 229, 229, 229, 229, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, 557 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 558, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 27, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 34 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 191, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 569, 569, 570, 571, 571, 571, 571, 571, 571, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, 58, 58, 58, 58, 58, 58, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, 58, 58, 58, 58, 58, 58, 58, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 58, 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 572, 572, 573, 574, 574, 574, 574, 574, 574, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 322, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 551, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 550, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 575, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 576, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 577, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, -1, -1, -1, -1, -1 },
{ -1, 554, -1, -1, -1, -1, 722, -1, 555, 555, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 246, 246, 250, 254, 254, 254, 254, 254, 254, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 556, -1, -1, -1, -1, 722, -1, 555, 555, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, 867 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 728, -1, -1, -1, -1, -1, 580, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 582, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 583, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 584, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 981 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 27, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 27, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 586, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 571, 571, 571, 571, 571, 571, 571, 571, 571, 813, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 571, 571, 571, 571, 571, -1, -1, -1, -1, 813, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 813, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 589, 589, 589, 589, 589, 589, 574, 574, 574, 590, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 589, 589, 589, 589, 589, 818, -1, -1, -1, 590, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 818, 818, 818, 818, 818, 818, -1, -1, -1, 590, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 591, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727, 727 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 579 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 592, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 581, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 593, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 822, 822, 594, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 569, 569, 570, 571, 571, 571, 571, 571, 571, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 597, 597, 598, 571, 571, 571, 571, 571, 571, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 191, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 826, 826, 826, 826, 826, 826, 599, 599, 599, 590, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 830, 830, 830, 830, 830, 830, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 601, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 603, 603, 603, 603, 603, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 596, 596, 596, 596, 596, 596, 596, 596, 596, 604, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 604, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 605, 605, 605, 605, 605, 605, 605, 605, 605, 813, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 605, 605, 605, 605, 605, -1, -1, -1, -1, 813, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 608, 608, 608, 608, 608, 608, 609, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 610, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 27, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 878, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, 36, 36, 36, 36, 36, 59, 77, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 611, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 94, 94, 94, 94, 94, 59, 77, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, 608, 608, 608, 608, 608, 609, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 613, 613, 613, 613, 613, 613, 596, 596, 596, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 730, 730, 730, 730, 730, 730, 730, 730, 730, 604, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 615, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 837, 837, 837, 837, 837, 837, 617, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 109, 109, 109, 109, 109, 109, 122, 77, 77, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 618, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 619, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 619, -1, -1, -1, -1, -1, -1, 621, 621, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 144, 144, 144, 144, 144, 144, 144, 144, 144, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 37, 627, 734, 734, 734, 734, 734, 734, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 155, 155, 166, 176, 176, 176, 176, 176, 176, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 43, 43, 114, 648, 648, 648, 648, 648, 648, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 46, 46, 46, 46, 46, 46, 46, 46, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 57, 57, 57, 57, 57, 57, 57, 57, 57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 734, 734, 734, 734, 734, 634, 78, 78, 78, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, -1, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, -1, 97, 97, 97, 97, 97, 97, 97, 97, 865, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 323, 327, -1, -1, -1, 325, -1, 326, 326, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 327, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 238, 238, 238, 238, 238, 238, 238, 238, 238, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 849, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 538, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 78, 78, 78, 78, 78, 78, 78, 78, 78, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 437, 438, 438, 438, 438, 438, 438, 438, 438, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 737, 737, 737, 737, 737, 219, 225, 225, 225, 213, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, 47, -1, -1, -1, -1, 190, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 471, 471, 471, 471, 471, 471, 471, 471, 471, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, -1, -1, -1, 409, 410, 411, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199 },
{ -1, 323, 689, -1, -1, -1, 325, -1, 326, 326, -1, 649, 649, 649, 649, 649, 649, 649, 649, 649, 689, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116, 116, 116, 116, 116, 116, 116, 116, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 247, 251, -1, -1, -1, -1, -1, -1, 110, 123, 255, 255, 255, 255, 255, 269, 269, 269, 269, 259, -1, -1, 263, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, 266, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 231, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 757, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 721, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, 448, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 180, 180, 180, 180, 180, 180, 180, 180, 180, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 392, 689, -1, -1, -1, 325, -1, 326, 326, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 689, -1, -1, 203, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 203, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 540, -1, -1, -1, 540, 541, 542, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 552, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 554, 457, -1, -1, -1, 722, -1, 555, 555, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 457, -1, -1, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 181, 181, 181, 181, 181, 181, 181, 181, 181, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 742, 742, 742, 742, 742, 211, 142, 142, 142, 205, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 249, 23, 23, 23, 23, 23, 23, 23, 23, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, 533, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 533, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 632, 632, 632, 632, 632, 632, 632, 632, 632, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 744, 744, 744, 744, 744, 233, 190, 190, 190, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 687, -1, -1, -1, -1, 335, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 253, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 307, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, 408, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 408, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 721, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1 },
{ -1, -1, 450, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 637, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746, 746 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 552, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276 },
{ -1, 453, 454, -1, -1, -1, 455, -1, 456, 456, -1, 670, 670, 670, 670, 670, 670, 670, 670, 670, 454, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, 578, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 322, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 313, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 315, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 400, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 399, 399, 399, 399, 978, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 309, -1, -1, -1, 310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 311, -1, -1, -1, -1 },
{ -1, -1, 329, -1, -1, -1, -1, -1, -1, 329, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 361, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 741, 741, 741, 741, 741, 741, 655, 149, 149, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 771, 771, 771, 771, 771, 771, 660, 181, 181, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 451, 451, 451, 451, 451, 451, 451, 451, 451, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 702, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 383, -1, -1, -1, -1, -1 },
{ -1, -1, 329, -1, -1, -1, -1, -1, -1, 329, -1, 686, 686, 686, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 424, -1, -1, -1, -1, 425, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 703, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 428, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 429, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 431, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 706, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 711, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 400, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777, 777 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 427, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 485, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 502, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 510, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 56, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683, 683 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 535, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 543, 544, 544, 545, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 549, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747, 747 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 671, 671, 223, 229, 229, 229, 229, 229, 229, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 563, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 585, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681, 681 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 580, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 612, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 616, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 769, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, 766, 766, 766, -1, -1, -1, -1, -1, -1, -1, 740, 740, 114, 648, 648, 648, 648, 648, 648, -1, -1, -1, -1, -1, -1, 766, -1, -1, -1, 766, -1, -1, -1, -1, -1, 65, -1, -1, -1, 65, 83, 99, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 625, 625, 625, 625, 625, 625, 625, 625, 625, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 634, 634, 634, 634, 634, 634, 78, 78, 78, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 323, 689, -1, -1, -1, 325, -1, 326, 326, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 689, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 438, 438, 438, 439, 439, 439, 439, 439, 439, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 219, 219, 219, 219, 219, 219, 225, 225, 225, 213, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 247, 251, -1, -1, -1, -1, -1, -1, 110, 123, 269, 269, 271, 271, 271, 271, 271, 271, 271, 259, -1, -1, 263, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, 266, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 872, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 657, 657, 657, 657, 657, 657, 657, 657, 657, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 249, 249, 249, 249, 249, 249, 249, 249, 249, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 211, 211, 211, 211, 211, 211, 142, 142, 142, 205, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, 578, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 233, 233, 233, 233, 233, 233, 190, 190, 190, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 341, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775, 775 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776, 776 },
{ -1, 453, 457, -1, -1, -1, 455, -1, 456, 456, -1, 670, 670, 670, 670, 670, 670, 670, 670, 670, 457, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 252 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 401, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 340, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 398, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 759, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 487, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 443, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 401, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 476, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 511, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 787, 97, 97, 97, 890, 97, 97, 97, 97, 97, 921, 97, 97, 124, 97, 97, 97, 97, 97, 97, 97 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 439, 439, 439, 439, 439, 439, 439, 439, 439, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, 247, 251, -1, -1, -1, -1, -1, -1, 110, 123, 271, 271, 271, 271, 271, 271, 271, 271, 271, 259, -1, -1, 263, -1, -1, 177, -1, 187, -1, 194, 4, 200, -1, -1, 206, 212, 218, 266, -1, 224, 230, 236, -1, 42, 242, 858, 678 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 892, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 208, 208, 208, 208, 208, 208, 208, 208, 208, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 404, 405, -1, -1, -1, 406, -1, 407, 407, -1, 253, 253, 253, 253, 253, 253, 253, 253, 253, -1, -1, -1, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, 578, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 578, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676, 676 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 801, 801, 801, 801, 801, 239, 244, 244, 244, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, 518, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 518, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682, 682 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748, 748 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 252, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 296, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 401, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 473, 474, 474, 474, 474, 474, 474, 474, 474, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 449, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 462, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 481, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 799, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 809, 97, 97, 97, 97 },
{ -1, 277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 439, 439, 439, 439, 439, 439, 440, 61, 61, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, 194, -1, -1, -1, -1, 283, -1, -1, -1, -1, -1, 285, 677, -1, -1, 242, -1, 678 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 980, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 208, 208, 208, 208, 208, 214, 214, 214, 214, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 239, 239, 239, 239, 239, 239, 244, 244, 244, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 680, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 328, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 402, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 474, 474, 474, 474, 474, 474, 474, 474, 474, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 1000, 399, 399, 463, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 482, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 816, 97, 97, 97, 97, 97, 97, 97, 973, 97, 97, 97, 97, 97, 157, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 950, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, 360, -1, -1, -1, -1, -1, -1, -1, -1, 214, 214, 214, 214, 214, 214, 214, 214, 214, 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 233, 233, 233, 233, 233, 233, 270, 270, 270, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 252, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 336, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 400, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 568, 568, 568, 568, 568, 568, 568, 568, 568, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 464, 399, 399, 399, 399, 399, 465, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 488, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 905, 97, 97, 97, 908, 97, 97, 97, 97, 97, 168, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 750, 829, 778, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 337, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 401, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 595, 595, 595, 595, 595, 595, 596, 596, 596, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 466, 399, 399, 399, 467, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 715, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 821, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 900, 829, 829, 829, 829, 829, 829, 986 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 343, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 599, 599, 599, 599, 599, 599, 599, 599, 599, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 468, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 469, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 178, 97, 97, 97, 825, 97, 97, 97, 910, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 157, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 957, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 603, 603, 603, 603, 603, 603, 603, 603, 603, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 470, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 908, 97, 97, 188, 97, 97, 97, 97, 97, 97, 912, 97, 97, 97, 97, 97, 195, 97, 982, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 897, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 792, 829, 829, 829, 829, 829, 954, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 606, 606, 606, 606, 606, 606, 607, 599, 599, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 401, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 201, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 729, 729, 729, 729, 729, 729, 729, 729, 729, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 402, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 752, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 614, 614, 614, 614, 614, 614, 614, 614, 614, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 400 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 780, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 618, 618, 618, 618, 618, 618, 618, 618, 618, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 512, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 752, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 512, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 256, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 514, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 812, 256, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 400, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 260, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 515, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 401, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 539, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 564, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 565, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 566, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 602, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 323, 324, -1, -1, -1, 325, -1, 326, 875, -1, 44, 44, 44, 630, 630, 630, 630, 630, 630, 327, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 961, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 981, 399, 850, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 626, 626, 626, 626, 626, 626, 626, 626, 626, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 629, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 323, 688, -1, -1, -1, 325, -1, 326, 875, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 689, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 631, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 969, 399, 399, 399, 399 },
{ -1, 323, 688, -1, -1, -1, 325, -1, 326, 875, -1, 115, 115, 115, 649, 649, 649, 649, 649, 649, 689, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 641, 641, 641, 641, 641, 641, 641, 641, 641, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 833, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 802, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 801, 801, 801, 801, 801, 801, 801, 801, 801, 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789, 789 },
{ -1, -1, -1, -1, -1, -1, -1, 190, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791, 791 },
{ -1, 453, 454, -1, -1, -1, 455, -1, 456, 456, -1, 674, 674, 674, 674, 674, 749, 749, 749, 749, 454, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 873, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 707, 399, 399, 399, 399, 399, 399 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 300, -1, 885, 898, 898, 904, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 866, 866, 774, 790, 790, 790, 790, 790, 790, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 755, 755, 755, 755, 755, 755, 755, 755, 755, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 835, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 834, 834, 834, 834, 834, 834, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 97, 97, 97, 97, 864, 97, 97, 993, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 275, -1, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, -1, 97, 97, 97, 97, 97, 97, 97, 97, 135, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 757, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, 448, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 893, 248, 248, 248, 248, 248, 248, 248 },
{ -1, 323, 324, -1, -1, -1, 325, -1, 326, 875, -1, 630, 630, 630, 630, 630, 630, 630, 630, 630, 327, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 854, 733, 733, 733, 733, 733, 733, 733, 733, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 906, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 851, 399, 399, 399, 981, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 917, 399, 399, 399, 399, 399, 399 },
{ -1, 323, 688, -1, -1, -1, 325, -1, 326, 875, -1, 649, 649, 649, 649, 649, 649, 649, 649, 649, 689, -1, -1, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 836, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 839, 829, 829, 829, 829, 829, 829, 829 },
{ -1, 453, 454, -1, -1, -1, 455, -1, 456, 456, -1, 749, 749, 749, 749, 749, 749, 749, 749, 749, 454, -1, -1, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 977, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 761, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 951, 951, 951, 951, 951, 951, 951, 951, 951, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 838, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 899, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 901, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 733, 733, 733, 733, 733, 733, 733, 733, 733, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 841, 829, 829, 829, 829, 829, 829 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 804, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 827, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 805, 805, 805, 805, 805, 805, 805, 805, 805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 840, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 733, 733, 854, 854, 854, 854, 854, 854, 854, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 841, 829 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 831, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 842, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 836, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 844, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 836, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 831, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 845, 829, 829, 829, 829, 829, 829, 829, 829, 960, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 761, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 846, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 847, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 848, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 852, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 883, 829, 829, 829, 829 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 382, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, 384, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 388, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 300, 300, -1, -1, -1, -1, -1, -1, 874, -1, 9, 9, 9, 9, 9, 9, 9, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 882, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 877, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 920, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 922, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 923, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 924, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 881, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 925, -1, 926, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 927, -1, -1, -1, -1, -1, -1, 919 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 923, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 928, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 929, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 909, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 938, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 937, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 933, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 934, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 940, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 952, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 966, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 971, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 930, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 902, 902, 902, 902, 902, 902, 902, 902, 902, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 907, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 913, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 964, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 991, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 988, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 958, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 909, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 877, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 968, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 911, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 915, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 970, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 913, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 911, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 911, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 916, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 914, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 917, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 913, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 918, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 947, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 931, -1, -1, -1, -1, 932, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 935, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 936, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 939, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 941, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 941, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 983, 248, 248, 248 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 987, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 963, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 953, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 990, 399, 399, 399, 399, 399, 972, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 992, 248, 248, 248, 248, 248 },
{ -1, 275, 275, -1, -1, -1, -1, 81, -1, 359, 320, 6, 6, 6, 624, 732, 732, 732, 732, 732, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 959, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 971, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 962, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 972, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 965, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 967, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 979, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 984, 399, 399, 399, 399, 399 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 997, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 989, 248, 248, 248 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 996, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 97, 97, 97, 999, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97 },
{ -1, -1, -1, -1, -1, -1, -1, 81, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 829, 985, 829, 829, 829, 829, 829, 829 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 320, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 399, 994, 399, 399, 399, 399, 399, 399, 399 }
};
private static int[] yy_state_dtrans = new int[]
{
0
};
#endregion
public Tokens GetNextToken()
{
int current_state = yy_state_dtrans[(int)current_lexical_state];
int last_accept_state = NoState;
bool is_initial_state = true;
MarkTokenChunkStart();
token_start = token_chunk_start;
expanding_token = false;
if (acceptCondition[current_state] != AcceptConditions.NotAccept)
{
last_accept_state = current_state;
MarkTokenEnd();
}
while (true)
{
char lookahead = (is_initial_state && yy_at_bol) ? BOL : Advance();
int next_state = nextState[rowMap[current_state], colMap[lookahead]];
if (lookahead == EOF && is_initial_state)
{
return Tokens.EOF;
}
if (next_state != -1)
{
current_state = next_state;
is_initial_state = false;
if (acceptCondition[current_state] != AcceptConditions.NotAccept)
{
last_accept_state = current_state;
MarkTokenEnd();
}
}
else
{
if (last_accept_state == NoState)
{
return Tokens.ERROR;
}
else
{
if ((acceptCondition[last_accept_state] & AcceptConditions.AcceptOnEnd) != 0)
TrimTokenEnd();
MoveToTokenEnd();
if (last_accept_state < 0)
{
System.Diagnostics.Debug.Assert(last_accept_state >= 1001);
}
else
{
bool accepted = false;
yyreturn = Accept0(last_accept_state, out accepted);
if (accepted)
{
return yyreturn;
}
}
// token ignored:
is_initial_state = true;
current_state = yy_state_dtrans[(int)current_lexical_state];
last_accept_state = NoState;
MarkTokenChunkStart();
if (acceptCondition[current_state] != AcceptConditions.NotAccept)
{
last_accept_state = current_state;
MarkTokenEnd();
}
}
}
}
} // end of GetNextToken
}
}
================================================
FILE: Source/ClassLibrary/Generated/jsonLexer.cs
================================================
namespace PHP.Library.Json
{
#region User Code
using System;
using System.Text;
using System.Collections.Generic;
#endregion
public partial class Lexer
{
public enum LexicalStates
{
INITIAL = 0,
IN_STRING = 1,
}
[Flags]
private enum AcceptConditions : byte
{
NotAccept = 0,
AcceptOnStart = 1,
AcceptOnEnd = 2,
Accept = 4
}
private const int NoState = -1;
private const char BOL = (char)128;
private const char EOF = (char)129;
private Tokens yyreturn;
// content of the STRING literal text
protected string yytext()
{
return new String(buffer, token_start, token_end - token_start);
}
private StringBuilder str = null;
protected string QuotedStringContent{get{return str.ToString();}}
private System.IO.TextReader reader;
private char[] buffer = new char[512];
// whether the currently parsed token is being expanded (yymore has been called):
private bool expanding_token;
// offset in buffer where the currently parsed token starts:
private int token_start;
// offset in buffer where the currently parsed token chunk starts:
private int token_chunk_start;
// offset in buffer one char behind the currently parsed token (chunk) ending character:
private int token_end;
// offset of the lookahead character (number of characters parsed):
private int lookahead_index;
// number of characters read into the buffer:
private int chars_read;
private bool yy_at_bol = false;
public LexicalStates CurrentLexicalState { get { return current_lexical_state; } set { current_lexical_state = value; } }
private LexicalStates current_lexical_state;
public Lexer(System.IO.TextReader reader)
{
Initialize(reader, LexicalStates.INITIAL);
}
public void Initialize(System.IO.TextReader reader, LexicalStates lexicalState, bool atBol)
{
this.expanding_token = false;
this.token_start = 0;
this.chars_read = 0;
this.lookahead_index = 0;
this.token_chunk_start = 0;
this.token_end = 0;
this.reader = reader;
this.yy_at_bol = atBol;
this.current_lexical_state = lexicalState;
}
public void Initialize(System.IO.TextReader reader, LexicalStates lexicalState)
{
Initialize(reader, lexicalState, false);
}
#region Accept
#pragma warning disable 162
Tokens Accept0(int state,out bool accepted)
{
accepted = true;
switch(state)
{
case 2:
// #line 54
{return Tokens.ARRAY_OPEN;}
break;
case 3:
// #line 55
{return Tokens.ARRAY_CLOSE;}
break;
case 4:
// #line 56
{return Tokens.ITEMS_SEPARATOR;}
break;
case 5:
// #line 57
{return Tokens.NAMEVALUE_SEPARATOR;}
break;
case 6:
// #line 58
{return Tokens.OBJECT_OPEN;}
break;
case 7:
// #line 59
{return Tokens.OBJECT_CLOSE;}
break;
case 8:
// #line 64
{return Tokens.INTEGER;}
break;
case 9:
// #line 65
{}
break;
case 10:
// #line 67
{BEGIN(LexicalStates.IN_STRING); str = new StringBuilder(); return Tokens.STRING_BEGIN;}
break;
case 11:
// #line 63
{return Tokens.DOUBLE;}
break;
case 12:
// #line 60
{return Tokens.TRUE;}
break;
case 13:
// #line 62
{return Tokens.NULL;}
break;
case 14:
// #line 61
{return Tokens.FALSE;}
break;
case 15:
// #line 68
{str.Append(yytext()); return Tokens.CHARS;}
break;
case 16:
// #line 78
{BEGIN(LexicalStates.INITIAL); return Tokens.STRING_END;}
break;
case 17:
// #line 74
{str.Append('\t'); return Tokens.ESCAPEDCHAR;}
break;
case 18:
// #line 72
{str.Append('\r'); return Tokens.ESCAPEDCHAR;}
break;
case 19:
// #line 70
{str.Append('\f'); return Tokens.ESCAPEDCHAR;}
break;
case 20:
// #line 73
{str.Append('\n'); return Tokens.ESCAPEDCHAR;}
break;
case 21:
// #line 77
{str.Append('"'); return Tokens.ESCAPEDCHAR;}
break;
case 22:
// #line 75
{str.Append('\\'); return Tokens.ESCAPEDCHAR;}
break;
case 23:
// #line 71
{str.Append('\b'); return Tokens.ESCAPEDCHAR;}
break;
case 24:
// #line 76
{str.Append('/'); return Tokens.ESCAPEDCHAR;}
break;
case 25:
// #line 69
{str.Append((char)int.Parse(yytext().Substring(2), System.Globalization.NumberStyles.HexNumber)); return Tokens.UNICODECHAR;}
break;
case 27: goto case 11;
}
accepted = false;
return yyreturn;
}
#pragma warning restore 162
#endregion
private void BEGIN(LexicalStates state)
{
current_lexical_state = state;
}
private char Advance()
{
if (lookahead_index >= chars_read)
{
if (token_start > 0)
{
// shift buffer left:
int length = chars_read - token_start;
System.Buffer.BlockCopy(buffer, token_start << 1, buffer, 0, length << 1);
token_end -= token_start;
token_chunk_start -= token_start;
token_start = 0;
chars_read = lookahead_index = length;
// populate the remaining bytes:
int count = reader.Read(buffer, chars_read, buffer.Length - chars_read);
if (count <= 0) return EOF;
chars_read += count;
}
while (lookahead_index >= chars_read)
{
if (lookahead_index >= buffer.Length)
buffer = ResizeBuffer(buffer);
int count = reader.Read(buffer, chars_read, buffer.Length - chars_read);
if (count <= 0) return EOF;
chars_read += count;
}
}
return Map(buffer[lookahead_index++]);
}
private char[] ResizeBuffer(char[] buf)
{
char[] result = new char[buf.Length << 1];
System.Buffer.BlockCopy(buf, 0, result, 0, buf.Length << 1);
return result;
}
private void TrimTokenEnd()
{
if (token_end > token_chunk_start && buffer[token_end - 1] == '\n')
token_end--;
if (token_end > token_chunk_start && buffer[token_end - 1] == '\r')
token_end--;
}
private void MarkTokenChunkStart()
{
token_chunk_start = lookahead_index;
}
private void MarkTokenEnd()
{
token_end = lookahead_index;
}
private void MoveToTokenEnd()
{
lookahead_index = token_end;
yy_at_bol = (token_end > token_chunk_start) && (buffer[token_end - 1] == '\r' || buffer[token_end - 1] == '\n');
}
public int TokenLength
{
get { return token_end - token_start; }
}
public int TokenChunkLength
{
get { return token_end - token_chunk_start; }
}
private void yymore()
{
if (!expanding_token)
{
token_start = token_chunk_start;
expanding_token = true;
}
}
private void yyless(int count)
{
lookahead_index = token_end = token_chunk_start + count;
}
private Stack stateStack = new Stack(20);
private void yy_push_state(LexicalStates state)
{
stateStack.Push(current_lexical_state);
current_lexical_state = state;
}
private bool yy_pop_state()
{
if (stateStack.Count == 0) return false;
current_lexical_state = stateStack.Pop();
return true;
}
private LexicalStates yy_top_state()
{
return stateStack.Peek();
}
#region Tables
private static AcceptConditions[] acceptCondition = new AcceptConditions[]
{
AcceptConditions.NotAccept, // 0
AcceptConditions.Accept, // 1
AcceptConditions.Accept, // 2
AcceptConditions.Accept, // 3
AcceptConditions.Accept, // 4
AcceptConditions.Accept, // 5
AcceptConditions.Accept, // 6
AcceptConditions.Accept, // 7
AcceptConditions.Accept, // 8
AcceptConditions.Accept, // 9
AcceptConditions.Accept, // 10
AcceptConditions.Accept, // 11
AcceptConditions.Accept, // 12
AcceptConditions.Accept, // 13
AcceptConditions.Accept, // 14
AcceptConditions.Accept, // 15
AcceptConditions.Accept, // 16
AcceptConditions.Accept, // 17
AcceptConditions.Accept, // 18
AcceptConditions.Accept, // 19
AcceptConditions.Accept, // 20
AcceptConditions.Accept, // 21
AcceptConditions.Accept, // 22
AcceptConditions.Accept, // 23
AcceptConditions.Accept, // 24
AcceptConditions.Accept, // 25
AcceptConditions.NotAccept, // 26
AcceptConditions.Accept, // 27
AcceptConditions.NotAccept, // 28
AcceptConditions.NotAccept, // 29
AcceptConditions.NotAccept, // 30
AcceptConditions.NotAccept, // 31
AcceptConditions.NotAccept, // 32
AcceptConditions.NotAccept, // 33
AcceptConditions.NotAccept, // 34
AcceptConditions.NotAccept, // 35
AcceptConditions.NotAccept, // 36
AcceptConditions.NotAccept, // 37
AcceptConditions.NotAccept, // 38
AcceptConditions.NotAccept, // 39
AcceptConditions.NotAccept, // 40
AcceptConditions.NotAccept, // 41
AcceptConditions.NotAccept, // 42
AcceptConditions.NotAccept, // 43
AcceptConditions.NotAccept, // 44
AcceptConditions.NotAccept, // 45
AcceptConditions.NotAccept, // 46
AcceptConditions.NotAccept, // 47
};
private static int[] colMap = new int[]
{
23, 23, 23, 23, 23, 23, 23, 23, 23, 20, 20, 23, 23, 20, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
20, 23, 22, 23, 23, 23, 23, 23, 23, 23, 23, 19, 3, 16, 18, 27,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 4, 23, 23, 23, 23, 23,
23, 12, 26, 25, 25, 10, 11, 23, 23, 23, 23, 23, 13, 23, 15, 23,
23, 23, 8, 14, 7, 9, 23, 23, 23, 23, 23, 1, 24, 2, 23, 23,
23, 12, 26, 25, 25, 10, 11, 23, 23, 23, 23, 23, 13, 23, 15, 23,
23, 23, 8, 14, 7, 9, 23, 23, 23, 23, 23, 5, 21, 6, 23, 23,
0, 0
};
private static int[] rowMap = new int[]
{
0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 4,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 3, 16, 11, 17, 18, 19, 20, 21, 22, 23, 24
};
private static int[,] nextState = new int[,]
{
{ 1, 2, 3, 4, 5, 6, 7, 26, -1, -1, -1, 28, -1, -1, -1, 29, 30, 8, -1, -1, 9, 9, 10, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, 8, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -1, 15, -1, 15, 15, 15 },
{ -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 11, -1, 37, -1, 37, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 15, 41, 15, 15, 15 },
{ -1, -1, -1, -1, -1, -1, -1, 17, 18, 42, -1, 19, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, 21, -1, 22, -1, 23, 24 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 47, 47, 47, -1, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 47, 47, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25, 25, 25, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1, 25, 25, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, 43, 43, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, 43, 43, -1 },
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46, 46, 46, -1, -1, -1, -1, 46, -1, -1, -1, -1, -1, -1, -1, 46, 46, -1 }
};
private static int[] yy_state_dtrans = new int[]
{
0,
40
};
#endregion
public Tokens GetNextToken()
{
int current_state = yy_state_dtrans[(int)current_lexical_state];
int last_accept_state = NoState;
bool is_initial_state = true;
MarkTokenChunkStart();
token_start = token_chunk_start;
expanding_token = false;
if (acceptCondition[current_state] != AcceptConditions.NotAccept)
{
last_accept_state = current_state;
MarkTokenEnd();
}
while (true)
{
char lookahead = (is_initial_state && yy_at_bol) ? BOL : Advance();
int next_state = nextState[rowMap[current_state], colMap[lookahead]];
if (lookahead == EOF && is_initial_state)
{
return Tokens.EOF;
}
if (next_state != -1)
{
current_state = next_state;
is_initial_state = false;
if (acceptCondition[current_state] != AcceptConditions.NotAccept)
{
last_accept_state = current_state;
MarkTokenEnd();
}
}
else
{
if (last_accept_state == NoState)
{
return Tokens.ERROR;
}
else
{
if ((acceptCondition[last_accept_state] & AcceptConditions.AcceptOnEnd) != 0)
TrimTokenEnd();
MoveToTokenEnd();
if (last_accept_state < 0)
{
System.Diagnostics.Debug.Assert(last_accept_state >= 48);
}
else
{
bool accepted = false;
yyreturn = Accept0(last_accept_state, out accepted);
if (accepted)
{
return yyreturn;
}
}
// token ignored:
is_initial_state = true;
current_state = yy_state_dtrans[(int)current_lexical_state];
last_accept_state = NoState;
MarkTokenChunkStart();
if (acceptCondition[current_state] != AcceptConditions.NotAccept)
{
last_accept_state = current_state;
MarkTokenEnd();
}
}
}
}
} // end of GetNextToken
}
}
================================================
FILE: Source/ClassLibrary/Generated/jsonParser.cs
================================================
// This code was generated by the Gardens Point Parser Generator
// Copyright (c) Wayne Kelly, QUT 2005
// (see accompanying GPPGcopyright.rtf)
using System;
using System.Text;
using System.Collections.Generic;
using PHP.Core;
using PHP.Core.Parsers.GPPG;
using System.Diagnostics;
namespace PHP.Library.Json
{
public enum Tokens {ERROR=1,EOF=2,ARRAY_OPEN=3,ARRAY_CLOSE=4,ITEMS_SEPARATOR=5,NAMEVALUE_SEPARATOR=6,OBJECT_OPEN=7,OBJECT_CLOSE=8,TRUE=9,FALSE=10,NULL=11,INTEGER=12,DOUBLE=13,STRING=14,STRING_BEGIN=15,CHARS=16,UNICODECHAR=17,ESCAPEDCHAR=18,STRING_END=19};
public partial struct SemanticValueType
{
public object obj;
}
public partial struct Position
{
public int FirstLine;
public int FirstColumn;
public int FirstOffset;
public int LastLine;
public int LastColumn;
public int LastOffset;
public Position(int firstLine, int firstColumn, int firstOffset, int lastLine, int lastColumn, int lastOffset)
{
this.FirstLine = firstLine;
this.FirstColumn = firstColumn;
this.FirstOffset = firstOffset;
this.LastLine = lastLine;
this.LastColumn = lastColumn;
this.LastOffset = lastOffset;
}
}
public partial class Parser: ShiftReduceParser
{
protected override string[] NonTerminals { get { return nonTerminals; } }
private static string[] nonTerminals;
protected override State[] States { get { return states; } }
private static State[] states;
protected override Rule[] Rules { get { return rules; } }
private static Rule[] rules;
protected sealed override Position CombinePositions(Position first, Position last)
{
return new Position(first.FirstLine, first.FirstColumn, first.FirstOffset, last.LastLine, last.LastColumn, last.LastOffset);
}
#region Construction
static Parser()
{
states = new State[]
{
new State(0, new int[] {14,4,12,5,13,6,7,8,3,19,9,26,10,27,11,28}, new int[] {-1,1,-3,3,-4,7,-7,18}),
new State(1, new int[] {2,2}),
new State(2, -1),
new State(3, -2),
new State(4, -12),
new State(5, -13),
new State(6, -14),
new State(7, -15),
new State(8, new int[] {8,11,14,15}, new int[] {-5,9,-6,12}),
new State(9, new int[] {8,10}),
new State(10, -3),
new State(11, -4),
new State(12, new int[] {5,13,8,-6}),
new State(13, new int[] {14,15}, new int[] {-5,14,-6,12}),
new State(14, -5),
new State(15, new int[] {6,16}),
new State(16, new int[] {14,4,12,5,13,6,7,8,3,19,9,26,10,27,11,28}, new int[] {-3,17,-4,7,-7,18}),
new State(17, -7),
new State(18, -16),
new State(19, new int[] {4,22,14,4,12,5,13,6,7,8,3,19,9,26,10,27,11,28}, new int[] {-8,20,-3,23,-4,7,-7,18}),
new State(20, new int[] {4,21}),
new State(21, -8),
new State(22, -9),
new State(23, new int[] {5,24,4,-11}),
new State(24, new int[] {14,4,12,5,13,6,7,8,3,19,9,26,10,27,11,28}, new int[] {-8,25,-3,23,-4,7,-7,18}),
new State(25, -10),
new State(26, -17),
new State(27, -18),
new State(28, -19),
};
rules = new Rule[20];
rules[1]=new Rule(-2, new int[]{-1,2});
rules[2]=new Rule(-1, new int[]{-3});
rules[3]=new Rule(-4, new int[]{7,-5,8});
rules[4]=new Rule(-4, new int[]{7,8});
rules[5]=new Rule(-5, new int[]{-6,5,-5});
rules[6]=new Rule(-5, new int[]{-6});
rules[7]=new Rule(-6, new int[]{14,6,-3});
rules[8]=new Rule(-7, new int[]{3,-8,4});
rules[9]=new Rule(-7, new int[]{3,4});
rules[10]=new Rule(-8, new int[]{-3,5,-8});
rules[11]=new Rule(-8, new int[]{-3});
rules[12]=new Rule(-3, new int[]{14});
rules[13]=new Rule(-3, new int[]{12});
rules[14]=new Rule(-3, new int[]{13});
rules[15]=new Rule(-3, new int[]{-4});
rules[16]=new Rule(-3, new int[]{-7});
rules[17]=new Rule(-3, new int[]{9});
rules[18]=new Rule(-3, new int[]{10});
rules[19]=new Rule(-3, new int[]{11});
nonTerminals = new string[] {"", "start", "$accept", "value", "object",
"members", "pair", "array", "elements", };
}
#endregion
protected override void DoAction(int action)
{
switch (action)
{
case 2: // start -> value
{ Result = value_stack.array[value_stack.top-1].yyval.obj; }
return;
case 3: // object -> OBJECT_OPEN members OBJECT_CLOSE
{
var elements = (List>)value_stack.array[value_stack.top-2].yyval.obj;
if (decodeOptions.Assoc)
{
var arr = new PhpArray( elements.Count );
foreach (var item in elements)
arr.Add( PHP.Core.Convert.StringToArrayKey(item.Key), item.Value );
yyval.obj = arr;
}
else
{
var std = new stdClass(context, true);
std.AddRange( elements );
yyval.obj = std;
}
}
return;
case 4: // object -> OBJECT_OPEN OBJECT_CLOSE
{ yyval.obj = new stdClass(context, true); }
return;
case 5: // members -> pair ITEMS_SEPARATOR members
{
var elements = (List>)value_stack.array[value_stack.top-1].yyval.obj;
var result = new List>( elements.Count + 1 ){ (KeyValuePair)value_stack.array[value_stack.top-3].yyval.obj };
result.AddRange(elements);
yyval.obj = result;
}
return;
case 6: // members -> pair
{ yyval.obj = new List>(){ (KeyValuePair)value_stack.array[value_stack.top-1].yyval.obj }; }
return;
case 7: // pair -> STRING NAMEVALUE_SEPARATOR value
{ yyval.obj = new KeyValuePair((string)value_stack.array[value_stack.top-3].yyval.obj, value_stack.array[value_stack.top-1].yyval.obj); }
return;
case 8: // array -> ARRAY_OPEN elements ARRAY_CLOSE
{
var elements = (List)value_stack.array[value_stack.top-2].yyval.obj;
var arr = new PhpArray( elements.Count );
foreach (var item in elements)
arr.Add( item );
yyval.obj = arr;
}
return;
case 9: // array -> ARRAY_OPEN ARRAY_CLOSE
{ yyval.obj = new PhpArray(); }
return;
case 10: // elements -> value ITEMS_SEPARATOR elements
{
var elements = (List)value_stack.array[value_stack.top-1].yyval.obj;
var result = new List( elements.Count + 1 ){ value_stack.array[value_stack.top-3].yyval.obj };
result.AddRange(elements);
yyval.obj = result;
}
return;
case 11: // elements -> value
{ yyval.obj = new List(){ value_stack.array[value_stack.top-1].yyval.obj }; }
return;
case 12: // value -> STRING
{yyval.obj = value_stack.array[value_stack.top-1].yyval.obj;}
return;
case 13: // value -> INTEGER
{yyval.obj = value_stack.array[value_stack.top-1].yyval.obj;}
return;
case 14: // value -> DOUBLE
{yyval.obj = value_stack.array[value_stack.top-1].yyval.obj;}
return;
case 15: // value -> object
{yyval.obj = value_stack.array[value_stack.top-1].yyval.obj;}
return;
case 16: // value -> array
{yyval.obj = value_stack.array[value_stack.top-1].yyval.obj;}
return;
case 17: // value -> TRUE
{yyval.obj = true;}
return;
case 18: // value -> FALSE
{yyval.obj = false;}
return;
case 19: // value -> NULL
{yyval.obj = null;}
return;
}
}
protected override string TerminalToString(int terminal)
{
if (((Tokens)terminal).ToString() != terminal.ToString())
return ((Tokens)terminal).ToString();
else
return CharToString((char)terminal);
}
protected override int EofToken { get { return (int)Tokens.EOF; } }
protected override int ErrorToken { get { return (int)Tokens.ERROR; } }
private readonly ScriptContext/*!*/context;
private readonly PHP.Library.JsonFormatter.DecodeOptions/*!*/decodeOptions;
public Parser(ScriptContext/*!*/context, PHP.Library.JsonFormatter.DecodeOptions/*!*/decodeOptions)
{
System.Diagnostics.Debug.Assert(context != null && decodeOptions != null);
this.context = context;
this.decodeOptions = decodeOptions;
}
public object Result{get;private set;}
}
}
================================================
FILE: Source/ClassLibrary/Generators/Generate.cmd
================================================
"..\..\..\Tools\cslex" "StrToTime.lex" "..\Generated\StrToTimeScanner.cs" /v:2
"..\..\..\Tools\cslex" "json.lex" "..\Generated\jsonLexer.cs" /v:2
"..\..\..\Tools\gppg" /l /r "json.y" "..\Generated\jsonParser.cs" "..\Generated\json.log"
pause
================================================
FILE: Source/ClassLibrary/Generators/StrToTime.lex
================================================
using System;
using System.Collections.Generic;
/*
Copyright (c) 2005-2006 Tomas Matousek. Based on PHP5 implementation by Derick Rethans .
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
%%
%namespace PHP.Library.StrToTime
%type Tokens
%eofval Tokens.EOF
%errorval Tokens.ERROR
%attributes internal
%class Scanner
%function GetNextToken
%{
internal DateInfo Time { get { return time; } }
private DateInfo time = new DateInfo();
internal int Errors { get { return errors; } }
private int errors = 0;
internal int Position { get { return pos; } }
private int pos = 0;
private string str;
void INIT()
{
str = new string(buffer, token_start, token_end - token_start);
pos = 0;
}
void DEINIT()
{
}
%}
any [\000-\377]
frac "."[0-9]+
az14 [a-z]|[a-z][a-z]|[a-z][a-z][a-z]|[a-z][a-z][a-z][a-z]
ago "ago"
hour24 [01]?[0-9]|"2"[0-4]
hour24lz [01][0-9]|"2"[0-4]
hour12 "0"?[1-9]|"1"[0-2]
minute [0-5]?[0-9]
minutelz [0-5][0-9]
second {minute}|"60"
secondlz {minutelz}|"60"
meridian [ap]"."?m"."?
daysuf "st"|"nd"|"rd"|"th"
tz "("?{az14}")"?|[a-z][a-z]+([_/][a-z][a-z]+)+
tzcorrection [+-]{hour24}":"?{minute}?
zone {tzcorrection}|{tz}
month "0"?[0-9]|"1"[0-2]
day ([0-2]?[0-9]|"3"[01]){daysuf}?
year [0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]
year2 [0-9][0-9]
year4 [0-9][0-9][0-9][0-9]
dayofyear "00"[1-9]|"0"[1-9][0-9]|[1-2][0-9][0-9]|"3"[0-5][0-9]|"36"[0-6]
weekofyear "0"[1-9]|[1-4][0-9]|"5"[0-3]
monthlz "0"[1-9]|"1"[0-2]
daylz "0"[1-9]|[1-2][0-9]|"3"[01]
dayfull "sunday"|"monday"|"tuesday"|"wednesday"|"thursday"|"friday"|"saturday"
dayabbr "sun"|"mon"|"tue"|"wed"|"thu"|"fri"|"sat"|"sun"
daytext {dayfull}|{dayabbr}
monthfull "january"|"february"|"march"|"april"|"may"|"june"|"july"|"august"|"september"|"october"|"november"|"december"
monthabbr "jan"|"feb"|"mar"|"apr"|"may"|"jun"|"jul"|"aug"|"sep"|"sept"|"oct"|"nov"|"dec"
monthroman "i"|"ii"|"iii"|"iv"|"v"|"vi"|"vii"|"viii"|"ix"|"x"|"xi"|"xii"
monthtext {monthfull}|{monthabbr}|{monthroman}
timetiny12 {hour12}[ ]*{meridian}
timeshort12 {hour12}[:.]{minutelz}[ ]*{meridian}
timelong12 {hour12}[:.]{minute}[:.]{secondlz}[ ]*{meridian}
timeshort24 {hour24}[:.]{minute}([ ]*{zone})?
timelong24 {hour24}[:.]{minute}[:.]{second}([ ]*{zone})?
iso8601long {hour24}[:.]{minute}[:.]{second}{frac}([ ]*{zone})?
iso8601normtz {hour24}[:.]{minute}[:.]{secondlz}[ ]*{zone}
gnunocolon {hour24lz}{minutelz}
iso8601nocolon {hour24lz}{minutelz}{secondlz}
americanshort {month}"/"{day}
american {month}"/"{day}"/"{year}
iso8601dateslash {year4}"/"{monthlz}"/"{daylz}"/"?
pointeddate4 {day}[-.]{month}[-.]{year4}
gnudateshort {year}"-"{month}"-"{day}
iso8601date {year4}"-"{monthlz}"-"{daylz}
pointeddate2 {day}"."{month}"."{year2}
datefull {day}([-. ])*{monthtext}([-. ])*{year}
datenoday {monthtext}([-. ])*{year4}
datenodayrev {year4}([-. ])*{monthtext}
datetextual {monthtext}([-. ])*{day}[,.stndrh ]*{year}
datenoyear {monthtext}([-. ])*{day}[,.stndrh ]*
datenoyearrev {day}([-. ])*{monthtext}
datenocolon {year4}{monthlz}{daylz}
soap {year4}"-"{monthlz}"-"{daylz}"t"{hour24lz}":"{minutelz}":"{secondlz}{frac}{tzcorrection}?
xmlrpc {year4}{monthlz}{daylz}"t"{hour24}":"{minutelz}":"{secondlz}
xmlrpcnocolon {year4}{monthlz}{daylz}"t"{hour24}{minutelz}{secondlz}
wddx {year4}"-"{month}"-"{day}"t"{hour24}":"{minute}":"{second}
pgydotd {year4}"."?{dayofyear}
pgtextshort {monthabbr}"-"{daylz}"-"{year}
pgtextreverse {year}"-"{monthabbr}"-"{daylz}
isoweekday {year4}"w"{weekofyear}[0-7]
isoweek {year4}"w"{weekofyear}
clf {day}"/"{monthabbr}"/"{year4}":"{hour24lz}":"{minutelz}":"{secondlz}[ ]+{tzcorrection}
timestamp "@""-"?[1-9][0-9]*
dateshortwithtimeshort {datenoyear}{timeshort24}
dateshortwithtimelong {datenoyear}{timelong24}
dateshortwithtimelongtz {datenoyear}{iso8601normtz}
reltextnumber "first"|"next"|"second"|"third"|"fourth"|"fifth"|"sixth"|"seventh"|"eight"|"ninth"|"tenth"|"eleventh"|"twelfth"|"last"|"previous"|"this"
reltextunit (("sec"|"second"|"min"|"minute"|"hour"|"day"|"week"|"fortnight"|"forthnight"|"month"|"year")"s"?)|{daytext}
relnumber ([+-]?[ ]*[0-9]+)
relative {relnumber}[ ]*{reltextunit}
relativetext {reltextnumber}[ ]*{reltextunit}
%%
"yesterday" {
INIT();
time.HAVE_RELATIVE();
time.UNHAVE_TIME();
time.relative.d = -1;
DEINIT();
return Tokens.RELATIVE;
}
"now" {
INIT();
DEINIT();
return Tokens.RELATIVE;
}
"noon" {
INIT();
time.UNHAVE_TIME();
time.HAVE_TIME();
time.h = 12;
DEINIT();
return Tokens.RELATIVE;
}
"midnight"|"today" {
INIT();
time.UNHAVE_TIME();
DEINIT();
return Tokens.RELATIVE;
}
"tomorrow" {
INIT();
time.HAVE_RELATIVE();
time.UNHAVE_TIME();
time.relative.d = 1;
DEINIT();
return Tokens.RELATIVE;
}
{timestamp} {
INIT();
time.HAVE_RELATIVE();
time.UNHAVE_DATE();
time.UNHAVE_TIME();
int i = DateInfo.ParseSignedInt(str, ref pos, 24);
time.y = 1970;
time.m = 1;
time.d = 1;
time.h = time.i = time.s = 0;
time.f = 0.0;
time.relative.s += i;
time.z = 0;
time.HAVE_TZ();
DEINIT();
return Tokens.RELATIVE;
}
{timetiny12}|{timeshort12}|{timelong12} {
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && (str[pos] == ':' || str[pos] == '.'))
{
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && (str[pos] == ':' || str[pos] == '.'))
{
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
}
}
if (!time.SetMeridian(str, ref pos))
{
return Tokens.ERROR;
}
DEINIT();
return Tokens.TIME12;
}
{timeshort24}|{timelong24}|{iso8601long} {
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && (str[pos] == ':' || str[pos] == '.'))
{
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '.')
time.f = DateInfo.ParseFraction(str, ref pos, 8);
}
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.TIME24_WITH_ZONE;
}
{gnunocolon} {
INIT();
switch (time.have_time)
{
case 0:
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = 0;
break;
case 1:
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
break;
default:
DEINIT();
return Tokens.ERROR;
}
time.have_time++;
DEINIT();
return Tokens.GNU_NOCOLON;
}
{iso8601nocolon} {
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.ISO_NOCOLON;
}
{americanshort}|{american} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '/')
{
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
}
DEINIT();
return Tokens.AMERICAN;
}
{iso8601date}|{iso8601dateslash} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DEINIT();
return Tokens.ISO_DATE;
}
{datefull} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR;}
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DateInfo.SkipDaySuffix(str, ref pos);
time.m = DateInfo.ParseMonth(str, ref pos);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_FULL;
}
{gnudateshort} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.ISO_DATE;
}
{pointeddate4} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR;}
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
DEINIT();
return Tokens.DATE_FULL_POINTED;
}
{pointeddate2} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR;}
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_FULL_POINTED;
}
{datenoday} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.d = 1;
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_NO_DAY;
}
{datenodayrev} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = 1;
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_NO_DAY;
}
{datetextual}|{datenoyear}
{
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.DATE_TEXT;
}
{datenoyearrev} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DateInfo.SkipDaySuffix(str, ref pos);
time.m = DateInfo.ParseMonth(str, ref pos);
DEINIT();
return Tokens.DATE_TEXT;
}
{datenocolon} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
DEINIT();
return Tokens.DATE_NOCOLON;
}
{xmlrpc}|{xmlrpcnocolon}|{soap}|{wddx} {
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '.')
{
time.f = DateInfo.ParseFraction(str, ref pos, 9);
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
}
DEINIT();
return Tokens.XMLRPC_SOAP;
}
{pgydotd} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 3);
time.m = 1;
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.PG_YEARDAY;
}
{isoweekday} {
int week, day;
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.HAVE_RELATIVE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
week = DateInfo.ParseUnsignedInt(str, ref pos, 2);
day = DateInfo.ParseUnsignedInt(str, ref pos, 1);
time.m = 1;
time.d = 1;
time.relative.d = DateInfo.WeekToDay(time.y, week, day);
DEINIT();
return Tokens.ISO_WEEK;
}
{isoweek} {
{
int w, d;
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.HAVE_RELATIVE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
w = DateInfo.ParseUnsignedInt(str, ref pos, 2);
d = 1;
time.m = 1;
time.d = 1;
time.relative.d = DateInfo.WeekToDay(time.y, w, d);
DEINIT();
return Tokens.ISO_WEEK;
}
}
{pgtextshort} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.PG_TEXT;
}
{pgtextreverse} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.y = DateInfo.ProcessYear(time.y);
DEINIT();
return Tokens.PG_TEXT;
}
{clf} {
INIT();
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.m = DateInfo.ParseMonth(str, ref pos);
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.CLF;
}
{year4} {
INIT();
time.y = DateInfo.ParseUnsignedInt(str, ref pos, 4);
DEINIT();
return Tokens.CLF;
}
{ago} {
INIT();
time.relative.y = -time.relative.y;
time.relative.m = -time.relative.m;
time.relative.d = -time.relative.d;
time.relative.h = -time.relative.h;
time.relative.i = -time.relative.i;
time.relative.s = -time.relative.s;
time.relative.weekday = -time.relative.weekday;
DEINIT();
return Tokens.AGO;
}
{relativetext} {
INIT();
time.HAVE_RELATIVE();
while (pos < str.Length)
{
int behavior;
int amount = DateInfo.ParseRelativeText(str, ref pos, out behavior);
while (pos < str.Length && str[pos] == ' ') pos++;
time.SetRelative(DateInfo.ReadToSpace(str,ref pos), amount, behavior);
}
DEINIT();
return Tokens.RELATIVE;
}
{daytext} {
INIT();
time.HAVE_RELATIVE();
time.HAVE_WEEKDAY_RELATIVE();
time.UNHAVE_TIME();
time.SetWeekDay(DateInfo.ReadToSpace(str,ref pos));
time.relative.weekday_behavior = 1;
DEINIT();
return Tokens.WEEKDAY;
}
{tzcorrection}|{tz}
{
INIT();
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.TIMEZONE;
}
{dateshortwithtimeshort}|{dateshortwithtimelong}|{dateshortwithtimelongtz} {
INIT();
if (time.have_date!=0) { return Tokens.ERROR; }
time.HAVE_DATE();
time.m = DateInfo.ParseMonth(str, ref pos);
time.d = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (time.have_time!=0) { return Tokens.ERROR; }
time.HAVE_TIME();
time.h = DateInfo.ParseUnsignedInt(str, ref pos, 2);
time.i = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == ':')
{
time.s = DateInfo.ParseUnsignedInt(str, ref pos, 2);
if (pos < str.Length && str[pos] == '.')
time.f = DateInfo.ParseFraction(str, ref pos, 8);
}
if (pos < str.Length)
errors += time.SetTimeZone(str, ref pos) ? 0 : 1;
DEINIT();
return Tokens.SHORTDATE_WITH_TIME;
}
{relative} {
INIT();
time.HAVE_RELATIVE();
while(pos < str.Length)
{
int amount = DateInfo.ParseSignedInt(str, ref pos, 24);
while (pos < str.Length && str[pos] == ' ') pos++;
time.SetRelative(DateInfo.ReadToSpace(str, ref pos), amount, 0);
}
DEINIT();
return Tokens.RELATIVE;
}
[ .,\0\n\r\t] {
break;
}
{any} {
return Tokens.ERROR;
}
================================================
FILE: Source/ClassLibrary/Generators/json.lex
================================================
using System;
using System.Text;
using System.Collections.Generic;
%%
%namespace PHP.Library.Json
%type Tokens
%class Lexer
%eofval Tokens.EOF
%errorval Tokens.ERROR
%attributes public partial
%charmap Map
%function GetNextToken
%ignorecase
%{
// content of the STRING literal text
protected string yytext()
{
return new String(buffer, token_start, token_end - token_start);
}
private StringBuilder str = null;
protected string QuotedStringContent{get{return str.ToString();}}
%}
e e[\+|\-]?
hex [0-9a-fA-F]
digit [0-9]
digit1 [1-9]
digits {digit}+
exp {e}{digits}
frac "."{digits}
int -?{digits}
double {int}({frac}{exp}|{frac}|{exp})
integer {int}
quote \"
charUnicode \\u{hex}{hex}{hex}{hex}
charNormal [^\"\\]
charEscaped [\\f|\\b|\\r|\\n|\\t|\\\\|\\/|\\\"]
whitespace [\r|\n|\t| ] // whitespaces allowed between tokens
%x INITIAL
%x IN_STRING
%%
"[" {return Tokens.ARRAY_OPEN;}
"]" {return Tokens.ARRAY_CLOSE;}
"," {return Tokens.ITEMS_SEPARATOR;}
":" {return Tokens.NAMEVALUE_SEPARATOR;}
"{" {return Tokens.OBJECT_OPEN;}
"}" {return Tokens.OBJECT_CLOSE;}
"true" {return Tokens.TRUE;}
"false" {return Tokens.FALSE;}
"null" {return Tokens.NULL;}
{double} {return Tokens.DOUBLE;}
{integer} {return Tokens.INTEGER;}
{whitespace} {}
{quote} {BEGIN(LexicalStates.IN_STRING); str = new StringBuilder(); return Tokens.STRING_BEGIN;}
{charNormal}+ {str.Append(yytext()); return Tokens.CHARS;}
{charUnicode} {str.Append((char)int.Parse(yytext().Substring(2), System.Globalization.NumberStyles.HexNumber)); return Tokens.UNICODECHAR;}
"\\f" {str.Append('\f'); return Tokens.ESCAPEDCHAR;}
"\\b" {str.Append('\b'); return Tokens.ESCAPEDCHAR;}
"\\r" {str.Append('\r'); return Tokens.ESCAPEDCHAR;}
"\\n" {str.Append('\n'); return Tokens.ESCAPEDCHAR;}
"\\t" {str.Append('\t'); return Tokens.ESCAPEDCHAR;}
"\\\\" {str.Append('\\'); return Tokens.ESCAPEDCHAR;}
"\\/" {str.Append('/'); return Tokens.ESCAPEDCHAR;}
"\\\"" {str.Append('"'); return Tokens.ESCAPEDCHAR;}
{quote} {BEGIN(LexicalStates.INITIAL); return Tokens.STRING_END;}
================================================
FILE: Source/ClassLibrary/Generators/json.y
================================================
using PHP.Core;
using PHP.Core.Parsers.GPPG;
using System.Diagnostics;
%%
%namespace PHP.Library.Json
%valuetype SemanticValueType
%positiontype Position
%tokentype Tokens
%visibility public
%union
{
public object obj;
}
%token ARRAY_OPEN
%token ARRAY_CLOSE
%token ITEMS_SEPARATOR
%token NAMEVALUE_SEPARATOR
%token OBJECT_OPEN
%token OBJECT_CLOSE
%token TRUE
%token FALSE
%token NULL
%token INTEGER
%token DOUBLE
%token STRING
%token STRING_BEGIN
%token CHARS
%token UNICODECHAR
%token ESCAPEDCHAR
%token STRING_END
%% /* Productions */
start:
value { Result = $1.obj; }
;
object:
OBJECT_OPEN members OBJECT_CLOSE
{
var elements = (List>)$2.obj;
if (decodeOptions.Assoc)
{
var arr = new PhpArray( elements.Count );
foreach (var item in elements)
arr.Add( PHP.Core.Convert.StringToArrayKey(item.Key), item.Value );
$$.obj = arr;
}
else
{
var std = new stdClass(context, true);
std.AddRange( elements );
$$.obj = std;
}
}
| OBJECT_OPEN OBJECT_CLOSE { $$.obj = new stdClass(context, true); }
;
members:
pair ITEMS_SEPARATOR members
{
var elements = (List>)$3.obj;
var result = new List>( elements.Count + 1 ){ (KeyValuePair)$1.obj };
result.AddRange(elements);
$$.obj = result;
}
| pair { $$.obj = new List>(){ (KeyValuePair)$1.obj }; }
;
pair:
STRING NAMEVALUE_SEPARATOR value { $$.obj = new KeyValuePair((string)$1.obj, $3.obj); }
;
array:
ARRAY_OPEN elements ARRAY_CLOSE
{
var elements = (List)$2.obj;
var arr = new PhpArray( elements.Count );
foreach (var item in elements)
arr.Add( item );
$$.obj = arr;
}
| ARRAY_OPEN ARRAY_CLOSE { $$.obj = new PhpArray(); }
;
elements:
value ITEMS_SEPARATOR elements
{
var elements = (List)$3.obj;
var result = new List( elements.Count + 1 ){ $1.obj };
result.AddRange(elements);
$$.obj = result;
}
| value { $$.obj = new List(){ $1.obj }; }
;
value:
STRING {$$.obj = $1.obj;}
| INTEGER {$$.obj = $1.obj;}
| DOUBLE {$$.obj = $1.obj;}
| object {$$.obj = $1.obj;}
| array {$$.obj = $1.obj;}
| TRUE {$$.obj = true;}
| FALSE {$$.obj = false;}
| NULL {$$.obj = null;}
;
%%
protected override int EofToken { get { return (int)Tokens.EOF; } }
protected override int ErrorToken { get { return (int)Tokens.ERROR; } }
private readonly ScriptContext/*!*/context;
private readonly PHP.Library.JsonFormatter.DecodeOptions/*!*/decodeOptions;
public Parser(ScriptContext/*!*/context, PHP.Library.JsonFormatter.DecodeOptions/*!*/decodeOptions)
{
System.Diagnostics.Debug.Assert(context != null && decodeOptions != null);
this.context = context;
this.decodeOptions = decodeOptions;
}
public object Result{get;private set;}
================================================
FILE: Source/ClassLibrary/Hash.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek and Ladislav Prosek.
Copyright (c) 2010 Jakub Misek
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
/*
TODO: (PHP 5.2 hash functions)
* hash_algos — Return a list of registered hashing algorithms
* hash_copy — Copy hashing context
* hash_file — Generate a hash value using the contents of a given file
* hash_final — Finalize an incremental hash and return resulting digest
* hash_hmac_file — Generate a keyed hash value using the HMAC method and the contents of a given file
* hash_hmac — Generate a keyed hash value using the HMAC method
* hash_init — Initialize an incremental hashing context
* hash_update_file — Pump data into an active hashing context from a file
* hash_update_stream — Pump data into an active hashing context from an open stream
* hash_update — Pump data into an active hashing context
* hash — Generate a hash value (message digest)
*/
using System;
using PHP.Core;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.ComponentModel;
using CRYPT = System.Security.Cryptography;
#if SILVERLIGHT
using PHP.CoreCLR;
using System.Windows.Browser;
#else
using System.Web;
using System.Diagnostics;
#endif
namespace PHP.Library
{
///
/// PHP hash functions support.
///
[ImplementsExtension(LibraryDescriptor.ExtHash)]
public static class PhpHash
{
#region crc32, (Only CLR:) md5, md5_file, sha1, sha1_file, sha256, sha256_file
///
/// Calculates the crc32 polynomial of a string of bytes.
///
/// The string of bytes to compute crc32 of.
/// The CRC32 of .
[ImplementsFunction("crc32")]
[PureFunction]
public static int CRC32(PhpBytes bytes)
{
return BitConverter.ToInt32(new CRC32().ComputeHash(bytes.ReadonlyData), 0);
}
#if !SILVERLIGHT
///
/// Calculate the md5 hash of a string of bytes.
///
/// The string of bytes to compute md5 of.
/// MD5 of as a sequence of hexadecimal numbers.
[ImplementsFunction("md5")]
[PureFunction]
public static string MD5(PhpBytes bytes)
{
return (string)MD5(bytes, false);
}
///
/// Calculate the md5 hash of a string of bytes.
///
/// The string of bytes to compute md5 of.
/// If true, returns raw binary hash, otherwise returns hash as
/// a sequence of hexadecimal numbers.
/// md5 of .
[ImplementsFunction("md5")]
[PureFunction]
public static object MD5(PhpBytes bytes, bool rawOutput)
{
return Hash(new CRYPT.MD5CryptoServiceProvider(), bytes, rawOutput);
}
///
/// Calculates the md5 hash of a given file.
///
/// The file name.
/// MD5 of given content.
[ImplementsFunction("md5_file")]
public static string MD5FromFile(string fileName)
{
return (string)MD5FromFile(fileName, false);
}
///
/// Calculates the md5 hash of a given file.
///
/// The file name.
/// If true , returns raw binary hash, otherwise returns hash as
/// a sequence of hexadecimal numbers.
/// MD5 of given content.
[ImplementsFunction("md5_file")]
public static object MD5FromFile(string fileName, bool rawOutput)
{
return HashFromFile(new CRYPT.MD5CryptoServiceProvider(), fileName, rawOutput);
}
///
/// Calculate the sha1 hash of a string of bytes.
///
/// The string of bytes to compute SHA1 of.
/// SHA1 of as a sequence of hexadecimal numbers.
[ImplementsFunction("sha1")]
[PureFunction]
public static string SHA1(PhpBytes bytes)
{
return (string)SHA1(bytes, false);
}
///
/// Calculate the SHA1 hash of a string of bytes.
///
/// The string of bytes to compute SHA1 of.
/// If true , returns raw binary hash, otherwise returns hash as
/// a sequence of hexadecimal numbers.
/// md5 of .
[ImplementsFunction("sha1")]
[PureFunction]
public static object SHA1(PhpBytes bytes, bool rawOutput)
{
return Hash(new CRYPT.SHA1CryptoServiceProvider(), bytes, rawOutput);
}
///
/// Calculates the SHA1 hash of a given file.
///
/// The file name.
/// SHA1 of given content.
[ImplementsFunction("sha1_file")]
public static string SHA1FromFile(string fileName)
{
return (string)SHA1FromFile(fileName, false);
}
///
/// Calculates the SHA1 hash of a given file.
///
/// The file name.
/// If true , returns raw binary hash, otherwise returns hash as
/// a sequence of hexadecimal numbers.
/// SHA1 of content.
[ImplementsFunction("sha1_file")]
public static object SHA1FromFile(string fileName, bool rawOutput)
{
return HashFromFile(new CRYPT.SHA1CryptoServiceProvider(), fileName, rawOutput);
}
#endif
#region not implemented in PHP
/////
///// Calculate the sha256 hash of a string of bytes.
/////
///// The string of bytes to compute SHA256 of.
///// SHA256 of as a sequence of hexadecimal numbers.
//[ImplementsFunction("sha256")]
//public static string SHA256(PhpBytes bytes)
//{
// return (string)SHA256(bytes, false);
//}
/////
///// Calculate the SHA256 hash of a string of bytes.
/////
///// The string of bytes to compute SHA256 of.
///// If true , returns raw binary hash, otherwise returns hash as
///// a sequence of hexadecimal numbers.
///// md5 of .
//[ImplementsFunction("sha256")]
//public static object SHA256(PhpBytes bytes, bool rawOutput)
//{
// return Hash(new CRYPT.SHA256Managed(), bytes, rawOutput);
//}
/////
///// Calculates the SHA256 hash of a given file.
/////
///// The file name.
///// SHA256 of as a sequence of hexadecimal numbers.
//[ImplementsFunction("sha256_file")]
//public static string SHA256FromFile(string fileName)
//{
// return (string)SHA256FromFile(fileName, false);
//}
/////
///// Calculates the SHA256 hash of a given file.
/////
///// The file name.
///// If true , returns raw binary hash, otherwise returns hash as
///// a sequence of hexadecimal numbers.
///// SHA256 of .
//[ImplementsFunction("sha256_file")]
//public static object SHA256FromFile(string fileName, bool rawOutput)
//{
// return HashFromFile(new CRYPT.SHA256Managed(), fileName, rawOutput);
//}
#endregion
///
/// Computes a hash of a string of bytes using specified algorithm.
///
private static object Hash(CRYPT.HashAlgorithm/*!*/ algorithm, PhpBytes bytes, bool rawOutput)
{
if (bytes == null) return null;
byte[] hash = algorithm.ComputeHash(bytes.ReadonlyData);
if (rawOutput)
return new PhpBytes(hash);
else
return StringUtils.BinToHex(hash, null);
}
///
/// Computes a hash of a file using specified algorithm.
///
private static object HashFromFile(CRYPT.HashAlgorithm/*!*/ algorithm, string fileName, bool rawOutput)
{
byte[] hash;
try
{
using (PhpStream stream = PhpStream.Open(fileName, "rb", StreamOpenOptions.Empty, StreamContext.Default))
//using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
if (stream == null)
return null;
object data = stream.ReadContents();
if (data == null)
return null;
PhpBytes bytes = PhpStream.AsBinary(data);
if (bytes == null)
return null;
hash = algorithm.ComputeHash(bytes.ReadonlyData);
}
}
catch (SystemException)
{
return null;
}
if (rawOutput)
return new PhpBytes(hash);
else
return StringUtils.BinToHex(hash, null);
}
#endregion
#region HashPhpResource
///
/// The Hashing Context PHP Resource.
///
public abstract class HashPhpResource : PhpResource
{
#region HashPhpResource base ctor
///
/// hash_init
///
protected HashPhpResource()
: base("Hash Context")
{
Init();
}
#endregion
#region HashPhpResource interface
///
/// hash_copy
///
///
public abstract HashPhpResource Clone();
///
/// hash_init
/// Restart the hashing algorithm.
///
public abstract void Init();
///
/// hash_update
/// Push more data into the algorithm, incremental hashing.
///
///
///
public abstract bool Update(byte[] data);
///
/// hash_final
/// Finalize the algorithm. Get the result.
///
///
public abstract byte[] Final();
///
/// HMAC key max size.
///
public abstract int BlockSize { get; }
#endregion
#region hash_init state
internal HashInitOptions options = HashInitOptions.HASH_DEFAULT;
internal byte[] HMACkey = null;
protected void CloneHashState(HashPhpResource clone)
{
clone.options = this.options;
clone.HMACkey = (this.HMACkey != null) ? (byte[])this.HMACkey.Clone() : null;
}
#endregion
#region Helper methods
#region Buffering for blocks of input data
private byte[] buffer = null;
private int bufferUsage = 0;
///
/// Returns blocks of data, using buffered data stored before.
/// Provided data can be too small to fit the block, so they are buffered and processed when more data comes.
///
/// New pack of data to be appended to the buffered ones.
/// Block size, when buffered data fits this, they are returned.
/// Packs of block, as a pair of byte array and index of first element.
internal IEnumerable> ProcessBlocked(byte[]/*!*/newData, int blockSize)
{
Debug.Assert(newData != null);
Debug.Assert(blockSize > 0);
int index = 0; // index of first byte in the newData to be used as a block start
// fill the buffer / used buffered data if it fits the block size
if (bufferUsage > 0)
{
Debug.Assert(buffer != null);
Debug.Assert(buffer.Length == blockSize);
int bytesToFitBuffer = blockSize - bufferUsage; // bytes needed to fill the whole buffer
if (newData.Length < bytesToFitBuffer)
{
Array.Copy(newData, 0, buffer, bufferUsage, newData.Length);
bufferUsage += newData.Length;
yield break;
}
Array.Copy(newData, 0, buffer, bufferUsage, bytesToFitBuffer);
yield return new Tuple(buffer, 0); // use the data from buffer
bufferUsage = 0; // buffer is empty now
index += bytesToFitBuffer; // part of newData was used
}
// returns blocks from the newData
while (index + blockSize <= newData.Length)
{
yield return new Tuple(newData, index);
index += blockSize;
}
// put the rest of newData into the buffer
int remainingBytes = newData.Length - index;
if (remainingBytes > 0)
{
if (buffer == null) buffer = new byte[blockSize];
Debug.Assert(remainingBytes < blockSize);
Debug.Assert(buffer.Length == blockSize);
Array.Copy(newData, index, buffer, 0, remainingBytes);
bufferUsage = remainingBytes;
}
}
///
/// Returns the buffered bytes not processed yet.
///
/// Amount of used bytes in the buffer.
/// Buffer, can be null.
internal byte[] GetBufferedBlock(out int length)
{
length = bufferUsage;
return buffer;
}
internal void ClearBufferedBlock()
{
bufferUsage = 0;
buffer = null;
}
///
/// Copies the buffered information from this instance into the clone.
///
/// Copy buffered info here.
internal void CloneBufferedBlock(HashPhpResource clone)
{
if (bufferUsage > 0)
{
clone.bufferUsage = this.bufferUsage;
clone.buffer = new byte[this.buffer.Length];
this.buffer.CopyTo(clone.buffer, 0);
}
else
{
clone.bufferUsage = 0;
clone.buffer = null;
}
}
#endregion
#region Conversion
protected static void DWORDToBigEndian(byte[] block, uint[] x, int digits)
{
int index = 0;
for (int i = 0; index < digits; i += 4)
{
block[i] = (byte)((x[index] >> 0x18) & 0xff);
block[i + 1] = (byte)((x[index] >> 0x10) & 0xff);
block[i + 2] = (byte)((x[index] >> 8) & 0xff);
block[i + 3] = (byte)(x[index] & 0xff);
index++;
}
}
protected static void DWORDFromBigEndian(uint[] x, int digits, byte[] block)
{
int index = 0;
for (int i = 0; index < digits; i += 4)
{
x[index] = ((((uint)block[i] << 0x18) | (uint)(block[i + 1] << 0x10)) | (uint)(block[i + 2] << 8)) | (uint)block[i + 3];
index++;
}
}
#endregion
///
/// Simply compute hash on existing HashPhpResource instance.
/// No HMAC.
/// The algorithm is reinitialized.
///
///
///
public byte[] ComputeHash(byte[] data)
{
this.Init();
if (!this.Update(data))
return null;
return this.Final();
}
#endregion
#region hash algorithms implementation
#region list of available algorithms
internal delegate HashPhpResource HashAlgFactory();
internal static Dictionary _HashAlgorithms = null;
internal static Dictionary HashAlgorithms
{
get
{
if (_HashAlgorithms == null)
{
var algs = new Dictionary(25, StringComparer.OrdinalIgnoreCase);
//
// note: use lower case as algorithms name
//
algs["crc32"] = () => new CRC32();
algs["crc32b"] = () => new CRC32B();
algs["md2"] = () => new MD2();
algs["md4"] = () => new MD4();
algs["md5"] = () => new MD5();
//algs["haval256,3"] = () => new HAVAL256();
//algs["haval224,3"] = () => new HAVAL224();
//algs["haval192,3"] = () => new HAVAL192();
//algs["haval160,3"] = () => new HAVAL160();
//algs["haval128,3"] = () => new HAVAL128();
//algs["tiger192,3"] = () => new TIGER();
//algs["tiger128,3"] = () => new TIGER128();
//algs["tiger160,3"] = () => new TIGER160();
//algs["gost"] = () => new GOST();
algs["adler32"] = () => new ADLER32();
algs["sha1"] = () => new SHA1();
//algs["sha224"] = () => new SHA224();
algs["sha256"] = () => new SHA256();
//algs["sha384"] = () => new SHA384();
//algs["sha512"] = () => new SHA512();
//algs["whirlpool"] = () => new WHIRLPOOL();
//algs["ripemd160"] = () => new RIPEMD160();
//algs["ripemd128"] = () => new RIPEMD128();
//algs["ripemd256"] = () => new RIPEMD256();
//algs["ripemd320"] = () => new RIPEMD320();
//algs["snefru256"] = () => new SNEFRU256();
_HashAlgorithms = algs;
}
return _HashAlgorithms;
}
}
#endregion
public sealed class ADLER32 : HashPhpResource
{
private uint state;
public override HashPhpResource Clone()
{
var clone = new ADLER32()
{
state = this.state
};
CloneHashState(clone);
return clone;
}
public override void Init()
{
state = 1;
}
public override bool Update(byte[] data)
{
uint s0, s1;
s0 = state & 0xffff;
s1 = (state >> 16) & 0xffff;
foreach (byte b in data)
{
s0 = (s0 + b) % 65521;
s1 = (s1 + s0) % 65521;
}
state = s0 + (s1 << 16);
return true;
}
public override byte[] Final()
{
byte[] bytes = BitConverter.GetBytes((uint)state);
Array.Reverse(bytes);
state = 0;
return bytes;
}
public override int BlockSize { get { return 4; } }
}
public sealed class CRC32 : HashPhpResource
{
private uint state;
private static uint[] crc32_table = { 0x0,
0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};
public override HashPhpResource Clone()
{
var clone = new CRC32()
{
state = this.state
};
CloneHashState(clone);
return clone;
}
public override void Init()
{
state = ~(uint)0;
}
public override bool Update(byte[] data)
{
foreach (byte b in data)
{
state = (state << 8) ^ crc32_table[(state >> 24) ^ (b & 0xff)];
}
return true;
}
public override byte[] Final()
{
state = ~state;
var h = BitConverter.GetBytes((uint)state);
state = 0;
return h;
}
public override int BlockSize { get { return 4; } }
}
public sealed class CRC32B : HashPhpResource
{
private uint state;
private static uint[] crc32b_table = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
public override HashPhpResource Clone()
{
var clone = new CRC32B()
{
state = this.state
};
CloneHashState(clone);
return clone;
}
public override void Init()
{
state = ~(uint)0;
}
public override bool Update(byte[] data)
{
foreach (byte b in data)
{
state = (state >> 8) ^ crc32b_table[(state ^ b) & 0xff];
}
return true;
}
public override byte[] Final()
{
state = ~state;
byte[] bytes = BitConverter.GetBytes((uint)state);
Array.Reverse(bytes);
state = 0;
return bytes;
}
public override int BlockSize { get { return 4; } }
}
public sealed class MD2 : HashPhpResource
{
private static byte[] MD2_S = {
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19,
98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202,
30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18,
190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122,
169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33,
128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3,
255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198,
79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241,
69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2,
27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38,
44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82,
106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74,
120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57,
242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 };
#region state
private readonly byte[] state = new byte[48];
private readonly byte[] checksum = new byte[16];
#endregion
public override HashPhpResource Clone()
{
var clone = new MD2();
this.CloneHashState(clone);
this.CloneBufferedBlock(clone);
this.state.CopyTo(clone.state, 0);
this.checksum.CopyTo(clone.checksum, 0);
return clone;
}
public override void Init()
{
this.ClearBufferedBlock();
Array.Clear(this.state, 0, this.state.Length);
Array.Clear(this.checksum, 0, this.checksum.Length);
}
private void TransformBlock(byte[]/*!*//*byte[16+startIndex]*/block, int startIndex)
{
Debug.Assert(block != null);
Debug.Assert(block.Length >= 16 + startIndex);
byte i, j, t = 0;
for (i = 0; i < 16; i++)
{
state[16 + i] = block[i + startIndex];
state[32 + i] = (byte)(state[16 + i] ^ state[i]);
}
for (i = 0; i < 18; i++)
{
for (j = 0; j < 48; j++)
{
t = state[j] = (byte)(state[j] ^ MD2_S[t]);
}
unchecked
{
t += i;
}
}
/* Update checksum -- must be after transform to avoid fouling up last message block */
t = checksum[15];
for (i = 0; i < 16; i++)
{
t = checksum[i] ^= MD2_S[block[i + startIndex] ^ t];
}
}
public override bool Update(byte[] data)
{
foreach (var block in ProcessBlocked(data, 16))
TransformBlock(block.Item1, block.Item2);
return true;
}
public override byte[] Final()
{
// take the remaining buffer
// fill the rest up to 16 bytes with "remainingBytes" value
int bufferUsage;
byte[] buffer = GetBufferedBlock(out bufferUsage);
if (buffer == null) buffer = new byte[16];
Debug.Assert(buffer.Length == 16);
Debug.Assert(bufferUsage < 16);
byte remainingBytes = (byte)(16 - bufferUsage);
for (int i = bufferUsage; i < 16; ++i)
buffer[i] = remainingBytes;
//
TransformBlock(buffer, 0);
TransformBlock(checksum, 0);
//
byte[] hash = new byte[16];
Array.Copy(this.state, 0, hash, 0, 16);
return hash;
}
public override int BlockSize { get { return 16; } }
}
public sealed class MD4 : HashPhpResource
{
#region state
private uint[] state = new uint[4];
private uint[] count = new uint[2];
#endregion
#region MD4 transformation
private static uint MD4_F(uint x, uint y, uint z) { return ((z) ^ ((x) & ((y) ^ (z)))); }
private static uint MD4_G(uint x, uint y, uint z) { return (((x) & ((y) | (z))) | ((y) & (z))); }
private static uint MD4_H(uint x, uint y, uint z) { return ((x) ^ (y) ^ (z)); }
private static uint ROTL32(byte s, uint v) { return (((v) << (s)) | ((v) >> (32 - (s)))); }
private static void MD4_R1(ref uint a, uint b, uint c, uint d, uint xk, byte s) { unchecked { a = ROTL32(s, a + MD4_F(b, c, d) + xk); } }
private static void MD4_R2(ref uint a, uint b, uint c, uint d, uint xk, byte s) { unchecked { a = ROTL32(s, a + MD4_G(b, c, d) + xk + 0x5A827999); } }
private static void MD4_R3(ref uint a, uint b, uint c, uint d, uint xk, byte s) { unchecked { a = ROTL32(s, a + MD4_H(b, c, d) + xk + 0x6ED9EBA1); } }
private static uint[] Decode(byte[] block, int startIndex, int bytesCount)
{
Debug.Assert(bytesCount > 0);
Debug.Assert((bytesCount % 4) == 0);
uint[] result = new uint[bytesCount / 4];
int index = 0;
while (bytesCount > 0)
{
result[index++] = BitConverter.ToUInt32(block, startIndex);
startIndex += 4;
bytesCount -= 4;
}
return result;
}
private static byte[] Encode(uint[] nums, int startIndex, int bytesCount)
{
Debug.Assert(bytesCount > 0);
Debug.Assert((bytesCount % 4) == 0);
byte[] result = new byte[bytesCount];
int index = 0;
while (index < bytesCount)
{
Array.Copy(BitConverter.GetBytes(nums[startIndex++]), 0, result, index, 4);
index += 4;
}
return result;
}
private void MD4Transform(byte[] block, int startIndex)
{
uint a = state[0], b = state[1], c = state[2], d = state[3];
uint[] x = Decode(block, startIndex, 64);
/* Round 1 */
MD4_R1(ref a, b, c, d, x[0], 3);
MD4_R1(ref d, a, b, c, x[1], 7);
MD4_R1(ref c, d, a, b, x[2], 11);
MD4_R1(ref b, c, d, a, x[3], 19);
MD4_R1(ref a, b, c, d, x[4], 3);
MD4_R1(ref d, a, b, c, x[5], 7);
MD4_R1(ref c, d, a, b, x[6], 11);
MD4_R1(ref b, c, d, a, x[7], 19);
MD4_R1(ref a, b, c, d, x[8], 3);
MD4_R1(ref d, a, b, c, x[9], 7);
MD4_R1(ref c, d, a, b, x[10], 11);
MD4_R1(ref b, c, d, a, x[11], 19);
MD4_R1(ref a, b, c, d, x[12], 3);
MD4_R1(ref d, a, b, c, x[13], 7);
MD4_R1(ref c, d, a, b, x[14], 11);
MD4_R1(ref b, c, d, a, x[15], 19);
/* Round 2 */
MD4_R2(ref a, b, c, d, x[0], 3);
MD4_R2(ref d, a, b, c, x[4], 5);
MD4_R2(ref c, d, a, b, x[8], 9);
MD4_R2(ref b, c, d, a, x[12], 13);
MD4_R2(ref a, b, c, d, x[1], 3);
MD4_R2(ref d, a, b, c, x[5], 5);
MD4_R2(ref c, d, a, b, x[9], 9);
MD4_R2(ref b, c, d, a, x[13], 13);
MD4_R2(ref a, b, c, d, x[2], 3);
MD4_R2(ref d, a, b, c, x[6], 5);
MD4_R2(ref c, d, a, b, x[10], 9);
MD4_R2(ref b, c, d, a, x[14], 13);
MD4_R2(ref a, b, c, d, x[3], 3);
MD4_R2(ref d, a, b, c, x[7], 5);
MD4_R2(ref c, d, a, b, x[11], 9);
MD4_R2(ref b, c, d, a, x[15], 13);
/* Round 3 */
MD4_R3(ref a, b, c, d, x[0], 3);
MD4_R3(ref d, a, b, c, x[8], 9);
MD4_R3(ref c, d, a, b, x[4], 11);
MD4_R3(ref b, c, d, a, x[12], 15);
MD4_R3(ref a, b, c, d, x[2], 3);
MD4_R3(ref d, a, b, c, x[10], 9);
MD4_R3(ref c, d, a, b, x[6], 11);
MD4_R3(ref b, c, d, a, x[14], 15);
MD4_R3(ref a, b, c, d, x[1], 3);
MD4_R3(ref d, a, b, c, x[9], 9);
MD4_R3(ref c, d, a, b, x[5], 11);
MD4_R3(ref b, c, d, a, x[13], 15);
MD4_R3(ref a, b, c, d, x[3], 3);
MD4_R3(ref d, a, b, c, x[11], 9);
MD4_R3(ref c, d, a, b, x[7], 11);
MD4_R3(ref b, c, d, a, x[15], 15);
unchecked
{
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
}
#endregion
#region HashPhpResource
public override HashPhpResource Clone()
{
var clone = new MD4();
this.CloneHashState(clone);
this.CloneBufferedBlock(clone);
this.state.CopyTo(clone.state, 0);
this.count.CopyTo(clone.count, 0);
return clone;
}
public override void Init()
{
this.ClearBufferedBlock();
count[0] = count[1] = 0;
/* Load magic initialization constants.
*/
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
public override bool Update(byte[] data)
{
/* Update number of bits */
if ((count[0] += ((uint)data.Length << 3)) < ((uint)data.Length << 3))
++count[1];
count[1] += ((uint)data.Length >> 29);
foreach (var block in ProcessBlocked(data, 64))
MD4Transform(block.Item1, block.Item2);
return true;
}
public override byte[] Final()
{
// save length
byte[] bits = Encode(count, 0, 8);
// padd to 56 mod 64
int bufferUsage;
byte[] buffer = GetBufferedBlock(out bufferUsage);
if (buffer == null) buffer = new byte[64];
Debug.Assert(buffer.Length == 64);
int padLen = (bufferUsage < 56) ? (56 - bufferUsage) : (120 - bufferUsage);
if (padLen > 0)
{
byte[] padding = new byte[padLen];
padding[0] = 0x80;
Update(padding);
}
Update(bits);
byte[] result = Encode(state, 0, 16);
// cleanup sensitive data
Array.Clear(state, 0, state.Length);
Array.Clear(count, 0, count.Length);
// done
return result;
}
public override int BlockSize { get { return 64; } }
#endregion
}
public sealed class MD5 : HashPhpResource
{
#region state
private uint[] state = new uint[4];
private uint[] count = new uint[2];
#endregion
#region MD5 transformation
///
/// MD5 Transformation constants.
///
enum MD5Consts : byte
{
S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22,
S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20,
S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23,
S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21,
}
/// F, G, H and I are basic MD5 functions.
private static uint F(uint x, uint y, uint z) { return (((x) & (y)) | ((~x) & (z))); }
private static uint G(uint x, uint y, uint z) { return (((x) & (z)) | ((y) & (~z))); }
private static uint H(uint x, uint y, uint z) { return ((x) ^ (y) ^ (z)); }
private static uint I(uint x, uint y, uint z) { return ((y) ^ ((x) | (~z))); }
///
/// ROTATE_LEFT rotates x left n bits.
///
///
///
///
private static uint ROTATE_LEFT(uint x, byte n) { return (((x) << (n)) | ((x) >> (32 - (n)))); }
/// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
/// Rotation is separate from addition to prevent re-computation.
private static void FF(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac)
{
unchecked
{
(a) += F((b), (c), (d)) + (x) + (ac);
(a) = ROTATE_LEFT((a), (s));
(a) += (b);
}
}
private static void GG(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac)
{
unchecked
{
(a) += G((b), (c), (d)) + (x) + (ac);
(a) = ROTATE_LEFT((a), (s));
(a) += (b);
}
}
private static void HH(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac)
{
unchecked
{
(a) += H((b), (c), (d)) + (x) + (ac);
(a) = ROTATE_LEFT((a), (s));
(a) += (b);
}
}
private static void II(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac)
{
unchecked
{
(a) += I((b), (c), (d)) + (x) + (ac);
(a) = ROTATE_LEFT((a), (s));
(a) += (b);
}
}
private static uint[] Decode(byte[] block, int startIndex, int bytesCount)
{
Debug.Assert(bytesCount > 0);
Debug.Assert((bytesCount % 4) == 0);
uint[] result = new uint[bytesCount / 4];
int index = 0;
while (bytesCount > 0)
{
result[index++] = BitConverter.ToUInt32(block, startIndex);
startIndex += 4;
bytesCount -= 4;
}
return result;
}
private static byte[] Encode(uint[] nums, int startIndex, int bytesCount)
{
Debug.Assert(bytesCount > 0);
Debug.Assert((bytesCount % 4) == 0);
byte[] result = new byte[bytesCount];
int index = 0;
while (index < bytesCount)
{
Array.Copy(BitConverter.GetBytes(nums[startIndex++]), 0, result, index, 4);
index += 4;
}
return result;
}
///
/// MD5 basic transformation. Transforms state based on block.
///
///
///
private void MD5Transform(byte[]/*[64]*/block, int startIndex)
{
uint a = state[0], b = state[1], c = state[2], d = state[3];
uint[] x = Decode(block, startIndex, 64); // [16]
Debug.Assert(x.Length == 16);
/* Round 1 */
FF(ref a, b, c, d, x[0], (byte)MD5Consts.S11, 0xd76aa478); /* 1 */
FF(ref d, a, b, c, x[1], (byte)MD5Consts.S12, 0xe8c7b756); /* 2 */
FF(ref c, d, a, b, x[2], (byte)MD5Consts.S13, 0x242070db); /* 3 */
FF(ref b, c, d, a, x[3], (byte)MD5Consts.S14, 0xc1bdceee); /* 4 */
FF(ref a, b, c, d, x[4], (byte)MD5Consts.S11, 0xf57c0faf); /* 5 */
FF(ref d, a, b, c, x[5], (byte)MD5Consts.S12, 0x4787c62a); /* 6 */
FF(ref c, d, a, b, x[6], (byte)MD5Consts.S13, 0xa8304613); /* 7 */
FF(ref b, c, d, a, x[7], (byte)MD5Consts.S14, 0xfd469501); /* 8 */
FF(ref a, b, c, d, x[8], (byte)MD5Consts.S11, 0x698098d8); /* 9 */
FF(ref d, a, b, c, x[9], (byte)MD5Consts.S12, 0x8b44f7af); /* 10 */
FF(ref c, d, a, b, x[10], (byte)MD5Consts.S13, 0xffff5bb1); /* 11 */
FF(ref b, c, d, a, x[11], (byte)MD5Consts.S14, 0x895cd7be); /* 12 */
FF(ref a, b, c, d, x[12], (byte)MD5Consts.S11, 0x6b901122); /* 13 */
FF(ref d, a, b, c, x[13], (byte)MD5Consts.S12, 0xfd987193); /* 14 */
FF(ref c, d, a, b, x[14], (byte)MD5Consts.S13, 0xa679438e); /* 15 */
FF(ref b, c, d, a, x[15], (byte)MD5Consts.S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(ref a, b, c, d, x[1], (byte)MD5Consts.S21, 0xf61e2562); /* 17 */
GG(ref d, a, b, c, x[6], (byte)MD5Consts.S22, 0xc040b340); /* 18 */
GG(ref c, d, a, b, x[11], (byte)MD5Consts.S23, 0x265e5a51); /* 19 */
GG(ref b, c, d, a, x[0], (byte)MD5Consts.S24, 0xe9b6c7aa); /* 20 */
GG(ref a, b, c, d, x[5], (byte)MD5Consts.S21, 0xd62f105d); /* 21 */
GG(ref d, a, b, c, x[10], (byte)MD5Consts.S22, 0x2441453); /* 22 */
GG(ref c, d, a, b, x[15], (byte)MD5Consts.S23, 0xd8a1e681); /* 23 */
GG(ref b, c, d, a, x[4], (byte)MD5Consts.S24, 0xe7d3fbc8); /* 24 */
GG(ref a, b, c, d, x[9], (byte)MD5Consts.S21, 0x21e1cde6); /* 25 */
GG(ref d, a, b, c, x[14], (byte)MD5Consts.S22, 0xc33707d6); /* 26 */
GG(ref c, d, a, b, x[3], (byte)MD5Consts.S23, 0xf4d50d87); /* 27 */
GG(ref b, c, d, a, x[8], (byte)MD5Consts.S24, 0x455a14ed); /* 28 */
GG(ref a, b, c, d, x[13], (byte)MD5Consts.S21, 0xa9e3e905); /* 29 */
GG(ref d, a, b, c, x[2], (byte)MD5Consts.S22, 0xfcefa3f8); /* 30 */
GG(ref c, d, a, b, x[7], (byte)MD5Consts.S23, 0x676f02d9); /* 31 */
GG(ref b, c, d, a, x[12], (byte)MD5Consts.S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(ref a, b, c, d, x[5], (byte)MD5Consts.S31, 0xfffa3942); /* 33 */
HH(ref d, a, b, c, x[8], (byte)MD5Consts.S32, 0x8771f681); /* 34 */
HH(ref c, d, a, b, x[11], (byte)MD5Consts.S33, 0x6d9d6122); /* 35 */
HH(ref b, c, d, a, x[14], (byte)MD5Consts.S34, 0xfde5380c); /* 36 */
HH(ref a, b, c, d, x[1], (byte)MD5Consts.S31, 0xa4beea44); /* 37 */
HH(ref d, a, b, c, x[4], (byte)MD5Consts.S32, 0x4bdecfa9); /* 38 */
HH(ref c, d, a, b, x[7], (byte)MD5Consts.S33, 0xf6bb4b60); /* 39 */
HH(ref b, c, d, a, x[10], (byte)MD5Consts.S34, 0xbebfbc70); /* 40 */
HH(ref a, b, c, d, x[13], (byte)MD5Consts.S31, 0x289b7ec6); /* 41 */
HH(ref d, a, b, c, x[0], (byte)MD5Consts.S32, 0xeaa127fa); /* 42 */
HH(ref c, d, a, b, x[3], (byte)MD5Consts.S33, 0xd4ef3085); /* 43 */
HH(ref b, c, d, a, x[6], (byte)MD5Consts.S34, 0x4881d05); /* 44 */
HH(ref a, b, c, d, x[9], (byte)MD5Consts.S31, 0xd9d4d039); /* 45 */
HH(ref d, a, b, c, x[12], (byte)MD5Consts.S32, 0xe6db99e5); /* 46 */
HH(ref c, d, a, b, x[15], (byte)MD5Consts.S33, 0x1fa27cf8); /* 47 */
HH(ref b, c, d, a, x[2], (byte)MD5Consts.S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(ref a, b, c, d, x[0], (byte)MD5Consts.S41, 0xf4292244); /* 49 */
II(ref d, a, b, c, x[7], (byte)MD5Consts.S42, 0x432aff97); /* 50 */
II(ref c, d, a, b, x[14], (byte)MD5Consts.S43, 0xab9423a7); /* 51 */
II(ref b, c, d, a, x[5], (byte)MD5Consts.S44, 0xfc93a039); /* 52 */
II(ref a, b, c, d, x[12], (byte)MD5Consts.S41, 0x655b59c3); /* 53 */
II(ref d, a, b, c, x[3], (byte)MD5Consts.S42, 0x8f0ccc92); /* 54 */
II(ref c, d, a, b, x[10], (byte)MD5Consts.S43, 0xffeff47d); /* 55 */
II(ref b, c, d, a, x[1], (byte)MD5Consts.S44, 0x85845dd1); /* 56 */
II(ref a, b, c, d, x[8], (byte)MD5Consts.S41, 0x6fa87e4f); /* 57 */
II(ref d, a, b, c, x[15], (byte)MD5Consts.S42, 0xfe2ce6e0); /* 58 */
II(ref c, d, a, b, x[6], (byte)MD5Consts.S43, 0xa3014314); /* 59 */
II(ref b, c, d, a, x[13], (byte)MD5Consts.S44, 0x4e0811a1); /* 60 */
II(ref a, b, c, d, x[4], (byte)MD5Consts.S41, 0xf7537e82); /* 61 */
II(ref d, a, b, c, x[11], (byte)MD5Consts.S42, 0xbd3af235); /* 62 */
II(ref c, d, a, b, x[2], (byte)MD5Consts.S43, 0x2ad7d2bb); /* 63 */
II(ref b, c, d, a, x[9], (byte)MD5Consts.S44, 0xeb86d391); /* 64 */
unchecked
{
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
}
Array.Clear(x, 0, 16);
}
#endregion
#region HashPhpResource
public override HashPhpResource Clone()
{
var clone = new MD5();
this.CloneHashState(clone);
this.CloneBufferedBlock(clone);
this.state.CopyTo(clone.state, 0);
this.count.CopyTo(clone.count, 0);
return clone;
}
public override void Init()
{
count[0] = count[1] = 0;
/* Load magic initialization constants.
*/
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
public override bool Update(byte[]/*!*/data)
{
Debug.Assert(data != null);
// Update number of bits
if ((count[0] += ((uint)data.Length << 3)) < ((uint)data.Length << 3)) count[1]++;
count[1] += ((uint)data.Length >> 29);
// Transform blocks of 64 bytes
foreach (var block in ProcessBlocked(data, 64))
MD5Transform(block.Item1, block.Item2);
return true;
}
public override byte[] Final()
{
// save length
byte[] bits = Encode(count, 0, 8);
// padd to 56 mod 64
int bufferUsage;
byte[] buffer = GetBufferedBlock(out bufferUsage);
if (buffer == null) buffer = new byte[64];
Debug.Assert(buffer.Length == 64);
int padLen = (bufferUsage < 56) ? (56 - bufferUsage) : (120 - bufferUsage);
if (padLen > 0)
{
byte[] padding = new byte[padLen];
padding[0] = 0x80;
Update(padding);
}
Update(bits);
byte[] result = Encode(state, 0, 16);
// cleanup sensitive data
Array.Clear(state, 0, state.Length);
Array.Clear(count, 0, count.Length);
// done
return result;
}
public override int BlockSize
{
get { return 64; }
}
#endregion
}
///
/// Base class for SHA based hashing algorithms.
///
/// Actual type of SHA class. Used to instantiate new one in method.
public abstract class SHA : HashPhpResource where T: SHA, new()
{
#region state
///
/// Internal buffer holding SHA results.
///
protected readonly byte[]/*!*/_buffer;
///
/// Amount of chars encoded.
///
protected long _count;
///
/// Temporary buffer used internally by method.
///
protected readonly uint[]/*!*/_tmp;
///
/// Current hash state.
///
protected readonly uint[]/*!*/_state;
#endregion
#region Constructor
public SHA(int bufferSize, int tmpSize, int stateSize)
{
Debug.Assert(bufferSize > 0);
Debug.Assert(tmpSize > 0);
Debug.Assert(stateSize > 0);
this._buffer = new byte[bufferSize];
this._tmp = new uint[tmpSize];
this._state = new uint[stateSize];
// initialize the state:
this.InitializeState();
}
#endregion
#region SHA (to be implemented in derived class)
///
/// Set and to their initial state.
///
protected abstract void InitializeState();
///
/// Finalize the hash.
///
/// Resulting hash.
protected abstract byte[] _EndHash();
///
/// Pump more data into the hashing algorithm.
///
/// Array of data to be hashed.
/// Index where to start reading from .
/// Amount of bytes to read from .
/// true if hashing succeeded.
protected abstract bool _HashData(byte[] partIn, int ibStart, int cbSize);
#endregion
#region HashPhpResource
public override void Init()
{
if (_state != null /*&& _buffer != null && _tmp != null*/) // iff we are initialized already (base .ctor which calls Init is called before this .ctor, so these arrays may not be initialized yet)
{
this.InitializeState();
Array.Clear(this._buffer, 0, this._buffer.Length);
Array.Clear(this._tmp, 0, this._tmp.Length);
}
}
public override bool Update(byte[]/*!*/data)
{
Debug.Assert(data != null);
return _HashData(data, 0, data.Length);
}
public override byte[] Final()
{
try
{
return _EndHash();
}
finally
{
InitializeState(); // clear the state
}
}
public override HashPhpResource Clone()
{
var clone = new T() { _count = this._count };
this.CloneHashState(clone);
this._buffer.CopyTo(clone._buffer, 0);
this._tmp.CopyTo(clone._tmp, 0);
this._state.CopyTo(clone._state, 0);
return clone;
}
public override int BlockSize
{
get { return _buffer.Length; }
}
#endregion
}
public sealed class SHA1 : SHA
{
#region SHA1 hashing internals
public SHA1()
:base(64,80,5)
{
}
protected override void InitializeState()
{
this._count = 0L;
this._state[0] = 0x67452301;
this._state[1] = 0xefcdab89;
this._state[2] = 0x98badcfe;
this._state[3] = 0x10325476;
this._state[4] = 0xc3d2e1f0;
}
///
/// Finalize the hash.
///
/// Hashed bytes.
protected override byte[] _EndHash()
{
byte[] block = new byte[20];
int num = 0x40 - ((int)(this._count & 0x3fL));
if (num <= 8)
num += 0x40;
byte[] partIn = new byte[num];
partIn[0] = 0x80;
long num2 = this._count * 8L;
partIn[num - 8] = (byte)((num2 >> 0x38) & 0xffL);
partIn[num - 7] = (byte)((num2 >> 0x30) & 0xffL);
partIn[num - 6] = (byte)((num2 >> 40) & 0xffL);
partIn[num - 5] = (byte)((num2 >> 0x20) & 0xffL);
partIn[num - 4] = (byte)((num2 >> 0x18) & 0xffL);
partIn[num - 3] = (byte)((num2 >> 0x10) & 0xffL);
partIn[num - 2] = (byte)((num2 >> 8) & 0xffL);
partIn[num - 1] = (byte)(num2 & 0xffL);
this._HashData(partIn, 0, partIn.Length);
DWORDToBigEndian(block, this._state, 5);
//base.HashValue = block;
return block;
}
protected override bool _HashData(byte[] partIn, int ibStart, int cbSize)
{
unchecked
{
int byteCount = cbSize;
int srcOffsetBytes = ibStart;
int dstOffsetBytes = (int)(this._count & 0x3fL);
this._count += byteCount;
if ((dstOffsetBytes > 0) && ((dstOffsetBytes + byteCount) >= 0x40))
{
Buffer.BlockCopy(partIn, srcOffsetBytes, this._buffer, dstOffsetBytes, 0x40 - dstOffsetBytes);
srcOffsetBytes += 0x40 - dstOffsetBytes;
byteCount -= 0x40 - dstOffsetBytes;
SHATransform(_tmp, _state, _buffer);
dstOffsetBytes = 0;
}
while (byteCount >= 0x40)
{
Buffer.BlockCopy(partIn, srcOffsetBytes, this._buffer, 0, 0x40);
srcOffsetBytes += 0x40;
byteCount -= 0x40;
SHATransform(_tmp, _state, _buffer);
}
if (byteCount > 0)
{
Buffer.BlockCopy(partIn, srcOffsetBytes, this._buffer, dstOffsetBytes, byteCount);
}
}
return true;
}
private static void SHAExpand(uint[] x)
{
unchecked
{
for (int i = 0x10; i < 80; i++)
{
uint num2 = ((x[i - 3] ^ x[i - 8]) ^ x[i - 14]) ^ x[i - 0x10];
x[i] = (num2 << 1) | (num2 >> 0x1f);
}
}
}
private static void SHATransform(uint[] tmp, uint[] state, byte[] block)
{
Debug.Assert(tmp != null && tmp.Length == 80);
uint num = state[0];
uint num2 = state[1];
uint num3 = state[2];
uint num4 = state[3];
uint num5 = state[4];
DWORDFromBigEndian(tmp, 0x10, block);
SHAExpand(tmp);
int index = 0;
unchecked
{
while (index < 20)
{
num5 += ((((num << 5) | (num >> 0x1b)) + (num4 ^ (num2 & (num3 ^ num4)))) + tmp[index]) + 0x5a827999;
num2 = (num2 << 30) | (num2 >> 2);
num4 += ((((num5 << 5) | (num5 >> 0x1b)) + (num3 ^ (num & (num2 ^ num3)))) + tmp[index + 1]) + 0x5a827999;
num = (num << 30) | (num >> 2);
num3 += ((((num4 << 5) | (num4 >> 0x1b)) + (num2 ^ (num5 & (num ^ num2)))) + tmp[index + 2]) + 0x5a827999;
num5 = (num5 << 30) | (num5 >> 2);
num2 += ((((num3 << 5) | (num3 >> 0x1b)) + (num ^ (num4 & (num5 ^ num)))) + tmp[index + 3]) + 0x5a827999;
num4 = (num4 << 30) | (num4 >> 2);
num += ((((num2 << 5) | (num2 >> 0x1b)) + (num5 ^ (num3 & (num4 ^ num5)))) + tmp[index + 4]) + 0x5a827999;
num3 = (num3 << 30) | (num3 >> 2);
index += 5;
}
while (index < 40)
{
num5 += ((((num << 5) | (num >> 0x1b)) + ((num2 ^ num3) ^ num4)) + tmp[index]) + 0x6ed9eba1;
num2 = (num2 << 30) | (num2 >> 2);
num4 += ((((num5 << 5) | (num5 >> 0x1b)) + ((num ^ num2) ^ num3)) + tmp[index + 1]) + 0x6ed9eba1;
num = (num << 30) | (num >> 2);
num3 += ((((num4 << 5) | (num4 >> 0x1b)) + ((num5 ^ num) ^ num2)) + tmp[index + 2]) + 0x6ed9eba1;
num5 = (num5 << 30) | (num5 >> 2);
num2 += ((((num3 << 5) | (num3 >> 0x1b)) + ((num4 ^ num5) ^ num)) + tmp[index + 3]) + 0x6ed9eba1;
num4 = (num4 << 30) | (num4 >> 2);
num += ((((num2 << 5) | (num2 >> 0x1b)) + ((num3 ^ num4) ^ num5)) + tmp[index + 4]) + 0x6ed9eba1;
num3 = (num3 << 30) | (num3 >> 2);
index += 5;
}
while (index < 60)
{
num5 += ((((num << 5) | (num >> 0x1b)) + ((num2 & num3) | (num4 & (num2 | num3)))) + tmp[index]) + 0x8f1bbcdc;
num2 = (num2 << 30) | (num2 >> 2);
num4 += ((((num5 << 5) | (num5 >> 0x1b)) + ((num & num2) | (num3 & (num | num2)))) + tmp[index + 1]) + 0x8f1bbcdc;
num = (num << 30) | (num >> 2);
num3 += ((((num4 << 5) | (num4 >> 0x1b)) + ((num5 & num) | (num2 & (num5 | num)))) + tmp[index + 2]) + 0x8f1bbcdc;
num5 = (num5 << 30) | (num5 >> 2);
num2 += ((((num3 << 5) | (num3 >> 0x1b)) + ((num4 & num5) | (num & (num4 | num5)))) + tmp[index + 3]) + 0x8f1bbcdc;
num4 = (num4 << 30) | (num4 >> 2);
num += ((((num2 << 5) | (num2 >> 0x1b)) + ((num3 & num4) | (num5 & (num3 | num4)))) + tmp[index + 4]) + 0x8f1bbcdc;
num3 = (num3 << 30) | (num3 >> 2);
index += 5;
}
while (index < 80)
{
num5 += ((((num << 5) | (num >> 0x1b)) + ((num2 ^ num3) ^ num4)) + tmp[index]) + 0xca62c1d6;
num2 = (num2 << 30) | (num2 >> 2);
num4 += ((((num5 << 5) | (num5 >> 0x1b)) + ((num ^ num2) ^ num3)) + tmp[index + 1]) + 0xca62c1d6;
num = (num << 30) | (num >> 2);
num3 += ((((num4 << 5) | (num4 >> 0x1b)) + ((num5 ^ num) ^ num2)) + tmp[index + 2]) + 0xca62c1d6;
num5 = (num5 << 30) | (num5 >> 2);
num2 += ((((num3 << 5) | (num3 >> 0x1b)) + ((num4 ^ num5) ^ num)) + tmp[index + 3]) + 0xca62c1d6;
num4 = (num4 << 30) | (num4 >> 2);
num += ((((num2 << 5) | (num2 >> 0x1b)) + ((num3 ^ num4) ^ num5)) + tmp[index + 4]) + 0xca62c1d6;
num3 = (num3 << 30) | (num3 >> 2);
index += 5;
}
state[0] += num;
state[1] += num2;
state[2] += num3;
state[3] += num4;
state[4] += num5;
}
}
#endregion
}
public sealed class SHA256 : SHA
{
#region SHA256 hashing internals
public SHA256()
:base(64,64,8)
{
}
protected override void InitializeState()
{
this._count = 0L;
// initialize the state:
this._state[0] = 0x6a09e667;
this._state[1] = 0xbb67ae85;
this._state[2] = 0x3c6ef372;
this._state[3] = 0xa54ff53a;
this._state[4] = 0x510e527f;
this._state[5] = 0x9b05688c;
this._state[6] = 0x1f83d9ab;
this._state[7] = 0x5be0cd19;
}
///
/// Finalize the hash.
///
/// Hashed bytes.
protected override byte[] _EndHash()
{
byte[] block = new byte[32];
int num = 0x40 - ((int)(this._count & 0x3fL));
if (num <= 8)
num += 0x40;
byte[] partIn = new byte[num];
partIn[0] = 0x80;
long num2 = this._count * 8L;
partIn[num - 8] = (byte)((num2 >> 0x38) & 0xffL);
partIn[num - 7] = (byte)((num2 >> 0x30) & 0xffL);
partIn[num - 6] = (byte)((num2 >> 40) & 0xffL);
partIn[num - 5] = (byte)((num2 >> 0x20) & 0xffL);
partIn[num - 4] = (byte)((num2 >> 0x18) & 0xffL);
partIn[num - 3] = (byte)((num2 >> 0x10) & 0xffL);
partIn[num - 2] = (byte)((num2 >> 8) & 0xffL);
partIn[num - 1] = (byte)(num2 & 0xffL);
this._HashData(partIn, 0, partIn.Length);
DWORDToBigEndian(block, this._state, 8);
//base.HashValue = block;
return block;
}
protected override bool _HashData(byte[] partIn, int ibStart, int cbSize)
{
unchecked
{
int byteCount = cbSize;
int srcOffsetBytes = ibStart;
int dstOffsetBytes = (int)(this._count & 0x3fL);
this._count += byteCount;
if ((dstOffsetBytes > 0) && ((dstOffsetBytes + byteCount) >= 0x40))
{
Buffer.BlockCopy(partIn, srcOffsetBytes, this._buffer, dstOffsetBytes, 0x40 - dstOffsetBytes);
srcOffsetBytes += 0x40 - dstOffsetBytes;
byteCount -= 0x40 - dstOffsetBytes;
SHATransform(_tmp, _state, _buffer);
dstOffsetBytes = 0;
}
while (byteCount >= 0x40)
{
Buffer.BlockCopy(partIn, srcOffsetBytes, this._buffer, 0, 0x40);
srcOffsetBytes += 0x40;
byteCount -= 0x40;
SHATransform(_tmp, _state, _buffer);
}
if (byteCount > 0)
{
Buffer.BlockCopy(partIn, srcOffsetBytes, this._buffer, dstOffsetBytes, byteCount);
}
}
return true;
}
#region SHA256 internals
private static uint ROTR32(int b, uint x) { return unchecked((x >> b) | (x << (32 - b))); }
private static uint SHR(int b, uint x) { return unchecked(x >> b); }
private static uint SHA256_F0(uint x, uint y, uint z) { return unchecked(((x) & (y)) ^ ((~(x)) & (z))); }
private static uint SHA256_F1(uint x, uint y, uint z) { return unchecked(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))); }
private static uint SHA256_F2(uint x) { return unchecked(ROTR32(2, (x)) ^ ROTR32(13, (x)) ^ ROTR32(22, (x))); }
private static uint SHA256_F3(uint x) { return unchecked(ROTR32(6, (x)) ^ ROTR32(11, (x)) ^ ROTR32(25, (x))); }
private static uint SHA256_F4(uint x) { return unchecked(ROTR32(7, (x)) ^ ROTR32(18, (x)) ^ SHR(3, (x))); }
private static uint SHA256_F5(uint x) { return unchecked(ROTR32(17, (x)) ^ ROTR32(19, (x)) ^ SHR(10, (x))); }
static readonly uint[] SHA256_K = new uint[]{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
#endregion
private static void SHATransform(uint[] tmp, uint[] state, byte[] block)
{
Debug.Assert(tmp != null && tmp.Length == 64);
unchecked
{
uint a = state[0], b = state[1], c = state[2], d = state[3], e = state[4], f = state[5], g = state[6], h = state[7];
DWORDFromBigEndian(tmp, 0x10, block);
for (int i = 16; i < 64; i++)
tmp[i] = SHA256_F5(tmp[i - 2]) + tmp[i - 7] + SHA256_F4(tmp[i - 15]) + tmp[i - 16];
for (int i = 0; i < 64; i++)
{
uint T1 = h + SHA256_F3(e) + SHA256_F0(e, f, g) + SHA256_K[i] + tmp[i];
uint T2 = SHA256_F2(a) + SHA256_F1(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
}
#endregion
}
#endregion
}
#endregion
#region hash_algos
///
/// Get an array of available hashing algorithms. These names can be used in hash* functions, as the "algo" argument.
///
/// Zero-based indexed array of names of hashing algorithms.
[ImplementsFunction("hash_algos")]
public static PhpArray GetHashAlgorithms()
{
var algos = HashPhpResource.HashAlgorithms;
var result = new PhpArray(algos.Count, 0);
foreach (var x in algos)
result.Add(x.Key);
return result;
}
#endregion
#region options
///
/// hash_init() options
///
[Flags]
public enum HashInitOptions
{
///
/// No options.
/// Default.
///
[ImplementsConstant("HASH_DEFAULT")]
HASH_DEFAULT = 0,
///
/// Use HMAC. The key must be provided.
///
[ImplementsConstant("HASH_HMAC")]
HASH_HMAC = 1,
}
#endregion
#region hash_copy, hash_init, hash_update, hash_final, hash_update_file, hash_update_stream
[ImplementsFunction("hash_copy")]
public static PhpResource HashCopy(PhpResource context)
{
HashPhpResource h = context as HashPhpResource;
if (h == null)
{
PhpException.InvalidArgumentType("context", PhpResource.PhpTypeName);
return null;
}
return h.Clone();
}
[ImplementsFunction("hash_init")]
public static PhpResource HashInit(string algo)
{
return HashInit(algo, HashInitOptions.HASH_DEFAULT, null);
}
[ImplementsFunction("hash_init")]
public static PhpResource HashInit(string algo, HashInitOptions options)
{
return HashInit(algo, options, null);
}
[ImplementsFunction("hash_init")]
public static PhpResource HashInit(string algo, HashInitOptions options, PhpBytes key)
{
bool hmac = (options & HashInitOptions.HASH_HMAC) != 0;
if (hmac && (key == null || key.Length == 0))
{
PhpException.Throw(PhpError.Warning, "HMAC requested without a key"); // TODO: to resources
return null;
}
HashPhpResource.HashAlgFactory algFactory;
if (!HashPhpResource.HashAlgorithms.TryGetValue(algo, out algFactory))
{
PhpException.Throw(PhpError.Warning, "Unknown hashing algorithm: " + algo); // TODO: to resources
return null;
}
//
// create the hashing algorithm context
//
HashPhpResource h = algFactory();
h.options = options;
//
// HMAC
//
if (hmac)
{
// Take the given key and hash it in the context of newly created hashing context.
Debug.Assert(h.BlockSize > 0);
byte[] K = key.ReadonlyData;
if (K.Length > h.BlockSize)
{
// provided key is too long, hash it to obtain shorter key
h.Update(K);
K = h.Final();
h.Init();// restart the algorithm
}
else
{
K = (byte[])K.Clone();
}
if (K.Length != h.BlockSize)
{
Debug.Assert(K.Length < h.BlockSize);
byte[] KAligned = new byte[h.BlockSize];
K.CopyTo(KAligned, 0);
K = KAligned;
}
for (int i = 0; i < K.Length; ++i)
K[i] ^= 0x36;
h.Update(K);
h.HMACkey = K;
}
return h;
}
[ImplementsFunction("hash_update")]
public static bool HashUpdate(PhpResource context, PhpBytes data)
{
HashPhpResource h = context as HashPhpResource;
if (h == null)
{
PhpException.InvalidArgumentType("context", PhpResource.PhpTypeName);
return false;
}
h.Update(data.ReadonlyData);
return true;
}
[ImplementsFunction("hash_final")]
public static object HashFinal(PhpResource context)
{
return HashFinal(context, false);
}
[ImplementsFunction("hash_final")]
public static object HashFinal(PhpResource context, bool raw_output)
{
HashPhpResource h = context as HashPhpResource;
if (h == null)
{
PhpException.InvalidArgumentType("context", PhpResource.PhpTypeName);
return null;
}
byte[] hash = h.Final();
//
// HMAC
//
if (/*(h.options & HashInitOptions.HASH_HMAC) != 0 &&*/ h.HMACkey != null)
{
/* Convert K to opad -- 0x6A = 0x36 ^ 0x5C */
byte[] K = h.HMACkey;
for (int i = 0; i < K.Length; ++i)
K[i] ^= 0x6A;
/* Feed this result into the outter hash */
h.Init();
h.Update(K);
h.Update(hash);
hash = h.Final();
/* Zero the key */
//Array.Clear(K, 0, K.Length);
h.HMACkey = null;
}
//
// output
//
if (raw_output)
return new PhpBytes(hash);
else
return StringUtils.BinToHex(hash, null);
}
[ImplementsFunction("hash_update_file")]
public static bool HashUpdateFromFile(PhpResource context, string filename)
{
return HashUpdateFromFile(context, filename, StreamContext.Default);
}
[ImplementsFunction("hash_update_file")]
public static bool HashUpdateFromFile(PhpResource context, string filename, PhpResource stream_context)
{
// hashing context
HashPhpResource h = context as HashPhpResource;
if (h == null)
{
PhpException.InvalidArgumentType("context", PhpResource.PhpTypeName);
return false;
}
// stream context
StreamContext sc = StreamContext.GetValid(stream_context);
if (sc == null)
return false;
// read data from file (or URL)
using (PhpStream stream = PhpStream.Open(filename, "rb", StreamOpenOptions.Empty, sc))
{
if (stream == null)
return false;
if (HashUpdateFromStream(h, stream, -1) < 0)
return false;
}
//
return true;
}
[ImplementsFunction("hash_update_stream")]
[return: CastToFalse]
public static int HashUpdateFromStream(PhpResource context, PhpResource handle)
{
return HashUpdateFromStream(context, handle, -1);
}
[ImplementsFunction("hash_update_stream")]
[return: CastToFalse]
public static int HashUpdateFromStream(PhpResource context, PhpResource handle, int length/*=-1*/)
{
// hashing context
HashPhpResource h = context as HashPhpResource;
if (h == null)
{
PhpException.InvalidArgumentType("context", PhpResource.PhpTypeName);
return -1;
}
PhpStream stream = PhpStream.GetValid(handle);
if (stream == null)
return -1;
// read data from stream, return number of used bytes
return HashUpdateFromStream(h, stream, length);
}
///
/// Pump data from valid PHP stream into the hashing incremental algorithm.
///
/// Hash resource to be updated from given . Cannot be null.
/// The to read from. Cannot be null.
/// Maximum number of bytes to read from . Or -1 to read entire stream.
/// Number of bytes read from given .
private static int HashUpdateFromStream(HashPhpResource/*!*/context, PhpStream/*!*/stream, int length/*=-1*/)
{
Debug.Assert(context != null);
Debug.Assert(stream != null);
int n = 0;
bool done = false;
const int buffsize = 4096;
do
{
// read data from stream sub-sequentially to lower memory consumption
int bytestoread = (length < 0) ? buffsize : Math.Min(length - n, buffsize); // read bytes, or up to bytes
if (bytestoread == 0)
break;
PhpBytes bytes = stream.ReadBytes(bytestoread);
if (bytes == null)
break;
// update the incremental hash
context.Update(bytes.ReadonlyData);
n += bytes.Length;
done = (bytes.Length < bytestoread);
} while (!done);
return n;
}
#endregion
#region hash, hash_file
[ImplementsFunction("hash")]
[PureFunction]
public static object DoHash(string algo, PhpBytes data)
{
return DoHash(algo, data, false);
}
[ImplementsFunction("hash")]
[PureFunction]
public static object DoHash(string algo, PhpBytes data, bool raw_output)
{
var h = HashInit(algo);
if (h == null)
return false;
if (!HashUpdate(h, data))
return false;
return HashFinal(h, raw_output);
}
[ImplementsFunction("hash_file")]
public static object DoHashFile(string algo, string filename)
{
return DoHashFile(algo, filename, false);
}
[ImplementsFunction("hash_file")]
public static object DoHashFile(string algo, string filename, bool raw_output)
{
var h = HashInit(algo);
if (h == null)
return false;
if (!HashUpdateFromFile(h, filename))
return false;
return HashFinal(h, raw_output);
}
#endregion
#region hash_hmac, hash_hmac_file
[ImplementsFunction("hash_hmac")]
[PureFunction]
public static object DoHashHMAC(string algo, PhpBytes data, PhpBytes key)
{
return DoHashHMAC(algo, data, key, false);
}
[ImplementsFunction("hash_hmac")]
[PureFunction]
public static object DoHashHMAC(string algo, PhpBytes data, PhpBytes key, bool raw_output)
{
var h = HashInit(algo, HashInitOptions.HASH_HMAC, key);
if (h == null)
return false;
if (!HashUpdate(h, data))
return false;
return HashFinal(h, raw_output);
}
[ImplementsFunction("hash_hmac_file")]
public static object DoHashHMACFile(string algo, string filename, PhpBytes key)
{
return DoHashHMACFile(algo, filename, key, false);
}
[ImplementsFunction("hash_hmac_file")]
public static object DoHashHMACFile(string algo, string filename, PhpBytes key, bool raw_output)
{
var h = HashInit(algo, HashInitOptions.HASH_HMAC, key);
if (h == null)
return false;
if (!HashUpdateFromFile(h, filename))
return false;
return HashFinal(h, raw_output);
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Highlighting.cs
================================================
/*
Copyright (c) 2005-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using PHP;
using PHP.Core;
using PHP.Core.Parsers;
#if SILVERLIGHT
using System.Windows.Browser;
#else
using System.Web;
using System.Diagnostics;
#endif
namespace PHP.Library
{
///
/// Functions for highlighting PHP source code written as HTML.
///
public static class Highlighting
{
#region highlight_file, highlight_string, show_source
///
/// Writes PHP source code from file highlighted to output.
///
/// PHP source file to highlight.
/// True if the source code was succesfuly highlighted.
[ImplementsFunction("highlight_file")]
public static object HighlightFile(string fileName)
{
return HighlightFile(fileName, false);
}
///
/// Writes PHP source code from file highlighted to output or returns this code as string
/// according to second parameter.
///
/// PHP source file to highlight.
/// True if highlighted code should be returned,
/// false if it should be printed out.
/// Highlighted source code or - if it is printed out - true if the code was
/// highlighted succesfuly, false otherwise.
[ImplementsFunction("highlight_file")]
public static object HighlightFile(string fileName, bool returnHighlighted)
{
using (PhpStream stream = PhpStream.Open(fileName, "rt"))
{
if (stream == null)
return false;
string source = stream.ReadStringContents(-1);
Debug.Assert(source != null);
return HighlightString(source, returnHighlighted);
}
}
///
/// Writes highlighted PHP source code passed as string to output.
///
/// PHP source code to highlight
/// True if the source code was successfully highlighted.
[ImplementsFunction("highlight_string")]
public static object HighlightString(string str)
{
return HighlightString(str, false);
}
///
/// Writes PHP source code highlighted to output or returns this code as string
/// according to second parameter.
///
/// PHP source code
/// True if highlighted code should be returned,
/// false if it should be printed out.
/// Highlighted source code or - if it is printed out - true if the code was
/// highlighted succesfuly, false otherwise.
[ImplementsFunction("highlight_string")]
public static object HighlightString(string str, bool returnHighlighted)
{
if (str == null) str = "";
ScriptContext context = ScriptContext.CurrentContext;
LibraryConfiguration config = LibraryConfiguration.GetLocal(context);
TextWriter output = returnHighlighted ? new StringWriter() : context.Output;
bool success = Highlight(str, output, config);
if (returnHighlighted)
return output.ToString();
else
return success;
}
///
/// Alias for .
///
[ImplementsFunction("show_source")]
public static object ShowSource(string fileName)
{
return HighlightFile(fileName, false);
}
///
/// Alias for .
///
[ImplementsFunction("show_source")]
public static object ShowSource(string fileName, bool returnHighlighted)
{
return HighlightFile(fileName, returnHighlighted);
}
#endregion
public static bool Highlight(string/*!*/ code, TextWriter/*!*/ output, LibraryConfiguration/*!*/ config)
{
if (code == null)
throw new ArgumentNullException("code");
if (output == null)
throw new ArgumentNullException("output");
if (config == null)
throw new ArgumentNullException("config");
Tokenizer.Features features = Tokenizer.Features.Default | Tokenizer.Features.ContextKeywords;
Tokenizer tokenizer = new Tokenizer(new StringReader(code), features);
Tokens token;
output.Write("");
output.Write("");
for (; ; )
{
token = tokenizer.GetNextToken();
if (token == Tokens.ERROR || token == Tokens.EOF) break;
string fcolor = config.Highlighting.Default;
bool is_bold = false;
switch (tokenizer.TokenCategory)
{
case TokenCategory.Unknown:
case TokenCategory.Text:
case TokenCategory.Delimiter:
case TokenCategory.Number:
case TokenCategory.Identifier:
case TokenCategory.Operator:
case TokenCategory.WhiteSpace:
break;
case TokenCategory.Html:
fcolor = config.Highlighting.Html;
break;
case TokenCategory.Comment:
case TokenCategory.LineComment:
fcolor = config.Highlighting.Comment;
break;
case TokenCategory.ScriptTags:
fcolor = config.Highlighting.ScriptTags;
break;
case TokenCategory.Keyword:
fcolor = config.Highlighting.Keyword;
break;
case TokenCategory.StringCode:
is_bold = true;
fcolor = config.Highlighting.String;
break;
case TokenCategory.String:
fcolor = config.Highlighting.String;
break;
}
output.Write("");
if (is_bold) output.Write("");
output.Write(HttpUtility.HtmlEncode(tokenizer.TokenText));
if (is_bold) output.Write(" ");
output.Write(" ");
}
output.Write(" ");
return token != Tokens.ERROR;
}
}
}
================================================
FILE: Source/ClassLibrary/LibraryDescriptor.cs
================================================
/*
Copyright (c) 2005-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Xml;
using System.IO;
using System.Configuration;
using System.Runtime.Serialization;
using PHP.Core;
#if !SILVERLIGHT
using System.Web;
using System.Runtime.Serialization.Formatters.Binary;
#endif
namespace PHP.Library
{
///
/// Describes the class library assembly content and configuration.
///
public sealed class LibraryDescriptor : PhpLibraryDescriptor
{
// default extension:
public const string ExtStandard = "standard";
// other extensions:
//public const string ExtCalendar = "calendar";//There isn't managed calender in class library
public const string ExtCore = "Core";//Class Library defines some functions/constants that in PHP belongs to Core
public const string ExtSession = "session";
public const string ExtCType = "ctype";
public const string ExtTokenizer = "tokenizer";
public const string ExtDate = "date";
public const string ExtPcre = "pcre";
public const string ExtEreg = "ereg";
public const string ExtJson = "json";
public const string ExtHash = "hash";
public const string ExtSpl = "SPL";
///
/// Stores one and only instance of the class that is created when the assembly is loaded.
///
internal static LibraryDescriptor Singleton { get { return singleton; } }
private static LibraryDescriptor singleton;
/////
///// Gets a list of implemented extensions.
/////
//public override string[] ImplementedExtensions
//{
// get { return new string[] { ExtStandard, ExtCore,/* ExtCalendar,*/ ExtCType, ExtSession, ExtTokenizer, ExtDate, ExtPcre, ExtEreg, ExtJson, ExtHash, ExtSpl }; }
//}
///
/// Called by the Core after the library is loaded.
///
protected override void Loaded(PhpLibraryAttribute assemblyAttribute, LibraryConfigStore config)
{
base.Loaded(assemblyAttribute, config);
singleton = this;
#if !SILVERLIGHT
LibraryConfiguration.RegisterLegacyOptions();
// registers session handlers:
SessionHandlers.RegisterHandler(PhpSessionHandler.Default);
SessionHandlers.RegisterHandler(PhpUserSessionHandler.Default);
SessionHandlers.RegisterHandler(AspNetThruSessionHandler.Default);
// registers serializers:
Serializers.RegisterSerializer(PhpSerializer.Default);
//Serializers.RegisterSerializer(PhalangerSerializer.Default);
Serializers.RegisterSerializer(new ContextualSerializer("dotnet", delegate(PHP.Core.Reflection.DTypeDesc caller/*ignored*/)
{
return new BinaryFormatter(
null,
new StreamingContext(StreamingContextStates.Persistence, new SerializationContext()));
}));
#endif
}
#if !SILVERLIGHT
///
/// Creates empty library configuration context.
///
/// An initialized configuration context. Should not be a null reference.
protected override ConfigContextBase CreateConfigContext()
{
return new ConfigContextBase(new LibraryConfiguration(), null);
}
///
/// Parses a configuration section belonging to the library.
///
/// A library configuration context.
/// The context of the configuration created by Phalanger Core.
/// A XML node containing the configuration or its part.
/// Updated library configuration context.
protected override ConfigContextBase ParseConfig(ConfigContextBase result, PhpConfigurationContext context, XmlNode section)
{
LibraryConfiguration local = (LibraryConfiguration)result.Local;
// parses XML tree:
foreach (XmlNode node in section.ChildNodes)
{
if (node.NodeType == XmlNodeType.Element)
{
switch (node.Name)
{
case "mailer":
ConfigUtils.ParseNameValueList(node, context, local.Mailer);
break;
case "highlighting":
ConfigUtils.ParseNameValueList(node, context, local.Highlighting);
break;
case "session":
// allowed only in web application configuration:
if (HttpContext.Current == null)
throw new ConfigurationErrorsException(CoreResources.GetString("web_only_option"), node);
ConfigUtils.ParseNameValueList(node, context, local.Session);
break;
case "date":
ConfigUtils.ParseNameValueList(node, context, local.Date);
break;
case "serialization":
ConfigUtils.ParseNameValueList(node, context, local.Serialization);
break;
default:
throw new ConfigUtils.InvalidNodeException(node);
}
}
}
return result;
}
#endif
}
}
================================================
FILE: Source/ClassLibrary/Locale.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Threading;
using System.Globalization;
using System.Collections;
using System.ComponentModel;
using PHP.Core;
using System.Diagnostics;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
///
/// This class manages locale information for PHP and interacts .NET Framework.
///
///
public static class Locale
{
[ImplementsConstant("CHAR_MAX")]
public const int CHAR_MAX = 127;
private static readonly char[] CultureNameSeparators = new char[] { '-', '_' };
#region Categorized Cultures
///
/// A locale categories.
///
///
public enum Category
{
///
/// Assigning a culture to this category is equivalent to assigning it to all other categories.
///
[ImplementsConstant("LC_ALL")]
All,
///
/// Influences function strcoll .
///
[ImplementsConstant("LC_COLLATE")]
Collate,
///
/// Influences functions strtolower , strtoupper
///
[ImplementsConstant("LC_CTYPE")]
CType,
///
/// Influences functions money_format , localeconv
///
[ImplementsConstant("LC_MONETARY")]
Monetary,
///
/// Influences function localeconv and formatting of all floating-point numbers.
///
[ImplementsConstant("LC_NUMERIC")]
Numeric,
///
/// Influences function strftime .
///
[ImplementsConstant("LC_TIME")]
Time
}
///
/// Cultures associated with cathegories.
///
private static CultureInfo[] cultures
{
get
{
if (_cultures == null)
_cultures = new CultureInfo[(int)Category.Time + 1];
return _cultures;
}
}
#if !SILVERLIGHT
[ThreadStatic]
#endif
private static CultureInfo[] _cultures;
static Locale()
{
RequestContext.RequestEnd += new Action(Clear);
}
private static void Clear()
{
_cultures = null;
}
///
/// Gets a culture specific for the given category.
///
/// The category.
/// Non-null culture info.
public static CultureInfo GetCulture(Category category)
{
if ((int)category < 0 || (int)category >= cultures.Length)
throw new ArgumentOutOfRangeException("category");
return cultures[(int)category] ?? CultureInfo.CurrentCulture;
}
///
/// Sets a culture specific for the given category.
///
/// The category.
/// The culture.
public static void SetCulture(Category category, CultureInfo culture)
{
if ((int)category < 0 || (int)category >= cultures.Length)
throw new ArgumentOutOfRangeException("category");
// sets specific culture:
if (category == Category.All)
{
for (int i = 0; i < cultures.Length; i++)
cultures[i] = culture;
}
else
{
cultures[(int)category] = culture;
}
// sets global culture used in many places:
if (category == Category.All || category == Category.Numeric)
Thread.CurrentThread.CurrentCulture = culture;
}
///
/// Creates a new comparing according to the current collate.
///
/// Whether to create a case-insensitive comparer.
/// The comparer.
public static PhpLocaleStringComparer GetStringComparer(bool ignoreCase)
{
return new PhpLocaleStringComparer(GetCulture(Category.Collate), ignoreCase);
}
#endregion
#region localeconv
///
/// Converts .NET groups information to PHP array.
///
private static PhpArray GetGroupingArray(int[] groups)
{
Debug.Assert(groups != null);
int length = groups.Length;
PhpArray result = new PhpArray(length, 0);
for (int i = 0; i < length; i++)
if (groups[i] == 0)
result.Add(i, CHAR_MAX);
else
result.Add(i, groups[i]);
return result;
}
///
/// Gets information about the current thread culture.
///
/// The associative array of number and currency information.
[ImplementsFunction("localeconv")]
public static PhpArray localeconv()
{
PhpArray result = new PhpArray(0, 18);
NumberFormatInfo number;
number = GetCulture(Category.Numeric).NumberFormat;
result.Add("decimal_point", number.NumberDecimalSeparator);
result.Add("thousands_sep", number.NumberGroupSeparator);
result.Add("grouping", GetGroupingArray(number.CurrencyGroupSizes));
result.Add("positive_sign", number.PositiveSign);
result.Add("negative_sign", number.NegativeSign);
result.Add("frac_digits", number.CurrencyDecimalDigits);
number = GetCulture(Category.Monetary).NumberFormat;
result.Add("currency_symbol", number.CurrencySymbol);
result.Add("mon_decimal_point", number.CurrencyDecimalSeparator);
result.Add("mon_thousands_sep", number.CurrencyGroupSeparator);
result.Add("mon_grouping", GetGroupingArray(number.CurrencyGroupSizes));
// currency patterns: 0 -> $n, 1 -> n$, 2 -> $ n, 3 -> n $
result.Add("p_cs_precedes", number.CurrencyPositivePattern == 0 || number.CurrencyPositivePattern == 2);
result.Add("p_sep_by_space", number.CurrencyPositivePattern == 2 || number.CurrencyPositivePattern == 3);
result.Add("n_cs_precedes", number.CurrencyNegativePattern == 0 || number.CurrencyNegativePattern == 2);
result.Add("n_sep_by_space", number.CurrencyNegativePattern == 2 || number.CurrencyNegativePattern == 3);
result.Add("p_sign_posn", 1);
result.Add("n_sign_posn", 1);
return result;
}
#endregion
#region setlocale, strcoll, nl_langinfo (NS)
#if !SILVERLIGHT
///
/// Sets or gets the current thread culture settings.
///
///
/// A category to be modified. The only supported value in this version is .
///
/// Either an instance of containing locales or a locale.
/// If is not of type contains locales, ignored otherwise.
/// The culture string (e.g. "en-US").
///
///
/// Values specified in and are converted to strings.
/// Each value should have format "{language}-{region}" or "{language}_{region}" or "{language}" or special values "C" or empty string
/// which represents the invariant culture or special values null or "0" which means no changes is made
/// by the method rather the current culture name is returned.
/// The first value containing am existing culture string is used.
///
///
/// has an invalid or unsupported value. (Warning)
[ImplementsFunction("setlocale")]
[return: CastToFalse]
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);
}
///
/// Searches in given objects for a locale string describing an existing culture.
///
/// Contains either an instance of containing locales or a locale.
/// If is not of type contains locales, ignored otherwise.
/// The resulting culture. A null reference means no culture has been found.
/// Whether a culture settings should be changed.
private static bool GetFirstExistingCulture(object locale, object[] moreLocales, out CultureInfo culture)
{
PhpArray array;
IEnumerator locales;
culture = null;
if ((array = locale as PhpArray) != null)
{
// locales are stored in the "locale" array:
locales = array.GetEnumerator();
locales.MoveNext();
locale = locales.Current;
}
else if (moreLocales != null)
{
// locales are stored in the "locale" and "moreLocales":
locales = moreLocales.GetEnumerator();
}
else
{
throw new ArgumentNullException("moreLocales");
}
// enumerates locales and finds out the first which is valid:
for (; ; )
{
string name = (locale != null) ? Core.Convert.ObjectToString(locale) : null;
culture = GetCultureByName(name);
// name is "empty" then the current culture is not changed:
if (name == null || name == "0") return false;
// if culture exists and is specific then finish searching:
if (culture != null) return true;
// the next locale:
if (!locales.MoveNext()) return false;
locale = locales.Current;
}
}
///
/// Gets a culture of a specified name.
/// Tries "{language}-{country}", "{country}-{language}".
/// Recognizes "C", "", "0" and null as invariant culture.
/// Note, PHP swaps language and country codes.
///
private static CultureInfo GetCultureByName(string name)
{
// invariant culture:
if (name == null || name == "0" || name == String.Empty || name == "C")
return CultureInfo.InvariantCulture;
int separator = name.IndexOfAny(CultureNameSeparators);
if (separator < 0)
{
try
{
return CultureInfo.CreateSpecificCulture(name);
}
catch (ArgumentException)
{
}
}
else
{
string part1 = name.Substring(0, separator);
string part2 = name.Substring(separator + 1);
try
{
return CultureInfo.CreateSpecificCulture(String.Concat(part1, "-", part2));
}
catch (ArgumentException)
{
try
{
return CultureInfo.CreateSpecificCulture(String.Concat(part2, "-", part1));
}
catch (ArgumentException)
{
}
}
}
return null;
}
///
/// Compares two specified strings, honoring their case, using culture specific comparison.
///
/// A string.
/// A string.
///
/// Returns -1 if is less than ; +1 if is greater than ,
/// and 0 if they are equal.
///
[ImplementsFunction("strcoll")]
public static int StringCollate(string str1, string str2)
{
return String.Compare(str1, str2, false, GetCulture(Category.Collate));
}
///
/// Not supported.
///
[ImplementsFunction("nl_langinfo", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static string nl_langinfo(int item)
{
PhpException.FunctionNotSupported();
return null;
}
#endif
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Mailer.CLR.cs
================================================
/*
Copyright (c) 2004-2012 Pavel Novak, Tomas Matousek, DEVSENSE.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO: .NET 2.0
*/
using System;
using PHP.Core;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using System.Diagnostics;
namespace PHP.Library
{
///
/// Maps PHP mailing methods to Framework ones.
///
///
public static class Mailer
{
#region mail, ezmlm_hash
///
/// Sends e-mail only with essential headers.
///
/// Recipient e-mail address.
/// E-mail subject.
/// Message body.
/// True if mail was accepted to send.
[ImplementsFunction("mail")]
public static bool Mail(string to, string subject, string message)
{
return Mail(to, subject, message, null);
}
///
/// Sends e-mail, allows specify additional headers.
/// Supported are Cc, Bcc, From, Priority, Content-type. Others are ignored.
///
///
/// E-mail addresses specified in additional headers must be valid (including From header).
/// Otherwise your e-mail will not be send.
///
/// Recipient e-mail address.
/// E-mail subject.
/// Message body.
/// Additional headers.
/// True if mail was accepted to send.
[ImplementsFunction("mail")]
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();
}
}
///
/// Sends e-mail, allows specify additional headers and additional parameters.
///
///
/// Additional parameters are not supported, must be null or empty string.
/// Use overload function without additionalParameters parameter.
///
/// Recipient e-mail address.
/// E-mail subject.
/// Message body.
/// Additional headers.
/// Additional parameters.
/// True if mail was accepted to send.
[ImplementsFunction("mail")]
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);
}
///
/// Counts hash value needed by EZMLM.
///
/// Mail address for which is hash value calculating.
/// Calculated hash value.
[ImplementsFunction("ezmlm_hash")]
public static int ezmlm_hash(string addr)
{
// this algorithm is assumed from PHP source code
uint h = 5381; // must be 32-bit unsigned
addr = addr.ToLower();
unchecked // overflow may occur, this is OK.
{
for (int j = 0; j < addr.Length; j++)
{
h = (h + (h << 5)) ^ (uint)addr[j];
}
}
h = (h % 53);
return (int)h;
}
#endregion
#region Mail headers parsing
///
/// Extracts mail headers from string headers and if the string contains supported headers,
/// appropriate fields are set to MailMessage mm object.
/// Supported headers are: Cc, Bcc, From, Priority, Content-type. Others are ignored.
///
/// String containing mail headers.
/// MailMessage object to set fields according to headers .
private static void SetMailHeaders(string headers, MailMessage mm)
{
// parse additional headers
Regex headerRegex = new Regex("^([^:]+):[ \t]*(.+)$");
Match headerMatch;
int line_begin, line_end = -1;
while (true)
{
line_begin = line_end + 1;
// search for non-empty line
while (line_begin < headers.Length && (headers[line_begin] == '\n' || headers[line_begin] == '\r'))
line_begin++;
if (line_begin >= headers.Length)
break;
// find the line end
line_end = line_begin + 1;
while (line_end < headers.Length && headers[line_end] != '\n' && headers[line_end] != '\r')
line_end++;
string header = headers.Substring(line_begin, line_end - line_begin);
headerMatch = headerRegex.Match(header);
// ignore wrong formatted headers
if (!headerMatch.Success)
continue;
string sw = headerMatch.Groups[1].Value.Trim().ToLower();
switch (sw)
{
case "cc":
mm.CC.Add(ExtractMailAddressesOnly(headerMatch.Groups[2].Value, Int32.MaxValue));
break;
case "bcc":
mm.Bcc.Add(ExtractMailAddressesOnly(headerMatch.Groups[2].Value, Int32.MaxValue));
break;
case "from":
string from = ExtractMailAddressesOnly(headerMatch.Groups[2].Value, 1);
if (!String.IsNullOrEmpty(from))
{
try
{
mm.From = new MailAddress(from);
}
catch (FormatException)
{ }
}
break;
case "priority":
mm.Priority = ExtractPriority(headerMatch.Groups[2].Value);
break;
case "content-type":
ExtractContentType(headerMatch.Groups[2].Value, mm);
break;
default:
mm.Headers.Add(headerMatch.Groups[1].Value.Trim(), headerMatch.Groups[2].Value);
break;
}
}
}
///
/// Converts semicolon separated list of email addresses and names of email owners
/// to semicolon separated list of only email addresses.
///
/// Semicolon separated list of email addresses and names.
/// Max number of emails returned.
/// Semicolon separated list of email addresses only.
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);
}
///
/// Used for converting header Priority to MailPriority value needed by .NET Framework mailer.
///
/// "Priority:" header value.
/// MailPriority specified by header value.
private static MailPriority ExtractPriority(string p)
{
switch (p.Trim().ToLowerInvariant())
{
case "high":
return MailPriority.High;
case "low":
return MailPriority.Low;
case "normal":
default:
return MailPriority.Normal;
}
}
///
/// Used for converting header ContentType to MailFormat value and Encoding class.
///
/// "Content-type:" header value
/// Mail message instance.
private static void ExtractContentType(string contentTypeHeader, MailMessage mm)
{
contentTypeHeader = contentTypeHeader.Trim().ToLower();
// extract content-type value parts (type/subtype; parameter1=value1; parameter2=value2)
string[] headerParts = contentTypeHeader.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (headerParts == null || headerParts.Length == 0)
return;
// process type/subtype
mm.IsBodyHtml = (headerParts[0].Trim() == "text/html");
for (int i = 1; i < headerParts.Length; ++i)
{
int asspos = headerParts[i].IndexOf('=');
if (asspos < 1) continue;
string propertyName = headerParts[i].Remove(asspos).Trim();
string propertyValue = headerParts[i].Substring(asspos + 1).Trim(new char[]{' ','\t','\"','\'','\n','\r'});
switch (propertyName)
{
case "charset":
try
{
mm.BodyEncoding = Encoding.GetEncoding(propertyValue);
}
catch (Exception)
{}
break;
default:
break;
}
}
// add header into the mail message as it is
mm.Headers.Add("content-type", contentTypeHeader);
}
#endregion
#region RawSmtpClient
///
/// Raw SMTP client serving the needs of PHP mail functions. This is reimplemented mainly because .NET SmtpClient provides
/// certain level of abstraction which is incompatible with mail function usage. Currently not as much advanced, but it can easily be.
///
internal class RawSmtpClient
{
///
/// Wait time for Socket.Poll - in microseconds.
///
private const int _pollTime = 100000;
///
/// Timeout of connection. We don't want to block for too long.
///
private const int _connectionTimeout = 5000;
///
/// Gets a value indicating whether this client is connected to a server.
///
public bool Connected { get { return _connected; } }
private bool _connected;
///
/// Gets or sets a value indicating whether this client should implicitly use ESMTP to connect to the server.
///
public bool UseExtendedSmtp { get { return _useExtendedSmtp; } }
private bool _useExtendedSmtp;
///
/// Gets host name set for this client to connect to.
///
public string/*!*/HostName { get { return _hostName; } }
private readonly string/*!*/_hostName;
///
/// Gets port number set for this client to connect to.
///
public int Port { get { return _port; } }
private readonly int _port;
///
/// Gets a list of SMTP extensions supported by current connection.
///
public string[] Extensions { get { return _extensions; } }
private string[] _extensions;
private TextReader _reader;
private TextWriter _writer;
private Socket _socket;
private NetworkStream _stream;
public RawSmtpClient(string hostName)
: this(hostName, 25)
{
}
///
/// Initializes a new instance of AdvancedSmtp client class.
///
/// Host name (IP or domain name) of the SMTP server.
/// Port on which SMTP server runs.
public RawSmtpClient(string hostName, int port)
{
_hostName = hostName ?? string.Empty;
_port = port;
_connected = false;
_useExtendedSmtp = true;
}
///
/// Resets the state of this object.
///
private void ResetConnection()
{
if (_reader != null)
{
_reader.Close();
_reader = null;
}
if (_writer != null)
{
_writer.Close();
_writer = null;
}
if (_stream != null)
{
_stream.Close();
_stream = null;
}
if (_socket != null)
{
if (_socket.Connected)
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
_socket = null;
}
_extensions = null;
_connected = false;
}
///
/// Connects to the server.
///
/// Method throws an exception on any error.
/// If any error occures.
public void Connect()
{
// invariant condition
Debug.Assert(_connected == (_socket != null));
// check whether socket is not already connected
if (_connected)
{
// check whether the socket is OK
bool error = _socket.Poll(_pollTime, SelectMode.SelectError);
if (!error)
// ok, we keep this connection
return;// true;
// close the socket and reset
ResetConnection();
}
// resolve host's domain
IPAddress[] addresses = null;
try
{
addresses = System.Net.Dns.GetHostAddresses(_hostName);
}
catch (Exception e)
{
// DNS error - reset and fail
ResetConnection();
//return false;
throw new SmtpException(e.Message);
}
Debug.Assert(addresses != null);
// create socket
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// begin async connect
IAsyncResult res = _socket.BeginConnect(addresses, _port, null, null);
// wait for some time
res.AsyncWaitHandle.WaitOne(_connectionTimeout);
// if socket could not connect, reset and fail
if (!_socket.Connected)
{
ResetConnection();
throw new SmtpException("Cannot connect to " + _hostName);
}
// if anything inside throws exception, we were not successful
try
{
// end connect
_socket.EndConnect(res);
// create a stream
_stream = new NetworkStream(_socket);
// create _reader and _writer
_reader = new StreamReader(_stream, Encoding.ASCII);
_writer = new StreamWriter(_stream, Encoding.ASCII);
_writer.NewLine = "\r\n";
string line;
// read server welcome message
line = _reader.ReadLine();
// if there is no 220 in the beginning, this is no SMTP server
if (!line.StartsWith("220")) throw new SmtpException("Expected 220, '"+line+"' given");// return false;
//TODO: server name processing
// send ESMTP welcome message
if (_useExtendedSmtp)
{
Post("EHLO " + System.Net.Dns.GetHostName());
// read response
line = _reader.ReadLine();
}
if (_useExtendedSmtp && line.StartsWith("250"))
{
// this is ESMTP server
// ESMTP returns '-' on fourth char if there are any more lines available
if (line[3] == ' ')
{
// there are no extensions
_extensions = ArrayUtils.EmptyStrings;
// success
return;// true;
}
else if (line[3] == '-')
{
List extensions = new List();
// we do not need to read first line - there is only a welcome string
while (true)
{
//read new line
line = _reader.ReadLine();
if (line.StartsWith("250-"))
{
//add new extension name
extensions.Add(line.Substring(4, line.Length - 4));
}
else if (line.StartsWith("250 "))
{
//add new extension name and finish handshake
extensions.Add(line.Substring(4, line.Length - 4));
_extensions = extensions.ToArray();
_connected = true;
return;// true;
}
else
{
//invalid response (do not send QUIT message)
break;
}
}
}
// this is not a valid ESMTP server
}
else if (line.StartsWith("500") || !_useExtendedSmtp)
{
Post("HELO " + System.Net.Dns.GetHostName());
if (Ack("250"))
{
_extensions = ArrayUtils.EmptyStrings;
// handshake complete
_connected = true;
return;// true;
}
}
}
catch (Exception e)
{
throw new SmtpException(e.Message);
} // any error is bad
ResetConnection(); // (do not send QUIT message)
throw new SmtpException("Unexpected"); //return false;
}
///
/// Disconnects the client from the server.
///
public void Disconnect()
{
if (!_connected)
{
ResetConnection();
return;
}
Post("QUIT");
Ack("221", null, (_) => {/*incorrect response (do nothing)*/});
//correct response
ResetConnection();
}
///
/// Sends reset message to the server.
///
private void Reset()
{
if (!_connected) return;
if (_reader.Peek() != -1)
{
// there is something on the input (should be empty)
ResetConnection();
return;
}
Post("RSET");
Ack("250", null,
(_) => ResetConnection());
}
///
/// Starts mail transaction and prepares the data lines from supplied message properties.
/// Processes provided headers to determine cc, bcc and from values.
/// All data will be send as ASCII if possible.
///
/// Sender of the mail.
/// Recipients of the mail.
/// Subject of the mail.
/// Additional headers.
/// Message body.
/// List of message body lines.
private IEnumerable/*!*/ProcessMessageHeaders(string from, string to, string subject, string headers, string body)
{
Dictionary headerHashtable = new Dictionary(StringComparer.OrdinalIgnoreCase);
List> headerList = new List>();
List recipients = new List(1) { to };
//parse headers
if (headers != null)
using (StringReader reader = new StringReader(headers))
{
string line;
while ((line = reader.ReadLine()) != null)
{
int index = line.IndexOf(": ", StringComparison.Ordinal);
if (index > 0)
{
string name = line.Substring(0, index);
string value = line.Substring(index + 2);
//
headerHashtable[name] = headerList.Count; // remember last position of header
headerList.Add(new KeyValuePair(name, value));
// process known headers:
if (from == null && name.EqualsOrdinalIgnoreCase("from"))
from = value;
if (name.EqualsOrdinalIgnoreCase("cc") || name.EqualsOrdinalIgnoreCase("bcc"))
recipients.Add(value); //PostRcptTo(value); // postponed until we are discovering from address
}
}
}
// check from address:
if (from == null)
throw new SmtpException(LibResources.GetString("smtp_sendmail_from_not_set"));
// start mail transaction:
Post(FormatEmailAddress(from, "MAIL FROM:<{0}>"));
Ack("250");
for (int i = 0; i < recipients.Count; i++)
PostRcptTo(recipients[i]);
// additional message lines:
List ret = new List();
// Date:
ret.Add("Date: " + DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zz00", new CultureInfo("en-US")));
// From: // Only add the From: field from parameter if it isn't in the custom headers:
if (!headerHashtable.ContainsKey("from") && !string.IsNullOrEmpty(from))
ret.Add("From: " + from);
// Subject:
ret.Add("Subject: " + (subject ?? "No Subject"));
// To: // Only add the To: field from the parameter if isn't in the custom headers:
if (!headerHashtable.ContainsKey("to") && !string.IsNullOrEmpty(to))
ret.Add("To: " + to);
// add headers, ignore duplicities (only accept the last occurance):
foreach (var headerIndex in headerHashtable.Values)
{
var header = headerList[headerIndex];
ret.Add(string.Format("{0}: {1}", header.Key, header.Value));
}
ret.Add("");
// parse the into lines:
StringReader bodyReader = new StringReader(body);
while (bodyReader.Peek() != -1)
ret.Add(bodyReader.ReadLine());
return ret;
}
///
/// Cut out the address if contained within <...> characters. Otherwise take the whole string.
/// The address is transformed using given format.
///
/// Given mail address.
/// Format to be used for method.
/// Formatted email address.
private static string FormatEmailAddress(string/*!*/address, string/*!*/formatString)
{
Debug.Assert(address != null, "address == null");
Debug.Assert(formatString != null, "formatString == null");
int a, b;
if ((a = address.IndexOf('<')) >= 0 && (b = address.IndexOf('>', a)) >= 0)
address = address.Substring(a + 1, b - a - 1);
return string.Format(formatString, address.Trim());
}
#region Post, Ack
///
/// Writes , appends CRLF and flushes internal writer.
///
/// to be written onto the internal writer.
private void Post(string line)
{
this._writer.WriteLine(line);
this._writer.Flush();
}
private bool Ack(string expected1)
{
return Ack(expected1, null,
(line) => ThrowExpectedResponseHelper(line, expected1));
}
private bool Ack(string expected1, string expected2)
{
return Ack(expected1, expected2,
(line) => ThrowExpectedResponseHelper(line, string.Format("{0} or {1}", expected1, expected2)));
}
private void ThrowExpectedResponseHelper(string givenResponse, string expectedStr)
{
Reset();
throw new SmtpException(string.Format("Expected response {0}, '{1}' given.", expectedStr, givenResponse));
}
private bool Ack(string expected1, string expected2, Action/*!*/fail)
{
Debug.Assert(fail != null);
var line = _reader.ReadLine();
if (expected1 != null && line.StartsWith(expected1, StringComparison.Ordinal))
return true; // ok
if (expected2 != null && line.StartsWith(expected2, StringComparison.Ordinal))
return true; // ok
fail(line);
return false;
}
#endregion
///
/// Send RCPT TO commands.
///
/// List of recipients comma-separated.
private void PostRcptTo(string recipients)
{
if (!string.IsNullOrEmpty(recipients))
foreach (var rcpt in recipients.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
if (rcpt.StartsWith("undisclosed-recipients:", StringComparison.Ordinal))
continue; // this should be specified in To: header, it is not intended for the SMTP server within RCPT TO command
Post(FormatEmailAddress(rcpt, "RCPT TO:<{0}>"));
Ack("250", "251");
}
}
///
/// Sends the raw message.
///
/// On eny error an exception is thrown.
/// When any error occures during the mail send.
public void SendMessage(string from, string to, string subject, string headers, string body)
{
//
// see http://email.about.com/cs/standards/a/smtp_error_code_2.htm for response codes.
//
if (!_connected)
throw new SmtpException("NOT CONNECTED");
// start mail transaction and
// process headers (may contain additional recipients and from address)
// and prepare data that is broken up to form data lines.
// Note ProcessMessageData may add additional recipients, so it must be called before "DATA" section.
var dataLines = ProcessMessageHeaders(from, to, subject, headers, body);
// send DATA
Post("DATA");
Ack("354");
foreach (string dataLine in dataLines)
{
// PHP implementation uses 991 line length limit (including CRLF)
const int maxLineLength = 989;
int lineStart = 0;
int correction = 0;
// if SP character is on the first place, we need to duplicate it
if (dataLine.Length > 0 && dataLine[0] == '.')
_writer.Write('.');
// according to MIME, the lines must not be longer than 998 characters (1000 including CRLF)
// so we need to break such lines using folding
while (dataLine.Length - lineStart > maxLineLength - correction)
{
//break the line, inserting FWS sequence
_writer.WriteLine(dataLine.Substring(lineStart, maxLineLength - correction));
_writer.Write(' ');
lineStart += maxLineLength - correction;
//make correction (whitespace on the next line)
correction += 1;
}
//output the rest of the line
_writer.WriteLine(dataLine.Substring(lineStart));
// flush the stream
_writer.Flush();
}
_writer.WriteLine(".");
// flush the stream
_writer.Flush();
Ack("250");
//return true; // ok
}
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Math.cs
================================================
/*
Copyright (c) 2004-2006 Jan Benda and Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Text;
using System.Collections;
using System.ComponentModel;
using PHP.Core;
#if SILVERLIGHT
using PHP.CoreCLR;
using MathEx = PHP.CoreCLR.MathEx;
#else
using MathEx = System.Math;
using System.Diagnostics;
#endif
namespace PHP.Library
{
///
/// Implements PHP mathematical functions and constants.
///
///
public static class PhpMath
{
#region Per-request Random Number Generators
///
/// Gets an initialized random number generator associated with the current thread.
///
internal static Random Generator
{
get
{
if (_generator == null)
_generator = new Random(unchecked((int)DateTime.UtcNow.ToFileTime()));
return _generator;
}
}
#if !SILVERLIGHT
[ThreadStatic]
#endif
private static Random _generator;
///
/// Gets an initialized Mersenne Twister random number generator associated with the current thread.
///
internal static MersenneTwister MTGenerator
{
get
{
if (_mtGenerator == null)
_mtGenerator = new MersenneTwister(unchecked((uint)DateTime.UtcNow.ToFileTime()));
return _mtGenerator;
}
}
#if !SILVERLIGHT
[ThreadStatic]
#endif
private static MersenneTwister _mtGenerator;
///
/// Registers routine to be called on request end.
///
static PhpMath()
{
RequestContext.RequestEnd += new Action(ClearGenerators);
}
///
/// Nulls and fields on request end.
///
private static void ClearGenerators()
{
_generator = null;
_mtGenerator = null;
}
#endregion
#region Constants
[ImplementsConstant("M_PI")]
public const double Pi = System.Math.PI;
[ImplementsConstant("M_E")]
public const double E = System.Math.E;
[ImplementsConstant("M_LOG2E")]
public const double Log2e = 1.4426950408889634074;
[ImplementsConstant("M_LOG10E")]
public const double Log10e = 0.43429448190325182765;
[ImplementsConstant("M_LN2")]
public const double Ln2 = 0.69314718055994530942;
[ImplementsConstant("M_LN10")]
public const double Ln10 = 2.30258509299404568402;
[ImplementsConstant("M_PI_2")]
public const double PiHalf = 1.57079632679489661923;
[ImplementsConstant("M_PI_4")]
public const double PiFourth = 0.78539816339744830962;
[ImplementsConstant("M_1_PI")]
public const double Pith = 0.31830988618379067154;
[ImplementsConstant("M_2_PI")]
public const double TwoPiths = 0.63661977236758134308;
[ImplementsConstant("M_SQRTPI")]
public const double SqrtPi = 1.77245385090551602729;
[ImplementsConstant("M_2_SQRTPI")]
public const double TwoSqrtPi = 1.12837916709551257390;
[ImplementsConstant("M_SQRT3")]
public const double Sqrt3 = 1.73205080756887729352;
[ImplementsConstant("M_SQRT1_2")]
public const double SqrtHalf = 0.70710678118654752440;
[ImplementsConstant("M_LNPI")]
public const double LnPi = 1.14472988584940017414;
[ImplementsConstant("M_EULER")]
public const double Euler = 0.57721566490153286061;
[ImplementsConstant("NAN")]
public const double NaN = Double.NaN;
[ImplementsConstant("INF")]
public const double Infinity = Double.PositiveInfinity;
#endregion
#region Absolutize Range
///
/// Absolutizes range specified by an offset and a length relatively to a dimension of an array.
///
/// The number of items in array. Should be non-negative.
///
/// The offset of the range relative to the beginning (if non-negative) or the end of the array (if negative).
/// If the offset underflows or overflows the length is shortened appropriately.
///
///
/// The length of the range if non-negative. Otherwise, its absolute value is the number of items
/// which will not be included in the range from the end of the array. In the latter case
/// the range ends with the | |-th item from the end of the array (counting from zero).
///
///
/// Ensures that [offset,offset + length] is subrange of [0,count] .
///
public static void AbsolutizeRange(ref int offset, ref int length, int count)
{
Debug.Assert(count >= 0);
// prevents overflows:
if (offset >= count || count == 0)
{
offset = count;
length = 0;
return;
}
// negative offset => offset is relative to the end of the string:
if (offset < 0)
{
offset += count;
if (offset < 0) offset = 0;
}
Debug.Assert(offset >= 0 && offset < count);
if (length < 0)
{
// there is count-offset items from offset to the end of array,
// the last |length| items is taken away:
length = count - offset + length;
if (length < 0) length = 0;
}
else if ((long)offset + length > count)
{
// interval ends on the end of array:
length = count - offset;
}
Debug.Assert(length >= 0 && offset + length <= count);
}
#endregion
#region rand, srand, getrandmax, uniqid, lcg_value
///
/// Gets 0 or 1 randomly.
///
static int Random01()
{
return (int)Math.Round(Generator.NextDouble());
}
///
/// Seed the random number generator. No return value.
///
[ImplementsFunction("srand")]
public static void Seed()
{
_generator = new Random();
}
///
/// Seed the random number generator. No return value.
///
/// Optional seed value.
[ImplementsFunction("srand")]
public static void Seed(int seed)
{
_generator = new Random(seed);
}
///
/// Show largest possible random value.
///
/// The largest possible random value returned by rand().
[ImplementsFunction("getrandmax")]
public static int GetMaxRandomValue()
{
return Int32.MaxValue;
}
///
/// Generate a random integer.
///
/// A pseudo random value between 0 and getrandmax(), inclusive.
[ImplementsFunction("rand")]
public static int Random()
{
return Generator.Next() + Random01();
}
///
/// Generate a random integer.
///
/// The lowest value to return.
/// The highest value to return.
/// A pseudo random value between min and max, inclusive.
[ImplementsFunction("rand")]
public static int Random(int min, int max)
{
if (min > max)
return Random(max, min);
if (min == max)
return min;
if (max == int.MaxValue)
return Generator.Next(min, int.MaxValue) + Random01();
return Generator.Next(min, max + 1);
}
///
/// Generate a unique ID.
/// Gets a prefixed unique identifier based on the current time in microseconds.
///
/// Returns the unique identifier, as a string.
[ImplementsFunction("uniqid")]
public static string UniqueId()
{
return UniqueId(null, false);
}
///
/// Generate a unique ID.
/// Gets a prefixed unique identifier based on the current time in microseconds.
///
/// Can be useful, for instance, if you generate identifiers simultaneously on several hosts that might happen to generate the identifier at the same microsecond.
/// With an empty prefix , the returned string will be 13 characters long.
///
/// Returns the unique identifier, as a string.
[ImplementsFunction("uniqid")]
public static string UniqueId(string prefix)
{
return UniqueId(prefix, false);
}
///
/// Generate a unique ID.
///
///
/// With an empty prefix, the returned string will be 13 characters long. If more_entropy is TRUE, it will be 23 characters.
///
/// Use the specified prefix.
/// Use LCG to generate a random postfix.
/// A pseudo-random string composed from the given prefix, current time and a random postfix.
[ImplementsFunction("uniqid")]
public static string UniqueId(string prefix, bool more_entropy)
{
// Note that Ticks specify time in 100nanoseconds but it is raised each 100144
// ticks which is around 10 times a second (the same for Milliseconds).
string ticks = String.Format("{0:X}", DateTime.Now.Ticks + Generator.Next());
ticks = ticks.Substring(ticks.Length - 13);
if (prefix == null) prefix = "";
if (more_entropy)
{
string rnd = LcgValue().ToString();
rnd = rnd.Substring(2, 8);
return String.Format("{0}{1}.{2}", prefix, ticks, rnd);
}
else return String.Format("{0}{1}", prefix, ticks);
}
///
/// Generates a pseudo-random number using linear congruential generator in the range of (0,1).
///
///
/// This method uses the Framwork generator
/// which may or may not be the same generator as the PHP one (L(CG(2^31 - 85),CG(2^31 - 249))).
///
///
[ImplementsFunction("lcg_value")]
public static double LcgValue()
{
return Generator.NextDouble();
}
#endregion
#region mt_getrandmax, mt_rand, mt_srand
[ImplementsFunction("mt_getrandmax")]
public static int MtGetMaxRandomValue()
{
return Int32.MaxValue;
}
[ImplementsFunction("mt_rand")]
public static int MtRandom()
{
return MTGenerator.Next();
}
[ImplementsFunction("mt_rand")]
public static int MtRandom(int min, int max)
{
return (min < max) ? MTGenerator.Next(min, max) : MTGenerator.Next(max, min);
}
///
/// Seed the better random number generator.
/// No return value.
///
[ImplementsFunction("mt_srand")]
public static void MtSeed()
{
MtSeed(Generator.Next());
}
///
/// Seed the better random number generator.
/// No return value.
///
/// Optional seed value.
[ImplementsFunction("mt_srand")]
public static void MtSeed(int seed)
{
MTGenerator.Seed(unchecked((uint)seed));
}
#endregion
#region is_nan,is_finite,is_infinite
[ImplementsFunction("is_nan")]
[PureFunction]
public static bool IsNaN(double x)
{
return Double.IsNaN(x);
}
[ImplementsFunction("is_finite")]
[PureFunction]
public static bool IsFinite(double x)
{
return !Double.IsInfinity(x);
}
[ImplementsFunction("is_infinite")]
[PureFunction]
public static bool IsInfinite(double x)
{
return Double.IsInfinity(x);
}
#endregion
#region decbin, bindec, decoct, octdec, dechex, hexdec, base_convert
///
/// Converts the given number to int (if the number is whole
/// and fits into the int's range).
///
///
/// int representation of number if possible, otherwise a double representation.
private static object ConvertToInt(double number)
{
if ((Math.Round(number) == number) && (number <= int.MaxValue) && (number >= int.MinValue))
{
return (int)number;
}
return number;
}
///
/// Converts the lowest 32 bits of the given number to a binary string.
///
///
///
[ImplementsFunction("decbin")]
public static PhpBytes DecToBin(double number)
{
// Trim the number to the lower 32 binary digits.
uint temp = unchecked((uint)number);
return DoubleToBase(temp, 2);
}
///
/// Converts the lowest 32 bits of the given number to a binary string.
///
///
///
[ImplementsFunction("decbin_unicode")]
public static string DecToBinUnicode(double number)
{
// Trim the number to the lower 32 binary digits.
uint temp = unchecked((uint)number);
return DoubleToBaseUnicode(temp, 2);
}
///
/// Returns the decimal equivalent of the binary number represented by the binary_string argument.
/// bindec() converts a binary number to an integer or, if needed for size reasons, double.
///
/// The binary string to convert.
/// The decimal value of .
[ImplementsFunction("bindec")]
public static object BinToDec(PhpBytes str)
{
if (str == null) return 0;
return ConvertToInt(BaseToDouble(str, 2));
}
[ImplementsFunction("bindec_unicode")]
public static object BinToDecUnicode(string str)
{
if (str == null) return 0;
return ConvertToInt(BaseToDoubleUnicode(str, 2));
}
///
/// Returns a string containing an octal representation of the given number argument.
///
/// Decimal value to convert.
/// Octal string representation of .
[ImplementsFunction("decoct")]
public static PhpBytes DecToOct(int number)
{
return new PhpBytes(System.Convert.ToString(number, 8));
}
[ImplementsFunction("decoct_unicode")]
public static string DecToOctUnicode(int number)
{
return System.Convert.ToString(number, 8);
}
///
/// Returns the decimal equivalent of the octal number represented by the argument.
///
/// The octal string to convert.
/// The decimal representation of .
[ImplementsFunction("octdec")]
public static object OctToDec(PhpBytes str)
{
if (str == null) return 0;
return ConvertToInt(BaseToDouble(str, 8));
}
[ImplementsFunction("octdec_unicode")]
public static object OctToDecUnicode(string str)
{
if (str == null) return 0;
return ConvertToInt(BaseToDoubleUnicode(str, 8));
}
///
/// Returns a string containing a hexadecimal representation of the given number argument.
///
/// Decimal value to convert.
/// Hexadecimal string representation of .
[ImplementsFunction("dechex")]
public static PhpBytes DecToHex(int number)
{
return new PhpBytes(System.Convert.ToString(number, 16));
}
[ImplementsFunction("dechex_unicode")]
public static string DecToHexUnicode(int number)
{
return System.Convert.ToString(number, 16);
}
///
/// Hexadecimal to decimal.
/// Returns the decimal equivalent of the hexadecimal number represented by the hex_string argument. hexdec() converts a hexadecimal string to a decimal number.
/// hexdec() will ignore any non-hexadecimal characters it encounters.
///
/// The hexadecimal string to convert.
/// The decimal representation of .
[ImplementsFunction("hexdec")]
public static object HexToDec(PhpBytes str)
{
if (str == null) return 0;
return ConvertToInt(BaseToDouble(str, 16));
}
[ImplementsFunction("hexdec_unicode")]
public static object HexToDecUnicode(string str)
{
if (str == null) return 0;
return ConvertToInt(BaseToDoubleUnicode(str, 16));
}
public static double BaseToDouble(PhpBytes number, int fromBase)
{
if (number == null)
{
PhpException.ArgumentNull("number");
return 0.0;
}
if (fromBase < 2 || fromBase > 36)
{
PhpException.InvalidArgument("toBase", LibResources.GetString("arg:out_of_bounds"));
return 0.0;
}
double fnum = 0;
for (int i = 0; i < number.Length; i++)
{
int digit = Core.Parsers.Convert.AlphaNumericToDigit((char)number.ReadonlyData[i]);
if (digit < fromBase)
fnum = fnum * fromBase + digit;
}
return fnum;
}
public static double BaseToDoubleUnicode(string number, int fromBase)
{
if (number == null)
{
PhpException.ArgumentNull("number");
return 0.0;
}
if (fromBase < 2 || fromBase > 36)
{
PhpException.InvalidArgument("toBase", LibResources.GetString("arg:out_of_bounds"));
return 0.0;
}
double fnum = 0;
for (int i = 0; i < number.Length; i++)
{
int digit = Core.Parsers.Convert.AlphaNumericToDigit(number[i]);
if (digit < fromBase)
fnum = fnum * fromBase + digit;
}
return fnum;
}
private const string digitsUnicode = "0123456789abcdefghijklmnopqrstuvwxyz";
private static byte[] digits = new byte[] {(byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7',(byte)'8',(byte)'9',
(byte)'a',(byte)'b',(byte)'c',(byte)'d',(byte)'e',(byte)'f',(byte)'g',(byte)'h',(byte)'i',(byte)'j',(byte)'k',(byte)'l',(byte)'m',(byte)'n',
(byte)'o',(byte)'p',(byte)'q',(byte)'r',(byte)'s',(byte)'t',(byte)'u',(byte)'v',(byte)'w',(byte)'x',(byte)'y',(byte)'z' };
public static PhpBytes DoubleToBase(double number, int toBase)
{
if (toBase < 2 || toBase > 36)
{
PhpException.InvalidArgument("toBase", LibResources.GetString("arg:out_of_bounds"));
return PhpBytes.Empty;
}
// Don't try to convert infinity or NaN:
if (Double.IsInfinity(number) || Double.IsNaN(number))
{
PhpException.InvalidArgument("number", LibResources.GetString("arg:out_of_bounds"));
return PhpBytes.Empty;
}
double fvalue = Math.Floor(number); /* floor it just in case */
if (Math.Abs(fvalue) < 1) return new PhpBytes(new byte[]{(byte)'0'});
System.Collections.Generic.List sb = new System.Collections.Generic.List();
while (Math.Abs(fvalue) >= 1)
{
double mod = Fmod(fvalue, toBase);
int i = (int)mod;
byte b = digits[i];
//sb.Append(digits[(int) fmod(fvalue, toBase)]);
sb.Add(b);
fvalue /= toBase;
}
sb.Reverse();
return new PhpBytes(sb.ToArray());
}
public static string DoubleToBaseUnicode(double number, int toBase)
{
if (toBase < 2 || toBase > 36)
{
PhpException.InvalidArgument("toBase", LibResources.GetString("arg:out_of_bounds"));
return String.Empty;
}
// Don't try to convert infinity or NaN:
if (Double.IsInfinity(number) || Double.IsNaN(number))
{
PhpException.InvalidArgument("number", LibResources.GetString("arg:out_of_bounds"));
return String.Empty;
}
double fvalue = Math.Floor(number); /* floor it just in case */
if (Math.Abs(fvalue) < 1) return "0";
StringBuilder sb = new StringBuilder();
while (Math.Abs(fvalue) >= 1)
{
double mod = Fmod(fvalue, toBase);
int i = (int)mod;
char c = digitsUnicode[i];
//sb.Append(digits[(int) fmod(fvalue, toBase)]);
sb.Append(c);
fvalue /= toBase;
}
return PhpStrings.Reverse(sb.ToString());
}
///
/// Convert a number between arbitrary bases.
/// Returns a string containing number represented in base tobase. The base in which number is given is specified in . Both and have to be between 2 and 36, inclusive. Digits in numbers with a base higher than 10 will be represented with the letters a-z, with a meaning 10, b meaning 11 and z meaning 35.
///
/// The number to convert
/// The base is in.
/// The base to convert to
/// converted to base .
[ImplementsFunction("base_convert")]
[return: CastToFalse]
public static string BaseConvert(string number, int fromBase, int toBase)
{
double value;
if (number == null) return "0";
try
{
value = BaseToDoubleUnicode(number, fromBase);
}
catch (ArgumentException)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:invalid_value", "fromBase", fromBase));
return null;
}
try
{
return DoubleToBaseUnicode(value, toBase);
}
catch (ArgumentException)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("arg:invalid_value", "toBase", toBase));
return null;
}
}
#endregion
#region deg2rad, pi, cos, sin, tan, acos, asin, atan, atan2
///
/// Degrees to radians.
///
///
///
[ImplementsFunction("deg2rad"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double DegreesToRadians(double degrees)
{
return degrees / 180 * Math.PI;
}
///
/// Radians to degrees.
///
///
///
[ImplementsFunction("rad2deg")]
[PureFunction]
public static double RadiansToDegrees(double radians)
{
return radians / Math.PI * 180;
}
///
/// Returns an approximation of pi.
///
/// The value of pi as double .
[ImplementsFunction("pi")]
[PureFunction]
public static double PI()
{
return Math.PI;
}
///
/// Returns the arc cosine of arg in radians.
/// acos() is the complementary function of cos(), which means that ==cos(acos( )) for every value of a that is within acos()' range.
///
/// The argument to process.
/// The arc cosine of in radians.
[ImplementsFunction("acos"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Acos(double x)
{
return Math.Acos(x);
}
///
/// Returns the arc sine of arg in radians. asin() is the complementary function of sin(), which means that ==sin(asin( )) for every value of a that is within asin()'s range.
///
/// The argument to process.
/// The arc sine of in radians.
[ImplementsFunction("asin"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Asin(double x)
{
return Math.Asin(x);
}
[ImplementsFunction("atan"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Atan(double x)
{
return Math.Atan(x);
}
[ImplementsFunction("atan2")]
[PureFunction]
public static double Atan2(double y, double x)
{
double rv = Math.Atan(y / x);
if (x < 0)
{
return ((rv > 0) ? -Math.PI : Math.PI) + rv;
}
else return rv;
}
[ImplementsFunction("cos"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Cos(double x)
{
return Math.Cos(x);
}
[ImplementsFunction("sin"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Sin(double x)
{
return Math.Sin(x);
}
[ImplementsFunction("tan"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Tan(double x)
{
return Math.Tan(x);
}
#endregion
#region cosh, sinh, tanh, acosh, asinh, atanh
[ImplementsFunction("cosh")]
[PureFunction]
public static double Cosh(double x)
{
return Math.Cosh(x);
}
[ImplementsFunction("sinh")]
[PureFunction]
public static double Sinh(double x)
{
return Math.Sinh(x);
}
[ImplementsFunction("tanh")]
[PureFunction]
public static double Tanh(double x)
{
return Math.Tanh(x);
}
[ImplementsFunction("acosh")]
[PureFunction]
public static double Acosh(double x)
{
return Math.Log(x + Math.Sqrt(x * x - 1));
}
[ImplementsFunction("asinh")]
[PureFunction]
public static double Asinh(double x)
{
return Math.Log(x + Math.Sqrt(x * x + 1));
}
[ImplementsFunction("atanh")]
[PureFunction]
public static double Atanh(double x)
{
return Math.Log((1 + x) / (1 - x)) / 2;
}
#endregion
#region exp, expm1, log, log10, log1p, pow, sqrt, hypot
///
/// Returns e raised to the power of .
///
[ImplementsFunction("exp"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Exp(double x)
{
return Math.Exp(x);
}
///
/// expm1() returns the equivalent to 'exp(arg) - 1' computed in a way that is accurate even
/// if the value of arg is near zero, a case where 'exp (arg) - 1' would be inaccurate due to
/// subtraction of two numbers that are nearly equal.
///
/// The argument to process
[ImplementsFunction("expm1")]
[PureFunction]
[EditorBrowsable(EditorBrowsableState.Never)]
public static double ExpM1(double x)
{
return Math.Exp(x) - 1.0; // TODO: implement exp(x)-1 for x near to zero
}
///
/// Returns the base-10 logarithm of .
///
[ImplementsFunction("log10")]
[PureFunction]
public static double Log10(double x)
{
return Math.Log10(x);
}
[ImplementsFunction("log"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Log(double x)
{
return Math.Log(x);
}
///
/// If the optional parameter is specified, log() returns log( ) , otherwise log() returns the natural logarithm of .
///
[ImplementsFunction("log"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Log(double x, double logBase)
{
return MathEx.Log(x, logBase);
}
///
/// log1p() returns log(1 + number) computed in a way that is accurate even when the value
/// of number is close to zero. log() might only return log(1) in this case due to lack of precision.
///
/// The argument to process
///
[ImplementsFunction("log1p")]
[PureFunction]
[EditorBrowsable(EditorBrowsableState.Never)]
public static double Log1P(double x)
{
return Math.Log(x + 1.0); // TODO: implement log(x+1) for x near to zero
}
///
/// Returns raised to the power of .
///
[ImplementsFunction("pow")]
[PureFunction]
public static object Power(object @base, object exp)
{
double dbase, dexp;
int ibase, iexp;
long lbase, lexp;
Core.Convert.NumberInfo info_base, info_exp;
info_base = Core.Convert.ObjectToNumber(@base, out ibase, out lbase, out dbase);
info_exp = Core.Convert.ObjectToNumber(exp, out iexp, out lexp, out dexp);
if (((info_base | info_exp) & PHP.Core.Convert.NumberInfo.Double) == 0 && lexp >= 0)
{
// integer base, non-negative integer exp //
long lpower;
double dpower;
if (!Power(lbase, lexp, out lpower, out dpower))
return dpower;
if (lpower >= Int32.MinValue && lpower <= Int32.MaxValue)
return (Int32)lpower;
return lpower;
}
if (dbase < 0)
{
// cannot rount to integer:
if (Math.Ceiling(dexp) > dexp)
return Double.NaN;
double result = Math.Pow(-dbase, dexp);
return (Math.IEEERemainder(Math.Abs(dexp), 2.0) < 1.0) ? result : -result;
}
if (dexp < 0)
return 1 / Math.Pow(dbase, -dexp);
else
return Math.Pow(dbase, dexp);
}
private static bool Power(long x, long y, out long longResult, out double doubleResult)
{
long l1 = 1, l2 = x;
if (y == 0) // anything powered by 0 is 1
{
doubleResult = longResult = 1;
return true;
}
if (x == 0) // 0^(anything except 0) is 0
{
doubleResult = longResult = 0;
return true;
}
try
{
while (y >= 1)
{
if ((y & 1) != 0)
{
l1 *= l2;
y--;
}
else
{
l2 *= l2;
y /= 2;
}
}
}
catch(ArithmeticException)
{
longResult = 0;//ignored
doubleResult = (double)l1 * Math.Pow(l2, y);
return false;
}
// able to do it with longs
doubleResult = longResult = l1;
return true;
}
[ImplementsFunction("sqrt"/*, FunctionImplOptions.Special*/)]
[PureFunction]
public static double Sqrt(double x)
{
return Math.Sqrt(x);
}
[ImplementsFunction("hypot")]
[PureFunction]
public static double Hypotenuse(double x, double y)
{
return Math.Sqrt(x * x + y * y);
}
#endregion
#region ceil, floor, round, abs, fmod, max, min
///
/// Returns the next highest integer value by rounding up if necessary.
///
/// The value to round.
/// rounded up to the next highest integer. The return value of ceil() is still of type double as the value range of double is usually bigger than that of integer.
[ImplementsFunction("ceil")]
[PureFunction]
public static double Ceiling(double x)
{
return Math.Ceiling(x);
}
///
/// Returns the next lowest integer value by rounding down if necessary.
///
/// The numeric value to round.
/// rounded to the next lowest integer. The return value of floor() is still of type double because the value range of double is usually bigger than that of integer.
[ImplementsFunction("floor")]
[PureFunction]
public static double Floor(double x)
{
return Math.Floor(x);
}
///
/// Rounds a float.
///
/// The value to round.
/// The rounded value.
[ImplementsFunction("round")]
[PureFunction]
public static double Round(double x)
{
return RoundInternal(x, RoundMode.HalfUp);
}
///
/// Rounds a float.
///
/// The value to round.
/// The optional number of decimal digits to round to. Can be less than zero to ommit digits at the end. Default is 0 .
/// The rounded value.
[ImplementsFunction("round")]
[PureFunction]
public static double Round(double x, int precision /*= 0*/)
{
return Round(x, precision, RoundMode.HalfUp);
}
///
/// $mode parameter for function.
///
public enum RoundMode : int
{
///
/// When a number is halfway between two others, it is rounded away from zero.
///
[ImplementsConstant("PHP_ROUND_HALF_UP")]
HalfUp = 1,
///
/// When a number is halfway between two others, it is rounded to the zero.
///
[ImplementsConstant("PHP_ROUND_HALF_DOWN")]
HalfDown = 2,
///
/// When a number is halfway between two others, it is rounded toward the nearest even number.
///
[ImplementsConstant("PHP_ROUND_HALF_EVEN")]
HalfEven = 3,
///
/// When a number is halfway between two others, it is rounded toward the nearest odd number.
///
[ImplementsConstant("PHP_ROUND_HALF_ODD")]
HalfOdd = 4,
}
#region Round Helpers
///
/// Returns precise value of 10^ .
///
private static double Power10Value(int power)
{
switch (power)
{
case -15: return .000000000000001;
case -14: return .00000000000001;
case -13: return .0000000000001;
case -12: return .000000000001;
case -11: return .00000000001;
case -10: return .0000000001;
case -9: return .000000001;
case -8: return .00000001;
case -7: return .0000001;
case -6: return .000001;
case -5: return .00001;
case -4: return .0001;
case -3: return .001;
case -2: return .01;
case -1: return .1;
case 0: return 1.0;
case 1: return 10.0;
case 2: return 100.0;
case 3: return 1000.0;
case 4: return 10000.0;
case 5: return 100000.0;
case 6: return 1000000.0;
case 7: return 10000000.0;
case 8: return 100000000.0;
case 9: return 1000000000.0;
case 10: return 10000000000.0;
case 11: return 100000000000.0;
case 12: return 1000000000000.0;
case 13: return 10000000000000.0;
case 14: return 100000000000000.0;
case 15: return 1000000000000000.0;
default: return Math.Pow(10.0, (double)power);
}
}
private static double RoundInternal(double value, RoundMode mode)
{
double tmp_value;
if (value >= 0.0)
{
tmp_value = Math.Floor(value + 0.5);
if (mode != RoundMode.HalfUp)
{
if ((mode == RoundMode.HalfDown && value == (-0.5 + tmp_value)) ||
(mode == RoundMode.HalfEven && value == (0.5 + 2 * Math.Floor(tmp_value * .5))) ||
(mode == RoundMode.HalfOdd && value == (0.5 + 2 * Math.Floor(tmp_value * .5) - 1.0)))
{
tmp_value = tmp_value - 1.0;
}
}
}
else
{
tmp_value = Math.Ceiling(value - 0.5);
if (mode != RoundMode.HalfUp)
{
if ((mode == RoundMode.HalfDown && value == (0.5 + tmp_value)) ||
(mode == RoundMode.HalfEven && value == (-0.5 + 2 * Math.Ceiling(tmp_value * .5))) ||
(mode == RoundMode.HalfOdd && value == (-0.5 + 2 * Math.Ceiling(tmp_value * .5) + 1.0)))
{
tmp_value = tmp_value + 1.0;
}
}
}
return tmp_value;
}
private static readonly double[] _Log10AbsValues = new[]
{
1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23
};
private static int _Log10Abs(double value)
{
value = Math.Abs(value);
if (value < 1e-8 || value > 1e23)
{
return (int)Math.Floor(Math.Log10(value));
}
else
{
var values = _Log10AbsValues;
/* Do a binary search with 5 steps */
var result = 16;
if (value < values[result])
result -= 8;
else
result += 8;
if (value < values[result])
result -= 4;
else
result += 4;
if (value < values[result])
result -= 2;
else
result += 2;
if (value < values[result])
result -= 1;
else
result += 1;
if (value < values[result])
result -= 1;
result -= 8;
//
return result;
}
}
#endregion
///
/// Rounds a float.
///
/// The value to round.
/// The optional number of decimal digits to round to. Can be less than zero to ommit digits at the end. Default is 0 .
/// One of PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, PHP_ROUND_HALF_EVEN, or PHP_ROUND_HALF_ODD. Default is PHP_ROUND_HALF_UP .
/// The rounded value.
[ImplementsFunction("round")]
[PureFunction]
public static double Round(double x, int precision /*= 0*/, RoundMode mode /*= RoundMode.HalfUp*/)
{
if (Double.IsInfinity(x) || Double.IsNaN(x) || x == default(double))
return x;
if (precision == 0)
{
return RoundInternal(x, mode);
}
else
{
if (precision > 23 || precision < -23)
return x;
//
// Following code is taken from math.c to avoid incorrect .NET rounding
//
var precision_places = 14 - _Log10Abs(x);
var f1 = Power10Value(precision);
double tmp_value;
/* If the decimal precision guaranteed by FP arithmetic is higher than
the requested places BUT is small enough to make sure a non-zero value
is returned, pre-round the result to the precision */
if (precision_places > precision && precision_places - precision < 15)
{
var f2 = Power10Value(precision_places);
tmp_value = x * f2;
/* preround the result (tmp_value will always be something * 1e14,
thus never larger than 1e15 here) */
tmp_value = RoundInternal(tmp_value, mode);
/* now correctly move the decimal point */
f2 = Power10Value(Math.Abs(precision - precision_places));
/* because places < precision_places */
tmp_value = tmp_value / f2;
}
else
{
/* adjust the value */
tmp_value = x * f1;
/* This value is beyond our precision, so rounding it is pointless */
if (Math.Abs(tmp_value) >= 1e15)
return x;
}
/* round the temp value */
tmp_value = RoundInternal(tmp_value, mode);
/* see if it makes sense to use simple division to round the value */
//if (precision < 23 && precision > -23)
{
tmp_value = tmp_value / f1;
}
//else
//{
// /* Simple division can't be used since that will cause wrong results.
// Instead, the number is converted to a string and back again using
// strtod(). strtod() will return the nearest possible FP value for
// that string. */
// /* 40 Bytes should be more than enough for this format string. The
// float won't be larger than 1e15 anyway. But just in case, use
// snprintf() and make sure the buffer is zero-terminated */
// char buf[40];
// snprintf(buf, 39, "%15fe%d", tmp_value, -places);
// buf[39] = '\0';
// tmp_value = zend_strtod(buf, NULL);
// /* couldn't convert to string and back */
// if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) {
// tmp_value = value;
// }
//}
return tmp_value;
}
}
///
/// Returns the absolute value of .
///
/// The numeric value to process.
///
[ImplementsFunction("abs")]
[PureFunction]
public static object Abs(object x)
{
double dx;
int ix;
long lx;
switch (Core.Convert.ObjectToNumber(x, out ix, out lx, out dx) & Core.Convert.NumberInfo.TypeMask)
{
case Core.Convert.NumberInfo.Double:
return Math.Abs(dx);
case Core.Convert.NumberInfo.Integer:
if (ix == int.MinValue)
return -lx;
else
return Math.Abs(ix);
case Core.Convert.NumberInfo.LongInteger:
if (lx == long.MinValue)
return -dx;
else
return Math.Abs(lx);
}
return null;
}
///
/// Returns the floating point remainder (modulo) of the division of the arguments.
///
/// The dividend.
/// The divisor.
/// The floating point remainder of / .
[ImplementsFunction("fmod")]
[PureFunction]
public static double Fmod(double x, double y)
{
y = Math.Abs(y);
double rem = Math.IEEERemainder(Math.Abs(x), y);
if (rem < 0) rem += y;
return (x >= 0) ? rem : -rem;
}
///
/// Find highest value.
/// If the first and only parameter is an array, max() returns the highest value in that array. If at least two parameters are provided, max() returns the biggest of these values.
///
/// An array containing the values or values separately.
/// max() returns the numerically highest of the parameter values. If multiple values can be considered of the same size, the one that is listed first will be returned.
/// When max() is given multiple arrays, the longest array is returned. If all the arrays have the same length, max() will use lexicographic ordering to find the return value.
/// When given a string it will be cast as an integer when comparing.
[ImplementsFunction("max")]
[PureFunction]
public static object Max(params object[] numbers)
{
return GetExtreme(numbers, true);
}
///
/// Find lowest value.
/// If the first and only parameter is an array, min() returns the lowest value in that array. If at least two parameters are provided, min() returns the smallest of these values.
///
/// An array containing the values or values separately.
/// min() returns the numerically lowest of the parameter values.
[ImplementsFunction("min")]
[PureFunction]
public static object Min(params object[] numbers)
{
return GetExtreme(numbers, false);
}
internal static object GetExtreme(object[] numbers, bool maximum)
{
if ((numbers.Length == 1) && (numbers[0] is PhpArray))
{
IEnumerable e = (numbers[0] as PhpArray).Values;
Debug.Assert(e != null);
return FindExtreme(e, maximum);
}
return FindExtreme(numbers, maximum);
}
internal static object FindExtreme(IEnumerable array, bool maximum)
{
object ex = null;
int fact = maximum ? 1 : -1;
foreach (object o in array)
{
if (ex == null) ex = o;
else
{
if ((PhpComparer.Default.Compare(o, ex) * fact) > 0) ex = o;
}
}
return ex;
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/MersenneTwister.cs
================================================
using System;
/*
Mersanne Twister random generator C# implementation. Adapted by Tomas Matousek from original
C version by Takuji Nishimura and Makoto Matsumoto (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html).
Experimental version.
*/
/*
License:
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace PHP.Library
{
///
/// Mersanne Twister random generator.
///
public sealed class MersenneTwister
{
// period parameters:
private const int N = 624;
private const int M = 397;
// mag01[x] = x * MATRIX_A for x=0,1
private static readonly uint[] mag01 = { 0, 0x9908b0dfU };
// mti==N+1 means mt[N] is not initialized:
private int mti = N + 1;
// the array for the state vector:
private readonly uint[] mt = new uint[N];
///
/// Create a new instance of using a default seed.
///
public MersenneTwister()
{
Seed(5489U);
}
///
/// Create a new instance of using a specified seed.
///
/// The seed.
public MersenneTwister(uint seed)
{
Seed(seed);
}
///
/// Seeds the generator.
///
/// The seed.
public void Seed(uint seed)
{
mt[0] = seed;
for (int i = 1; i < N; i++)
{
// See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
// In the previous versions, MSBs of the seed affect
// only MSBs of the array mt[].
// 2002/01/09 modified by Makoto Matsumoto
mt[i] = unchecked((uint)((1812433253UL * (mt[i - 1] ^ (mt[i - 1] >> 30)) + (ulong)i)));
}
mti = N;
}
///
/// Generates a random unsigned integer.
///
/// The generated number.
public uint NextUnsigned()
{
// most significant w-r bits:
const uint upper_mask = 0x80000000U;
// least significant r bits:
const uint lower_mask = 0x7fffffffU;
uint result;
unchecked
{
// generate N words at one time:
if (mti >= N)
{
int k;
for (k = 0; k < N - M; k++)
{
result = (mt[k] & upper_mask) | (mt[k + 1] & lower_mask);
mt[k] = mt[k + M] ^ (result >> 1) ^ mag01[result & 1];
}
for (; k < N - 1; k++)
{
result = (mt[k] & upper_mask) | (mt[k + 1] & lower_mask);
mt[k] = mt[k + (M - N)] ^ (result >> 1) ^ mag01[result & 1];
}
result = (mt[N - 1] & upper_mask) | (mt[0] & lower_mask);
mt[N - 1] = mt[M - 1] ^ (result >> 1) ^ mag01[result & 1];
mti = 0;
}
result = mt[mti++];
// tempering:
result ^= (result >> 11);
result ^= (result << 7) & 0x9d2c5680U;
result ^= (result << 15) & 0xefc60000U;
result ^= (result >> 18);
}
return result;
}
///
/// Generates a random signed integer value.
///
/// The generated number.
public int Next()
{
return unchecked((int)(NextUnsigned() >> 1));
}
///
/// Generates a random number from interval [min,max).
///
/// The generated number.
public int Next(int min, int max)
{
if (min > max)
throw new ArgumentOutOfRangeException("min");
unchecked
{
int range = max - min;
if (range < 0)
{
long long_range = (long)max - min;
return (int)((long)(NextDouble() * long_range) + min);
}
else
{
return ((int)(NextDouble() * range)) + min;
}
}
}
///
/// Generates a random double value from interval [0,1).
///
/// The generated number.
double NextDouble()
{
return (double)NextUnsigned() * (1.0 / (double)UInt32.MaxValue);
}
#region Unit Testing
#if DEBUG
public static void Test()
{
int i;
MersenneTwister mt = new MersenneTwister();
Console.WriteLine("1000 outputs of genrand_int32()");
for (i = 0; i < 1000; i++)
{
Console.Write("{0} ", mt.NextUnsigned());
if (i % 5 == 4) Console.WriteLine();
}
Console.ReadLine();
Console.WriteLine("1000 outputs of genrand_real2");
for (i = 0; i < 1000; i++)
{
Console.Write("{0} ", mt.NextDouble());
if (i % 5 == 4) Console.WriteLine();
}
}
#endif
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Misc.cs
================================================
using System;
using System.Diagnostics;
/*
Designed and implemented by Tomas Matousek.
*/
namespace PHP
{
///
/// Summary description for Utils.
///
public class Misc
{
private Misc() { }
///
/// Absolutizes range specified by an offset and a length relatively to a dimension of an array.
///
/// The number of items in array.
///
/// The offset of the range relative to the beginning (if non-negative) or the end of the array (if negative).
/// If the offset underflows or overflows the dimension of array it is trimmed appropriately.
///
///
/// The length of the range if non-negative. Otherwise, its absolute value is the number of items
/// which will not be included in the range from the end of the array. In the latter case
/// the range ends with the | |-th item from the end of the array (counting from zero).
///
public static void AbsolutizeRange(ref int offset, ref int length, int count)
{
// prevents overflows:
if (offset >= count)
{
offset = count;
length = 0;
return;
}
// negative offset => offset is relative to the end of the string:
if (offset < 0)
{
offset += count;
if (offset < 0) offset = 0;
}
Debug.Assert(offset >= 0 && offset < count);
if (length < 0)
{
// there is count-offset items from offset to the end of array,
// the last |length| items is taken away:
length = count - offset + length;
if (length < 0) length = 0;
}
else
if ((long)offset + length > count)
{
// interval ends on the end of array:
length = count - offset;
}
Debug.Assert(length >= 0 && offset + length <= count);
}
}
}
================================================
FILE: Source/ClassLibrary/Miscellaneous.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO:
- sleep() accepts negative values. (5.1.3)
*/
using System;
//using System.Web;
using System.IO;
using System.Linq;
using System.Collections;
using System.ComponentModel;
using System.Threading;
using System.Reflection;
using PHP.Core;
using PHP.Core.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
#if SILVERLIGHT
using PHP.CoreCLR;
#endif
namespace PHP.Library
{
#region Enumerations
///
[Flags]
[EditorBrowsable(EditorBrowsableState.Never)]
public enum PhpInfoSections
{
[ImplementsConstant("INFO_GENERAL")]
General = PhpNetInfo.Sections.General,
[ImplementsConstant("INFO_CREDITS")]
Credits = PhpNetInfo.Sections.Credits,
[ImplementsConstant("INFO_CONFIGURATION")]
Configuration = PhpNetInfo.Sections.Configuration,
[ImplementsConstant("INFO_MODULES")]
Extensions = PhpNetInfo.Sections.Extensions,
[ImplementsConstant("INFO_ENVIRONMENT")]
Environment = PhpNetInfo.Sections.Environment,
[ImplementsConstant("INFO_VARIABLES")]
Variables = PhpNetInfo.Sections.Variables,
[ImplementsConstant("INFO_LICENSE")]
License = PhpNetInfo.Sections.License,
[ImplementsConstant("INFO_ALL")]
All = PhpNetInfo.Sections.All
}
///
[Flags]
[EditorBrowsable(EditorBrowsableState.Never)]
public enum PhpCreditsSections
{
[ImplementsConstant("CREDITS_GROUP")]
Group = 1,
[ImplementsConstant("CREDITS_GENERAL")]
General = 2,
[ImplementsConstant("CREDITS_SAPI")]
SAPI = 4,
[ImplementsConstant("CREDITS_MODULES")]
Modules = 8,
[ImplementsConstant("CREDITS_DOCS")]
Docs = 16,
[ImplementsConstant("CREDITS_FULLPAGE")]
Fullpage = 32,
[ImplementsConstant("CREDITS_QA")]
QA = 64,
[ImplementsConstant("CREDITS_ALL")]
All = -1
}
#endregion
///
/// Miscellaneous functionality.
///
///
public static class Misc
{
#region phpinfo, phpcredits, phpversion, version_compare, zend_version
///
/// Shows all information about Phalanger.
///
/// 1.
[ImplementsFunction("phpinfo")]
public static int PhpInfo()
{
PhpNetInfo.Write(PhpNetInfo.Sections.All, ScriptContext.CurrentContext.Output);
return 1;
}
///
/// Shows specific information about Phalanger.
///
/// A section to show.
/// 1.
[ImplementsFunction("phpinfo")]
public static int PhpInfo(PhpInfoSections sections)
{
PhpNetInfo.Write((PhpNetInfo.Sections)sections, ScriptContext.CurrentContext.Output);
return 1;
}
///
/// Shows all credits of Phalanger.
///
/// True on success, or False on failure.
[ImplementsFunction("phpcredits")]
public static bool PhpCredits()
{
PhpNetInfo.Write(PhpNetInfo.Sections.Credits, ScriptContext.CurrentContext.Output);
return true;
}
///
/// Shows all credits of Phalanger.
///
/// Ignored.
/// /// True on success, or False on failure.
[ImplementsFunction("phpcredits")]
public static bool PhpCredits(PhpCreditsSections sections)
{
PhpNetInfo.Write(PhpNetInfo.Sections.Credits, ScriptContext.CurrentContext.Output);
return true;
}
///
/// Retrieves a string version of PHP language which features is supported by the Phalanger.
///
/// PHP language version.
[ImplementsFunction("phpversion")]
[PureFunction]
public static string PhpVersion()
{
return Core.PhpVersion.Current;
}
///
/// Retrieves a string version of a specified extension.
///
/// Version of the extension or null if it cannot be retrieved.
[ImplementsFunction("phpversion")]
[return: CastToFalse]
public static string PhpVersion(string extensionName)
{
PhpException.FunctionNotSupported();
//return ApplicationContext.Default.GetLoadedLibraries().FirstOrDefault(x => x.Descriptor.AssemblyAttribute ...
return null;
}
///
/// Compares PHP versions.
///
/// The first version.
/// The second version.
/// The result of comparison (-1,0,+1).
[ImplementsFunction("version_compare")]
[PureFunction]
public static int VersionCompare(string ver1, string ver2)
{
return Core.PhpVersion.Compare(ver1, ver2);
}
///
/// Compares PHP versions using a specified operators.
///
/// The first version.
/// The second version.
/// The operator to be used.
/// A boolean result of comparison or a null reference if the operator is invalid.
[ImplementsFunction("version_compare")]
[PureFunction]
public static object VersionCompare(string ver1, string ver2, string op)
{
return Core.PhpVersion.Compare(ver1, ver2, op);
}
///
/// Gets the current version of Zend engine as it is defined in the currently supported PHP.
///
/// The version.
[ImplementsFunction("zend_version")]
[PureFunction]
public static string ZendVersion()
{
return Core.PhpVersion.Zend;
}
#endregion
#region gethostname, php_uname, memory_get_usage, php_sapi_name
///
/// gethostname() gets the standard host name for the local machine.
///
/// Returns a string with the hostname on success, otherwise FALSE is returned.
[ImplementsFunction("gethostname")]
[return: CastToFalse]
public static string GetHostName()
{
string host = null;
#if !SILVERLIGHT
try { host = System.Net.Dns.GetHostName(); }
catch { }
#endif
return host;
}
///
/// Retrieves full version information about OS.
///
/// OS version.
[ImplementsFunction("php_uname")]
public static string PhpUName()
{
//return String.Concat(Environment.OSVersion,", CLR ",Environment.Version);
return PhpUName(null);
}
///
/// Retrieves specific version information about OS.
///
///
///
/// 'a' This is the default. Contains all modes in the sequence "s n r v m".
/// 's' Operating system name, e.g. "Windows NT", "Windows 9x".
/// 'n' Host name, e.g. "www.php-compiler.net".
/// 'r' Release name, e.g. "5.1".
/// 'v' Version information. Varies a lot between operating systems, e.g. "build 2600".
/// 'm' Machine type. eg. "i586".
///
///
/// OS version.
[ImplementsFunction("php_uname")]
public static string PhpUName(string mode)
{
string system, host, release, version, machine;
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT: system = "Windows NT"; break;
case PlatformID.Win32Windows: system = "Windows 9x"; break;
case PlatformID.Win32S: system = "Win32S"; break;
case PlatformID.WinCE: system = "Windows CE"; break;
default: system = "Unix"; break; // TODO
}
#if !SILVERLIGHT
host = System.Net.Dns.GetHostName();
machine = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
if (machine == "x86") machine = "i586"; // TODO
#endif
release = String.Concat(Environment.OSVersion.Version.Major, ".", Environment.OSVersion.Version.Minor);
version = String.Concat("build ", Environment.OSVersion.Version.Build);
if (mode != null && mode != "")
{
switch (mode[0])
{
case 's': return system;
case 'r': return release;
case 'v': return version;
#if !SILVERLIGHT
case 'm': return machine;
case 'n': return host;
#endif
}
}
#if !SILVERLIGHT
return String.Format("{0} {1} {2} {3} {4}", system, host, release, version, machine);
#else
return String.Format("{0} {1} {2}", system, release, version);
#endif
}
#if !SILVERLIGHT
///
/// Retrieves the size of the current process working set in bytes.
/// (In PHP, Returns the amount of memory, in bytes, that's currently being allocated to your PHP script.)
///
/// The size.
[ImplementsFunction("memory_get_usage")]
public static int MemoryGetUsage()
{
return MemoryGetUsage(false);
}
///
/// Retrieves the size of the current process working set in bytes.
///
///
/// "Set this to TRUE to get the real size of memory allocated from system.
/// If not set or FALSE only the memory used by emalloc() is reported."
/// The size.
[ImplementsFunction("memory_get_usage")]
public static int MemoryGetUsage(bool real_usage)
{
//if (real_usage == false)// TODO: real_usage = false
// PhpException.ArgumentValueNotSupported("real_usage");
long ws = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
if (ws > Int32.MaxValue) return Int32.MaxValue;
return (int)ws;
}
///
/// Returns the peak of memory, in bytes, that's been allocated to the PHP script.
///
/// The size.
[ImplementsFunction("memory_get_peak_usage", FunctionImplOptions.NotSupported)]
public static int MemoryGetPeakUsage()
{
return MemoryGetPeakUsage(false);
}
///
/// Returns the peak of memory, in bytes, that's been allocated to the PHP script.
///
///
/// Set this to TRUE to get the real size of memory allocated from system.
/// If not set or FALSE only the memory used by emalloc() is reported.
/// The size.
[ImplementsFunction("memory_get_peak_usage", FunctionImplOptions.NotSupported)]
public static int MemoryGetPeakUsage(bool real_usage)
{
//if (real_usage == false)// TODO: real_usage = false
// PhpException.ArgumentValueNotSupported("real_usage");
long ws = System.Diagnostics.Process.GetCurrentProcess().NonpagedSystemMemorySize64; // can't get current thread's memory
if (ws > Int32.MaxValue) return Int32.MaxValue;
return (int)ws;
}
///
/// Returns the type of interface between web server and Phalanger.
///
/// The "isapi" string if runned under webserver (ASP.NET works via ISAPI) or "cli" otherwise.
[ImplementsFunction("php_sapi_name")]
public static string PhpSapiName()
{
return (System.Web.HttpContext.Current == null) ? "cli" : "isapi";
}
#endif
#endregion
#region getmypid, getlastmod, get_current_user, (UNIX) getmyuid
#if !SILVERLIGHT
///
/// Returns the PID of the current process.
///
/// The PID.
[ImplementsFunction("getmypid")]
public static int GetCurrentProcessId()
{
return System.Diagnostics.Process.GetCurrentProcess().Id;
}
///
/// Gets time of last page modification.
///
/// The UNIX timestamp or -1 on error.
[ImplementsFunction("getlastmod")]
public static int GetLastModification()
{
try
{
PhpSourceFile file = ScriptContext.CurrentContext.MainScriptFile;
if (file == null) return -1;
return DateTimeUtils.UtcToUnixTimeStamp(File.GetLastWriteTime(file.FullPath).ToUniversalTime());
}
catch (System.Exception)
{
return -1;
}
}
///
/// Gets the name of the current user.
///
/// The name of the current user.
[ImplementsFunction("get_current_user")]
public static string GetCurrentUser()
{
return Environment.UserName;
}
#endif
///
/// Not supported.
///
/// Zero.
[ImplementsFunction("getmyuid", FunctionImplOptions.NotSupported)]
public static int GetCurrentUserId()
{
PhpException.FunctionNotSupported();
return 0;
}
#endregion
#region sleep, usleep, (UNIX) time_sleep_until, (UNIX) time_nanosleep
///
/// Sleeps the current thread for a specified amount of time.
///
/// The number of seconds to sleep.
/// Zero on success, or FALSE if negative argument is passed.
[ImplementsFunction("sleep")]
[return: CastToFalse]
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;
}
///
/// Sleeps the current thread for a specified amount of time.
/// No value is returned.
///
/// The number of microseconds to sleep.
[ImplementsFunction("usleep")]
public static void usleep(int microSeconds)
{
if (microSeconds < 0) microSeconds = 0;
Thread.Sleep(microSeconds / 1000);
}
#endregion
#region dl, extension_loaded, get_loaded_extensions, get_extension_funcs
///
/// Not supported.
///
/// Ignored.
/// false
[ImplementsFunction("dl")]
public static bool LoadExtension(string library)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("dl_not_supported"));
return false;
}
///
/// Determines whether a native extension is loaded.
///
/// Internal extension name (e.g. sockets ).
/// true if the is loaded, false otherwise.
[ImplementsFunction("extension_loaded")]
[PureFunction(typeof(Misc), "ExtensionLoaded_Analyze")]
public static bool ExtensionLoaded(string extension)
{
return ScriptContext.CurrentContext.ApplicationContext.GetExtensionImplementor(extension) != null;
}
#region analyzer of extension_loaded
public static bool ExtensionLoaded_Analyze(Analyzer/*!*/analyzer, string extension)
{
Debug.Assert(analyzer != null);
foreach (var loadedExtension in analyzer.Context.ApplicationContext.GetLoadedExtensions())
if (String.Compare(loadedExtension, extension, StringComparison.CurrentCultureIgnoreCase) == 0)
return true;
return false;
}
#endregion
///
/// Returns an array with names of all loaded native extensions.
///
/// The array of extension names.
[ImplementsFunction("get_loaded_extensions")]
public static PhpArray GetLoadedExtensions()
{
PhpArray result = new PhpArray();
foreach (string extension_name in ScriptContext.CurrentContext.ApplicationContext.GetLoadedExtensions())
result.Add(extension_name);
return result;
}
///
/// Returns an array with names of the functions of a native extension.
///
/// Internal extension name (e.g. sockets ).
/// The array of function names or null if the is not loaded.
[ImplementsFunction("get_extension_funcs")]
public static PhpArray GetExtensionFunctions(string extension)
{
if (extension == "zend") // since PHP 5.0
{
PhpException.ArgumentValueNotSupported("extension", extension); // TODO: functions in the module zend (php functions in PhpNetCore ?)
// ...
}
ApplicationContext app_context = ScriptContext.CurrentContext.ApplicationContext;
PhpLibraryDescriptor desc = app_context.GetExtensionImplementor(extension);
if (desc == null) return null;
PhpArray result = new PhpArray();
foreach (KeyValuePair function in app_context.Functions)
{
if (function.Value.DeclaringType.DeclaringModule == desc.Module)
{
result.Add(function.Key);
}
}
return result;
}
///
/// A callback used by method. Adds a function to the resulting array as a key.
///
private static bool AddFunctionToHashtable(MethodInfo info, ImplementsFunctionAttribute ifa, object result)
{
if ((ifa.Options & FunctionImplOptions.NotSupported) == 0)
((Hashtable)result)[ifa.Name] = null;
return true;
}
#endregion
#region get_required_files, get_included_files
///
/// Returns an array of included file paths.
///
/// The array of paths to included files (without duplicates).
[ImplementsFunction("get_required_files")]
public static PhpArray GetRequiredFiles()
{
return GetIncludedFiles();
}
///
/// Returns an array of included file paths.
///
/// The array of paths to included files (without duplicates).
[ImplementsFunction("get_included_files")]
public static PhpArray GetIncludedFiles()
{
PhpArray result = new PhpArray();
foreach (var source_file in ScriptContext.CurrentContext.GetIncludedScripts())
{
result.Add(source_file/*.FullPath.ToString()*/);
}
return result;
}
#endregion
#region NS: zend_logo_guid, php_logo_guid, (UNIX) getmygid, (UNIX) getmyinode
///
/// Not supported.
///
[ImplementsFunction("_mime_content_type", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static string GetMimeContentType(string fileName)
{
PhpException.FunctionNotSupported();
return "text/plain";
}
///
/// Not supported.
///
[ImplementsFunction("zend_logo_guid", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static string ZendLogoGuid()
{
PhpException.FunctionNotSupported();
return null;
}
///
/// Not supported.
///
[ImplementsFunction("php_logo_guid", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static string PhpLogoGuid()
{
PhpException.FunctionNotSupported();
return null;
}
///
/// Not supported.
///
[ImplementsFunction("getmygid", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static int GetMyGid()
{
PhpException.FunctionNotSupported();
return 0;
}
///
/// Not supported.
///
[ImplementsFunction("getmyinode", FunctionImplOptions.NotSupported)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static int GetMyINode()
{
PhpException.FunctionNotSupported();
return 0;
}
#endregion
#region gc_enabled
[ImplementsFunction("gc_enabled")]
public static bool gc_enabled()
{
return true; // status of the circular reference collector
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Network.CLR.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek and Ladislav Prosek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO:
Added: inet_pton,inet_ntop (PHP 5.1.0, UNIX only)
*/
using System;
using PHP.Core;
using System.Net;
using System.Net.Sockets;
using System.ComponentModel;
namespace PHP.Library
{
#region Enumerations
///
/// Types of the DNS record.
///
public enum DnsRecordType
{
/// IPv4 Address Resource
[ImplementsConstant("DNS_A")]
Ip4Address,
/// Mail Exchanger Resource
[ImplementsConstant("DNS_MX")]
Mail,
/// Alias (Canonical Name) Resource
[ImplementsConstant("DNS_CNAME")]
Alias,
/// Authoritative Name Server Resource.
[ImplementsConstant("DNS_NS")]
NameServer,
/// Pointer Resource.
[ImplementsConstant("DNS_PTR")]
Pointer,
/// Host Info Resource.
[ImplementsConstant("DNS_HINFO")]
HostInfo,
/// Start of Authority Resource.
[ImplementsConstant("DNS_SOA")]
StartOfAuthority,
/// Text Resource.
[ImplementsConstant("DNS_TXT")]
Text,
/// Any Resource Record.
[ImplementsConstant("DNS_ANY")]
Any,
/// IPv6 Address Resource
[ImplementsConstant("DNS_AAAA")]
Ip6Address,
/// Iteratively query the name server for each available record type.
[ImplementsConstant("DNS_ALL")]
All
}
#endregion
///
/// Socket functions.
///
///
public static class Sockets
{
#region pfsockopen
[ImplementsFunction("pfsockopen")]
[return: CastToFalse]
public static PhpResource OpenPersistent(string target, int port)
{
int errno;
string errstr;
return Open(target, port, out errno, out errstr, ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout, true);
}
[ImplementsFunction("pfsockopen")]
[return: CastToFalse]
public static PhpResource OpenPersistent(string target, int port, out int errno)
{
string errstr;
return Open(target, port, out errno, out errstr, ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout, true);
}
[ImplementsFunction("pfsockopen")]
[return: CastToFalse]
public static PhpResource OpenPersistent(string target, int port, out int errno, out string errstr)
{
return Open(target, port, out errno, out errstr, ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout, true);
}
[ImplementsFunction("pfsockopen")]
[return: CastToFalse]
public static PhpResource OpenPersistent(string target, int port, out int errno, out string errstr, double timeout)
{
return Open(target, port, out errno, out errstr, timeout, true);
}
#endregion
#region fsockopen
///
/// Not supported.
///
[ImplementsFunction("fsockopen")]
public static PhpResource Open(string target, int port)
{
int errno;
string errstr;
return Open(target, port, out errno, out errstr, ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout, false);
}
///
/// Not supported.
///
[ImplementsFunction("fsockopen")]
public static PhpResource Open(string target, int port, out int errno)
{
string errstr;
return Open(target, port, out errno, out errstr, ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout, false);
}
///
/// Not supported.
///
[ImplementsFunction("fsockopen")]
public static PhpResource Open(string target, int port, out int errno, out string errstr)
{
return Open(target, port, out errno, out errstr, ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout, false);
}
///
/// Not supported.
///
[ImplementsFunction("fsockopen")]
public static PhpResource Open(string target, int port, out int errno, out string errstr, double timeout)
{
return Open(target, port, out errno, out errstr, timeout, false);
}
///
/// Not supported.
///
[ImplementsFunction("fsockopen")]
public static PhpResource Open(string target, int port, out int errno, out string errstr, double timeout, bool persistent)
{
return StreamSocket.Connect(target, port, out errno, out errstr, timeout,
persistent ? StreamSocket.SocketOptions.Persistent : StreamSocket.SocketOptions.None,
StreamContext.Default);
}
#endregion
#region socket_get_status, socket_set_blocking, socket_set_timeout
///
/// Gets status.
///
/// A stream.
/// The array containing status info.
[ImplementsFunction("socket_get_status")]
public static PhpArray GetStatus(PhpResource stream)
{
return PhpStreams.GetMetaData(stream);
}
///
/// Sets blocking mode.
///
/// A stream.
/// A mode.
[ImplementsFunction("socket_set_blocking")]
public static bool SetBlocking(PhpResource stream, int mode)
{
return PhpStreams.SetBlocking(stream, mode);
}
///
/// Sets a timeout.
///
/// A stream.
/// The timeout in seconds.
[ImplementsFunction("socket_set_timeout")]
public static bool SetTimeout(PhpResource stream, int seconds)
{
return PhpStreams.SetTimeout(stream, seconds);
}
///
/// Sets a timeout.
///
/// A stream.
/// Seconds part of the timeout.
/// Microseconds part of the timeout.
[ImplementsFunction("socket_set_timeout")]
public static bool SetTimeout(PhpResource stream, int seconds, int microseconds)
{
return PhpStreams.SetTimeout(stream, seconds, microseconds);
}
#endregion
}
///
/// Functions working with DNS.
///
///
public static class Dns
{
#region NS: dns_check_record, checkdnsrr
///
/// Not supported.
///
[ImplementsFunction("checkdnsrr", FunctionImplOptions.NotSupported)]
public static int CheckRecordRows(string host)
{
return CheckRecords(host, "MX");
}
///
/// Not supported.
///
[ImplementsFunction("checkdnsrr", FunctionImplOptions.NotSupported)]
public static int CheckRecordRows(string host, string type)
{
return CheckRecords(host, type);
}
///
/// Not supported.
///
[ImplementsFunction("dns_check_record", FunctionImplOptions.NotSupported)]
public static int CheckRecords(string host, string type)
{
PhpException.FunctionNotSupported();
return 0;
}
#endregion
#region NS: dns_get_record
///
/// Not supported.
///
[ImplementsFunction("dns_get_record", FunctionImplOptions.NotSupported)]
public static PhpArray GetRecord(string host)
{
return GetRecord(host, DnsRecordType.All);
}
///
/// Not supported.
///
[ImplementsFunction("dns_get_record", FunctionImplOptions.NotSupported)]
public static PhpArray GetRecord(string host, DnsRecordType type)
{
PhpException.FunctionNotSupported();
return null;
}
///
/// Not supported.
///
[ImplementsFunction("dns_get_record", FunctionImplOptions.NotSupported)]
public static PhpArray GetRecord(string host, DnsRecordType type, out PhpArray authNS, out PhpArray additional)
{
PhpException.FunctionNotSupported();
authNS = null;
additional = null;
return null;
}
#endregion
#region gethostbyaddr, gethostbyname, gethostbynamel
///
/// Gets the Internet host name corresponding to a given IP address.
///
/// The IP address.
/// The host name or unmodified on failure.
[ImplementsFunction("gethostbyaddr")]
public static string GetHostByAddress(string ipAddress)
{
try
{
return System.Net.Dns.GetHostEntry(ipAddress).HostName;
}
catch (System.Exception)
{
return ipAddress;
}
}
///
/// Gets the IP address corresponding to a given Internet host name.
///
/// The host name.
/// The IP address or unmodified on failure.
[ImplementsFunction("gethostbyname")]
public static string GetHostByName(string hostName)
{
try
{
IPAddress[] addresses = System.Net.Dns.GetHostEntry(hostName).AddressList;
return (addresses.Length > 0) ? addresses[0].ToString() : hostName;
}
catch (System.Exception)
{
return hostName;
}
}
///
/// Gets a list of IP addresses corresponding to a given Internet host name.
///
/// The host name.
/// The list of IP addresses to which the Internet host specified by resolves.
///
[ImplementsFunction("gethostbynamel")]
public static PhpArray GetHostByNameList(string hostName)
{
try
{
IPAddress[] addresses = System.Net.Dns.GetHostEntry(hostName).AddressList;
PhpArray result = new PhpArray(addresses.Length, 0);
foreach (IPAddress address in addresses)
result.Add(address.ToString());
return result;
}
catch (System.Exception)
{
return null;
}
}
#endregion
#region NS: getmxrr, dns_get_mx
///
/// Not supported.
///
[ImplementsFunction("getmxrr")]
public static bool GetMxRecordRow(string hostName, PhpArray mxHosts)
{
return GetMxRecord(hostName, mxHosts); ;
}
///
/// Not supported.
///
[ImplementsFunction("getmxrr")]
public static bool GetMxRecordRow(string hostName, PhpArray mxHosts, PhpArray weight)
{
return GetMxRecord(hostName, mxHosts, weight);
}
///
/// Not supported.
///
[ImplementsFunction("dns_get_mx", FunctionImplOptions.NotSupported)]
public static bool GetMxRecord(string hostName, PhpArray mxHosts)
{
PhpException.FunctionNotSupported();
return false;
}
///
/// Not supported.
///
[ImplementsFunction("dns_get_mx", FunctionImplOptions.NotSupported)]
public static bool GetMxRecord(string hostName, PhpArray mxHosts, PhpArray weight)
{
PhpException.FunctionNotSupported();
return false;
}
#endregion
#region getprotobyname, getprotobynumber, getservbyname, getservbyport, ip2long, long2ip
///
/// Returns protocol number associated with a given protocol name.
///
/// The protocol name.
/// The protocol number or -1 if is not found.
[ImplementsFunction("getprotobyname")]
[return: CastToFalse]
public static int GetProtocolByName(string name)
{
if (string.IsNullOrEmpty(name)) return -1;
NetworkUtils.ProtoEnt ent = NetworkUtils.GetProtocolByName(name);
if (ent == null) return -1;
return ent.p_proto;
}
///
/// Returns protocol name associated with a given protocol number.
///
/// The protocol number.
/// The protocol name or null if is not found.
[ImplementsFunction("getprotobynumber")]
[return: CastToFalse]
public static string GetProtocolByNumber(int number)
{
NetworkUtils.ProtoEnt ent = NetworkUtils.GetProtocolByNumber(number);
if (ent == null) return null;
return ent.p_name;
}
///
/// Returns port number associated with a given Internet service and protocol.
///
/// The service.
/// The protocol.
/// The port number or -1 if not found.
[ImplementsFunction("getservbyname")]
[return: CastToFalse]
public static int GetServiceByName(string service, string protocol)
{
if (service == null) return -1;
NetworkUtils.ServEnt ent = NetworkUtils.GetServiceByName(service, protocol);
if (ent == null) return -1;
return IPAddress.NetworkToHostOrder(ent.s_port);
}
///
/// Returns an Internet service that corresponds to a given port and protocol.
///
/// The port.
/// The protocol.
/// The service name or null if not found.
[ImplementsFunction("getservbyport")]
[return: CastToFalse]
public static string GetServiceByPort(int port, string protocol)
{
NetworkUtils.ServEnt ent = NetworkUtils.GetServiceByPort(IPAddress.HostToNetworkOrder(port), protocol);
if (ent == null) return null;
return ent.s_proto;
}
///
/// Converts a string containing an (IPv4) Internet Protocol dotted address into a proper address.
///
/// The string representation of the address.
/// The integer representation of the address.
[ImplementsFunction("ip2long")]
[return: CastToFalse]
public static int IPToInteger(string ipAddress)
{
if (string.IsNullOrEmpty(ipAddress)) return -1;
IPAddress addr;
try
{
addr = IPAddress.Parse(ipAddress);
}
catch (FormatException)
{
return -1;
}
if (addr.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) return -1;
return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(addr.GetAddressBytes(), 0));
}
///
/// Converts an (IPv4) Internet network address into a string in Internet standard dotted format.
///
/// The integer representation of the address.
/// The string representation of the address.
[ImplementsFunction("long2ip")]
public static string IntegerToIP(int properAddress)
{
IPAddress addr;
unchecked
{
addr = new IPAddress((long)(uint)IPAddress.HostToNetworkOrder(properAddress));
}
return addr.ToString();
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/Objects.cs
================================================
/*
Copyright (c) 2004-2006 Ladislav Prosek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using PHP.Core;
using PHP.Core.Reflection;
using System.Diagnostics;
namespace PHP.Library
{
///
/// Contains object-related class library functions.
///
///
public static class PhpObjects
{
///
/// Calls the method referred by from the user defined
/// object with parameters .
///
/// DTypeDesc of the caller's class context. Can be UnknownTypeDesc.
/// The name of the method.
/// An instance to invoke the method on or a class name.
/// Parameters to invoke the method with.
/// The method's return value (always dereferenced).
internal static object CallUserMethodInternal(DTypeDesc caller, string methodName, object classNameOrObject, ICollection args)
{
PhpException.Throw(PhpError.Notice, LibResources.GetString("call_user_method_deprecated"));
object ret_val = false;
DObject obj;
string class_name;
ScriptContext context = ScriptContext.CurrentContext;
//DTypeDesc classContext = PhpStackTrace.GetClassContext(); // TODO: GetClassContext only if needed by context.ResolveType
if (caller != null && caller.IsUnknown) caller = PhpStackTrace.GetClassContext();
if ((obj = classNameOrObject as DObject) != null)
{
// push arguments on stack
context.Stack.AddFrame(args);
ret_val = obj.InvokeMethod(methodName, caller, context);
}
else if ((class_name = PhpVariable.AsString(classNameOrObject)) != null)
{
// push arguments on stack
context.Stack.AddFrame(args);
ResolveTypeFlags flags = ResolveTypeFlags.UseAutoload | ResolveTypeFlags.ThrowErrors;
DTypeDesc type = PHP.Core.Convert.ObjectToTypeDesc(class_name, flags, caller, context, null, null);
ret_val = Operators.InvokeStaticMethod(type, methodName, null, caller, context);
}
else
{
PhpException.InvalidArgument("classNameOrObject", LibResources.GetString("arg:not_object_or_class_name"));
}
return PhpVariable.Dereference(ret_val);
}
///
/// Calls the method referred by from the user defined
/// object with parameters .
///
/// DTypeDesc of the caller's class context. Can be UnknownTypeDesc.
/// The name of the method.
/// An instance to invoke the method on or a class name.
/// Parameters to invoke the method with.
/// The method's return value (always dereferenced).
[ImplementsFunction("call_user_method", FunctionImplOptions.NeedsClassContext)]
public static object CallUserMethod(DTypeDesc caller, string methodName, object classNameOrObject, params object[] args)
{
return CallUserMethodInternal(caller, methodName, classNameOrObject, args);
}
///
/// Calls the method referred by from the user defined
/// object with parameters .
///
/// DTypeDesc of the caller's class context. Can be UnknownTypeDesc.
/// The name of the method.
/// An instance to invoke the method on or a class name.
/// Parameters to invoke the method with.
/// The method's return value.
[ImplementsFunction("call_user_method_array", FunctionImplOptions.NeedsClassContext)]
public static object CallUserMethodArray(DTypeDesc caller, string methodName, object classNameOrObject, PhpArray args)
{
return CallUserMethodInternal(caller, methodName, classNameOrObject, ((IDictionary)args).Values);
}
///
/// Returns a of default fields of a class.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The name of the class.
/// Whether to list vars in PHP order (child vars then parent vars) or logical (parent vars then child).
/// Specifies whether static variables should be listed as well
/// Array of 's default fields.
///
///
/// The resulting array elements are in the form of varname => value , where value
/// is the default value of the field.
///
///
/// This method returns fields declared in and all its parent classes.
///
///
[ImplementsFunction("get_class_vars", FunctionImplOptions.NeedsClassContext)]
[return: PhpDeepCopy]
[return: CastToFalse]
public static PhpArray GetClassVars(DTypeDesc caller, string className, bool parentsFirst, bool includeStatic)
{
ScriptContext script_context = ScriptContext.CurrentContext;
DTypeDesc type = script_context.ResolveType(className);
if (type == null) return null;
// determine the calling type
//DTypeDesc caller = PhpStackTrace.GetClassContext();
if (caller != null && caller.IsUnknown) caller = PhpStackTrace.GetClassContext();
PhpArray result = new PhpArray();
// add instance properties
bool have_instance_props = false;
if (!type.IsAbstract)
{
// the class has to be instantiated in order to discover default instance property values
// (the constructor will initialize default properties, user defined constructor will not be called)
DObject obj = type.New(script_context) as DObject;
if (obj == null) return null;
// populate the resulting array taking into account current caller
IDictionaryEnumerator enumerator = obj.GetEnumerator(caller);
while (enumerator.MoveNext())
{
result.Add(enumerator.Key, enumerator.Value);
}
have_instance_props = true;
}
// add static fields (static and instance fields if the type is abstract)
if (includeStatic)
{
foreach (KeyValuePair pair in type.EnumerateProperties(caller))
{
if (pair.Value.IsStatic)
{
result.Add(pair.Key.ToString(), pair.Value.Get(null));
}
else if (!have_instance_props)
{
result.Add(pair.Key.ToString(), null);
}
}
}
result.InplaceCopyOnReturn = true;
return result;
}
[ImplementsFunction("get_class_vars", FunctionImplOptions.NeedsClassContext)]
[return: PhpDeepCopy]
[return: CastToFalse]
public static PhpArray GetClassVars(DTypeDesc caller, string className)
{
return GetClassVars(caller, className, false, true);
}
///
/// Returns a of defined fields for the specified object .
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object whose fields are requested.
/// Array of 's fields (name => value pairs).
///
/// This method returns default fields (those declared in the class using "var") declared in the
/// class and all its parent classes) as well as fields added at runtime.
///
[ImplementsFunction("get_object_vars", FunctionImplOptions.NeedsClassContext)]
//[return: PhpDeepCopy]
public static PhpArray GetObjectVars(DTypeDesc caller, DObject obj)
{
return GetObjectVars(caller,obj,false);
}
///
/// Returns a of defined fields for the specified object .
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object whose fields are requested.
/// References will be omited from the result
/// Array of 's fields (name => value pairs).
///
/// This method returns default fields (those declared in the class using "var") declared in the
/// class and all its parent classes) as well as fields added at runtime.
///
[ImplementsFunction("get_object_vars", FunctionImplOptions.NeedsClassContext)]
//[return: PhpDeepCopy] // already deep copied
public static PhpArray GetObjectVars(DTypeDesc caller, DObject obj, bool IgnoreReferences)
{
if (obj == null) return null;
Converter copy = null;
///////////////////////////////////////
// This is hot fix for a reference counting problem when reference aren't released in same way as in PHP.
// Hence, we need to perform deep copy ignoring references
if (IgnoreReferences)
copy = (value) =>
{
PhpReference refValue = value as PhpReference;
if (refValue != null)
return copy(refValue.Value);
PhpArray array = value as PhpArray;
if (array != null)
{
PhpArray dst = new PhpArray(array.IntegerCount, array.StringCount);
foreach (KeyValuePair entry in array)
{
// checks whether a value is a reference pointing to the instance itself:
refValue = entry.Value as PhpReference;
if (refValue != null && refValue.Value == array)
{
// copies the value so that it will self-reference the new instance (not the old one):
dst.Add(entry.Key, new PhpReference(dst));
}
else
{
dst.Add(entry.Key, copy(entry.Value));
}
}
return dst;
}
return value;
};
else
copy = (value) => { return PhpVariable.DeepCopy(value); }; // perform InplaceDeepCopy() here to save one more iteration through the array
///////////////////////////////////////
PhpArray result = new PhpArray(0, obj.Count);
var foreachEnumerator = obj.GetEnumerator((caller != null && caller.IsUnknown) ? PhpStackTrace.GetClassContext() : caller);
while (foreachEnumerator.MoveNext())
//foreach (DictionaryEntry pair in obj)
{
DictionaryEntry pair = (DictionaryEntry)foreachEnumerator.Current;
result.Add((string)pair.Key, copy(pair.Value));
}
//result.InplaceCopyOnReturn = true; // already deep copied
return result;
}
///
/// Verifies whether the method given by has been defined for the given
/// object .
///
/// Current class context.
/// The object to test.
/// The name of the method.
/// True if the method given by has been defined for the given
/// object , false otherwise.
[ImplementsFunction("method_exists", FunctionImplOptions.NeedsClassContext)]
public static bool MethodExists(DTypeDesc caller, object obj, string methodName)
{
if (obj == null || string.IsNullOrEmpty(methodName)) return false;
DTypeDesc dtype;
DObject dobj;
string str;
if ((dobj = (obj as DObject)) != null)
{
dtype = dobj.TypeDesc;
if (dtype == null)
{
Debug.Fail("DObject.TypeDesc should not be null");
return false;
}
}
else if ((str = PhpVariable.AsString(obj)) != null)
{
ScriptContext script_context = ScriptContext.CurrentContext;
dtype = script_context.ResolveType(str, null, caller, null, ResolveTypeFlags.UseAutoload);
if (dtype == null)
return false;
}
else
{
// other type names are not handled
return false;
}
DRoutineDesc method;
return (dtype.GetMethod(new Name(methodName), dtype, out method) != GetMemberResult.NotFound);
}
///
/// Converts a class name or class instance to object.
///
/// Current .
/// Current .
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The class name or class instance ( ).
/// True iff the __autoload magic function should be used.
/// The type desc that corresponds to or null
/// if the type could not be found or is neither a string
/// nor .
internal static DTypeDesc ClassNameOrObjectToType(ScriptContext/*!*/ scriptContext, NamingContext namingContext,
DTypeDesc caller, object classNameOrObject, bool useAutoload)
{
string class_name = PhpVariable.AsString(classNameOrObject);
if (class_name != null)
{
// lookup the Type
return scriptContext.ResolveType(class_name, namingContext, caller, null,
(useAutoload ? ResolveTypeFlags.UseAutoload : ResolveTypeFlags.None));
}
else
{
DObject obj = classNameOrObject as DObject;
if (obj != null) return obj.TypeDesc;
}
return null;
}
///
/// Verifies whether the property given by has been defined for the given
/// object object or class.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object ( ) or the name of a class
/// ( ).
/// The name of the property.
/// True if the property given by has been defined for the
/// given class or object and is accessible from current class context.
///
/// This function has different semantics than , which ignores visibility.
/// If an object is passed in the first parameter, the property is searched among runtime fields as well.
///
[ImplementsFunction("property_exists", FunctionImplOptions.NeedsClassContext)]
public static bool PropertyExists(DTypeDesc caller, object classNameOrObject, string propertyName)
{
ScriptContext context = ScriptContext.CurrentContext;
DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, true);
if (type == null) return false;
// determine the calling class context
//DTypeDesc caller = PhpStackTrace.GetClassContext();
if (caller != null && caller.IsUnknown) caller = PhpStackTrace.GetClassContext();
DPropertyDesc property;
if (type.GetProperty(new VariableName(propertyName), caller, out property) == GetMemberResult.OK)
{
// CT property was found
return true;
}
else
{
// search RT fields, if possible
DObject obj = classNameOrObject as DObject;
return (obj != null && obj.RuntimeFields != null && obj.RuntimeFields.ContainsKey(propertyName));
}
}
///
/// Returns all methods defined in the specified class or class of specified object, and its predecessors.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object ( ) or the name of a class
/// ( ).
/// Array of all methods defined in .
[ImplementsFunction("get_class_methods", FunctionImplOptions.NeedsClassContext)]
public static PhpArray GetClassMethods(DTypeDesc caller, object classNameOrObject)
{
ScriptContext context = ScriptContext.CurrentContext;
DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, true);
if (type == null) return null;
// determine the calling type
//DTypeDesc caller = PhpStackTrace.GetClassContext();
if (caller != null && caller.IsUnknown) caller = PhpStackTrace.GetClassContext();
PhpArray result = new PhpArray();
foreach (KeyValuePair pair in type.EnumerateMethods(caller))
{
result.Add(pair.Key.ToString());
}
return result;
}
///
/// Returns a with names of all defined classes (system and user).
///
/// of class names.
[ImplementsFunction("get_declared_classes")]
public static PhpArray GetDeclaredClasses()
{
return (PhpArray)ScriptContext.CurrentContext.GetDeclaredClasses(new PhpArray());
}
///
/// Returns a with names of all defined interfaces (system and user).
///
/// of interface names.
[ImplementsFunction("get_declared_interfaces")]
public static PhpArray GetDeclaredInterfaces()
{
return (PhpArray)ScriptContext.CurrentContext.GetDeclaredInterfaces(new PhpArray());
}
///
/// Tests whether the class given by is derived from a class given
/// by .
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object ( ) or the name of a class
/// ( ).
/// The name of the (base) class.
/// true if implements or extends ,
/// false otherwise.
[ImplementsFunction("is_subclass_of", FunctionImplOptions.NeedsClassContext)]
public static bool IsSubclassOf(DTypeDesc caller, object classNameOrObject, string baseClassName)
{
ScriptContext context = ScriptContext.CurrentContext;
DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, true);
if (type == null) return false;
// look for the class, do not use autoload (since PHP 5.1):
DTypeDesc base_type = context.ResolveType(baseClassName, null, caller, null, ResolveTypeFlags.None); // do not call autoload [workitem:26664]
if (base_type == null) return false;
return (base_type.RealType.IsAssignableFrom(type.RealType) && base_type != type);
}
///
/// Tests whether a given class is defined.
///
/// The caller class context to resolve visibility.
/// The name of the class.
/// true if the class given by has been defined,
/// false otherwise.
[ImplementsFunction("class_exists", FunctionImplOptions.NeedsClassContext)]
[PureFunction(typeof(PhpObjects), "ClassExists_Analyze_1")]
public static bool ClassExists(DTypeDesc caller, string className)
{
return ClassExists(caller, className, true);
}
///
/// Tests whether a given class is defined.
///
/// The caller class context to resolve visibility.
/// The name of the class.
/// Whether to attempt to call __autoload .
/// true if the class given by has been defined,
/// false otherwise.
[ImplementsFunction("class_exists", FunctionImplOptions.NeedsClassContext)]
[PureFunction(typeof(PhpObjects), "ClassExists_Analyze_2")]
public static bool ClassExists(DTypeDesc caller, string className, bool autoload)
{
DTypeDesc type = ScriptContext.CurrentContext.ResolveType(className, null, caller, null, autoload ? ResolveTypeFlags.UseAutoload : ResolveTypeFlags.None);
return type != null;
}
#region analyzer of class_exists
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo ClassExists_Analyze_2(Analyzer analyzer, string name, bool autoload)
{
// ignore autoload at the compile time
return ClassExists_Analyze_1(analyzer, name);
}
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo ClassExists_Analyze_1(Analyzer analyzer, string name)
{
QualifiedName? alias;
DType type = analyzer.SourceUnit.ResolveTypeName(
new QualifiedName(new Name(name)),
analyzer.CurrentScope,
out alias,
null,
PHP.Core.Text.Span.Invalid,
false);
if (type == null || type.IsUnknown)
return null; // type is not known at the compilation time. However it can be defined at the runtime (dynamic include, script library, etc).
return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo()
{
value = true // type is definitely known the the compilation time
};
}
#endregion
///
/// Tests whether a given interface is defined.
///
/// The class context of the caller.
/// The name of the interface.
/// true if the interface given by has been defined,
/// false otherwise.
[ImplementsFunction("interface_exists", FunctionImplOptions.NeedsClassContext)]
public static bool InterfaceExists(DTypeDesc caller, string ifaceName)
{
return InterfaceExists(caller, ifaceName, true);
}
///
/// Tests whether a given interface is defined.
///
/// The class context of the caller.
/// The name of the interface.
/// Whether to attempt to call __autoload .
/// true if the interface given by has been defined,
/// false otherwise.
[ImplementsFunction("interface_exists", FunctionImplOptions.NeedsClassContext)]
public static bool InterfaceExists(DTypeDesc caller, string ifaceName, bool autoload)
{
DTypeDesc type = ScriptContext.CurrentContext.ResolveType(ifaceName, null, caller, null, autoload ? ResolveTypeFlags.UseAutoload : ResolveTypeFlags.None);
return type != null && type.IsInterface;
}
///
/// Returns the name of the current class.
///
/// Current class context.
/// Current class name.
[ImplementsFunction("get_class", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
public static string GetClass(DTypeDesc caller)
{
if (caller == null || caller.IsUnknown)
return null;
return caller.MakeFullName();
}
///
/// Returns the name of the class of which the object is an instance.
///
/// Current class context.
/// The object whose class is requested.
/// 's class name or current class name if is
/// null .
[ImplementsFunction("get_class", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
public static string GetClass(DTypeDesc caller, object var)
{
if (var == null)
return GetClass(caller);
DObject obj = var as DObject;
return (obj != null) ? obj.TypeName : null;
}
[ImplementsFunction("get_called_class", FunctionImplOptions.NeedsLateStaticBind)]
[return: CastToFalse]
public static string GetCalledClass(DTypeDesc caller)
{
if (caller == null || caller.IsUnknown)
return null;
return caller.MakeFullName();
}
///
/// Gets the name of the class from which class given by
/// inherits.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object ( ) or the name of a class
/// ( ).
/// If is an , returns the name
/// of the parent class of the class of which is an instance.
/// If is a , returns the name of the parent
/// class of the class with that name.
///
/// If the class given by has no parent in PHP class hierarchy,
/// this method returns null .
///
[ImplementsFunction("get_parent_class", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
[PureFunction(typeof(PhpObjects), "GetParentClass_Analyze")]
public static string GetParentClass(DTypeDesc caller, object classNameOrObject)
{
ScriptContext context = ScriptContext.CurrentContext;
DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, true);
if (type == null || type.IsInterface) return null;
DTypeDesc parent_type = type.Base;
return (parent_type == null ? null : parent_type.MakeFullName());
}
#region analyzer of get_parent_class
[return: CastToFalse]
public static PHP.Core.Compiler.AST.FunctionCallEvaluateInfo GetParentClass_Analyze(Analyzer analyzer, string name)
{
QualifiedName? alias;
DType type = analyzer.SourceUnit.ResolveTypeName(
new QualifiedName(new Name(name)),
analyzer.CurrentScope,
out alias,
null,
PHP.Core.Text.Span.Invalid,
false);
if (type == null || type.IsUnknown)
return null; // type is not known at the compilation time. However it can be defined at the runtime (dynamic include, script library, etc).
// type is definitely known the the compilation time
var parent_type = type.Base;
return new PHP.Core.Compiler.AST.FunctionCallEvaluateInfo()
{
value = (parent_type == null ? null : parent_type.FullName)
};
}
#endregion
///
/// Tests whether 's class is derived from a class given by .
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The object to test.
/// The name of the class.
/// true if the object belongs to class or
/// a class which is a subclass of , false otherwise.
[ImplementsFunction("is_a", FunctionImplOptions.NeedsClassContext)]
public static bool IsA(DTypeDesc caller, object obj, string className)
{
if (obj == null || !(obj is DObject)) return false;
DObject dobj = (DObject)obj;
DTypeDesc type = ScriptContext.CurrentContext.ResolveType(className, null, caller, null, ResolveTypeFlags.None); // do not call autoload [workitem:26664]
if (type == null) return false;
return type.IsAssignableFrom(dobj.TypeDesc);
}
///
/// Returns a with keys and values being names of a given class's
/// base classes.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The or class name to get base classes of.
/// True if the magic __autoload function should be used.
/// The with base class names.
[ImplementsFunction("class_parents", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
public static PhpArray GetClassParents(DTypeDesc caller, object classNameOrObject, bool useAutoload)
{
ScriptContext context = ScriptContext.CurrentContext;
DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, useAutoload);
if (type == null || type.IsInterface) return null;
PhpArray result = new PhpArray();
while ((type = type.Base) != null)
{
string class_name = type.MakeFullName();
result.Add(class_name, class_name);
}
return result;
}
///
/// Returns a with keys and values being names of a given class's
/// base classes.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The or class name to get base classes of.
/// The with base class names.
[ImplementsFunction("class_parents", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
public static PhpArray GetClassParents(DTypeDesc caller, object classNameOrObject)
{
return GetClassParents(caller, classNameOrObject, true);
}
///
/// Returns a with keys and values being names of interfaces implemented by a given
/// class.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The or class name to get implemented interfaces of.
/// True if the magic __autoload function should be used.
///
/// The with interface names.
[ImplementsFunction("class_implements", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
public static PhpArray GetClassInterfaces(DTypeDesc caller, object classNameOrObject, bool useAutoload)
{
ScriptContext context = ScriptContext.CurrentContext;
DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, useAutoload);
if (type == null) return null;
PhpArray result = new PhpArray();
DTypeDesc[] interfaces = type.GetImplementedInterfaces();
for (int i = 0; i < interfaces.Length; i++)
{
string iface_name = interfaces[i].MakeFullName();
result[iface_name] = iface_name;
}
return result;
}
///
/// Returns a with keys and values being names of interfaces implemented by a given
/// class.
///
/// The caller of the method to resolve visible properties properly. Can be UnknownTypeDesc.
/// The or class name to get implemented interfaces of.
///
/// The with interface names.
[ImplementsFunction("class_implements", FunctionImplOptions.NeedsClassContext)]
[return: CastToFalse]
public static PhpArray GetClassInterfaces(DTypeDesc caller, object classNameOrObject)
{
return GetClassInterfaces(caller, classNameOrObject, true);
}
}
}
================================================
FILE: Source/ClassLibrary/Output.CLR.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Web;
using PHP.Core;
namespace PHP.Library
{
///
/// PHP output control functions implementation.
///
///
[ImplementsExtension(LibraryDescriptor.ExtCore)]
public static class Output
{
[Flags]
public enum _ChunkPosition
{
[ImplementsConstant("PHP_OUTPUT_HANDLER_START")]
First = BufferedOutput.ChunkPosition.First,
[ImplementsConstant("PHP_OUTPUT_HANDLER_CONT")]
Middle = BufferedOutput.ChunkPosition.Middle,
[ImplementsConstant("PHP_OUTPUT_HANDLER_END")]
Last = BufferedOutput.ChunkPosition.Last
}
#region fprintf, vprintf
///
/// Generates output according to the specified formatting string.
///
/// The formatting string. See also the sprintf function ( ).
/// Variables to format.
/// Returns the length of the outputted string.
[ImplementsFunction("printf")]
public static int PrintFormatted(string format, params object[] args)
{
string formattedString = PhpStrings.FormatInternal(format, args);
ScriptContext.CurrentContext.Output.Write(formattedString);
return formattedString.Length;
}
///
/// Generates output according to the specified formatting string.
///
/// The formatting string.
/// Array of variables to format.
/// Returns the length of the outputted string.
[ImplementsFunction("vprintf")]
public static int PrintFormatted(string format, PhpArray args)
{
string formattedString = PhpStrings.Format(format, args);
ScriptContext.CurrentContext.Output.Write(formattedString);
return formattedString.Length;
}
#endregion
#region ob_start
///
/// Increases the level of buffering and enables output buffering if disabled.
///
/// Always true.
[ImplementsFunction("ob_start")]
public static bool Start()
{
return Start(null, 0, true);
}
///
/// Increases the level of buffering, enables output buffering if disabled and assignes the filtering callback
/// to the new level of buffering.
///
/// The filtering callback. Ignores invalid callbacks.
/// Whether the filter is empty or a valid callback.
[ImplementsFunction("ob_start")]
public static bool Start(PhpCallback filter)
{
return Start(filter, 0, true);
}
///
/// Increases the level of buffering, enables output buffering if disabled and assignes the filtering callback
/// to the new level of buffering.
///
/// The filtering callback. Ignores invalid callbacks.
/// Not supported.
/// Whether the filter is empty or a valid callback.
[ImplementsFunction("ob_start")]
public static bool Start(PhpCallback filter, int chunkSize)
{
return Start(filter, chunkSize, true);
}
///
/// Increases the level of buffering, enables output buffering if disabled and assignes the filtering callback
/// to the new level of buffering.
///
/// The filtering callback. Ignores invalid callbacks.
/// Not supported.
/// Not supported.
/// Whether the filter is valid callback.
[ImplementsFunction("ob_start")]
public static bool Start(PhpCallback filter, int chunkSize, bool erase)
{
if (chunkSize != 0)
PhpException.ArgumentValueNotSupported("chunkSize", "!= 0");
if (!erase)
PhpException.ArgumentValueNotSupported("erase", erase);
ScriptContext context = ScriptContext.CurrentContext;
context.BufferedOutput.IncreaseLevel();
bool result = true;
// skips filter setting if filter is not specified or valid:
if (filter != null && (result = filter.Bind()))
context.BufferedOutput.SetFilter(filter);
context.IsOutputBuffered = true;
return result;
}
#endregion
#region ob_clean, ob_end_clean, ob_end_flush
///
/// Discards the contents of the current level of buffering.
/// No value is returned.
///
[ImplementsFunction("ob_clean")]
public static void Clean()
{
ScriptContext.CurrentContext.BufferedOutput.Clean();
}
///
/// Discards the contents of the current level of buffering and decreases the level.
///
/// Whether the content was discarded and the level was decreased.
[ImplementsFunction("ob_end_clean")]
public static bool EndAndClean()
{
return EndInternal(ScriptContext.CurrentContext, false);
}
///
/// Flushes the contents of the current level of buffering and decreases the level.
///
/// Whether the content was discarded and the level was decreased.
[ImplementsFunction("ob_end_flush")]
public static bool EndAndFlush()
{
return EndInternal(ScriptContext.CurrentContext, true);
}
///
/// Decreases the level of buffering and discards or flushes data on the current level of buffering.
///
/// Current script context.
/// Whether to flush data.
/// Whether the content was discarded and the level was decreased.
private static bool EndInternal(ScriptContext/*!*/ context, bool flush)
{
BufferedOutput buf = context.BufferedOutput;
if (buf.Level == 0)
{
PhpException.Throw(PhpError.Notice, CoreResources.GetString("output_buffering_disabled"));
return false;
}
if (buf.DecreaseLevel(flush) < 0)
context.IsOutputBuffered = false;
return true;
}
#endregion
#region ob_get_clean, ob_get_contents, ob_get_flush, ob_get_level, ob_get_length, ob_get_status
///
/// Gets the contents of the current buffer and cleans it.
///
/// The content of type or .
[ImplementsFunction("ob_get_clean")]
[return: CastToFalse]
public static object GetAndClean()
{
ScriptContext context = ScriptContext.CurrentContext;
BufferedOutput bo = context.BufferedOutput;
object result = bo.GetContent();
bo.Clean();
EndInternal(context, true);
return result;
}
///
/// Gets the content of the current buffer.
///
/// The content of type or .
[ImplementsFunction("ob_get_contents")]
[return: CastToFalse]
public static object GetContents()
{
return ScriptContext.CurrentContext.BufferedOutput.GetContent();
}
///
/// Gets the content of the current buffer and decreases the level of buffering.
///
/// The content of the buffer.
[ImplementsFunction("ob_get_flush")]
public static object GetAndFlush()
{
ScriptContext context = ScriptContext.CurrentContext;
BufferedOutput bo = context.BufferedOutput;
object result = bo.GetContent();
EndInternal(context, true);
return result;
}
///
/// Retrieves the level of buffering.
///
/// The level of buffering.
[ImplementsFunction("ob_get_level")]
public static int GetLevel()
{
return ScriptContext.CurrentContext.BufferedOutput.Level;
}
///
/// Retrieves the length of the output buffer.
///
/// The length of the contents in the output buffer or false , if output buffering isn't active.
[ImplementsFunction("ob_get_length")]
[return: CastToFalse]
public static int GetLength()
{
return ScriptContext.CurrentContext.BufferedOutput.Length;
}
///
/// Get the status of the current or all output buffers.
///
/// The array of name => value pairs containing information.
[ImplementsFunction("ob_get_status")]
public static PhpArray GetStatus()
{
return GetStatus(false);
}
///
/// Get the status of the current or all output buffers.
///
/// Whether to retrieve extended information about all levels of buffering or about the current one.
/// The array of name => value pairs containing information.
[ImplementsFunction("ob_get_status")]
public static PhpArray GetStatus(bool full)
{
BufferedOutput bo = ScriptContext.CurrentContext.BufferedOutput;
PhpArray result;
if (full)
{
result = new PhpArray(bo.Level, 0);
for (int i = 1; i <= bo.Level; i++)
result.Add(i, GetLevelStatus(bo, i));
}
else if (bo.Level > 0)
{
result = GetLevelStatus(bo, bo.Level);
result.Add("level", bo.Level);
}
else
result = new PhpArray(0, 0);
return result;
}
private static PhpArray/*!*/ GetLevelStatus(BufferedOutput/*!*/ bo, int index)
{
PhpArray result = new PhpArray(0, 3);
PhpCallback filter;
int size;
bo.GetLevelInfo(index, out filter, out size);
if (filter != null)
{
result.Add("type", 1);
result.Add("name", ((IPhpConvertible)filter).ToString());
}
else
{
result.Add("type", 0);
}
result.Add("buffer_size", size);
return result;
}
#endregion
#region flush, ob_flush
///
/// Flush the output buffer of the HTTP server. Has no effect on data buffered in Phalanger output buffers.
/// No value is returned.
///
[ImplementsFunction("flush")]
public static void FlushHttpBuffers()
{
HttpContext http_context = HttpContext.Current;
if (http_context != null) http_context.Response.Flush();
}
///
/// Flushes data from the current level of buffering to the previous one or to the client
/// if the current one is the first one. Applies the filter assigned to the current level (if any).
/// No value is returned.
///
[ImplementsFunction("ob_flush")]
public static void FlushOutputBuffer()
{
ScriptContext.CurrentContext.BufferedOutput.Flush();
}
#endregion
#region ob_implicit_flush
///
/// Switches implicit flushing on.
/// No value is returned.
///
/// Affects the current script context.
[ImplementsFunction("ob_implicit_flush")]
public static void ImplicitFlush()
{
HttpContext http_context = HttpContext.Current;
if (http_context != null) http_context.Response.BufferOutput = true;
}
///
/// Switches implicit flushing on or off.
/// No value is returned.
///
/// Do flush implicitly?
///
/// Affects the current script context.
///
/// There is a bug in the PHP implementation of this function:
/// "Turning implicit flushing on will disable output buffering, the output buffers current output
/// will be sent as if ob_end_flush() had been called."
/// Actually, this is not true (PHP doesn't do that) and in fact it is nonsense because
/// ob_end_flush only flushes and destroys one level of buffering.
/// It would be more meaningful if ob_implicit_flush function had flushed and destroyed all existing buffers
/// and so disabled output buffering.
///
[ImplementsFunction("ob_implicit_flush")]
public static void ImplicitFlush(bool doFlush)
{
HttpContext http_context = HttpContext.Current;
if (http_context != null) http_context.Response.BufferOutput = doFlush;
}
#endregion
#region ob_list_handlers
[ImplementsFunction("ob_list_handlers")]
public static PhpArray GetHandlers()
{
BufferedOutput bo = ScriptContext.CurrentContext.BufferedOutput;
PhpArray result = new PhpArray(bo.Level, 0);
for (int i = 0; i < bo.Level; i++)
{
result.Add(bo.GetLevelName(i));
}
return result;
}
#endregion
#region ob_gzhandler
/////
///// Compresses data by gzip compression. Not supported.
/////
///// Data to compress.
///// Compressed data.
//[ImplementsFunction("ob_gzhandler")]
//public static PhpBytes GzipHandler(string data)
//{
// return GzipHandler(data, 4);
//}
///
/// Available content encodings.
///
/// Values correspond to "content-encoding" response header.
private enum ContentEncoding
{
gzip, deflate
}
///
/// Compresses data by gzip compression.
///
/// Data to be compressed.
/// Compression mode.
/// Compressed data.
/// The function does not support subsequent calls to compress more chunks of data subsequentally.
[ImplementsFunction("ob_gzhandler")]
[return: CastToFalse]
public static object GzipHandler(object data, int mode)
{
// TODO: mode is not passed by Core properly. Therefore it is not possible to make subsequent calls to this handler.
// Otherwise headers of ZIP stream will be mishmashed.
// check input data
if (data == null) return null;
// check if we are running web application
var httpcontext = HttpContext.Current;
System.Collections.Specialized.NameValueCollection headers;
if (httpcontext == null ||
httpcontext.Request == null ||
(headers = httpcontext.Request.Headers) == null)
return data;
// check if compression is supported by browser
string acceptEncoding = headers["Accept-Encoding"];
if (acceptEncoding != null)
{
acceptEncoding = acceptEncoding.ToLower(System.Globalization.CultureInfo.InvariantCulture);
if (acceptEncoding.Contains("gzip"))
return DoGzipHandler(data, httpcontext, ContentEncoding.gzip);
if (acceptEncoding.Contains("*") || acceptEncoding.Contains("deflate"))
return DoGzipHandler(data, httpcontext, ContentEncoding.deflate);
}
return data;
/*
ScriptContext context = ScriptContext.CurrentContext;
bool do_start = (((BufferedOutput.ChunkPosition)mode) & BufferedOutput.ChunkPosition.First) != 0;
bool do_end = (((BufferedOutput.ChunkPosition)mode) & BufferedOutput.ChunkPosition.Last) != 0;
// redirects output to the sink to allow error reporting:
context.IsOutputBuffered = false;
PhpException.FunctionNotSupported(PhpError.Notice);
context.IsOutputBuffered = true;
if (data == null) return null;
return new PhpBytes(Configuration.Application.Globalization.PageEncoding.GetBytes(data));*/
}
///
/// Compress given data using compressor named in contentEncoding. Set the response header accordingly.
///
/// PhpBytes or string to be compressed.
/// Current HttpContext.
/// gzip or deflate
/// Byte stream of compressed data.
private static PhpBytes DoGzipHandler(object data, HttpContext/*!*/httpcontext, ContentEncoding contentEncoding)
{
PhpBytes phpbytes = data as PhpBytes;
var inputbytes = (phpbytes != null) ?
phpbytes.ReadonlyData :
Configuration.Application.Globalization.PageEncoding.GetBytes(PHP.Core.Convert.ObjectToString(data));
using (var outputStream = new System.IO.MemoryStream())
{
System.IO.Stream compressionStream;
switch (contentEncoding)
{
case ContentEncoding.gzip:
compressionStream = new System.IO.Compression.GZipStream(outputStream, System.IO.Compression.CompressionMode.Compress);
break;
case ContentEncoding.deflate:
compressionStream = new System.IO.Compression.DeflateStream(outputStream, System.IO.Compression.CompressionMode.Compress);
break;
default:
throw new ArgumentException("Not recognized content encoding to be compressed to.", "contentEncoding");
}
using (compressionStream)
{
compressionStream.Write(inputbytes, 0, inputbytes.Length);
}
//Debug.Assert(
// ScriptContext.CurrentContext.Headers["content-encoding"] != contentEncoding,
// "The content encoding was already set to '" + contentEncoding + "'. The ob_gzhandler() was called subsequently probably.");
ScriptContext.CurrentContext.Headers["content-encoding"] = contentEncoding.ToString();
return new PhpBytes(outputStream.ToArray());
}
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/PhpFormatter.CLR.cs
================================================
/*
Copyright (c) 2005-2006 Ladislav Prosek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using PHP.Core;
using PHP.Core.Reflection;
using System.Diagnostics;
namespace PHP.Library
{
///
/// Implements a PHP-compatible formatter (serializer).
///
public sealed class PhpFormatter : IFormatter
{
#region Tokens
///
/// Contains definition of (one-character) tokens that constitute PHP serialized data.
///
internal class Tokens
{
internal const char BraceOpen = '{';
internal const char BraceClose = '}';
internal const char Colon = ':';
internal const char Semicolon = ';';
internal const char Quote = '"';
internal const char Null = 'N';
internal const char Boolean = 'b';
internal const char Integer = 'i';
internal const char Double = 'd';
internal const char String = 's';
internal const char Array = 'a';
internal const char Object = 'O'; // instance of a class that does not implement SPL.Serializable
internal const char ObjectSer = 'C'; // instance of a class that implements SPL.Serializable
internal const char ClrObject = 'T'; // instance of CLR object, serialized using binary formatter
internal const char Reference = 'R'; // &-like reference
internal const char ObjectRef = 'r'; // same instance reference (PHP5 object semantics)
}
#endregion
///
/// Implements the serialization functionality. Serializes an object, or graph of objects
/// with the given root to the provided .
///
internal class ObjectWriter : Serializer.ClassContextHolder
{
#region Fields and Properties
private ScriptContext/*!*/ context;
///
/// The stream writer to write serialized data to.
///
private StreamWriter/*!*/ writer;
///
/// Object ID counter used by the r and R tokens.
///
private int sequenceNumber;
///
/// Maintains a sequence number for every and
/// that have already been serialized.
///
private Dictionary serializedRefs { get { return _serializedRefs ?? (_serializedRefs = new Dictionary()); } }
private Dictionary _serializedRefs;
#endregion
#region Construction
///
/// Creates a new with a given .
///
/// The current .
/// The writer to write serialized data to.
/// DTypeDesc of the caller's class context if it is known or UnknownTypeDesc if it should be determined lazily.
internal ObjectWriter(ScriptContext/*!*/ context, StreamWriter/*!*/ writer, DTypeDesc caller)
: base(caller)
{
Debug.Assert(context != null && writer != null);
this.context = context;
this.writer = writer;
}
#endregion
#region Serialize and Write*
///
/// Serializes an object or graph of objects to .
///
/// The object (graph) to serialize.
///
/// This is just a switch over 's type that delegates the task
/// to one of , , ,
/// , , ,
/// , and .
///
internal void Serialize(object graph)
{
sequenceNumber++;
if (graph == null) WriteNull();
else
{
switch (Type.GetTypeCode(graph.GetType()))
{
case TypeCode.Boolean: WriteBoolean((bool)graph); break;
case TypeCode.Int32: WriteInteger((int)graph); break;
case TypeCode.Int64: WriteInteger((long)graph); break;
case TypeCode.Double: WriteDouble((double)graph); break;
case TypeCode.String: WriteString((string)graph); break;
case TypeCode.Object:
{
PhpReference reference = graph as PhpReference;
if (reference != null)
{
WriteReference(reference);
break;
}
PhpBytes bytes = graph as PhpBytes;
if (bytes != null)
{
WriteBinaryData(bytes.ReadonlyData);
break;
}
PhpString str = graph as PhpString;
if (str != null)
{
WriteString(str.ToString());
break;
}
PhpArray array = graph as PhpArray;
if (array != null)
{
WriteArray(array);
break;
}
DObject obj = graph as DObject;
if (obj != null)
{
WriteObject(obj);
break;
}
PhpResource res = graph as PhpResource;
if (res != null)
{
// resources are serialized as 0
WriteInteger(0);
break;
}
goto default;
}
default:
throw new SerializationException(string.Format(Strings.serialization_unsupported_type, graph.GetType().FullName));
}
}
}
///
/// Serializes Null .
///
private void WriteNull()
{
writer.Write(Tokens.Null);
writer.Write(Tokens.Semicolon);
}
///
/// Serializes a bool value.
///
/// The value.
private void WriteBoolean(bool value)
{
writer.Write(Tokens.Boolean);
writer.Write(Tokens.Colon);
writer.Write(value ? '1' : '0');
writer.Write(Tokens.Semicolon);
}
///
/// Serializes an integer.
///
/// The integer.
private void WriteInteger(long value)
{
writer.Write(Tokens.Integer);
writer.Write(Tokens.Colon);
writer.Write(value);
writer.Write(Tokens.Semicolon);
}
///
/// Serializes a double.
///
/// The double.
private void WriteDouble(double value)
{
writer.Write(Tokens.Double);
writer.Write(Tokens.Colon);
// handle NaN, +Inf, -Inf
if (Double.IsNaN(value)) writer.Write("NAN");
else if (Double.IsPositiveInfinity(value)) writer.Write("INF");
else if (Double.IsNegativeInfinity(value)) writer.Write("-INF");
else writer.Write(value.ToString("R", NumberFormatInfo.InvariantInfo));
writer.Write(Tokens.Semicolon);
}
///
/// Serializes a string.
///
/// The string.
private void WriteString(string value)
{
byte[] binaryValue = writer.Encoding.GetBytes(value);
writer.Write(Tokens.String);
writer.Write(Tokens.Colon);
writer.Write(binaryValue.Length);
writer.Write(Tokens.Colon);
writer.Write(Tokens.Quote);
// flush the StreamWriter before accessing its underlying stream
writer.Flush();
writer.BaseStream.Write(binaryValue, 0, binaryValue.Length);
writer.Write(Tokens.Quote);
writer.Write(Tokens.Semicolon);
}
///
/// Serializes binary data.
///
/// The data.
private void WriteBinaryData(byte[] value)
{
writer.Write(Tokens.String);
writer.Write(Tokens.Colon);
writer.Write(value.Length);
writer.Write(Tokens.Colon);
writer.Write(Tokens.Quote);
// flush the StreamWriter before accessing its underlying stream
writer.Flush();
writer.BaseStream.Write(value, 0, value.Length);
writer.Write(Tokens.Quote);
writer.Write(Tokens.Semicolon);
}
///
/// Serializes a .
///
/// The reference.
private void WriteReference(PhpReference value)
{
sequenceNumber--;
if (!value.IsAliased)
{
Serialize(value.Value);
return;
}
int seq;
if (serializedRefs.TryGetValue(value, out seq))
{
// this reference has already been serialized -> write out its seq. number
writer.Write(Tokens.Reference);
writer.Write(Tokens.Colon);
writer.Write(seq);
writer.Write(Tokens.Semicolon);
}
else
{
serializedRefs.Add(value, sequenceNumber + 1);
if (value.Value is DObject && serializedRefs.TryGetValue(value.Value, out seq))
{
// this reference's value has already been serialized -> write out its seq. number
// (this is to handle situations such as array($x, &$x), where $x is an object instance)
writer.Write(Tokens.Reference);
writer.Write(Tokens.Colon);
writer.Write(seq);
writer.Write(Tokens.Semicolon);
}
else Serialize(value.Value);
}
}
///
/// Serializes a .
///
/// The array.
private void WriteArray(PhpArray value)
{
serializedRefs[value] = sequenceNumber;
writer.Write(Tokens.Array);
writer.Write(Tokens.Colon);
writer.Write(value.Count);
writer.Write(Tokens.Colon);
writer.Write(Tokens.BraceOpen);
// write out array items in the correct order
foreach (KeyValuePair entry in value)
{
Serialize(entry.Key.Object);
// don't assign a seq number to array keys
sequenceNumber--;
Serialize(entry.Value);
}
writer.Write(Tokens.BraceClose);
}
///
/// Serializes a .
///
/// The object.
/// Avoids redundant serialization of the same object by using .
private void WriteObject(DObject value)
{
int seq;
if (serializedRefs.TryGetValue(value, out seq))
{
// this object instance has already been serialized -> write out its seq. number
writer.Write(Tokens.ObjectRef);
writer.Write(Tokens.Colon);
writer.Write(seq);
writer.Write(Tokens.Semicolon);
sequenceNumber--;
}
else
{
serializedRefs.Add(value, sequenceNumber);
if (value is ClrObject || value is IClrValue)
WriteClrObjectInternal(value.RealObject);
else
WritePhpObjectInternal(value);
}
}
///
/// Serializes using PHP serialization.
///
/// The object.
private void WritePhpObjectInternal(DObject/*!*/value)
{
byte[] binaryClassName;
// determine class name
bool avoid_pic_name = false;
string class_name = null;
__PHP_Incomplete_Class pic = value as __PHP_Incomplete_Class;
if (pic != null)
{
if (pic.__PHP_Incomplete_Class_Name.IsSet)
{
avoid_pic_name = true;
class_name = pic.__PHP_Incomplete_Class_Name.Value as string;
}
}
if (value is stdClass) class_name = stdClass.ClassName;
if (class_name == null) class_name = value.TypeName;
// is the instance PHP5.1 Serializable?
if (value.RealObject is Library.SPL.Serializable)
{
context.Stack.AddFrame();
object res = PhpVariable.Dereference(value.InvokeMethod("serialize", null, context));
if (res == null)
{
// serialize returned NULL -> serialize the instance as NULL
WriteNull();
return;
}
byte[] resdata = null;
if (res is PhpString)
{
res = res.ToString();
}
if (res is string)
{
resdata = writer.Encoding.GetBytes((string)res);
}
else if (res is PhpBytes)
{
resdata = ((PhpBytes)res).ReadonlyData;
}
if (resdata == null)
{
// serialize did not return NULL nor a string -> throw an exception
SPL.Exception.ThrowSplException(
_ctx => new SPL.Exception(_ctx, true),
context,
string.Format(CoreResources.serialize_must_return_null_or_string, value.TypeName), 0, null);
}
writer.Write(Tokens.ObjectSer);
writer.Write(Tokens.Colon);
binaryClassName = writer.Encoding.GetBytes(class_name);
// write out class name
writer.Write(binaryClassName.Length);
writer.Write(Tokens.Colon);
writer.Write(Tokens.Quote);
// flush the StreamWriter before accessing its underlying stream
writer.Flush();
writer.BaseStream.Write(binaryClassName, 0, binaryClassName.Length);
writer.Write(Tokens.Quote);
writer.Write(Tokens.Colon);
// write out the result of serialize
writer.Write(resdata.Length);
writer.Write(Tokens.Colon);
writer.Write(Tokens.BraceOpen);
// flush the StreamWriter before accessing its underlying stream
writer.Flush();
writer.BaseStream.Write(resdata, 0, resdata.Length);
writer.Write(Tokens.BraceClose);
return;
}
// try to call the __sleep method
bool sleep_called;
PhpArray ser_props = value.Sleep(ClassContext, context, out sleep_called);
if (sleep_called && ser_props == null)
{
// __sleep did not return an array -> serialize the instance as NULL
WriteNull();
return;
}
writer.Write(Tokens.Object);
writer.Write(Tokens.Colon);
// write out class name
binaryClassName = writer.Encoding.GetBytes(class_name);
// write out class name
writer.Write(binaryClassName.Length);
writer.Write(Tokens.Colon);
writer.Write(Tokens.Quote);
// flush the StreamWriter before accessing its underlying stream
writer.Flush();
writer.BaseStream.Write(binaryClassName, 0, binaryClassName.Length);
writer.Write(Tokens.Quote);
writer.Write(Tokens.Colon);
// write out property count
if (ser_props != null) writer.Write(ser_props.Count);
else writer.Write(value.Count - (avoid_pic_name ? 1 : 0));
writer.Write(Tokens.Colon);
writer.Write(Tokens.BraceOpen);
// write out properties
if (ser_props != null) WriteSleepResult(value, ser_props);
else WriteAllProperties(value, avoid_pic_name);
writer.Write(Tokens.BraceClose);
}
///
/// Serializes an object using .NET binary formatter.
///
/// The object.
private void WriteClrObjectInternal(object realObject)
{
writer.Write(Tokens.ClrObject);
writer.Write(Tokens.Colon);
writer.Write(Tokens.BraceOpen);
// flush the StreamWriter before accessing its underlying stream
writer.Flush();
// serialize CLR object
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Serialize(writer.BaseStream, realObject);
//
writer.Write(Tokens.BraceClose);
}
///
/// Serializes properties whose names have been returned by __sleep .
///
/// The instance containing the properties to serialize.
/// The array containing names of the properties to serialize.
private void WriteSleepResult(DObject value, PhpArray propertiesToSerialize)
{
// serialize the properties whose names have been returned by __sleep
foreach (KeyValuePair pair in Serialization.EnumerateSerializableProperties(
value, propertiesToSerialize, context))
{
// write out the property name and the property value
Serialize(pair.Key);
sequenceNumber--; // don't assign a seq number to property names
Serialize(pair.Value);
}
}
///
/// Serializes all properties of a given instance.
///
/// The instance containing the properties to serialize.
/// If true , the property named __PHP_Incomplete_Class_Name
/// should not be serialized.
private void WriteAllProperties(DObject value, bool avoidPicName)
{
// if have no sleep result, serialize all instance properties
foreach (KeyValuePair pair in Serialization.EnumerateSerializableProperties(value))
{
if (avoidPicName && pair.Key == __PHP_Incomplete_Class.ClassNameFieldName)
{
// skip the __PHP_Incomplete_Class_Name field
continue;
}
// write out the property name and the property value
Serialize(pair.Key);
sequenceNumber--; // don't assign a seq number to property names
Serialize(pair.Value);
}
}
#endregion
}
///
/// Implements the deserialization functionality. Deserializes the data on the provided
/// and reconstitutes the graph of objects.
///
internal class ObjectReader : Serializer.ClassContextHolder
{
#region BackReference
///
/// Intermediate representation of a r or R record in serialized stream.
///
private class BackReference
{
///
/// The index referenced by this back-reference record.
///
private int index;
///
/// If true , this is a proper & reference (R ), if false ,
/// this is an object instance reference (r ) following the PHP 5 reference
/// semantics in objects.
///
private bool isProper;
///
/// Creates a new with a given index.
///
/// The index of the record being referred to.
/// Indicates whether this is a & reference, or
/// just object identity (valid only for objects - class instances).
internal BackReference(int index, bool isProper)
{
this.index = index;
this.isProper = isProper;
}
///
/// Returns the index that is being referred to.
///
internal int Index
{
get { return index; }
}
///
/// Returns true is this a & reference. See .
///
internal bool IsProper
{
get { return isProper; }
}
}
#endregion
#region Fields and Properties
private readonly ScriptContext/*!*/ context;
///
/// The stream to read serialized data from.
///
private readonly Stream/*!*/ stream;
///
/// Encoding to be used for conversion from binary to unicode strings.
///
private readonly Encoding/*!*/ encoding;
///
/// List of objects deserialized from the reader.
///
///
/// In its first phase, the deserializer reads the input stream token by token and stores the
/// deserialized items to this . If a proper back-reference (& )
/// is encountered, the referenced item is converted to and a
/// instance is stored to . End of array item and
/// object property lists are delimited by the singleton. In the second phase,
/// after the whole stream has been read, the object graph is built from this list (see
/// ).
///
private List atoms;
///
/// Maps sequence numbers used in the serialized stream to indices in the
/// list.
///
///
/// This is built simultaneously with during the
/// first "parsing" phase.
///
private List sequenceMap;
///
/// The lookahead symbol of the parser input (i.e. the ).
///
private char lookAhead;
///
/// Tells whether Consume methods are in Unicode reading mode. Legacy only, will be removed.
///
private bool unicodeMode;
///
/// Used for switching back from Unicode mode. Legacy only, will be removed.
///
private long lastUnicodeCharacterPos;
///
/// Used by Unicode consume to buffer bytes and read characters, if possible.
///
private byte[] miniByteBuffer;
///
/// Used by Unicode consume to buffer chars.
///
private char[] miniCharBuffer;
///
/// Used by Unicode consume to decode characters;
///
private Decoder decoder;
///
/// If true , there are no more characters in the input stream.
///
private bool endOfStream;
///
/// If true , the next item being added to the list should not be
/// assigned a sequence number.
///
private bool skipSequenceNumber;
///
/// Marks ends of array items and ends of object properties in the list.
///
private static object delimiter = new object();
///
/// Current position in the list during object graph building.
///
private int atomCounter;
///
/// Temporarily used . Remember it to save GC.
/// This method always returns the same instance of , it will always reset its to 0 .
///
private StringBuilder/*!*/GetTemporaryStringBuilder(int initialCapacity)
{
var tmp = tmpStringBuilder;
if (tmp != null)
{
tmp.Length = 0;
}
else
{
tmpStringBuilder = tmp = new StringBuilder(initialCapacity, int.MaxValue);
}
return tmp;
}
private StringBuilder tmpStringBuilder;
#endregion
#region Construction
///
/// Creates a new with a given .
///
/// The current .
/// The stream to read serialized data from.
/// Encoding used to read serialized strings.
/// DTypeDesc of the caller's class context if it is known or UnknownTypeDesc if it should be determined lazily.
internal ObjectReader(ScriptContext/*!*/ context, Stream/*!*/ stream, Encoding/*!*/ encoding, DTypeDesc caller)
:base(caller)
{
Debug.Assert(context != null && stream != null);
this.context = context;
this.stream = stream;
this.encoding = encoding;
this.atoms = new List();
this.sequenceMap = new List();
this.miniByteBuffer = new byte[1];
this.miniCharBuffer = new char[1];
this.decoder = encoding.GetDecoder();
// read look ahead character
Consume();
}
#endregion
#region Parser helpers: Throw*, Consume, AddAtom
///
/// Throws a due to an unexpected character.
///
private void ThrowUnexpected()
{
throw new SerializationException(LibResources.GetString("unexpected_character_in_stream"));
}
///
/// Throws a due to an unexpected end of stream.
///
private void ThrowEndOfStream()
{
throw new SerializationException(LibResources.GetString("unexpected_end_of_stream"));
}
///
/// Throws a due to an data type.
///
private void ThrowInvalidDataType()
{
throw new SerializationException(LibResources.GetString("invalid_data_bad_type"));
}
///
/// Throws a due to an invalid length marker.
///
private void ThrowInvalidLength()
{
throw new SerializationException(LibResources.GetString("invalid_data_bad_length"));
}
///
/// Throws a due to an invalid back-reference.
///
private void ThrowInvalidReference()
{
throw new SerializationException(LibResources.GetString("invalid_data_bad_back_reference"));
}
///
/// Consumes the look ahead character and moves to the next character in the input stream.
///
/// The old (consumed) look ahead character.
/// The consumed value is 8-bit, always in range 0x00 - 0xff.
private char Consume()
{
if (unicodeMode)
{
unicodeMode = false;
endOfStream = false;
stream.Seek(lastUnicodeCharacterPos, SeekOrigin.Begin);
Consume(); // update lookahead
}
if (endOfStream) ThrowEndOfStream();
char ret = lookAhead;
int next = stream.ReadByte();
if (next == -1)
{
endOfStream = true;
lookAhead = (char)0;
}
else lookAhead = (char)next;
return ret;
}
///
/// Consumes Unicode character based on encoding.
///
///
private char ConsumeLegacy()
{
if (!unicodeMode && !endOfStream)
{
unicodeMode = true;
stream.Seek(stream.Position - 1, SeekOrigin.Begin);
ConsumeLegacy();
}
if (endOfStream) ThrowEndOfStream();
lastUnicodeCharacterPos = stream.Position;
char ret = lookAhead;
while (true)
{
bool completed;
int bytesUsed;
int charsUsed;
int next = stream.ReadByte();
if (next == -1)
{
endOfStream = true;
lookAhead = (char)0;
return ret;
}
miniByteBuffer[0] = unchecked((byte)next);
decoder.Convert(miniByteBuffer, 0, 1, miniCharBuffer, 0, 1, false, out bytesUsed, out charsUsed, out completed);
if (charsUsed == 1) break;
}
lookAhead = miniCharBuffer[0];
return ret;
}
///
/// Consumes a given look ahead character and moves to the next character in the input stream.
///
/// The character that should be consumed.
/// If does not match current look ahead character,
/// is called.
private void Consume(char ch)
{
if (unicodeMode)
{
unicodeMode = false;
endOfStream = false;
stream.Seek(lastUnicodeCharacterPos, SeekOrigin.Begin);
Consume(); // update lookahead
}
if (endOfStream) ThrowEndOfStream();
if (lookAhead != ch) ThrowUnexpected();
int next = stream.ReadByte();
if (next == -1)
{
endOfStream = true;
lookAhead = (char)0;
}
else lookAhead = (char)next;
}
///
/// Tries to consume a given look ahead character and, if successful, moves to the next character in the input stream.
///
/// The character that should be consumed.
/// If does not match current look ahead character,
/// is called.
/// True if a character was successfully consumed, otherwise false.
private bool TryConsume(char ch)
{
if (unicodeMode)
{
unicodeMode = false;
endOfStream = false;
stream.Seek(lastUnicodeCharacterPos, SeekOrigin.Begin);
Consume(); // update lookahead
}
if (endOfStream) return false;
if (lookAhead != ch) return false;
int next = stream.ReadByte();
if (next == -1)
{
endOfStream = true;
lookAhead = (char)0;
}
else lookAhead = (char)next;
return true;
}
private void Seek(long position)
{
stream.Seek(position, SeekOrigin.Begin);
if (unicodeMode)
ConsumeLegacy();
else
Consume();
}
///
/// Adds an item to the list and optionally assigns a sequence number to it.
///
/// The item to add.
private void AddAtom(object obj)
{
if (!skipSequenceNumber) sequenceMap.Add(atoms.Count);
else skipSequenceNumber = false;
atoms.Add(obj);
}
#endregion
#region Utils
///
/// Quickly check if the look ahead byte is digit. Assumes the value is in range 0x00 - 0xff.
///
/// The lookAhead byte value.
/// True if value is in range '0'-'9'.
private static bool IsDigit(char lookAhead)
{
return Digit(lookAhead) != -1;
}
///
/// Quickly determine the numeric value of given lookAhead byte.
///
/// The lookAhead byte value.
///
private static int Digit(char lookAhead)
{
int num = unchecked((int)lookAhead - (int)'0');
return (num >= 0 && num <= 9) ? num : -1;
}
#endregion
#region Parser
///
/// The top-level parser method.
///
/// Just a switch over the look ahead characters that delegates the work to one of
/// , , , ,
/// , , , ,
/// .
private void Parse()
{
switch (Consume())
{
case Tokens.Null: ParseNull(); break;
case Tokens.Boolean: ParseBoolean(); break;
case Tokens.Integer: ParseInteger(); break;
case Tokens.Double: ParseDouble(); break;
case Tokens.String: ParseString(); break;
case Tokens.Array: ParseArray(); break;
case Tokens.Object: ParseObject(false); break;
case Tokens.ObjectSer: ParseObject(true); break;
case Tokens.ClrObject: ParseClrObject(); break;
case Tokens.Reference: ParseReference(); break;
case Tokens.ObjectRef: ParseObjectRef(); break;
default: ThrowUnexpected(); break;
}
}
///
/// Reads a signed 64-bit integer number from the .
///
/// The integer.
private long ReadInteger()
{
// pattern:
// [+-]?[0-9]+
long number = 0;
bool minus = (lookAhead == '-');
if (minus || (lookAhead == '+'))
Consume();
int digit; // == Digit(lookAhead)
if ((digit = Digit(lookAhead)) == -1)
ThrowUnexpected();
do
{
// let it overflow just as PHP does
number = unchecked((10 * number) + digit);
Consume();
} while ((digit = Digit(lookAhead)) != -1);
return (minus ? unchecked(-number) : number);
}
///
/// Reads a double-precision floating point number from the .
///
/// The double.
private double ReadDouble()
{
// pattern:
// NAN
// [+-]INF
// [+-]?[0-9]*[.]?[0-9]*([eE][+-]?[0-9]+)?
// NaN
if (lookAhead == 'N')
{
Consume();
Consume('A');
Consume('N');
return Double.NaN;
}
// mantissa + / -
int sign = 1;
if (lookAhead == '+') Consume();
else if (lookAhead == '-')
{
sign = -1;
Consume();
}
// Infinity
if (lookAhead == 'I')
{
Consume();
Consume('N');
Consume('F');
return (sign > 0 ? Double.PositiveInfinity : Double.NegativeInfinity);
}
// reconstruct the number:
StringBuilder number = GetTemporaryStringBuilder(16);
if (sign < 0) number.Append('-');
// [^;]*
while (Tokens.Semicolon != lookAhead)
{
number.Append(lookAhead);
Consume();
}
double result;
if (!Double.TryParse(number.ToString(), NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent | NumberStyles.AllowLeadingSign, NumberFormatInfo.InvariantInfo, out result))
ThrowUnexpected();
return result;
}
///
/// Reads a string with a given length surrounded by quotes from the .
///
/// The expected length of the string.
/// Byte array or null if string appears to be unicode (old functionality of serialize).
private byte[]/*!*/ReadString(int length)
{
//ASCII character - we can expect if will be always there (UTF16 is not supported).
Consume(Tokens.Quote);
if (endOfStream) ThrowEndOfStream();
if (length > 0)
{
byte[] buffer = new byte[length];
// use current lookahead
buffer[0] = unchecked((byte)lookAhead);
// read the rest from stream
int rlen = stream.Read(buffer, 1, length - 1);
// unicode string would be longer or of same length, so it is safe to fail if end of stream was reached
if (rlen != length - 1) ThrowEndOfStream();
// this just updates lookahead, and returns the lastahead which we already used
Consume();
// try to consume
bool success = TryConsume(Tokens.Quote);
if (success)
return buffer;
else
{
return null;
}
}
else
{
return ArrayUtils.EmptyBytes;
}
}
///
/// Reads a string with a given length surrounded by quotes from the .
///
/// The expected length of the string.
/// The string or null.
private string ReadStringUnicode(int length)
{
var bytes = ReadString(length);
if (bytes == null) return null;
return encoding.GetString(bytes);
}
///
/// LEGACY functionality, will be removed in future.
///
///
///
private string ReadStringLegacy(int length)
{
var sb = GetTemporaryStringBuilder(length);
Consume(Tokens.Quote);
while (length-- > 0) sb.Append(ConsumeLegacy());
Consume(Tokens.Quote);
return sb.ToString();
}
///
/// Parses the N token.
///
private void ParseNull()
{
Consume(Tokens.Semicolon);
AddAtom(null);
}
///
/// Parses the b token.
///
private void ParseBoolean()
{
Consume(Tokens.Colon);
switch (Consume())
{
case '0': AddAtom(false); break;
case '1': AddAtom(true); break;
default: ThrowUnexpected(); break;
}
Consume(Tokens.Semicolon);
}
///
/// Parses the i token.
///
private void ParseInteger()
{
Consume(Tokens.Colon);
long i = ReadInteger();
if (i >= Int32.MinValue && i <= Int32.MaxValue) AddAtom((int)i);
else AddAtom(i);
Consume(Tokens.Semicolon);
}
///
/// Parses the d token.
///
private void ParseDouble()
{
Consume(Tokens.Colon);
AddAtom(ReadDouble());
Consume(Tokens.Semicolon);
}
///
/// Parses the s token.
///
private void ParseString()
{
Consume(Tokens.Colon);
int length = (unchecked((int)ReadInteger()));
if (length < 0) ThrowInvalidLength();
long position = stream.Position;
Consume(Tokens.Colon);
var str = ReadString(length);
if (str != null && TryConsume(Tokens.Semicolon))
{
AddAtom(new PhpBytes(str));
}
else
{
Seek(position);
AddAtom(ReadStringLegacy(length));
Consume(Tokens.Semicolon);
}
}
///
/// Parses the a token.
///
private void ParseArray()
{
Consume(Tokens.Colon);
int length = (unchecked((int)ReadInteger()));
if (length < 0) ThrowInvalidLength();
Consume(Tokens.Colon);
AddAtom(new PhpArray(length / 2, length / 2));
Consume(Tokens.BraceOpen);
while (length-- > 0)
{
skipSequenceNumber = true;
Parse();
// J: do not encode byte[] to string
//if (atoms[atoms.Count - 1] is PhpBytes)
//{
// atoms[atoms.Count - 1] = encoding.GetString(((PhpBytes)atoms[atoms.Count - 1]).ReadonlyData);
//}
Parse();
}
atoms.Add(delimiter);
Consume(Tokens.BraceClose);
}
///
/// Parses the O and C tokens.
///
/// If true , the last token eaten was C , otherwise O .
private void ParseObject(bool serializable)
{
Consume(Tokens.Colon);
int length = (unchecked((int)ReadInteger()));
if (length < 0) ThrowInvalidLength();
long position = stream.Position;
Consume(Tokens.Colon);
string class_name = ReadStringUnicode(length);
if (class_name == null)
{
Seek(position);
class_name = ReadStringLegacy(length);
}
Consume(Tokens.Colon);
length = (unchecked((int)ReadInteger()));
if (length < 0) ThrowInvalidLength();
Consume(Tokens.Colon);
// bind to the specified class
DObject obj = Serialization.GetUninitializedInstance(class_name, context);
if (obj == null)
{
throw new SerializationException(LibResources.GetString("class_instantiation_failed",
class_name));
}
// check whether the instance is PHP5.1 Serializable
if (serializable && !(obj.RealObject is Library.SPL.Serializable))
{
throw new SerializationException(LibResources.GetString("class_has_no_unserializer",
class_name));
}
AddAtom(obj);
atoms.Add(serializable);
Consume(Tokens.BraceOpen);
if (serializable)
{
if (length > 0)
{
// add serialized representation to be later passed to unserialize
if (endOfStream) ThrowEndOfStream();
byte[] buffer = new byte[length];
// use current lookahead
buffer[0] = unchecked((byte)lookAhead);
// read the rest from stream
int rlen = stream.Read(buffer, 1, length - 1);
if (rlen != length - 1) ThrowEndOfStream();
// this just updates lookahead, and returns the lastahead which we already used
Consume();
atoms.Add(new PhpBytes(buffer));
}
else
{
atoms.Add(PhpBytes.Empty);
}
}
else
{
// parse properties
while (length-- > 0)
{
skipSequenceNumber = true;
// parse property name
Parse();
// verify that the name is either string or int
object name = atoms[atoms.Count - 1];
if (name is PhpBytes) // property name needs to be string
name = atoms[atoms.Count - 1] = encoding.GetString(((PhpBytes)name).ReadonlyData);
if (!(name is string))
{
if (!(name is int)) ThrowInvalidDataType();
atoms[atoms.Count - 1] = name.ToString();
}
// parse property value
Parse();
}
atoms.Add(delimiter);
}
Consume(Tokens.BraceClose);
}
///
/// Parses the T token.
///
/// Expects CLR object formatted using .
private void ParseClrObject()
{
// T,{DATA}
Consume(Tokens.Colon);
if (lookAhead != Tokens.BraceOpen)
ThrowUnexpected();
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
var obj = formatter.Deserialize(stream);
AddAtom(ClrObject.WrapDynamic(obj));
atoms.Add(false); // !serializable
atoms.Add(delimiter); // end
// restore lookAhead state:
int next = stream.ReadByte();
if (next == -1)
{
endOfStream = true;
lookAhead = (char)0;
}
else lookAhead = (char)next;
Consume(Tokens.BraceClose);
}
///
/// Parses the R token.
///
private void ParseReference()
{
Consume(Tokens.Colon);
int seq_number = (unchecked((int)ReadInteger())) - 1;
Consume(Tokens.Semicolon);
if (seq_number < 0 || seq_number >= sequenceMap.Count) ThrowInvalidReference();
int index = sequenceMap[seq_number];
// make the referenced atom a PhpReference
PhpReference reference = atoms[index] as PhpReference;
if (reference == null)
{
reference = new PhpReference(atoms[index]);
atoms[index] = reference;
}
atoms.Add(new BackReference(index, true));
}
///
/// Parses the r token.
///
private void ParseObjectRef()
{
Consume(Tokens.Colon);
int seq_number = (unchecked((int)ReadInteger())) - 1;
Consume(Tokens.Semicolon);
if (seq_number < 0 || seq_number >= sequenceMap.Count) ThrowInvalidReference();
int index = sequenceMap[seq_number];
atoms.Add(new BackReference(index, false));
}
#endregion
#region BuildObjectGraph, Deserialize
///
/// Builds the object graph from .
///
///
private object BuildObjectGraph()
{
object atom = atoms[atomCounter++];
if (atom != null /*&& Type.GetTypeCode(atom.GetType()) == TypeCode.Object*//* note (Jakub): useless check, in result much slower than a few .isinst */)
{
// back reference (either r or R)
BackReference back_ref = atom as BackReference;
if (back_ref != null)
{
PhpReference reference;
object ref_val = atoms[back_ref.Index];
if (back_ref.IsProper) return ref_val;
// object references should reference objects only
reference = ref_val as PhpReference;
if ((reference != null && !(reference.Value is DObject)) &&
!(ref_val is DObject)) ThrowInvalidReference();
return ref_val;
}
// dereference an eventual reference
object value = PhpVariable.Dereference(atom);
// array
PhpArray array = value as PhpArray;
if (array != null)
{
while (atoms[atomCounter] != delimiter)
{
object arraykey = BuildObjectGraph();
object arrayvalue = BuildObjectGraph();
if (arraykey is PhpBytes)// IntStringKey does not allow PhpBytes yet
arraykey = encoding.GetString(((PhpBytes)arraykey).ReadonlyData);
array.Add(arraykey, arrayvalue);
}
atomCounter++; // for the delimiter
return atom;
}
// object
DObject obj = value as DObject;
if (obj != null)
{
BuildDObject(obj);
return atom;
}
}
// no special treatment for the rest of the types
return atom;
}
///
/// Builds a from atoms (the object itself given as parameter).
///
/// The instance.
private void BuildDObject(DObject obj)
{
bool serializable = ((bool)atoms[atomCounter++] == true);
if (serializable && obj.RealObject is Library.SPL.Serializable)
{
// pass the serialized data to unserialize
context.Stack.AddFrame(BuildObjectGraph());
obj.InvokeMethod("unserialize", null, context);
return;
}
while (atoms[atomCounter] != delimiter)
{
string property_name = (string)BuildObjectGraph();
object property_value = BuildObjectGraph();
Debug.Assert(property_name != null);
Serialization.SetProperty(obj, property_name, property_value, context);
}
atomCounter++; // for the delimiter
// invoke __wakeup on the deserialized instance
obj.Wakeup(ClassContext, context);
}
///
/// Deserializes the data from the and reconstitutes the graph of objects.
///
/// The top object of the deserialized graph.
internal object Deserialize()
{
// parsing phase
Parse();
// object building phase
atomCounter = 0;
return BuildObjectGraph();
}
#endregion
}
#region Fields and properties
///
/// Serialization security permission demanded in .
///
private static SecurityPermission serializationPermission =
new SecurityPermission(SecurityPermissionFlag.SerializationFormatter);
///
/// The encoding to be used when writing and reading the serialization stream.
///
private readonly Encoding encoding;
///
/// DTypeDesc of the caller class context known already or UnknownTypeDesc if class context should be determined lazily.
///
private readonly DTypeDesc caller;
///
/// Gets or sets the serialization binder that performs type lookups during deserialization.
///
public SerializationBinder Binder
{
get { return null; }
set { throw new NotSupportedException(LibResources.GetString("serialization_binder_unsupported")); }
}
///
/// Gets or sets the streaming context used for serialization and deserialization.
///
public StreamingContext Context
{
get { return new StreamingContext(StreamingContextStates.Persistence); }
set { throw new NotSupportedException(LibResources.GetString("streaming_context_unsupported")); }
}
///
/// Gets or sets the surrogate selector used by the current formatter.
///
public ISurrogateSelector SurrogateSelector
{
get { return null; }
set { throw new NotSupportedException(LibResources.GetString("surrogate_selector_unsupported")); }
}
#endregion
#region Construction
/////
///// Creates a new with and
///// default .
/////
//public PhpFormatter()
//{
// this.encoding = new ASCIIEncoding();
//}
///
/// Creates a new with a given and
/// default .
///
/// The encoding to be used when writing and reading the serialization stream.
/// DTypeDesc of the caller's class context if it is known or UnknownTypeDesc if it should be determined lazily.
public PhpFormatter(Encoding encoding, DTypeDesc caller)
{
this.caller = caller;
// no UTF8 BOM!
if (encoding is UTF8Encoding)
this.encoding = new UTF8Encoding(false);
else
this.encoding = (encoding ?? new ASCIIEncoding());
}
#endregion
#region Serialize and Deserialize
///
/// Serializes an object, or graph of objects with the given root to the provided stream.
///
/// The stream where the formatter puts the serialized data.
/// The object, or root of the object graph, to serialize.
public void Serialize(Stream serializationStream, object graph)
{
if (serializationStream == null)
{
throw new ArgumentNullException("serializationStream");
}
serializationPermission.Demand();
StreamWriter stream_writer = new StreamWriter(serializationStream, encoding);
ObjectWriter object_writer = new ObjectWriter(ScriptContext.CurrentContext, stream_writer, caller);
try
{
object_writer.Serialize(graph);
}
finally
{
stream_writer.Flush();
}
}
///
/// Deserializes the data on the provided stream and reconstitutes the graph of objects.
///
/// The stream containing the data to deserialize.
/// The top object of the deserialized graph.
public object Deserialize(Stream serializationStream)
{
if (serializationStream == null)
{
throw new ArgumentNullException("serializationStream");
}
serializationPermission.Demand();
ScriptContext context = ScriptContext.CurrentContext;
ObjectReader object_reader = new ObjectReader(context, serializationStream, encoding, caller);
return object_reader.Deserialize();
}
#endregion
}
}
================================================
FILE: Source/ClassLibrary/PhpHttpUtility.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PHP.Library
{
///
/// This class implements alternative for HttpUtility.UrlEncode function which results have
/// hexadecimal values with small letters. However PHP returns big letters. This can lead
/// to incompatibility. e.g. %3a vs %3A
///
internal static class PhpHttpUtility
{
public static byte[] UrlEncode(byte[] bytes)
{
if (bytes == null)
{
return null;
}
return UrlEncode(bytes, 0, bytes.Length);
}
public static string UrlEncode(string str, Encoding e)
{
if (str == null)
{
return null;
}
byte[] bytes = e.GetBytes(str);
bytes = UrlEncode(bytes, 0, bytes.Length);
return Encoding.ASCII.GetString(bytes);
}
private static byte[] UrlEncode(byte[] bytes, int offset, int count)
{
if (!ValidateUrlEncodingParameters(bytes, offset, count))
{
return null;
}
int num = 0;
int num2 = 0;
for (int i = 0; i < count; i++)
{
char ch = (char)bytes[offset + i];
if (ch == ' ')
{
num++;
}
else if (!IsUrlSafeChar(ch))
{
num2++;
}
}
if ((num == 0) && (num2 == 0))
{
return bytes;
}
byte[] buffer = new byte[count + (num2 * 2)];
int num4 = 0;
for (int j = 0; j < count; j++)
{
byte num6 = bytes[offset + j];
char ch2 = (char)num6;
if (IsUrlSafeChar(ch2))
{
buffer[num4++] = num6;
}
else if (ch2 == ' ')
{
buffer[num4++] = 0x2b;
}
else
{
buffer[num4++] = 0x25;
buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15);
buffer[num4++] = (byte)IntToHex(num6 & 15);
}
}
return buffer;
}
private static bool ValidateUrlEncodingParameters(byte[] bytes, int offset, int count)
{
if ((bytes == null) && (count == 0))
{
return false;
}
if (bytes == null)
{
throw new ArgumentNullException("bytes");
}
if ((offset < 0) || (offset > bytes.Length))
{
throw new ArgumentOutOfRangeException("offset");
}
if ((count < 0) || ((offset + count) > bytes.Length))
{
throw new ArgumentOutOfRangeException("count");
}
return true;
}
public static bool IsUrlSafeChar(char ch)
{
if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) || ((ch >= '0') && (ch <= '9')))
{
return true;
}
switch (ch)
{
case '(':
case ')':
case '*':
case '-':
case '.':
case '_':
case '!':
return true;
}
return false;
}
public static char IntToHex(int n)
{
if (n <= 9)
{
return (char)(n + 0x30);
}
return (char)((n - 10) + 0x41);
}
}
}
================================================
FILE: Source/ClassLibrary/PhpIni.CLR.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.IO;
using System.Web;
using System.Xml;
using System.Threading;
using System.Collections;
using System.ComponentModel;
using PHP;
using PHP.Core;
using Convert = PHP.Core.Convert;
using System.Web.Configuration;
using System.Diagnostics;
namespace PHP.Library
{
#region Enumerations
///
/// Assertion options.
///
public enum AssertOption
{
///
/// Whether assertions are evaluated.
///
[ImplementsConstant("ASSERT_ACTIVE")]
Active,
///
/// Whether an error is reported if assertion fails.
///
[ImplementsConstant("ASSERT_WARNING")]
ReportWarning,
///
/// Whether script execution is terminated if assertion fails.
///
[ImplementsConstant("ASSERT_BAIL")]
Terminate,
///
/// Whether to disable error reporting during assertion evaluation.
///
[ImplementsConstant("ASSERT_QUIET_EVAL")]
Quiet,
///
/// The user callback to be called if assertion fails.
/// Can be a null reference which means no function is called.
///
[ImplementsConstant("ASSERT_CALLBACK")]
Callback
}
#endregion
///
/// Class manipulating PHP configuration.
/// The class is provided only for backward compatibility with PHP and
/// is intended to be used only by a compiler of PHP language.
///
///
public static class PhpIni
{
#region Default values for Core options having no equivalent in configuration record
///
/// Default value for "default_mimetype" PHP configuration option.
///
public const string DefaultMimetype = "text/html";
///
/// Default value for "default_charset" PHP configuration option.
///
public static readonly string DefaultCharset = Configuration.Application.Globalization.PageEncoding.HeaderName;
///
/// A value of "error_log" option meaning System log.
///
public const string ErrorLogSysLog = "syslog";
#endregion
#region Core Options
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
case "extension_dir": Debug.Assert(action == IniAction.Get); return app.Paths.Libraries;
#endregion
#region
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
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
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
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
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
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
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
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
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
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;
}
///
/// Writes Core legacy options and their values to XML text stream.
/// Skips options whose values are the same as default values of Phalanger.
///
/// XML writer.
/// A hashtable containing PHP names and option values. Consumed options are removed from the table.
/// Whether to add "phpName" attribute to option nodes.
public static void CoreOptionsToXml(XmlTextWriter writer, Hashtable options, bool writePhpNames) // GENERICS:
{
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();
}
#endregion
#region Public GSRs
internal static bool OptionValueToBoolean(object value)
{
string sval = value as string;
if (sval != null)
{
switch (sval.ToLower(System.Globalization.CultureInfo.InvariantCulture)) // we dont need any unicode chars lowercased properly, CurrentCulture is slow
{
case "on":
case "yes": return true;
case "off":
case "no":
case "none": return false;
}
}
return Convert.ObjectToBoolean(value);
}
///
/// Gets, sets or restores boolean option.
///
public static object GSR(ref bool option, bool defaultValue, object value, IniAction action)
{
object result = option;
switch (action)
{
case IniAction.Set: option = OptionValueToBoolean(value); break;
case IniAction.Restore: option = defaultValue; break;
}
return result;
}
///
/// Gets, sets or restores integer option.
///
public static object GSR(ref int option, int defaultValue, object value, IniAction action)
{
object result = option;
switch (action)
{
case IniAction.Set: option = Convert.ObjectToInteger(value); break;
case IniAction.Restore: option = defaultValue; break;
}
return result;
}
///
/// Gets, sets or restores double option.
///
public static object GSR(ref double option, double defaultValue, object value, IniAction action)
{
object result = option;
switch (action)
{
case IniAction.Set: option = Convert.ObjectToDouble(value); break;
case IniAction.Restore: option = defaultValue; break;
}
return result;
}
///
/// Gets, sets or restores string option.
///
public static object GSR(ref string option, string defaultValue, object value, IniAction action)
{
object result = option;
switch (action)
{
case IniAction.Set: option = Convert.ObjectToString(value); break;
case IniAction.Restore: option = defaultValue; break;
}
return result;
}
///
/// Gets, sets or restores callback option.
///
public static object GSR(ref PhpCallback option, PhpCallback defaultValue, object value, IniAction action)
{
object result = option;
switch (action)
{
case IniAction.Set: option = Convert.ObjectToCallback(value); break;
case IniAction.Restore: option = defaultValue; break;
}
return result;
}
#endregion
#region Special GSRs
///
/// Gets, sets or restores "default_charset" option.
///
private static object GsrDefaultCharset(object value, IniAction action)
{
HttpContext context;
if (!Web.EnsureHttpContext(out context)) return null;
object result = context.Response.Charset;
switch (action)
{
case IniAction.Set: context.Response.Charset = Convert.ObjectToString(value); break;
case IniAction.Restore: context.Response.Charset = DefaultCharset; break;
}
return result;
}
///
/// Gets, sets or restores "default_mimetype" option.
///
private static object GsrDefaultMimetype(object value, IniAction action)
{
HttpContext context;
if (!Web.EnsureHttpContext(out context)) return null;
object result = context.Response.ContentType;
switch (action)
{
case IniAction.Set: context.Response.ContentType = Convert.ObjectToString(value); break;
case IniAction.Restore: context.Response.ContentType = DefaultMimetype; break;
}
return result;
}
///
/// Gets, sets or restores "memory_limit" option.
///
private static object GsrMemoryLimit(object value, IniAction action)
{
object result = -1;
switch (action)
{
case IniAction.Set:
case IniAction.Restore:
PhpException.ArgumentValueNotSupported("memory_limit", action);
break;
}
return result;
}
///
/// Gets, sets or restores "disable_functions" option.
///
private static object GsrDisableFunctions(object value, IniAction action)
{
object result = "";
switch (action)
{
case IniAction.Set:
case IniAction.Restore:
PhpException.ArgumentValueNotSupported("disable_functions", action);
break;
}
return result;
}
///
/// Gets, sets or restores "variables_order" option.
///
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;
}
///
/// Gets, sets or restores "error_log" option.
///
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;
}
#endregion
#region ini_get, ini_set, ini_restore, get_cfg_var, ini_alter
///
/// Gets the value of a configuration option.
///
/// The option name (case sensitive).
/// The option old value conveted to string or false on error.
/// The option is not supported (Warning).
[ImplementsFunction("ini_get")]
public static object Get(string option)
{
bool error;
object result = IniOptions.TryGetSetRestore(option, null, IniAction.Get, out error);
if (error) return false;
return Convert.ObjectToString(result);
}
///
/// Sets the value of a configuration option.
///
/// The option name (case sensitive).
/// The option new value.
/// The option old value converted to string or false on error.
/// The option is not supported (Warning).
/// The option cannot be set by script (Warning).
[ImplementsFunction("ini_set")]
public static object Set(string option, object value)
{
bool error;
object result = IniOptions.TryGetSetRestore(option, value, IniAction.Set, out error);
if (error) return false;
return Convert.ObjectToString(result);
}
///
/// Restores the value of a configuration option to its global value.
/// No value is returned.
///
/// The option name (case sensitive).
/// The option is not supported (Warning).
[ImplementsFunction("ini_restore")]
public static void Restore(string option)
{
bool error;
IniOptions.TryGetSetRestore(option, null, IniAction.Restore, out error);
}
///
/// Gets the value of a configuration option (alias for ).
///
/// The option name (case sensitive).
/// The option old value conveted to string or false on error.
/// The option is not supported (Warning).
[ImplementsFunction("get_cfg_var")]
public static object GetCfgVar(string option)
{
return Get(option);
}
///
/// Sets the value of a configuration option (alias for ).
///
/// The option name (case sensitive).
/// The option new value converted to string.
/// The option old value.
/// The option is not supported (Warning).
/// The option cannot be set by script (Warning).
[ImplementsFunction("ini_alter")]
public static object Alter(string option, object value)
{
return Set(option, value);
}
#endregion
#region get_all
///
/// Retrieves an array of all configuration entries.
///
///
[ImplementsFunction("ini_get_all")]
public static PhpArray GetAll()
{
return (PhpArray)IniOptions.GetAllOptionStates(null, new PhpArray(0, IniOptions.Count));
}
///
/// Retrieves an array of configuration entries of a specified extension.
///
/// The PHP internal extension name.
///
/// For each supported configuration option an entry is added to the resulting array.
/// The key is the name of the option and the value is an array having three entries:
///
/// global_value - global value of the option
/// local_value - local value of the option
/// access - 7 (PHP_INI_ALL), 6 (PHP_INI_PERDIR | PHP_INI_SYSTEM) or 4 (PHP_INI_SYSTEM)
///
///
[ImplementsFunction("ini_get_all")]
public static PhpArray GetAll(string extension)
{
PhpArray result = new PhpArray();
// adds options from managed libraries:
IniOptions.GetAllOptionStates(extension, result);
return result;
}
#endregion
#region assert_options
///
/// Gets a value of an assert option.
///
/// The option which value to get.
/// The value of the option.
[ImplementsFunction("assert_options")]
public static object AssertOptions(AssertOption option)
{
return AssertOptions(option, null, IniAction.Get);
}
///
/// Sets a value of an assert option.
///
/// The option which value to get.
/// The new value for the option.
/// The value of the option.
[ImplementsFunction("assert_options")]
public static object AssertOptions(AssertOption option, object value)
{
return AssertOptions(option, value, IniAction.Set);
}
///
/// Implementation of and .
///
/// Only gets/sets. No restore.
private static object AssertOptions(AssertOption option, object value, IniAction action)
{
LocalConfiguration config = Configuration.Local;
switch (option)
{
case AssertOption.Active:
return GSR(ref config.Assertion.Active, false, value, action);
case AssertOption.Callback:
return GSR(ref config.Assertion.Callback, null, value, action);
case AssertOption.Quiet:
return GSR(ref config.Assertion.Quiet, false, value, action);
case AssertOption.Terminate:
return GSR(ref config.Assertion.Terminate, false, value, action);
case AssertOption.ReportWarning:
return GSR(ref config.Assertion.ReportWarning, false, value, action);
default:
PhpException.InvalidArgument("option");
return false;
}
}
#endregion
#region get_include_path, set_include_path, restore_include_path
///
/// Gets a value of "include_path" option.
///
/// The current value.
[ImplementsFunction("get_include_path")]
public static string GetIncludePath()
{
return Configuration.Local.FileSystem.IncludePaths;
}
///
/// Sets a new value of "include_path" option.
///
/// A previous value.
[ImplementsFunction("set_include_path")]
public static string SetIncludePath(string value)
{
LocalConfiguration config = Configuration.Local;
string result = config.FileSystem.IncludePaths;
config.FileSystem.IncludePaths = value;
return result;
}
///
/// Restores a value of "include_path" option from global configuration.
/// No value is returned.
///
[ImplementsFunction("restore_include_path")]
public static void RestoreIncludePath()
{
Configuration.Local.FileSystem.IncludePaths = Configuration.DefaultLocal.FileSystem.IncludePaths;
}
#endregion
#region get_magic_quotes_gpc, get_magic_quotes_runtime, set_magic_quotes_runtime
///
/// Gets a value of "magic_quotes_gpc" option.
///
/// The current value.
[ImplementsFunction("get_magic_quotes_gpc")]
public static bool GetMagicQuotesGPC()
{
return Configuration.Global.GlobalVariables.QuoteGpcVariables;
}
///
/// Gets a value of "magic_quotes_runtime" option.
///
/// The current value.
[ImplementsFunction("get_magic_quotes_runtime")]
public static bool GetMagicQuotesRuntime()
{
return Configuration.Local.Variables.QuoteRuntimeVariables;
}
///
/// Sets a new value of "magic_quotes_runtime" option.
///
/// The new value.
/// A previous value.
[ImplementsFunction("set_magic_quotes_runtime")]
public static bool SetMagicQuotesRuntime(bool value)
{
LocalConfiguration local = Configuration.Local;
bool result = local.Variables.QuoteRuntimeVariables;
local.Variables.QuoteRuntimeVariables = value;
return result;
}
#endregion
#region error_reporting, set_error_handler, restore_error_handler, set_exception_handler, restore_exception_handler
///
/// Retrieves the current error reporting level.
///
///
/// The bitmask of error types which are reported. Returns 0 if error reporting is disabled
/// by means of @ operator.
///
[ImplementsFunction("error_reporting")]
public static int ErrorReporting()
{
return ScriptContext.CurrentContext.ErrorReportingLevel;
}
///
/// Sets a new level of error reporting.
///
/// The new level.
/// The original level.
[ImplementsFunction("error_reporting")]
public static int ErrorReporting(int level)
{
if ((level & (int)PhpErrorSet.All) == 0 && level != 0)
PhpException.InvalidArgument("level");
ScriptContext context = ScriptContext.CurrentContext;
int result = context.ErrorReportingLevel;
context.Config.ErrorControl.ReportErrors = PhpErrorSet.All & (PhpErrorSet)level;
return result;
}
///
/// Internal record in the error handler stack.
///
private class ErrorHandlerRecord
{
///
/// Error handler callback.
///
public PhpCallback ErrorHandler;
///
/// Error types to be handled.
///
public PhpError ErrorTypes;
///
/// Public constructor of the class.
///
/// Error handler callback.
/// Error types to be handled.
public ErrorHandlerRecord(PhpCallback handler, PhpError errors)
{
ErrorHandler = handler;
ErrorTypes = errors;
}
}
///
/// Stores user error handlers which has been rewritten by a new one.
///
[ThreadStatic]
private static Stack OldUserErrorHandlers; // GENERICS:
///
/// Stores user exception handlers which has been rewritten by a new one.
///
[ThreadStatic]
private static Stack OldUserExceptionHandlers; // GENERICS:
///
/// Clears and on request end.
///
private static void ClearOldUserHandlers()
{
OldUserErrorHandlers = null;
OldUserExceptionHandlers = null;
}
///
/// Sets user defined handler to handle errors.
///
/// The class context used to bind the callback.
/// The user callback called to handle an error.
///
/// The PHP representation of previous user handler, null if there is no user one, or
/// false if is invalid or empty.
///
///
/// Stores old user handlers on the stack so that it is possible to
/// go back to arbitrary previous user handler.
///
[ImplementsFunction("set_error_handler", FunctionImplOptions.NeedsClassContext)]
public static object SetErrorHandler(PHP.Core.Reflection.DTypeDesc caller, PhpCallback newHandler)
{
return SetErrorHandler(caller, newHandler, (int)PhpErrorSet.Handleable);
}
///
/// Sets user defined handler to handle errors.
///
/// The class context used to bind the callback.
/// The user callback called to handle an error.
/// Error types to be handled by the handler.
///
/// The PHP representation of previous user handler, null if there is no user one, or
/// false if is invalid or empty.
///
///
/// Stores old user handlers on the stack so that it is possible to
/// go back to arbitrary previous user handler.
///
[ImplementsFunction("set_error_handler", FunctionImplOptions.NeedsClassContext)]
public static object SetErrorHandler(PHP.Core.Reflection.DTypeDesc caller, PhpCallback newHandler, int errorTypes)
{
if (!PhpArgument.CheckCallback(newHandler, caller, "newHandler", 0, false)) return null;
PhpCallback old_handler = Configuration.Local.ErrorControl.UserHandler;
PhpError old_errors = Configuration.Local.ErrorControl.UserHandlerErrors;
// previous handler was defined by user => store it into the stack:
if (old_handler != null)
{
if (OldUserErrorHandlers == null)
{
OldUserErrorHandlers = new Stack(5);
RequestContext.RequestEnd += new Action(ClearOldUserHandlers);
}
OldUserErrorHandlers.Push(new ErrorHandlerRecord(old_handler, old_errors));
}
// sets the current handler:
Configuration.Local.ErrorControl.UserHandler = newHandler;
Configuration.Local.ErrorControl.UserHandlerErrors = (PhpError)errorTypes;
// returns the previous handler:
return (old_handler != null) ? old_handler.ToPhpRepresentation() : null;
}
///
/// Restores the previous user error handler if there was any.
///
[ImplementsFunction("restore_error_handler")]
public static bool RestoreErrorHandler()
{
// if some user handlers has been stored in the stack then restore the top-most, otherwise set to null:
if (OldUserErrorHandlers != null && OldUserErrorHandlers.Count > 0)
{
ErrorHandlerRecord record = (ErrorHandlerRecord)OldUserErrorHandlers.Pop();
Configuration.Local.ErrorControl.UserHandler = record.ErrorHandler;
Configuration.Local.ErrorControl.UserHandlerErrors = record.ErrorTypes;
}
else
{
Configuration.Local.ErrorControl.UserHandler = null;
Configuration.Local.ErrorControl.UserHandlerErrors = (PhpError)PhpErrorSet.None;
}
return true;
}
///
/// Sets user defined handler to handle exceptions.
///
/// The class context used to bind the callback.
/// The user callback called to handle an exceptions.
///
/// The PHP representation of previous user handler, null if there is no user one, or
/// false if is invalid or empty.
///
///
/// Stores old user handlers on the stack so that it is possible to
/// go back to arbitrary previous user handler.
///
[ImplementsFunction("set_exception_handler", FunctionImplOptions.NeedsClassContext)]
public static object SetExceptionHandler(PHP.Core.Reflection.DTypeDesc caller, PhpCallback newHandler)
{
if (!PhpArgument.CheckCallback(newHandler, caller, "newHandler", 0, false)) return null;
PhpCallback old_handler = Configuration.Local.ErrorControl.UserExceptionHandler;
// previous handler was defined by user => store it into the stack:
if (old_handler != null)
{
if (OldUserExceptionHandlers == null)
{
OldUserExceptionHandlers = new Stack(5);
RequestContext.RequestEnd += new Action(ClearOldUserHandlers);
}
OldUserExceptionHandlers.Push(old_handler);
}
// sets the current handler:
Configuration.Local.ErrorControl.UserExceptionHandler = newHandler;
// returns the previous handler:
return (old_handler != null) ? old_handler.ToPhpRepresentation() : null;
}
///
/// Restores the previous user error handler if there was any.
///
[ImplementsFunction("restore_exception_handler")]
public static bool RestoreExceptionHandler()
{
if (OldUserExceptionHandlers != null && OldUserExceptionHandlers.Count > 0)
Configuration.Local.ErrorControl.UserExceptionHandler = (PhpCallback)OldUserExceptionHandlers.Pop();
else
Configuration.Local.ErrorControl.UserExceptionHandler = null;
return true;
}
#endregion
#region set_time_limit, ignore_user_abort
///
/// Sets the request time-out in seconds (configuration option "max_execution_time").
/// No value is returned.
///
/// The time-out setting for request.
[ImplementsFunction("set_time_limit")]
public static void SetTimeLimit(int seconds)
{
ScriptContext.CurrentContext.ApplyExecutionTimeout(seconds);
}
///
/// Get a value of a configuration option "ignore_user_abort".
///
/// The current value of the option.
[ImplementsFunction("ignore_user_abort")]
public static bool IgnoreUserAbort()
{
return Configuration.Local.RequestControl.IgnoreUserAbort;
}
///
/// Sets a value of a configuration option "ignore_user_abort".
///
/// The new value of the option.
/// The previous value of the option.
/// Web request PHP context is not available (Warning).
[ImplementsFunction("ignore_user_abort")]
public static bool IgnoreUserAbort(bool value)
{
RequestContext context;
if (!Web.EnsureRequestContext(out context)) return true;
LocalConfiguration local = Configuration.Local;
bool result = local.RequestControl.IgnoreUserAbort;
local.RequestControl.IgnoreUserAbort = value;
// enables/disables disconnection tracking:
context.TrackClientDisconnection = !value;
return result;
}
#endregion
}
#region PhpIniXmlWriter
public sealed class PhpIniXmlWriter
{
private readonly XmlTextWriter writer;
private readonly Hashtable options; // GENERICS:
private readonly bool writePhpNames;
private string startSection;
private bool sectionOpened;
public PhpIniXmlWriter(XmlTextWriter writer, Hashtable options, bool writePhpNames)
{
this.writer = writer;
this.options = options;
this.writePhpNames = writePhpNames;
}
public void WriteEnd()
{
if (sectionOpened)
writer.WriteEndElement();
}
public void StartSection(string name)
{
startSection = name;
}
private void StartElement()
{
if (startSection != null)
{
if (sectionOpened)
writer.WriteEndElement();
writer.WriteStartElement(startSection);
startSection = null;
sectionOpened = true;
}
}
private void WriteSetNode(string phpName, string xmlName, string value)
{
StartElement();
writer.WriteStartElement("set");
writer.WriteAttributeString("name", xmlName);
writer.WriteAttributeString("value", value);
if (writePhpNames)
writer.WriteAttributeString("phpName", phpName);
writer.WriteEndElement();
}
private void WriteEnumSetNode(string phpName, string xmlName, int value, Type type)
{
StartElement();
writer.WriteStartElement("set");
writer.WriteAttributeString("name", xmlName);
if (writePhpNames)
writer.WriteAttributeString("phpName", phpName);
writer.WriteStartElement("clear");
writer.WriteEndElement();
writer.WriteStartElement("add");
writer.WriteAttributeString("value", Enum.Format(type, value, "G"));
writer.WriteEndElement();
writer.WriteEndElement();
}
public void WriteOption(string phpName, string xmlName, string phpValue, string defValue)
{
if (options.ContainsKey(phpName))
{
phpValue = (string)options[phpName];
options.Remove(phpName);
}
if (phpValue == null) phpValue = "";
if (defValue == null) defValue = "";
if (phpValue != defValue)
WriteSetNode(phpName, xmlName, phpValue);
}
public void WriteOption(string phpName, string xmlName, bool phpValue, bool defValue)
{
if (options.ContainsKey(phpName))
{
phpValue = Core.Convert.StringToBoolean((string)options[phpName]);
options.Remove(phpName);
}
if (phpValue != defValue)
WriteSetNode(phpName, xmlName, phpValue ? "true" : "false");
}
public void WriteByteSize(string phpName, string xmlName, int phpValue, int defValue)
{
if (options.ContainsKey(phpName))
{
phpValue = Core.Convert.StringByteSizeToInteger((string)options[phpName]);
options.Remove(phpName);
}
if (phpValue != defValue)
WriteSetNode(phpName, xmlName, phpValue.ToString());
}
public void WriteOption(string phpName, string xmlName, int phpValue, int defValue)
{
if (options.ContainsKey(phpName))
{
phpValue = Core.Convert.StringToInteger((string)options[phpName]);
options.Remove(phpName);
}
if (phpValue != defValue)
WriteSetNode(phpName, xmlName, phpValue.ToString());
}
public void WriteOption(string phpName, string xmlName, double phpValue, double defValue)
{
if (options.ContainsKey(phpName))
{
phpValue = Core.Convert.StringToDouble((string)options[phpName]);
options.Remove(phpName);
}
if (phpValue != defValue)
WriteSetNode(phpName, xmlName, phpValue.ToString());
}
public void WriteOption(string phpName, string xmlName, string phpValue, PhpCallback defValue)
{
WriteOption(phpName, xmlName, phpValue, (defValue != null) ? ((IPhpConvertible)defValue).ToString() : null);
}
internal void WriteErrorLog(string phpName, string phpValue, bool defSysLog, string defLogFile)
{
if (options.ContainsKey(phpName))
{
phpValue = (string)options[phpName];
options.Remove(phpName);
}
bool phpSysLog = phpValue == PhpIni.ErrorLogSysLog;
string phpLogFile = phpSysLog ? null : phpValue;
if (phpLogFile == null) phpLogFile = "";
if (defLogFile == null) defLogFile = "";
if (phpLogFile != defLogFile)
WriteSetNode(phpName, "LogFile", phpLogFile);
if (phpSysLog != defSysLog)
WriteSetNode(phpName, "SysLog", phpSysLog ? "true" : "false");
}
public void WriteEnumOption(string phpName, string xmlName, int phpValue, int defValue, Type type)
{
if (options.ContainsKey(phpName))
{
phpValue = Core.Convert.StringToInteger((string)options[phpName]);
options.Remove(phpName);
}
if (phpValue != defValue)
WriteEnumSetNode(phpName, xmlName, phpValue, type);
}
}
#endregion
}
================================================
FILE: Source/ClassLibrary/PhpIniOptions.CLR.cs
================================================
/*
Copyright (c) 2004-2006 Tomas Matousek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using PHP.Core;
using Convert = PHP.Core.Convert;
using System.Diagnostics;
namespace PHP.Library
{
public delegate object GetSetRestoreDelegate(LocalConfiguration config, string option, object value, IniAction action);
///
/// An action which can be performed on option.
///
public enum IniAction
{
Restore, Set, Get
}
[Flags]
public enum IniFlags : byte
{
Unsupported = 0,
Global = 0,
Supported = 1,
Local = 2,
Http = 4,
}
[Flags]
public enum IniAccessability
{
User = 1,
PerDirectory = 2,
System = 4,
All = 7,
Global = PerDirectory | System,
Local = All
}
public static class IniOptions
{
#region Options Table
///
/// Holds information about the option.
///
public class OptionDefinition // GENERICS: struct
{
public readonly IniFlags Flags;
public readonly GetSetRestoreDelegate Gsr;
public readonly string Extension;
internal OptionDefinition(IniFlags flags, GetSetRestoreDelegate gsr, string extension)
{
this.Flags = flags;
this.Gsr = gsr;
this.Extension = extension;
}
}
private static Dictionary options;
private static GetSetRestoreDelegate GsrCoreOption = new GetSetRestoreDelegate(PhpIni.GetSetRestoreCoreOption);
///
/// Gets a number of currently registered options.
///
public static int Count { get { return options.Count; } }
///
/// Gets an option by name.
///
/// The name of the option.
/// Information about the option or a null reference if it has not been registered yet.
/// is a null reference.
/// Shouldn't be called before or during option registration (not thread safe for writes).
public static OptionDefinition GetOption(string name)
{
if (name == null)
throw new ArgumentNullException("name");
OptionDefinition value;
return options.TryGetValue(name, out value) ? value : null;
}
///
/// Registeres a legacy configuration option. Not thread safe.
///
/// A case-sensitive unique option name.
/// Flags.
/// A delegate pointing to a method which will perform option's value getting, setting, and restoring.
/// A case-sensitive name of the extension which the option belongs to. Can be a null reference.
///
/// Registered options are known to ini_get , ini_set , and ini_restore PHP functions.
///
/// is a null reference.
/// is a null reference.
/// An option with specified name has already been registered.
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));
}
///
/// Registeres a Core option.
///
private static void RegisterCoreOption(string name, IniFlags flags)
{
options.Add(name, new OptionDefinition(flags, GsrCoreOption, null));
}
#endregion
#region Initialization
static IniOptions()
{
options = new Dictionary(150);
RegisterCoreOption("allow_call_time_pass_reference", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("allow_url_fopen", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("allow_webdav_methods", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("always_populate_raw_post_data", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("arg_separator.input", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("arg_separator.output", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("asp_tags", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("assert.active", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("assert.bail", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("assert.callback", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("assert.quiet_eval", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("assert.warning", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("async_send", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("auto_append_file", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("auto_detect_line_endings", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("auto_prepend_file", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("browscap", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("cgi.force_redirect", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("cgi.redirect_status_env", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("cgi.rfc2616_headers", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("child_terminate", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("debugger.enabled", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("debugger.host", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("debugger.port", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("default_charset", IniFlags.Supported | IniFlags.Local | IniFlags.Http);
RegisterCoreOption("default_mimetype", IniFlags.Supported | IniFlags.Local | IniFlags.Http);
RegisterCoreOption("default_socket_timeout", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("define_syslog_variables", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("disable_classes", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("disable_functions", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("display_errors", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("display_startup_errors", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("doc_root", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("enable_dl", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("engine", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("error_append_string", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("error_log", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("error_prepend_string", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("error_reporting", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("expose_php", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("extension_dir", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("fastcgi.impersonate", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("file_uploads", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("from", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("gpc_order", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("html_errors", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("ignore_repeated_errors", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("ignore_repeated_source", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("ignore_user_abort", IniFlags.Supported | IniFlags.Local | IniFlags.Http);
RegisterCoreOption("implicit_flush", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("include_path", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("last_modified", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("log_errors", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("log_errors_max_len", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("magic_quotes_gpc", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("magic_quotes_runtime", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("magic_quotes_sybase", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("max_execution_time", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("max_input_time", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("memory_limit", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("mime_magic.magicfile", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("open_basedir", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("output_buffering", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("output_handler", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("post_max_size", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("precision", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("register_argc_argv", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("register_globals", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("register_long_arrays", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("report_memleaks", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("safe_mode", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("safe_mode_allowed_env_vars", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("safe_mode_exec_dir", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("safe_mode_gid", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("safe_mode_include_dir", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("safe_mode_protected_env_vars", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("session.auto_start", IniFlags.Supported | IniFlags.Global | IniFlags.Http);
RegisterCoreOption("session.save_handler", IniFlags.Supported | IniFlags.Local | IniFlags.Http);
RegisterCoreOption("session.name", IniFlags.Supported | IniFlags.Global | IniFlags.Http);
RegisterCoreOption("short_open_tag", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("sql.safe_mode", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("track_errors", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("unserialize_callback_func", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("upload_max_filesize", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("upload_tmp_dir", IniFlags.Supported | IniFlags.Global);
RegisterCoreOption("url_rewriter.tags", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("user_agent", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("user_dir", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("variables_order", IniFlags.Supported | IniFlags.Local);
RegisterCoreOption("warn_plus_overloading", IniFlags.Unsupported | IniFlags.Global);
RegisterCoreOption("xbithack", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("y2k_compliance", IniFlags.Unsupported | IniFlags.Local);
RegisterCoreOption("zend.ze1_compatibility_mode", IniFlags.Supported | IniFlags.Local);
}
#endregion
///
/// Tries to get, set, or restore an option given its PHP name and value.
///
/// The option name.
/// The option new value if applicable.
/// The action to be taken.
/// true , on failure.
/// The option old value.
/// The option not supported (Warning).
/// The option is read only but action demands write access (Warning).
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);
}
///
/// Formats a state of the specified option into .
///
/// The option's flag.
/// A default value of the option.
/// A script local value of the option.
/// An array containig keys "global_value" , "local_value" , "access" .
private static PhpArray FormatOptionState(IniFlags flags, object defaultValue, object localValue)
{
PhpArray result = new PhpArray(0, 3);
// default value:
result.Add("global_value", Convert.ObjectToString(defaultValue));
// local value:
result.Add("local_value", Convert.ObjectToString(localValue));
// accessibility:
result.Add("access", (int)((flags & IniFlags.Local) != 0 ? IniAccessability.Local : IniAccessability.Global));
return result;
}
///
/// Gets an array of options states formatted by .
///
/// An extension which options to retrieve.
/// A dictionary where to add options.
/// An array of option states.
/// Options already contained in are overwritten.
internal static IDictionary GetAllOptionStates(string extension, IDictionary result)
{
Debug.Assert(result != null);
LocalConfiguration local = Configuration.Local;
LocalConfiguration @default = Configuration.DefaultLocal;
foreach (KeyValuePair entry in options)
{
string name = entry.Key;
OptionDefinition def = entry.Value;
// skips configuration which don't belong to the specified extension:
if ((extension == null || extension == def.Extension))
{
if ((def.Flags & IniFlags.Supported) == 0)
{
result[name] = FormatOptionState(
def.Flags,
"Not Supported",
"Not Supported");
}
else if ((def.Flags & IniFlags.Http) != 0 && System.Web.HttpContext.Current == null)
{
result[name] = FormatOptionState(
def.Flags,
"Http Context Required",
"Http Context Required");
}
else
{
result[name] = FormatOptionState(
def.Flags,
def.Gsr(@default, name, null, IniAction.Get),
def.Gsr(local, name, null, IniAction.Get));
}
}
}
return result;
}
}
}
================================================
FILE: Source/ClassLibrary/PhpIniParser.CLR.cs
================================================
/*
Copyright (c) 2005-2006 Ladislav Prosek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
TODO:
Added possibility to access INI variables from within .ini file. (Andrei) (PHP 5.1.0)
*/
using System;
using System.Text;
using PHP.Core;
using System.Diagnostics;
namespace PHP.Library
{
///
/// Implements the INI file parsing functionality (see the parse_ini_file PHP function).
///
///
/// The parser is implemented by hand using the recursive descent (LL) approach.
/// Note (jakub): can be implemented using regular expressions ?
///
public sealed class PhpIniParser
{
///
/// Type of sorting.
///
public enum ScannerMode
{
/// Normal scanner mode.
[ImplementsConstant("INI_SCANNER_NORMAL")]
Normal = 0,
/// Raw scanner mode.
[ImplementsConstant("INI_SCANNER_RAW")]
Raw = 1,
};
#region parse_ini_string
///
/// Parse a configuration string.
///
/// The contents of the ini file being parsed.
/// The settings are returned as an associative array on success, and FALSE on failure.
[ImplementsFunction("parse_ini_string")]
[return: CastToFalse]
public static PhpArray ParseString(string ini)
{
return ParseString(ini, false, 0);
}
///
/// Parse a configuration string.
///
/// The contents of the ini file being parsed.
/// By setting the process_sections parameter to TRUE, you get a multidimensional array, with the section names and settings included. The default for process_sections is FALSE
/// The settings are returned as an associative array on success, and FALSE on failure.
[ImplementsFunction("parse_ini_string")]
[return: CastToFalse]
public static PhpArray ParseString(string ini, bool processSections)
{
return ParseString(ini, processSections, 0);
}
///
/// Parse a configuration string.
///
/// The contents of the ini file being parsed.
/// By setting the process_sections parameter to TRUE, you get a multidimensional array, with the section names and settings included. The default for process_sections is FALSE
/// Can either be INI_SCANNER_NORMAL (default) or INI_SCANNER_RAW. If INI_SCANNER_RAW is supplied, then option values will not be parsed.
/// The settings are returned as an associative array on success, and FALSE on failure.
[ImplementsFunction("parse_ini_string")]
[return: CastToFalse]
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;
}
#endregion
#region parse_ini_file
///
/// Parses an INI-style configuration file.
///
/// A file designation (may be a local file path, an URL, or whatever is accepted
/// by fopen ).
/// An array of key-value pairs read from the INI file.
/// Parse error (Warning).
///
/// Section names and keys are converted to integers if applicable. The parser recognizes special values
/// true , on and yes (converted to "1"); and false , off ,
/// no and none (converted to "").
///
[ImplementsFunction("parse_ini_file")]
[return: CastToFalse]
public static PhpArray ParseFile(string fileName)
{
return ParseFile(fileName, false, 0);
}
///
/// Parses an INI-style configuration file.
///
/// A file designation (may be a local file path, an URL, or whatever is accepted
/// by fopen ).
/// If true , the returned array contains nested arrays corresponding
/// to individual INI sections. If false , section names are completely disregarded and the returned
/// array contains directly key-value pairs from all sections.
/// An array of key-value pairs read from the INI file.
/// Parse error (Warning).
///
/// Section names and keys are converted to integers if applicable. The parser recognizes special values
/// true , on and yes (converted to "1"); and false , off ,
/// no and none (converted to "").
///
[ImplementsFunction("parse_ini_file")]
[return: CastToFalse]
public static PhpArray ParseFile(string fileName, bool processSections)
{
return ParseFile(fileName, processSections, 0);
}
///
/// Parses an INI-style configuration file.
///
/// A file designation (may be a local file path, an URL, or whatever is accepted
/// by fopen ).
/// If true , the returned array contains nested arrays corresponding
/// to individual INI sections. If false , section names are completely disregarded and the returned
/// array contains directly key-value pairs from all sections.
/// Can either be INI_SCANNER_NORMAL (default) = 0 or INI_SCANNER_RAW = 1. If INI_SCANNER_RAW is supplied, then option values will not be parsed.
/// An array of key-value pairs ( is false ) or an array
/// of arrays of key-value pairs ( is true ).
/// Parse error (Warning).
///
/// Section names and keys are converted to integers if applicable. The parser recognizes special values
/// true , on and yes (converted to "1"); and false , off ,
/// no and none (converted to "").
///
[ImplementsFunction("parse_ini_file")]
[return: CastToFalse]
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;
}
}
///
/// Parses an INI-style configuration file.
///
/// A stream referring to the file to parse. Should be open in binary mode.
/// Implementation of the parser callbacks invoked during parsing.
/// Parse error.
/// or is a null reference.
/// Stream is was not opened as binary.
public static void Parse(PhpStream stream, IParserCallbacks callbacks)
{
if (stream == null)
throw new ArgumentNullException("stream");
if (!stream.IsBinary)
throw new ArgumentException("Stream must be binary");
if (callbacks == null)
throw new ArgumentNullException("callbacks");
PhpIniParser parser = new PhpIniParser(stream, callbacks);
parser.TopLevel();
}
public static void Parse(string ini, IParserCallbacks callbacks)
{
if (ini == null)
throw new ArgumentNullException("ini");
if (callbacks == null)
throw new ArgumentNullException("callbacks");
PhpIniParser parser = new PhpIniParser(ini, callbacks);
parser.TopLevel();
}
#endregion
#region IParserCallbacks
///
/// Groups together methods that are called back by the parser during parsing.
///
public interface IParserCallbacks
{
///
/// Called when an INI section is encountered.
///
/// The section name (without the enclosing brackets). Either a string or
/// an integer.
void ProcessSection(object sectionName);
///
/// Called when an option (i.e. a key-value pair) is encountered.
///
/// The key. Either a string or an integer.
/// The value.
void ProcessOption(object key, string value);
///
/// Called when a token, which might possibly denote a constant, should be resolved.
///
/// The constant name.
/// The constant value. Should be either a string or an integer. Usually, when the
/// implementing method is unable to resolve the constant, it simply returns .
///
object GetConstantValue(string name);
}
#endregion
#region ArrayBuilder
///
/// Provides an array-building implementation of the the parser callbacks.
///
///
/// The format of the resulting complies to the parse_ini_file
/// return value.
///
public class ArrayBuilder : IParserCallbacks
{
#region Fields and Properties
///
/// The resulting array.
///
private PhpArray result;
///
/// The section currently being processed.
///
private PhpArray currentSection;
///
/// The used to lookup constants.
///
private ScriptContext scriptContext;
///
/// A flag that affects the way the is built up.
///
///
/// If true , the resulting array contains nested arrays corresponding to individual
/// INI sections. If false , section names are completely disregarded and the resulting
/// array contains directly key-value pairs from all sections.
///
private bool processSections;
///
/// Returns the resulting array.
///
public PhpArray Result
{
get
{ return result; }
}
#endregion
#region Construction
///
/// Creates a new .
///
/// The used to lookup constants or a null reference.
/// If true , the resulting array contains nested arrays
/// corresponding to individual INI sections. If false , section names are completely
/// disregarded and the resulting array contains directly key-value pairs from all sections.
/// is a null reference.
public ArrayBuilder(ScriptContext scriptContext, bool processSections)
{
this.scriptContext = scriptContext;
this.processSections = processSections;
result = new PhpArray();
currentSection = result;
}
#endregion
#region IParserCallbacks Members
///
/// Called when an INI section is encountered.
///
public void ProcessSection(object sectionName)
{
if (processSections)
{
currentSection = new PhpArray();
result[sectionName] = currentSection;
}
}
///
/// Called when an option (i.e. a key-value pair) is encountered.
///
public void ProcessOption(object key, string value)
{
currentSection[key] = value;
}
///
/// Called when a token, which might possibly denote a constant, should be resolved.
///
public object GetConstantValue(string name)
{
return scriptContext.GetConstantValue(name, true, true);
}
#endregion
}
#endregion
#region Tokens
///
/// Contains definition of (one-character) tokens that are relevant for INI files.
///
internal class Tokens
{
internal const char BracketOpen = '[';
internal const char BracketClose = ']';
internal const char EqualS = '=';
internal const char Quote = '"';
internal const char Semicolon = ';';
internal const char Or = '|';
internal const char And = '&';
internal const char Not = '!';
internal const char Neg = '~';
internal const char ParOpen = '(';
internal const char ParClose = ')';
internal const char EndOfLine = (char)0;
}
#endregion
#region ParseException
///
/// An exception thrown by the parser when an error occurs.
///
internal class ParseException : ApplicationException
{
///
/// Number of the line where the parse error occured.
///
private int lineNumber;
///
/// Returns the number of the line where the parse error occured.
///
public int LineNumber
{
get
{ return lineNumber; }
}
///
/// Creates a new .
///
/// Number of the line where the parse error occured.
public ParseException(int lineNumber)
{
this.lineNumber = lineNumber;
}
}
#endregion
#region Line getter
///
/// Interface for getting next line from the source.
///
private abstract class LineGetter
{
///
/// Get the next line from the source. Every line must ends with "\n".
///
/// Next line or null if you reach the end of the source.
public abstract string GetLine();
}
///
/// Getting next line from the PhpStream.
///
private sealed class LineGetterStream:LineGetter
{
///
/// A stream representing the input INI file, instead of text.
///
private PhpStream stream;
public LineGetterStream(PhpStream stream)
{
if (stream == null)
throw new ArgumentNullException("stream");
this.stream = stream;
}
public override string GetLine()
{
if (stream.Eof) return null;
return stream.ReadLine(-1, null);
}
}
///
/// Getting next line from the string.
///
private sealed class LineGetterString:LineGetter
{
private string[] lines;
private int nextLineIndex = 0;
public LineGetterString(string text)
{
if (text == null)
lines = ArrayUtils.EmptyStrings;
else
lines = text.Split(new char[] { '\n' });
}
public override string GetLine()
{
if (nextLineIndex < lines.Length)
return lines[nextLineIndex++] + "\n";
else
return null;
}
}
#endregion
#region Fields
///
/// Object getting next lines of INI source.
///
private LineGetter lineGetter;
///
/// Implementation of the parser callbacks invoked during parsing.
///
private IParserCallbacks callbacks;
///
/// The line read from that is currently being processed.
///
private string line;
///
/// Current line number.
///
private int lineNumber = 0;
///
/// The position within the current (0-based column).
///
///
/// line[linePos] denotes a lookahead symbol.
///
private int linePos;
#endregion
#region Construction
///
/// Creates a new operating on a given input stream.
///
/// The input stream. Should be open in binary mode.
/// Implementation of the parser callbacks invoked during parsing.
private PhpIniParser(PhpStream stream, IParserCallbacks callbacks)
{
this.lineGetter = new LineGetterStream(stream);
this.callbacks = callbacks;
}
///
/// Creates a new operating on a given input stream.
///
/// The input INI file content.
/// Implementation of the parser callbacks invoked during parsing.
private PhpIniParser(string text, IParserCallbacks callbacks)
{
this.lineGetter = new LineGetterString(text);
this.callbacks = callbacks;
}
#endregion
#region Parser helpers: LoadLine, LookAhead, Consume*, AddValue
///
/// Loads the next line from , and updates and .
///
/// true if a line was successfully loaded, false if end-of-file was reached.
private bool LoadLine()
{
line = lineGetter.GetLine();
linePos = 0;
if (line != null)
{
lineNumber++;
return true;
}
else
{
return false;
}
}
///
/// Returns the lookahead symbol which is either line[linePos] or
/// if there are no more characters in the current line.
///
private char LookAhead
{
get
{
return (linePos < line.Length ? line[linePos] : Tokens.EndOfLine);
}
}
///
/// Returns the lookahead symbol and cosumes it, i.e. advances the .
///
///
/// The original lookahead (before advancing).
private char Consume()
{
return (linePos < line.Length ? line[linePos++] : Tokens.EndOfLine);
}
///
/// Consumes the current lookahead symbol and compares it to a given character.
///
/// The character that is expected as the current lookahead symbol. If the characters
/// do not match, a is thrown.
private void Consume(char ch)
{
if (Consume() != ch) throw new ParseException(lineNumber);
}
///
/// Keeps consuming the current lookahead as long as it is categorized as a white space.
///
private void ConsumeWhiteSpace()
{
while (linePos < line.Length && Char.IsWhiteSpace(line, linePos)) linePos++;
}
///
/// Adds a key-value pair into a . If a value with the same key already exists,
/// a nested containing all values with this key is created.
///
/// The array to add the pair to.
/// The key.
/// The value.
private static void AddValue(PhpArray array, object key, string value)
{
if (!array.Contains(key)) array.Add(key, value);
else
{
object old_value = array[key];
PhpArray nested_array = old_value as PhpArray;
if (nested_array != null) nested_array.Add(value);
else
{
nested_array = new PhpArray();
nested_array.Add(old_value);
nested_array.Add(value);
array[key] = nested_array;
}
}
}
#endregion
#region Conversions
///
/// Converts a substring of the current into the array key representing a section name
/// (the interior of [ ] ) or an option name (on the left of = ).
///
/// The start index of the substring (within the current ).
/// The length of the substring.
/// The key found at the position given by and .
/// This may be either a string or an integer (decimal, hexadecimal and octal numbers are decoded).
private object SubstringToKey(int start, int length)
{
Debug.Assert(start >= 0 && start <= line.Length && (start + length) <= line.Length && length > 0);
int radix = 10;
if (line[start] == '0')
{
if (length > 2 && (line[start + 1] == 'x' || line[start + 1] == 'X'))
{
radix = 16;
// skip the "0x" prefix
start += 2;
length -= 2;
}
else radix = 8;
}
int pos = start;
int res = (int)Core.Convert.SubstringToLongStrict(line, length, radix, Int32.MaxValue, ref pos);
if (pos == start + length) return res;
else return line.Substring(start, length);
}
///
/// Converts a substring of the current into the array value representing an option
/// value (on the right of = ).
///
/// The start index of the substring (within the current ).
/// The length of the substring.
/// The value found at the position given by and .
/// This may be either a string or an integer (decimal numbers are decoded and constants are looked up).
///
private object SubstringToValue(int start, int length)
{
Debug.Assert(start >= 0 && start <= line.Length && (start + length) <= line.Length);
if (length == 0) return String.Empty;
// check for decimal number
int pos = start;
long res = Core.Convert.SubstringToLongInteger(line, length, ref pos);
if (pos == start + length)
{
int ires = unchecked((int)res);
if (ires == res) return ires; // is Int32 big enough?
return res;
}
string val = line.Substring(start, length);
// check for predefined "INI constants"
switch (val.ToUpper())
{
case "ON":
case "YES": return "1";
case "OFF":
case "NO":
case "NONE": return String.Empty;
default:
{
object obj = callbacks.GetConstantValue(val);
if (obj is int) return obj;
else return Core.Convert.ObjectToString(obj);
}
}
}
#endregion
#region Parser
///
/// Top level parsing method.
///
///
/// Reads and processes lines from the input stream until the end-of-file is reached. Invokes the
/// during parsing.
///
private void TopLevel()
{
StringBuilder val = null;
bool multiline = false;
object key = null;
while (LoadLine())
{
if (multiline)
{
// this is the next line of a multi-line value
val.Append(Value(ref multiline));
// it is the last line of multi-line value, save the entire value
if (!multiline) callbacks.ProcessOption(key, val.ToString());
}
else
{
ConsumeWhiteSpace();
char la = LookAhead;
// check for end-of-line and comment (line starting with ;)
if (la == Tokens.EndOfLine || la == Tokens.Semicolon) continue;
if (la == Tokens.BracketOpen)
{
// this line denotes a section
callbacks.ProcessSection(Section());
}
else if ((key = Key()) != null)
{
// this line denotes an ordinary entry
string s = Value(ref multiline);
if (!multiline) callbacks.ProcessOption(key, s);
else val = new StringBuilder(s);
}
}
}
// check for an unterminated multi-line value
if (multiline) throw new ParseException(lineNumber);
}
///
/// Parses an INI section ([<section_name><whitespace>]<whitespace> ).
///
/// The section name (either a string or an integer).
private object Section()
{
Consume(Tokens.BracketOpen);
//ConsumeWhiteSpace();
int start = linePos, end = linePos;
char ch;
while ((ch = Consume()) != Tokens.BracketClose)
{
if (ch == Tokens.EndOfLine) throw new ParseException(lineNumber);
// remember the last non-whitespace
/*if (!Char.IsWhiteSpace(ch)) */end = linePos; // include white-spaces too, as it is in PHP 5.3.1
}
ConsumeWhiteSpace();
// section name must not be empty and we must have reached end-of-line by now
if (end == start || (LookAhead != Tokens.EndOfLine && LookAhead != Tokens.Semicolon))
{
throw new ParseException(lineNumber);
}
return SubstringToKey(start, end - start);
}
///
/// Parses an INI option name (<option_name><whitespace>= ).
///
/// The option name (either a string or an integer).
private object Key()
{
int start = linePos, end = linePos, whitespace = start - 1;
char ch;
while ((ch = Consume()) != Tokens.EqualS)
{
if (ch == Tokens.EndOfLine || ch == Tokens.Semicolon) return null;
// remember the last non-whitespace and whitespace
if (!Char.IsWhiteSpace(ch))
{
end = linePos;
if (linePos == (whitespace + 1)) // new word starts, ignore the words before
start = linePos - 1;
}
else
{
whitespace = linePos;
}
}
// option name must not be empty
if (end == start) throw new ParseException(lineNumber);
return SubstringToKey(start, end - start);
}
///
/// Parses an INI option value ("<quoted_value> or <expression> ).
///
/// If true , next line of a multi-line value is expected; if false
/// otherwise. Receives true if more lines should follow and false if this was the last one
/// or the only one line.
/// The option value (always a string). If receives true ,
/// the return values is just a fragment and should be concatenated with subsequent return values to
/// obtain the entire option value.
private string Value(ref bool multiline)
{
if (multiline) return QuotedValue(out multiline);
// this is the first line (just after the =)
ConsumeWhiteSpace();
if (LookAhead == Tokens.Quote)
{
// quoted string starts here
Consume();
return QuotedValue(out multiline);
}
// no quotes - let's parse an expression
string result = Core.Convert.ObjectToString(Expression());
// must have reached end-of-line
if (LookAhead != Tokens.EndOfLine && LookAhead != Tokens.Semicolon) throw new ParseException(lineNumber);
return result;
}
///
/// Parses an INI option quoted value (<option_value> or
/// <option_value>"<whitespace> ).
///
/// Receives true if this value consists of more lines that
/// should follow (i.e. right quote not found yet), false otherwise.
/// The option value (always a string). If receives
/// true , the return values is just a fragment and should be concatenated with subsequent
/// return values to obtain the entire option value.
private string QuotedValue(out bool moreLinesFollow)
{
char ch;
int start = linePos;
// reading next line of a multiline quoted string
while ((ch = Consume()) != Tokens.EndOfLine)
{
if (ch == Tokens.Quote)
{
// right quote
moreLinesFollow = false;
int end = linePos - 1;
ConsumeWhiteSpace();
if (LookAhead != Tokens.EndOfLine && LookAhead != Tokens.Semicolon)
{
throw new ParseException(lineNumber);
}
return line.Substring(start, end - start);
}
}
// the string shall continue on the following line
moreLinesFollow = true;
return (start == 0 ? line : line.Substring(start));
}
///
/// Parses an INI option value expression (<literal>(&/|<literal>)* ).
///
/// The expression value (either a string or an integer).
private object Expression()
{
object result = Literal();
while (LookAhead != Tokens.EndOfLine && LookAhead != Tokens.Semicolon && LookAhead != Tokens.ParClose)
{
// expecting either & or |
char op = Consume();
if (op != Tokens.And && op != Tokens.Or) throw new ParseException(lineNumber);
// both operands must be converted to an integer
int lhs = Core.Convert.ObjectToInteger(result);
int rhs = Core.Convert.ObjectToInteger(Literal());
// perform the operation eagerly (like a stupid calculator)
result = (op == Tokens.And ? (int)(lhs & rhs) : (int)(lhs | rhs));
}
return result;
}
///
/// Parses an INI option value literal (<whitespace>(<expression>)<whitespace> ,
/// <whitespace>!<literal> , <whitespace>~<literal> or
/// <whitespace><literal_value><whitespace> ).
///
/// The literal value (either a string or an integer).
private object Literal()
{
ConsumeWhiteSpace();
switch (LookAhead)
{
case Tokens.ParOpen:
{
// literal ::= ( expression )
Consume();
object result = Expression();
Consume(Tokens.ParClose);
ConsumeWhiteSpace();
return result;
}
case Tokens.Not:
{
// literal ::= ! literal
Consume();
return (Core.Convert.ObjectToBoolean(Literal()) ? "0" : "1");
}
case Tokens.Neg:
{
// literal ::= ~ literal
Consume();
return (int)~Core.Convert.ObjectToInteger(Literal());
}
default:
{
// literal ::= alphanum
int start = linePos, end = start;
while (true)
{
char la = LookAhead;
switch (la)
{
case Tokens.EqualS:
case Tokens.Quote:
case Tokens.Or:
case Tokens.And:
case Tokens.Not:
case Tokens.Neg:
case Tokens.ParOpen:
case Tokens.ParClose:
case Tokens.Semicolon:
case Tokens.EndOfLine:
{
return SubstringToValue(start, end - start);
}
default:
{
Consume();
// remember the last non-whitespace
if (!Char.IsWhiteSpace(la)) end = linePos;
break;
}
}
}
}
}
}
}
#endregion
}
================================================
FILE: Source/ClassLibrary/PhpJson.cs
================================================
/*
Copyright (c) 2004-2010 Tomas Matousek, Jakub Misek.
The use and distribution terms for this software are contained in the file named License.txt,
which can be found in the root of the Phalanger distribution. By using this software
in any fashion, you are agreeing to be bound by the terms of this license.
You must not remove this notice from this software.
*/
/*
* TODO:
*
* JSON_NUMERIC_CHECK (integer)
* Encodes numeric strings as numbers. Available since PHP 5.3.3.
*
* JSON_BIGINT_AS_STRING (integer)
* Available since PHP 5.4.0.
*
* JSON_PRETTY_PRINT (integer)
* Use whitespace in returned data to format it. Available since PHP 5.4.0.
*
* JSON_UNESCAPED_SLASHES (integer)
* Don't escape /. Available since PHP 5.4.0.
* */
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using PHP.Core;
using PHP.Core.Reflection;
using PHP.Library;
#if SILVERLIGHT
using PHP.CoreCLR;
#else
using System.Web;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;
#endif
namespace PHP.Library
{
#region JSON PHP API
///
/// Classes implementing Countable can be used with the count() function.
///
[ImplementsType]
public interface JsonSerializable
{
///
/// Specify data which should be serialized to JSON.
///
/// Current provided by Phalanger.
/// Return data which should be serialized by json_encode() , see .
[ImplementsMethod]
[AllowReturnValueOverride]
object jsonSerialize(ScriptContext context);
}
///
/// JSON encoding/decoding functions.
///
///
[ImplementsExtension(LibraryDescriptor.ExtJson)]
public static class PhpJson
{
#region Constants
///
/// Values returned by json_last_error function.
///
public enum JsonLastError : int
{
///
/// No error has occurred
///
[ImplementsConstant("JSON_ERROR_NONE")]
JSON_ERROR_NONE = 0,
///
/// The maximum stack depth has been exceeded
///
[ImplementsConstant("JSON_ERROR_DEPTH")]
JSON_ERROR_DEPTH = 1,
///
/// Occurs with underflow or with the modes mismatch.
///
[ImplementsConstant("PHP_JSON_ERROR_STATE_MISMATCH")]
PHP_JSON_ERROR_STATE_MISMATCH = 2,
///
/// Control character error, possibly incorrectly encoded
///
[ImplementsConstant("JSON_ERROR_CTRL_CHAR")]
JSON_ERROR_CTRL_CHAR = 3,
///
/// Syntax error
///
[ImplementsConstant("JSON_ERROR_SYNTAX")]
JSON_ERROR_SYNTAX = 4,
///
///
///
[ImplementsConstant("JSON_ERROR_UTF8")]
JSON_ERROR_UTF8 = 5,
}
///
/// Options given to json_encode function.
///
public enum JsonEncodeOptions
{
///
/// No options specified.
///
Default = 0,
///
/// All < and > are converted to \u003C and \u003E.
///
[ImplementsConstant("JSON_HEX_TAG")]
JSON_HEX_TAG = 1,
///
/// All &s are converted to \u0026.
///
[ImplementsConstant("JSON_HEX_AMP")]
JSON_HEX_AMP = 2,
///
/// All ' are converted to \u0027.
///
[ImplementsConstant("JSON_HEX_APOS")]
JSON_HEX_APOS = 4,
///
/// All " are converted to \u0022.
///
[ImplementsConstant("JSON_HEX_QUOT")]
JSON_HEX_QUOT = 8,
///
/// Outputs an object rather than an array when a non-associative array is used. Especially useful when the recipient of the output is expecting an object and the array is empty.
///
[ImplementsConstant("JSON_FORCE_OBJECT")]
JSON_FORCE_OBJECT = 16,
///
/// Encodes numeric strings as numbers.
///
[ImplementsConstant("JSON_NUMERIC_CHECK")]
JSON_NUMERIC_CHECK = 32,
}
///
/// Options given to json_decode function.
///
public enum JsonDecodeOptions
{
Default = 0,
///
/// Big integers represent as strings rather than floats.
///
[ImplementsConstant("JSON_BIGINT_AS_STRING")]
JSON_BIGINT_AS_STRING = 1,
}
#endregion
#region json_encode, json_decode, json_last_error (CLR only)
#if !SILVERLIGHT
[ImplementsFunction("json_encode")]
public static PhpBytes Serialize(object value)
{
return PhpJsonSerializer.Default.Serialize(value, UnknownTypeDesc.Singleton);
}
[ImplementsFunction("json_encode")]
public static PhpBytes Serialize(object value, JsonEncodeOptions options)
{
return new PhpJsonSerializer(
new JsonFormatter.EncodeOptions()
{
ForceObject = (options & JsonEncodeOptions.JSON_FORCE_OBJECT) != 0,
HexAmp = (options & JsonEncodeOptions.JSON_HEX_AMP) != 0,
HexApos = (options & JsonEncodeOptions.JSON_HEX_APOS) != 0,
HexQuot = (options & JsonEncodeOptions.JSON_HEX_QUOT) != 0,
HexTag = (options & JsonEncodeOptions.JSON_HEX_TAG) != 0,
NumericCheck = (options & JsonEncodeOptions.JSON_NUMERIC_CHECK) != 0,
},
new JsonFormatter.DecodeOptions()
).Serialize(value, UnknownTypeDesc.Singleton);
}
[ImplementsFunction("json_decode")]
public static PhpReference Unserialize(PhpBytes json)
{
if (json == null)
return null;
return PhpJsonSerializer.Default.Deserialize(json, UnknownTypeDesc.Singleton);
}
[ImplementsFunction("json_decode")]
public static PhpReference Unserialize(PhpBytes json, bool assoc /* = false*/)
{
return Unserialize(json, assoc, 512, JsonDecodeOptions.Default);
}
[ImplementsFunction("json_decode")]
public static PhpReference Unserialize(PhpBytes json, bool assoc /* = false*/ , int depth /* = 512*/)
{
return Unserialize(json, assoc, depth, JsonDecodeOptions.Default);
}
///
///
///
///
/// When TRUE, returned object's will be converted into associative array s.
/// User specified recursion depth.
///
///
[ImplementsFunction("json_decode")]
public static PhpReference Unserialize(PhpBytes json, bool assoc /* = false*/ , int depth /* = 512*/ , JsonDecodeOptions options /* = 0 */)
{
if (json == null)
return null;
return new PhpJsonSerializer(
new JsonFormatter.EncodeOptions(),
new JsonFormatter.DecodeOptions()
{
Assoc = assoc,
Depth = depth,
BigIntAsString = (options & JsonDecodeOptions.JSON_BIGINT_AS_STRING) != 0
}
).Deserialize(json, UnknownTypeDesc.Singleton);
}
[ImplementsFunction("json_last_error")]
public static int GetLastError()
{
JsonLastError err;
var ctx = ScriptContext.CurrentContext;
if (ctx.Properties.TryGetProperty(out err) == false)
err = JsonLastError.JSON_ERROR_NONE;
return (int)err;
}
#endif
#endregion
}
#endregion
#region JsonFormatter
///
/// Implements a JSON formatter (serializer).
///
public sealed class JsonFormatter : IFormatter
{
#region Tokens
///
/// Contains definition of (one-character) tokens that constitute PHP serialized data.
///
internal class Tokens
{
internal const char ObjectOpen = '{';
internal const char ObjectClose = '}';
internal const char ItemsSeparator = ',';
internal const char PropertyKeyValueSeparator = ':';
internal const char Quote = '"';
internal const char Escape = '\\';
internal const string EscapedNewLine = @"\n";
internal const string EscapedCR = @"\r";
internal const string EscapedTab = @"\t";
internal const string EscapedBackspace = @"\b";
internal const string EscapedQuote = "\\\"";
internal const string EscapedReverseSolidus = @"\\";
internal const string EscapedSolidus = @"\/";
internal const string EscapedFormFeed = @"\f";
internal const string EscapedUnicodeChar = @"\u"; // 4-digit number follows
internal const char ArrayOpen = '[';
internal const char ArrayClose = ']';
internal const string NullLiteral = "null";
internal const string TrueLiteral = "true";
internal const string FalseLiteral = "false";
}
#endregion
///
/// Implements the serialization functionality. Serializes an object, or graph of objects
/// with the given root to the provided .
///
internal class ObjectWriter
{
#region Fields and Properties
private readonly ScriptContext/*!*/ context;
///
/// The stream writer to write serialized data to.
///
private readonly StreamWriter/*!*/ writer;
///
/// Options.
///
private readonly EncodeOptions/*!*/ encodeOptions;
///
/// The encoding to be used when writing and reading the serialization stream.
///
private Encoding encoding;
///
/// Stack of objects being currently serialized. Used to avoid stack overflow and to properly outputs "recursion_detected" warning.
///
private List recursionStack = null;
#endregion
#region Construction
///
/// Creates a new with a given .
///
/// The current .
/// The writer to write serialized data to.
/// Encoding options.
/// Encoding used for reading PhpBytes.
internal ObjectWriter(ScriptContext/*!*/ context, StreamWriter/*!*/ writer, EncodeOptions/*!*/encodeOptions, Encoding encoding)
{
Debug.Assert(context != null && writer != null && encodeOptions != null);
this.context = context;
this.writer = writer;
this.encodeOptions = encodeOptions;
this.encoding = encoding;
}
#endregion
#region Recursion
///
/// Push currently serialized array or object to the stack to prevent recursion.
///
///
///
private bool PushObject(object/*!*/obj)
{
Debug.Assert(obj != null);
if (recursionStack == null)
recursionStack = new List(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;
}
///
/// Pop the serialized object from the stack.
///
private void PopObject()
{
Debug.Assert(recursionStack != null);
recursionStack.RemoveAt(recursionStack.Count - 1);
}
#endregion
#region Serialize, Write*
///
/// Serializes an object or graph of objects to .
///
/// The object (graph) to serialize.
internal void Serialize(object graph)
{
if (graph == null)
{
WriteNull();
return;
}
switch (Type.GetTypeCode(graph.GetType()))
{
case TypeCode.Boolean:
WriteBoolean((bool)graph); break;
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Decimal:
writer.Write(graph.ToString());
break;
case TypeCode.Single:
writer.Write(graph.ToString());
break;
case TypeCode.Double:
writer.Write((double)graph);
break;
case TypeCode.Char:
WriteString(graph.ToString());
break;
case TypeCode.String:
WriteString((string)graph);
break;
case TypeCode.Object:
{
PhpArray array;
if ((array = graph as PhpArray) != null)
{
if (PushObject(graph))
{
WriteArray(array);
PopObject();
}
else
WriteNull();
break;
}
DObject obj;
JsonSerializable jsonserializeble;
if ((jsonserializeble = graph as JsonSerializable) != null)
{
var retval = jsonserializeble.jsonSerialize(context);
if ((obj = (retval as DObject)) != null) // Handle the case where jsonSerialize() returns itself.
WriteDObject(obj);
else
Serialize(retval);
break;
}
if ((obj = graph as DObject) != null)
{
if (PushObject(graph))
{
WriteDObject(obj);
PopObject();
}
else
WriteNull();
break;
}
PhpReference reference;
if ((reference = graph as PhpReference) != null)
{
Serialize(reference.Value);
break;
}
PhpBytes bytes;
if ((bytes = graph as PhpBytes) != null)
{
WriteString(((IPhpConvertible)bytes).ToString());
break;
}
PhpString str;
if ((str = graph as PhpString) != null)
{
WriteString(str.ToString());
break;
}
if (graph is PhpResource)
{
WriteUnsupported(PhpResource.PhpTypeName);
break;
}
goto default;
}
default:
WriteUnsupported(graph.GetType().FullName);
break;
}
}
///
/// Serializes null and throws an exception.
///
///
private void WriteUnsupported(string TypeName)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("serialization_unsupported_type", TypeName));
WriteNull();
}
///
/// Serializes Null .
///
private void WriteNull()
{
writer.Write(Tokens.NullLiteral);
}
///
/// Serializes a bool value.
///
/// The value.
private void WriteBoolean(bool value)
{
writer.Write(value ? Tokens.TrueLiteral : Tokens.FalseLiteral);
}
#region encoding strings
///
/// Determines if given character is printable character. Otherwise it must be encoded.
///
///
///
private static bool CharIsPrintable(char c)
{
return
(c <= 0x7f) && // ASCII
(!char.IsControl(c)) && // not control
(!(c >= 9 && c <= 13)); // not BS, HT, LF, Vertical Tab, Form Feed, CR
}
///
/// Determines if given character should be encoded.
///
///
///
private bool CharShouldBeEncoded(char c)
{
switch (c)
{
case '\n':
case '\r':
case '\t':
case '/':
case Tokens.Escape:
case '\b':
case '\f':
case Tokens.Quote:
return true;
case '\'':
return encodeOptions.HexApos;
case '<':
return encodeOptions.HexTag;
case '>':
return encodeOptions.HexTag;
case '&':
return encodeOptions.HexAmp;
default:
return !CharIsPrintable(c);
}
}
///
/// Convert 16b character into json encoded character.
///
/// The full string to be encoded.
/// The index of character to be encoded. Can be increased if more characters are processed.
/// The encoded part of string, from value[i] to value[i after method call]
private string EncodeStringIncremental(string value, ref int i)
{
char c = value[i];
switch (c)
{
case '\n': return (Tokens.EscapedNewLine);
case '\r': return (Tokens.EscapedCR);
case '\t': return (Tokens.EscapedTab);
case '/': return (Tokens.EscapedSolidus);
case Tokens.Escape: return (Tokens.EscapedReverseSolidus);
case '\b': return (Tokens.EscapedBackspace);
case '\f': return (Tokens.EscapedFormFeed);
case Tokens.Quote: return (encodeOptions.HexQuot ? (Tokens.EscapedUnicodeChar + "0022") : Tokens.EscapedQuote);
case '\'': return (encodeOptions.HexApos ? (Tokens.EscapedUnicodeChar + "0027") : "'");
case '<': return (encodeOptions.HexTag ? (Tokens.EscapedUnicodeChar + "003C") : "<");
case '>': return (encodeOptions.HexTag ? (Tokens.EscapedUnicodeChar + "003E") : ">");
case '&': return (encodeOptions.HexAmp ? (Tokens.EscapedUnicodeChar + "0026") : "&");
default:
{
if (CharIsPrintable(c))
{
int start = i++;
for (; i < value.Length && !CharShouldBeEncoded(value[i]); ++i)
;
return value.Substring(start, (i--) - start); // accumulate characters, mostly it is entire string value (faster)
}
else
{
return (Tokens.EscapedUnicodeChar + ((int)c).ToString("X4"));
}
}
}
}
#endregion
///
/// Serializes JSON string.
///
/// The string.
private void WriteString(string value)
{
if (encodeOptions.NumericCheck)
{
int i;
long l;
double d;
var result = PHP.Core.Convert.StringToNumber(value, out i, out l, out d);
if ((result & Core.Convert.NumberInfo.IsNumber) != 0)
{
if ((result & Core.Convert.NumberInfo.Integer) != 0) writer.Write(i.ToString());
if ((result & Core.Convert.NumberInfo.LongInteger) != 0) writer.Write(l.ToString());
if ((result & Core.Convert.NumberInfo.Double) != 0) writer.Write(d.ToString());
return;
}
}
StringBuilder strVal = new StringBuilder(value.Length + 2);
strVal.Append(Tokens.Quote);
for (int i = 0; i < value.Length; ++i)
{
strVal.Append(EncodeStringIncremental(value, ref i));
}
strVal.Append(Tokens.Quote);
writer.Write(strVal.ToString());
}
#region formatting JSON objects / arrays
private void WriteJsonObject(IEnumerable> items)
{
writer.Write(Tokens.ObjectOpen);
bool bFirst = true;
foreach (var x in items)
{
if (bFirst) bFirst = false;
else writer.Write(Tokens.ItemsSeparator);
WriteString(x.Key);
writer.Write(Tokens.PropertyKeyValueSeparator);
Serialize(x.Value);
}
writer.Write(Tokens.ObjectClose);
}
private void WriteJsonArray(IEnumerable items)
{
writer.Write(Tokens.ArrayOpen);
bool bFirst = true;
foreach (var x in items)
{
if (bFirst) bFirst = false;
else writer.Write(Tokens.ItemsSeparator);
Serialize(x);
}
writer.Write(Tokens.ArrayClose);
}
private IEnumerable> JsonObjectProperties(PhpArray/*!*/value)
{
foreach (var x in value)
yield return new KeyValuePair(x.Key.ToString(), x.Value);
}
private IEnumerable> JsonObjectProperties(DObject/*!*/value, bool avoidPicName)
{
foreach (KeyValuePair pair in Serialization.EnumerateSerializableProperties(value))
{
if (avoidPicName && pair.Key == __PHP_Incomplete_Class.ClassNameFieldName)
{
// skip the __PHP_Incomplete_Class_Name field
continue;
}
yield return pair;
}
}
#endregion
///