Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_subr/io.c  view on Meta::CPAN

  static const char * const generic_binary = "application/octet-stream";

  svn_node_kind_t kind;
  apr_file_t *fh;
  svn_error_t *err;
  unsigned char block[1024];
  apr_size_t amt_read = sizeof(block);

  /* Default return value is NULL. */
  *mimetype = NULL;

  /* If there is a mimetype_map provided, we'll first try to look up
     our file's extension in the map.  Failing that, we'll run the
     heuristic. */
  if (mimetype_map)
    {
      const char *type_from_map;
      char *path_ext; /* Can point to physical const memory but only when
                         svn_path_splitext sets it to "". */
      svn_path_splitext(NULL, (const char **)&path_ext, file, pool);
      fileext_tolower(path_ext);
      if ((type_from_map = svn_hash_gets(mimetype_map, path_ext)))
        {
          *mimetype = type_from_map;
          return SVN_NO_ERROR;
        }
    }

  /* See if this file even exists, and make sure it really is a file. */
  SVN_ERR(svn_io_check_path(file, &kind, pool));
  if (kind != svn_node_file)
    return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
                             _("Can't detect MIME type of non-file '%s'"),
                             svn_dirent_local_style(file, pool));

  SVN_ERR(svn_io_file_open(&fh, file, APR_READ, 0, pool));

  /* Read a block of data from FILE. */
  err = svn_io_file_read(fh, block, &amt_read, pool);
  if (err && ! APR_STATUS_IS_EOF(err->apr_err))
    return err;
  svn_error_clear(err);

  /* Now close the file.  No use keeping it open any more.  */
  SVN_ERR(svn_io_file_close(fh, pool));

  if (svn_io_is_binary_data(block, amt_read))
    *mimetype = generic_binary;

  return SVN_NO_ERROR;
}


svn_boolean_t
svn_io_is_binary_data(const void *data, apr_size_t len)
{
  const unsigned char *buf = data;

  if (len == 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
    {
      /* This is an empty UTF-8 file which only contains the UTF-8 BOM.
       * Treat it as plain text. */
      return FALSE;
    }

  /* Right now, this function is going to be really stupid.  It's
     going to examine the block of data, and make sure that 15%
     of the bytes are such that their value is in the ranges 0x07-0x0D
     or 0x20-0x7F, and that none of those bytes is 0x00.  If those
     criteria are not met, we're calling it binary.

     NOTE:  Originally, I intended to target 85% of the bytes being in
     the specified ranges, but I flubbed the condition.  At any rate,
     folks aren't complaining, so I'm not sure that it's worth
     adjusting this retroactively now.  --cmpilato  */
  if (len > 0)
    {
      apr_size_t i;
      apr_size_t binary_count = 0;

      /* Run through the data we've read, counting the 'binary-ish'
         bytes.  HINT: If we see a 0x00 byte, we'll set our count to its
         max and stop reading the file. */
      for (i = 0; i < len; i++)
        {
          if (buf[i] == 0)
            {
              binary_count = len;
              break;
            }
          if ((buf[i] < 0x07)
              || ((buf[i] > 0x0D) && (buf[i] < 0x20))
              || (buf[i] > 0x7F))
            {
              binary_count++;
            }
        }

      return (((binary_count * 1000) / len) > 850);
    }

  return FALSE;
}


svn_error_t *
svn_io_detect_mimetype(const char **mimetype,
                       const char *file,
                       apr_pool_t *pool)
{
  return svn_io_detect_mimetype2(mimetype, file, NULL, pool);
}


svn_error_t *
svn_io_file_open(apr_file_t **new_file, const char *fname,
                 apr_int32_t flag, apr_fileperms_t perm,
                 apr_pool_t *pool)
{
  const char *fname_apr;
  apr_status_t status;



( run in 1.619 second using v1.01-cache-2.11-cpan-39bf76dae61 )