[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r2562: Add the miniupnpc 1.0 source to Vidalia's source tree and ad (in vidalia: . branches/upnp/src branches/upnp/src/miniupnpc)



Author: edmanm
Date: 2008-05-08 20:01:35 -0400 (Thu, 08 May 2008)
New Revision: 2562

Added:
   vidalia/branches/upnp/src/miniupnpc/
   vidalia/branches/upnp/src/miniupnpc/CMakeLists.txt
   vidalia/branches/upnp/src/miniupnpc/bsdqueue.h
   vidalia/branches/upnp/src/miniupnpc/declspec.h
   vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.c
   vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.h
   vidalia/branches/upnp/src/miniupnpc/minisoap.c
   vidalia/branches/upnp/src/miniupnpc/minisoap.h
   vidalia/branches/upnp/src/miniupnpc/minissdpc.c
   vidalia/branches/upnp/src/miniupnpc/minissdpc.h
   vidalia/branches/upnp/src/miniupnpc/miniupnpc.c
   vidalia/branches/upnp/src/miniupnpc/miniupnpc.h
   vidalia/branches/upnp/src/miniupnpc/miniupnpcmodule.c
   vidalia/branches/upnp/src/miniupnpc/miniwget.c
   vidalia/branches/upnp/src/miniupnpc/miniwget.h
   vidalia/branches/upnp/src/miniupnpc/minixml.c
   vidalia/branches/upnp/src/miniupnpc/minixml.h
   vidalia/branches/upnp/src/miniupnpc/minixmlvalid.c
   vidalia/branches/upnp/src/miniupnpc/upnpcommands.c
   vidalia/branches/upnp/src/miniupnpc/upnpcommands.h
   vidalia/branches/upnp/src/miniupnpc/upnperrors.c
   vidalia/branches/upnp/src/miniupnpc/upnperrors.h
   vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.c
   vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.h
Modified:
   vidalia/
Log:
 r283@rae:  edmanm | 2008-05-08 20:00:29 -0400
 Add the miniupnpc 1.0 source to Vidalia's source tree and add a
 CMakeLists.txt to build it as a static library.



Property changes on: vidalia
___________________________________________________________________
 svk:merge ticket from /local/vidalia [r283] on 45a62a8a-8088-484c-baad-c7b3e776dd32

Added: vidalia/branches/upnp/src/miniupnpc/CMakeLists.txt
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/CMakeLists.txt	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/CMakeLists.txt	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,29 @@
+##
+##  $Id: $
+## 
+##  This file is part of Vidalia, and is subject to the license terms in the
+##  LICENSE file, found in the top level directory of this distribution. If 
+##  you did not receive the LICENSE file with this file, you may obtain it
+##  from the Vidalia source package distributed by the Vidalia Project at
+##  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+##  may be copied, modified, propagated, or distributed except according to
+##  the terms described in the LICENSE file.
+##
+
+add_definitions(-DSTATICLIB -DNDEBUG)
+
+set(miniupnpc_SRCS
+  igd_desc_parse.c
+  minisoap.c
+  minissdpc.c
+  miniupnpc.c
+  miniwget.c
+  minixml.c
+  minixmlvalid.c
+  upnpcommands.c
+  upnperrors.c
+  upnpreplyparse.c
+)
+
+add_library(miniupnpc STATIC ${miniupnpc_SRCS})
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/CMakeLists.txt
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/bsdqueue.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/bsdqueue.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/bsdqueue.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,531 @@
+/*	$OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $	*/
+/*	$NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $	*/
+
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef	_SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists, 
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#ifdef QUEUE_MACRO_DEBUG
+#define _Q_INVALIDATE(a) (a) = ((void *)-1)
+#else
+#define _Q_INVALIDATE(a)
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+ 
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#ifdef SLIST_ENTRY
+#undef SLIST_ENTRY
+#endif
+
+#define SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+ 
+/*
+ * Singly-linked List access methods.
+ */
+#define	SLIST_FIRST(head)	((head)->slh_first)
+#define	SLIST_END(head)		NULL
+#define	SLIST_EMPTY(head)	(SLIST_FIRST(head) == SLIST_END(head))
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for((var) = SLIST_FIRST(head);					\
+	    (var) != SLIST_END(head);					\
+	    (var) = SLIST_NEXT(var, field))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != SLIST_END(head);			\
+	    (varp) = &SLIST_NEXT((var), field))
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_INIT(head) {						\
+	SLIST_FIRST(head) = SLIST_END(head);				\
+}
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
+	(slistelm)->field.sle_next = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.sle_next = (head)->slh_first;			\
+	(head)->slh_first = (elm);					\
+} while (0)
+
+#define	SLIST_REMOVE_NEXT(head, elm, field) do {			\
+	(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next;	\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	(head)->slh_first = (head)->slh_first->field.sle_next;		\
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do {			\
+	if ((head)->slh_first == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->slh_first;		\
+									\
+		while (curelm->field.sle_next != (elm))			\
+			curelm = curelm->field.sle_next;		\
+		curelm->field.sle_next =				\
+		    curelm->field.sle_next->field.sle_next;		\
+		_Q_INVALIDATE((elm)->field.sle_next);			\
+	}								\
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List access methods
+ */
+#define	LIST_FIRST(head)		((head)->lh_first)
+#define	LIST_END(head)			NULL
+#define	LIST_EMPTY(head)		(LIST_FIRST(head) == LIST_END(head))
+#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field)					\
+	for((var) = LIST_FIRST(head);					\
+	    (var)!= LIST_END(head);					\
+	    (var) = LIST_NEXT(var, field))
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST(head) = LIST_END(head);				\
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	(elm)->field.le_next = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+} while (0)
+
+#define LIST_REMOVE(elm, field) do {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev =			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+	_Q_INVALIDATE((elm)->field.le_prev);				\
+	_Q_INVALIDATE((elm)->field.le_next);				\
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do {				\
+	if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)	\
+		(elm2)->field.le_next->field.le_prev =			\
+		    &(elm2)->field.le_next;				\
+	(elm2)->field.le_prev = (elm)->field.le_prev;			\
+	*(elm2)->field.le_prev = (elm2);				\
+	_Q_INVALIDATE((elm)->field.le_prev);				\
+	_Q_INVALIDATE((elm)->field.le_next);				\
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *sqh_first;	/* first element */			\
+	struct type **sqh_last;	/* addr of last next element */		\
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type)						\
+struct {								\
+	struct type *sqe_next;	/* next element */			\
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define	SIMPLEQ_FIRST(head)	    ((head)->sqh_first)
+#define	SIMPLEQ_END(head)	    NULL
+#define	SIMPLEQ_EMPTY(head)	    (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define	SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field)				\
+	for((var) = SIMPLEQ_FIRST(head);				\
+	    (var) != SIMPLEQ_END(head);					\
+	    (var) = SIMPLEQ_NEXT(var, field))
+
+/*
+ * Simple queue functions.
+ */
+#define	SIMPLEQ_INIT(head) do {						\
+	(head)->sqh_first = NULL;					\
+	(head)->sqh_last = &(head)->sqh_first;				\
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(head)->sqh_first = (elm);					\
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.sqe_next = NULL;					\
+	*(head)->sqh_last = (elm);					\
+	(head)->sqh_last = &(elm)->field.sqe_next;			\
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(listelm)->field.sqe_next = (elm);				\
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do {			\
+	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+		(head)->sqh_last = &(head)->sqh_first;			\
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/* 
+ * tail queue access methods 
+ */
+#define	TAILQ_FIRST(head)		((head)->tqh_first)
+#define	TAILQ_END(head)			NULL
+#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define	TAILQ_EMPTY(head)						\
+	(TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field)					\
+	for((var) = TAILQ_FIRST(head);					\
+	    (var) != TAILQ_END(head);					\
+	    (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for((var) = TAILQ_LAST(head, headname);				\
+	    (var) != TAILQ_END(head);					\
+	    (var) = TAILQ_PREV(var, headname, field))
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) do {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(head)->tqh_first->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	(elm)->field.tqe_next = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+	_Q_INVALIDATE((elm)->field.tqe_prev);				\
+	_Q_INVALIDATE((elm)->field.tqe_next);				\
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do {			\
+	if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)	\
+		(elm2)->field.tqe_next->field.tqe_prev =		\
+		    &(elm2)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm2)->field.tqe_next;		\
+	(elm2)->field.tqe_prev = (elm)->field.tqe_prev;			\
+	*(elm2)->field.tqe_prev = (elm2);				\
+	_Q_INVALIDATE((elm)->field.tqe_prev);				\
+	_Q_INVALIDATE((elm)->field.tqe_next);				\
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue access methods 
+ */
+#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
+#define	CIRCLEQ_END(head)		((void *)(head))
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
+#define	CIRCLEQ_EMPTY(head)						\
+	(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field)				\
+	for((var) = CIRCLEQ_FIRST(head);				\
+	    (var) != CIRCLEQ_END(head);					\
+	    (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for((var) = CIRCLEQ_LAST(head);					\
+	    (var) != CIRCLEQ_END(head);					\
+	    (var) = CIRCLEQ_PREV(var, field))
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) do {						\
+	(head)->cqh_first = CIRCLEQ_END(head);				\
+	(head)->cqh_last = CIRCLEQ_END(head);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == CIRCLEQ_END(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == CIRCLEQ_END(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = CIRCLEQ_END(head);			\
+	if ((head)->cqh_last == CIRCLEQ_END(head))			\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.cqe_next = CIRCLEQ_END(head);			\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == CIRCLEQ_END(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if ((elm)->field.cqe_next == CIRCLEQ_END(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == CIRCLEQ_END(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+	_Q_INVALIDATE((elm)->field.cqe_prev);				\
+	_Q_INVALIDATE((elm)->field.cqe_next);				\
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do {			\
+	if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==		\
+	    CIRCLEQ_END(head))						\
+		(head).cqh_last = (elm2);				\
+	else								\
+		(elm2)->field.cqe_next->field.cqe_prev = (elm2);	\
+	if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==		\
+	    CIRCLEQ_END(head))						\
+		(head).cqh_first = (elm2);				\
+	else								\
+		(elm2)->field.cqe_prev->field.cqe_next = (elm2);	\
+	_Q_INVALIDATE((elm)->field.cqe_prev);				\
+	_Q_INVALIDATE((elm)->field.cqe_next);				\
+} while (0)
+
+#endif	/* !_SYS_QUEUE_H_ */


Property changes on: vidalia/branches/upnp/src/miniupnpc/bsdqueue.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/declspec.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/declspec.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/declspec.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,15 @@
+#ifndef __DECLSPEC_H__
+#define __DECLSPEC_H__
+
+#if defined(WIN32) && !defined(STATICLIB)
+	#ifdef MINIUPNP_EXPORTS
+		#define LIBSPEC __declspec(dllexport)
+	#else
+		#define LIBSPEC __declspec(dllimport)
+	#endif
+#else
+	#define LIBSPEC
+#endif
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/declspec.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,115 @@
+/* $Id: igd_desc_parse.c,v 1.7 2006/11/19 22:32:33 nanard Exp $ */
+/* Project : miniupnp
+ * http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2005 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided in this distribution.
+ * */
+#include "igd_desc_parse.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Start element handler :
+ * update nesting level counter and copy element name */
+void IGDstartelt(void * d, const char * name, int l)
+{
+	struct IGDdatas * datas = (struct IGDdatas *)d;
+	memcpy( datas->cureltname, name, l);
+	datas->cureltname[l] = '\0';
+	datas->level++;
+}
+
+/* End element handler :
+ * update nesting level counter and update parser state if
+ * service element is parsed */
+void IGDendelt(void * d, const char * name, int l)
+{
+	struct IGDdatas * datas = (struct IGDdatas *)d;
+	datas->level--;
+	/*printf("endelt %2d %.*s\n", datas->level, l, name);*/
+	if( (l==7) && !memcmp(name, "service", l) )
+	{
+		/*datas->state++; */
+		/*
+		if( datas->state < 1
+			&& !strcmp(datas->servicetype,
+				//	"urn:schemas-upnp-org:service:WANIPConnection:1") )
+				"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
+			datas->state ++;
+		*/
+		if(0==strcmp(datas->servicetype_CIF,
+				"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"))
+			datas->state = 2;
+		if(0==strcmp(datas->servicetype,
+				"urn:schemas-upnp-org:service:WANIPConnection:1") )
+			datas->state = 3;
+/*		if(0==strcmp(datas->servicetype,
+				"urn:schemas-upnp-org:service:WANPPPConnection:1") )
+			datas->state = 4; */
+	}
+}
+
+/* Data handler :
+ * copy data depending on the current element name and state */
+void IGDdata(void * d, const char * data, int l)
+{
+	struct IGDdatas * datas = (struct IGDdatas *)d;
+	char * dstmember = 0;
+	/*printf("%2d %s : %.*s\n",
+           datas->level, datas->cureltname, l, data);	*/
+	if( !strcmp(datas->cureltname, "URLBase") )
+		dstmember = datas->urlbase;
+	else if(datas->state<=1)
+	{
+		if( !strcmp(datas->cureltname, "serviceType") )
+			dstmember = datas->servicetype_CIF;
+		else if( !strcmp(datas->cureltname, "controlURL") )
+			dstmember = datas->controlurl_CIF;
+		else if( !strcmp(datas->cureltname, "eventSubURL") )
+			dstmember = datas->eventsuburl_CIF;
+		else if( !strcmp(datas->cureltname, "SCPDURL") )
+			dstmember = datas->scpdurl_CIF;
+		else if( !strcmp(datas->cureltname, "deviceType") )
+			dstmember = datas->devicetype_CIF;
+	}
+	else if(datas->state==2)
+	{
+		if( !strcmp(datas->cureltname, "serviceType") )
+			dstmember = datas->servicetype;
+		else if( !strcmp(datas->cureltname, "controlURL") )
+			dstmember = datas->controlurl;
+		else if( !strcmp(datas->cureltname, "eventSubURL") )
+			dstmember = datas->eventsuburl;
+		else if( !strcmp(datas->cureltname, "SCPDURL") )
+			dstmember = datas->scpdurl;
+		else if( !strcmp(datas->cureltname, "deviceType") )
+			dstmember = datas->devicetype;
+	}
+	if(dstmember)
+	{
+		if(l>=MINIUPNPC_URL_MAXSIZE)
+			l = MINIUPNPC_URL_MAXSIZE-1;
+		memcpy(dstmember, data, l);
+		dstmember[l] = '\0';
+	}
+}
+
+void printIGD(struct IGDdatas * d)
+{
+	printf("urlbase = %s\n", d->urlbase);
+	printf("WAN Device (Common interface config) :\n");
+	printf(" deviceType = %s\n", d->devicetype_CIF);
+	printf(" serviceType = %s\n", d->servicetype_CIF);
+	printf(" controlURL = %s\n", d->controlurl_CIF);
+	printf(" eventSubURL = %s\n", d->eventsuburl_CIF);
+	printf(" SCPDURL = %s\n", d->scpdurl_CIF);
+	printf("WAN Connection Device :\n");
+	printf(" deviceType = %s\n", d->devicetype);
+	printf(" servicetype = %s\n", d->servicetype);
+	printf(" controlURL = %s\n", d->controlurl);
+	printf(" eventSubURL = %s\n", d->eventsuburl);
+	printf(" SCPDURL = %s\n", d->scpdurl);
+}
+
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,38 @@
+/* $Id: igd_desc_parse.h,v 1.5 2007/04/11 15:21:09 nanard Exp $ */
+/* Project : miniupnp
+ * http://miniupnp.free.fr/
+ * 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 __IGD_DESC_PARSE_H__
+#define __IGD_DESC_PARSE_H__
+
+/* Structure to store the result of the parsing of UPnP
+ * descriptions of Internet Gateway Devices */
+#define MINIUPNPC_URL_MAXSIZE (128)
+struct IGDdatas {
+	char cureltname[MINIUPNPC_URL_MAXSIZE];
+	char urlbase[MINIUPNPC_URL_MAXSIZE];
+	int level;
+	int state;
+	char controlurl_CIF[MINIUPNPC_URL_MAXSIZE];
+	char eventsuburl_CIF[MINIUPNPC_URL_MAXSIZE];
+	char scpdurl_CIF[MINIUPNPC_URL_MAXSIZE];
+	char servicetype_CIF[MINIUPNPC_URL_MAXSIZE];
+	char devicetype_CIF[MINIUPNPC_URL_MAXSIZE];
+	char controlurl[MINIUPNPC_URL_MAXSIZE];
+	char eventsuburl[MINIUPNPC_URL_MAXSIZE];
+	char scpdurl[MINIUPNPC_URL_MAXSIZE];
+	char servicetype[MINIUPNPC_URL_MAXSIZE];
+	char devicetype[MINIUPNPC_URL_MAXSIZE];
+};
+
+void IGDstartelt(void *, const char *, int);
+void IGDendelt(void *, const char *, int);
+void IGDdata(void *, const char *, int);
+void printIGD(struct IGDdatas *);
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/igd_desc_parse.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minisoap.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minisoap.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minisoap.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,112 @@
+/* $Id: minisoap.c,v 1.15 2008/02/17 17:57:07 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.
+ *
+ * Minimal SOAP implementation for UPnP protocol.
+ */
+#include <stdio.h>
+#include <string.h>
+#ifdef WIN32
+#include <io.h>
+#include <winsock2.h>
+#define snprintf _snprintf
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+#include "minisoap.h"
+
+/* only for malloc */
+#include <stdlib.h>
+
+#ifdef WIN32
+#define PRINT_SOCKET_ERROR(x)    printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#else
+#define PRINT_SOCKET_ERROR(x) perror(x)
+#endif
+
+/* httpWrite sends the headers and the body to the socket
+ * and returns the number of bytes sent */
+static int
+httpWrite(int fd, const char * body, int bodysize,
+          const char * headers, int headerssize)
+{
+	int n = 0;
+	/*n = write(fd, headers, headerssize);*/
+	/*if(bodysize>0)
+		n += write(fd, body, bodysize);*/
+	/* Note : my old linksys router only took into account
+	 * soap request that are sent into only one packet */
+	char * p;
+	/* TODO: AVOID MALLOC */
+	p = malloc(headerssize+bodysize);
+	if(!p)
+	  return 0;
+	memcpy(p, headers, headerssize);
+	memcpy(p+headerssize, body, bodysize);
+	/*n = write(fd, p, headerssize+bodysize);*/
+	n = send(fd, p, headerssize+bodysize, 0);
+	if(n<0) {
+	  PRINT_SOCKET_ERROR("send");
+	}
+	/* disable send on the socket */
+	/* draytek routers dont seems to like that... */
+#if 0
+#ifdef WIN32
+	if(shutdown(fd, SD_SEND)<0) {
+#else
+	if(shutdown(fd, SHUT_WR)<0)	{ /*SD_SEND*/
+#endif
+		PRINT_SOCKET_ERROR("shutdown");
+	}
+#endif
+	free(p);
+	return n;
+}
+
+/* self explanatory  */
+int soapPostSubmit(int fd,
+                   const char * url,
+				   const char * host,
+				   unsigned short port,
+				   const char * action,
+				   const char * body)
+{
+	int bodysize;
+	char headerbuf[512];
+	int headerssize;
+	char portstr[8];
+	bodysize = (int)strlen(body);
+	/* We are not using keep-alive HTTP connections.
+	 * HTTP/1.1 needs the header Connection: close to do that.
+	 * This is the default with HTTP/1.0 */
+    /* Connection: Close is normally there only in HTTP/1.1 but who knows */
+	portstr[0] = '\0';
+	if(port != 80)
+		snprintf(portstr, sizeof(portstr), ":%hu", port);
+	headerssize = snprintf(headerbuf, sizeof(headerbuf),
+                       "POST %s HTTP/1.1\r\n"
+/*                       "POST %s HTTP/1.0\r\n"*/
+	                   "Host: %s%s\r\n"
+					   "User-Agent: POSIX, UPnP/1.0, miniUPnPc/1.0\r\n"
+	                   "Content-Length: %d\r\n"
+					   "Content-Type: text/xml\r\n"
+					   "SOAPAction: \"%s\"\r\n"
+					   "Connection: Close\r\n"
+					   "Cache-Control: no-cache\r\n"	/* ??? */
+					   "Pragma: no-cache\r\n"
+					   "\r\n",
+					   url, host, portstr, bodysize, action);
+#ifdef DEBUG
+	printf("SOAP request : headersize=%d bodysize=%d\n",
+	       headerssize, bodysize);
+	/*printf("%s", headerbuf);*/
+#endif
+	return httpWrite(fd, body, bodysize, headerbuf, headerssize);
+}
+
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minisoap.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minisoap.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minisoap.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minisoap.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,15 @@
+/* $Id: minisoap.h,v 1.3 2006/11/19 22:32:34 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__
+
+/*int httpWrite(int, const char *, int, const char *);*/
+int soapPostSubmit(int, const char *, const char *, unsigned short,
+				   const char *, const char *);
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minisoap.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minissdpc.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minissdpc.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minissdpc.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,107 @@
+/* $Id: minissdpc.c,v 1.4 2007/12/19 14:56:58 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2005-2007 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+/*#include <syslog.h>*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "minissdpc.h"
+#include "miniupnpc.h"
+
+#define DECODELENGTH(n, p) n = 0; \
+                           do { n = (n << 7) | (*p & 0x7f); } \
+                           while(*(p++)&0x80);
+#define CODELENGTH(n, p) do { *p = (n & 0x7f) | ((n > 0x7f) ? 0x80 : 0); \
+                              p++; n >>= 7; } while(n);
+
+struct UPNPDev *
+getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath)
+{
+	struct UPNPDev * tmp;
+	struct UPNPDev * devlist = NULL;
+	unsigned char buffer[2048];
+	ssize_t n;
+	unsigned char * p;
+	unsigned char * url;
+	unsigned int i;
+	unsigned int urlsize, stsize, usnsize, l;
+	int s;
+	struct sockaddr_un addr;
+
+	s = socket(AF_UNIX, SOCK_STREAM, 0);
+	if(s < 0)
+	{
+		/*syslog(LOG_ERR, "socket(unix): %m");*/
+		perror("socket(unix)");
+		return NULL;
+	}
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
+	if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
+	{
+		/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
+		close(s);
+		return NULL;
+	}
+	stsize = strlen(devtype);
+	buffer[0] = 1;
+	p = buffer + 1;
+	l = stsize;	CODELENGTH(l, p);
+	memcpy(p, devtype, stsize);
+	p += stsize;
+	if(write(s, buffer, p - buffer) < 0)
+	{
+		/*syslog(LOG_ERR, "write(): %m");*/
+		perror("minissdpc.c: write()");
+		close(s);
+		return NULL;
+	}
+	n = read(s, buffer, sizeof(buffer));
+	if(n<=0)
+	{
+		perror("minissdpc.c: read()");
+		close(s);
+		return NULL;
+	}
+	p = buffer + 1;
+	for(i = 0; i < buffer[0]; i++)
+	{
+		if(p+2>=buffer+sizeof(buffer))
+			break;
+		DECODELENGTH(urlsize, p);
+		if(p+urlsize+2>=buffer+sizeof(buffer))
+			break;
+		url = p;
+		p += urlsize;
+		DECODELENGTH(stsize, p);
+		if(p+stsize+2>=buffer+sizeof(buffer))
+			break;
+		tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
+		tmp->pNext = devlist;
+		tmp->descURL = tmp->buffer;
+		tmp->st = tmp->buffer + 1 + urlsize;
+		memcpy(tmp->buffer, url, urlsize);
+		tmp->buffer[urlsize] = '\0';
+		memcpy(tmp->buffer + urlsize + 1, p, stsize);
+		p += stsize;
+		tmp->buffer[urlsize+1+stsize] = '\0';
+		devlist = tmp;
+		/* added for compatibility with recent versions of MiniSSDPd 
+		 * >= 2007/12/19 */
+		DECODELENGTH(usnsize, p);
+		p += usnsize;
+		if(p>buffer + sizeof(buffer))
+			break;
+	}
+	close(s);
+	return devlist;
+}
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minissdpc.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minissdpc.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minissdpc.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minissdpc.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,15 @@
+/* $Id: minissdpc.h,v 1.1 2007/08/31 15:15:33 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__
+
+struct UPNPDev *
+getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath);
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minissdpc.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/miniupnpc.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/miniupnpc.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/miniupnpc.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,751 @@
+/* $Id: miniupnpc.c,v 1.52 2008/02/18 13:28:33 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2005-2007 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <io.h>
+#define snprintf _snprintf
+#define strncasecmp memicmp
+#define MAXHOSTNAMELEN 64
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#include <netdb.h>
+#define closesocket close
+#endif
+#include "miniupnpc.h"
+#include "minissdpc.h"
+#include "miniwget.h"
+#include "minisoap.h"
+#include "minixml.h"
+#include "upnpcommands.h"
+
+/* Uncomment the following to transmit the msearch from the same port
+ * as the UPnP multicast port. With WinXP this seems to result in the
+ * responses to the msearch being lost, thus if things dont work then
+ * comment this out. */
+/* #define TX_FROM_UPNP_PORT */
+
+#ifdef WIN32
+#define PRINT_SOCKET_ERROR(x)    printf("Socket error: %s, %d\n", x, WSAGetLastError());
+#else
+#define PRINT_SOCKET_ERROR(x) perror(x)
+#endif
+
+/* root description parsing */
+void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
+{
+	struct xmlparser parser;
+	/* xmlparser object */
+	parser.xmlstart = buffer;
+	parser.xmlsize = bufsize;
+	parser.data = data;
+	parser.starteltfunc = IGDstartelt;
+	parser.endeltfunc = IGDendelt;
+	parser.datafunc = IGDdata;
+	parser.attfunc = 0;
+	parsexml(&parser);
+#ifndef NDEBUG
+	printIGD(data);
+#endif
+}
+
+/* Content-length: nnn */
+static int getcontentlenfromline(const char * p, int n)
+{
+	static const char contlenstr[] = "content-length";
+	const char * p2 = contlenstr;
+	int a = 0;
+	while(*p2)
+	{
+		if(n==0)
+			return -1;
+		if(*p2 != *p && *p2 != (*p + 32))
+			return -1;
+		p++; p2++; n--;
+	}
+	if(n==0)
+		return -1;
+	if(*p != ':')
+		return -1;
+	p++; n--;
+	while(*p == ' ')
+	{
+		if(n==0)
+			return -1;
+		p++; n--;
+	}
+	while(*p >= '0' && *p <= '9')
+	{
+		if(n==0)
+			return -1;
+		a = (a * 10) + (*p - '0');
+		p++; n--;
+	}
+	return a;
+}
+
+static void
+getContentLengthAndHeaderLength(char * p, int n,
+                                int * contentlen, int * headerlen)
+{
+	char * line;
+	int linelen;
+	int r;
+	line = p;
+	while(line < p + n)
+	{
+		linelen = 0;
+		while(line[linelen] != '\r' && line[linelen] != '\r')
+		{
+			if(line+linelen >= p+n)
+				return;
+			linelen++;
+		}
+		r = getcontentlenfromline(line, linelen);
+		if(r>0)
+			*contentlen = r;
+		line = line + linelen + 2;
+		if(line[0] == '\r' && line[1] == '\n')
+		{
+			*headerlen = (line - p) + 2;
+			return;
+		}
+	}
+}
+
+/* simpleUPnPcommand :
+ * not so simple !
+ * return values :
+ *   0 - OK
+ *  -1 - error */
+int simpleUPnPcommand(int s, const char * url, const char * service,
+                      const char * action, struct UPNParg * args,
+                      char * buffer, int * bufsize)
+{
+	struct sockaddr_in dest;
+	char hostname[MAXHOSTNAMELEN+1];
+	unsigned short port = 0;
+	char * path;
+	char soapact[128];
+	char soapbody[2048];
+	int soapbodylen;
+	char * buf;
+	int buffree;
+    int n;
+	int contentlen, headerlen;	/* for the response */
+	snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
+	if(args==NULL)
+	{
+		/*soapbodylen = snprintf(soapbody, sizeof(soapbody),
+						"<?xml version=\"1.0\"?>\r\n"
+	    	              "<SOAP-ENV:Envelope "
+						  "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"; "
+						  "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\";>"
+						  "<SOAP-ENV:Body>"
+						  "<m:%s xmlns:m=\"%s\"/>"
+						  "</SOAP-ENV:Body></SOAP-ENV:Envelope>"
+					 	  "\r\n", action, service);*/
+		soapbodylen = snprintf(soapbody, sizeof(soapbody),
+						"<?xml version=\"1.0\"?>\r\n"
+	    	              "<s:Envelope "
+						  "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"; "
+						  "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\";>"
+						  "<s:Body>"
+						  "<m:%s xmlns:m=\"%s\">"
+						  "</m:%s>"
+						  "</s:Body></s:Envelope>"
+					 	  "\r\n", action, service, action);
+	}
+	else
+	{
+		char * p;
+		const char * pe, * pv;
+		soapbodylen = snprintf(soapbody, sizeof(soapbody),
+						"<?xml version=\"1.0\"?>\r\n"
+	    	            "<SOAP-ENV:Envelope "
+						"xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"; "
+						"SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\";>"
+						"<SOAP-ENV:Body>"
+						"<m:%s xmlns:m=\"%s\">",
+						action, service);
+		p = soapbody + soapbodylen;
+		while(args->elt)
+		{
+			/* check that we are never overflowing the string... */
+			if(soapbody + sizeof(soapbody) <= p + 100)
+			{
+				/* we keep a margin of at least 100 bytes */
+				*bufsize = 0;
+				return -1;
+			}
+			*(p++) = '<';
+			pe = args->elt;
+			while(*pe)
+				*(p++) = *(pe++);
+			*(p++) = '>';
+			if((pv = args->val))
+			{
+				while(*pv)
+					*(p++) = *(pv++);
+			}
+			*(p++) = '<';
+			*(p++) = '/';
+			pe = args->elt;
+			while(*pe)
+				*(p++) = *(pe++);
+			*(p++) = '>';
+			args++;
+		}
+		*(p++) = '<';
+		*(p++) = '/';
+		*(p++) = 'm';
+		*(p++) = ':';
+		pe = action;
+		while(*pe)
+			*(p++) = *(pe++);
+		strncpy(p, "></SOAP-ENV:Body></SOAP-ENV:Envelope>\r\n",
+		        soapbody + sizeof(soapbody) - p);
+	}
+	if(!parseURL(url, hostname, &port, &path)) return -1;
+	if(s<0)
+	{
+		s = socket(PF_INET, SOCK_STREAM, 0);
+		if(s<0)
+		{
+			PRINT_SOCKET_ERROR("socket");
+			*bufsize = 0;
+			return -1;
+		}
+		dest.sin_family = AF_INET;
+		dest.sin_port = htons(port);
+		dest.sin_addr.s_addr = inet_addr(hostname);
+		if(connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr))<0)
+		{
+			PRINT_SOCKET_ERROR("connect");
+			closesocket(s);
+			*bufsize = 0;
+			return -1;
+		}
+	}
+
+	n = soapPostSubmit(s, path, hostname, port, soapact, soapbody);
+	if(n<=0) {
+#ifdef DEBUG
+		printf("Error sending SOAP request\n");
+#endif
+		closesocket(s);
+		return -1;
+	}
+
+	contentlen = -1;
+	headerlen = -1;
+	buf = buffer;
+	buffree = *bufsize;
+	*bufsize = 0;
+	while ((n = ReceiveData(s, buf, buffree, 5000)) > 0) {
+		buffree -= n;
+		buf += n;
+		*bufsize += n;
+		getContentLengthAndHeaderLength(buffer, *bufsize,
+		                                &contentlen, &headerlen);
+#ifdef DEBUG
+		printf("received n=%dbytes bufsize=%d ContLen=%d HeadLen=%d\n",
+		       n, *bufsize, contentlen, headerlen);
+#endif
+		/* break if we received everything */
+		if(contentlen > 0 && headerlen > 0 && *bufsize >= contentlen+headerlen)
+			break;
+	}
+	
+	closesocket(s);
+	return 0;
+}
+
+/* parseMSEARCHReply()
+ * the last 4 arguments are filled during the parsing :
+ *    - location/locationsize : "location:" field of the SSDP reply packet
+ *    - st/stsize : "st:" field of the SSDP reply packet.
+ * The strings are NOT null terminated */
+static void
+parseMSEARCHReply(const char * reply, int size,
+                  const char * * location, int * locationsize,
+			      const char * * st, int * stsize)
+{
+	int a, b, i;
+	i = 0;
+	a = i;	/* start of the line */
+	b = 0;
+	while(i<size)
+	{
+		switch(reply[i])
+		{
+		case ':':
+				if(b==0)
+				{
+					b = i; /* end of the "header" */
+					/*for(j=a; j<b; j++)
+					{
+						putchar(reply[j]);
+					}
+					*/
+				}
+				break;
+		case '\x0a':
+		case '\x0d':
+				if(b!=0)
+				{
+					/*for(j=b+1; j<i; j++)
+					{
+						putchar(reply[j]);
+					}
+					putchar('\n');*/
+					do { b++; } while(reply[b]==' ');
+					if(0==strncasecmp(reply+a, "location", 8))
+					{
+						*location = reply+b;
+						*locationsize = i-b;
+					}
+					else if(0==strncasecmp(reply+a, "st", 2))
+					{
+						*st = reply+b;
+						*stsize = i-b;
+					}
+					b = 0;
+				}
+				a = i+1;
+				break;
+		default:
+				break;
+		}
+		i++;
+	}
+}
+
+/* port upnp discover : SSDP protocol */
+#define PORT (1900)
+#define UPNP_MCAST_ADDR "239.255.255.250"
+
+/* upnpDiscover() :
+ * return a chained list of all devices found or NULL if
+ * no devices was found.
+ * It is up to the caller to free the chained list
+ * delay is in millisecond (poll) */
+struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
+                              const char * minissdpdsock)
+{
+	struct UPNPDev * tmp;
+	struct UPNPDev * devlist = 0;
+	int opt = 1;
+	static const char MSearchMsgFmt[] = 
+	"M-SEARCH * HTTP/1.1\r\n"
+	"HOST: " UPNP_MCAST_ADDR ":" "1900" "\r\n"
+	"ST: %s\r\n"
+	"MAN: \"ssdp:discover\"\r\n"
+	"MX: 3\r\n"
+	"\r\n";
+	static const char * const deviceList[] = {
+		"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
+		"urn:schemas-upnp-org:service:WANIPConnection:1",
+		"urn:schemas-upnp-org:service:WANPPPConnection:1",
+		"upnp:rootdevice",
+		0
+	};
+	int deviceIndex = 0;
+	char bufr[1536];	/* reception and emission buffer */
+	int sudp;
+	int n;
+	struct sockaddr_in sockudp_r, sockudp_w;
+
+#ifndef WIN32
+	/* first try to get infos from minissdpd ! */
+	if(!minissdpdsock)
+		minissdpdsock = "/var/run/minissdpd.sock";
+	while(!devlist && deviceList[deviceIndex]) {
+		devlist = getDevicesFromMiniSSDPD(deviceList[deviceIndex],
+		                                  minissdpdsock);
+		/* We return what we have found if it was not only a rootdevice */
+		if(devlist && !strstr(deviceList[deviceIndex], "rootdevice"))
+			return devlist;
+		deviceIndex++;
+	}
+	deviceIndex = 0;
+#endif
+	/* fallback to direct discovery */
+#ifdef WIN32
+	sudp = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+#else
+	sudp = socket(PF_INET, SOCK_DGRAM, 0);
+#endif
+	if(sudp < 0)
+	{
+		PRINT_SOCKET_ERROR("socket");
+		return NULL;
+	}
+    /* reception */
+    memset(&sockudp_r, 0, sizeof(struct sockaddr_in));
+    sockudp_r.sin_family = AF_INET;
+#ifdef TX_FROM_UPNP_PORT
+    sockudp_r.sin_port = htons(PORT);
+#endif
+    sockudp_r.sin_addr.s_addr = INADDR_ANY;
+    /* emission */
+    memset(&sockudp_w, 0, sizeof(struct sockaddr_in));
+    sockudp_w.sin_family = AF_INET;
+    sockudp_w.sin_port = htons(PORT);
+    sockudp_w.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
+
+#ifdef WIN32
+	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
+#else
+	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
+#endif
+	{
+		PRINT_SOCKET_ERROR("setsockopt");
+		return NULL;
+	}
+
+	if(multicastif)
+	{
+		struct in_addr mc_if;
+		mc_if.s_addr = inet_addr(multicastif);
+    	sockudp_r.sin_addr.s_addr = mc_if.s_addr;
+		if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
+		{
+			PRINT_SOCKET_ERROR("setsockopt");
+		}
+	}
+
+	/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
+    if (bind(sudp, (struct sockaddr *)&sockudp_r, sizeof(struct sockaddr_in)) != 0)
+	{
+        PRINT_SOCKET_ERROR("bind");
+		closesocket(sudp);
+		return NULL;
+    }
+
+	/* receiving SSDP response packet */
+	for(n = 0;;)
+	{
+	if(n == 0)
+	{
+		/* sending the SSDP M-SEARCH packet */
+		n = snprintf(bufr, sizeof(bufr),
+		             MSearchMsgFmt, deviceList[deviceIndex++]);
+		/*printf("Sending %s", bufr);*/
+		n = sendto(sudp, bufr, n, 0,
+		           (struct sockaddr *)&sockudp_w, sizeof(struct sockaddr_in));
+		if (n < 0) {
+			PRINT_SOCKET_ERROR("sendto");
+			closesocket(sudp);
+			return devlist;
+		}
+	}
+	/* Waiting for SSDP REPLY packet to M-SEARCH */
+	n = ReceiveData(sudp, bufr, sizeof(bufr), delay);
+	if (n < 0) {
+		/* error */
+		closesocket(sudp);
+		return devlist;
+	} else if (n == 0) {
+		/* no data or Time Out */
+		if (devlist || (deviceList[deviceIndex] == 0)) {
+			/* no more device type to look for... */
+			closesocket(sudp);
+			return devlist;
+		}
+	} else {
+		const char * descURL=NULL;
+		int urlsize=0;
+		const char * st=NULL;
+		int stsize=0;
+        /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */
+		parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
+		if(st&&descURL)
+		{
+			/*printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
+			       stsize, st, urlsize, descURL); */
+			tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
+			tmp->pNext = devlist;
+			tmp->descURL = tmp->buffer;
+			tmp->st = tmp->buffer + 1 + urlsize;
+			memcpy(tmp->buffer, descURL, urlsize);
+			tmp->buffer[urlsize] = '\0';
+			memcpy(tmp->buffer + urlsize + 1, st, stsize);
+			tmp->buffer[urlsize+1+stsize] = '\0';
+			devlist = tmp;
+		}
+	}
+	}
+}
+
+/* freeUPNPDevlist() should be used to
+ * free the chained list returned by upnpDiscover() */
+void freeUPNPDevlist(struct UPNPDev * devlist)
+{
+	struct UPNPDev * next;
+	while(devlist)
+	{
+		next = devlist->pNext;
+		free(devlist);
+		devlist = next;
+	}
+}
+
+static void
+url_cpy_or_cat(char * dst, const char * src, int n)
+{
+	if(  (src[0] == 'h')
+	   &&(src[1] == 't')
+	   &&(src[2] == 't')
+	   &&(src[3] == 'p')
+	   &&(src[4] == ':')
+	   &&(src[5] == '/')
+	   &&(src[6] == '/'))
+	{
+		strncpy(dst, src, n);
+	}
+	else
+	{
+		int l = strlen(dst);
+		if(src[0] != '/')
+			dst[l++] = '/';
+		if(l<=n)
+			strncpy(dst + l, src, n - l);
+	}
+}
+
+/* Prepare the Urls for usage...
+ */
+void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
+                 const char * descURL)
+{
+	char * p;
+	int n1, n2, n3;
+	n1 = strlen(data->urlbase);
+	if(n1==0)
+		n1 = strlen(descURL);
+	n1 += 2;	/* 1 byte more for Null terminator, 1 byte for '/' if needed */
+	n2 = n1; n3 = n1;
+	n1 += strlen(data->scpdurl);
+	n2 += strlen(data->controlurl);
+	n3 += strlen(data->controlurl_CIF);
+
+	urls->ipcondescURL = (char *)malloc(n1);
+	urls->controlURL = (char *)malloc(n2);
+	urls->controlURL_CIF = (char *)malloc(n3);
+	/* maintenant on chope la desc du WANIPConnection */
+	if(data->urlbase[0] != '\0')
+		strncpy(urls->ipcondescURL, data->urlbase, n1);
+	else
+		strncpy(urls->ipcondescURL, descURL, n1);
+	p = strchr(urls->ipcondescURL+7, '/');
+	if(p) p[0] = '\0';
+	strncpy(urls->controlURL, urls->ipcondescURL, n2);
+	strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3);
+	
+	url_cpy_or_cat(urls->ipcondescURL, data->scpdurl, n1);
+
+	url_cpy_or_cat(urls->controlURL, data->controlurl, n2);
+
+	url_cpy_or_cat(urls->controlURL_CIF, data->controlurl_CIF, n3);
+
+#ifdef DEBUG
+	printf("urls->ipcondescURL='%s' %d n1=%d\n", urls->ipcondescURL,
+	       strlen(urls->ipcondescURL), n1);
+	printf("urls->controlURL='%s' %d n2=%d\n", urls->controlURL,
+	       strlen(urls->controlURL), n2);
+	printf("urls->controlURL_CIF='%s' %d n3=%d\n", urls->controlURL_CIF,
+	       strlen(urls->controlURL_CIF), n3);
+#endif
+}
+
+void
+FreeUPNPUrls(struct UPNPUrls * urls)
+{
+	if(!urls)
+		return;
+	free(urls->controlURL);
+	urls->controlURL = 0;
+	free(urls->ipcondescURL);
+	urls->ipcondescURL = 0;
+	free(urls->controlURL_CIF);
+	urls->controlURL_CIF = 0;
+}
+
+
+int ReceiveData(int socket, char * data, int length, int timeout)
+{
+    int n;
+#ifndef WIN32
+    struct pollfd fds[1]; /* for the poll */
+    fds[0].fd = socket;
+    fds[0].events = POLLIN;
+    n = poll(fds, 1, timeout);
+    if(n < 0)
+    {
+        PRINT_SOCKET_ERROR("poll");
+        return -1;
+    }
+    else if(n == 0)
+    {
+        return 0;
+    }
+#else
+    fd_set socketSet;
+    TIMEVAL timeval;
+    FD_ZERO(&socketSet);
+    FD_SET(socket, &socketSet);
+    timeval.tv_sec = timeout / 1000;
+    timeval.tv_usec = (timeout % 1000) * 1000;
+    /*n = select(0, &socketSet, NULL, NULL, &timeval);*/
+    n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval);
+    if(n < 0)
+    {
+        PRINT_SOCKET_ERROR("select");
+        return -1;
+    }
+    else if(n == 0)
+    {
+        return 0;
+    }    
+#endif
+	n = recv(socket, data, length, 0);
+	if(n<0)
+	{
+		PRINT_SOCKET_ERROR("recv");
+	}
+	return n;
+}
+
+int
+UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
+{
+	char status[64];
+	unsigned int uptime;
+	status[0] = '\0';
+	UPNP_GetStatusInfo(urls->controlURL, data->servicetype,
+	                   status, &uptime, NULL);
+	if(0 == strcmp("Connected", status))
+	{
+		return 1;
+	}
+	else
+		return 0;
+}
+
+
+/* UPNP_GetValidIGD() :
+ * return values :
+ *     0 = NO IGD found
+ *     1 = A valid connected IGD has been found
+ *     2 = A valid IGD has been found but it reported as
+ *         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
+ * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
+ * free allocated memory.
+ */
+int
+UPNP_GetValidIGD(struct UPNPDev * devlist,
+                 struct UPNPUrls * urls,
+				 struct IGDdatas * data,
+				 char * lanaddr, int lanaddrlen)
+{
+	char * descXML;
+	int descXMLsize = 0;
+	struct UPNPDev * dev;
+	int ndev = 0;
+	int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
+	if(!devlist)
+	{
+#ifdef DEBUG
+		printf("Empty devlist\n");
+#endif
+		return 0;
+	}
+	for(state = 1; state <= 3; state++)
+	{
+		for(dev = devlist; dev; dev = dev->pNext)
+		{
+			/* we should choose an internet gateway device.
+		 	* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
+			descXML = miniwget_getaddr(dev->descURL, &descXMLsize,
+			   	                        lanaddr, lanaddrlen);
+			if(descXML)
+			{
+				ndev++;
+				memset(data, 0, sizeof(struct IGDdatas));
+				memset(urls, 0, sizeof(struct UPNPUrls));
+				parserootdesc(descXML, descXMLsize, data);
+				free(descXML);
+				descXML = NULL;
+				if(0==strcmp(data->servicetype_CIF,
+				   "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1")
+				   || state >= 3 )
+				{
+				  GetUPNPUrls(urls, data, dev->descURL);
+
+#ifdef DEBUG
+				  printf("UPNPIGD_IsConnected(%s) = %d\n",
+				     urls->controlURL,
+			         UPNPIGD_IsConnected(urls, data));
+#endif
+				  if((state >= 2) || UPNPIGD_IsConnected(urls, data))
+					return state;
+				  FreeUPNPUrls(urls);
+				}
+				memset(data, 0, sizeof(struct IGDdatas));
+			}
+#ifdef DEBUG
+			else
+			{
+				printf("error getting XML description %s\n", dev->descURL);
+			}
+#endif
+		}
+	}
+	return 0;
+}
+
+/* UPNP_GetIGDFromUrl()
+ * Used when skipping the discovery process.
+ * return value :
+ *   0 - Not ok
+ *   1 - OK */
+int
+UPNP_GetIGDFromUrl(const char * rootdescurl,
+                   struct UPNPUrls * urls,
+                   struct IGDdatas * data,
+                   char * lanaddr, int lanaddrlen)
+{
+	char * descXML;
+	int descXMLsize = 0;
+	descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
+	   	                       lanaddr, lanaddrlen);
+	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);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/miniupnpc.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/miniupnpc.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/miniupnpc.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/miniupnpc.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,108 @@
+/* $Id: miniupnpc.h,v 1.17 2007/12/19 14:58:54 nanard Exp $ */
+/* Project: miniupnp
+ * http://miniupnp.free.fr/
+ * Author: Thomas Bernard
+ * Copyright (c) 2005-2006 Thomas Bernard
+ * This software is subjects to the conditions detailed
+ * in the LICENCE file provided within this distribution */
+#ifndef __MINIUPNPC_H__
+#define __MINIUPNPC_H__
+
+#include "declspec.h"
+#include "igd_desc_parse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Structures definitions : */
+struct UPNParg { const char * elt; const char * val; };
+
+int simpleUPnPcommand(int, const char *, const char *,
+                      const char *, struct UPNParg *,
+                      char *, int *);
+
+struct UPNPDev {
+	struct UPNPDev * pNext;
+	char * descURL;
+	char * st;
+	char buffer[2];
+};
+
+/* upnpDiscover()
+ * discover UPnP devices on the network.
+ * The discovered devices are returned as a chained list.
+ * It is up to the caller to free the list with freeUPNPDevlist().
+ * delay (in millisecond) is the maximum time for waiting any device
+ * response.
+ * If available, device list will be obtained from MiniSSDPd.
+ * Default path for minissdpd socket will be used if minissdpdsock argument
+ * is NULL.
+ * If multicastif is not NULL, it will be used instead of the default
+ * multicast interface for sending SSDP discover packets. */
+LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
+                                      const char * minissdpdsock);
+/* freeUPNPDevlist()
+ * free list returned by upnpDiscover() */
+LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist);
+
+/* parserootdesc() :
+ * parse root XML description of a UPnP device and fill the IGDdatas
+ * structure. */
+LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
+
+/* structure used to get fast access to urls
+ * controlURL: controlURL of the WANIPConnection
+ * ipcondescURL: url of the description of the WANIPConnection
+ * controlURL_CIF: controlURL of the WANCommonInterfaceConfig
+ */
+struct UPNPUrls {
+	char * controlURL;
+	char * ipcondescURL;
+	char * controlURL_CIF;
+};
+
+/* UPNP_GetValidIGD() :
+ * return values :
+ *     0 = NO IGD found
+ *     1 = A valid connected IGD has been found
+ *     2 = A valid IGD has been found but it reported as
+ *         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
+ * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
+ * free allocated memory.
+ */
+LIBSPEC int
+UPNP_GetValidIGD(struct UPNPDev * devlist,
+                 struct UPNPUrls * urls,
+				 struct IGDdatas * data,
+				 char * lanaddr, int lanaddrlen);
+
+/* UPNP_GetIGDFromUrl()
+ * Used when skipping the discovery process.
+ * return value :
+ *   0 - Not ok
+ *   1 - OK */
+LIBSPEC int
+UPNP_GetIGDFromUrl(const char * rootdescurl,
+                   struct UPNPUrls * urls,
+                   struct IGDdatas * data,
+                   char * lanaddr, int lanaddrlen);
+
+LIBSPEC void GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, const char *);
+
+LIBSPEC void FreeUPNPUrls(struct UPNPUrls *);
+
+/* 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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/miniupnpc.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/miniupnpcmodule.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/miniupnpcmodule.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/miniupnpcmodule.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,413 @@
+/* $Id: miniupnpcmodule.c,v 1.7 2007/12/19 15:00:47 nanard Exp $*/
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * website : http://miniupnp.tuxfamily.org/
+ * copyright (c) 2007 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <Python.h>
+#define STATICLIB
+#include "structmember.h"
+#include "miniupnpc.h"
+#include "upnpcommands.h"
+
+/* for compatibility with Python < 2.4 */
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#endif
+
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
+#endif
+
+typedef struct {
+    PyObject_HEAD
+    /* Type-specific fields go here. */
+	struct UPNPDev * devlist;
+	struct UPNPUrls urls;
+	struct IGDdatas data;
+	unsigned int discoverdelay;	/* value passed to upnpDiscover() */
+	char lanaddr[16];	/* our ip address on the LAN */
+	char * multicastif;
+	char * minissdpdsocket;
+} UPnPObject;
+
+static PyMemberDef UPnP_members[] = {
+	{"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
+	 READONLY, "ip address on the LAN"
+	},
+	{"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
+	 0/*READWRITE*/, "value in ms used to wait for SSDP responses"
+	},
+	/* T_STRING is allways readonly :( */
+	{"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
+	 0, "IP of the network interface to be used for multicast operations"
+	},
+	{"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
+	 0, "path of the MiniSSDPd unix socket"
+	},
+	{NULL}
+};
+
+static void
+UPnPObject_dealloc(UPnPObject *self)
+{
+	freeUPNPDevlist(self->devlist);
+	FreeUPNPUrls(&self->urls);
+	self->ob_type->tp_free((PyObject*)self);
+}
+
+static PyObject *
+UPnP_discover(UPnPObject *self)
+{
+	struct UPNPDev * dev;
+	int i;
+	PyObject *res = NULL;
+	if(self->devlist)
+	{
+		freeUPNPDevlist(self->devlist);
+		self->devlist = 0;
+	}
+	self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
+	                             0/* multicast if*/,
+	                             0/*minissdpd socket*/);
+	/* Py_RETURN_NONE ??? */
+	for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
+		i++;
+	res = Py_BuildValue("i", i);
+	return res;
+}
+
+static PyObject *
+UPnP_selectigd(UPnPObject *self)
+{
+	if(UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
+	                    self->lanaddr, sizeof(self->lanaddr)))
+	{
+		return Py_BuildValue("s", self->urls.controlURL);
+	}
+	else
+	{
+		/* TODO: have our own exception type ! */
+		PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
+		return NULL;
+	}
+}
+
+static PyObject *
+UPnP_totalbytesent(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_totalbytereceived(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_totalpacketsent(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_totalpacketreceived(UPnPObject *self)
+{
+	return Py_BuildValue("I",
+	           UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
+			                          self->data.servicetype_CIF));
+}
+
+static PyObject *
+UPnP_statusinfo(UPnPObject *self)
+{
+	char status[64];
+	unsigned int uptime = 0;
+	status[0] = '\0';
+	UPNP_GetStatusInfo(self->urls.controlURL, self->data.servicetype,
+	                   status, &uptime);
+	return Py_BuildValue("(s,I)", status, uptime);
+}
+
+static PyObject *
+UPnP_connectiontype(UPnPObject *self)
+{
+	char connectionType[64];
+	connectionType[0] = '\0';
+	UPNP_GetConnectionTypeInfo(self->urls.controlURL,
+	                           self->data.servicetype,
+							   connectionType);
+	return Py_BuildValue("s", connectionType);
+}
+
+static PyObject *
+UPnP_externalipaddress(UPnPObject *self)
+{
+	char externalIPAddress[16];
+	externalIPAddress[0] = '\0';
+	UPNP_GetExternalIPAddress(self->urls.controlURL,
+	                          self->data.servicetype,
+							  externalIPAddress);
+	return Py_BuildValue("s", externalIPAddress);
+}
+
+/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc) 
+ * protocol is 'UDP' or 'TCP' */
+static PyObject *
+UPnP_addportmapping(UPnPObject *self, PyObject *args)
+{
+	char extPort[6];
+	unsigned short ePort;
+	char inPort[6];
+	unsigned short iPort;
+	const char * proto;
+	const char * host;
+	const char * desc;
+	int r;
+	if (!PyArg_ParseTuple(args, "HssHs", &ePort, &proto,
+	                                     &host, &iPort, &desc))
+        return NULL;
+	sprintf(extPort, "%hu", ePort);
+	sprintf(inPort, "%hu", iPort);
+	r = UPNP_AddPortMapping(self->urls.controlURL, self->data.servicetype,
+	                        extPort, inPort, host, desc, proto);
+	if(r)
+	{
+		Py_RETURN_TRUE;
+	}
+	else
+	{
+		Py_RETURN_FALSE;
+	}
+}
+
+/* DeletePortMapping(extPort, proto)
+ * proto = 'UDP', 'TCP' */
+static PyObject *
+UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
+{
+	char extPort[6];
+	unsigned short ePort;
+	const char * proto;
+	if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
+		return NULL;
+	sprintf(extPort, "%hu", ePort);
+	UPNP_DeletePortMapping(self->urls.controlURL, self->data.servicetype,
+	                       extPort, proto);
+	Py_RETURN_TRUE;
+}
+
+static PyObject *
+UPnP_getportmappingnumberofentries(UPnPObject *self)
+{
+	unsigned int n = 0;
+	UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
+	                                   self->data.servicetype,
+									   &n);
+	return Py_BuildValue("I", n);
+}
+
+/* GetSpecificPortMapping(ePort, proto) 
+ * proto = 'UDP' or 'TCP' */
+static PyObject *
+UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
+{
+	char extPort[6];
+	unsigned short ePort;
+	const char * proto;
+	char intClient[16];
+	char intPort[6];
+	unsigned short iPort;
+	if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
+		return NULL;
+	sprintf(extPort, "%hu", ePort);
+	UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
+	                                 self->data.servicetype,
+									 extPort, proto,
+									 intClient, intPort);
+	if(intClient[0])
+	{
+		iPort = (unsigned short)atoi(intPort);
+		return Py_BuildValue("(s,H)", intClient, iPort);
+	}
+	else
+	{
+		Py_RETURN_NONE;
+	}
+}
+
+/* GetGenericPortMapping(index) */
+static PyObject *
+UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
+{
+	int i, r;
+	char index[8];
+	char intClient[16];
+	char intPort[6];
+	unsigned short iPort;
+	char extPort[6];
+	unsigned short ePort;
+	char protocol[4];
+	char desc[80];
+	char enabled[6];
+	char rHost[64];
+	char duration[16];	/* lease duration */
+	unsigned int dur;
+	if(!PyArg_ParseTuple(args, "i", &i))
+		return NULL;
+	snprintf(index, sizeof(index), "%d", i);
+	rHost[0] = '\0'; enabled[0] = '\0';
+	duration[0] = '\0'; desc[0] = '\0';
+	extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
+	r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
+	                                    self->data.servicetype,
+										index,
+										extPort, intClient, intPort,
+										protocol, desc, enabled, rHost,
+										duration);
+	if(r)
+	{
+		Py_RETURN_NONE;
+	}
+	else
+	{
+		ePort = (unsigned short)atoi(extPort);
+		iPort = (unsigned short)atoi(intPort);
+		dur = (unsigned int)strtoul(duration, 0, 0);
+		return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
+		                     ePort, protocol, intClient, iPort,
+		                     desc, enabled, rHost, dur);
+	}
+}
+
+/* miniupnpc.UPnP object Method Table */
+static PyMethodDef UPnP_methods[] = {
+    {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
+     "discover UPnP IGD devices on the network"
+    },
+	{"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
+	 "select a valid UPnP IGD among discovered devices"
+	},
+	{"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
+	 "return the total number of bytes sent by UPnP IGD"
+	},
+	{"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
+	 "return the total number of bytes received by UPnP IGD"
+	},
+	{"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
+	 "return the total number of packets sent by UPnP IGD"
+	},
+	{"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
+	 "return the total number of packets received by UPnP IGD"
+	},
+	{"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
+	 "return status and uptime"
+	},
+	{"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
+	 "return IGD WAN connection type"
+	},
+	{"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
+	 "return external IP address"
+	},
+	{"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
+	 "add a port mapping"
+	},
+	{"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
+	 "delete a port mapping"
+	},
+	{"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
+	 "-- non standard --"
+	},
+	{"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
+	 "get details about a specific port mapping entry"
+	},
+	{"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
+	 "get all details about the port mapping at index"
+	},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject UPnPType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                         /*ob_size*/
+    "miniupnpc.UPnP",          /*tp_name*/
+    sizeof(UPnPObject),        /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)UPnPObject_dealloc,/*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_compare*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
+    "UPnP objects",            /* tp_doc */
+    0,		                   /* tp_traverse */
+    0,		                   /* tp_clear */
+    0,		                   /* tp_richcompare */
+    0,		                   /* tp_weaklistoffset */
+    0,		                   /* tp_iter */
+    0,		                   /* tp_iternext */
+    UPnP_methods,              /* tp_methods */
+    UPnP_members,              /* tp_members */
+    0,                         /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,/*(initproc)UPnP_init,*/      /* tp_init */
+    0,                         /* tp_alloc */
+#ifndef WIN32
+    PyType_GenericNew,/*UPnP_new,*/      /* tp_new */
+#else
+    0,
+#endif
+};
+
+/* module methods */
+static PyMethodDef miniupnpc_methods[] = {
+    {NULL}  /* Sentinel */
+};
+
+#ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC
+initminiupnpc(void) 
+{
+    PyObject* m;
+
+#ifdef WIN32
+    UPnPType.tp_new = PyType_GenericNew;
+#endif
+    if (PyType_Ready(&UPnPType) < 0)
+        return;
+
+    m = Py_InitModule3("miniupnpc", miniupnpc_methods,
+                       "miniupnpc module.");
+
+    Py_INCREF(&UPnPType);
+    PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
+}
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/miniupnpcmodule.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/miniwget.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/miniwget.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/miniwget.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,219 @@
+/* $Id: miniwget.c,v 1.19 2007/11/02 14:16:19 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.
+ * */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "miniupnpc.h"
+#ifdef WIN32
+#include <winsock2.h>
+#include <io.h>
+#define MAXHOSTNAMELEN 64
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define snprintf _snprintf
+#define herror
+#define socklen_t int
+#else
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#define closesocket close
+#endif
+/* for MIN() macro : */
+#if defined(__sun) || defined(sun)
+#include <utility.h>
+#endif
+
+/* miniwget2() :
+ * */
+static void *
+miniwget2(const char * url, const char * host,
+		  unsigned short port, const char * path,
+		  int * size, char * addr_str, int addr_str_len)
+{
+	char buf[2048];
+    int s;
+	struct sockaddr_in dest;
+	struct hostent *hp;
+	*size = 0;
+	hp = gethostbyname(host);
+	if(hp==NULL)
+	{
+		herror(host);
+		return NULL;
+	}
+	/*  memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length);  */
+	memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
+	memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
+	s = socket(PF_INET, SOCK_STREAM, 0);
+	if(s < 0)
+	{
+		perror("socket");
+		return NULL;
+	}
+	dest.sin_family = AF_INET;
+	dest.sin_port = htons(port);
+	if(connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in))<0)
+	{
+		perror("connect");
+		closesocket(s);
+		return NULL;
+	}
+
+	/* get address for caller ! */
+	if(addr_str)
+	{
+		struct sockaddr_in saddr;
+		socklen_t len;
+
+		len = sizeof(saddr);
+		getsockname(s, (struct sockaddr *)&saddr, &len);
+#ifndef WIN32
+		inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
+#else
+	/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
+     * But his function make a string with the port :  nn.nn.nn.nn:port */
+/*		if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
+                            NULL, addr_str, (DWORD *)&addr_str_len))
+		{
+		    printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
+		}*/
+		strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len);
+#endif
+#ifdef DEBUG
+		printf("address miniwget : %s\n", addr_str);
+#endif
+	}
+
+	snprintf(buf, sizeof(buf),
+                 "GET %s HTTP/1.1\r\n"
+			     "Host: %s:%d\r\n"
+				 "Connection: Close\r\n"
+				 "\r\n",
+		    path, host, port);
+	/*write(s, buf, strlen(buf));*/
+	send(s, buf, strlen(buf), 0);
+	{
+		int n, headers=1;
+		char * respbuffer = NULL;
+		int allreadyread = 0;
+		/*while((n = recv(s, buf, 2048, 0)) > 0)*/
+		while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
+		{
+			if(headers)
+			{
+				int i=0;
+				while(i<n-3)
+				{
+					if(buf[i]=='\r' && buf[i+1]=='\n'
+					   && buf[i+2]=='\r' && buf[i+3]=='\n')
+					{
+						headers = 0;	/* end */
+						if(i<n-4)
+						{
+							respbuffer = (char *)realloc((void *)respbuffer, 
+														 allreadyread+(n-i-4));
+							memcpy(respbuffer+allreadyread, buf + i + 4, n-i-4);
+							allreadyread += (n-i-4);
+						}
+						break;
+					}
+					i++;
+				}
+			}
+			else
+			{
+				respbuffer = (char *)realloc((void *)respbuffer, 
+								 allreadyread+n);
+				memcpy(respbuffer+allreadyread, buf, n);
+				allreadyread += n;
+			}
+		}
+		*size = allreadyread;
+#ifndef NDEBUG
+		printf("%d bytes read\n", *size);
+#endif
+		closesocket(s);
+		return respbuffer;
+	}
+}
+
+/* parseURL()
+ * arguments :
+ *   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 
+ *
+ * Return values :
+ *    0 - Failure
+ *    1 - Success         */
+int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
+{
+	char * p1, *p2, *p3;
+	p1 = strstr(url, "://");
+	if(!p1)
+		return 0;
+	p1 += 3;
+	if(  (url[0]!='h') || (url[1]!='t')
+	   ||(url[2]!='t') || (url[3]!='p'))
+		return 0;
+	p2 = strchr(p1, ':');
+	p3 = strchr(p1, '/');
+	if(!p3)
+		return 0;
+	memset(hostname, 0, MAXHOSTNAMELEN + 1);
+	if(!p2 || (p2>p3))
+	{
+		strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
+		*port = 80;
+	}
+	else
+	{
+		strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
+		*port = 0;
+		p2++;
+		while( (*p2 >= '0') && (*p2 <= '9'))
+		{
+			*port *= 10;
+			*port += (unsigned short)(*p2 - '0');
+			p2++;
+		}
+	}
+	*path = p3;
+	return 1;
+}
+
+void * miniwget(const char * url, int * size)
+{
+	unsigned short port;
+	char * path;
+	/* protocol://host:port/chemin */
+	char hostname[MAXHOSTNAMELEN+1];
+	*size = 0;
+	if(!parseURL(url, hostname, &port, &path))
+		return NULL;
+	return miniwget2(url, hostname, port, path, size, 0, 0);
+}
+
+void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
+{
+	unsigned short port;
+	char * path;
+	/* protocol://host:port/chemin */
+	char hostname[MAXHOSTNAMELEN+1];
+	*size = 0;
+	if(addr)
+		addr[0] = '\0';
+	if(!parseURL(url, hostname, &port, &path))
+		return NULL;
+	return miniwget2(url, hostname, port, path, size, addr, addrlen);
+}
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/miniwget.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/miniwget.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/miniwget.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/miniwget.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,28 @@
+/* $Id: miniwget.h,v 1.5 2007/01/29 20:27:23 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 __MINIWGET_H__
+#define __MINIWGET_H__
+
+#include "declspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBSPEC void * miniwget(const char *, int *);
+
+LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int);
+
+int parseURL(const char *, char *, unsigned short *, char * *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/miniwget.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minixml.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minixml.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minixml.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,191 @@
+/* $Id: minixml.c,v 1.6 2007/05/15 18:14:08 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-2007, Thomas BERNARD 
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * The name of the author may not be used to endorse or promote products
+	  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "minixml.h"
+
+/* parseatt : used to parse the argument list
+ * return 0 (false) in case of success and -1 (true) if the end
+ * of the xmlbuffer is reached. */
+int parseatt(struct xmlparser * p)
+{
+	const char * attname;
+	int attnamelen;
+	const char * attvalue;
+	int attvaluelen;
+	while(p->xml < p->xmlend)
+	{
+		if(*p->xml=='/' || *p->xml=='>')
+			return 0;
+		if( !IS_WHITE_SPACE(*p->xml) )
+		{
+			char sep;
+			attname = p->xml;
+			attnamelen = 0;
+			while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
+			{
+				attnamelen++; p->xml++;
+				if(p->xml >= p->xmlend)
+					return -1;
+			}
+			while(*(p->xml++) != '=')
+			{
+				if(p->xml >= p->xmlend)
+					return -1;
+			}
+			while(IS_WHITE_SPACE(*p->xml))
+			{
+				p->xml++;
+				if(p->xml >= p->xmlend)
+					return -1;
+			}
+			sep = *p->xml;
+			if(sep=='\'' || sep=='\"')
+			{
+				p->xml++;
+				if(p->xml >= p->xmlend)
+					return -1;
+				attvalue = p->xml;
+				attvaluelen = 0;
+				while(*p->xml != sep)
+				{
+					attvaluelen++; p->xml++;
+					if(p->xml >= p->xmlend)
+						return -1;
+				}
+			}
+			else
+			{
+				attvalue = p->xml;
+				attvaluelen = 0;
+				while(   !IS_WHITE_SPACE(*p->xml)
+					  && *p->xml != '>' && *p->xml != '/')
+				{
+					attvaluelen++; p->xml++;
+					if(p->xml >= p->xmlend)
+						return -1;
+				}
+			}
+			/*printf("%.*s='%.*s'\n",
+			       attnamelen, attname, attvaluelen, attvalue);*/
+			if(p->attfunc)
+				p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
+		}
+		p->xml++;
+	}
+	return -1;
+}
+
+/* parseelt parse the xml stream and
+ * call the callback functions when needed... */
+void parseelt(struct xmlparser * p)
+{
+	int i;
+	const char * elementname;
+	while(p->xml < (p->xmlend - 1))
+	{
+		if((p->xml)[0]=='<' && (p->xml)[1]!='?')
+		{
+			i = 0; elementname = ++p->xml;
+			while( !IS_WHITE_SPACE(*p->xml)
+				  && (*p->xml!='>') && (*p->xml!='/')
+				 )
+			{
+				i++; p->xml++;
+				if (p->xml >= p->xmlend)
+					return;
+				/* to ignore namespace : */
+				if(*p->xml==':')
+				{
+					i = 0;
+					elementname = ++p->xml;
+				}
+			}
+			if(i>0)
+			{
+				if(p->starteltfunc)
+					p->starteltfunc(p->data, elementname, i);
+				if(parseatt(p))
+					return;
+				if(*p->xml!='/')
+				{
+					const char * data;
+					i = 0; data = ++p->xml;
+					if (p->xml >= p->xmlend)
+						return;
+					while( IS_WHITE_SPACE(*p->xml) )
+					{
+						p->xml++;
+						if (p->xml >= p->xmlend)
+							return;
+					}
+					while(*p->xml!='<')
+					{
+						i++; p->xml++;
+						if (p->xml >= p->xmlend)
+							return;
+					}
+					if(i>0 && p->datafunc)
+						p->datafunc(p->data, data, i);
+				}
+			}
+			else if(*p->xml == '/')
+			{
+				i = 0; elementname = ++p->xml;
+				if (p->xml >= p->xmlend)
+					return;
+				while((*p->xml != '>'))
+				{
+					i++; p->xml++;
+					if (p->xml >= p->xmlend)
+						return;
+				}
+				if(p->endeltfunc)
+					p->endeltfunc(p->data, elementname, i);
+				p->xml++;
+			}
+		}
+		else
+		{
+			p->xml++;
+		}
+	}
+}
+
+/* the parser must be initialized before calling this function */
+void parsexml(struct xmlparser * parser)
+{
+	parser->xml = parser->xmlstart;
+	parser->xmlend = parser->xmlstart + parser->xmlsize;
+	parseelt(parser);
+}
+
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minixml.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minixml.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minixml.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minixml.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,37 @@
+/* $Id: minixml.h,v 1.6 2006/11/30 11:47:21 nanard Exp $ */
+/* minimal xml parser
+ *
+ * Project : miniupnp
+ * Website : http://miniupnp.free.fr/
+ * 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 __MINIXML_H__
+#define __MINIXML_H__
+#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
+
+/* if a callback function pointer is set to NULL,
+ * the function is not called */
+struct xmlparser {
+	const char *xmlstart;
+	const char *xmlend;
+	const char *xml;	/* pointer to current character */
+	int xmlsize;
+	void * data;
+	void (*starteltfunc) (void *, const char *, int);
+	void (*endeltfunc) (void *, const char *, int);
+	void (*datafunc) (void *, const char *, int);
+	void (*attfunc) (void *, const char *, int, const char *, int);
+};
+
+/* parsexml()
+ * the xmlparser structure must be initialized before the call
+ * the following structure members have to be initialized :
+ * xmlstart, xmlsize, data, *func
+ * xml is for internal usage, xmlend is computed automatically */
+void parsexml(struct xmlparser *);
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minixml.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/minixmlvalid.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/minixmlvalid.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/minixmlvalid.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,149 @@
+/* $Id: minixmlvalid.c,v 1.2 2006/11/30 11:31:55 nanard Exp $ */
+/* MiniUPnP Project
+ * http://miniupnp.tuxfamily.org/ or http://miniupnp.free.fr/
+ * minixmlvalid.c :
+ * validation program for the minixml parser
+ *
+ * (c) 2006 Thomas Bernard */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "minixml.h"
+
+/* xml event structure */
+struct event {
+	enum { ELTSTART, ELTEND, ATT, CHARDATA } type;
+	const char * data;
+	int len;
+};
+
+struct eventlist {
+	int n;
+	struct event * events;
+};
+
+/* compare 2 xml event lists
+ * return 0 if the two lists are equals */
+int evtlistcmp(struct eventlist * a, struct eventlist * b)
+{
+	int i;
+	struct event * ae, * be;
+	if(a->n != b->n)
+		return 1;
+	for(i=0; i<a->n; i++)
+	{
+		ae = a->events + i;
+		be = b->events + i;
+		if(  (ae->type != be->type)
+		   ||(ae->len != be->len)
+		   ||memcmp(ae->data, be->data, ae->len))
+		{
+			printf("Found a difference : %d '%.*s' != %d '%.*s'\n",
+			       ae->type, ae->len, ae->data,
+			       be->type, be->len, be->data);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/* Test data */
+static const char xmldata[] =
+"<xmlroot>\n"
+" <elt1 att1=\"attvalue1\" att2=\"attvalue2\">"
+"character data"
+"</elt1> \n \t"
+"<elt1b/>"
+"<elt2a> \t<elt2b>chardata1</elt2b><elt2b>chardata2</elt2b></elt2a>"
+"</xmlroot>";
+
+static const struct event evtref[] =
+{
+	{ELTSTART, "xmlroot", 7},
+	{ELTSTART, "elt1", 4},
+	/* attributes */
+	{CHARDATA, "character data", 14},
+	{ELTEND, "elt1", 4},
+	{ELTSTART, "elt1b", 5},
+	{ELTSTART, "elt2a", 5},
+	{ELTSTART, "elt2b", 5},
+	{CHARDATA, "chardata1", 9},
+	{ELTEND, "elt2b", 5},
+	{ELTSTART, "elt2b", 5},
+	{CHARDATA, "chardata2", 9},
+	{ELTEND, "elt2b", 5},
+	{ELTEND, "elt2a", 5},
+	{ELTEND, "xmlroot", 7}
+};	
+
+void startelt(void * data, const char * p, int l)
+{
+	struct eventlist * evtlist = data;
+	struct event * evt;
+	evt = evtlist->events + evtlist->n;
+	/*printf("startelt : %.*s\n", l, p);*/
+	evt->type = ELTSTART;
+	evt->data = p;
+	evt->len = l;
+	evtlist->n++;
+}
+
+void endelt(void * data, const char * p, int l)
+{
+	struct eventlist * evtlist = data;
+	struct event * evt;
+	evt = evtlist->events + evtlist->n;
+	/*printf("endelt : %.*s\n", l, p);*/
+	evt->type = ELTEND;
+	evt->data = p;
+	evt->len = l;
+	evtlist->n++;
+}
+
+void chardata(void * data, const char * p, int l)
+{
+	struct eventlist * evtlist = data;
+	struct event * evt;
+	evt = evtlist->events + evtlist->n;
+	/*printf("chardata : '%.*s'\n", l, p);*/
+	evt->type = CHARDATA;
+	evt->data = p;
+	evt->len = l;
+	evtlist->n++;
+}
+
+int testxmlparser(const char * xml, int size)
+{
+	int r;
+	struct eventlist evtlist;
+	struct eventlist evtlistref;
+	struct xmlparser parser;
+	evtlist.n = 0;
+	evtlist.events = malloc(sizeof(struct event)*100);
+	memset(&parser, 0, sizeof(parser));
+	parser.xmlstart = xml;
+	parser.xmlsize = size;
+	parser.data = &evtlist;
+	parser.starteltfunc = startelt;
+	parser.endeltfunc = endelt;
+	parser.datafunc = chardata;
+	parsexml(&parser);
+	printf("%d events\n", evtlist.n);
+	/* compare */
+	evtlistref.n = sizeof(evtref)/sizeof(struct event);
+	evtlistref.events = (struct event *)evtref;
+	r = evtlistcmp(&evtlistref, &evtlist);
+	free(evtlist.events);
+	return r;
+}
+
+int main(int argc, char * * argv)
+{
+	int r;
+	r = testxmlparser(xmldata, sizeof(xmldata)-1);
+	if(r)
+		printf("minixml validation test failed\n");
+	return r;
+}
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/minixmlvalid.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/upnpcommands.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/upnpcommands.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/upnpcommands.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,569 @@
+/* $Id: upnpcommands.c,v 1.19 2008/02/18 13:27:23 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.
+ * */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "upnpcommands.h"
+#include "miniupnpc.h"
+
+static unsigned int
+my_atoui(const char * s)
+{
+	return s ? ((unsigned int)strtoul(s, NULL, 0)) : 0;
+}
+
+/*
+ * */
+unsigned int
+UPNP_GetTotalBytesSent(const char * controlURL,
+					const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesSent", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalBytesSent");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/*
+ * */
+unsigned int
+UPNP_GetTotalBytesReceived(const char * controlURL,
+						const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalBytesReceived", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalBytesReceived");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/*
+ * */
+unsigned int
+UPNP_GetTotalPacketsSent(const char * controlURL,
+						const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsSent", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalPacketsSent");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/*
+ * */
+unsigned int
+UPNP_GetTotalPacketsReceived(const char * controlURL,
+						const char * servicetype)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	unsigned int r = 0;
+	char * p;
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetTotalPacketsReceived", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	p = GetValueFromNameValueList(&pdata, "NewTotalPacketsReceived");
+	r = my_atoui(p);
+	ClearNameValueList(&pdata);
+	return r;
+}
+
+/* UPNP_GetStatusInfo() call the corresponding UPNP method
+ * returns the current status and uptime */
+int UPNP_GetStatusInfo(const char * controlURL,
+					const char * servicetype,
+					char * status, 
+					unsigned int * uptime,
+					char * lastconnerror)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	char * up;
+	char * err;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!status && !uptime)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetStatusInfo", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	up = GetValueFromNameValueList(&pdata, "NewUptime");
+	p = GetValueFromNameValueList(&pdata, "NewConnectionStatus");
+	err = GetValueFromNameValueList(&pdata, "NewLastConnectionError");
+	if(p && up)
+	  ret = UPNPCOMMAND_SUCCESS;
+
+	if(status) {
+		if(p){
+			strncpy(status, p, 64 );
+			status[63] = '\0';
+		}else
+			status[0]= '\0';
+	}
+
+	if(uptime) {
+		if(up)
+			sscanf(up,"%u",uptime);
+		else
+			uptime = 0;
+	}
+
+	if(lastconnerror) {
+		if(err) {
+			strncpy(lastconnerror, err, 64 );
+			lastconnerror[63] = '\0';
+		} else
+			lastconnerror[0] = '\0';
+	}
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+/* UPNP_GetConnectionTypeInfo() call the corresponding UPNP method
+ * returns the connection type */
+int UPNP_GetConnectionTypeInfo(const char * controlURL,
+                               const char * servicetype,
+                               char * connectionType)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!connectionType)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetConnectionTypeInfo", 0, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	p = GetValueFromNameValueList(&pdata, "NewConnectionType");
+	/*p = GetValueFromNameValueList(&pdata, "NewPossibleConnectionTypes");*/
+	/* PossibleConnectionTypes will have several values.... */
+	if(p) {
+		strncpy(connectionType, p, 64 );
+		connectionType[63] = '\0';
+		ret = UPNPCOMMAND_SUCCESS;
+	} else
+		connectionType[0] = '\0';
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+/* UPNP_GetLinkLayerMaxBitRate() call the corresponding UPNP method.
+ * Returns 2 values: Downloadlink bandwidth and Uplink bandwidth.
+ * One of the values can be null 
+ * Note : GetLinkLayerMaxBitRates belongs to WANPPPConnection:1 only 
+ * We can use the GetCommonLinkProperties from WANCommonInterfaceConfig:1 */
+int UPNP_GetLinkLayerMaxBitRates(const char * controlURL, const char * servicetype, unsigned int * bitrateDown, unsigned int* bitrateUp)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+	char * down;
+	char * up;
+	char * p;
+
+	if(!bitrateDown && !bitrateUp)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	/* shouldn't we use GetCommonLinkProperties ? */
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetCommonLinkProperties", 0, buffer, &bufsize);
+	                  /*"GetLinkLayerMaxBitRates", 0, buffer, &bufsize);*/
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*down = GetValueFromNameValueList(&pdata, "NewDownstreamMaxBitRate");*/
+	/*up = GetValueFromNameValueList(&pdata, "NewUpstreamMaxBitRate");*/
+	down = GetValueFromNameValueList(&pdata, "NewLayer1DownstreamMaxBitRate");
+	up = GetValueFromNameValueList(&pdata, "NewLayer1UpstreamMaxBitRate");
+	/*GetValueFromNameValueList(&pdata, "NewWANAccessType");*/
+	/*GetValueFromNameValueList(&pdata, "NewPhysicalLinkSatus");*/
+	if(down && up)
+		ret = UPNPCOMMAND_SUCCESS;
+
+	if(bitrateDown)
+	{
+		if(down)
+			sscanf(down,"%u",bitrateDown);
+		else
+			*bitrateDown = 0;
+	}
+
+	if(bitrateUp)
+	{
+		if(up)
+			sscanf(up,"%u",bitrateUp);
+		else
+			*bitrateUp = 0;
+	}
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+
+/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
+ * if the third arg is not null the value is copied to it.
+ * at least 16 bytes must be available
+ * 
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR Either an UPnP error code or an unknown error.
+ *
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 501 Action Failed - See UPnP Device Architecture section on Control.
+ */
+int UPNP_GetExternalIPAddress(const char * controlURL,
+                              const char * servicetype,
+							  char * extIpAdd)
+{
+	struct NameValueParserData pdata;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!extIpAdd || !controlURL || !servicetype)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	simpleUPnPcommand(-1, controlURL, servicetype, "GetExternalIPAddress", 0, buffer, &bufsize);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	/*printf("external ip = %s\n", GetValueFromNameValueList(&pdata, "NewExternalIPAddress") );*/
+	p = GetValueFromNameValueList(&pdata, "NewExternalIPAddress");
+	if(p) {
+		strncpy(extIpAdd, p, 16 );
+		extIpAdd[15] = '\0';
+		ret = UPNPCOMMAND_SUCCESS;
+	} else
+		extIpAdd[0] = '\0';
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+
+	ClearNameValueList(&pdata);
+	return ret;
+}
+
+int
+UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
+                    const char * extPort,
+					const char * inPort,
+					const char * inClient,
+					const char * desc,
+					const char * proto)
+{
+	struct UPNParg * AddPortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	struct NameValueParserData pdata;
+	const char * resVal;
+	int ret;
+
+	if(!inPort || !inClient || !proto || !extPort)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	AddPortMappingArgs = calloc(9, sizeof(struct UPNParg));
+	AddPortMappingArgs[0].elt = "NewRemoteHost";
+	AddPortMappingArgs[1].elt = "NewExternalPort";
+	AddPortMappingArgs[1].val = extPort;
+	AddPortMappingArgs[2].elt = "NewProtocol";
+	AddPortMappingArgs[2].val = proto;
+	AddPortMappingArgs[3].elt = "NewInternalPort";
+	AddPortMappingArgs[3].val = inPort;
+	AddPortMappingArgs[4].elt = "NewInternalClient";
+	AddPortMappingArgs[4].val = inClient;
+	AddPortMappingArgs[5].elt = "NewEnabled";
+	AddPortMappingArgs[5].val = "1";
+	AddPortMappingArgs[6].elt = "NewPortMappingDescription";
+	AddPortMappingArgs[6].val = desc?desc:"libminiupnpc";
+	AddPortMappingArgs[7].elt = "NewLeaseDuration";
+	AddPortMappingArgs[7].val = "0";
+	simpleUPnPcommand(-1, controlURL, servicetype, "AddPortMapping", AddPortMappingArgs, buffer, &bufsize);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	/*buffer[bufsize] = '\0';*/
+	/*puts(buffer);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	resVal = GetValueFromNameValueList(&pdata, "errorCode");
+	if(resVal) {
+		/*printf("AddPortMapping errorCode = '%s'\n", resVal); */
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(resVal, "%d", &ret);
+	} else {
+		ret = UPNPCOMMAND_SUCCESS;
+	}
+	ClearNameValueList(&pdata);
+	free(AddPortMappingArgs);
+	return ret;
+}
+
+int
+UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
+                       const char * extPort, const char * proto)
+{
+	/*struct NameValueParserData pdata;*/
+	struct UPNParg * DeletePortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	struct NameValueParserData pdata;
+	const char * resVal;
+	int ret;
+
+	if(!extPort || !proto)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	DeletePortMappingArgs = calloc(4, sizeof(struct UPNParg));
+	DeletePortMappingArgs[0].elt = "NewRemoteHost";
+	DeletePortMappingArgs[1].elt = "NewExternalPort";
+	DeletePortMappingArgs[1].val = extPort;
+	DeletePortMappingArgs[2].elt = "NewProtocol";
+	DeletePortMappingArgs[2].val = proto;
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "DeletePortMapping",
+					  DeletePortMappingArgs, buffer, &bufsize);
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+	resVal = GetValueFromNameValueList(&pdata, "errorCode");
+	if(resVal) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(resVal, "%d", &ret);
+	} else {
+		ret = UPNPCOMMAND_SUCCESS;
+	}
+	ClearNameValueList(&pdata);
+	free(DeletePortMappingArgs);
+	return ret;
+}
+
+int UPNP_GetGenericPortMappingEntry(const char * controlURL,
+                                     const char * servicetype,
+									 const char * index,
+									 char * extPort,
+									 char * intClient,
+									 char * intPort,
+									 char * protocol,
+									 char * desc,
+									 char * enabled,
+									 char * rHost,
+									 char * duration)
+{
+	struct NameValueParserData pdata;
+	struct UPNParg * GetPortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int r = UPNPCOMMAND_UNKNOWN_ERROR;
+	if(!index)
+		return UPNPCOMMAND_INVALID_ARGS;
+	intClient[0] = '\0';
+	intPort[0] = '\0';
+	GetPortMappingArgs = calloc(2, sizeof(struct UPNParg));
+	GetPortMappingArgs[0].elt = "NewPortMappingIndex";
+	GetPortMappingArgs[0].val = index;
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetGenericPortMappingEntry",
+					  GetPortMappingArgs, buffer, &bufsize);
+	ParseNameValue(buffer, bufsize, &pdata);
+	p = GetValueFromNameValueList(&pdata, "NewRemoteHost");
+	if(p && rHost)
+	{
+		strncpy(rHost, p, 64);
+		rHost[63] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewExternalPort");
+	if(p && extPort)
+	{
+		strncpy(extPort, p, 6);
+		extPort[5] = '\0';
+		r = UPNPCOMMAND_SUCCESS;
+	}
+	p = GetValueFromNameValueList(&pdata, "NewProtocol");
+	if(p && protocol)
+	{
+		strncpy(protocol, p, 4);
+		protocol[3] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewInternalClient");
+	if(p && intClient)
+	{
+		strncpy(intClient, p, 16);
+		intClient[15] = '\0';
+		r = 0;
+	}
+	p = GetValueFromNameValueList(&pdata, "NewInternalPort");
+	if(p && intPort)
+	{
+		strncpy(intPort, p, 6);
+		intPort[5] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewEnabled");
+	if(p && enabled)
+	{
+		strncpy(enabled, p, 4);
+		enabled[3] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewPortMappingDescription");
+	if(p && desc)
+	{
+		strncpy(desc, p, 80);
+		desc[79] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "NewLeaseDuration");
+	if(p && duration)
+	{
+		strncpy(duration, p, 16);
+		duration[15] = '\0';
+	}
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		r = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &r);
+	}
+	ClearNameValueList(&pdata);
+	free(GetPortMappingArgs);
+	return r;
+}
+
+int UPNP_GetPortMappingNumberOfEntries(const char * controlURL, const char * servicetype, unsigned int * numEntries)
+{
+ 	struct NameValueParserData pdata;
+ 	char buffer[4096];
+ 	int bufsize = 4096;
+ 	char* p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+ 	simpleUPnPcommand(-1, controlURL, servicetype, "GetPortMappingNumberOfEntries", 0, buffer, &bufsize);
+#ifndef NDEBUG
+	DisplayNameValueList(buffer, bufsize);
+#endif
+ 	ParseNameValue(buffer, bufsize, &pdata);
+
+ 	p = GetValueFromNameValueList(&pdata, "NewPortMappingNumberOfEntries");
+ 	if(numEntries && p) {
+		*numEntries = 0;
+ 		sscanf(p, "%u", numEntries);
+		ret = UPNPCOMMAND_SUCCESS;
+ 	}
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+
+ 	ClearNameValueList(&pdata);
+	return ret;
+}
+
+/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
+ * the result is returned in the intClient and intPort strings
+ * please provide 16 and 6 bytes of data */
+int
+UPNP_GetSpecificPortMappingEntry(const char * controlURL,
+                                 const char * servicetype,
+                                 const char * extPort,
+							     const char * proto,
+                                 char * intClient,
+                                 char * intPort)
+{
+	struct NameValueParserData pdata;
+	struct UPNParg * GetPortMappingArgs;
+	char buffer[4096];
+	int bufsize = 4096;
+	char * p;
+	int ret = UPNPCOMMAND_UNKNOWN_ERROR;
+
+	if(!intPort || !intClient || !extPort || !proto)
+		return UPNPCOMMAND_INVALID_ARGS;
+
+	GetPortMappingArgs = calloc(4, sizeof(struct UPNParg));
+	GetPortMappingArgs[0].elt = "NewRemoteHost";
+	GetPortMappingArgs[1].elt = "NewExternalPort";
+	GetPortMappingArgs[1].val = extPort;
+	GetPortMappingArgs[2].elt = "NewProtocol";
+	GetPortMappingArgs[2].val = proto;
+	simpleUPnPcommand(-1, controlURL, servicetype,
+	                  "GetSpecificPortMappingEntry",
+					  GetPortMappingArgs, buffer, &bufsize);
+	/*fd = simpleUPnPcommand(fd, controlURL, data.servicetype, "GetSpecificPortMappingEntry", AddPortMappingArgs, buffer, &bufsize); */
+	/*DisplayNameValueList(buffer, bufsize);*/
+	ParseNameValue(buffer, bufsize, &pdata);
+
+	p = GetValueFromNameValueList(&pdata, "NewInternalClient");
+	if(p) {
+		strncpy(intClient, p, 16);
+		intClient[15] = '\0';
+		ret = UPNPCOMMAND_SUCCESS;
+	} else
+		intClient[0] = '\0';
+
+	p = GetValueFromNameValueList(&pdata, "NewInternalPort");
+	if(p) {
+		strncpy(intPort, p, 6);
+		intPort[5] = '\0';
+	} else
+		intPort[0] = '\0';
+
+	p = GetValueFromNameValueList(&pdata, "errorCode");
+	if(p) {
+		ret = UPNPCOMMAND_UNKNOWN_ERROR;
+		sscanf(p, "%d", &ret);
+	}
+
+	ClearNameValueList(&pdata);
+	free(GetPortMappingArgs);
+	return ret;
+}
+
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/upnpcommands.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/upnpcommands.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/upnpcommands.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/upnpcommands.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,179 @@
+/* $Id: upnpcommands.h,v 1.13 2008/02/18 13:27:24 nanard Exp $ */
+/* Miniupnp project : http://miniupnp.free.fr/
+ * Author : Thomas Bernard
+ * Copyright (c) 2005-2006 Thomas Bernard
+ * This software is subject to the conditions detailed in the
+ * LICENCE file provided within this distribution */
+#ifndef __UPNPCOMMANDS_H__
+#define __UPNPCOMMANDS_H__
+
+#include "upnpreplyparse.h"
+#include "declspec.h"
+
+/* MiniUPnPc return codes : */
+#define UPNPCOMMAND_SUCCESS (0)
+#define UPNPCOMMAND_UNKNOWN_ERROR (-1)
+#define UPNPCOMMAND_INVALID_ARGS (-2)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBSPEC unsigned int
+UPNP_GetTotalBytesSent(const char * controlURL,
+					const char * servicetype);
+
+LIBSPEC unsigned int
+UPNP_GetTotalBytesReceived(const char * controlURL,
+						const char * servicetype);
+
+LIBSPEC unsigned int
+UPNP_GetTotalPacketsSent(const char * controlURL,
+					const char * servicetype);
+
+LIBSPEC unsigned int
+UPNP_GetTotalPacketsReceived(const char * controlURL,
+					const char * servicetype);
+
+/* UPNP_GetStatusInfo()
+ * status and lastconnerror are 64 byte buffers
+ * Return values :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error code */
+LIBSPEC int
+UPNP_GetStatusInfo(const char * controlURL,
+			       const char * servicetype,
+				   char * status,
+				   unsigned int * uptime,
+                   char * lastconnerror);
+
+/* UPNP_GetConnectionTypeInfo()
+ * argument connectionType is a 64 character buffer
+ * Return Values :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error code */
+LIBSPEC int
+UPNP_GetConnectionTypeInfo(const char * controlURL,
+                           const char * servicetype,
+						   char * connectionType);
+
+/* UPNP_GetExternalIPAddress() call the corresponding UPNP method.
+ * if the third arg is not null the value is copied to it.
+ * at least 16 bytes must be available 
+ *
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR Either an UPnP error code or an unknown error.
+ * 
+ * possible UPnP Errors :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 501 Action Failed - See UPnP Device Architecture section on Control. */
+LIBSPEC int
+UPNP_GetExternalIPAddress(const char * controlURL,
+                          const char * servicetype,
+                          char * extIpAdd);
+
+/* UPNP_GetLinkLayerMaxBitRates()
+ * call WANCommonInterfaceConfig:1#GetCommonLinkProperties
+ *
+ * return values :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error Code. */
+LIBSPEC int
+UPNP_GetLinkLayerMaxBitRates(const char* controlURL,
+							const char* servicetype,
+							unsigned int * bitrateDown,
+							unsigned int * bitrateUp);
+
+/* UPNP_AddPortMapping()
+ *
+ * Return values :
+ * 0 : SUCCESS
+ * NON ZERO : ERROR. Either an UPnP error code or an unknown error.
+ * 
+ * List of possible UPnP errors for AddPortMapping :
+ * 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.
+ * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be
+ *                                   wild-carded
+ * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded
+ * 718 ConflictInMappingEntry - The port mapping entry specified conflicts
+ *                     with a mapping assigned previously to another client
+ * 724 SamePortValuesRequired - Internal and External port values
+ *                              must be the same 
+ * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports
+ *                  permanent lease times on port mappings
+ * 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 */
+LIBSPEC int
+UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
+                    const char * extPort,
+				    const char * inPort,
+					const char * inClient,
+					const char * desc,
+                    const char * proto);
+
+/* UPNP_DeletePortMapping()
+ * Return Values :
+ * 0 : SUCCESS
+ * NON ZERO : error. Either an UPnP error code or an undefined error.
+ *
+ * List of possible UPnP errors for DeletePortMapping :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 714 NoSuchEntryInArray - The specified value does not exist in the array */
+LIBSPEC int
+UPNP_DeletePortMapping(const char * controlURL, const char * servicetype,
+                       const char * extPort, const char * proto);
+
+/* UPNP_GetPortMappingNumberOfEntries()
+ * not supported by all routers */
+LIBSPEC int
+UPNP_GetPortMappingNumberOfEntries(const char* controlURL, const char* servicetype, unsigned int * num);
+
+/* UPNP_GetSpecificPortMappingEntry retrieves an existing port mapping
+ * the result is returned in the intClient and intPort strings
+ * please provide 16 and 6 bytes of data
+ *
+ * return value :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error Code. */
+LIBSPEC int
+UPNP_GetSpecificPortMappingEntry(const char * controlURL,
+                                 const char * servicetype,
+                                 const char * extPort,
+                                 const char * proto,
+                                 char * intClient,
+                                 char * intPort);
+
+/* UPNP_GetGenericPortMappingEntry()
+ *
+ * return value :
+ * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR
+ * or a UPnP Error Code.
+ *
+ * Possible UPNP Error codes :
+ * 402 Invalid Args - See UPnP Device Architecture section on Control.
+ * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
+ */
+LIBSPEC int
+UPNP_GetGenericPortMappingEntry(const char * controlURL,
+                                const char * servicetype,
+								const char * index,
+								char * extPort,
+								char * intClient,
+								char * intPort,
+								char * protocol,
+								char * desc,
+								char * enabled,
+								char * rHost,
+								char * duration);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+


Property changes on: vidalia/branches/upnp/src/miniupnpc/upnpcommands.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/upnperrors.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/upnperrors.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/upnperrors.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,55 @@
+/* $Id: upnperrors.c,v 1.2 2008/02/05 12:50:22 nanard Exp $ */
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * copyright (c) 2007 Thomas Bernard
+ * All Right reserved.
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <string.h>
+#include "upnperrors.h"
+
+const char * strupnperror(int err)
+{
+	const char * s = NULL;
+	switch(err) {
+	case 401:
+		s = "Invalid Action";
+		break;
+	case 402:
+		s = "Invalid Args";
+		break;
+	case 501:
+		s = "Action Failed";
+		break;
+	case 713:
+		s = "SpecifiedArrayIndexInvalid";
+		break;
+	case 714:
+		s = "NoSuchEntryInArray";
+		break;
+	case 715:
+		s = "WildCardNotPermittedInSrcIP";
+		break;
+	case 716:
+		s = "WildCardNotPermittedInExtPort";
+		break;
+	case 718:
+		s = "ConflictInMappingEntry";
+		break;
+	case 724:
+		s = "SamePortValuesRequired";
+		break;
+	case 725:
+		s = "OnlyPermanentLeasesSupported";
+		break;
+	case 726:
+		s = "RemoteHostOnlySupportsWildcard";
+		break;
+	case 727:
+		s = "ExternalPortOnlySupportsWildcard";
+		break;
+	default:
+		s = NULL;
+	}
+	return s;
+}


Property changes on: vidalia/branches/upnp/src/miniupnpc/upnperrors.c
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/upnperrors.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/upnperrors.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/upnperrors.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,16 @@
+/* $Id: upnperrors.h,v 1.1 2007/12/22 11:28:04 nanard Exp $ */
+/* (c) 2007 Thomas Bernard
+ * All rights reserved.
+ * MiniUPnP Project.
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#ifndef __UPNPERRORS_H__
+#define __UPNPERRORS_H__
+
+/* strupnperror()
+ * Return a string description of the UPnP error code 
+ * or NULL for undefinded errors */
+const char * strupnperror(int err);
+
+#endif


Property changes on: vidalia/branches/upnp/src/miniupnpc/upnperrors.h
___________________________________________________________________
Name: svn:eol-style
   + native

Added: vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.c
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.c	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.c	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,127 @@
+/* $Id: upnpreplyparse.c,v 1.10 2008/02/21 13:05:27 nanard Exp $ */
+/* MiniUPnP project
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * (c) 2006 Thomas Bernard 
+ * This software is subject to the conditions detailed
+ * in the LICENCE file provided within the distribution */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "upnpreplyparse.h"
+#include "minixml.h"
+
+static void
+NameValueParserStartElt(void * d, const char * name, int l)
+{
+    struct NameValueParserData * data = (struct NameValueParserData *)d;
+    if(l>63)
+        l = 63;
+    memcpy(data->curelt, name, l);
+    data->curelt[l] = '\0';
+}
+
+static void
+NameValueParserGetData(void * d, const char * datas, int l)
+{
+    struct NameValueParserData * data = (struct NameValueParserData *)d;
+    struct NameValue * nv;
+    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);
+}
+
+void
+ParseNameValue(const char * buffer, int bufsize,
+                    struct NameValueParserData * data)
+{
+    struct xmlparser parser;
+    LIST_INIT(&(data->head));
+    /* init xmlparser object */
+    parser.xmlstart = buffer;
+    parser.xmlsize = bufsize;
+    parser.data = data;
+    parser.starteltfunc = NameValueParserStartElt;
+    parser.endeltfunc = 0;
+    parser.datafunc = NameValueParserGetData;
+	parser.attfunc = 0;
+    parsexml(&parser);
+}
+
+void
+ClearNameValueList(struct NameValueParserData * pdata)
+{
+    struct NameValue * nv;
+    while((nv = pdata->head.lh_first) != NULL)
+    {
+        LIST_REMOVE(nv, entries);
+        free(nv);
+    }
+}
+
+char * 
+GetValueFromNameValueList(struct NameValueParserData * pdata,
+                          const char * Name)
+{
+    struct NameValue * nv;
+    char * p = NULL;
+    for(nv = pdata->head.lh_first;
+        (nv != NULL) && (p == NULL);
+        nv = nv->entries.le_next)
+    {
+        if(strcmp(nv->name, Name) == 0)
+            p = nv->value;
+    }
+    return p;
+}
+
+#if 0
+/* useless now that minixml ignores namespaces by itself */
+char *
+GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
+                                  const char * Name)
+{
+	struct NameValue * nv;
+	char * p = NULL;
+	char * pname;
+	for(nv = pdata->head.lh_first;
+	    (nv != NULL) && (p == NULL);
+		nv = nv->entries.le_next)
+	{
+		pname = strrchr(nv->name, ':');
+		if(pname)
+			pname++;
+		else
+			pname = nv->name;
+		if(strcmp(pname, Name)==0)
+			p = nv->value;
+	}
+	return p;
+}
+#endif
+
+/* debug all-in-one function 
+ * do parsing then display to stdout */
+#ifdef DEBUG
+void
+DisplayNameValueList(char * buffer, int bufsize)
+{
+    struct NameValueParserData pdata;
+    struct NameValue * nv;
+    ParseNameValue(buffer, bufsize, &pdata);
+    for(nv = pdata.head.lh_first;
+        nv != NULL;
+        nv = nv->entries.le_next)
+    {
+        printf("%s = %s\n", nv->name, nv->value);
+    }
+    ClearNameValueList(&pdata);
+}
+#endif
+

Added: vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.h
===================================================================
--- vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.h	                        (rev 0)
+++ vidalia/branches/upnp/src/miniupnpc/upnpreplyparse.h	2008-05-09 00:01:35 UTC (rev 2562)
@@ -0,0 +1,62 @@
+/* $Id: upnpreplyparse.h,v 1.8 2008/02/21 13:05:27 nanard Exp $ */
+/* MiniUPnP project
+ * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+ * (c) 2006 Thomas Bernard 
+ * This software is subject to the conditions detailed
+ * in the LICENCE file provided within the distribution */
+
+#ifndef __UPNPREPLYPARSE_H__
+#define __UPNPREPLYPARSE_H__
+
+#if defined(NO_SYS_QUEUE_H) || defined(WIN32)
+#include "bsdqueue.h"
+#else
+#include <sys/queue.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct NameValue {
+    LIST_ENTRY(NameValue) entries;
+    char name[64];
+    char value[64];
+};
+
+struct NameValueParserData {
+    LIST_HEAD(listhead, NameValue) head;
+    char curelt[64];
+};
+
+/* ParseNameValue() */
+void
+ParseNameValue(const char * buffer, int bufsize,
+               struct NameValueParserData * data);
+
+/* ClearNameValueList() */
+void
+ClearNameValueList(struct NameValueParserData * pdata);
+
+/* GetValueFromNameValueList() */
+char *
+GetValueFromNameValueList(struct NameValueParserData * pdata,
+                          const char * Name);
+
+/* GetValueFromNameValueListIgnoreNS() */
+char *
+GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
+                                  const char * Name);
+
+/* DisplayNameValueList() */
+#ifdef DEBUG
+void
+DisplayNameValueList(char * buffer, int bufsize);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+