foldershare-8.x-1.2/src/ManageFilenameExtensions.php

src/ManageFilenameExtensions.php
<?php
 
namespace Drupal\foldershare;
 
use Drupal\foldershare\Entity\FolderShare;
 
/**
 * Manages file name extensions for the FolderShare module.
 *
 * This class provides static methods to manage lists of filename extensions
 * and queries to check them. Supported operations include:
 * - Getting topical groups of known extensions.
 * - Parsing a file name or path to get the extension.
 * - Checking if an extension is allowed for a FolderShare file.
 * - Getting and setting the list of allowed extensions for a FolderShare file.
 *
 * @ingroup foldershare
 *
 */
class ManageFilenameExtensions {
 
  /*---------------------------------------------------------------------
   *
   * Topical filename extensions.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Returns common file name extensions for archives.
   *
   * An archive is a multi-file container used to package related files
   * and folders together for easier management and distribution. The
   * most widely used archive format is "zip". Other formats exist, many
   * of which are particular to specific OSes for specific uses.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   */
  public static function getArchiveExtensions() {
    return [
      // General.
      'zip',
 
      // OS-specific, Android.
      'apk',
      // OS-specific, Debian.
      'deb',
      // OS-specific, Linux, BSD, and macOS.
      'a', 'cpio', 'bcpio', 'rar', 'tar', 'gtar', 'tgz', 'tbz2',
      'shar', 'gz', 'gzip', 'z', 'bz', 'bz2',
      // OS-specific, RedHat Linux.
      "rpm",
      // OS-specific, macOS.
      'dmg', 'iso', 'mpkg', 'sit', 'sitx',
      // OS-specific, Windows.
      'cab', 'dll', 'rar',
 
      // Content-specific, Java.
      'jar',
      // Content-specific, PHP.
      'phar',
    ];
  }
 
  /**
   * Returns common file name extensions for audio files.
   *
   * An audio file contains a recorded or synthesized sound waveform that may
   * be played back to create sound. The most widely used formats are those
   * defined by MPEG, such as the ubiquitous "mp3" format. Other common
   * formats include "flac", "ogg", and "wav".
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getVideoExtensions()
   */
  public static function getAudioExtensions() {
    return [
      // General.
      'aif', 'aiff', 'flac',
      'mp3', 'm3u', 'm4a',
      'ogg', 'oga', 'mogg',
 
      // OS-specific, Windows.
      'wma', 'wav',
      // OS-specific, macOS, iOS.
      'm4p', 'm4r',
 
      // Older formats.
      'au',
    ];
  }
 
  /**
   * Returns common file name extensions for data files.
   *
   * A data file contains primarily numeric data in a task-specific format.
   * The common "data" and "bin" extensions are used generically, while
   * the standard "hdf" format is used for self-describing structured data
   * in many science applications.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   */
  public static function getDataExtensions() {
    return [
      // General.
      'asc', 'ascii', 'bin', 'dat', 'data', 'text', 'txt',
      'csv', 'tsv',
 
      // Science formats.
      'hdf', 'hdf5', 'h5', 'nc', 'fits', 'daq', 'fig',
      // Matlab.
      'mat', 'mn',
 
      // Web and Drupal et al.
      'yaml', 'yml', 'twig', 'info',
      // Web page styles.
      'css', 'less', 'sass', 'scss', 'xsl', 'xsd',
      // Web data.
      'json', 'xml', 'rdf',
 
      // Calendar.
      'ics',
      // Google.
      'kml', 'kmz',
    ];
  }
 
  /**
   * Returns common file name extensions for document files.
   *
   * A document file contains numeric and text data to support presentation
   * and editing of a formatted document. Common formats include HTML and
   * PDF, as well as Microsoft Word, Microsoft Excel, and Microsoft PowerPoint.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getTextEextensions()
   */
  public static function getDocumentExtensions() {
    return [
      // Web.
      'htm', 'html', 'xhtml', 'rss', 'dtd', 'xml',
      // Other.
      'man', 'rtf', 'rtx', 'tex', 'ltx', 'latex', 'pdf', 'md',
 
      // Word.
      'docx', 'docm', 'dotx', 'dotm', 'docb',
      // Excel.
      'xlsx', 'xlsm', 'xltx', 'xltm',
      // Powerpoint.
      'pptx', 'pptm', 'potx', 'potm', 'ppam', 'ppsx', 'ppsm',
      'sldx', 'sldm',
      // Access.
      'adn', 'accdb', 'accdr', 'accdt', 'accda', 'mdw', 'accde',
      'mam', 'maq', 'mar', 'mat', 'maf', 'laccdb',
 
      // Legacy Word.
      'doc', 'dot', 'wbk',
      // Legacy Excel.
      'xls', 'xlt', 'xlm',
      // Legacy Powerpoint.
      'ppt', 'pot', 'pps',
      // Legacy Access.
      'ade', 'adp', 'mdb', 'cdb', 'mda', 'mdn', 'mdt', 'mdf',
      'mde', 'ldb',
 
      // Wordperfect.
      'wpd',
      // KDE.
      'karbon', 'chrt', 'kfo', 'flw', 'kon', 'kpr', 'ksp', 'kwd',
      // OpenDocument.
      'odc', 'otc', 'odb', 'odf', 'odft', 'odg', 'otg', 'odi',
      'oti', 'odp', 'otp', 'ods', 'ots', 'odt', 'odm', 'ott',
      // Open office.
      'sxc', 'stc', 'sxd', 'std', 'sxi', 'sti', 'sxm', 'sxw',
      'sxg', 'stw', 'oxt',
      // Star office.
      'sdc', 'sda', 'sdd', 'smf', 'sdw', 'sgl',
    ];
  }
 
  /**
   * Returns common file name extensions for drawing files.
   *
   * A drawing file contains instructions and data for drawing shapes in
   * 2D or 3D. This includes vendor-neutral formats like "ps" for PostScript,
   * or "svg" for scalable vector graphics. This also includes vendor-specific
   * formats, such as "blend" for Blender, "3ds" for 3D Studio Max, or
   * "dxf" for Autocad.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getImageExtensions()
   */
  public static function getDrawingExtensions() {
    return [
      // General, web.
      'svg',
      // General, printing.
      'ps', 'eps', 'ppd',
      // Vendor neutral.
      'dae', 'odg', 'stl',
      // Vendor-specific.
      'ai', 'dwf', 'dxf', 'blend', '3ds',
    ];
  }
 
  /**
   * Returns common file name extensions for binary executable files.
   *
   * An executable file contains a compiled program that can be executed
   * by the OS. The most common of these is a Windows "exe" file. On Linux,
   * BSD, and macOS, however, executable programs do not have a specific
   * extension.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getScriptExtensions()
   * @see ::getSoftwareExtensions()
   */
  public static function getExecutableExtensions() {
    return [
      // OS-specific, macOS UI application (but not command-line programs).
      'app',
      // OS-specific, Windows and DOS.
      'exe',
    ];
  }
 
  /**
   * Returns common file name extensions for image files.
   *
   * An image file contains a representation of a rectangular grid of
   * raster pixels. Typical image formats on the web include "png",
   * "jpeg", and "gif".
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getDrawingExtensions()
   */
  public static function getImageExtensions() {
    return [
      // General.
      'png', 'gif', 'ico', 'webp',
      // JPEG and JPEG2000.
      'jpg', 'jpeg', 'jp2', 'j2k', 'jpf', 'jpx', 'jpm',
      // TIFF.
      'tif', 'tiff',
      // OS-specific, Linux, BSD, macOS (generally).
      'ppm', 'pbm', 'pgm', 'pnm', 'xbm', 'xpm',
      // OS-specific, Windows.
      'bmp', 'pcx', 'tga',
      // Other.
      'fits', 'psd',
    ];
  }
 
  /**
   * Returns common file name extensions for command script files.
   *
   * A command script file contains a list of instructions for running
   * commands on an OS. This includes command, batch, and shell script files,
   * but not scripting programming languages, like perl or PHP, which
   * require a separate interpreter that is not typically considered part of
   * a core OS distribution.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getExecutableExtensions()
   * @see ::getSoftwareExtensions()
   */
  public static function getScriptExtensions() {
    return [
      // OS-specific, Linux, BSD, and macOS.
      'cgi', 'sh', 'bash', 'csh', 'shar',
      // OS-specific, Windows and DOS.
      'bat', 'cmd', 'com',
    ];
  }
 
  /**
   * Returns common file name extensions for software files.
   *
   * A software file contains the source code or intermediate code used during
   * software development. This can include assembly, object files, class files,
   * and libraries, along with source code for specific programming languages.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included. For instance, the various
   * legacy Flash and Shockwave formats are not included (e.g. "fla", "flv",
   * "f4v", "swf").
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getExecutableExtensions()
   */
  public static function getSoftwareExtensions() {
    return [
      // Assembly.
      'asm', 's',
      // Basic.
      'b',
      // C, C++, C#.
      'c', 'c++', 'cp', 'cpp', 'cxx', 'cs', 'csx',
      'h', 'hpp', 'inc', 'include',
      // Cobol.
      'cbl',
      // ECMAscript (a.k.a. Javascript or LiveScript).
      'js',
      // Fortran.
      'f',
      // Java.
      'class', 'java', 'jsp',
      // Objective-C.
      'm',
      // Perl.
      'pl', 'prl', 'perl',
      // PHP.
      'php', 'phar',
      // PHP, Drupal-specific.
      'module', 'install',
      // Python.
      'py', 'pyc', 'python',
      // R.
      'r',
      // Swift.
      'swift',
      // General macro processing.
      'm4',
      // OS-specific, Linux, BSD, and macOS.
      'awk', 'sed', 'o', 'make', 'mk', 'cmake', 'ini', 'config',
      // OS-specific, Windows.
      'cd', 'cs', 'vbp', 'vbproj', 'vbx', 'vcxproj', 'asp',
    ];
  }
 
  /**
   * Returns common file name extensions for text files.
   *
   * A text file contains human-readable text without formatting. Text files
   * can be created in any text editor, and viewed without a specific
   * document formatting application. This specifically excludes document
   * files, such as for Microsoft Office.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getDocumentExtensions()
   */
  public static function getTextExtensions() {
    return [
      // General.
      'asc', 'ascii', 'text', 'txt',
      // OS-specific, Linux, BSD, and macOS (generally).
      'readme', '1st',
    ];
  }
 
  /**
   * Returns common file name extensions for video files.
   *
   * A video file contains a sequence of raster images that may be played
   * back onto a display to recreate an animation or movie. The most common
   * of these are by MPEG ("mp4") and Apple for QuickTime ("qt").
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getAudioExtensions()
   */
  public static function getVideoExtensions() {
    return [
      // MPEG.
      'mp4', 'm4v', 'mpg', 'mpv', 'mpeg',
      // OS-specific, Windows.
      'avi', 'wmv',
      // OS-specific, macOS.
      'mov', 'qt',
      // Other.
      'h264', 'mj2', 'mkv', 'ogv', 'webm',
    ];
  }
 
  /**
   * Returns common file name extensions for web files.
   *
   * This method returns a mix of file formats commonly used on the web.
   * This includes formats like "html", "png", and "txt", but excludes
   * vendor- or OS-specific formats like those in Microsoft Office.
   *
   * The list returned by this method is not exhaustive. Only the most
   * common formats are included. Obscure, legacy, narrowly-used, or
   * vendor-specific extensions are not included.
   *
   * @return string[]
   *   Returns a list of extensions, without dots.
   *
   * @see ::getArchiveExtensions()
   * @see ::getAudioExtensions()
   * @see ::getDataExtensions()
   * @see ::getDocumentExtensions()
   * @see ::getDrawingExtensions()
   * @see ::getImageExtensions()
   * @see ::getSoftwareExtensions()
   * @see ::getTextExtensions()
   * @see ::getVideoExtensions()
   */
  public static function getWebExtensions() {
    return [
      // Archives.
      'zip', 'tar', 'tgz',
      // Audio.
      'mp3', 'flac', 'ogg', 'wav',
      // Data.
      'css',
      // Document.
      'htm', 'html', 'xhtml', 'rss', 'dtd', 'rtf', 'pdf',
      // Drawing.
      'svg', 'ps', 'eps',
      // Image.
      'png', 'gif', 'ico', 'jpg', 'jpeg',
      // Software.
      'js',
      // Text.
      'text', 'txt',
      // Video.
      'mp4',
    ];
  }
 
  /*---------------------------------------------------------------------
   *
   * Methods.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Returns an array of all file name extensions defined here.
   *
   * This method returns an exhaustive list of file name extensions for
   * common file formats used for archives, audio, data, documents,
   * executables, drawings, images, software, text, and videos.
   *
   * @return string[]
   *   Returns an array of filename extensions, without leading dots.
   *   Extensions are unique and sorted alphabetically.
   *
   * @see ::getArchiveExtensions()
   * @see ::getAudioExtensions()
   * @see ::getDataExtensions()
   * @see ::getDocumentExtensions()
   * @see ::getExecutableExtensions()
   * @see ::getDrawingExtensions()
   * @see ::getImageExtensions()
   * @see ::GetScriptExtensions()
   * @see ::getSoftwareExtensions()
   * @see ::getTextExtensions()
   * @see ::getVideoExtensions()
   */
  public static function getAllExtensions() {
    $merged = array_unique(array_merge(
      self::getArchiveExtensions(),
      self::getAudioExtensions(),
      self::getDataExtensions(),
      self::getDocumentExtensions(),
      self::getExecutableExtensions(),
      self::getDrawingExtensions(),
      self::getImageExtensions(),
      self::getScriptExtensions(),
      self::getSoftwareExtensions(),
      self::getTextExtensions(),
      self::getVideoExtensions()));
    natsort($merged);
    return $merged;
  }
 
  /**
   * Returns an array of all text-oriented file name extensions defined here.
   *
   * This method returns an abbreviated list of file name extensions for
   * files that are primarily text, though the specific format may have some
   * binary structure. This includes common file formats for documents,
   * software, and text.
   *
   * @return string[]
   *   Returns an array of filename extensions, without leading dots.
   *   Extensions are unique and sorted alphabetically.
   *
   * @see ::getDocumentExtensions()
   * @see ::GetScriptExtensions()
   * @see ::getSoftwareExtensions()
   * @see ::getTextExtensions()
   */
  public static function getAllTextExtensions() {
    $merged = array_unique(array_merge(
      self::getDocumentExtensions(),
      self::getScriptExtensions(),
      self::getSoftwareExtensions(),
      self::getTextExtensions(),
      [
        // Misc. formats extracted from the longer lists.
        'tar',
        'dat',
        'yaml', 'yml', 'twig', 'info',
        'css', 'less', 'sass', 'scss', 'xsl', 'xsd',
        'json',
      ]));
    natsort($merged);
    return $merged;
  }
 
  /*---------------------------------------------------------------------
   *
   * Extensions for file and image fields.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Returns file name extensions allowed for FolderShare files.
   *
   * The field definition for the 'file' field (which is always the same
   * as for the 'image' field) is queried and its current file name extensions
   * setting returned. This setting is a single string containing a
   * space-separated list of allowed file name extensions. Extensions do
   * not include a leading "dot".
   *
   * File name extensions are always lower case. There are no redundant
   * extensions. Extensions in the list are not ordered.
   *
   * If the list of extensions is empty, then any extension is allowed
   * for uploaded and renamed files.
   *
   * @return string
   *   Returns a string containing a space-separated list of file
   *   extensions (without the leading dot) supported for files.
   *
   * @see ::isNameExtensionAllowed()
   * @see ::setAllowedNameExtensions()
   * @see \Drupal\foldershare\Settings::getAllowedNameExtensionsDefault()
   * @see \Drupal\foldershare\Settings::getAllowedNameExtensions()
   */
  public static function getAllowedNameExtensions() {
    // Get the extensions string on the 'file' field. These will always be
    // the same as on the 'image' field.
    $fieldManager = \Drupal::service('entity_field.manager');
    $def = $fieldManager->getFieldDefinitions(
      FolderShare::ENTITY_TYPE_ID,
      FolderShare::ENTITY_TYPE_ID);
 
    return $def['file']->getSetting('file_extensions');
  }
 
  /**
   * Sets the file name extensions allowed for FolderShare files.
   *
   * <B>This method is internal and strictly for use by the FolderShare
   * module itself.</B>
   *
   * The field definitions for the 'file' and 'image' fields are changed and
   * their current file name extensions settings updated. This setting is a
   * single string containing a space-separated list of allowed file name
   * extensions. Extensions do not include a leading "dot".
   *
   * File name extensions are automatically folded to lower case.
   * Redundant extensions are removed.
   *
   * If the list of extensions is empty, then any extension is allowed
   * for uploaded and renamed files.
   *
   * <B>Process locks</B>
   * This method does not lock access. The caller should lock around changes
   * to the field definition entity.
   *
   * @param string $extensions
   *   A string containing a space list of file name extensions
   *   (without the leading dot) supported for folder files.
   *
   * @see ::getAllowedNameExtensions()
   * @see \Drupal\foldershare\Settings::getAllowedNameExtensionsDefault()
   * @see \Drupal\foldershare\Settings::setAllowedNameExtensions()
   */
  public static function setAllowedNameExtensions(string $extensions) {
    if (empty($extensions) === TRUE) {
      // The given extensions list is empty, so no further processing
      // is required.
      $uniqueExtensions = '';
    }
    else {
      // Fold the entire string to lower case. Then split it into
      // individual extensions.
      $extList = mb_split(' ', mb_strtolower($extensions));
 
      // Check for and remove any leading dot on extensions.
      foreach ($extList as $key => $value) {
        if (mb_strpos($value, '.') === 0) {
          $extList[$key] = mb_substr($value, 1);
        }
      }
 
      // Remove redundant extensions and rebuild the list string.
      $uniqueExtensions = implode(' ', array_unique($extList));
    }
 
    // Set the extensions string on the 'file' and 'image' fields.
    $fieldManager = \Drupal::service('entity_field.manager');
    $def = $fieldManager->getFieldDefinitions(
      FolderShare::ENTITY_TYPE_ID,
      FolderShare::ENTITY_TYPE_ID);
 
    $cfd = $def['file']->getConfig(FolderShare::ENTITY_TYPE_ID);
    $cfd->setSetting('file_extensions', $uniqueExtensions);
    $cfd->save();
 
    $cfd = $def['image']->getConfig(FolderShare::ENTITY_TYPE_ID);
    $cfd->setSetting('file_extensions', $uniqueExtensions);
    $cfd->save();
  }
 
  /*---------------------------------------------------------------------
   *
   * Extension parsing.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Returns the lower case file name extension from a file name or path.
   *
   * @param string $path
   *   The URI or local path to parse.
   *
   * @return string
   *   Returns the file name extension (the part after the last "."),
   *   converted to lower case. If there is no extension, an empty
   *   string is returned.
   */
  public static function getExtensionFromPath(string $path) {
    $ext = pathinfo($path, PATHINFO_EXTENSION);
    if (empty($ext) === TRUE) {
      return '';
    }
 
    return mb_strtolower($ext);
  }
 
  /*---------------------------------------------------------------------
   *
   * Extension testing.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Returns TRUE if the file name is using an allowed file extension.
   *
   * <B>This method is internal and strictly for use by the FolderShare
   * module itself.</B>
   *
   * The text following the last '.' in the given file name is extracted
   * as the name's extension, then checked against the given array of
   * allowed extensions. If the name is found, TRUE is returned.
   *
   * If the file name has no '.', it has no extension, and TRUE is
   * returned.
   *
   * If the extensions array is empty, all extensions are accepted and
   * TRUE is returned.
   *
   * @param string $path
   *   The local path to parse.
   * @param array $extensions
   *   (optional, default = NULL) An array of allowed file name extensions.
   *   If the extensions array is empty, all extensions are allowed. If
   *   the extensions argument is NULL, the extensions array is retrieved
   *   from module settings.
   *
   * @return bool
   *   Returns TRUE if the name has no extension, the extensions array is
   *   empty, the module has no list of allowed extensions, or if it uses
   *   an allowed extension, and FALSE otherwise.
   *
   * @see ::getAllowedNameExtensions()
   */
  public static function isNameExtensionAllowed(
    string $path,
    array $extensions = NULL) {
 
    $ext = self::getExtensionFromPath($path);
    if (empty($ext) === TRUE) {
      // No extension. Default to allowed.
      return TRUE;
    }
 
    if ($extensions === NULL) {
      $extensionsString = self::getAllowedNameExtensions();
      if (empty($extensionsString) === TRUE) {
        // There are no allowed extensions. All extensions are allowed.
        return TRUE;
      }
 
      $extensions = mb_split(' ', $extensionsString);
    }
 
    if (count($extensions) === 0) {
      // There are no allowed extensions. All extensions are allowed.
      return TRUE;
    }
 
    // Look for in allowed extensions array.
    return in_array($ext, $extensions);
  }
 
  /**
   * Returns TRUE if the ZIP file name extension is allowed.
   *
   * @return bool
   *   Returns TRUE if it is allowed, and FALSE otherwise.
   */
  public static function isZipExtensionAllowed() {
    $extensionsString = self::getAllowedNameExtensions();
    if (empty($extensionsString) === TRUE) {
      // No extension restrictions.
      return TRUE;
    }
 
    $extensions = mb_split(' ', $extensionsString);
    foreach ($extensions as $ext) {
      if ($ext === 'zip') {
        return TRUE;
      }
    }
 
    return FALSE;
  }
 
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc