Compare commits
10 Commits
6defeaf607
...
1a9b32ee7a
Author | SHA1 | Date | |
---|---|---|---|
|
1a9b32ee7a | ||
|
9bd58553fa | ||
|
d809ab778f | ||
|
b4dd1e28f9 | ||
|
c7a1c900ab | ||
|
5df410a53d | ||
|
c5c4d9e169 | ||
|
0a6e10e821 | ||
|
f140859351 | ||
|
f35304a5d2 |
12
NEWS
12
NEWS
@ -1,3 +1,15 @@
|
|||||||
|
1.3.3 - Released 1-Jun-2023
|
||||||
|
--------------------------------
|
||||||
|
- Fixed HTTP chunk length parsing.
|
||||||
|
- Improved Dutch and Swedish translations.
|
||||||
|
- Fixed directory symlink deletion handling.
|
||||||
|
|
||||||
|
1.3.2 - Released 30-Aug-2022
|
||||||
|
--------------------------------
|
||||||
|
- Improved DNS rebinding attack protection.
|
||||||
|
- Added Samsung Neo QLED series (2021) support.
|
||||||
|
- Added webm/rm/rmvb support.
|
||||||
|
|
||||||
1.3.1 - Released 11-Feb-2022
|
1.3.1 - Released 11-Feb-2022
|
||||||
--------------------------------
|
--------------------------------
|
||||||
- Fixed a potential crash in SSDP request parsing.
|
- Fixed a potential crash in SSDP request parsing.
|
||||||
|
@ -9,5 +9,5 @@ export BR2_EXTERNAL=$(realpath .)
|
|||||||
cd $BUILDROOT_DIR
|
cd $BUILDROOT_DIR
|
||||||
make O=output-readymedia defconfig BR2_DEFCONFIG=${BR2_DEFCONFIG}
|
make O=output-readymedia defconfig BR2_DEFCONFIG=${BR2_DEFCONFIG}
|
||||||
make O=output-readymedia
|
make O=output-readymedia
|
||||||
echo -e "\n\nStatic binary built in $(realpath output/target/usr/sbin/minidlnad)"
|
echo -e "\n\nStatic binary built in $(realpath output-readymedia/target/usr/sbin/minidlnad)"
|
||||||
ls -lh $(realpath output/target/usr/sbin/minidlnad)
|
ls -lh $(realpath output-readymedia/target/usr/sbin/minidlnad)
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
READYMEDIA_VERSION = v1_3_1
|
READYMEDIA_VERSION = v1_3_3
|
||||||
READYMEDIA_SITE = https://git.code.sf.net/p/minidlna/git
|
READYMEDIA_SITE = https://git.code.sf.net/p/minidlna/git
|
||||||
|
#READYMEDIA_SITE = ssh://localhost/home/jmaggard/source/minidlna
|
||||||
READYMEDIA_SITE_METHOD = git
|
READYMEDIA_SITE_METHOD = git
|
||||||
READYMEDIA_LICENSE = GPL-2.0, BSD-3-Clause
|
READYMEDIA_LICENSE = GPL-2.0, BSD-3-Clause
|
||||||
READYMEDIA_LICENSE_FILES = COPYING LICENCE.miniupnpd
|
READYMEDIA_LICENSE_FILES = COPYING LICENCE.miniupnpd
|
||||||
|
@ -404,7 +404,7 @@ for dir in "" /usr/local $SEARCH_DIR; do
|
|||||||
AC_CHECK_LIB([exif], [exif_data_new_from_file], [LIBEXIF_LIBS="-lexif"], [unset ac_cv_lib_exif_exif_data_new_from_file; LDFLAGS="$LDFLAGS_SAVE"; continue])
|
AC_CHECK_LIB([exif], [exif_data_new_from_file], [LIBEXIF_LIBS="-lexif"], [unset ac_cv_lib_exif_exif_data_new_from_file; LDFLAGS="$LDFLAGS_SAVE"; continue])
|
||||||
break
|
break
|
||||||
done
|
done
|
||||||
test x"$ac_cv_lib_jpeg_jpeg_set_defaults" = x"yes" || AC_MSG_ERROR([Could not find libexif])
|
test x"$ac_cv_lib_exif_exif_data_new_from_file" = x"yes" || AC_MSG_ERROR([Could not find libexif])
|
||||||
AC_SUBST(LIBEXIF_LIBS)
|
AC_SUBST(LIBEXIF_LIBS)
|
||||||
|
|
||||||
LDFLAGS_SAVE="$LDFLAGS"
|
LDFLAGS_SAVE="$LDFLAGS"
|
||||||
|
24
monitor.c
24
monitor.c
@ -366,21 +366,13 @@ monitor_insert_directory(int fd, char *name, const char * path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
monitor_remove_directory(int fd, const char * path)
|
monitor_remove_tree(const char * path)
|
||||||
{
|
{
|
||||||
char * sql;
|
char * sql;
|
||||||
char **result;
|
char **result;
|
||||||
int64_t detailID = 0;
|
int64_t detailID = 0;
|
||||||
int rows, i, ret = 1;
|
int rows, i, ret = 1;
|
||||||
|
|
||||||
/* Invalidate the scanner cache so we don't insert files into non-existent containers */
|
|
||||||
valid_cache = 0;
|
|
||||||
#ifdef HAVE_WATCH
|
|
||||||
if( fd > 0 )
|
|
||||||
{
|
|
||||||
monitor_remove_watch(fd, path);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
sql = sqlite3_mprintf("SELECT ID from DETAILS where (PATH > '%q/' and PATH <= '%q/%c')"
|
sql = sqlite3_mprintf("SELECT ID from DETAILS where (PATH > '%q/' and PATH <= '%q/%c')"
|
||||||
" or PATH = '%q'", path, path, 0xFF, path);
|
" or PATH = '%q'", path, path, 0xFF, path);
|
||||||
if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) )
|
if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) )
|
||||||
@ -403,3 +395,17 @@ monitor_remove_directory(int fd, const char * path)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
monitor_remove_directory(int fd, const char * path)
|
||||||
|
{
|
||||||
|
/* Invalidate the scanner cache so we don't insert files into non-existent containers */
|
||||||
|
valid_cache = 0;
|
||||||
|
#ifdef HAVE_WATCH
|
||||||
|
if( fd > 0 )
|
||||||
|
{
|
||||||
|
monitor_remove_watch(fd, path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return monitor_remove_tree(path);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
int monitor_insert_file(const char *name, const char *path);
|
int monitor_insert_file(const char *name, const char *path);
|
||||||
int monitor_insert_directory(int fd, char *name, const char * path);
|
int monitor_insert_directory(int fd, char *name, const char * path);
|
||||||
int monitor_remove_file(const char * path);
|
int monitor_remove_file(const char * path);
|
||||||
|
int monitor_remove_tree(const char * path);
|
||||||
int monitor_remove_directory(int fd, const char * path);
|
int monitor_remove_directory(int fd, const char * path);
|
||||||
|
|
||||||
#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
|
#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
|
||||||
|
@ -366,7 +366,16 @@ inotify_thread(void *arg)
|
|||||||
if ( event->mask & IN_ISDIR )
|
if ( event->mask & IN_ISDIR )
|
||||||
monitor_remove_directory(pollfds[0].fd, path_buf);
|
monitor_remove_directory(pollfds[0].fd, path_buf);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
monitor_remove_file(path_buf);
|
monitor_remove_file(path_buf);
|
||||||
|
/*
|
||||||
|
* When a symlink to a directory is deleted
|
||||||
|
* we cannot tell it from a regular file deletion
|
||||||
|
* to prevent its children from becoming orphans
|
||||||
|
* we delete the whole tree when it exists
|
||||||
|
*/
|
||||||
|
monitor_remove_tree(path_buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(esc_name);
|
free(esc_name);
|
||||||
}
|
}
|
||||||
|
14
po/nl.po
14
po/nl.po
@ -46,7 +46,7 @@ msgstr "Muziek"
|
|||||||
|
|
||||||
#: scanner.c:529
|
#: scanner.c:529
|
||||||
msgid "All Music"
|
msgid "All Music"
|
||||||
msgstr "Alle muziek bestanden"
|
msgstr "Alle muziekbestanden"
|
||||||
|
|
||||||
#: scanner.c:530
|
#: scanner.c:530
|
||||||
msgid "Genre"
|
msgid "Genre"
|
||||||
@ -70,7 +70,7 @@ msgstr "Afspeellijst"
|
|||||||
|
|
||||||
#: scanner.c:598
|
#: scanner.c:598
|
||||||
msgid "Recently Added"
|
msgid "Recently Added"
|
||||||
msgstr "Nyligen tillagd"
|
msgstr "Recent toegevoegd"
|
||||||
|
|
||||||
#: scanner.c:536
|
#: scanner.c:536
|
||||||
msgid "Video"
|
msgid "Video"
|
||||||
@ -78,7 +78,7 @@ msgstr "Video"
|
|||||||
|
|
||||||
#: scanner.c:537
|
#: scanner.c:537
|
||||||
msgid "All Video"
|
msgid "All Video"
|
||||||
msgstr "Alle video bestanden"
|
msgstr "Alle videobestanden"
|
||||||
|
|
||||||
#: scanner.c:540
|
#: scanner.c:540
|
||||||
msgid "Pictures"
|
msgid "Pictures"
|
||||||
@ -86,11 +86,11 @@ msgstr "Foto's"
|
|||||||
|
|
||||||
#: scanner.c:541
|
#: scanner.c:541
|
||||||
msgid "All Pictures"
|
msgid "All Pictures"
|
||||||
msgstr "Alle foto bestanden"
|
msgstr "Alle fotobestanden"
|
||||||
|
|
||||||
#: scanner.c:542
|
#: scanner.c:542
|
||||||
msgid "Date Taken"
|
msgid "Date Taken"
|
||||||
msgstr "Opname datum"
|
msgstr "Opnamedatum"
|
||||||
|
|
||||||
#: scanner.c:543
|
#: scanner.c:543
|
||||||
msgid "Camera"
|
msgid "Camera"
|
||||||
@ -103,9 +103,9 @@ msgstr "Mappen doorzoeken"
|
|||||||
#: scanner.c:690
|
#: scanner.c:690
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Scanning %s\n"
|
msgid "Scanning %s\n"
|
||||||
msgstr "Zoeken %s\n"
|
msgstr "%s aan het scannen\n"
|
||||||
|
|
||||||
#: scanner.c:766
|
#: scanner.c:766
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Scanning %s finished (%llu files)!\n"
|
msgid "Scanning %s finished (%llu files)!\n"
|
||||||
msgstr "Zoeken %s gereed (%llu files)!\n"
|
msgstr "Scannen van %s gereed (%llu bestanden)!\n"
|
||||||
|
9
po/sv.po
9
po/sv.po
@ -46,7 +46,7 @@ msgstr "Musik"
|
|||||||
|
|
||||||
#: scanner.c:529
|
#: scanner.c:529
|
||||||
msgid "All Music"
|
msgid "All Music"
|
||||||
msgstr "All Musik"
|
msgstr "All musik"
|
||||||
|
|
||||||
#: scanner.c:530
|
#: scanner.c:530
|
||||||
msgid "Genre"
|
msgid "Genre"
|
||||||
@ -66,11 +66,11 @@ msgstr "Mappar"
|
|||||||
|
|
||||||
#: scanner.c:534
|
#: scanner.c:534
|
||||||
msgid "Playlists"
|
msgid "Playlists"
|
||||||
msgstr "Spelningslistor"
|
msgstr "Spellistor"
|
||||||
|
|
||||||
#: scanner.c:598
|
#: scanner.c:598
|
||||||
msgid "Recently Added"
|
msgid "Recently Added"
|
||||||
msgstr "nyligen tillagda"
|
msgstr "Nyss tillagt"
|
||||||
|
|
||||||
#: scanner.c:536
|
#: scanner.c:536
|
||||||
msgid "Video"
|
msgid "Video"
|
||||||
@ -108,4 +108,5 @@ msgstr "Söker %s\n"
|
|||||||
#: scanner.c:766
|
#: scanner.c:766
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Scanning %s finished (%llu files)!\n"
|
msgid "Scanning %s finished (%llu files)!\n"
|
||||||
msgstr "Avsökning %s slutförd (%llu filer)!\n"
|
msgstr "Genomsökning av %s slutförd (%llu filer)!\n"
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ static void upnp_event_recv(struct upnp_event_notify * obj)
|
|||||||
DPRINTF(E_DEBUG, L_HTTP, "%s: (%dbytes) %.*s\n", "upnp_event_recv",
|
DPRINTF(E_DEBUG, L_HTTP, "%s: (%dbytes) %.*s\n", "upnp_event_recv",
|
||||||
n, n, obj->buffer);
|
n, n, obj->buffer);
|
||||||
obj->state = EFinished;
|
obj->state = EFinished;
|
||||||
event_module.del(&obj->ev, 0);
|
event_module.del(&obj->ev, EV_FLAG_CLOSING);
|
||||||
if(obj->sub)
|
if(obj->sub)
|
||||||
{
|
{
|
||||||
obj->sub->seq++;
|
obj->sub->seq++;
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#define MINIDLNA_VERSION "1.3.1"
|
#define MINIDLNA_VERSION "1.3.3"
|
||||||
|
|
||||||
#ifdef NETGEAR
|
#ifdef NETGEAR
|
||||||
# define SERVER_NAME "ReadyDLNA"
|
# define SERVER_NAME "ReadyDLNA"
|
||||||
|
28
upnphttp.c
28
upnphttp.c
@ -432,7 +432,7 @@ next_header:
|
|||||||
if (h->req_buflen <= h->req_contentoff)
|
if (h->req_buflen <= h->req_contentoff)
|
||||||
return;
|
return;
|
||||||
while( (line < (h->req_buf + h->req_buflen)) &&
|
while( (line < (h->req_buf + h->req_buflen)) &&
|
||||||
(h->req_chunklen = strtol(line, &endptr, 16) > 0) &&
|
((h->req_chunklen = strtol(line, &endptr, 16)) > 0) &&
|
||||||
(endptr != line) )
|
(endptr != line) )
|
||||||
{
|
{
|
||||||
endptr = strstr(endptr, "\r\n");
|
endptr = strstr(endptr, "\r\n");
|
||||||
@ -915,15 +915,29 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h)
|
|||||||
|
|
||||||
DPRINTF(E_DEBUG, L_HTTP, "HTTP REQUEST: %.*s\n", h->req_buflen, h->req_buf);
|
DPRINTF(E_DEBUG, L_HTTP, "HTTP REQUEST: %.*s\n", h->req_buflen, h->req_buf);
|
||||||
if(h->req_Host && h->req_HostLen > 0) {
|
if(h->req_Host && h->req_HostLen > 0) {
|
||||||
const char *ptr = h->req_Host;
|
const char *port = memchr(h->req_Host, ':', h->req_HostLen);
|
||||||
|
size_t ip_sz = port ? (port - h->req_Host) : h->req_HostLen;
|
||||||
|
struct in_addr addr;
|
||||||
|
char ip_buf[16];
|
||||||
DPRINTF(E_MAXDEBUG, L_HTTP, "Host: %.*s\n", h->req_HostLen, h->req_Host);
|
DPRINTF(E_MAXDEBUG, L_HTTP, "Host: %.*s\n", h->req_HostLen, h->req_Host);
|
||||||
for(i = 0; i < h->req_HostLen; i++) {
|
if (port) {
|
||||||
if(*ptr != ':' && *ptr != '.' && (*ptr > '9' || *ptr < '0')) {
|
const char *ptr = port + 1;
|
||||||
DPRINTF(E_ERROR, L_HTTP, "DNS rebinding attack suspected (Host: %.*s)", h->req_HostLen, h->req_Host);
|
for (i = ip_sz + 2; i < h->req_HostLen; i++) {
|
||||||
Send404(h);/* 403 */
|
if (*ptr > '9' || *ptr < '0')
|
||||||
|
break;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
if (i != h->req_HostLen || atoi(port + 1) > 65535) {
|
||||||
|
DPRINTF(E_ERROR, L_HTTP, "DNS rebinding attack suspected (Host: %.*s)\n", h->req_HostLen, h->req_Host);
|
||||||
|
Send400(h);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ptr++;
|
}
|
||||||
|
strncpyt(ip_buf, h->req_Host, MIN(ip_sz + 1, sizeof(ip_buf)));
|
||||||
|
if (ip_sz >= sizeof(ip_buf) || inet_pton(AF_INET, ip_buf, &addr) <= 0 || !addr.s_addr) {
|
||||||
|
DPRINTF(E_ERROR, L_HTTP, "DNS rebinding attack suspected (Host: %.*s)\n", h->req_HostLen, h->req_Host);
|
||||||
|
Send400(h);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(strcmp("POST", HttpCommand) == 0)
|
if(strcmp("POST", HttpCommand) == 0)
|
||||||
|
11
upnpsoap.c
11
upnpsoap.c
@ -813,7 +813,7 @@ get_child_count(const char *object, struct magic_container_s *magic)
|
|||||||
else if (magic && magic->objectid && *(magic->objectid))
|
else if (magic && magic->objectid && *(magic->objectid))
|
||||||
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", *(magic->objectid));
|
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", *(magic->objectid));
|
||||||
else
|
else
|
||||||
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", object);
|
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%q';", object);
|
||||||
|
|
||||||
return (ret > 0) ? ret : 0;
|
return (ret > 0) ? ret : 0;
|
||||||
}
|
}
|
||||||
@ -836,6 +836,9 @@ object_exists(const char *object)
|
|||||||
static int
|
static int
|
||||||
callback(void *args, int argc, char **argv, char **azColName)
|
callback(void *args, int argc, char **argv, char **azColName)
|
||||||
{
|
{
|
||||||
|
(void)args;
|
||||||
|
(void)argc;
|
||||||
|
(void)azColName;
|
||||||
struct Response *passed_args = (struct Response *)args;
|
struct Response *passed_args = (struct Response *)args;
|
||||||
char *id = argv[0], *parent = argv[1], *refID = argv[2], *detailID = argv[3], *class = argv[4], *size = argv[5], *title = argv[6],
|
char *id = argv[0], *parent = argv[1], *refID = argv[2], *detailID = argv[3], *class = argv[4], *size = argv[5], *title = argv[6],
|
||||||
*duration = argv[7], *bitrate = argv[8], *sampleFrequency = argv[9], *artist = argv[10], *album = argv[11],
|
*duration = argv[7], *bitrate = argv[8], *sampleFrequency = argv[9], *artist = argv[10], *album = argv[11],
|
||||||
@ -1295,6 +1298,7 @@ callback(void *args, int argc, char **argv, char **azColName)
|
|||||||
static void
|
static void
|
||||||
BrowseContentDirectory(struct upnphttp * h, const char * action)
|
BrowseContentDirectory(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
|
(void)action;
|
||||||
static const char resp0[] =
|
static const char resp0[] =
|
||||||
"<u:BrowseResponse "
|
"<u:BrowseResponse "
|
||||||
"xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
"xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
||||||
@ -1817,6 +1821,7 @@ parse_search_criteria(const char *str, char *sep)
|
|||||||
static void
|
static void
|
||||||
SearchContentDirectory(struct upnphttp * h, const char * action)
|
SearchContentDirectory(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
|
(void)action;
|
||||||
static const char resp0[] =
|
static const char resp0[] =
|
||||||
"<u:SearchResponse "
|
"<u:SearchResponse "
|
||||||
"xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
"xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
||||||
@ -2063,6 +2068,7 @@ static void _kodi_decode(char *str)
|
|||||||
case '/':
|
case '/':
|
||||||
if (!str[1])
|
if (!str[1])
|
||||||
*str = '\0';
|
*str = '\0';
|
||||||
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
str++;
|
str++;
|
||||||
break;
|
break;
|
||||||
@ -2082,6 +2088,7 @@ static int duration_sec(const char *str)
|
|||||||
|
|
||||||
static void UpdateObject(struct upnphttp * h, const char * action)
|
static void UpdateObject(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
|
(void)action;
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
"<u:UpdateObjectResponse"
|
"<u:UpdateObjectResponse"
|
||||||
" xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
" xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
||||||
@ -2166,6 +2173,7 @@ static void UpdateObject(struct upnphttp * h, const char * action)
|
|||||||
static void
|
static void
|
||||||
SamsungGetFeatureList(struct upnphttp * h, const char * action)
|
SamsungGetFeatureList(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
|
(void)action;
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
"<u:X_GetFeatureListResponse xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
"<u:X_GetFeatureListResponse xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
||||||
"<FeatureList>"
|
"<FeatureList>"
|
||||||
@ -2215,6 +2223,7 @@ SamsungGetFeatureList(struct upnphttp * h, const char * action)
|
|||||||
static void
|
static void
|
||||||
SamsungSetBookmark(struct upnphttp * h, const char * action)
|
SamsungSetBookmark(struct upnphttp * h, const char * action)
|
||||||
{
|
{
|
||||||
|
(void)action;
|
||||||
static const char resp[] =
|
static const char resp[] =
|
||||||
"<u:X_SetBookmarkResponse"
|
"<u:X_SetBookmarkResponse"
|
||||||
" xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
" xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user