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 )