/// <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; }
/// <summary> /// Merges the path with the current working directory /// to get a canonicalized absolute pathname representing the same file. /// </summary> /// <remarks> /// This method is an analogy of <c>main/safe_mode.c: php_checkuid</c>. /// Looks for the file in the <c>include_path</c> and checks for <c>open_basedir</c> restrictions. /// </remarks> /// <param name="ctx">Current runtime context.</param> /// <param name="path">An absolute or relative path to a file.</param> /// <param name="wrapper">The wrapper found for the specified file or <c>null</c> if the path resolution fails.</param> /// <param name="mode">The checking mode of the <see cref="CheckAccess"/> method (file, directory etc.).</param> /// <param name="options">Additional options for the <see cref="CheckAccess"/> method.</param> /// <returns><c>true</c> if all the resolution and checking passed without an error, <b>false</b> otherwise.</returns> /// <exception cref="PhpException">Security violation - when the target file /// lays outside the tree defined by <c>open_basedir</c> configuration option.</exception> public static bool ResolvePath(Context ctx, ref string path, out StreamWrapper wrapper, CheckAccessMode mode, CheckAccessOptions options) { // Path will contain the absolute path without file:// or the complete URL; filename is the relative path. string filename, scheme = GetSchemeInternal(path, out filename); wrapper = StreamWrapper.GetWrapper(ctx, scheme, (StreamOptions)options); if (wrapper == null) return false; if (wrapper.IsUrl) { // Note: path contains the whole URL, filename the same without the scheme:// portion. // What to check more? } else if (scheme != "php") { try { // Filename contains the original path without the scheme:// portion, check for include path. bool isInclude = false; if ((options & CheckAccessOptions.UseIncludePath) > 0) { isInclude = CheckIncludePath(ctx, filename, ref path); } // Path will now contain an absolute path (either to an include or actual directory). if (!isInclude) { path = Path.GetFullPath(Path.Combine(ctx.WorkingDirectory, filename)); } } catch (System.Exception) { if ((options & CheckAccessOptions.Quiet) == 0) PhpException.Throw(PhpError.Warning, ErrResources.stream_filename_invalid, FileSystemUtils.StripPassword(path)); return false; } // NOTE: we should let OS & Security configuration to decide //var global_config = Configuration.Global; //// Note: extensions check open_basedir too -> double check.. //if (!global_config.SafeMode.IsPathAllowed(path)) //{ // if ((options & CheckAccessOptions.Quiet) == 0) // PhpException.Throw(PhpError.Warning, ErrResources.open_basedir_effect, path, global_config.SafeMode.GetAllowedPathPrefixesJoin()); // return false; //} // Replace all '/' with '\'. // path = path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); Debug.Assert( path.IndexOf(Path.AltDirectorySeparatorChar) == -1 || (Path.AltDirectorySeparatorChar == Path.DirectorySeparatorChar), // on Mono, so ignore it string.Format("'{0}' should not contain '{1}' char.", path, Path.AltDirectorySeparatorChar)); // The file wrapper expects an absolute path w/o the scheme, others expect the scheme://url. if (scheme != "file") { path = String.Format("{0}://{1}", scheme, path); } } return true; }
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; }
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> ///// Insert a new wrapper to the list of user StreamWrappers. ///// </summary> ///// <remarks> ///// Each script has its own set of user StreamWrappers registered ///// by stream_wrapper_register() stored in the ScriptContext. ///// </remarks> ///// <param name="protocol">The scheme portion of URLs this wrapper can handle.</param> ///// <param name="wrapper">An instance of the corresponding StreamWrapper descendant.</param> ///// <returns>True if succeeds, false if the scheme is already registered.</returns> //public static bool RegisterUserWrapper(string protocol, StreamWrapper wrapper) //{ // // Userwrappers may be initialized to null // if (UserWrappers == null) // CreateUserWrapperTable(); // UserWrappers.Add(protocol, wrapper); // return true; //} /// <summary> /// Register a new system wrapper /// </summary> /// <param name="wrapper">An instance of the corresponding StreamWrapper descendant.</param> /// <returns>True if succeeds, false if the scheme is already registered.</returns> public static bool RegisterSystemWrapper(StreamWrapper wrapper) { if (!systemStreamWrappers.ContainsKey(wrapper.Scheme)) { systemStreamWrappers.Add(wrapper.Scheme, wrapper); return true; } return false; }
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; }