# final class \SmartFileSystem
{ } ::

Class: SmartFileSystem - provides the File System Access functions.
This class enforces the use of RELATIVE PATHS to force using correct path access in a web environment application.
Relative paths must be relative to the web application folder as folder: `some-folder/` or file: `some-folder/my-file.txt`.
Absolute paths are denied by internal checks as they are NOT SAFE in a Web Application from the security point of view ...
Also the backward path access like `../some-file-or-folder` is denied from the above exposed reasons.
Files and Folders must contain ONLY safe characters as: `[a-z] [A-Z] [0-9] _ - . @ #` ; folders can also contain slashes `/` (as path separators); no spaces are allowed in paths !!
All operations in this class are safe against TOC/TOU (time-of-check to time-of-use) expoits

- Language: PHP
- Located at: lib/core/lib_filesys.php
- Package: Application:FileSystem
- Namespace: \
- Class Name: SmartFileSystem
- Version: v.20240119
- Depends: classes: Smart, SmartEnvironment ; constants: SMART_FRAMEWORK_CHMOD_DIRS, SMART_FRAMEWORK_CHMOD_FILES
- Hints: This class can handle thread concurency to the filesystem in a safe way by using the LOCK_EX (lock exclusive) feature on each file written / appended thus making also reads to be mostly safe ; Reads can also use optional shared locking if needed
- Usage: static object: Class::method() - This class provides only STATIC methods

## class Methods

public static function fix_dir_chmod ( string $dir_name ) {} :: BOOL
@return: {BOOLEAN} TRUE if success, FALSE if not
@param: {STRING} $dir_name: The relative path to the directory name to fix chmod for (folder)
Fix the Directory CHMOD as defined in SMART_FRAMEWORK_CHMOD_DIRS.
This provides a safe way to fix chmod on directories (symlinks or files will be skipped) ...
public static function fix_file_chmod ( string $file_name ) {} :: BOOL
@return: {BOOLEAN} TRUE if success, FALSE if not
@param: {STRING} $file_name: The relative path to the file name to fix chmod for (file)
Fix the File CHMOD as defined in SMART_FRAMEWORK_CHMOD_FILES.
This provides a safe way to fix chmod on files (symlinks or dirs will be skipped) ...
public static function get_file_size ( string $file_name ) {} :: INT
@return: {INTEGER} 0 (zero) if file does not exists or invalid file type ; the file size in bytes for the rest of cases
@param: {STRING} $file_name: The relative path to the file name to get the size for (file or symlink)
GET the File Size in Bytes. If invalid file or not file or broken link will return 0 (zero).
This provides a safe way to get the file size (works also with symlinks) ...
public static function get_file_ctime ( string $file_name ) {} :: INT
@return: {INTEGER} 0 (zero) if file does not exists or invalid file type ; the file creation timestamp for the rest of cases
@param: {STRING} $file_name: The relative path to the file name to get the creation timestamp for (file or symlink)
GET the File Creation Timestamp. If invalid file or not file or broken link will return 0 (zero).
This provides a safe way to get the file creation timestamp (works also with symlinks) ...
public static function get_file_mtime ( string $file_name ) {} :: INT
@return: {INTEGER} 0 (zero) if file does not exists or invalid file type ; the file modification timestamp for the rest of cases
@param: {STRING} $file_name: The relative path to the file name to get the last modification timestamp for (file or symlink)
GET the File Modification Timestamp. If invalid file or not file or broken link will return 0 (zero).
This provides a safe way to get the file modification timestamp (works also with symlinks) ...
public static function get_file_md5_checksum ( string $file_name ) {} :: STRING
@return: {STRING} empty string if file does not exists or invalid file type ; the file md5 checksum for the rest of cases
@param: {STRING} $file_name: The relative path to the file name to get the last modification timestamp for (file or symlink)
GET the File MD5 Checksum. If invalid file or not file or broken link will return empty string.
This provides a safe way to get the md5_file checksum (works also with symlinks) ...
public static function is_type_dir ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if directory (folder), FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path is a directory (folder) type and exists.
This provides a safe way to check if a path is directory (folder) (works also with symlinks) ...
public static function is_type_file ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if file, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path is a file type and exists.
This provides a safe way to check if a path is file (works also with symlinks) ...
public static function is_type_link ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if symlink, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path directory or file is a symlink and exists. Will not check if symlink is broken (not check if symlink origin exists)
This provides a safe way to check if a path is symlink (may be broken or not) ...
public static function have_access_read ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if readable, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path directory or file exists and is readable (includding if a symlink).
This provides a safe way to check if a path is readable ...
public static function have_access_write ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if writable, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path directory or file exists and is writable (includding if a symlink).
This provides a safe way to check if a path is writable ...
public static function have_access_executable ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if file, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or symlink)
CHECK if a path is an executable file.
This provides a safe way to check if a file path is executable (works also with symlinks) ...
public static function path_exists ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if exists, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path exists (includding if a symlink or a broken symlink).
This provides a safe way to check if a path exists because using only PHP file_exists() will return false if the path is a broken symlink ...
public static function path_real_exists ( string $path ) {} :: BOOL
@return: {BOOLEAN} TRUE if exists, FALSE if not
@param: {STRING} $path: The relative path name to be checked (file or dir or symlink)
CHECK if a path real exists (excluding if a symlink or a broken symlink).
This provides a way to check if a path exists but only if take in consideration that the path may be a broken symlink that will return false if checked
For normal checking if a path exists use SmartFileSystem::path_exists().
Use this in special cases where you need to check if a path that may be a broken link ...
public static function read ( string $file_name, int $file_len = 0, string $markchmod = "no", string $safelock = "no", bool $allow_protected_paths = false ) {} :: STRING
@return: {STRING} The file contents (or a part of file contents if $file_len parameter is used) ; if the file does not exists will return an empty string
@param: {STRING} $file_name: The relative path of file to be read (can be a symlink to a file)
@param: {INTEGER+} $file_len: DEFAULT is 0 (zero) ; If zero will read the entire file ; If > 0 (ex: 100) will read only the first 100 bytes fro the file or less if the file size is under 100 bytes
@param: {YES/NO} $markchmod: DEFAULT is 'no' ; If 'yes' will force a chmod (as defined in SMART_FRAMEWORK_CHMOD_FILES) on the file before trying to read to ensure consistent chmod on all accesible files.
@param: {YES/NO} $safelock: DEFAULT is 'no' ; If 'yes' will try to get a read shared lock on file prior to read ; If cannot lock the file will return empty string to avoid partial content read where reading a file that have intensive writes (there is always a risk to cannot achieve the lock ... there is no perfect scenario for intensive file operations in multi threaded environments ...)
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe READ A FILE contents. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/file.ext).
It can read the full file content or just a part, starting from the zero offset (ex: first 100 bytes only)
IT CANNOT BE USED TO ACCESS TEMPORARY UPLOAD FILES WHICH ARE ALWAYS ABSOLUTE PATHS. To access uploaded files use the method SmartFileSystem::read_uploaded()
public static function write ( string $file_name, string $file_content = "", string $write_mode = "w", bool $allow_protected_paths = false ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $file_name: The relative path of file to be written (can be an existing symlink to a file)
@param: {STRING} $file_content: DEFAULT is '' ; The content string to be written to the file (binary safe)
@param: {ENUM} $write_mode: DEFAULT is 'w' Write (If file exists then overwrite. If the file does not exist create it) ; If 'a' will use Write-Append by appending the content to a file which can exists or not.
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe CREATE AND/OR WRITE/APPEND CONTENTS TO A FILE. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/file.ext).
It can create a new file or overwrite an existing file.
It also can to write append to a file.
The file will be chmod standardized, as set in SMART_FRAMEWORK_CHMOD_FILES.
public static function write_if_not_exists ( string $file_name, string $file_content, string $y_chkcompare = "no", bool $allow_protected_paths = false ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $file_name: The relative path of file to be written (can be an existing symlink to a file)
@param: {STRING} $file_content: DEFAULT is '' ; The content string to be written to the file (binary safe)
@param: {YES/NO} $y_chkcompare: DEFAULT is 'no' ; If 'yes' will check the existing fiile contents and will overwrite if different than the passed contents in $file_content
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe CREATE OR WRITE TO A FILE IF NOT EXISTS OR CONTENT DIFFERS. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/file.ext).
It can only create a new file or overwrite an existing file if the content does not match.
The file will be chmod standardized, as set in SMART_FRAMEWORK_CHMOD_FILES.
public static function copy ( string $file_name, string $newlocation, bool $overwrite_destination = false, bool $check_copy_contents = true, bool $allow_protected_paths = false ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $file_name: The relative path of file to be copied (can be a symlink to a file)
@param: {STRING} $newlocation: The relative path of the destination file (where to copy)
@param: {BOOLEAN} $overwrite_destination: DEFAULT is FALSE ; If set to FALSE will FAIL if destination file exists ; If set to TRUE will overwrite the file destination if exists
@param: {BOOLEAN} $check_copy_contents: DEFAULT is TRUE ; If set to TRUE (safe mode) will compare the copied content from the destination file with the original file content using sha1-file checksums ; If set to FALSE (non-safe mode) will not do this comparison check (but may save a big amount of time when working with very large files)
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe COPY A FILE TO A DIFFERENT LOCATION. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/file.ext).
It will copy the file from source location to a destination location (includding across partitions).
The destination file will be chmod standardized, as set in SMART_FRAMEWORK_CHMOD_FILES.
public static function rename ( string $file_name, string $newlocation, bool $overwrite_destination = false, bool $allow_protected_paths = false ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $file_name: The relative path of file to be renamed or moved (can be a symlink to a file)
@param: {STRING} $newlocation: The relative path of the destination file (new file name to rename or a new path where to move)
@param: {BOOL} $overwrite_destination: DEFAULT is FALSE ; If set to FALSE will FAIL if destination file exists ; If set to TRUE will overwrite the file destination if exists
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe RENAME OR MOVE A FILE TO A DIFFERENT LOCATION. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/file.ext).
It will rename or move the file from source location to a destination location (includding across partitions).
The destination file will NOT be rewritten if exists and the $overwrite_destination is set to FALSE, so in this case
be sure to check and remove the destination if you intend to overwrite it.
If the $overwrite_destination is set to TRUE the $newlocation will be overwritten.
After rename or move the destination will be chmod standardized, as set in SMART_FRAMEWORK_CHMOD_FILES.
public static function read_uploaded ( string $file_name ) {} :: STRING
@return: {STRING} The file contents ; if the file does not exists or it is not an uploaded file will return an empty string
@param: {STRING} $file_name: The absolute path of the uploaded file to be read
Safe READ AN UPLOADED FILE contents. WORKS WITH ABSOLUTE PATHS (Ex: /tmp/path/to/uploaded-file.ext).
INFO: This function is 100% SAFE ON LINUX and UNIX file systems.
WARNING: This function is NOT VERY SAFE TO USE ON WINDOWS file systems (use it on your own risk) because extra checks over the absolute path are not available on windows paths, thus in theory it may lead to insecure path access if crafted paths may result ...
It will read the full file content of the uploaded file.
IT SHOULD BE USED TO ACCESS ONLY TEMPORARY UPLOAD FILES. To read other files use the method SmartFileSystem::read()
public static function move_uploaded ( string $file_name, string $newlocation, bool $check_moved_contents = true ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $file_name: The absolute path of the uploaded file to be moved
@param: {STRING} $newlocation: The relative path of the destination file (the path where to move)
@param: {BOOLEAN} $check_moved_contents: If TRUE will compare the TMP File with Destination using SHA1-File
Safe MOVE AN UPLOADED FILE to a new RELATIVE location. WORKS WITH ABSOLUTE PATH FOR UPLOADED FILE (Ex: /tmp/path/to/uploaded-file.ext) and a RELATIVE PATH FOR THE DESTINATION FILE (Ex: path/to/a/file.ext).
INFO: This function is 100% SAFE ON LINUX and UNIX file systems.
WARNING: This function is NOT VERY SAFE TO USE ON WINDOWS file systems (use it on your own risk) because extra checks over the absolute path are not available on windows paths, thus in theory it may lead to insecure path access if crafted paths may result ...
It will move an uploaded file to a new destination.
The destination file will be rewritten if exists.
IT SHOULD BE USED TO MOVE ONLY TEMPORARY UPLOAD FILES. To move/rename other files use the method SmartFileSystem::rename()
public static function delete ( string $file_name, bool $allow_protected_paths = false ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $file_name: The relative path of file to be deleted (can be a symlink to a file)
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe DELETE A FILE. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/file.ext).
It will delete a file (or a symlink) if exists
public static function dir_create ( string $dir_name, bool $recursive = false, bool $allow_protected_paths = false ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $dir_name: The relative path of directory to be created (can be an existing symlink to a directory)
@param: {BOOLEAN} $recursive: DEFAULT is FALSE ; If TRUE will attempt to create the full directory (folder) structure if not exists and apply over each segment the standardized chmod, as set in SMART_FRAMEWORK_CHMOD_DIRS
@param: {BOOLEAN} $allow_protected_paths: DEFAULT is FALSE ; If TRUE it may be used to create special protected folders (set to TRUE only if you know what you are really doing and you need to create a folder starting with a `#`, otherwise may lead to security issues ...) ; for task area this is always hardcoded to TRUE and cannot be overrided
Safe CREATE A DIRECTORY (FOLDER) RECURSIVE OR NON-RECURSIVE. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/new-dir).
It will create a new directory (folder) if not exists. If non-recursive will try to create just the last directory (folder) segment.
The directory (folder) will be chmod standardized, as set in SMART_FRAMEWORK_CHMOD_DIRS.
WARNING: The $allow_protected_paths parameter MUST BE SET TO TRUE ONLY FOR VERY SPECIAL USAGE ONLY, TO ALLOW relative paths like : #path/to/a/new-dir that may not be used with standard SmartFileSystem functions as they should be PROTECTED.
Protected Paths (Directories / Folders) are intended for separing the accesible part of filesystem (for regular operations provided via this class) by the protected part of filesystem that can be by example accessed only from special designed libraries.
Example: create a folder #db/sqlite/ and it's content (files, sub-dirs) will not be accessed by this class but only from outside libraries like SQLite).
This feature implements a separation between regular file system folders that this class can access and other application level protected folders in order to avoid filesystem direct access to the protected folders.
As long as all file system operations will be provided only by this class and not using the PHP internal file system functions this separation is safe and secure.
public static function dir_rename ( string $dir_name, string $new_dir_name ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $dir_name: The relative path of directory (folder) to be renamed or moved (can be a symlink to a directory)
@param: {STRING} $new_dir_name: The relative path of the destination directory (folder) or a new directory (folder) name to rename or a new path where to move
Safe RENAME OR MOVE A DIRECTORY (FOLDER) TO A DIFFERENT LOCATION. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/some-dir).
It will rename or move the source directory (folder) to a new location (destination), includding across partitions.
It will FAIL if the destination directory exists, so be sure to check and remove the destination if you intend to overwrite it.
After rename or move the destination will be chmod standardized, as set in SMART_FRAMEWORK_CHMOD_DIRS.
public static function dir_delete ( string $dir_name, bool $recursive = true ) {} :: INT
@return: {INTEGER} 1 if SUCCESS ; 0 on FAIL (this is integer instead of boolean for future extending with status codes)
@param: {STRING} $dir_name: The relative path of directory (folder) to be deleted (removed) ; it can be a symlink to another directory
@param: {BOOLEAN} $recursive: DEFAULT is TRUE ; If set to TRUE will remove directory and all it's content ; If FALSE will try just to remove the directory if empty, otherwise will FAIL
Safe DELETE (REMOVE) A DIRECTORY (FOLDER). IF RECURSIVE WILL REMOVE ALL THE SUB-DIR CONTENTS (FILES AND SUB-DIRS). WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/some-dir).
It will try to remove the directory (folder) if empty in non-recursive mode or will try to delete all directory content (files and sub-folders), if recursive mode enabled.
It will FAIL in non-recursive mode if the directory (folder) is not empty.
public static function compare_folders ( string $dir1, string $dir2, bool $include_dot_files = true, bool $recurring = true ) {} :: ARRAY
@return: {ARRAY} Array of Differences ; If Empty Array, there are no diferences ; If array size > 0, will contain the differences between the compared directories (folders)
@param: {STRING} $dir1: The relative path of the LEFT directory (folder) to compare ; it can be a symlink to another directory
@param: {STRING} $dir2: The relative path of the RIGHT directory (folder) to compare ; it can be a symlink to another directory
@param: {BOOLEAN} $include_dot_files: DEFAULT is TRUE ; If set to TRUE will compare also dot files (ex: .gitignore) ; If FALSE will skip comparing dot files
@param: {BOOLEAN} $recurring: DEFAULT is TRUE ; If set to TRUE will do a full comparison (recuring) ; If set to FALSE will compare just the first level of each directory and will not recurse and compare into sub-directories
Safe COMPARE TWO DIRECTORIES (FOLDERS) FROM LEFT TO RIGHT. RECURSIVE OR NOT. WORKS ONLY WITH RELATIVE PATHS (Ex: path/to/a/some-dir).

## class Properties

## class Constants

public const APP_DB_FOLDER = "#db/" ; ::

## Sample code: PHP

`

    <?php

    // Usage example:
     SmartFileSystem::some_method_of_this_class(...);

    // #end php code

`

documentation generated on: 2024-12-16 16:53:45 +0000

Smart.Framework © 2009-2024 unix-world.org