diff --git a/stream/stream.h b/stream/stream.h index 0f028e330d..28f9936fce 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -266,6 +266,7 @@ void mp_cancel_reset(struct mp_cancel *c); // stream_file.c char *mp_file_url_to_filename(void *talloc_ctx, bstr url); +char *mp_file_get_path(void *talloc_ctx, bstr url); void stream_print_proto_list(struct mp_log *log); diff --git a/stream/stream_dvd.c b/stream/stream_dvd.c index 857d144a65..eb055abc13 100644 --- a/stream/stream_dvd.c +++ b/stream/stream_dvd.c @@ -33,6 +33,8 @@ #include #include +#include "osdep/io.h" + #include "config.h" #include "talloc.h" #include "common/common.h" @@ -46,6 +48,7 @@ #include "stream.h" #include "options/m_option.h" #include "options/options.h" +#include "options/path.h" #include "stream_dvd_common.h" @@ -913,38 +916,37 @@ fail: return STREAM_UNSUPPORTED; } -static int ifo_stream_open (stream_t *stream) +static int ifo_stream_open(stream_t *stream) { - char* filename; dvd_priv_t *priv = talloc_ptrtype(stream, priv); stream->priv = priv; *priv = stream_priv_dflts; - // "file://" prefix -> decode URL-style escapes - if (strlen(stream->url) > strlen(stream->path)) - mp_url_unescape_inplace(stream->path); + char *path = mp_file_get_path(priv, bstr0(stream->url)); + if (!path) + goto unsupported; - int len = strlen(stream->path); - if (len < 4 || strcasecmp (stream->path + len - 4, ".ifo")) - return STREAM_UNSUPPORTED; + if (!dvd_probe(path, ".ifo", "DVDVIDEO-VTS")) + goto unsupported; - MP_INFO(stream, ".IFO detected. Redirecting to dvd://\n"); + char *base = mp_basename(path); - filename = strdup(basename(stream->path)); + // Only accept individual titles - use dvdnav for video_ts.ifo + if (strncasecmp(base, "vts_", 4)) + goto unsupported; - talloc_free(priv->cfg_device); - priv->cfg_device = talloc_strdup(NULL, dirname(stream->path)); - if(!strncasecmp(filename,"vts_",4)) - { - if(sscanf(filename+3, "_%02d_", &priv->cfg_title)!=0) - priv->cfg_title = 0; - }else - priv->cfg_title = 0; + if (sscanf(base + 3, "_%02d_", &priv->cfg_title) != 1) + goto unsupported; - free(filename); - stream->url=talloc_strdup(stream, "dvdread://"); + priv->cfg_device = bstrto0(priv, mp_dirname(path)); + MP_INFO(stream, ".IFO detected. Redirecting to dvdread://\n"); return open_s(stream); + +unsupported: + talloc_free(priv); + stream->priv = NULL; + return STREAM_UNSUPPORTED; } const stream_info_t stream_info_dvd = { diff --git a/stream/stream_dvd_common.c b/stream/stream_dvd_common.c index a9a6895384..99e9067621 100644 --- a/stream/stream_dvd_common.c +++ b/stream/stream_dvd_common.c @@ -21,6 +21,9 @@ #include #include #include +#include +#include + #include #include "config.h" @@ -42,6 +45,7 @@ #include "osdep/io.h" #include "common/msg.h" +#include "misc/bstr.h" #include "stream_dvd_common.h" const char * const dvd_audio_stream_types[8] = { "ac3","unknown","mpeg1","mpeg2ext","lpcm","unknown","dts" }; @@ -134,3 +138,28 @@ int mp_dvdtimetomsec(dvd_time_t *dt) msec += (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 100000 / framerate; return msec; } + +// Check if this is likely to be an .ifo or similar file. +int dvd_probe(const char *path, const char *ext, const char *sig) +{ + if (!bstr_case_endswith(bstr0(path), bstr0(ext))) + return false; + + FILE *temp = fopen(path, "rb"); + if (!temp) + return false; + + bool r = false; + + char data[50]; + + assert(strlen(sig) <= sizeof(data)); + + if (fread(data, 50, 1, temp) == 1) { + if (memcmp(data, sig, strlen(sig)) == 0) + r = true; + } + + fclose(temp); + return r; +} diff --git a/stream/stream_dvd_common.h b/stream/stream_dvd_common.h index a2b05e8b77..96dfbb3cb3 100644 --- a/stream/stream_dvd_common.h +++ b/stream/stream_dvd_common.h @@ -20,7 +20,7 @@ #define MPLAYER_STREAM_DVD_COMMON_H #include -#include +#include #include "stream.h" extern const char * const dvd_audio_stream_channels[6]; @@ -29,4 +29,6 @@ extern const char * const dvd_audio_stream_types[8]; void dvd_set_speed(stream_t *stream, char *device, unsigned speed); int mp_dvdtimetomsec(dvd_time_t *dt); +int dvd_probe(const char *path, const char *ext, const char *sig); + #endif /* MPLAYER_STREAM_DVD_COMMON_H */ diff --git a/stream/stream_file.c b/stream/stream_file.c index 6a10114832..eef0dcc5cc 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -126,6 +126,17 @@ char *mp_file_url_to_filename(void *talloc_ctx, bstr url) return filename; } +// Return talloc_strdup's filesystem path if local, otherwise NULL. +// Unlike mp_file_url_to_filename(), doesn't return NULL if already local. +char *mp_file_get_path(void *talloc_ctx, bstr url) +{ + if (mp_split_proto(url, &(bstr){0}).len) { + return mp_file_url_to_filename(talloc_ctx, url); + } else { + return bstrto0(talloc_ctx, url); + } +} + #if HAVE_BSD_FSTATFS static bool check_stream_network(stream_t *stream) {