#include "php_fileinfo.h"
#include "fopen_wrappers.h" /* needed for is_url */
+#ifndef _S_IFDIR
+# define _S_IFDIR S_IFDIR
+#endif
+
/* {{{ macros and type definitions */
struct php_fileinfo {
long options;
}
/* }}} */
-static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
+#define FILEINFO_MODE_BUFFER 0
+#define FILEINFO_MODE_STREAM 1
+#define FILEINFO_MODE_FILE 2
+
+static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mimetype_emu) /* {{{ */
{
long options = 0;
- char *tmp, *ret_val, *buffer = NULL;
+ char *ret_val = NULL, *buffer = NULL;
int buffer_len;
struct php_fileinfo *finfo;
zval *zfinfo, *zcontext = NULL;
+ zval *what;
+ char mime_directory[] = "directory";
+
+ struct magic_set *magic = NULL;
FILEINFO_DECLARE_INIT_OBJECT(object)
- if (object) {
+ if (mimetype_emu) {
+
+ /* mime_content_type(..) emulation */
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &what) == FAILURE) {
+ return;
+ }
+
+ switch (Z_TYPE_P(what)) {
+ case IS_UNICODE:
+ case IS_STRING:
+ if (Z_TYPE_P(what) == IS_UNICODE) {
+ convert_to_string_ex(&what);
+ }
+
+ buffer = Z_STRVAL_P(what);
+ buffer_len = Z_STRLEN_P(what);
+ mode = FILEINFO_MODE_FILE;
+ break;
+
+ case IS_RESOURCE:
+ mode = FILEINFO_MODE_STREAM;
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments");
+ RETURN_FALSE;
+ }
+
+ magic = magic_open(MAGIC_MIME);
+ if (magic_load(magic, NULL) == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database.");
+ goto common;
+ }
+ } else if (object) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lr", &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
RETURN_FALSE;
}
FILEINFO_FROM_OBJECT(finfo, object);
+ magic = finfo->magic;
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lr", &zfinfo, &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
RETURN_FALSE;
}
ZEND_FETCH_RESOURCE(finfo, struct php_fileinfo *, &zfinfo, -1, "file_info", le_fileinfo);
+ magic = finfo->magic;
}
/* Set options for the current file/buffer. */
if (options) {
- FINFO_SET_OPTION(finfo->magic, options)
+ FINFO_SET_OPTION(magic, options)
}
- if (mode) { /* file */
- /* determine if the file is a local file or remote URL */
- char *tmp2;
- php_stream_wrapper *wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0 TSRMLS_CC);
- if (wrap && wrap->is_url) {
-#ifdef ZEND_ENGINE_2
- php_stream_context *context = php_stream_context_from_zval(zcontext, 0);
-#else
- php_stream_context *context = NULL;
-#endif
- php_stream *stream = php_stream_open_wrapper_ex(buffer, "rb",
- ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
- if (!stream) {
- RETURN_FALSE;
+ switch (mode) {
+ case FILEINFO_MODE_BUFFER:
+ {
+ ret_val = (char *) magic_buffer(magic, buffer, buffer_len);
+ break;
+ }
+
+ case FILEINFO_MODE_STREAM:
+ {
+ php_stream *stream;
+ off_t streampos;
+
+ php_stream_from_zval_no_verify(stream, &what);
+ if (!stream) {
+ goto common;
+ }
+
+ streampos = php_stream_tell(stream); /* remember stream position for restoration */
+ php_stream_seek(stream, 0, SEEK_SET);
+
+ ret_val = (char *) magic_stream(magic, stream);
+ break;
+ }
+
+ case FILEINFO_MODE_FILE:
+ {
+ /* determine if the file is a local file or remote URL */
+ char *tmp2;
+ php_stream_wrapper *wrap;
+ struct stat sb;
+
+ if (buffer == NULL || !*buffer) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty filename or path");
+ RETVAL_FALSE;
+ goto clean;
}
- buffer_len = php_stream_copy_to_mem(stream, &tmp, HOWMANY, 0);
- php_stream_close(stream);
- if (buffer_len == 0) {
- RETURN_FALSE;
+ if (php_sys_stat(buffer, &sb) == 0) {
+ if (sb.st_mode & _S_IFDIR) {
+ ret_val = mime_directory;
+ goto common;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "File or path not found '%s'", buffer);
+ RETVAL_FALSE;
+ goto clean;
}
- } else { /* local file */
- char resolved_path[MAXPATHLEN];
+ wrap = php_stream_locate_url_wrapper(buffer, &tmp2, 0 TSRMLS_CC);
+
+ if (wrap) {
+ php_stream_context *context = php_stream_context_from_zval(zcontext, 0);
- if (*buffer && VCWD_REALPATH(buffer, resolved_path)) {
- if (php_check_open_basedir(resolved_path TSRMLS_CC)) {
- RETURN_FALSE;
+ php_stream *stream = php_stream_open_wrapper_ex(buffer, "rb", REPORT_ERRORS, NULL, context);
+
+ if (!stream) {
+ if (mimetype_emu) {
+ magic_close(magic);
+ }
+ RETVAL_FALSE;
+ goto clean;
}
- ret_val = (char *) magic_file(finfo->magic, resolved_path);
- } else {
- RETURN_FALSE;
+
+ ret_val = magic_stream(magic, stream);
+ php_stream_close(stream);
}
- goto common;
+ break;
}
- } else { /* buffer */
- tmp = buffer;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments");
+ }
+
+common:
+ if (ret_val) {
+ RETVAL_STRING(ret_val, 1);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
+ RETVAL_FALSE;
}
- ret_val = (char *) magic_buffer(finfo->magic, tmp, buffer_len);
- if (mode) {
- efree(tmp);
+clean:
+ if (mimetype_emu) {
+ magic_close(magic);
}
-common:
+
/* Restore options */
if (options) {
- FINFO_SET_OPTION(finfo->magic, finfo->options)
- }
-
- if (!ret_val) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s",
- magic_errno(finfo->magic), magic_error(finfo->magic));
- RETURN_FALSE;
- } else {
- RETURN_STRING(ret_val, 1);
+ FINFO_SET_OPTION(magic, finfo->options)
}
+ return;
}
/* }}} */
Return information about a file. */
PHP_FUNCTION(finfo_file)
{
- _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+ _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_FILE, 0);
}
/* }}} */
Return infromation about a string buffer. */
PHP_FUNCTION(finfo_buffer)
{
- _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, FILEINFO_MODE_BUFFER, 0);
}
/* }}} */
Return content-type for file */
PHP_FUNCTION(mime_content_type)
{
- zval *what;
- magic_t magic;
- char *tmp, *ret_val;
- int buffer_len;
- char *tmp2;
- php_stream_wrapper *wrap;
- zval *zcontext = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &what) == FAILURE) {
- return;
- }
-
- RETVAL_FALSE;
-
- magic = magic_open(MAGIC_MIME);
- if (magic_load(magic, NULL) == -1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load magic database.");
- goto cleanup;
- }
-
- switch (Z_TYPE_P(what)) {
- case IS_STRING:
- wrap = php_stream_locate_url_wrapper(Z_STRVAL_P(what), &tmp2, 0 TSRMLS_CC);
- /* determine if the file is a local file or remote URL */
- if (wrap && wrap->is_url) {
- php_stream_context *context = php_stream_context_from_zval(zcontext, 0);
- php_stream *stream = php_stream_open_wrapper_ex(Z_STRVAL_P(what), "rb",
- ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
- if (!stream) {
- goto cleanup;
- }
- buffer_len = php_stream_copy_to_mem(stream, &tmp, 4096, 0);
- php_stream_close(stream);
-
- if (buffer_len == 0) {
- goto cleanup;
- }
- ret_val = (char *) magic_buffer(magic, tmp, buffer_len);
- } else { /* local file */
- char resolved_path[MAXPATHLEN];
-
- if (*Z_STRVAL_P(what) && VCWD_REALPATH(Z_STRVAL_P(what), resolved_path)) {
- if (php_check_open_basedir(resolved_path TSRMLS_CC)) {
- goto cleanup;
- }
- ret_val = (char *) magic_file(magic, resolved_path);
- } else {
- goto cleanup;
- }
- }
- break;
- case IS_RESOURCE:
- {
- php_stream *stream;
- off_t streampos;
-
- php_stream_from_zval_no_verify(stream, &what);
- if (!stream) {
- goto cleanup;
- }
- streampos = php_stream_tell(stream); /* remember stream position for restoration */
- php_stream_seek(stream, 0, SEEK_SET);
-
- buffer_len = php_stream_copy_to_mem(stream, &tmp, 4096, 0);
- php_stream_seek(stream, streampos, SEEK_SET);
-
- if (buffer_len == 0) {
- goto cleanup;
- }
- ret_val = (char *) magic_buffer(magic, tmp, buffer_len);
- }
- break;
- default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only process string or stream arguments");
- goto cleanup;
- }
- if (!ret_val) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed identify data %d:%s",
- magic_errno(magic), magic_error(magic));
- } else {
- RETVAL_STRING(ret_val, 1);
- }
-cleanup:
- magic_close(magic);
+ _php_finfo_get_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1, 1);
}
/* }}} */
* apprentice - make one pass through /etc/magic, learning its secrets.
*/
+#include "php.h"
+
#include "file.h"
#include "magic.h"
#include "patchlevel.h"
#include <stdlib.h>
-//#ifdef HAVE_UNISTD_H
+
+#ifdef PHP_WIN32
+#include "win32/unistd.h"
+#define strtoull _strtoui64
+#else
#include <unistd.h>
-//#endif
+#endif
+
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
+#ifndef PHP_WIN32
#include <sys/param.h>
+#endif
#include <sys/types.h>
+#ifndef PHP_WIN32
#include <dirent.h>
+#endif
#ifndef lint
FILE_RCSID("@(#)$File: apprentice.c,v 1.132 2008/03/28 18:19:30 christos Exp $")
# undef XX_NULL
};
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode) & _S_IFDIR)
+#endif
+
private int
get_type(const char *l, const char **t)
{
load_1(struct magic_set *ms, int action, const char *fn, int *errs,
struct magic_entry **marray, uint32_t *marraycount)
{
- char line[BUFSIZ];
+ zstr buffer;
+ char *line;
+ size_t line_len;
size_t lineno = 0;
- FILE *f = fopen(ms->file = fn, "r");
- if (f == NULL) {
+
+ php_stream *stream;
+
+ TSRMLS_FETCH();
+
+#if (PHP_MAJOR_VERSION < 6)
+ stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+#else
+ stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
+#endif
+ if (stream == NULL) {
if (errno != ENOENT)
file_error(ms, errno, "cannot read magic file `%s'",
fn);
(*errs)++;
} else {
- /* read and parse this file */
- for (ms->line = 1; fgets(line, sizeof(line), f) != NULL; ms->line++) {
- size_t len;
- len = strlen(line);
- if (len == 0) /* null line, garbage, etc */
+ buffer.v = emalloc(BUFSIZ+1);
+ for (ms->line = 1; (line = php_stream_get_line(stream, buffer, BUFSIZ, &line_len)) != NULL; ms->line++) {
+ if (line_len == 0 || /* null line, garbage, etc */
+ line[0] == '\0' || /* empty*/
+ line[0] == '#' || /* comment */
+ line[0] == '\n' || line[0] == '\r') { /* New Line */
continue;
- if (line[len - 1] == '\n') {
+ }
+
+ if (line[line_len - 1] == '\n') {
lineno++;
- line[len - 1] = '\0'; /* delete newline */
+ line[line_len - 1] = '\0'; /* delete newline */
}
- if (line[0] == '\0') /* empty, do not parse */
- continue;
- if (line[0] == '#') /* comment, do not parse */
- continue;
- if (len > mime_marker_len &&
+
+ if (line_len > mime_marker_len &&
memcmp(line, mime_marker, mime_marker_len) == 0) {
/* MIME type */
if (parse_mime(ms, marray, marraycount,
if (parse(ms, marray, marraycount, line, lineno, action) != 0)
(*errs)++;
}
-
- (void)fclose(f);
+ efree(buffer.v);
+ php_stream_close(stream);
}
}
ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
- maxmagic = MAXMAGIS;
+ maxmagic = MAXMAGIS;
marray = ecalloc(maxmagic, sizeof(*marray));
marraycount = 0;
(void)fprintf(stderr, "%s\n", usg_hdr);
/* load directory or file */
- if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
+ if (php_sys_stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
dir = opendir(fn);
if (dir) {
while ((d = readdir(dir))) {
apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
const char *fn)
{
- int fd;
- struct stat st;
uint32_t *ptr;
uint32_t version;
int needsbyteswap;
char *dbname = NULL;
void *mm = NULL;
int ret = 0;
+ php_stream *stream;
+ php_stream_statbuf st;
+
+
+ TSRMLS_FETCH();
if (fn == NULL) {
- mm = &php_magic_database;
+ mm = (void *)&php_magic_database;
ret = 3;
goto internal_loaded;
}
if (dbname == NULL)
goto error2;
- if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)
+#if (PHP_MAJOR_VERSION < 6)
+ stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+#else
+ stream = php_stream_open_wrapper((char *)fn, "rb", REPORT_ERRORS, NULL);
+#endif
+
+ if (!stream) {
goto error2;
+ }
- if (fstat(fd, &st) == -1) {
+ if (php_stream_stat(stream, &st) < 0) {
file_error(ms, errno, "cannot stat `%s'", dbname);
goto error1;
}
- if (st.st_size < 8) {
+
+ if (st.sb.st_size < 8) {
file_error(ms, 0, "file `%s' is too small", dbname);
goto error1;
}
- mm = emalloc((size_t)st.st_size);
- if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
+ mm = emalloc((size_t)st.sb.st_size);
+ if (php_stream_read(stream, mm, (size_t)st.sb.st_size) != (size_t)st.sb.st_size) {
file_badread(ms);
goto error1;
}
ret = 1;
- (void)close(fd);
- fd = -1;
+ php_stream_close(stream);
+ stream = NULL;
internal_loaded:
*magicp = mm;
if (fn == NULL) {
*nmagicp = (sizeof(php_magic_database) / sizeof(struct magic));
} else {
- *nmagicp = (uint32_t)(st.st_size / sizeof(struct magic));
+ *nmagicp = (uint32_t)(st.sb.st_size / sizeof(struct magic));
}
if (*nmagicp > 0) {
(*nmagicp)--;
return ret;
error1:
- if (fd != -1)
- (void)close(fd);
+ if (stream) {
+ php_stream_close(stream);
+ }
if (mm) {
efree(mm);
} else {
apprentice_compile(struct magic_set *ms, struct magic **magicp,
uint32_t *nmagicp, const char *fn)
{
- int fd;
char *dbname;
int rv = -1;
+ php_stream *stream;
+
+ TSRMLS_FETCH();
mkdbname(fn, &dbname, 1);
- if (dbname == NULL)
+ if (dbname == NULL) {
goto out;
+ }
- if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) {
+/* wb+ == O_WRONLY|O_CREAT|O_TRUNC|O_BINARY */
+#if (PHP_MAJOR_VERSION < 6)
+ stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+#else
+ stream = php_stream_open_wrapper((char *)fn, "wb+", REPORT_ERRORS, NULL);
+#endif
+
+ if (!stream) {
file_error(ms, errno, "cannot open `%s'", dbname);
goto out;
}
- if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
+ if (php_stream_write(stream, (char *)ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
file_error(ms, errno, "error writing `%s'", dbname);
goto out;
}
- if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET)
- != sizeof(struct magic)) {
+ if (php_stream_seek(stream,(off_t)sizeof(struct magic), SEEK_SET) != sizeof(struct magic)) {
file_error(ms, errno, "error seeking `%s'", dbname);
goto out;
}
- if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp))
- != (ssize_t)(sizeof(struct magic) * *nmagicp)) {
+ if (php_stream_write(stream, (char *)*magicp, (sizeof(struct magic) * *nmagicp) != (ssize_t)(sizeof(struct magic) * *nmagicp))) {
file_error(ms, errno, "error writing `%s'", dbname);
goto out;
}
- (void)close(fd);
+ php_stream_close(stream);
+
rv = 0;
out:
efree(dbname);
#include <string.h>
#include <errno.h>
#include <sys/types.h>
+#ifndef PHP_WIN32
#include <sys/ioctl.h>
+#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <zlib.h>
#endif
+#undef FIONREAD
#ifndef lint
FILE_RCSID("@(#)$File: compress.c,v 1.56 2008/02/07 00:58:52 christos Exp $")
private ssize_t swrite(int, const void *, size_t);
+#ifdef PHP_FILEINFO_UNCOMPRESS
private size_t uncompressbuf(struct magic_set *, int, size_t,
const unsigned char *, unsigned char **, size_t);
#ifdef BUILTIN_DECOMPRESS
ms->flags |= MAGIC_COMPRESS;
return rv;
}
+#endif
/*
* `safe' write for sockets and pipes.
return fd;
}
+#ifdef PHP_FILEINFO_UNCOMPRESS
#ifdef BUILTIN_DECOMPRESS
#define FHCRC (1 << 1)
#define FNAME (1 << 3)
#define FCOMMENT (1 << 4)
+
private size_t
uncompressgzipped(struct magic_set *ms, const unsigned char *old,
unsigned char **newch, size_t n)
return n;
}
}
+#endif /* if PHP_FILEINFO_UNCOMPRESS */
#ifndef __file_h__
#define __file_h__
-//#ifdef HAVE_CONFIG_H
#include "config.h"
-//#endif */
#include <stdio.h> /* Include that here, to make sure __P gets defined */
#include <errno.h>
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
+#ifdef PHP_WIN32
+#include "win32/php_stdint.h"
+#endif
#include "php.h"
#include "ext/standard/php_string.h"
#define MAGIC "/etc/magic"
#endif
-#ifdef __EMX__
+#if defined(__EMX__) || defined(PHP_WIN32)
#define PATHSEP ';'
#else
#define PATHSEP ':'
struct stat;
protected const char *file_fmttime(uint32_t, int);
-protected int file_buffer(struct magic_set *, int, const char *, const void *,
+protected int file_buffer(struct magic_set *, php_stream *, const char *, const void *,
size_t);
-protected int file_fsmagic(struct magic_set *, const char *, struct stat *);
+protected int file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream);
protected int file_pipe2file(struct magic_set *, int, const void *, size_t);
protected int file_printf(struct magic_set *, const char *, ...);
protected int file_reset(struct magic_set *);
protected int file_tryelf(struct magic_set *, int, const unsigned char *,
size_t);
+#ifdef PHP_FILEINFO_UNCOMPRESS
protected int file_zmagic(struct magic_set *, int, const char *,
const unsigned char *, size_t);
+#endif
protected int file_ascmagic(struct magic_set *, const unsigned char *, size_t);
protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, int);
FILE_RCSID("@(#)$File: fsmagic.c,v 1.50 2008/02/12 17:22:54 rrt Exp $")
#endif /* lint */
-private int
-bad_link(struct magic_set *ms, int err, char *buf)
-{
- char *errfmt;
- if (err == ELOOP)
- errfmt = "symbolic link in a loop";
- else
- errfmt = "broken symbolic link to `%s'";
- if (ms->flags & MAGIC_ERROR) {
- file_error(ms, err, errfmt, buf);
- return -1;
- }
- if (file_printf(ms, errfmt, buf) == -1)
- return -1;
- return 1;
-}
+#ifdef PHP_WIN32
-protected int
-file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
-{
- int ret = 0;
- int mime = ms->flags & MAGIC_MIME;
-#ifdef S_IFLNK
- char buf[BUFSIZ+4];
- int nch;
- struct stat tstatbuf;
+# undef S_IFIFO
#endif
- if (fn == NULL)
- return 0;
- /*
- * Fstat is cheaper but fails for files you don't have read perms on.
- * On 4.2BSD and similar systems, use lstat() to identify symlinks.
- */
-#ifdef S_IFLNK
- if ((ms->flags & MAGIC_SYMLINK) == 0)
- ret = lstat(fn, sb);
- else
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode) & _S_IFDIR)
#endif
- ret = stat(fn, sb); /* don't merge into if; see "ret =" above */
- if (ret) {
- if (ms->flags & MAGIC_ERROR) {
- file_error(ms, errno, "cannot stat `%s'", fn);
- return -1;
- }
- if (file_printf(ms, "cannot open `%s' (%s)",
- fn, strerror(errno)) == -1)
- return -1;
- return 1;
+#ifndef S_ISREG
+#define S_ISREG(mode) ((mode) & _S_IFREG)
+#endif
+
+protected int
+file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
+{
+ int mime = ms->flags & MAGIC_MIME;
+ TSRMLS_FETCH();
+
+ if (!fn && !stream) {
+ return -1;
}
- if (mime) {
- if ((sb->st_mode & S_IFMT) != S_IFREG) {
- if ((mime & MAGIC_MIME_TYPE) &&
- file_printf(ms, "application/x-not-regular-file")
- == -1)
- return -1;
+ if (stream) {
+ php_stream_statbuf ssb;
+ if (php_stream_stat(stream, &ssb) < 0) {
+ if (ms->flags & MAGIC_ERROR) {
+ file_error(ms, errno, "cannot stat `%s'", fn);
+ }
+ return 1;
+ }
+ memcpy(sb, &ssb.sb, sizeof(struct stat));
+ } else {
+ if (php_sys_stat(fn, sb) != 0) {
+ if (ms->flags & MAGIC_ERROR) {
+ file_error(ms, errno, "cannot stat `%s'", fn);
+ }
return 1;
}
}
- else {
+
+ if (mime) {
+ if (!S_ISREG(sb->st_mode)) {
+ if ((mime & MAGIC_MIME_TYPE) &&
+ file_printf(ms, "application/x-not-regular-file") == -1) {
+ return -1;
+ }
+ return 1;
+ }
+
+ if (S_ISDIR(sb->st_mode)) {
+ if (file_printf(ms, "directory") == -1) {
+ return -1;
+ }
+ return 1;
+ }
+ } else {
#ifdef S_ISUID
if (sb->st_mode & S_ISUID)
if (file_printf(ms, "setuid ") == -1)
return -1;
#endif
}
-
+
switch (sb->st_mode & S_IFMT) {
- case S_IFDIR:
- if (file_printf(ms, "directory") == -1)
- return -1;
- return 1;
-#ifdef S_IFCHR
- case S_IFCHR:
- /*
- * If -s has been specified, treat character special files
- * like ordinary files. Otherwise, just report that they
- * are block special files and go on to the next file.
- */
- if ((ms->flags & MAGIC_DEVICES) != 0)
- break;
-#ifdef HAVE_STAT_ST_RDEV
-# ifdef dv_unit
- if (file_printf(ms, "character special (%d/%d/%d)",
- major(sb->st_rdev), dv_unit(sb->st_rdev),
- dv_subunit(sb->st_rdev)) == -1)
- return -1;
-# else
- if (file_printf(ms, "character special (%ld/%ld)",
- (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
- return -1;
-# endif
-#else
- if (file_printf(ms, "character special") == -1)
- return -1;
-#endif
- return 1;
-#endif
-#ifdef S_IFBLK
- case S_IFBLK:
- /*
- * If -s has been specified, treat block special files
- * like ordinary files. Otherwise, just report that they
- * are block special files and go on to the next file.
- */
- if ((ms->flags & MAGIC_DEVICES) != 0)
- break;
-#ifdef HAVE_STAT_ST_RDEV
-# ifdef dv_unit
- if (file_printf(ms, "block special (%d/%d/%d)",
- major(sb->st_rdev), dv_unit(sb->st_rdev),
- dv_subunit(sb->st_rdev)) == -1)
- return -1;
-# else
- if (file_printf(ms, "block special (%ld/%ld)",
- (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
- return -1;
+#ifndef PHP_WIN32
+# ifdef S_IFCHR
+ case S_IFCHR:
+ /*
+ * If -s has been specified, treat character special files
+ * like ordinary files. Otherwise, just report that they
+ * are block special files and go on to the next file.
+ */
+ if ((ms->flags & MAGIC_DEVICES) != 0) {
+ break;
+ }
+# ifdef HAVE_STAT_ST_RDEV
+# ifdef dv_unit
+ if (file_printf(ms, "character special (%d/%d/%d)",
+ major(sb->st_rdev), dv_unit(sb->st_rdev),
+ dv_subunit(sb->st_rdev)) == -1) {
+ return -1;
+ }
+# else
+ if (file_printf(ms, "character special (%ld/%ld)",
+ (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1) {
+ return -1;
+ }
+# endif
+# else
+ if (file_printf(ms, "character special") == -1) {
+ return -1;
+ }
+# endif
+ return 1;
# endif
-#else
- if (file_printf(ms, "block special") == -1)
- return -1;
-#endif
- return 1;
#endif
- /* TODO add code to handle V7 MUX and Blit MUX files */
+
#ifdef S_IFIFO
case S_IFIFO:
if((ms->flags & MAGIC_DEVICES) != 0)
return -1;
return 1;
#endif
+
#ifdef S_IFLNK
case S_IFLNK:
- if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
+ /* stat is used, if it made here then the link is broken */
if (ms->flags & MAGIC_ERROR) {
- file_error(ms, errno, "unreadable symlink `%s'",
- fn);
+ file_error(ms, errno, "unreadable symlink `%s'", fn);
return -1;
}
- if (file_printf(ms,
- "unreadable symlink `%s' (%s)", fn,
- strerror(errno)) == -1)
- return -1;
- return 1;
- }
- buf[nch] = '\0'; /* readlink(2) does not do this */
-
- /* If broken symlink, say so and quit early. */
- if (*buf == '/') {
- if (stat(buf, &tstatbuf) < 0)
- return bad_link(ms, errno, buf);
- } else {
- char *tmp;
- char buf2[BUFSIZ+BUFSIZ+4];
-
- if ((tmp = strrchr(fn, '/')) == NULL) {
- tmp = buf; /* in current directory anyway */
- } else {
- if (tmp - fn + 1 > BUFSIZ) {
- if (ms->flags & MAGIC_ERROR) {
- file_error(ms, 0,
- "path too long: `%s'", buf);
- return -1;
- }
- if (file_printf(ms,
- "path too long: `%s'", fn) == -1)
- return -1;
- return 1;
- }
- (void)strcpy(buf2, fn); /* take dir part */
- buf2[tmp - fn + 1] = '\0';
- (void)strcat(buf2, buf); /* plus (rel) link */
- tmp = buf2;
- }
- if (stat(tmp, &tstatbuf) < 0)
- return bad_link(ms, errno, buf);
- }
-
- /* Otherwise, handle it. */
- if ((ms->flags & MAGIC_SYMLINK) != 0) {
- const char *p;
- ms->flags &= MAGIC_SYMLINK;
- p = magic_file(ms, buf);
- ms->flags |= MAGIC_SYMLINK;
- return p != NULL ? 1 : -1;
- } else { /* just print what it points to */
- if (file_printf(ms, "symbolic link to `%s'",
- buf) == -1)
- return -1;
- }
return 1;
#endif
+
#ifdef S_IFSOCK
#ifndef __COHERENT__
case S_IFSOCK:
return 1;
#endif
#endif
- case S_IFREG:
- break;
- default:
- file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
- return -1;
- /*NOTREACHED*/
+
+ case S_IFREG:
+ break;
+
+ default:
+ file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
+ return -1;
+ /*NOTREACHED*/
}
/*
}
protected int
-file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
+file_buffer(struct magic_set *ms, php_stream *stream, const char *inname, const void *buf,
size_t nb)
{
int m;
return 1;
}
-#ifdef __EMX__
+#if defined(__EMX__)
if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
switch (file_os2_apptype(ms, inname, buf, nb)) {
case -1:
}
#endif
+#if PHP_FILEINFO_UNCOMPRESS
/* try compression stuff */
if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 ||
- (m = file_zmagic(ms, fd, inname, buf, nb)) == 0) {
- /* Check if we have a tar file */
- if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 ||
- (m = file_is_tar(ms, buf, nb)) == 0) {
- /* try tests in /etc/magic (or surrogate magic file) */
- if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 ||
- (m = file_softmagic(ms, buf, nb, BINTEST)) == 0) {
- /* try known keywords, check whether it is ASCII */
- if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 ||
- (m = file_ascmagic(ms, buf, nb)) == 0) {
- /* abandon hope, all ye who remain here */
- if ((!mime || (mime & MAGIC_MIME_TYPE)) &&
- file_printf(ms, mime ? "application/octet-stream" :
- "data") == -1)
- return -1;
- m = 1;
- }
- }
+ (m = file_zmagic(ms, stream, inname, buf, nb)) == 0)
+#endif
+ {
+ /* Check if we have a tar file */
+ if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 || (m = file_is_tar(ms, buf, nb)) == 0) {
+ /* try tests in /etc/magic (or surrogate magic file) */
+ if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 || (m = file_softmagic(ms, buf, nb, BINTEST)) == 0) {
+ /* try known keywords, check whether it is ASCII */
+ if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 || (m = file_ascmagic(ms, buf, nb)) == 0) {
+ /* abandon hope, all ye who remain here */
+ if ((!mime || (mime & MAGIC_MIME_TYPE)) && file_printf(ms, mime ? "application/octet-stream" : "data") == -1) {
+ return -1;
+ }
+ m = 1;
+ }
+ }
}
}
#ifdef BUILTIN_ELF
- if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 &&
- nb > 5 && fd != -1) {
+ if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && nb > 5 && fd != -1) {
/*
* We matched something in the file, so this *might*
* be an ELF file, and the file is at least 5 bytes
* information from the ELF headers that cannot easily
* be extracted with rules in the magic file.
*/
- (void)file_tryelf(ms, fd, buf, nb);
+ (void)file_tryelf(ms, stream, buf, nb);
}
#endif
return m;
#include <stdio.h>
#include <stdlib.h>
+#ifdef PHP_WIN32
+#include "win32/unistd.h"
+#else
#include <unistd.h>
+#endif
#include <string.h>
#include <sys/types.h>
-#include <sys/param.h> /* for MAXPATHLEN */
+#ifdef PHP_WIN32
+# include "config.w32.h"
+#else
+# include "php_config.h"
+#endif
+
#include <sys/stat.h>
#include <limits.h> /* for PIPE_BUF */
#include <locale.h>
#endif
-#include <netinet/in.h> /* for byte swapping */
+#ifndef PHP_WIN32
+# include <netinet/in.h> /* for byte swapping */
+#endif
#include "patchlevel.h"
#endif
#endif
+#ifdef PHP_WIN32
+# undef S_IFLNK
+# undef S_IFIFO
+#endif
+
#ifdef __EMX__
private char *apptypeName = NULL;
protected int file_os2_apptype(struct magic_set *ms, const char *fn,
private void close_and_restore(const struct magic_set *, const char *, int,
const struct stat *);
private int info_from_stat(struct magic_set *, mode_t);
-private const char *file_or_fd(struct magic_set *, const char *, int);
+private const char *file_or_stream(struct magic_set *, const char *, php_stream *);
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
close_and_restore(const struct magic_set *ms, const char *name, int fd,
const struct stat *sb)
{
- if (fd == STDIN_FILENO)
- return;
- (void) close(fd);
if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
/*
public const char *
magic_descriptor(struct magic_set *ms, int fd)
{
- return file_or_fd(ms, NULL, fd);
+ return file_or_stream(ms, NULL, NULL);
}
/*
public const char *
magic_file(struct magic_set *ms, const char *inname)
{
- return file_or_fd(ms, inname, STDIN_FILENO);
+ return file_or_stream(ms, inname, NULL);
+}
+
+public const char *
+magic_stream(struct magic_set *ms, php_stream *stream)
+{
+ return file_or_stream(ms, NULL, stream);
}
private const char *
-file_or_fd(struct magic_set *ms, const char *inname, int fd)
+file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
{
int rv = -1;
unsigned char *buf;
struct stat sb;
ssize_t nbytes = 0; /* number of bytes read from a datafile */
- int ispipe = 0;
+ int no_in_stream = 0;
+ TSRMLS_FETCH();
+
+ if (!inname && !stream) {
+ return NULL;
+ }
/*
* one extra for terminating '\0', and
#define SLOP (1 + sizeof(union VALUETYPE))
buf = emalloc(HOWMANY + SLOP);
- if (file_reset(ms) == -1)
+ if (file_reset(ms) == -1) {
goto done;
+ }
- switch (file_fsmagic(ms, inname, &sb)) {
- case -1: /* error */
- goto done;
- case 0: /* nothing found */
- break;
- default: /* matched it and printed type */
+ switch (file_fsmagic(ms, inname, &sb, stream)) {
+ case -1: /* error */
+ goto done;
+ case 0: /* nothing found */
+ break;
+ default: /* matched it and printed type */
+ rv = 0;
+ goto done;
+ }
+
+ errno = 0;
+
+ if (!stream && inname) {
+ no_in_stream = 1;
+#if (PHP_MAJOR_VERSION < 6)
+ stream = php_stream_open_wrapper(inname, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+#else
+ stream = php_stream_open_wrapper(inname, "rb", REPORT_ERRORS, NULL);
+#endif
+ }
+
+ if (!stream) {
+ fprintf(stderr, "couldn't open file\n");
+ if (info_from_stat(ms, sb.st_mode) == -1)
+ goto done;
rv = 0;
goto done;
}
- if (inname == NULL) {
- if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
- ispipe = 1;
- } else {
- int flags = O_RDONLY|O_BINARY;
-
- if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
- flags |= O_NONBLOCK;
- ispipe = 1;
- }
-
- errno = 0;
- if ((fd = open(inname, flags)) < 0) {
-#ifdef __CYGWIN__
- /* FIXME: Do this with EXEEXT from autotools */
- char *tmp = alloca(strlen(inname) + 5);
- (void)strcat(strcpy(tmp, inname), ".exe");
- if ((fd = open(tmp, flags)) < 0) {
-#endif
- fprintf(stderr, "couldn't open file\n");
- if (info_from_stat(ms, sb.st_mode) == -1)
- goto done;
- rv = 0;
- goto done;
-#ifdef __CYGWIN__
- }
-#endif
- }
#ifdef O_NONBLOCK
- if ((flags = fcntl(fd, F_GETFL)) != -1) {
- flags &= ~O_NONBLOCK;
- (void)fcntl(fd, F_SETFL, flags);
- }
+/* we should be already be in non blocking mode for network socket */
#endif
- }
/*
* try looking at the first HOWMANY bytes
*/
- if (ispipe) {
- ssize_t r = 0;
-
- while ((r = sread(fd, (void *)&buf[nbytes],
- (size_t)(HOWMANY - nbytes), 1)) > 0) {
- nbytes += r;
- if (r < PIPE_BUF) break;
- }
-
- if (nbytes == 0) {
- /* We can not read it, but we were able to stat it. */
- if (info_from_stat(ms, sb.st_mode) == -1)
- goto done;
- rv = 0;
- goto done;
- }
-
- } else {
- if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
- file_error(ms, errno, "cannot read `%s'", inname);
- goto done;
- }
+ if ((nbytes = php_stream_read(stream, (char *)buf, HOWMANY)) < 0) {
+ file_error(ms, errno, "cannot read `%s'", inname);
+ goto done;
}
(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
- if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
+ if (file_buffer(ms, stream, inname, buf, (size_t)nbytes) == -1)
goto done;
rv = 0;
done:
efree(buf);
- close_and_restore(ms, inname, fd, &sb);
+
+ if (no_in_stream && stream) {
+ php_stream_close(stream);
+ }
+
+ close_and_restore(ms, inname, 0, &sb);
return rv == 0 ? file_getbuffer(ms) : NULL;
}
-
public const char *
magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
{
* The main work is done here!
* We have the file name and/or the data buffer to be identified.
*/
- if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
+ if (file_buffer(ms, NULL, NULL, buf, nb) == -1) {
return NULL;
}
return file_getbuffer(ms);
void magic_close(magic_t);
const char *magic_file(magic_t, const char *);
+const char *magic_stream(magic_t, php_stream *);
const char *magic_descriptor(magic_t, int);
const char *magic_buffer(magic_t, const void *, size_t);
var_dump(finfo_file($fp, '&'));
?>
---EXPECT--
+--EXPECTF--
+Warning: finfo_file(): Empty filename or path in %s on line %d
bool(false)
+
+Warning: finfo_file(): Empty filename or path in %s on line %d
bool(false)
+
+Warning: finfo_file(): Empty filename or path in %s on line %d
bool(false)
string(9) "directory"
+
+Warning: finfo_file(): File or path not found '&' in %s on line %d
bool(false)
Warning: mime_content_type(): Can only process string or stream arguments in %s on line %d
-Warning: mime_content_type(foo/inexistent): failed to open stream: No such file or directory in %s on line %d
+Warning: mime_content_type(): File or path not found 'foo/inexistent' in %s on line %d
Warning: mime_content_type(): Empty filename or path in %s on line %d