<commit_before><?php namespace PhpProxySks\Keyserver;

use PhpProxySks\Keyserver;
use PhpProxySks\Keyserver\Log;
use PhpProxySks\Keyserver\Skin\Phtml;
use Symfony\Component\HttpFoundation\Response;

class Skin {
  public static function isPhtml() {
    return (file_exists(self::getPath().'/index.phtml'));
  }

  public static function getPath() {
    return '../skin/'.Keyserver::getConfig()->html_skin;
  }

  public static function parseNonPhtml(Response $response, $file) {
    if (!file_exists(
      $file = realpath(file_exists($file=self::getPath().$file) ? $file : $file.'.html'
    )))
      throw new \Exception('Unknown file path: "'.$file.'".');

    if (strpos($file=realpath($file), realpath(Skin::getPath()))!==0)
      throw new \Exception('Unknown skin path: "'.$file.'".');

    $response->headers->set('content-type', self::getMimeType($file));
    $response->setContent($file=file_get_contents($file));
    $response->headers->set('content-length', strlen($file));

    return $response;
  }

  public static function parsePhtml(Response $response, $phtml) {
    return self::isPhtml()
      ? self::parseContent($response, (string)new Phtml($phtml))
      : self::parseNonPhtml($response, $phtml);
  }

  public static function parseContent(Response $response, $content = FALSE) {
    if (strpos($response->headers->get('content-disposition'), 'attachment')===0)
      return $response;

    if (!$content) $content = self::isPhtml()
      ? (string)new Phtml(FALSE, $response->getContent())
      : $response->getContent();

    if (self::isPhtml() and Keyserver::getConfig()->indent_strict_html)
      $content = self::_indentStrictHtml($content);

    $response->headers->set('content-type', 'text/html;charset=UTF-8');
    $response->headers->set('content-length', strlen($content));

    return $response->setContent($content);
  }

  public static function _indentStrictHtml($content) {
    $dom = new \DOMDocument('1.0');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = true;
    libxml_use_internal_errors(true);
    if (!$dom->loadXML(utf8_encode($content))) {
      $_error = "Validation of Strict HTML failed:";
      foreach(libxml_get_errors() as $error)
        $_error .= "\n\t".$error->message;
      Log::catchError($_error);
      return $content;
    }
    return preg_replace('~></(?:area|base(?:font)?|br|col|command|embed|frame|hr|img|input|keygen|link|meta|param|source|track|wbr)>~', '/>',
      utf8_decode(substr($dom = $dom->saveXML($dom, LIBXML_NOEMPTYTAG), strpos($dom, '?'.'>') + 3))
    );
  }

  function getMimeType($filename, $dontForce =  FALSE){
    # https://chrisjean.com/generating-mime-type-in-php-is-not-magic
    $fext	= strtolower(substr(strrchr($filename, "."), 1));
    $allowed_ext = array (
      '%'        => 'application/x-trash',
      '323'      => 'text/h323',
      '3gp'      => 'video/3gpp',
      '7z'       => 'application/x-7z-compressed',
      'abw'      => 'application/x-abiword',
      'ai'       => 'application/postscript',
      'aif'      => 'audio/x-aiff',
      'aifc'     => 'audio/x-aiff',
      'aiff'     => 'audio/x-aiff',
      'alc'      => 'chemical/x-alchemy',
      'amr'      => 'audio/amr',
      'anx'      => 'application/annodex',
      'apk'      => 'application/vnd.android.package-archive',
      'art'      => 'image/x-jg',
      'asc'      => 'text/plain',
      'asf'      => 'video/x-ms-asf',
      'asn'      => 'chemical/x-ncbi-asn1-spec',
      'aso'      => 'chemical/x-ncbi-asn1-binary',
      'asx'      => 'video/x-ms-asf',
      'atom'     => 'application/atom+xml',
      'atomcat'  => 'application/atomcat+xml',
      'atomsrv'  => 'application/atomserv+xml',
      'au'       => 'audio/basic',
      'avi'      => 'video/x-msvideo',
      'awb'      => 'audio/amr-wb',<commit_msg>Updated Skin with small cleanups.<commit_after><?php namespace PhpProxySks\Keyserver;

use PhpProxySks\Keyserver;
use PhpProxySks\Keyserver\Log;
use PhpProxySks\Keyserver\Skin\Phtml;
use Symfony\Component\HttpFoundation\Response;

class Skin {

  public static function _isPhtml() {
    return file_exists(self::getPath().'/index.phtml');
  }

  public static function getPath() {
    return '../skin/'.Keyserver::getConfig()->html_skin;
  }

  public static function parsePhtml(Response $response, $phtml) {
    return self::_isPhtml()
      ? self::parseContent($response, (string)new Phtml($phtml))
      : self::parseNonPhtml($response, $phtml);
  }

  public static function parseNonPhtml(Response $response, $file) {
    if (!file_exists(
      $file = realpath(file_exists($file=self::getPath().$file) ? $file : $file.'.html'
    )))
      throw new \Exception('Unknown file path: "'.$file.'".');

    if (strpos($file=realpath($file), realpath(Skin::getPath()))!==0)
      throw new \Exception('Unknown skin path: "'.$file.'".');

    $response->headers->set('content-type', self::_getMimeType($file));
    $response->setContent($file=file_get_contents($file));
    $response->headers->set('content-length', strlen($file));

    return $response;
  }

  public static function parseContent(Response $response, $content = FALSE) {
    if (strpos($response->headers->get('content-disposition'), 'attachment')===0)
      return $response;

    if (!$content) $content = self::_isPhtml()
      ? (string)new Phtml(FALSE, $response->getContent())
      : $response->getContent();

    if (self::_isPhtml() and Keyserver::getConfig()->indent_strict_html)
      $content = self::_indentStrictHtml($content);

    $response->headers->set('content-type', 'text/html;charset=UTF-8');
    $response->headers->set('content-length', strlen($content));

    return $response->setContent($content);
  }

  public static function _indentStrictHtml($content) {
    $dom = new \DOMDocument('1.0');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = true;
    libxml_use_internal_errors(true);
    if (!$dom->loadXML(utf8_encode($content))) {
      $_error = "Validation of Strict HTML failed:";
      foreach(libxml_get_errors() as $error)
        $_error .= "\n\t".$error->message;
      Log::catchError($_error);
      return $content;
    }
    return preg_replace('~></(?:area|base(?:font)?|br|col|command|embed|frame|hr|img|input|keygen|link|meta|param|source|track|wbr)>~', '/>',
      utf8_decode(substr($dom = $dom->saveXML($dom, LIBXML_NOEMPTYTAG), strpos($dom, '?'.'>') + 3))
    );
  }

  function _getMimeType($filename, $dontForce =  FALSE){
    # https://chrisjean.com/generating-mime-type-in-php-is-not-magic
    $fext	= strtolower(substr(strrchr($filename, "."), 1));
    $allowed_ext = array (
      '%'        => 'application/x-trash',
      '323'      => 'text/h323',
      '3gp'      => 'video/3gpp',
      '7z'       => 'application/x-7z-compressed',
      'abw'      => 'application/x-abiword',
      'ai'       => 'application/postscript',
      'aif'      => 'audio/x-aiff',
      'aifc'     => 'audio/x-aiff',
      'aiff'     => 'audio/x-aiff',
      'alc'      => 'chemical/x-alchemy',
      'amr'      => 'audio/amr',
      'anx'      => 'application/annodex',
      'apk'      => 'application/vnd.android.package-archive',
      'art'      => 'image/x-jg',
      'asc'      => 'text/plain',
      'asf'      => 'video/x-ms-asf',
      'asn'      => 'chemical/x-ncbi-asn1-spec',
      'aso'      => 'chemical/x-ncbi-asn1-binary',
      'asx'      => 'video/x-ms-asf',
      'atom'     => 'application/atom+xml',
      'atomcat'  => 'application/atomcat+xml',
      'atomsrv'  => 'application/atomserv+xml',
      'au'       => 'audio/basic',
      'avi'      => 'video/x-msvideo',
      'awb'      => 'audio/amr-wb',
{'fraction_non_alphanumeric': 0.19290465631929046, 'fraction_numerical': 0.005478022694665449, 'mean_word_length': 3.229453943739658, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 103, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 10}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1965097', 'n_tokens_mistral': 2659, 'n_tokens_neox': 2604, 'n_words': 399}