From a7137b7bb9189f4df148932f060400de811bce1d Mon Sep 17 00:00:00 2001 From: Jordan Lee Date: Sun, 27 Apr 2014 19:31:10 +0000 Subject: [PATCH] upgrade miniupnp version to 1.9. update autoconf script to detect the API version; update upnp.c's #ifdefs to use the API version. --- configure.ac | 78 +++++--- libtransmission/upnp.c | 74 +++++--- third-party/miniupnp/Changelog.txt | 85 ++++++++- third-party/miniupnp/apiversions.txt | 127 +++++++++++++ third-party/miniupnp/codelength.h | 6 +- third-party/miniupnp/connecthostport.c | 36 +++- third-party/miniupnp/connecthostport.h | 11 +- third-party/miniupnp/declspec.h | 12 +- third-party/miniupnp/igd_desc_parse.h | 6 +- third-party/miniupnp/minisoap.h | 6 +- third-party/miniupnp/minissdpc.h | 6 +- third-party/miniupnp/miniupnpc.c | 171 +++++++++++++----- third-party/miniupnp/miniupnpc.h | 20 +- third-party/miniupnp/miniupnpctypes.h | 6 +- third-party/miniupnp/miniwget.c | 99 +++++++--- third-party/miniupnp/miniwget.h | 14 +- third-party/miniupnp/minixml.c | 19 +- third-party/miniupnp/minixml.h | 6 +- third-party/miniupnp/portlistingparse.c | 4 +- third-party/miniupnp/portlistingparse.h | 6 +- third-party/miniupnp/receivedata.c | 31 +++- third-party/miniupnp/receivedata.h | 12 +- .../miniupnp/updateminiupnpcstrings.sh | 49 ++--- third-party/miniupnp/upnpcommands.c | 11 +- third-party/miniupnp/upnpcommands.h | 34 +++- third-party/miniupnp/upnpreplyparse.c | 59 ++++-- third-party/miniupnp/upnpreplyparse.h | 15 +- 27 files changed, 769 insertions(+), 234 deletions(-) create mode 100644 third-party/miniupnp/apiversions.txt diff --git a/configure.ac b/configure.ac index a92ed7a6f..41a8785a0 100644 --- a/configure.ac +++ b/configure.ac @@ -243,52 +243,82 @@ dnl dnl look for preinstalled miniupnpc... dnl -AC_MSG_CHECKING([supported miniupnp library]) -upnp_version="none" ac_save_LIBS="$LIBS" LIBS="-lminiupnpc" -# See if the OS has its miniupnp 1.5 installed -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +AC_MSG_CHECKING([system miniupnpc library]) + +dnl See if ANY version of miniupnpc is installed +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], + [struct UPNPDev dev;])], + [upnp_version="unknown"], + [upnp_version="none"] +) + +dnl Let's hope it's 1.7 or higher, since it provides +dnl MINIUPNPC_API_VERSION and we won't have to figure +dnl it out on our own +if test "x$upnp_version" = "xunknown" ; then + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [#include + #include ], + [#ifdef MINIUPNPC_API_VERSION + return EXIT_SUCCESS; + #else + return EXIT_FAILURE; + #endif] + )], + [upnp_version=">= 1.7"] + ) +fi + +dnl Or maybe it's miniupnp 1.6 +if test "x$upnp_version" = "xunknown" ; then + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include + #include #include #include -]], [[ + ]], [[ struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; + struct UPNPUrls urls; + struct IGDdatas data; char lanaddr[16]; char portStr[8]; char intPort[8]; char intClient[16]; - upnpDiscover( 2000, NULL, NULL, 0 ); + upnpDiscover( 2000, NULL, NULL, 0, 0, &errno ); UPNP_GetValidIGD( devlist, &urls, &data, lanaddr, sizeof( lanaddr ) ); UPNP_GetSpecificPortMappingEntry( urls.controlURL, data.first.servicetype, - portStr, "TCP", intClient, intPort ); -]])],[ -AC_DEFINE(HAVE_MINIUPNP_15, 1, [Define to 1 if you have miniupnpc version 1.5]) -upnp_version="1.5"],[]) + portStr, "TCP", intClient, intPort, NULL, NULL, NULL ); + ]])],[ + AC_DEFINE(MINIUPNPC_API_VERSION, 8, [miniupnpc 1.6's API version is 8]) + upnp_version="1.6"]) +fi -# See if the OS has its miniupnp 1.6 installed -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +dnl Or maybe it's miniupnp 1.5 +if test "x$upnp_version" = "xunknown" ; then + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include - #include #include #include -]], [[ + ]], [[ struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; + struct UPNPUrls urls; + struct IGDdatas data; char lanaddr[16]; char portStr[8]; char intPort[8]; char intClient[16]; - upnpDiscover( 2000, NULL, NULL, 0, 0, &errno ); + upnpDiscover( 2000, NULL, NULL, 0 ); UPNP_GetValidIGD( devlist, &urls, &data, lanaddr, sizeof( lanaddr ) ); UPNP_GetSpecificPortMappingEntry( urls.controlURL, data.first.servicetype, - portStr, "TCP", intClient, intPort, NULL, NULL, NULL ); -]])],[ -AC_DEFINE(HAVE_MINIUPNP_16, 1, [Define to 1 if you have miniupnpc version 1.6]) -upnp_version="1.6"],[]) + portStr, "TCP", intClient, intPort ); + ]])],[ + AC_DEFINE(MINIUPNPC_API_VERSION, 5, [miniupnpc 1.5's API version is 5]) + upnp_version="1.5"]) +fi # ... and the results of our tests LIBS="$ac_save_LIBS" @@ -298,8 +328,6 @@ if test "x$upnp_version" = "xnone" ; then LIBUPNP_CFLAGS="-I\$(top_srcdir)/third-party/" LIBUPNP_LIBS="\$(top_builddir)/third-party/miniupnp/libminiupnp.a" LIBUPNP_LIBS_QT="\$\${TRANSMISSION_TOP}/third-party/miniupnp/libminiupnp.a" - dnl because this is the version that we bundle... - AC_DEFINE(HAVE_MINIUPNP_16, 1, [Define to 1 if you have miniupnpc version 1.6]) else AC_DEFINE([SYSTEM_MINIUPNP]) LIBUPNP_CFLAGS="" diff --git a/libtransmission/upnp.c b/libtransmission/upnp.c index 0513f4f48..b280c10c6 100644 --- a/libtransmission/upnp.c +++ b/libtransmission/upnp.c @@ -18,10 +18,6 @@ #include #endif -#ifdef SYS_DARWIN - #define HAVE_MINIUPNP_16 1 -#endif - #include "transmission.h" #include "log.h" #include "port-forwarding.h" @@ -87,20 +83,22 @@ tr_upnpClose (tr_upnp * handle) static struct UPNPDev * tr_upnpDiscover (int msec) { - struct UPNPDev * ret = NULL; - -#if defined (HAVE_MINIUPNP_16) - int err = UPNPDISCOVER_SUCCESS; - ret = upnpDiscover (msec, NULL, NULL, 0, 0, &err); - if (err != UPNPDISCOVER_SUCCESS) -#elif defined (HAVE_MINIUPNP_15) - ret = upnpDiscover (msec, NULL, NULL, 0); - if (ret == NULL) + struct UPNPDev * ret; + bool have_err; + +#if (MINIUPNPC_API_VERSION >= 8) /* adds ipv6 and error args */ + int err = UPNPDISCOVER_SUCCESS; + ret = upnpDiscover (msec, NULL, NULL, 0, 0, &err); + have_err = err != UPNPDISCOVER_SUCCESS; +#else + ret = upnpDiscover (msec, NULL, NULL, 0); + have_err = ret == NULL; #endif - tr_logAddNamedDbg (getKey (), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror (errno)); + if (have_err) + tr_logAddNamedDbg (getKey (), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror (errno)); - return ret; + return ret; } static int @@ -114,14 +112,42 @@ tr_upnpGetSpecificPortMappingEntry (tr_upnp * handle, const char * proto) *intClient = '\0'; *intPort = '\0'; - tr_snprintf (portStr, sizeof (portStr), "%d", (int)handle->port); + tr_snprintf (portStr, sizeof(portStr), "%d", (int)handle->port); + +#if (MINIUPNPC_API_VERSION >= 10) /* adds remoteHost arg */ + + err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, + handle->data.first.servicetype, + portStr, + proto, + NULL /*remoteHost*/, + intClient, + intPort, + NULL /*desc*/, + NULL /*enabled*/, + NULL /*duration*/); + +#elif (MINIUPNPC_API_VERSION >= 8) /* adds desc, enabled and leaseDuration args */ + + err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, + handle->data.first.servicetype, + portStr, + proto, + intClient, + intPort, + NULL /*desc*/, + NULL /*enabled*/, + NULL /*duration*/); -#if defined (HAVE_MINIUPNP_16) - err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, handle->data.first.servicetype, portStr, proto, intClient, intPort, NULL, NULL, NULL); -#elif defined (HAVE_MINIUPNP_15) - err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, handle->data.first.servicetype, portStr, proto, intClient, intPort); #else - err = UPNPCOMMAND_UNKNOWN_ERROR; + + err = UPNP_GetSpecificPortMappingEntry (handle->urls.controlURL, + handle->data.first.servicetype, + portStr, + proto, + intClient, + intPort); + #endif return err; @@ -137,12 +163,10 @@ tr_upnpAddPortMapping (const tr_upnp * handle, const char * proto, tr_port port, tr_snprintf (portStr, sizeof (portStr), "%d", (int)port); -#if defined (HAVE_MINIUPNP_16) +#if (MINIUPNPC_API_VERSION >= 8) err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL, NULL); -#elif defined (HAVE_MINIUPNP_15) - err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL); #else - err = UPNPCOMMAND_UNKNOWN_ERROR; + err = UPNP_AddPortMapping (handle->urls.controlURL, handle->data.first.servicetype, portStr, portStr, handle->lanaddr, desc, proto, NULL); #endif if (err) diff --git a/third-party/miniupnp/Changelog.txt b/third-party/miniupnp/Changelog.txt index 4503ace17..53e9a112b 100644 --- a/third-party/miniupnp/Changelog.txt +++ b/third-party/miniupnp/Changelog.txt @@ -1,6 +1,89 @@ -$Id: Changelog.txt,v 1.169 2012/05/24 18:08:49 nanard Exp $ +$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $ miniUPnP client Changelog. +2014/02/05: + handle EINPROGRESS after connect() + +2014/02/03: + minixml now handle XML comments + +VERSION 1.9 : released 2014/01/31 + +2014/01/31: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + increment API_VERSION to 10 + +2013/12/09: + --help and -h arguments in upnpc.c + +2013/10/07: + fixed potential buffer overrun in miniwget.c + Modified UPNP_GetValidIGD() to check for ExternalIpAddress + +2013/08/01: + define MAXHOSTNAMELEN if not already done + +2013/06/06: + update upnpreplyparse to allow larger values (128 chars instead of 64) + +2013/05/14: + Update upnpreplyparse to take into account "empty" elements + validate upnpreplyparse.c code with "make check" + +2013/05/03: + Fix Solaris build thanks to Maciej Małecki + +2013/04/27: + Fix testminiwget.sh for BSD + +2013/03/23: + Fixed Makefile for *BSD + +2013/03/11: + Update Makefile to use JNAerator version 0.11 + +2013/02/11: + Fix testminiwget.sh for use with dash + Use $(DESTDIR) in Makefile + +VERSION 1.8 : released 2013/02/06 + +2012/10/16: + fix testminiwget with no IPv6 support + +2012/09/27: + Rename all include guards to not clash with C99 + (7.1.3 Reserved identifiers). + +2012/08/30: + Added -e option to upnpc program (set description for port mappings) + +2012/08/29: + Python 3 support (thanks to Christopher Foo) + +2012/08/11: + Fix a memory link in UPNP_GetValidIGD() + Try to handle scope id in link local IPv6 URL under MS Windows + +2012/07/20: + Disable HAS_IP_MREQN on DragonFly BSD + +2012/06/28: + GetUPNPUrls() now inserts scope into link-local IPv6 addresses + +2012/06/23: + More error return checks in upnpc.c + #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id + parseURL() now parses IPv6 addresses scope + new parameter for miniwget() : IPv6 address scope + increment API_VERSION to 9 + +2012/06/20: + fixed CMakeLists.txt + +2012/05/29 + Improvements in testminiwget.sh + VERSION 1.7 : released 2012/05/24 2012/05/01: diff --git a/third-party/miniupnp/apiversions.txt b/third-party/miniupnp/apiversions.txt new file mode 100644 index 000000000..69f61c799 --- /dev/null +++ b/third-party/miniupnp/apiversions.txt @@ -0,0 +1,127 @@ +$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $ + +Differences in API between miniUPnPc versions + +====================== miniUPnPc version 1.9 ====================== +API version 10 + +upnpcommands.h: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.9" + #define MINIUPNPC_API_VERSION 10 + +====================== miniUPnPc version 1.8 ====================== +API version 9 + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.8" + #define MINIUPNPC_API_VERSION 9 + added "unsigned int scope_id;" to struct UPNPDev + added scope_id argument to GetUPNPUrls() + + + +====================== miniUPnPc version 1.7 ====================== +API version 8 + +miniupnpc.h : + add new macros : + #define MINIUPNPC_VERSION "1.7" + #define MINIUPNPC_API_VERSION 8 + add rootdescURL to struct UPNPUrls + + + +====================== miniUPnPc version 1.6 ====================== +API version 8 + +Adding support for IPv6. +igd_desc_parse.h : + struct IGDdatas_service : + add char presentationurl[MINIUPNPC_URL_MAXSIZE]; + struct IGDdatas : + add struct IGDdatas_service IPv6FC; +miniupnpc.h : + new macros : + #define UPNPDISCOVER_SUCCESS (0) + #define UPNPDISCOVER_UNKNOWN_ERROR (-1) + #define UPNPDISCOVER_SOCKET_ERROR (-101) + #define UPNPDISCOVER_MEMORY_ERROR (-102) + simpleUPnPcommand() prototype changed (but is normaly not used by API users) + add arguments ipv6 and error to upnpDiscover() : + struct UPNPDev * + upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport, + int ipv6, + int * error); + add controlURL_6FC member to struct UPNPUrls : + struct UPNPUrls { + char * controlURL; + char * ipcondescURL; + char * controlURL_CIF; + char * controlURL_6FC; + }; + +upnpcommands.h : + add leaseDuration argument to UPNP_AddPortMapping() + add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry() + add UPNP_GetListOfPortMappings() function (IGDv2) + add IGDv2 IPv6 related functions : + UPNP_GetFirewallStatus() + UPNP_GetOutboundPinholeTimeout() + UPNP_AddPinhole() + UPNP_UpdatePinhole() + UPNP_DeletePinhole() + UPNP_CheckPinholeWorking() + UPNP_GetPinholePackets() + + + +====================== miniUPnPc version 1.5 ====================== +API version 5 + +new function : +int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); +new macro in upnpcommands.h : +#define UPNPCOMMAND_HTTP_ERROR + +====================== miniUPnPc version 1.4 ====================== +Same API as version 1.3 + +====================== miniUPnPc version 1.3 ====================== +API version 4 + +Use UNSIGNED_INTEGER type for +UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(), +UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived() +Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping() + +====================== miniUPnPc version 1.2 ====================== +API version 3 + +added sameport argument to upnpDiscover() +struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock, int sameport); + +====================== miniUPnPc Version 1.1 ====================== +Same API as 1.0 + + +====================== miniUPnPc Version 1.0 ====================== +API version 2 + + +struct UPNPDev { + struct UPNPDev * pNext; + char * descURL; + char * st; + char buffer[2]; +}; +struct UPNPDev * upnpDiscover(int delay, const char * multicastif, + const char * minissdpdsock); + diff --git a/third-party/miniupnp/codelength.h b/third-party/miniupnp/codelength.h index e89aeb01a..d342bd141 100644 --- a/third-party/miniupnp/codelength.h +++ b/third-party/miniupnp/codelength.h @@ -1,11 +1,11 @@ -/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */ +/* $Id: codelength.h,v 1.4 2012/09/27 15:40:29 nanard Exp $ */ /* Project : miniupnp * Author : Thomas BERNARD * copyright (c) 2005-2011 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ -#ifndef __CODELENGTH_H__ -#define __CODELENGTH_H__ +#ifndef CODELENGTH_H_INCLUDED +#define CODELENGTH_H_INCLUDED /* Encode length by using 7bit per Byte : * Most significant bit of each byte specifies that the diff --git a/third-party/miniupnp/connecthostport.c b/third-party/miniupnp/connecthostport.c index 9601e0f8e..d66ae315f 100644 --- a/third-party/miniupnp/connecthostport.c +++ b/third-party/miniupnp/connecthostport.c @@ -1,7 +1,7 @@ -/* $Id: connecthostport.c,v 1.7 2012/03/05 19:42:46 nanard Exp $ */ +/* $Id: connecthostport.c,v 1.13 2014/03/31 12:36:36 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2010-2012 Thomas Bernard + * Copyright (c) 2010-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -24,15 +24,18 @@ #else /* #ifdef _WIN32 */ #include #include +#include #include #define closesocket close #include +#include /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions * during the connect() call */ #define MINIUPNPC_IGNORE_EINTR #ifndef USE_GETHOSTBYNAME #include #include +#include #endif /* #ifndef USE_GETHOSTBYNAME */ #endif /* #else _WIN32 */ @@ -49,10 +52,15 @@ #include "connecthostport.h" +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + /* connecthostport() * return a socket connected (TCP) to the host and port * or -1 in case of error */ -int connecthostport(const char * host, unsigned short port) +int connecthostport(const char * host, unsigned short port, + unsigned int scope_id) { int s, n; #ifdef USE_GETHOSTBYNAME @@ -102,7 +110,10 @@ int connecthostport(const char * host, unsigned short port) dest.sin_port = htons(port); n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); #ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) + /* EINTR The system call was interrupted by a signal that was caught + * EINPROGRESS The socket is nonblocking and the connection cannot + * be completed immediately. */ + while(n < 0 && (errno == EINTR || errno = EINPROGRESS)) { socklen_t len; fd_set wset; @@ -145,10 +156,12 @@ int connecthostport(const char * host, unsigned short port) if(host[0] == '[') { /* literal ip v6 address */ - int i; - for(i = 0; host[i+1] && (host[i+1] != ']') && i < MAXHOSTNAMELEN; i++) + int i, j; + for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++) { - tmp_host[i] = host[i+1]; + tmp_host[i] = host[j]; + if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */ + j+=2; /* skip "25" */ } tmp_host[i] = '\0'; } @@ -173,6 +186,10 @@ int connecthostport(const char * host, unsigned short port) s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if(s < 0) continue; + if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) { + struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr; + addr6->sin6_scope_id = scope_id; + } #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT /* setting a 3 seconds timeout for the connect() call */ timeout.tv_sec = 3; @@ -190,7 +207,10 @@ int connecthostport(const char * host, unsigned short port) #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ n = connect(s, p->ai_addr, p->ai_addrlen); #ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) + /* EINTR The system call was interrupted by a signal that was caught + * EINPROGRESS The socket is nonblocking and the connection cannot + * be completed immediately. */ + while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) { socklen_t len; fd_set wset; diff --git a/third-party/miniupnp/connecthostport.h b/third-party/miniupnp/connecthostport.h index 57e24eb27..56941d6fa 100644 --- a/third-party/miniupnp/connecthostport.h +++ b/third-party/miniupnp/connecthostport.h @@ -1,17 +1,18 @@ -/* $Id: connecthostport.h,v 1.1 2010/04/04 23:21:03 nanard Exp $ */ +/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2010 Thomas Bernard + * Copyright (c) 2010-2012 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __CONNECTHOSTPORT_H__ -#define __CONNECTHOSTPORT_H__ +#ifndef CONNECTHOSTPORT_H_INCLUDED +#define CONNECTHOSTPORT_H_INCLUDED /* connecthostport() * return a socket connected (TCP) to the host and port * or -1 in case of error */ -int connecthostport(const char * host, unsigned short port); +int connecthostport(const char * host, unsigned short port, + unsigned int scope_id); #endif diff --git a/third-party/miniupnp/declspec.h b/third-party/miniupnp/declspec.h index 2638faa61..77299693b 100644 --- a/third-party/miniupnp/declspec.h +++ b/third-party/miniupnp/declspec.h @@ -1,14 +1,20 @@ -#ifndef __DECLSPEC_H__ -#define __DECLSPEC_H__ +#ifndef DECLSPEC_H_INCLUDED +#define DECLSPEC_H_INCLUDED #if defined(_WIN32) && !defined(STATICLIB) + /* for windows dll */ #ifdef MINIUPNP_EXPORTS #define LIBSPEC __declspec(dllexport) #else #define LIBSPEC __declspec(dllimport) #endif #else - #define LIBSPEC + #if defined(__GNUC__) && __GNUC__ >= 4 + /* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ + #define LIBSPEC __attribute__ ((visibility ("default"))) + #else + #define LIBSPEC + #endif #endif #endif diff --git a/third-party/miniupnp/igd_desc_parse.h b/third-party/miniupnp/igd_desc_parse.h index bab1fd56f..0a49b019d 100644 --- a/third-party/miniupnp/igd_desc_parse.h +++ b/third-party/miniupnp/igd_desc_parse.h @@ -1,4 +1,4 @@ -/* $Id: igd_desc_parse.h,v 1.10 2011/04/11 09:19:24 nanard Exp $ */ +/* $Id: igd_desc_parse.h,v 1.11 2012/10/16 16:49:02 nanard Exp $ */ /* Project : miniupnp * http://miniupnp.free.fr/ * Author : Thomas Bernard @@ -6,8 +6,8 @@ * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ -#ifndef __IGD_DESC_PARSE_H__ -#define __IGD_DESC_PARSE_H__ +#ifndef IGD_DESC_PARSE_H_INCLUDED +#define IGD_DESC_PARSE_H_INCLUDED /* Structure to store the result of the parsing of UPnP * descriptions of Internet Gateway Devices */ diff --git a/third-party/miniupnp/minisoap.h b/third-party/miniupnp/minisoap.h index 696725f62..14c859d1e 100644 --- a/third-party/miniupnp/minisoap.h +++ b/third-party/miniupnp/minisoap.h @@ -1,11 +1,11 @@ -/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */ +/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ -#ifndef __MINISOAP_H__ -#define __MINISOAP_H__ +#ifndef MINISOAP_H_INCLUDED +#define MINISOAP_H_INCLUDED /*int httpWrite(int, const char *, int, const char *);*/ int soapPostSubmit(int, const char *, const char *, unsigned short, diff --git a/third-party/miniupnp/minissdpc.h b/third-party/miniupnp/minissdpc.h index 25e91ce31..915b0026f 100644 --- a/third-party/miniupnp/minissdpc.h +++ b/third-party/miniupnp/minissdpc.h @@ -1,12 +1,12 @@ -/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 nanard Exp $ */ +/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard * Copyright (c) 2005-2007 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __MINISSDPC_H__ -#define __MINISSDPC_H__ +#ifndef MINISSDPC_H_INCLUDED +#define MINISSDPC_H_INCLUDED struct UPNPDev * getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); diff --git a/third-party/miniupnp/miniupnpc.c b/third-party/miniupnp/miniupnpc.c index 15435ea4d..85b7d7577 100644 --- a/third-party/miniupnp/miniupnpc.c +++ b/third-party/miniupnp/miniupnpc.c @@ -1,8 +1,8 @@ -/* $Id: miniupnpc.c,v 1.106 2012/06/11 16:08:17 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.117 2014/01/31 14:19:13 nanard Exp $ */ /* Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD - * copyright (c) 2005-2012 Thomas Bernard + * copyright (c) 2005-2014 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #define __EXTENSIONS__ 1 @@ -17,7 +17,7 @@ #endif #endif -#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) +#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) #define HAS_IP_MREQN #endif @@ -31,6 +31,7 @@ #include #include #define snprintf _snprintf +#define strdup _strdup #ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define strncasecmp _memicmp @@ -70,6 +71,17 @@ #define TIMEVAL struct timeval #endif + +#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN) +/* Several versions of glibc don't define this structure, define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */ +struct ip_mreqn +{ + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ +}; +#endif + #include "miniupnpc.h" #include "minissdpc.h" #include "miniwget.h" @@ -85,6 +97,10 @@ #define PRINT_SOCKET_ERROR(x) perror(x) #endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + #define SOAPPREFIX "s" #define SERVICEPREFIX "u" #define SERVICEPREFIX2 'u' @@ -112,9 +128,9 @@ LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * d * return values : * pointer - OK * NULL - error */ -char * simpleUPnPcommand2(int s, const char * url, const char * service, - const char * action, struct UPNParg * args, - int * bufsize, const char * httpversion) +static char * simpleUPnPcommand2(int s, const char * url, const char * service, + const char * action, struct UPNParg * args, + int * bufsize, const char * httpversion) { char hostname[MAXHOSTNAMELEN+1]; unsigned short port = 0; @@ -189,12 +205,11 @@ char * simpleUPnPcommand2(int s, const char * url, const char * service, strncpy(p, ">\r\n", soapbody + sizeof(soapbody) - p); } - if(!parseURL(url, hostname, &port, &path)) return NULL; - if(s<0) - { - s = connecthostport(hostname, port); - if(s < 0) - { + if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; + if(s < 0) { + s = connecthostport(hostname, port, 0); + if(s < 0) { + /* failed to connect */ return NULL; } } @@ -230,8 +245,9 @@ char * simpleUPnPcommand(int s, const char * url, const char * service, { char * buf; +#if 1 buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); -/* +#else buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0"); if (!buf || *bufsize == 0) { @@ -240,7 +256,7 @@ char * simpleUPnPcommand(int s, const char * url, const char * service, #endif buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); } -*/ +#endif return buf; } @@ -327,6 +343,7 @@ upnpDiscover(int delay, const char * multicastif, { struct UPNPDev * tmp; struct UPNPDev * devlist = 0; + unsigned int scope_id = 0; int opt = 1; static const char MSearchMsgFmt[] = "M-SEARCH * HTTP/1.1\r\n" @@ -528,7 +545,8 @@ upnpDiscover(int delay, const char * multicastif, } } - /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ + /* Before sending the packed, we first "bind" in order to be able + * to receive the response */ if (bind(sudp, (const struct sockaddr *)&sockudp_r, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) { @@ -543,6 +561,10 @@ upnpDiscover(int delay, const char * multicastif, *error = UPNPDISCOVER_SUCCESS; /* Calculating maximum response time in seconds */ mx = ((unsigned int)delay) / 1000u; + if(mx == 0) { + mx = 1; + delay = 1000; + } /* receiving SSDP response packet */ for(n = 0; deviceList[deviceIndex]; deviceIndex++) { @@ -625,7 +647,7 @@ upnpDiscover(int delay, const char * multicastif, #endif /* #ifdef NO_GETADDRINFO */ } /* Waiting for SSDP REPLY packet to M-SEARCH */ - n = receivedata(sudp, bufr, sizeof(bufr), delay); + n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); if (n < 0) { /* error */ if(error) @@ -685,6 +707,7 @@ upnpDiscover(int delay, const char * multicastif, tmp->buffer[urlsize] = '\0'; memcpy(tmp->buffer + urlsize + 1, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; + tmp->scope_id = scope_id; devlist = tmp; } } @@ -731,15 +754,31 @@ url_cpy_or_cat(char * dst, const char * src, int n) /* Prepare the Urls for usage... */ -LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, - const char * descURL) +LIBSPEC void +GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, + const char * descURL, unsigned int scope_id) { char * p; int n1, n2, n3, n4; +#ifdef IF_NAMESIZE + char ifname[IF_NAMESIZE]; +#else + char scope_str[8]; +#endif n1 = strlen(data->urlbase); if(n1==0) n1 = strlen(descURL); + if(scope_id != 0) { +#ifdef IF_NAMESIZE + if(if_indextoname(scope_id, ifname)) { + n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */ + } +#else + /* under windows, scope is numerical */ + snprintf(scope_str, sizeof(scope_str), "%u", scope_id); +#endif + } n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ n2 = n1; n3 = n1; n4 = n1; n1 += strlen(data->first.scpdurl); @@ -763,6 +802,24 @@ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, strncpy(urls->ipcondescURL, descURL, n1); p = strchr(urls->ipcondescURL+7, '/'); if(p) p[0] = '\0'; + if(scope_id != 0) { + if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) { + /* this is a linklocal IPv6 address */ + p = strchr(urls->ipcondescURL, ']'); + if(p) { + /* insert %25 into URL */ +#ifdef IF_NAMESIZE + memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); + memcpy(p, "%25", 3); + memcpy(p + 3, ifname, strlen(ifname)); +#else + memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); + memcpy(p, "%25", 3); + memcpy(p + 3, scope_str, strlen(scope_str)); +#endif + } + } + } strncpy(urls->controlURL, urls->ipcondescURL, n2); strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); @@ -830,7 +887,7 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data) * not connected * 3 = an UPnP device has been found but was not recognized as an IGD * - * In any non zero return case, the urls and data structures + * In any positive non zero return case, the urls and data structures * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to * free allocated memory. */ @@ -843,11 +900,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, struct xml_desc { char * xml; int size; + int is_igd; } * desc = NULL; struct UPNPDev * dev; int ndev = 0; int i; int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ + int n_igd = 0; + char extIpAddr[16]; if(!devlist) { #ifdef DEBUG @@ -855,6 +915,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, #endif return 0; } + /* counting total number of devices in the list */ for(dev = devlist; dev; dev = dev->pNext) ndev++; if(ndev > 0) @@ -863,40 +924,58 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, if(!desc) return -1; /* memory allocation error */ } - for(state = 1; state <= 3; state++) + /* Step 1 : downloading descriptions and testing type */ + for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) { - for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) - { - /* we should choose an internet gateway device. - * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ - if(state == 1) - { - desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), - lanaddr, lanaddrlen); + /* we should choose an internet gateway device. + * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ + desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), + lanaddr, lanaddrlen, + dev->scope_id); #ifdef DEBUG - if(!desc[i].xml) - { - printf("error getting XML description %s\n", dev->descURL); - } + if(!desc[i].xml) + { + printf("error getting XML description %s\n", dev->descURL); + } #endif + if(desc[i].xml) + { + memset(data, 0, sizeof(struct IGDdatas)); + memset(urls, 0, sizeof(struct UPNPUrls)); + parserootdesc(desc[i].xml, desc[i].size, data); + if(0==strcmp(data->CIF.servicetype, + "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")) + { + desc[i].is_igd = 1; + n_igd++; } + } + } + /* iterate the list to find a device depending on state */ + for(state = 1; state <= 3; state++) + { + for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) + { if(desc[i].xml) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(desc[i].xml, desc[i].size, data); - if(0==strcmp(data->CIF.servicetype, - "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") - || state >= 3 ) + if(desc[i].is_igd || state >= 3 ) { - GetUPNPUrls(urls, data, dev->descURL); + GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); + /* in state 2 and 3 we dont test if device is connected ! */ + if(state >= 2) + goto free_and_return; #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif - if((state >= 2) || UPNPIGD_IsConnected(urls, data)) + /* checks that status is connected AND there is a external IP address assigned */ + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) goto free_and_return; FreeUPNPUrls(urls); if(data->second.servicetype[0] != '\0') { @@ -908,13 +987,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); - GetUPNPUrls(urls, data, dev->descURL); + GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); #ifdef DEBUG printf("UPNPIGD_IsConnected(%s) = %d\n", urls->controlURL, UPNPIGD_IsConnected(urls, data)); #endif - if((state >= 2) || UPNPIGD_IsConnected(urls, data)) + if(UPNPIGD_IsConnected(urls, data) + && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) goto free_and_return; FreeUPNPUrls(urls); } @@ -925,7 +1005,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, } state = 0; free_and_return: - free(desc); + if(desc) { + for(i = 0; i < ndev; i++) { + if(desc[i].xml) { + free(desc[i].xml); + } + } + free(desc); + } return state; } @@ -943,14 +1030,14 @@ UPNP_GetIGDFromUrl(const char * rootdescurl, char * descXML; int descXMLsize = 0; descXML = miniwget_getaddr(rootdescurl, &descXMLsize, - lanaddr, lanaddrlen); + lanaddr, lanaddrlen, 0); if(descXML) { memset(data, 0, sizeof(struct IGDdatas)); memset(urls, 0, sizeof(struct UPNPUrls)); parserootdesc(descXML, descXMLsize, data); free(descXML); descXML = NULL; - GetUPNPUrls(urls, data, rootdescurl); + GetUPNPUrls(urls, data, rootdescurl, 0); return 1; } else { return 0; diff --git a/third-party/miniupnp/miniupnpc.h b/third-party/miniupnp/miniupnpc.h index 64341629a..3af109cf1 100644 --- a/third-party/miniupnp/miniupnpc.h +++ b/third-party/miniupnp/miniupnpc.h @@ -1,12 +1,12 @@ -/* $Id: miniupnpc.h,v 1.25 2011/10/09 16:17:29 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.35 2014/01/31 13:26:34 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2005-2011 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __MINIUPNPC_H__ -#define __MINIUPNPC_H__ +#ifndef MINIUPNPC_H_INCLUDED +#define MINIUPNPC_H_INCLUDED #include "declspec.h" #include "igd_desc_parse.h" @@ -18,8 +18,8 @@ #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ -#define MINIUPNPC_VERSION "1.7" -#define MINIUPNPC_API_VERSION 8 +#define MINIUPNPC_VERSION "1.9.20140401" +#define MINIUPNPC_API_VERSION 10 #ifdef __cplusplus extern "C" { @@ -37,6 +37,7 @@ struct UPNPDev { struct UPNPDev * pNext; char * descURL; char * st; + unsigned int scope_id; char buffer[2]; }; @@ -110,9 +111,12 @@ UPNP_GetIGDFromUrl(const char * rootdescurl, struct IGDdatas * data, char * lanaddr, int lanaddrlen); -LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *); +LIBSPEC void +GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, + const char *, unsigned int); -LIBSPEC void FreeUPNPUrls(struct UPNPUrls *); +LIBSPEC void +FreeUPNPUrls(struct UPNPUrls *); /* return 0 or 1 */ LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); diff --git a/third-party/miniupnp/miniupnpctypes.h b/third-party/miniupnp/miniupnpctypes.h index 86081c3cc..591c32fb6 100644 --- a/third-party/miniupnp/miniupnpctypes.h +++ b/third-party/miniupnp/miniupnpctypes.h @@ -1,11 +1,11 @@ -/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */ +/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org * Author : Thomas Bernard * Copyright (c) 2011 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ -#ifndef __MINIUPNPCTYPES_H__ -#define __MINIUPNPCTYPES_H__ +#ifndef MINIUPNPCTYPES_H_INCLUDED +#define MINIUPNPCTYPES_H_INCLUDED #if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) #define UNSIGNED_INTEGER unsigned long long diff --git a/third-party/miniupnp/miniwget.c b/third-party/miniupnp/miniwget.c index 036379a4d..813db9324 100644 --- a/third-party/miniupnp/miniwget.c +++ b/third-party/miniupnp/miniwget.c @@ -1,8 +1,8 @@ -/* $Id: miniwget.c,v 1.56 2012/05/01 16:16:08 nanard Exp $ */ +/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2012 Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -36,11 +36,9 @@ #include #include #include +#include #include #define closesocket close -/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions - * during the connect() call */ -#define MINIUPNPC_IGNORE_EINTR #endif /* #else _WIN32 */ #if defined(__sun) || defined(sun) #define MIN(x,y) (((x)<(y))?(x):(y)) @@ -51,6 +49,10 @@ #include "connecthostport.h" #include "receivedata.h" +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + /* * Read a HTTP response from a socket. * Process Content-Length and Transfer-encoding headers. @@ -82,7 +84,7 @@ getHTTPResponse(int s, int * size) chunksize_buf[0] = '\0'; chunksize_buf_index = 0; - while((n = receivedata(s, buf, 2048, 5000)) > 0) + while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0) { if(endofheaders == 0) { @@ -157,7 +159,7 @@ getHTTPResponse(int s, int * size) chunked = 1; } } - while(header_buf[i]=='\r' || header_buf[i] == '\n') + while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n')) i++; linestart = i; colon = linestart; @@ -289,7 +291,7 @@ static void * miniwget3(const char * host, unsigned short port, const char * path, int * size, char * addr_str, int addr_str_len, - const char * httpversion) + const char * httpversion, unsigned int scope_id) { char buf[2048]; int s; @@ -299,7 +301,7 @@ miniwget3(const char * host, void * content; *size = 0; - s = connecthostport(host, port); + s = connecthostport(host, port, scope_id); if(s < 0) return NULL; @@ -392,22 +394,27 @@ miniwget3(const char * host, static void * miniwget2(const char * host, unsigned short port, const char * path, - int * size, char * addr_str, int addr_str_len) + int * size, char * addr_str, int addr_str_len, + unsigned int scope_id) { char * respbuffer; - respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1"); -/* - respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.0"); +#if 1 + respbuffer = miniwget3(host, port, path, size, + addr_str, addr_str_len, "1.1", scope_id); +#else + respbuffer = miniwget3(host, port, path, size, + addr_str, addr_str_len, "1.0", scope_id); if (*size == 0) { #ifdef DEBUG printf("Retrying with HTTP/1.1\n"); #endif free(respbuffer); - respbuffer = miniwget3(host, port, path, size, addr_str, addr_str_len, "1.1"); + respbuffer = miniwget3(host, port, path, size, + addr_str, addr_str_len, "1.1", scope_id); } -*/ +#endif return respbuffer; } @@ -424,7 +431,10 @@ miniwget2(const char * host, * Return values : * 0 - Failure * 1 - Success */ -int parseURL(const char * url, char * hostname, unsigned short * port, char * * path) +int +parseURL(const char * url, + char * hostname, unsigned short * port, + char * * path, unsigned int * scope_id) { char * p1, *p2, *p3; if(!url) @@ -440,7 +450,43 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * * if(*p1 == '[') { /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ + char * scope; + scope = strchr(p1, '%'); p2 = strchr(p1, ']'); + if(p2 && scope && scope < p2 && scope_id) { + /* parse scope */ +#ifdef IF_NAMESIZE + char tmp[IF_NAMESIZE]; + int l; + scope++; + /* "%25" is just '%' in URL encoding */ + if(scope[0] == '2' && scope[1] == '5') + scope += 2; /* skip "25" */ + l = p2 - scope; + if(l >= IF_NAMESIZE) + l = IF_NAMESIZE - 1; + memcpy(tmp, scope, l); + tmp[l] = '\0'; + *scope_id = if_nametoindex(tmp); + if(*scope_id == 0) { + *scope_id = (unsigned int)strtoul(tmp, NULL, 10); + } +#else + /* under windows, scope is numerical */ + char tmp[8]; + int l; + scope++; + /* "%25" is just '%' in URL encoding */ + if(scope[0] == '2' && scope[1] == '5') + scope += 2; /* skip "25" */ + l = p2 - scope; + if(l >= sizeof(tmp)) + l = sizeof(tmp) - 1; + memcpy(tmp, scope, l); + tmp[l] = '\0'; + *scope_id = (unsigned int)strtoul(tmp, NULL, 10); +#endif + } p3 = strchr(p1, '/'); if(p2 && p3) { @@ -490,22 +536,26 @@ int parseURL(const char * url, char * hostname, unsigned short * port, char * * return 1; } -void * miniwget(const char * url, int * size) +void * +miniwget(const char * url, int * size, unsigned int scope_id) { unsigned short port; char * path; /* protocol://host:port/chemin */ char hostname[MAXHOSTNAMELEN+1]; *size = 0; - if(!parseURL(url, hostname, &port, &path)) + if(!parseURL(url, hostname, &port, &path, &scope_id)) return NULL; #ifdef DEBUG - printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path); + printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", + hostname, port, path, scope_id); #endif - return miniwget2(hostname, port, path, size, 0, 0); + return miniwget2(hostname, port, path, size, 0, 0, scope_id); } -void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen) +void * +miniwget_getaddr(const char * url, int * size, + char * addr, int addrlen, unsigned int scope_id) { unsigned short port; char * path; @@ -514,11 +564,12 @@ void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen) *size = 0; if(addr) addr[0] = '\0'; - if(!parseURL(url, hostname, &port, &path)) + if(!parseURL(url, hostname, &port, &path, &scope_id)) return NULL; #ifdef DEBUG - printf("parsed url : hostname='%s' port=%hu path='%s'\n", hostname, port, path); + printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n", + hostname, port, path, scope_id); #endif - return miniwget2(hostname, port, path, size, addr, addrlen); + return miniwget2(hostname, port, path, size, addr, addrlen, scope_id); } diff --git a/third-party/miniupnp/miniwget.h b/third-party/miniupnp/miniwget.h index 8314b4000..31bcea322 100644 --- a/third-party/miniupnp/miniwget.h +++ b/third-party/miniupnp/miniwget.h @@ -1,12 +1,12 @@ -/* $Id: miniwget.h,v 1.6 2010/12/09 16:11:33 nanard Exp $ */ +/* $Id: miniwget.h,v 1.8 2012/09/27 15:42:10 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ -#ifndef __MINIWGET_H__ -#define __MINIWGET_H__ +#ifndef MINIWGET_H_INCLUDED +#define MINIWGET_H_INCLUDED #include "declspec.h" @@ -16,11 +16,11 @@ extern "C" { LIBSPEC void * getHTTPResponse(int s, int * size); -LIBSPEC void * miniwget(const char *, int *); +LIBSPEC void * miniwget(const char *, int *, unsigned int); -LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int); +LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); -int parseURL(const char *, char *, unsigned short *, char * *); +int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); #ifdef __cplusplus } diff --git a/third-party/miniupnp/minixml.c b/third-party/miniupnp/minixml.c index eb4d7d985..3e201ec2c 100644 --- a/third-party/miniupnp/minixml.c +++ b/third-party/miniupnp/minixml.c @@ -1,10 +1,10 @@ -/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ +/* $Id: minixml.c,v 1.11 2014/02/03 15:54:12 nanard Exp $ */ /* minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard -Copyright (c) 2005-2011, Thomas BERNARD +Copyright (c) 2005-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without @@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p) const char * elementname; while(p->xml < (p->xmlend - 1)) { - if((p->xml)[0]=='<' && (p->xml)[1]!='?') + if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); + p->xml += 3; + } + else if((p->xml)[0]=='<' && (p->xml)[1]!='?') { i = 0; elementname = ++p->xml; while( !IS_WHITE_SPACE(*p->xml) diff --git a/third-party/miniupnp/minixml.h b/third-party/miniupnp/minixml.h index 857c70ee9..9f43aa48c 100644 --- a/third-party/miniupnp/minixml.h +++ b/third-party/miniupnp/minixml.h @@ -1,4 +1,4 @@ -/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */ +/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ /* minimal xml parser * * Project : miniupnp @@ -8,8 +8,8 @@ * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ -#ifndef __MINIXML_H__ -#define __MINIXML_H__ +#ifndef MINIXML_H_INCLUDED +#define MINIXML_H_INCLUDED #define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) /* if a callback function pointer is set to NULL, diff --git a/third-party/miniupnp/portlistingparse.c b/third-party/miniupnp/portlistingparse.c index 525171ae1..19e3054eb 100644 --- a/third-party/miniupnp/portlistingparse.c +++ b/third-party/miniupnp/portlistingparse.c @@ -1,4 +1,4 @@ -/* $Id: portlistingparse.c,v 1.5 2012/03/05 19:42:47 nanard Exp $ */ +/* $Id: portlistingparse.c,v 1.6 2012/05/29 10:26:51 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2011 Thomas Bernard @@ -71,6 +71,8 @@ static void endelt(void * d, const char * name, int l) { struct PortMappingParserData * pdata = (struct PortMappingParserData *)d; + (void)name; + (void)l; pdata->curelt = PortMappingEltNone; } diff --git a/third-party/miniupnp/portlistingparse.h b/third-party/miniupnp/portlistingparse.h index 78ffe95ea..bafa2a47c 100644 --- a/third-party/miniupnp/portlistingparse.h +++ b/third-party/miniupnp/portlistingparse.h @@ -1,11 +1,11 @@ -/* $Id: portlistingparse.h,v 1.6 2012/03/05 19:42:47 nanard Exp $ */ +/* $Id: portlistingparse.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2011-2012 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ -#ifndef __PORTLISTINGPARSE_H__ -#define __PORTLISTINGPARSE_H__ +#ifndef PORTLISTINGPARSE_H_INCLUDED +#define PORTLISTINGPARSE_H_INCLUDED #include "declspec.h" /* for the definition of UNSIGNED_INTEGER */ diff --git a/third-party/miniupnp/receivedata.c b/third-party/miniupnp/receivedata.c index d1bc87028..9599556ab 100644 --- a/third-party/miniupnp/receivedata.c +++ b/third-party/miniupnp/receivedata.c @@ -1,4 +1,4 @@ -/* $Id: receivedata.c,v 1.3 2012/03/05 19:42:47 nanard Exp $ */ +/* $Id: receivedata.c,v 1.5 2013/10/07 09:48:36 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard @@ -18,6 +18,7 @@ #include #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ #include +#include #if !defined(__amigaos__) && !defined(__amigaos4__) #include #endif @@ -34,8 +35,19 @@ #include "receivedata.h" int -receivedata(int socket, char * data, int length, int timeout) +receivedata(int socket, + char * data, int length, + int timeout, unsigned int * scope_id) { +#ifdef MINIUPNPC_GET_SRC_ADDR +#ifdef DEBUG + /* to shut up valgrind about uninit value */ + struct sockaddr_storage src_addr = {0}; +#else + struct sockaddr_storage src_addr; +#endif + socklen_t src_addr_len = sizeof(src_addr); +#endif int n; #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) /* using poll */ @@ -72,10 +84,25 @@ receivedata(int socket, char * data, int length, int timeout) return 0; } #endif +#ifdef MINIUPNPC_GET_SRC_ADDR + n = recvfrom(socket, data, length, 0, + (struct sockaddr *)&src_addr, &src_addr_len); +#else n = recv(socket, data, length, 0); +#endif if(n<0) { PRINT_SOCKET_ERROR("recv"); } +#ifdef MINIUPNPC_GET_SRC_ADDR + if (src_addr.ss_family == AF_INET6) { + const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; +#ifdef DEBUG + printf("scope_id=%u\n", src_addr6->sin6_scope_id); +#endif + if(scope_id) + *scope_id = src_addr6->sin6_scope_id; + } +#endif return n; } diff --git a/third-party/miniupnp/receivedata.h b/third-party/miniupnp/receivedata.h index 1293b1036..0520a11d3 100644 --- a/third-party/miniupnp/receivedata.h +++ b/third-party/miniupnp/receivedata.h @@ -1,17 +1,19 @@ -/* $Id: receivedata.h,v 1.2 2012/03/05 19:42:47 nanard Exp $ */ +/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author: Thomas Bernard - * Copyright (c) 2011 Thomas Bernard + * Copyright (c) 2011-2012 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ -#ifndef __RECEIVEDATA_H__ -#define __RECEIVEDATA_H__ +#ifndef RECEIVEDATA_H_INCLUDED +#define RECEIVEDATA_H_INCLUDED /* Reads data from the specified socket. * Returns the number of bytes read if successful, zero if no bytes were * read or if we timed out. Returns negative if there was an error. */ -int receivedata(int socket, char * data, int length, int timeout); +int receivedata(int socket, + char * data, int length, + int timeout, unsigned int * scope_id); #endif diff --git a/third-party/miniupnp/updateminiupnpcstrings.sh b/third-party/miniupnp/updateminiupnpcstrings.sh index df448105c..dde4354a8 100755 --- a/third-party/miniupnp/updateminiupnpcstrings.sh +++ b/third-party/miniupnp/updateminiupnpcstrings.sh @@ -1,52 +1,53 @@ #! /bin/sh -# $Id: updateminiupnpcstrings.sh,v 1.4 2009/07/29 08:34:01 nanard Exp $ +# $Id: updateminiupnpcstrings.sh,v 1.7 2011/01/04 11:41:53 nanard Exp $ +# project miniupnp : http://miniupnp.free.fr/ +# (c) 2009 Thomas Bernard -VERSION_FILE=$1 -TEMPLATE_FILE=$2 -FILE=$3 -TMPFILE=$3.tmp +FILE=miniupnpcstrings.h +TMPFILE=miniupnpcstrings.h.tmp +TEMPLATE_FILE=${FILE}.in # detecting the OS name and version OS_NAME=`uname -s` OS_VERSION=`uname -r` if [ -f /etc/debian_version ]; then - OS_NAME=Debian - OS_VERSION=`cat /etc/debian_version` + OS_NAME=Debian + OS_VERSION=`cat /etc/debian_version` fi # use lsb_release (Linux Standard Base) when available LSB_RELEASE=`which lsb_release` if [ 0 -eq $? -a -x "${LSB_RELEASE}" ]; then - OS_NAME=`${LSB_RELEASE} -i -s` - OS_VERSION=`${LSB_RELEASE} -r -s` - case $OS_NAME in - Debian) - #OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - Ubuntu) - #OS_VERSION=`${LSB_RELEASE} -c -s` - ;; - esac + OS_NAME=`${LSB_RELEASE} -i -s` + OS_VERSION=`${LSB_RELEASE} -r -s` + case $OS_NAME in + Debian) + #OS_VERSION=`${LSB_RELEASE} -c -s` + ;; + Ubuntu) + #OS_VERSION=`${LSB_RELEASE} -c -s` + ;; + esac fi # on AmigaOS 3, uname -r returns "unknown", so we use uname -v if [ "$OS_NAME" = "AmigaOS" ]; then - if [ "$OS_VERSION" = "unknown" ]; then - OS_VERSION=`uname -v` - fi + if [ "$OS_VERSION" = "unknown" ]; then + OS_VERSION=`uname -v` + fi fi echo "Detected OS [$OS_NAME] version [$OS_VERSION]" -MINIUPNPC_VERSION=`cat "$VERSION_FILE"` +MINIUPNPC_VERSION=`cat VERSION` echo "MiniUPnPc version [${MINIUPNPC_VERSION}]" EXPR="s|OS_STRING \".*\"|OS_STRING \"${OS_NAME}/${OS_VERSION}\"|" #echo $EXPR test -f ${FILE}.in echo "setting OS_STRING macro value to ${OS_NAME}/${OS_VERSION} in $FILE." -sed -e "$EXPR" < "$TEMPLATE_FILE" > "$TMPFILE" +sed -e "$EXPR" < $TEMPLATE_FILE > $TMPFILE EXPR="s|MINIUPNPC_VERSION_STRING \".*\"|MINIUPNPC_VERSION_STRING \"${MINIUPNPC_VERSION}\"|" echo "setting MINIUPNPC_VERSION_STRING macro value to ${MINIUPNPC_VERSION} in $FILE." -sed -e "$EXPR" < "$TMPFILE" > "$FILE" -rm "$TMPFILE" +sed -e "$EXPR" < $TMPFILE > $FILE +rm $TMPFILE diff --git a/third-party/miniupnp/upnpcommands.c b/third-party/miniupnp/upnpcommands.c index 47745fff4..ad6978105 100644 --- a/third-party/miniupnp/upnpcommands.c +++ b/third-party/miniupnp/upnpcommands.c @@ -1,7 +1,7 @@ -/* $Id: upnpcommands.c,v 1.39 2012/04/09 12:49:27 nanard Exp $ */ +/* $Id: upnpcommands.c,v 1.42 2014/01/31 13:18:25 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2011 Thomas Bernard + * Copyright (c) 2005-2012 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * */ @@ -578,7 +578,8 @@ LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, - const char * proto, + const char * proto, + const char * remoteHost, char * intClient, char * intPort, char * desc, @@ -597,7 +598,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); GetPortMappingArgs[0].elt = "NewRemoteHost"; - /* TODO : add remote host ? */ + GetPortMappingArgs[0].val = remoteHost; GetPortMappingArgs[1].elt = "NewExternalPort"; GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[2].elt = "NewProtocol"; @@ -759,7 +760,7 @@ UPNP_GetFirewallStatus(const char * controlURL, char * fe, *ipa, *p; int ret = UPNPCOMMAND_UNKNOWN_ERROR; - if(!firewallEnabled && !inboundPinholeAllowed) + if(!firewallEnabled || !inboundPinholeAllowed) return UPNPCOMMAND_INVALID_ARGS; buffer = simpleUPnPcommand(-1, controlURL, servicetype, diff --git a/third-party/miniupnp/upnpcommands.h b/third-party/miniupnp/upnpcommands.h index 4bd29b01c..93d9f3dd4 100644 --- a/third-party/miniupnp/upnpcommands.h +++ b/third-party/miniupnp/upnpcommands.h @@ -1,11 +1,11 @@ -/* $Id: upnpcommands.h,v 1.24 2012/03/05 19:42:47 nanard Exp $ */ +/* $Id: upnpcommands.h,v 1.27 2014/02/17 15:38:26 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2011 Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ -#ifndef __UPNPCOMMANDS_H__ -#define __UPNPCOMMANDS_H__ +#ifndef UPNPCOMMANDS_H_INCLUDED +#define UPNPCOMMANDS_H_INCLUDED #include "upnpreplyparse.h" #include "portlistingparse.h" @@ -100,6 +100,8 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, * errorCode errorDescription (short) - Description (long) * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + * the sender was not authorized. * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be * wild-carded * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded @@ -112,7 +114,13 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard * and cannot be a specific IP address or DNS name * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and - * cannot be a specific port value */ + * cannot be a specific port value + * 728 NoPortMapsAvailable - There are not enough free ports available to + * complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + * due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ LIBSPEC int UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * extPort, @@ -132,6 +140,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, * * List of possible UPnP errors for DeletePortMapping : * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. * 714 NoSuchEntryInArray - The specified value does not exist in the array */ LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, @@ -150,6 +160,7 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL, * params : * in extPort * in proto + * in remoteHost * out intClient (16 bytes) * out intPort (6 bytes) * out desc (80 bytes) @@ -158,12 +169,21 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL, * * return value : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. */ + * or a UPnP Error Code. + * + * List of possible UPnP errors for _GetSpecificPortMappingEntry : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 714 NoSuchEntryInArray - The specified value does not exist in the array. + */ LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, + const char * remoteHost, char * intClient, char * intPort, char * desc, @@ -188,6 +208,8 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, * * Possible UPNP Error codes : * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds */ LIBSPEC int diff --git a/third-party/miniupnp/upnpreplyparse.c b/third-party/miniupnp/upnpreplyparse.c index e3a0e992f..dafa26313 100644 --- a/third-party/miniupnp/upnpreplyparse.c +++ b/third-party/miniupnp/upnpreplyparse.c @@ -1,7 +1,7 @@ -/* $Id: upnpreplyparse.c,v 1.12 2012/03/05 19:42:48 nanard Exp $ */ +/* $Id: upnpreplyparse.c,v 1.15 2013/06/06 21:36:40 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -15,18 +15,55 @@ static void NameValueParserStartElt(void * d, const char * name, int l) { - struct NameValueParserData * data = (struct NameValueParserData *)d; + struct NameValueParserData * data = (struct NameValueParserData *)d; + data->topelt = 1; if(l>63) l = 63; memcpy(data->curelt, name, l); data->curelt[l] = '\0'; + data->cdata = NULL; + data->cdatalen = 0; } static void -NameValueParserGetData(void * d, const char * datas, int l) +NameValueParserEndElt(void * d, const char * name, int l) { struct NameValueParserData * data = (struct NameValueParserData *)d; struct NameValue * nv; + (void)name; + (void)l; + if(!data->topelt) + return; + if(strcmp(data->curelt, "NewPortListing") != 0) + { + int l; + /* standard case. Limited to n chars strings */ + l = data->cdatalen; + nv = malloc(sizeof(struct NameValue)); + if(l>=(int)sizeof(nv->value)) + l = sizeof(nv->value) - 1; + strncpy(nv->name, data->curelt, 64); + nv->name[63] = '\0'; + if(data->cdata != NULL) + { + memcpy(nv->value, data->cdata, l); + nv->value[l] = '\0'; + } + else + { + nv->value[0] = '\0'; + } + LIST_INSERT_HEAD( &(data->head), nv, entries); + } + data->cdata = NULL; + data->cdatalen = 0; + data->topelt = 0; +} + +static void +NameValueParserGetData(void * d, const char * datas, int l) +{ + struct NameValueParserData * data = (struct NameValueParserData *)d; if(strcmp(data->curelt, "NewPortListing") == 0) { /* specific case for NewPortListing which is a XML Document */ @@ -42,15 +79,9 @@ NameValueParserGetData(void * d, const char * datas, int l) } else { - /* standard case. Limited to 63 chars strings */ - nv = malloc(sizeof(struct NameValue)); - if(l>63) - l = 63; - strncpy(nv->name, data->curelt, 64); - nv->name[63] = '\0'; - memcpy(nv->value, datas, l); - nv->value[l] = '\0'; - LIST_INSERT_HEAD( &(data->head), nv, entries); + /* standard case. */ + data->cdata = datas; + data->cdatalen = l; } } @@ -67,7 +98,7 @@ ParseNameValue(const char * buffer, int bufsize, parser.xmlsize = bufsize; parser.data = data; parser.starteltfunc = NameValueParserStartElt; - parser.endeltfunc = 0; + parser.endeltfunc = NameValueParserEndElt; parser.datafunc = NameValueParserGetData; parser.attfunc = 0; parsexml(&parser); diff --git a/third-party/miniupnp/upnpreplyparse.h b/third-party/miniupnp/upnpreplyparse.h index a2eef1a28..d4e37576a 100644 --- a/third-party/miniupnp/upnpreplyparse.h +++ b/third-party/miniupnp/upnpreplyparse.h @@ -1,12 +1,12 @@ -/* $Id: upnpreplyparse.h,v 1.13 2012/03/05 19:42:48 nanard Exp $ */ +/* $Id: upnpreplyparse.h,v 1.17 2013/06/06 21:36:40 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ -#ifndef __UPNPREPLYPARSE_H__ -#define __UPNPREPLYPARSE_H__ +#ifndef UPNPREPLYPARSE_H_INCLUDED +#define UPNPREPLYPARSE_H_INCLUDED #if defined(NO_SYS_QUEUE_H) || defined(_WIN32) || defined(__HAIKU__) #include "bsdqueue.h" @@ -21,7 +21,7 @@ extern "C" { struct NameValue { LIST_ENTRY(NameValue) entries; char name[64]; - char value[64]; + char value[128]; }; struct NameValueParserData { @@ -29,6 +29,9 @@ struct NameValueParserData { char curelt[64]; char * portListing; int portListingLength; + int topelt; + const char * cdata; + int cdatalen; }; /* ParseNameValue() */ @@ -45,10 +48,12 @@ char * GetValueFromNameValueList(struct NameValueParserData * pdata, const char * Name); +#if 0 /* GetValueFromNameValueListIgnoreNS() */ char * GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, const char * Name); +#endif /* DisplayNameValueList() */ #ifdef DEBUG -- 2.40.0