Resource type used for associating additional options with stream wrappers.
Stream Contexts are stored in a Resource to save useless deep-copying of the contained constant array.
Наследование: Pchp.Core.PhpResource
Пример #1
0
        public override StatStruct Stat(string path, StreamStatOptions options, StreamContext context, bool streamStat)
        {
            StatStruct invalid = new StatStruct();

            invalid.st_size = -1;
            Debug.Assert(path != null);

            // Note: path is already absolute w/o the scheme, the permissions have already been checked.
            return(PhpPath.HandleFileSystemInfo(invalid, path, (p) =>
            {
                FileSystemInfo info = null;

                info = new DirectoryInfo(p);
                if (!info.Exists)
                {
                    info = new FileInfo(p);
                    if (!info.Exists)
                    {
                        return invalid;
                    }
                }

                return BuildStatStruct(info, info.Attributes, p);
            }));
        }
Пример #2
0
        public override bool Unlink(string path, StreamUnlinkOptions options, StreamContext context)
        {
            Debug.Assert(path != null);
            Debug.Assert(Path.IsPathRooted(path));

            try
            {
                File.Delete(path);
                return(true);
            }
            catch (DirectoryNotFoundException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_unlink_file_not_found, FileSystemUtils.StripPassword(path));
            }
            catch (UnauthorizedAccessException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
            }
            catch (IOException e)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_unlink_io_error, FileSystemUtils.StripPassword(path), PhpException.ToErrorMessage(e.Message));
            }
            catch (Exception)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_unlink_error, FileSystemUtils.StripPassword(path));
            }

            return(false);
        }
Пример #3
0
        /// <summary>
        /// Open client socket.
        /// </summary>
        public static PhpResource stream_socket_server(Context ctx, string localSocket, out int errno, out string errstr, SocketOptions flags, PhpResource context)
        {
            // defaults:
            errno  = 0;
            errstr = string.Empty;

            var sc = StreamContext.GetValid(context);

            if (sc == null)
            {
                return(null);
            }

            //
            int port = 0;

            if (TryParseSocketAddr(localSocket, out _, out var protocol, ref port, out var address))
            {
                try
                {
                    var socket = new Socket(address.AddressFamily, SocketType.Stream, protocol);
                    socket.Bind(new IPEndPoint(address, port));
                    //socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.MaxConnections) // Not Supported
                    socket.Listen(512); // NOTE: a default backlog should be used

                    return(new SocketStream(ctx, socket, localSocket, sc));
                }
                catch (SocketException e)
                {
                    errno  = e.ErrorCode;
                    errstr = e.Message;
                    return(null);
                }
            }
Пример #4
0
        /// <summary>
        /// Get the StreamContext from a handle representing either an isolated context or a PhpStream.
        /// </summary>
        /// <param name="stream_or_context">The PhpResource of either PhpStream or StreamContext type.</param>
        /// <param name="createContext">If true then a new context will be created at the place of <see cref="StreamContext.Default"/>.</param>
        /// <returns>The respective StreamContext.</returns>
        /// <exception cref="PhpException">If the first argument is neither a stream nor a context.</exception>
        private static StreamContext FromResource(PhpResource stream_or_context, bool createContext)
        {
            if ((stream_or_context != null) && (stream_or_context.IsValid))
            {
                // Get the context out of the stream
                PhpStream stream = stream_or_context as PhpStream;
                if (stream != null)
                {
                    Debug.Assert(stream.Context != null);
                    stream_or_context = stream.Context;
                }

                StreamContext context = stream_or_context as StreamContext;
                if (context == StreamContext.Default)
                {
                    if (!createContext)
                    {
                        return(null);
                    }
                    context = new StreamContext();
                }
                return(context);
            }
            PhpException.Throw(PhpError.Warning, Core.Resources.ErrResources.context_expected);
            return(null);
        }
Пример #5
0
 public SocketStream(Context ctx, Socket socket, string openedPath, StreamContext context)
     : base(ctx, null, StreamAccessOptions.Read | StreamAccessOptions.Write, openedPath, context)
 {
     Debug.Assert(socket != null);
     this.Socket          = socket;
     this.IsWriteBuffered = false;
     this.eof             = false;
     this.IsReadBuffered  = false;
 }
Пример #6
0
 public SocketStream(Context ctx, Socket socket, string openedPath, StreamContext context, bool isAsync = false)
     : base(ctx, null, StreamAccessOptions.Read | StreamAccessOptions.Write, openedPath, context)
 {
     Debug.Assert(socket != null);
     this.socket = socket;
     this.IsWriteBuffered = false;
     this.eof = false;
     this.isAsync = isAsync;
     this.IsReadBuffered = false;
 }
Пример #7
0
        /// <summary>
        /// Open client socket.
        /// </summary>
        public static PhpResource stream_socket_client(Context ctx, string remoteSocket, out int errno, out string errstr, double timeout, SocketOptions flags, PhpResource context)
        {
            var sc = StreamContext.GetValid(context);

            if (sc != null)
            {
                //SplitSocketAddressPort(ref remoteSocket, out port);
                return(Connect(ctx, remoteSocket, 0, out errno, out errstr, timeout, flags, sc));
            }
            else
            {
                errno  = -1;
                errstr = null;
                return(null);
            }
        }
Пример #8
0
        /// <summary>
        /// Open client socket.
        /// </summary>
        public static PhpResource stream_socket_server(Context ctx, string localSocket, out int errno, out string errstr, SocketOptions flags, PhpResource context)
        {
            StreamContext sc = StreamContext.GetValid(context);

            if (sc == null)
            {
                errno  = -1;
                errstr = null;
                return(null);
            }

            int port = 0;

            //SplitSocketAddressPort(ref localSocket, out port);
            return(Connect(ctx, localSocket, port, out errno, out errstr, Double.NaN, flags, sc));
        }
Пример #9
0
        public override string[] Listing(string path, StreamListingOptions options, StreamContext context)
        {
            Debug.Assert(path != null);
            Debug.Assert(Path.IsPathRooted(path));

            try
            {
                string[] listing = Directory.GetFileSystemEntries(path);
                bool     root    = Path.GetPathRoot(path) == path;
                int      index   = root ? 0 : 2;
                string[] rv      = new string[listing.Length + index];

                // Remove the absolute path information (PHP returns only filenames)
                int pathLength = path.Length;
                if (path[pathLength - 1] != Path.DirectorySeparatorChar)
                {
                    pathLength++;
                }

                // Check for the '.' and '..'; they should be present
                if (!root)
                {
                    rv[0] = ".";
                    rv[1] = "..";
                }
                for (int i = 0; i < listing.Length; i++)
                {
                    rv[index++] = listing[i].Substring(pathLength);
                }
                return(rv);
            }
            catch (DirectoryNotFoundException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_bad_directory, FileSystemUtils.StripPassword(path));
            }
            catch (UnauthorizedAccessException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
            }
            catch (Exception e)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_error, FileSystemUtils.StripPassword(path), e.Message);
            }
            return(null);
        }
Пример #10
0
        private static PhpArray GetContextData(PhpResource stream_or_context)
        {
            // Always create a new context if there is the Default one.
            StreamContext context = FromResource(stream_or_context, true);

            // Now create the data if this is a "lazy context".
            if (context != null)
            {
                if (context.Data == null)
                {
                    context.Data = new PhpArray(4);
                }

                return(context.Data);
                // Now it is OK.
            }
            return(null);
        }
Пример #11
0
 /// <remarks>
 /// <seealso cref="StreamUnlinkOptions"/> for the list of additional options.
 /// </remarks>
 public virtual bool Unlink(string path, StreamUnlinkOptions options, StreamContext context)
 {
     // int (*unlink)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); 
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Unlink");
     return false;
 }
Пример #12
0
 public virtual bool RemoveDirectory(string path, StreamRemoveDirectoryOptions options, StreamContext context)
 {
     // int (*stream_rmdir)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Rmdir");
     return(false);
 }
Пример #13
0
 public virtual string[] Listing(string path, StreamListingOptions options, StreamContext context)
 {
     // php_stream *(*dir_opener)(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Opendir");
     return(null);
 }
Пример #14
0
 /// <remarks>
 /// <seealso cref="StreamUnlinkOptions"/> for the list of additional options.
 /// </remarks>
 public virtual bool Unlink(string path, StreamUnlinkOptions options, StreamContext context)
 {
     // int (*unlink)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Unlink");
     return(false);
 }
Пример #15
0
 public override bool RemoveDirectory(string path, StreamRemoveDirectoryOptions options, StreamContext context)
 {
     try
     {
         // Deletes the directory (but not the contents - must be empty)
         Directory.Delete(path, false);
         return(true);
     }
     catch (UnauthorizedAccessException)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
     }
     catch (IOException)
     {
         // Directory not empty.
         PhpException.Throw(PhpError.Warning, ErrResources.stream_rmdir_io_error, FileSystemUtils.StripPassword(path));
     }
     return(false);
 }
Пример #16
0
 public override bool Rename(string fromPath, string toPath, StreamRenameOptions options, StreamContext context)
 {
     try
     {
         File.Move(fromPath, toPath);
         return(true);
     }
     catch (UnauthorizedAccessException)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(fromPath));
     }
     catch (IOException)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_rename_file_exists, FileSystemUtils.StripPassword(fromPath), FileSystemUtils.StripPassword(toPath));
     }
     catch (Exception e)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_error, FileSystemUtils.StripPassword(fromPath), e.Message);
     }
     return(false);
 }
Пример #17
0
 public virtual bool Rename(string fromPath, string toPath, StreamRenameOptions options, StreamContext context)
 {
     // int (*rename)(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Rename");
     return false;
 }
Пример #18
0
 public NativeStream(Context ctx, Stream nativeStream, StreamWrapper openingWrapper, StreamAccessOptions accessOptions, string openedPath, StreamContext context)
     : base(ctx, openingWrapper, accessOptions, openedPath, context)
 {
     Debug.Assert(nativeStream != null);
     this.stream = nativeStream;
 }
Пример #19
0
        /// <summary>
        /// Open client socket.
        /// </summary>
        public static PhpResource stream_socket_server(Context ctx, string localSocket, out int errno, out string errstr, SocketOptions flags, PhpResource context)
        {
            // defaults:
            errno  = 0;
            errstr = string.Empty;

            var sc = StreamContext.GetValid(context);

            if (sc == null)
            {
                return(null);
            }

            //
            int port = 0;

            if (TryParseSocketAddr(localSocket, out _, out var protocol, ref port, out var address))
            {
                try
                {
                    var socket  = new Socket(address.AddressFamily, SocketType.Stream, protocol);
                    var backlog = 512;

                    var socket_opts = sc.GetOptions("socket");
                    if (socket_opts != null)
                    {
                        var pairenum = socket_opts.GetFastEnumerator();
                        while (pairenum.MoveNext())
                        {
                            var pair    = pairenum.Current;
                            var optname = pair.Key.String;
                            if (optname == null) // numerical option?
                            {
                                continue;
                            }

                            //if (optname.Equals("bindto", StringComparison.OrdinalIgnoreCase))
                            //{

                            //}
                            //else
                            if (optname.Equals("backlog", StringComparison.OrdinalIgnoreCase))
                            {
                                backlog = pair.Value.ToInt();
                            }
                            //else if (optname.Equals("ipv6_v6only", StringComparison.OrdinalIgnoreCase))
                            //{

                            //}
                            else if (optname.Equals("so_reuseaddr", StringComparison.OrdinalIgnoreCase))
                            {
                                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, pair.Value.ToInt());
                            }
                            //else if (optname.Equals("so_reuseport", StringComparison.OrdinalIgnoreCase))
                            //{
                            //    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReusePort)
                            //}
                            else if (optname.Equals("so_broadcast", StringComparison.OrdinalIgnoreCase))
                            {
                                socket.EnableBroadcast = pair.Value.ToBoolean();
                            }
                            else if (optname.Equals("tcp_nodelay", StringComparison.OrdinalIgnoreCase))
                            {
                                socket.NoDelay = pair.Value.ToBoolean();
                            }
                            else if (optname.Equals("tcp_keepalive", StringComparison.OrdinalIgnoreCase))
                            {
                                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, pair.Value.ToBoolean());
                            }
                            else
                            {
                                // unknown option
                                PhpException.InvalidArgument(optname, nameof(stream_socket_server));
                            }
                        }
                    }

                    socket.Bind(new IPEndPoint(address, port));
                    //socket.NoDelay = false;
                    //socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.MaxConnections) // Not Supported
                    socket.Listen(backlog); // NOTE: a default backlog should be used

                    return(new SocketStream(ctx, socket, localSocket, sc));
                }
                catch (SocketException e)
                {
                    errno  = e.ErrorCode;
                    errstr = e.Message;
                    return(null);
                }
            }
Пример #20
0
 public override bool Rename(string fromPath, string toPath, StreamRenameOptions options, StreamContext context)
 {
     try
     {
         File.Move(fromPath, toPath);
         return true;
     }
     catch (UnauthorizedAccessException)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(fromPath));
     }
     catch (IOException)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_rename_file_exists, FileSystemUtils.StripPassword(fromPath), FileSystemUtils.StripPassword(toPath));
     }
     catch (System.Exception e)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_error, FileSystemUtils.StripPassword(fromPath), e.Message);
     }
     return false;
 }
Пример #21
0
        public override string[] Listing(string path, StreamListingOptions options, StreamContext context)
        {
            Debug.Assert(path != null);
            Debug.Assert(Path.IsPathRooted(path));

            try
            {
                string[] listing = Directory.GetFileSystemEntries(path);
                bool root = Path.GetPathRoot(path) == path;
                int index = root ? 0 : 2;
                string[] rv = new string[listing.Length + index];

                // Remove the absolute path information (PHP returns only filenames)
                int pathLength = path.Length;
                if (path[pathLength - 1] != Path.DirectorySeparatorChar) pathLength++;

                // Check for the '.' and '..'; they should be present
                if (!root)
                {
                    rv[0] = ".";
                    rv[1] = "..";
                }
                for (int i = 0; i < listing.Length; i++)
                {
                    rv[index++] = listing[i].Substring(pathLength);
                }
                return rv;
            }
            catch (DirectoryNotFoundException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_bad_directory, FileSystemUtils.StripPassword(path));
            }
            catch (UnauthorizedAccessException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
            }
            catch (System.Exception e)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_error, FileSystemUtils.StripPassword(path), e.Message);
            }
            return null;
        }
Пример #22
0
        public override bool Unlink(string path, StreamUnlinkOptions options, StreamContext context)
        {
            Debug.Assert(path != null);
            Debug.Assert(Path.IsPathRooted(path));

            try
            {
                File.Delete(path);
                return true;
            }
            catch (DirectoryNotFoundException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_unlink_file_not_found, FileSystemUtils.StripPassword(path));
            }
            catch (UnauthorizedAccessException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
            }
            catch (IOException e)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_unlink_io_error, FileSystemUtils.StripPassword(path), PhpException.ToErrorMessage(e.Message));
            }
            catch (System.Exception)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_unlink_error, FileSystemUtils.StripPassword(path));
            }

            return false;
        }
Пример #23
0
        public override StatStruct Stat(string path, StreamStatOptions options, StreamContext context, bool streamStat)
        {
            StatStruct invalid = new StatStruct();
            invalid.st_size = -1;
            Debug.Assert(path != null);

            // Note: path is already absolute w/o the scheme, the permissions have already been checked.
            return PhpPath.HandleFileSystemInfo(invalid, path, (p) =>
            {
                FileSystemInfo info = null;

                info = new DirectoryInfo(p);
                if (!info.Exists)
                {
                    info = new FileInfo(p);
                    if (!info.Exists)
                    {
                        return invalid;
                    }
                }

                return BuildStatStruct(info, info.Attributes, p);
            });
        }
Пример #24
0
 public virtual StatStruct Stat(string path, StreamStatOptions options, StreamContext context, bool streamStat)
 {
     // int (*url_stat)(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
     return StatUnsupported();
 }
        //public static PhpArray stream_socket_pair(ProtocolFamily protocolFamily, SocketType type, ProtocolType protocol)
        //{
        //    PhpException.FunctionNotSupported();
        //    return null;
        //}

        #endregion

        #region Connect

        /// <summary>
        /// Opens a new SocketStream
        /// </summary>
        internal static SocketStream Connect(Context ctx, string remoteSocket, int port, out int errno, out string errstr, double timeout, SocketOptions flags, StreamContext /*!*/ context)
        {
            errno  = 0;
            errstr = null;

            if (remoteSocket == null)
            {
                PhpException.ArgumentNull("remoteSocket");
                return(null);
            }

            // TODO: extract schema (tcp://, udp://) and port from remoteSocket
            // Uri uri = Uri.TryCreate(remoteSocket);
            ProtocolType protocol = ProtocolType.Tcp;

            if (remoteSocket.Contains("://"))
            {
                String[] separator   = { "://" };
                String[] socketParts = remoteSocket.Split(separator, 2, StringSplitOptions.None);
                switch (socketParts[0])
                {
                case "udp":
                    protocol = ProtocolType.Udp;
                    break;

                case "tcp":
                default:
                    protocol = ProtocolType.Tcp;
                    break;
                }
                remoteSocket = socketParts[1];
            }

            if (remoteSocket.Contains(":"))
            {
                Char[]   separator   = { ':' };
                String[] socketParts = remoteSocket.Split(separator, 2, StringSplitOptions.None);
                remoteSocket = socketParts[0];

                int result = 0;
                if (socketParts[1] != "" && int.TryParse(socketParts[1], out result) &&
                    (0 < result && result < 65536))
                {
                    port = result;
                }
            }

            if (double.IsNaN(timeout))
            {
                timeout = ctx.Configuration.Core.DefaultSocketTimeout;
            }

            // TODO:
            if (flags != SocketOptions.None && flags != SocketOptions.Asynchronous)
            {
                PhpException.ArgumentValueNotSupported("flags", (int)flags);
            }

            try
            {
                // workitem 299181; for remoteSocket as IPv4 address it results in IPv6 address
                //IPAddress address = System.Net.Dns.GetHostEntry(remoteSocket).AddressList[0];

                IPAddress address;
                if (!IPAddress.TryParse(remoteSocket, out address)) // if remoteSocket is not a valid IP address then lookup the DNS
                {
                    var addresses = System.Net.Dns.GetHostAddressesAsync(remoteSocket).Result;
                    if (addresses != null && addresses.Length != 0)
                    {
                        address = addresses[0];
                    }
                    else
                    {
                        throw new ArgumentException(nameof(remoteSocket));
                    }
                }

                var socket = new Socket(address.AddressFamily, SocketType.Stream, protocol);
                if (!socket.ConnectAsync(address, port).Wait((int)(timeout * 1000)))
                {
                    Debug.Assert(!socket.Connected);
                    PhpException.Throw(PhpError.Warning, string.Format(Resources.LibResources.socket_open_timeout, FileSystemUtils.StripPassword(remoteSocket)));
                    return(null);
                }

                // socket.Connect(new IPEndPoint(address, port));
                return(new SocketStream(ctx, socket, remoteSocket, context, (flags & SocketOptions.Asynchronous) == SocketOptions.Asynchronous));
            }
            catch (SocketException e)
            {
                errno  = (int)e.SocketErrorCode;
                errstr = e.Message;
            }
            catch (System.Exception e)
            {
                errno  = -1;
                errstr = e.Message;
            }

            PhpException.Throw(PhpError.Warning, string.Format(Resources.LibResources.socket_open_error, FileSystemUtils.StripPassword(remoteSocket), errstr));
            return(null);
        }
Пример #26
0
        public override bool MakeDirectory(string path, int accessMode, StreamMakeDirectoryOptions options, StreamContext context)
        {
            if ((path == null) || (path == string.Empty))
            {
                PhpException.Throw(PhpError.Warning, ErrResources.path_argument_empty);
                return(false);
            }

            try
            {
                // Default Framework MakeDirectory is RECURSIVE, check for other intention.
                if ((options & StreamMakeDirectoryOptions.Recursive) == 0)
                {
                    int pos = path.Length - 1;
                    if (path[pos] == Path.DirectorySeparatorChar)
                    {
                        pos--;
                    }
                    pos = path.LastIndexOf(Path.DirectorySeparatorChar, pos);
                    if (pos <= 0)
                    {
                        PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_make_root, FileSystemUtils.StripPassword(path));
                        return(false);
                    }

                    // Parent must exist if not recursive.
                    string parent = path.Substring(0, pos);
                    if (!Directory.Exists(parent))
                    {
                        PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_make_parent, FileSystemUtils.StripPassword(path));
                        return(false);
                    }
                }

                // Creates the whole path
                Directory.CreateDirectory(path);
                return(true);
            }
            catch (UnauthorizedAccessException)
            {
                // The caller does not have the required permission.
                PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_access_denied, FileSystemUtils.StripPassword(path));
            }
            catch (IOException)
            {
                // The directory specified by path is read-only or is not empty.
                PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_error, FileSystemUtils.StripPassword(path));
            }
            catch (Exception e)
            {
                // The specified path is invalid, such as being on an unmapped drive ...
                PhpException.Throw(PhpError.Warning, ErrResources.stream_error, FileSystemUtils.StripPassword(path), e.Message);
            }
            return(false);
        }
Пример #27
0
 public PhpUserStream(Context ctx, UserStreamWrapper /*!*/ openingWrapper, StreamAccessOptions accessOptions, string openedPath, StreamContext context)
     : base(ctx, openingWrapper, accessOptions, openedPath, context)
 {
 }
Пример #28
0
 public abstract PhpStream Open(Context ctx, ref string path, string mode, StreamOpenOptions options, StreamContext context);
Пример #29
0
        public override PhpStream Open(Context ctx, ref string path, string mode, StreamOpenOptions options, StreamContext context)
        {
            Debug.Assert(path != null);
            //Debug.Assert(PhpPath.IsLocalFile(path));

            // Get the File.Open modes from the mode string
            FileMode fileMode;
            FileAccess fileAccess;
            StreamAccessOptions ao;

            if (!ParseMode(mode, options, out fileMode, out fileAccess, out ao)) return null;

            // Open the native stream
            FileStream stream = null;
            try
            {
                // stream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite);
                stream = new FileStream(path, fileMode, fileAccess, FileShare.ReadWrite | FileShare.Delete);
            }
            catch (FileNotFoundException)
            {
                // Note: There may still be an URL in the path here.
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_not_exists, FileSystemUtils.StripPassword(path));

                return null;
            }
            catch (IOException e)
            {
                if ((ao & StreamAccessOptions.Exclusive) > 0)
                {
                    PhpException.Throw(PhpError.Warning, ErrResources.stream_file_exists, FileSystemUtils.StripPassword(path));
                }
                else
                {
                    PhpException.Throw(PhpError.Warning, ErrResources.stream_file_io_error, FileSystemUtils.StripPassword(path), PhpException.ToErrorMessage(e.Message));
                }
                return null;
            }
            catch (UnauthorizedAccessException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
                return null;
            }
            catch (System.Exception)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_invalid, FileSystemUtils.StripPassword(path));
                return null;
            }

            if ((ao & StreamAccessOptions.SeekEnd) > 0)
            {
                // Read/Write Append is not supported. Seek to the end of file manually.
                stream.Seek(0, SeekOrigin.End);
            }

            if ((ao & StreamAccessOptions.Temporary) > 0)
            {
                // Set the file attributes to Temporary too.
                File.SetAttributes(path, FileAttributes.Temporary);
            }

            return new NativeStream(ctx, stream, this, ao, path, context);
        }
Пример #30
0
        public override PhpStream Open(Context ctx, ref string path, string mode, StreamOpenOptions options, StreamContext context)
        {
            Debug.Assert(path != null);
            //Debug.Assert(PhpPath.IsLocalFile(path));

            // Get the File.Open modes from the mode string
            FileMode            fileMode;
            FileAccess          fileAccess;
            StreamAccessOptions ao;

            if (!ParseMode(mode, options, out fileMode, out fileAccess, out ao))
            {
                return(null);
            }

            // Open the native stream
            FileStream stream = null;

            try
            {
                // stream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite);
                stream = new FileStream(path, fileMode, fileAccess, FileShare.ReadWrite | FileShare.Delete);
            }
            catch (FileNotFoundException)
            {
                // Note: There may still be an URL in the path here.
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_not_exists, FileSystemUtils.StripPassword(path));

                return(null);
            }
            catch (IOException e)
            {
                if ((ao & StreamAccessOptions.Exclusive) > 0)
                {
                    PhpException.Throw(PhpError.Warning, ErrResources.stream_file_exists, FileSystemUtils.StripPassword(path));
                }
                else
                {
                    PhpException.Throw(PhpError.Warning, ErrResources.stream_file_io_error, FileSystemUtils.StripPassword(path), PhpException.ToErrorMessage(e.Message));
                }
                return(null);
            }
            catch (UnauthorizedAccessException)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
                return(null);
            }
            catch (Exception)
            {
                PhpException.Throw(PhpError.Warning, ErrResources.stream_file_invalid, FileSystemUtils.StripPassword(path));
                return(null);
            }

            if ((ao & StreamAccessOptions.SeekEnd) > 0)
            {
                // Read/Write Append is not supported. Seek to the end of file manually.
                stream.Seek(0, SeekOrigin.End);
            }

            if ((ao & StreamAccessOptions.Temporary) > 0)
            {
                // Set the file attributes to Temporary too.
                File.SetAttributes(path, FileAttributes.Temporary);
            }

            return(new NativeStream(ctx, stream, this, ao, path, context));
        }
Пример #31
0
 public NativeStream(Context ctx, Stream nativeStream, StreamWrapper openingWrapper, StreamAccessOptions accessOptions, string openedPath, StreamContext context)
     : base(ctx, openingWrapper, accessOptions, openedPath, context)
 {
     Debug.Assert(nativeStream != null);
     this.stream = nativeStream;
 }
Пример #32
0
 public virtual bool Rename(string fromPath, string toPath, StreamRenameOptions options, StreamContext context)
 {
     // int (*rename)(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Rename");
     return(false);
 }
Пример #33
0
        /// <summary>
        /// Openes a PhpStream using the appropriate StreamWrapper.
        /// </summary>
        /// <param name="ctx">Current runtime context.</param>
        /// <param name="path">URI or filename of the resource to be opened.</param>
        /// <param name="mode">A file-access mode as passed to the PHP function.</param>
        /// <param name="options">A combination of <see cref="StreamOpenOptions"/>.</param>
        /// <param name="context">A valid StreamContext. Must not be <c>null</c>.</param>
        /// <returns></returns>
        public static PhpStream Open(Context ctx, string path, string mode, StreamOpenOptions options, StreamContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            Debug.Assert(ctx != null);

            StreamWrapper wrapper;
            if (!PhpStream.ResolvePath(ctx, ref path, out wrapper, CheckAccessMode.FileMayExist, (CheckAccessOptions)options))
                return null;

            return wrapper.Open(ctx, ref path, mode, options, context);

        }
Пример #34
0
 public virtual StatStruct Stat(string path, StreamStatOptions options, StreamContext context, bool streamStat)
 {
     // int (*url_stat)(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);
     return(StatUnsupported());
 }
Пример #35
0
 public override bool RemoveDirectory(string path, StreamRemoveDirectoryOptions options, StreamContext context)
 {
     try
     {
         // Deletes the directory (but not the contents - must be empty)
         Directory.Delete(path, false);
         return true;
     }
     catch (UnauthorizedAccessException)
     {
         PhpException.Throw(PhpError.Warning, ErrResources.stream_file_access_denied, FileSystemUtils.StripPassword(path));
     }
     catch (IOException)
     {
         // Directory not empty.
         PhpException.Throw(PhpError.Warning, ErrResources.stream_rmdir_io_error, FileSystemUtils.StripPassword(path));
     }
     return false;
 }
Пример #36
0
 public abstract PhpStream Open(Context ctx, ref string path, string mode, StreamOpenOptions options, StreamContext context);
Пример #37
0
        //public static PhpArray stream_socket_pair(ProtocolFamily protocolFamily, SocketType type, ProtocolType protocol)
        //{
        //    PhpException.FunctionNotSupported();
        //    return null;
        //}

        #endregion

        #region Connect

        /// <summary>
        /// Opens a new SocketStream
        /// </summary>
        internal static PhpStream Connect(Context ctx, string remoteSocket, int port, out int errno, out string errstr, double timeout, SocketOptions flags, StreamContext /*!*/ context)
        {
            errno  = 0;
            errstr = null;

            if (remoteSocket == null)
            {
                PhpException.ArgumentNull("remoteSocket");
                return(null);
            }

            bool IsSsl = false;

            // TODO: extract schema (tcp://, udp://) and port from remoteSocket
            // Uri uri = Uri.TryCreate(remoteSocket);
            const string protoSeparator = "://";
            var          protocol       = ProtocolType.Tcp;
            var          protoIdx       = remoteSocket.IndexOf(protoSeparator, StringComparison.Ordinal);

            if (protoIdx >= 0)
            {
                var protoStr = remoteSocket.AsSpan(0, protoIdx);
                if (protoStr.Equals("udp".AsSpan(), StringComparison.Ordinal))
                {
                    protocol = ProtocolType.Udp;
                }
                else if (protoStr.Equals("ssl".AsSpan(), StringComparison.Ordinal))
                {
                    // use SSL encryption
                    IsSsl = true;
                }

                remoteSocket = remoteSocket.Substring(protoIdx + protoSeparator.Length);
            }

            var colonIdx = remoteSocket.IndexOf(':');

            if (colonIdx >= 0)
            {
                var portStr = remoteSocket.AsSpan(colonIdx + 1);
                if (portStr.Length != 0 &&
                    int.TryParse(portStr.ToString(), out var n) &&    // TODO: (perf) ReadOnlySpan<char>
                    n > 0 && n <= 0xffff)
                {
                    port = n;
                }

                remoteSocket = remoteSocket.Remove(colonIdx);
            }

            if (double.IsNaN(timeout))
            {
                timeout = ctx.Configuration.Core.DefaultSocketTimeout;
            }

            // TODO:
            if (flags != SocketOptions.None && flags != SocketOptions.Asynchronous)
            {
                PhpException.ArgumentValueNotSupported("flags", (int)flags);
            }

            try
            {
                // workitem 299181; for remoteSocket as IPv4 address it results in IPv6 address
                //IPAddress address = System.Net.Dns.GetHostEntry(remoteSocket).AddressList[0];

                IPAddress address;
                if (!IPAddress.TryParse(remoteSocket, out address)) // if remoteSocket is not a valid IP address then lookup the DNS
                {
                    var addresses = System.Net.Dns.GetHostAddressesAsync(remoteSocket).Result;
                    if (addresses != null && addresses.Length != 0)
                    {
                        address = addresses[0];
                    }
                    else
                    {
                        throw new ArgumentException(nameof(remoteSocket));
                    }
                }

                var socket = new Socket(address.AddressFamily, SocketType.Stream, protocol);

                // socket.Connect(new IPEndPoint(address, port));
                if (socket.ConnectAsync(address, port).Wait((int)(timeout * 1000)))
                {
                    if (IsSsl)
                    {
                        var options = context.GetOptions("ssl");
                        if (options != null)
                        {
                            // TODO: provide parameters based on context[ssl][verify_peer|verify_peer_name|allow_self_signed|cafile]

                            options.TryGetValue("verify_peer", out var vpvalue);
                            options.TryGetValue("verify_peer_name", out var vpnvalue);
                            options.TryGetValue("allow_self_signed", out var assvalue);
                            options.TryGetValue("cafile", out var cafilevalue);

                            Debug.WriteLineIf(vpvalue.IsSet && !vpvalue, "ssl: verify_peer not supported");
                            Debug.WriteLineIf(vpnvalue.IsSet && (bool)vpnvalue, "ssl: verify_peer_name not supported");
                            Debug.WriteLineIf(assvalue.IsSet && !assvalue, "ssl: allow_self_signed not supported");
                            Debug.WriteLineIf(cafilevalue.IsSet, "ssl: cafile not supported");
                        }

                        var sslstream = new SslStream(new NetworkStream(socket, System.IO.FileAccess.ReadWrite, true), false,
                                                      null, //(sender, certificate, chain, sslPolicyErrors) => true,
                                                      null, //(sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => ??,
                                                      EncryptionPolicy.AllowNoEncryption);

                        sslstream.AuthenticateAsClient(remoteSocket);

                        return(new NativeStream(ctx, sslstream, null, StreamAccessOptions.Read | StreamAccessOptions.Write, remoteSocket, context)
                        {
                            IsWriteBuffered = false,
                            IsReadBuffered = false,
                        });
                    }
                    else
                    {
                        return(new SocketStream(ctx, socket, remoteSocket, context, (flags & SocketOptions.Asynchronous) != 0));
                    }
                }
                else
                {
                    Debug.Assert(!socket.Connected);
                    PhpException.Throw(PhpError.Warning, string.Format(Resources.LibResources.socket_open_timeout, FileSystemUtils.StripPassword(remoteSocket)));
                    return(null);
                }
            }
            catch (SocketException e)
            {
                errno  = (int)e.SocketErrorCode;
                errstr = e.Message;
            }
            catch (System.Exception e)
            {
                errno  = -1;
                errstr = e.Message;
            }

            PhpException.Throw(PhpError.Warning, string.Format(Resources.LibResources.socket_open_error, FileSystemUtils.StripPassword(remoteSocket), errstr));
            return(null);
        }
Пример #38
0
        public override PhpStream Open(Context ctx, ref string path, string mode, StreamOpenOptions options, StreamContext context)
        {
            int level       = -1;
            var deflateMode = DeflateFilterMode.Normal;

            #region Parse mode options
            // PHP just looks whether there are mode flags in the mode string (skip the first character)
            // last flag is the valid one

            for (int i = 1; i < mode.Length; i++)
            {
                if (Char.IsDigit(mode[i]))
                {
                    level = mode[i] - '0';
                }
                else if (mode[i] == 'f')
                {
                    deflateMode = DeflateFilterMode.Filter;
                }
                else if (mode[i] == 'h')
                {
                    deflateMode = DeflateFilterMode.Huffman;
                }
            }

            #endregion

            #region Path correction

            if (path.StartsWith("compress.zlib://"))
            {
                path = path.Substring(16);
            }
            else if (path.StartsWith("zlib:"))
            {
                path = path.Substring(5);
            }

            #endregion

            var stream = PhpStream.Open(ctx, path, mode, options);

            if (stream != null && stream.CanRead)
            {
                stream.AddFilter(new GzipUncompressionFilter(), FilterChainOptions.Read);
            }

            if (stream != null && stream.CanWrite)
            {
                stream.AddFilter(new GzipCompresionFilter(level, deflateMode), FilterChainOptions.Write);
            }

            return(stream);
        }
Пример #39
0
 public virtual string[] Listing(string path, StreamListingOptions options, StreamContext context)
 {
     // php_stream *(*dir_opener)(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Opendir");
     return null;
 }
 public NativeStream(IEncodingProvider enc_provider, Stream nativeStream, StreamWrapper openingWrapper, StreamAccessOptions accessOptions, string openedPath, StreamContext context)
     : base(enc_provider, openingWrapper, accessOptions, openedPath, context)
 {
     Debug.Assert(nativeStream != null);
     this.stream = nativeStream;
 }
Пример #41
0
 public virtual bool RemoveDirectory(string path, StreamRemoveDirectoryOptions options, StreamContext context)
 {
     // int (*stream_rmdir)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);    
     PhpException.Throw(PhpError.Warning, ErrResources.wrapper_op_unsupported, "Rmdir");
     return false;
 }
Пример #42
0
        /// <summary>
        /// PhpStream is created by a StreamWrapper together with the
        /// encapsulated RawStream (the actual file opening is handled 
        /// by the wrapper).
        /// </summary>
        /// <remarks>
        /// This class newly implements the auto-remove behavior too
        /// (see <see cref="StreamAccessOptions.Temporary"/>).
        /// </remarks>
        /// <param name="ctx">Runtime context.</param>
        /// <param name="openingWrapper">The parent instance.</param>
        /// <param name="accessOptions">The additional options parsed from the <c>fopen()</c> mode.</param>
        /// <param name="openedPath">The absolute path to the opened resource.</param>
        /// <param name="context">The stream context passed to fopen().</param>
        public PhpStream(Context ctx, StreamWrapper openingWrapper, StreamAccessOptions accessOptions, string openedPath, StreamContext context)
            : base(PhpStreamTypeName)
        {
            Debug.Assert(ctx != null);
            Debug.Assert(context != null);

            _ctx = ctx;
            _context = context;

            this.Wrapper = openingWrapper;
            this.OpenedPath = openedPath;

            // Stream modifiers (defined in open-time).
            this.Options = accessOptions;

            // Allocate the text conversion filters for this stream.
            if ((accessOptions & StreamAccessOptions.UseText) > 0)
            {
                if ((accessOptions & StreamAccessOptions.Read) > 0)
                {
                    textReadFilter = new TextReadFilter();
                }
                if ((accessOptions & StreamAccessOptions.Write) > 0)
                {
                    textWriteFilter = new TextWriteFilter();
                }
            }

            // this.readTimeout = ScriptContext.CurrentContext.Config.FileSystem.DefaultSocketTimeout;
        }
Пример #43
0
        public override bool MakeDirectory(string path, int accessMode, StreamMakeDirectoryOptions options, StreamContext context)
        {
            if ((path == null) || (path == string.Empty))
            {
                PhpException.Throw(PhpError.Warning, ErrResources.path_argument_empty);
                return false;
            }

            try
            {
                // Default Framework MakeDirectory is RECURSIVE, check for other intention. 
                if ((options & StreamMakeDirectoryOptions.Recursive) == 0)
                {
                    int pos = path.Length - 1;
                    if (path[pos] == Path.DirectorySeparatorChar) pos--;
                    pos = path.LastIndexOf(Path.DirectorySeparatorChar, pos);
                    if (pos <= 0)
                    {
                        PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_make_root, FileSystemUtils.StripPassword(path));
                        return false;
                    }

                    // Parent must exist if not recursive.
                    string parent = path.Substring(0, pos);
                    if (!Directory.Exists(parent))
                    {
                        PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_make_parent, FileSystemUtils.StripPassword(path));
                        return false;
                    }
                }

                // Creates the whole path
                Directory.CreateDirectory(path);
                return true;
            }
            catch (UnauthorizedAccessException)
            {
                // The caller does not have the required permission.
                PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_access_denied, FileSystemUtils.StripPassword(path));
            }
            catch (IOException)
            {
                // The directory specified by path is read-only or is not empty.
                PhpException.Throw(PhpError.Warning, ErrResources.stream_directory_error, FileSystemUtils.StripPassword(path));
            }
            catch (System.Exception e)
            {
                // The specified path is invalid, such as being on an unmapped drive ...
                PhpException.Throw(PhpError.Warning, ErrResources.stream_error, FileSystemUtils.StripPassword(path), e.Message);
            }
            return false;
        }