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); })); }
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); }
/// <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); } }
/// <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); }
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; }
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; }
/// <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); } }
/// <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)); }
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); }
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); }
/// <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; }
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); }
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); }
/// <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); }
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); }
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); }
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; }
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; }
/// <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); } }
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; }
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; }
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; }
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); }); }
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); }
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); }
public PhpUserStream(Context ctx, UserStreamWrapper /*!*/ openingWrapper, StreamAccessOptions accessOptions, string openedPath, StreamContext context) : base(ctx, openingWrapper, accessOptions, openedPath, context) { }
public abstract PhpStream Open(Context ctx, ref string path, string mode, StreamOpenOptions options, StreamContext context);
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); }
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)); }
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); }
/// <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); }
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 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; }
//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); }
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); }
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; }
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; }
/// <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; }
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; }