--- embedaddon/miniupnpc/miniwget.c	2012/02/21 23:16:22	1.1
+++ embedaddon/miniupnpc/miniwget.c	2013/07/22 00:36:10	1.1.1.2
@@ -1,15 +1,16 @@
-/* $Id: miniwget.c,v 1.1 2012/02/21 23:16:22 misho Exp $ */
+/* $Id: miniwget.c,v 1.1.1.2 2013/07/22 00:36:10 misho Exp $ */
 /* Project : miniupnp
+ * Website : http://miniupnp.free.fr/
  * 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. */
- 
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#ifdef WIN32
+#ifdef _WIN32
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #include <io.h>
@@ -24,7 +25,7 @@
 #define strncasecmp memicmp
 #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
 #endif /* #ifndef strncasecmp */
-#else /* #ifdef WIN32 */
+#else /* #ifdef _WIN32 */
 #include <unistd.h>
 #include <sys/param.h>
 #if defined(__amigaos__) && !defined(__amigaos4__)
@@ -33,13 +34,15 @@
 #include <sys/select.h>
 #endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
 #include <sys/socket.h>
+#include <netinet/in.h>
 #include <arpa/inet.h>
+#include <net/if.h>
 #include <netdb.h>
 #define closesocket close
 /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
  * during the connect() call */
 #define MINIUPNPC_IGNORE_EINTR
-#endif /* #else WIN32 */
+#endif /* #else _WIN32 */
 #if defined(__sun) || defined(sun)
 #define MIN(x,y) (((x)<(y))?(x):(y))
 #endif
@@ -67,20 +70,20 @@ getHTTPResponse(int s, int * size)
 	unsigned int bytestocopy = 0;
 	/* buffers : */
 	char * header_buf;
-	int header_buf_len = 2048;
-	int header_buf_used = 0;
+	unsigned int header_buf_len = 2048;
+	unsigned int header_buf_used = 0;
 	char * content_buf;
-	int content_buf_len = 2048;
-	int content_buf_used = 0;
+	unsigned int content_buf_len = 2048;
+	unsigned int content_buf_used = 0;
 	char chunksize_buf[32];
-	int chunksize_buf_index;
+	unsigned int chunksize_buf_index;
 
 	header_buf = malloc(header_buf_len);
 	content_buf = malloc(content_buf_len);
 	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)
 		{
@@ -97,14 +100,14 @@ getHTTPResponse(int s, int * size)
 			/* search for CR LF CR LF (end of headers)
 			 * recognize also LF LF */
 			i = 0;
-			while(i < (header_buf_used-1) && (endofheaders == 0)) {
+			while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
 				if(header_buf[i] == '\r') {
 					i++;
 					if(header_buf[i] == '\n') {
 						i++;
-						if(i < header_buf_used && header_buf[i] == '\r') {
+						if(i < (int)header_buf_used && header_buf[i] == '\r') {
 							i++;
-							if(i < header_buf_used && header_buf[i] == '\n') {
+							if(i < (int)header_buf_used && header_buf[i] == '\n') {
 								endofheaders = i+1;
 							}
 						}
@@ -160,7 +163,7 @@ getHTTPResponse(int s, int * size)
 					linestart = i;
 					colon = linestart;
 					valuestart = 0;
-				} 
+				}
 			}
 			/* copy the remaining of the received data back to buf */
 			n = header_buf_used - endofheaders;
@@ -194,7 +197,7 @@ getHTTPResponse(int s, int * size)
 							i++; /* discarding chunk-extension */
 						if(i<n && buf[i] == '\r') i++;
 						if(i<n && buf[i] == '\n') {
-							int j;
+							unsigned int j;
 							for(j = 0; j < chunksize_buf_index; j++) {
 							if(chunksize_buf[j] >= '0'
 							   && chunksize_buf[j] <= '9')
@@ -221,15 +224,15 @@ getHTTPResponse(int s, int * size)
 							goto end_of_stream;
 						}
 					}
-					bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i);
-					if((int)(content_buf_used + bytestocopy) > content_buf_len)
+					bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
+					if((content_buf_used + bytestocopy) > content_buf_len)
 					{
-						if(content_length >= content_buf_used + (int)bytestocopy) {
+						if(content_length >= (int)(content_buf_used + bytestocopy)) {
 							content_buf_len = content_length;
 						} else {
-							content_buf_len = content_buf_used + (int)bytestocopy;
+							content_buf_len = content_buf_used + bytestocopy;
 						}
-						content_buf = (char *)realloc((void *)content_buf, 
+						content_buf = (char *)realloc((void *)content_buf,
 						                              content_buf_len);
 					}
 					memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
@@ -242,18 +245,18 @@ getHTTPResponse(int s, int * size)
 			{
 				/* not chunked */
 				if(content_length > 0
-				   && (content_buf_used + n) > content_length) {
+				   && (int)(content_buf_used + n) > content_length) {
 					/* skipping additional bytes */
 					n = content_length - content_buf_used;
 				}
 				if(content_buf_used + n > content_buf_len)
 				{
-					if(content_length >= content_buf_used + n) {
+					if(content_length >= (int)(content_buf_used + n)) {
 						content_buf_len = content_length;
 					} else {
 						content_buf_len = content_buf_used + n;
 					}
-					content_buf = (char *)realloc((void *)content_buf, 
+					content_buf = (char *)realloc((void *)content_buf,
 					                              content_buf_len);
 				}
 				memcpy(content_buf + content_buf_used, buf, n);
@@ -261,7 +264,7 @@ getHTTPResponse(int s, int * size)
 			}
 		}
 		/* use the Content-Length header value if available */
-		if(content_length > 0 && content_buf_used >= content_length)
+		if(content_length > 0 && (int)content_buf_used >= content_length)
 		{
 #ifdef DEBUG
 			printf("End of HTTP content\n");
@@ -284,10 +287,10 @@ end_of_stream:
  * do all the work.
  * Return NULL if something failed. */
 static void *
-miniwget3(const char * url, const char * host,
+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;
@@ -297,7 +300,7 @@ miniwget3(const char * url, const char * host,
 	void * content;
 
 	*size = 0;
-	s = connecthostport(host, port);
+	s = connecthostport(host, port, scope_id);
 	if(s < 0)
 		return NULL;
 
@@ -343,7 +346,7 @@ miniwget3(const char * url, const char * host,
 			                NULL, 0,
 			                NI_NUMERICHOST | NI_NUMERICSERV);
 			if(n != 0) {
-#ifdef WIN32
+#ifdef _WIN32
 				fprintf(stderr, "getnameinfo() failed : %d\n", n);
 #else
 				fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
@@ -388,24 +391,29 @@ miniwget3(const char * url, const char * host,
 /* miniwget2() :
  * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
 static void *
-miniwget2(const char * url, const char * host,
+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(url, host, port, path, size, addr_str, addr_str_len, "1.1");
-/*
-	respbuffer = miniwget3(url, 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(url, 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;
 }
 
@@ -417,12 +425,15 @@ miniwget2(const char * url, const char * host,
  *   url :		source string not modified
  *   hostname :	hostname destination string (size of MAXHOSTNAMELEN+1)
  *   port :		port (destination)
- *   path :		pointer to the path part of the URL 
+ *   path :		pointer to the path part of the URL
  *
  * 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)
@@ -438,7 +449,43 @@ int parseURL(const char * url, char * hostname, unsign
 	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)
 		{
@@ -488,35 +535,40 @@ int parseURL(const char * url, char * hostname, unsign
 	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(url, 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;
-	/* protocol://host:port/chemin */
+	/* protocol://host:port/path */
 	char hostname[MAXHOSTNAMELEN+1];
 	*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(url, hostname, port, path, size, addr, addrlen);
+	return miniwget2(hostname, port, path, size, addr, addrlen, scope_id);
 }