Compare commits
39 Commits
release-1.
...
branch-1.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc335f5df7 | ||
|
|
cf31814e55 | ||
|
|
3b0fd070fd | ||
|
|
9f69fb1b80 | ||
|
|
c124ae6507 | ||
|
|
51a01cdba1 | ||
|
|
6905714a7e | ||
|
|
72460df747 | ||
|
|
a596abfbe3 | ||
|
|
fbbb24f406 | ||
|
|
0508fb0d6e | ||
|
|
848d66e69d | ||
|
|
04fb684323 | ||
|
|
faaef39a3c | ||
|
|
a1193f385e | ||
|
|
c20f2bd3a1 | ||
|
|
3fc0f9ad1d | ||
|
|
2211cc14e6 | ||
|
|
bf60dc06e0 | ||
|
|
908785fba7 | ||
|
|
1a28e8ff51 | ||
|
|
89ad5e6779 | ||
|
|
062ac0c926 | ||
|
|
06aa3b17c4 | ||
|
|
9f444a680e | ||
|
|
8e3a71905b | ||
|
|
72c29ef1f6 | ||
|
|
f6a3102b48 | ||
|
|
9a9c4e829e | ||
|
|
7a571f513e | ||
|
|
f10730f616 | ||
|
|
c70f5ce323 | ||
|
|
a3c540bc9b | ||
|
|
7b1aa4c9e3 | ||
|
|
907c7c2621 | ||
|
|
25c27b8af7 | ||
|
|
dcbbc30f5c | ||
|
|
3509991872 | ||
|
|
6279b7fa5f |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -73,6 +73,14 @@ GRTAGS
|
|||||||
GSYMS
|
GSYMS
|
||||||
GTAGS
|
GTAGS
|
||||||
|
|
||||||
|
# QT-Creator files
|
||||||
|
Makefile.am.user
|
||||||
|
pupnp.config
|
||||||
|
pupnp.creator
|
||||||
|
pupnp.creator.user
|
||||||
|
pupnp.files
|
||||||
|
pupnp.includes
|
||||||
|
|
||||||
*.orig
|
*.orig
|
||||||
*~
|
*~
|
||||||
\#*#
|
\#*#
|
||||||
|
|||||||
278
ChangeLog
278
ChangeLog
@@ -1,3 +1,281 @@
|
|||||||
|
*******************************************************************************
|
||||||
|
Version 1.6.20
|
||||||
|
*******************************************************************************
|
||||||
|
|
||||||
|
2015-02-04 Shaun Marko <semarko@users.sf.net>
|
||||||
|
|
||||||
|
Bug tracker #124 Build fails with --enable-debug
|
||||||
|
|
||||||
|
Build environment
|
||||||
|
Fedora 21
|
||||||
|
X86-64
|
||||||
|
* gcc 4.9.2
|
||||||
|
|
||||||
|
How to repeat
|
||||||
|
$ ./configure --enable debug
|
||||||
|
$ make
|
||||||
|
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../upnp/inc -I./inc -I../threadutil/inc
|
||||||
|
-I../ixml/inc -I./src/inc -pthread -g -O2 -Wall -MT src/api/libupnp_la-UpnpString.lo
|
||||||
|
-MD -MP -MF src/api/.deps/libupnp_la-UpnpString.Tpo -c src/api/UpnpString.c
|
||||||
|
-fPIC -DPIC -o src/api .libs/libupnp_la-UpnpString.o src/api/UpnpString.c:47:16:
|
||||||
|
error: expected identifier or '(' before 'extension'
|
||||||
|
extern char *strndup(const char *string, size_t __n);
|
||||||
|
^
|
||||||
|
Makefile:1016: recipe for target 'src/api/libupnp_la-UpnpString.lo' failed
|
||||||
|
|
||||||
|
Reason for failure
|
||||||
|
Build enables -O2 optimization flags which causes the inclusion of a
|
||||||
|
macro implementation of strndup from include/bits/string2.h.
|
||||||
|
|
||||||
|
Workarounds
|
||||||
|
Disable optimization when configuring or making:
|
||||||
|
$ configure CFLAGS='-g -pthread -O0' --enable-debug
|
||||||
|
$ make
|
||||||
|
or
|
||||||
|
$ configure --enable-debug
|
||||||
|
$ make CFLAGS='-g -pthread -O0' Define NO_STRING_INLINES
|
||||||
|
$ export CFLAGS="-DNO_STRING_INLINES -O2"
|
||||||
|
$ ./configure --enagble-debug
|
||||||
|
$ make
|
||||||
|
|
||||||
|
Fix
|
||||||
|
* Don't declare strndup in src/api/UpnpString.c if it exists
|
||||||
|
|
||||||
|
2015-02-01 Jean-Francois Dockes <medoc@users.sf.net>
|
||||||
|
|
||||||
|
Out-of-tree builds seem to be currently broken, because ixml and
|
||||||
|
threadutil files need an include path to include UpnpGlobal.h, and
|
||||||
|
configure tries to copy files into a directory which it does not create.
|
||||||
|
The patch fixes both issues.
|
||||||
|
|
||||||
|
2014-01-03 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
rewrite soap_device.c
|
||||||
|
|
||||||
|
1) separate HTTP handling from SOAP handling
|
||||||
|
2) remove repeated validity check, each check is performed exactly once
|
||||||
|
3) fix HTTP status code per UPnP spec, SOAP spec and RFC 2774
|
||||||
|
|
||||||
|
*******************************************************************************
|
||||||
|
Version 1.6.19
|
||||||
|
*******************************************************************************
|
||||||
|
|
||||||
|
2013-11-14 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
|
||||||
|
SF Bug Tracker #119, Creator: Klaus Fischer
|
||||||
|
Access violation due to changed usage of pthreads-win32
|
||||||
|
|
||||||
|
Dear libupnp developers,
|
||||||
|
|
||||||
|
I have experienced a crash (access violation) when using libupnp on
|
||||||
|
Windows. The crash is actually located in pthreads-win32 and happens
|
||||||
|
when repeatedly de-/initializing libupnp on Win32 in the same process
|
||||||
|
and both libupnp and pthreads-win32 are compiled as static libraries.
|
||||||
|
|
||||||
|
So I'm doing this:
|
||||||
|
- UpnpInit()
|
||||||
|
- UpnpFinish()
|
||||||
|
- UpnpInit() <- Crash
|
||||||
|
|
||||||
|
I am already in touch with Ross Johnson on the pthreads-win32 mailing
|
||||||
|
list regarding this issue:
|
||||||
|
|
||||||
|
http://sourceware.org/ml/pthreads-win32/2013/msg00020.html
|
||||||
|
|
||||||
|
He told me the problem is that the functions
|
||||||
|
pthread_win32_process_attach/detach_np() should no longer be called
|
||||||
|
directly, but are invoked automatically now since version 2.9.0 of
|
||||||
|
pthreads-win32, which has been released approx. 1.5 years ago. Please
|
||||||
|
refer to above link for in-depth information.
|
||||||
|
|
||||||
|
So for proper using of latest pthreads-win32 library, those function
|
||||||
|
calls should vanish inside libupnp. Could you consider adapting libupnp
|
||||||
|
in that way? I would really like to use both libraries out-of-the-box
|
||||||
|
without local modifications, and this issue prevents that.
|
||||||
|
|
||||||
|
Best regards,
|
||||||
|
Klaus
|
||||||
|
|
||||||
|
2013-11-08 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Fix several minor bugs in soap_device.c
|
||||||
|
|
||||||
|
1) remove redundant free
|
||||||
|
2) avoid user-provided ErrStr being overwritten by the default one
|
||||||
|
3) eliminated memory leak possiblity in handle_query_variable
|
||||||
|
|
||||||
|
2013-11-08 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Fix return value check of parse_uri.
|
||||||
|
|
||||||
|
2012-06-19 Yoichi NAKAYAMA <yoichi.nakayama(at)gmail.com>
|
||||||
|
|
||||||
|
SF Bug Tracker #118, Creator: T.Iwamoto
|
||||||
|
tv_ctrlpt crashes after detecting a later version of tvcontrol service
|
||||||
|
|
||||||
|
From: gon3456@users.sf.net
|
||||||
|
Steps to reproduce:
|
||||||
|
1. Extracts and build libupnp-1.6.18
|
||||||
|
$ tar -xjf /path/to/archive/libupnp-1.6.18.tar.bz2
|
||||||
|
$ cd libupnp-1.6.18
|
||||||
|
$ ./configure
|
||||||
|
$ make
|
||||||
|
2. Applies the attached patch and remake.
|
||||||
|
$ patch -p1 < /path/to/patch/libupnp-1.6.18.patch
|
||||||
|
$ make
|
||||||
|
3. Run tv_device.
|
||||||
|
$ cd upnp/sample
|
||||||
|
$ ./tv_device
|
||||||
|
4. Run tv_ctrlpt; the tv_ctrlpt crashes soon.
|
||||||
|
$ ./tv_ctrlpt
|
||||||
|
Segmentation fault (core dumped)
|
||||||
|
This is an issue report about the sample program of control point.
|
||||||
|
The tv_ctrlpt crashes after detecting a tvdevice that contains tvcontrol:2 or higher version of tvcontrol service.
|
||||||
|
tv_ctrlpt should detect correctly such devices due to forward compatibility of control points with device.
|
||||||
|
For more information about the compatibility, please refer the following document:
|
||||||
|
DLNA Architectures and Protocols Part 1 2011 December - 7.3.2.1.3 (GUN:GZJXU)
|
||||||
|
The attached patch changes the sample programs as below:
|
||||||
|
- device: changes version of tvcontrol service from 1 to 2. This change may occur in the future.
|
||||||
|
- cp: nothing changed: cp knows version 1 of tvcontrol service only.
|
||||||
|
I know many vendors implements their control points based on the tv_ctrlpt, so I hope to fix this issue ASAP.
|
||||||
|
|
||||||
|
==
|
||||||
|
|
||||||
|
From: Yoichi NAKAYAMA
|
||||||
|
SEGV is caused by strcpy with NULL argument.
|
||||||
|
Attached patch will avoid SEGV in strcpy, but there may be other inconsistencies.
|
||||||
|
|
||||||
|
> I know many vendors implements their control points based on the tv_ctrlpt,
|
||||||
|
|
||||||
|
I don't think so. I think tv_ctrlpt is just a sample to be used with tv_device.
|
||||||
|
|
||||||
|
2013-10-28 Pino Toscano <pinotree(at)users.sourceforge.net>
|
||||||
|
|
||||||
|
Fix compilation on GNU/Hurd
|
||||||
|
|
||||||
|
2013-10-28 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Fix return value of http_RecvPostMessage and update httpparser.c's comments
|
||||||
|
|
||||||
|
2013-10-17 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Fix return value of process_request and related subroutines
|
||||||
|
1) Only HTTP_XXX should be return
|
||||||
|
2) Make default return value work for process_request
|
||||||
|
|
||||||
|
2013-10-15 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Fix Content-Range generation bug
|
||||||
|
|
||||||
|
2013-09-10 zexian chen <chenzexian88(at)gmail.com>
|
||||||
|
|
||||||
|
Hi,
|
||||||
|
|
||||||
|
I had found some bugs about memory leak on libupnp-1.6.18.
|
||||||
|
|
||||||
|
It may lead to memory leak when calling ThreadPoolAdd() or
|
||||||
|
ThreadPoolAddPersistent() which does not return 0.
|
||||||
|
|
||||||
|
See the attachment for patch.
|
||||||
|
|
||||||
|
2013-09-03 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Fix return value of config_description_doc.
|
||||||
|
|
||||||
|
UPNP_E_XXX should not be used instead of IXML_XXX
|
||||||
|
|
||||||
|
2013-09-03 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Remove faulty free in GetDescDocumentAndURL.
|
||||||
|
|
||||||
|
temp_str, which points to part of description, should not be freed.
|
||||||
|
|
||||||
|
2013-09-02 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Suppose the UPnP device is listening on 192.168.1.102:49152. Use the following to send
|
||||||
|
garbage bytes to the device:
|
||||||
|
while true; do echo "\""; done | netcat 192.168.1.102 49152
|
||||||
|
|
||||||
|
The device just keeps receiving these bytes and its memory usage keeps growing.
|
||||||
|
Malicious client may exploit it to exhaust the device's memory.
|
||||||
|
|
||||||
|
The attached patch eliminates this possibility.
|
||||||
|
|
||||||
|
2013-09-02 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
1) restore the scanner's original cursor position in case of
|
||||||
|
insufficient input;
|
||||||
|
2) free the memories allocated for a new header in case of a failure.
|
||||||
|
|
||||||
|
2013-08-13 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Patch to fix behaviou when char is signed
|
||||||
|
|
||||||
|
it seems to me that there is still something wrong:
|
||||||
|
|
||||||
|
1) the new is_qdtext_char() is incorrect.
|
||||||
|
There is a trap if char is implemented as signed char.
|
||||||
|
Suppose that c is '\xFF', it will be -1 when converted to an int.
|
||||||
|
By definition, c should be qdtext:
|
||||||
|
qdtext = <any TEXT except <">>
|
||||||
|
TEXT = <any OCTET except CTLs, but including LWS>
|
||||||
|
OCTET = <any 8-bit sequence of data>
|
||||||
|
|
||||||
|
2) the character after '\\' could be either part of a quoted-pair
|
||||||
|
(together with '\\'), or a normal qdtext, since '\\' itself can
|
||||||
|
be treated as a qdtext. This is equivalent to saying that the
|
||||||
|
character after '\\' in a quoted string could be ANY octet.
|
||||||
|
|
||||||
|
A patch based on the above two observations is attached.
|
||||||
|
|
||||||
|
Peng
|
||||||
|
|
||||||
|
2013-08-13 Marcelo Roberto Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
|
||||||
|
Enforce RFC 2616 and accept "0" after a backslash for quoted-strings.
|
||||||
|
|
||||||
|
Reported by Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
2013-08-13 Peng <howtofly(at)gmail.com>
|
||||||
|
|
||||||
|
Patch to make scanner_get_token more robust (avoid over-reading).
|
||||||
|
|
||||||
|
2013-07-30 Zheng Peng <darkelf2010(at)users.sf.net>
|
||||||
|
|
||||||
|
SF ticket #116 UpnpRemoveVirtualDir wrong linked list operation
|
||||||
|
|
||||||
|
What if pVirtualDirList has two nodes and what we want to delete is the
|
||||||
|
first one. Patch attached.
|
||||||
|
|
||||||
|
2013-07-30 Sebastian Brandt <s.brandt(at)aixtrusion.de>
|
||||||
|
|
||||||
|
Dear libupnp-devels,
|
||||||
|
when POST'ing to the simple web server in libupnp, the application crashes.
|
||||||
|
This is caused by a missing "..." argument in webserver.c:1533.
|
||||||
|
Seems it has been there for a long time ... 1.6.9 and 1.6.18 have it.
|
||||||
|
|
||||||
|
webserver.c:1533 calls http_MakeMessage
|
||||||
|
/* Send response. */
|
||||||
|
http_MakeMessage(&headers, 1, 1,
|
||||||
|
"RTLSXcCc",
|
||||||
|
ret, "text/html", X_USER_AGENT);
|
||||||
|
The format parameter RTLSXcCc needs four arguments -
|
||||||
|
R - response code - ret,
|
||||||
|
T- content type - text/html,
|
||||||
|
L - struct SendInstruction * - NOT PRESENT
|
||||||
|
X - user agent - X_USER_AGENT
|
||||||
|
|
||||||
|
This results in a crash.
|
||||||
|
|
||||||
|
Changing to
|
||||||
|
http_MakeMessage(&headers, 1, 1,
|
||||||
|
"RTLSXcCc",
|
||||||
|
ret, "text/html", &RespInstr, X_USER_AGENT);
|
||||||
|
solves the situation.
|
||||||
|
|
||||||
|
Yours,
|
||||||
|
Sebastian Brandt
|
||||||
|
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
Version 1.6.18
|
Version 1.6.18
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|||||||
2
Doxyfile
2
Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME = libUPnP
|
|||||||
# This could be handy for archiving the generated documentation or
|
# This could be handy for archiving the generated documentation or
|
||||||
# if some version control system is used.
|
# if some version control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 1.6.18
|
PROJECT_NUMBER = 1.6.20
|
||||||
|
|
||||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||||
# base path where the generated documentation will be put.
|
# base path where the generated documentation will be put.
|
||||||
|
|||||||
10
THANKS
10
THANKS
@@ -23,6 +23,7 @@ exempt of errors.
|
|||||||
- Craig Nelson
|
- Craig Nelson
|
||||||
- David Blanchet
|
- David Blanchet
|
||||||
- David Maass
|
- David Maass
|
||||||
|
- Dirk (dirk_vdb)
|
||||||
- Emil Ljungdahl
|
- Emil Ljungdahl
|
||||||
- Erik Johansson
|
- Erik Johansson
|
||||||
- Eric Tanguy
|
- Eric Tanguy
|
||||||
@@ -37,6 +38,7 @@ exempt of errors.
|
|||||||
- Ingo Hofmann
|
- Ingo Hofmann
|
||||||
- Ivan Romanov (ivanromanov)
|
- Ivan Romanov (ivanromanov)
|
||||||
- Jiri Zouhar
|
- Jiri Zouhar
|
||||||
|
- Jean-Francois Dockes (medoc)
|
||||||
- John Dennis
|
- John Dennis
|
||||||
- Jonathan Casiot (no_dice)
|
- Jonathan Casiot (no_dice)
|
||||||
- Josh Carroll
|
- Josh Carroll
|
||||||
@@ -54,10 +56,16 @@ exempt of errors.
|
|||||||
- Oskar Liljeblad
|
- Oskar Liljeblad
|
||||||
- Michael (oxygenic)
|
- Michael (oxygenic)
|
||||||
- Paul Vixie
|
- Paul Vixie
|
||||||
|
- Peng
|
||||||
- Peter Hartley
|
- Peter Hartley
|
||||||
|
- Philipp Matthias Hahn
|
||||||
|
- Pino Toscano (pinotree)
|
||||||
- Rene Hexel
|
- Rene Hexel
|
||||||
|
- Robert Buckley (rbuckley)
|
||||||
- Robert Gingher (robsbox)
|
- Robert Gingher (robsbox)
|
||||||
- Ronan Menard
|
- Ronan Menard
|
||||||
|
- Sebastian Brandt
|
||||||
|
- Shaun Marko (semarko)
|
||||||
- Siva Chandran
|
- Siva Chandran
|
||||||
- Stefan Sommerfeld (zerocom)
|
- Stefan Sommerfeld (zerocom)
|
||||||
- Stéphane Corthésy
|
- Stéphane Corthésy
|
||||||
@@ -68,4 +76,6 @@ exempt of errors.
|
|||||||
- Tom (tomdev2)
|
- Tom (tomdev2)
|
||||||
- Yoichi Nakayama (yoichi)
|
- Yoichi Nakayama (yoichi)
|
||||||
- zephyrus (zephyrus00jp)
|
- zephyrus (zephyrus00jp)
|
||||||
|
- zexian chen
|
||||||
|
- Zheng Peng (darkelf2010)
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
#define PACKAGE_NAME "libupnp"
|
#define PACKAGE_NAME "libupnp"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* Define to the full name and version of this package. */
|
||||||
#define PACKAGE_STRING "libupnp 1.6.18"
|
#define PACKAGE_STRING "libupnp 1.6.20"
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
/* Define to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "libupnp"
|
#define PACKAGE_TARNAME "libupnp"
|
||||||
@@ -114,7 +114,7 @@
|
|||||||
#define PACKAGE_URL ""
|
#define PACKAGE_URL ""
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "1.6.18"
|
#define PACKAGE_VERSION "1.6.20"
|
||||||
|
|
||||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||||
your system. */
|
your system. */
|
||||||
@@ -172,13 +172,13 @@
|
|||||||
#define UPNP_VERSION_MINOR 6
|
#define UPNP_VERSION_MINOR 6
|
||||||
|
|
||||||
/* see upnpconfig.h */
|
/* see upnpconfig.h */
|
||||||
#define UPNP_VERSION_PATCH 18
|
#define UPNP_VERSION_PATCH 20
|
||||||
|
|
||||||
/* see upnpconfig.h */
|
/* see upnpconfig.h */
|
||||||
#define UPNP_VERSION_STRING "1.6.18"
|
#define UPNP_VERSION_STRING "1.6.20"
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "1.6.18"
|
#define VERSION "1.6.20"
|
||||||
|
|
||||||
/* File Offset size */
|
/* File Offset size */
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/** The library version (string) e.g. "1.3.0" */
|
/** The library version (string) e.g. "1.3.0" */
|
||||||
#define UPNP_VERSION_STRING "1.6.18"
|
#define UPNP_VERSION_STRING "1.6.20"
|
||||||
|
|
||||||
/** Major version of the library */
|
/** Major version of the library */
|
||||||
#define UPNP_VERSION_MAJOR 1
|
#define UPNP_VERSION_MAJOR 1
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
#define UPNP_VERSION_MINOR 6
|
#define UPNP_VERSION_MINOR 6
|
||||||
|
|
||||||
/** Patch version of the library */
|
/** Patch version of the library */
|
||||||
#define UPNP_VERSION_PATCH 18
|
#define UPNP_VERSION_PATCH 20
|
||||||
|
|
||||||
/** The library version (numeric) e.g. 10300 means version 1.3.0 */
|
/** The library version (numeric) e.g. 10300 means version 1.3.0 */
|
||||||
#define UPNP_VERSION \
|
#define UPNP_VERSION \
|
||||||
|
|||||||
31
configure.ac
31
configure.ac
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
|
|
||||||
AC_INIT([libupnp], [1.6.18], [mroberto@users.sourceforge.net])
|
AC_INIT([libupnp], [1.6.20], [mroberto@users.sourceforge.net])
|
||||||
dnl ############################################################################
|
dnl ############################################################################
|
||||||
dnl # *Independently* of the above libupnp package version, the libtool version
|
dnl # *Independently* of the above libupnp package version, the libtool version
|
||||||
dnl # of the 3 libraries need to be updated whenever there is a change released:
|
dnl # of the 3 libraries need to be updated whenever there is a change released:
|
||||||
@@ -328,9 +328,32 @@ dnl #AC_SUBST([LT_VERSION_THREADUTIL], [6:3:0])
|
|||||||
dnl #AC_SUBST([LT_VERSION_UPNP], [9:2:3])
|
dnl #AC_SUBST([LT_VERSION_UPNP], [9:2:3])
|
||||||
dnl #
|
dnl #
|
||||||
dnl ############################################################################
|
dnl ############################################################################
|
||||||
|
dnl # Release 1.6.19:
|
||||||
|
dnl # "current:revision:age"
|
||||||
|
dnl #
|
||||||
|
dnl # - Code has changed in threadutil
|
||||||
|
dnl # revision: 3 -> 4
|
||||||
|
dnl # - Code has changed in upnp
|
||||||
|
dnl # revision: 2 -> 3
|
||||||
|
dnl #
|
||||||
|
dnl #AC_SUBST([LT_VERSION_IXML], [2:8:0])
|
||||||
|
dnl #AC_SUBST([LT_VERSION_THREADUTIL], [6:4:0])
|
||||||
|
dnl #AC_SUBST([LT_VERSION_UPNP], [9:3:3])
|
||||||
|
dnl #
|
||||||
|
dnl ############################################################################
|
||||||
|
dnl # Release 1.6.20:
|
||||||
|
dnl # "current:revision:age"
|
||||||
|
dnl #
|
||||||
|
dnl # -
|
||||||
|
dnl #
|
||||||
|
dnl #AC_SUBST([LT_VERSION_IXML], [::])
|
||||||
|
dnl #AC_SUBST([LT_VERSION_THREADUTIL], [::])
|
||||||
|
dnl #AC_SUBST([LT_VERSION_UPNP], [::])
|
||||||
|
dnl #
|
||||||
|
dnl ############################################################################
|
||||||
AC_SUBST([LT_VERSION_IXML], [2:8:0])
|
AC_SUBST([LT_VERSION_IXML], [2:8:0])
|
||||||
AC_SUBST([LT_VERSION_THREADUTIL], [6:3:0])
|
AC_SUBST([LT_VERSION_THREADUTIL], [6:4:0])
|
||||||
AC_SUBST([LT_VERSION_UPNP], [9:2:3])
|
AC_SUBST([LT_VERSION_UPNP], [9:3:3])
|
||||||
dnl ############################################################################
|
dnl ############################################################################
|
||||||
dnl # Repeating the algorithm to place it closer to the modificatin place:
|
dnl # Repeating the algorithm to place it closer to the modificatin place:
|
||||||
dnl # - library code modified: revision++
|
dnl # - library code modified: revision++
|
||||||
@@ -508,6 +531,7 @@ AC_MSG_RESULT($docdir)
|
|||||||
#
|
#
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AM_PROG_CC_C_O
|
AM_PROG_CC_C_O
|
||||||
|
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||||
AC_PROG_LIBTOOL
|
AC_PROG_LIBTOOL
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
@@ -701,6 +725,7 @@ AC_OUTPUT
|
|||||||
# Files copied for windows compilation.
|
# Files copied for windows compilation.
|
||||||
#
|
#
|
||||||
echo "configure: copying \"autoconfig.h\" to \"build/inc/autoconfig.h\""
|
echo "configure: copying \"autoconfig.h\" to \"build/inc/autoconfig.h\""
|
||||||
|
test -d build/inc || mkdir -p build/inc
|
||||||
cp autoconfig.h build/inc/autoconfig.h
|
cp autoconfig.h build/inc/autoconfig.h
|
||||||
echo "configure: copying \"upnp/inc/upnpconfig.h\" to \"build/inc/upnpconfig.h\""
|
echo "configure: copying \"upnp/inc/upnpconfig.h\" to \"build/inc/upnpconfig.h\""
|
||||||
cp upnp/inc/upnpconfig.h build/inc/upnpconfig.h
|
cp upnp/inc/upnpconfig.h build/inc/upnpconfig.h
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
SUBDIRS = doc
|
SUBDIRS = doc
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(srcdir)/inc -I$(srcdir)/src/inc
|
AM_CPPFLAGS = -I$(srcdir)/inc -I$(srcdir)/src/inc \
|
||||||
|
-I$(top_srcdir)/upnp/inc
|
||||||
AM_CFLAGS =
|
AM_CFLAGS =
|
||||||
|
|
||||||
LDADD = libixml.la
|
LDADD = libixml.la
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Version: 1.6.18
|
Version: 1.6.20
|
||||||
Summary: Universal Plug and Play (UPnP) SDK
|
Summary: Universal Plug and Play (UPnP) SDK
|
||||||
Name: libupnp
|
Name: libupnp
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
# (C) Copyright 2005 Remi Turboult <r3mi@users.sourceforge.net>
|
# (C) Copyright 2005 Remi Turboult <r3mi@users.sourceforge.net>
|
||||||
#
|
#
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(srcdir)/inc -I$(srcdir)/src/inc
|
AM_CPPFLAGS = -I$(srcdir)/inc -I$(srcdir)/src/inc \
|
||||||
|
-I$(top_srcdir)/upnp/inc
|
||||||
|
|
||||||
if ENABLE_DEBUG
|
if ENABLE_DEBUG
|
||||||
AM_CPPFLAGS += -DDEBUG -DSTATS
|
AM_CPPFLAGS += -DDEBUG -DSTATS
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#if defined(BSD)
|
#if defined(BSD) && !defined(__GNU__)
|
||||||
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
|
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -200,10 +200,6 @@ typedef pthread_rwlockattr_t ithread_rwlockattr_t;
|
|||||||
static UPNP_INLINE int ithread_initialize_library(void) {
|
static UPNP_INLINE int ithread_initialize_library(void) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
#if defined(WIN32) && defined(PTW32_STATIC_LIB)
|
|
||||||
ret = !pthread_win32_process_attach_np();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,10 +218,6 @@ static UPNP_INLINE int ithread_initialize_library(void) {
|
|||||||
static UPNP_INLINE int ithread_cleanup_library(void) {
|
static UPNP_INLINE int ithread_cleanup_library(void) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
#if defined(WIN32) && defined(PTW32_STATIC_LIB)
|
|
||||||
ret = !pthread_win32_process_detach_np();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,10 +96,17 @@ static void *TimerThreadWorker(
|
|||||||
/* If time has elapsed, schedule job. */
|
/* If time has elapsed, schedule job. */
|
||||||
if (nextEvent && currentTime >= nextEventTime) {
|
if (nextEvent && currentTime >= nextEventTime) {
|
||||||
if( nextEvent->persistent ) {
|
if( nextEvent->persistent ) {
|
||||||
ThreadPoolAddPersistent( timer->tp, &nextEvent->job,
|
if (ThreadPoolAddPersistent( timer->tp, &nextEvent->job, &tempId ) != 0) {
|
||||||
&tempId );
|
if (nextEvent->job.arg != NULL && nextEvent->job.free_func != NULL) {
|
||||||
|
nextEvent->job.free_func(nextEvent->job.arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ThreadPoolAdd( timer->tp, &nextEvent->job, &tempId );
|
if (ThreadPoolAdd( timer->tp, &nextEvent->job, &tempId ) != 0) {
|
||||||
|
if (nextEvent->job.arg != NULL && nextEvent->job.free_func != NULL) {
|
||||||
|
nextEvent->job.free_func(nextEvent->job.arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ListDelNode( &timer->eventQ, head, 0 );
|
ListDelNode( &timer->eventQ, head, 0 );
|
||||||
FreeTimerEvent( timer, nextEvent );
|
FreeTimerEvent( timer, nextEvent );
|
||||||
|
|||||||
@@ -154,9 +154,10 @@ libupnp_la_SOURCES += \
|
|||||||
|
|
||||||
|
|
||||||
# check / distcheck tests
|
# check / distcheck tests
|
||||||
check_PROGRAMS = test_init
|
check_PROGRAMS = test_init test_url
|
||||||
TESTS = test_init
|
TESTS = test_init test_url
|
||||||
test_init_SOURCES = test/test_init.c
|
test_init_SOURCES = test/test_init.c
|
||||||
|
test_url_SOURCES = test/test_url.c
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
|||||||
@@ -65,9 +65,8 @@ tv_combo_SOURCES = \
|
|||||||
if WITH_DOCUMENTATION
|
if WITH_DOCUMENTATION
|
||||||
examplesdir = $(docdir)/examples
|
examplesdir = $(docdir)/examples
|
||||||
examples_DATA = \
|
examples_DATA = \
|
||||||
$(sort \
|
$(tv_ctrlpt_SOURCES) \
|
||||||
$(tv_ctrlpt_SOURCES) \
|
$(tv_device_SOURCES)
|
||||||
$(tv_device_SOURCES))
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
|||||||
@@ -741,6 +741,10 @@ void TvCtrlPointAddDevice(
|
|||||||
deviceNode->device.AdvrTimeOut = expires;
|
deviceNode->device.AdvrTimeOut = expires;
|
||||||
for (service = 0; service < TV_SERVICE_SERVCOUNT;
|
for (service = 0; service < TV_SERVICE_SERVCOUNT;
|
||||||
service++) {
|
service++) {
|
||||||
|
if (serviceId[service] == NULL) {
|
||||||
|
/* not found */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
strcpy(deviceNode->device.TvService[service].
|
strcpy(deviceNode->device.TvService[service].
|
||||||
ServiceId, serviceId[service]);
|
ServiceId, serviceId[service]);
|
||||||
strcpy(deviceNode->device.TvService[service].
|
strcpy(deviceNode->device.TvService[service].
|
||||||
|
|||||||
@@ -43,9 +43,7 @@
|
|||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
/* strndup() is a GNU extension. */
|
/* strndup() is a GNU extension. */
|
||||||
#if HAVE_STRNDUP && !defined(WIN32)
|
#if !HAVE_STRNDUP || defined(WIN32)
|
||||||
extern char *strndup(__const char *__string, size_t __n);
|
|
||||||
#else /* HAVE_STRNDUP && !defined(WIN32) */
|
|
||||||
static char *strndup(const char *__string, size_t __n)
|
static char *strndup(const char *__string, size_t __n)
|
||||||
{
|
{
|
||||||
size_t strsize = strnlen(__string, __n);
|
size_t strsize = strnlen(__string, __n);
|
||||||
|
|||||||
@@ -1590,7 +1590,6 @@ static int GetDescDocumentAndURL(
|
|||||||
}
|
}
|
||||||
if (strlen(temp_str) > (LINE_SIZE - 1)) {
|
if (strlen(temp_str) > (LINE_SIZE - 1)) {
|
||||||
ixmlDocument_free(*xmlDoc);
|
ixmlDocument_free(*xmlDoc);
|
||||||
free(temp_str);
|
|
||||||
return UPNP_E_URL_TOO_BIG;
|
return UPNP_E_URL_TOO_BIG;
|
||||||
}
|
}
|
||||||
strncpy(aliasStr, temp_str, sizeof(aliasStr) - 1);
|
strncpy(aliasStr, temp_str, sizeof(aliasStr) - 1);
|
||||||
@@ -1981,7 +1980,9 @@ int UpnpSubscribeAsync(
|
|||||||
TPJobInit(&job, (start_routine)UpnpThreadDistribution, Param);
|
TPJobInit(&job, (start_routine)UpnpThreadDistribution, Param);
|
||||||
TPJobSetFreeFunction(&job, (free_routine)free);
|
TPJobSetFreeFunction(&job, (free_routine)free);
|
||||||
TPJobSetPriority(&job, MED_PRIORITY);
|
TPJobSetPriority(&job, MED_PRIORITY);
|
||||||
ThreadPoolAdd(&gSendThreadPool, &job, NULL);
|
if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
|
||||||
|
free(Param);
|
||||||
|
}
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Exiting UpnpSubscribeAsync\n");
|
"Exiting UpnpSubscribeAsync\n");
|
||||||
@@ -2167,7 +2168,9 @@ int UpnpUnSubscribeAsync(
|
|||||||
TPJobInit( &job, ( start_routine ) UpnpThreadDistribution, Param );
|
TPJobInit( &job, ( start_routine ) UpnpThreadDistribution, Param );
|
||||||
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
TPJobSetPriority( &job, MED_PRIORITY );
|
||||||
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
if (ThreadPoolAdd( &gSendThreadPool, &job, NULL ) != 0) {
|
||||||
|
free(Param);
|
||||||
|
}
|
||||||
|
|
||||||
exit_function:
|
exit_function:
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpUnSubscribeAsync\n");
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpUnSubscribeAsync\n");
|
||||||
@@ -2293,7 +2296,9 @@ int UpnpRenewSubscriptionAsync(
|
|||||||
TPJobInit( &job, ( start_routine ) UpnpThreadDistribution, Param );
|
TPJobInit( &job, ( start_routine ) UpnpThreadDistribution, Param );
|
||||||
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
TPJobSetPriority( &job, MED_PRIORITY );
|
||||||
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
if (ThreadPoolAdd( &gSendThreadPool, &job, NULL ) != 0) {
|
||||||
|
free(Param);
|
||||||
|
}
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Exiting UpnpRenewSubscriptionAsync\n");
|
"Exiting UpnpRenewSubscriptionAsync\n");
|
||||||
@@ -2765,7 +2770,9 @@ int UpnpSendActionAsync(
|
|||||||
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
||||||
|
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
TPJobSetPriority( &job, MED_PRIORITY );
|
||||||
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
if (ThreadPoolAdd( &gSendThreadPool, &job, NULL ) != 0) {
|
||||||
|
free(Param);
|
||||||
|
}
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Exiting UpnpSendActionAsync \n");
|
"Exiting UpnpSendActionAsync \n");
|
||||||
@@ -2885,7 +2892,9 @@ int UpnpSendActionExAsync(
|
|||||||
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
||||||
|
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
TPJobSetPriority( &job, MED_PRIORITY );
|
||||||
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
if (ThreadPoolAdd( &gSendThreadPool, &job, NULL ) != 0) {
|
||||||
|
free(Param);
|
||||||
|
}
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Exiting UpnpSendActionAsync\n");
|
"Exiting UpnpSendActionAsync\n");
|
||||||
@@ -2952,7 +2961,9 @@ int UpnpGetServiceVarStatusAsync(
|
|||||||
|
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
TPJobSetPriority( &job, MED_PRIORITY );
|
||||||
|
|
||||||
ThreadPoolAdd( &gSendThreadPool, &job, NULL );
|
if (ThreadPoolAdd( &gSendThreadPool, &job, NULL ) != 0) {
|
||||||
|
free(Param);
|
||||||
|
}
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Exiting UpnpGetServiceVarStatusAsync\n");
|
"Exiting UpnpGetServiceVarStatusAsync\n");
|
||||||
@@ -4085,16 +4096,17 @@ int UpnpRemoveVirtualDir(const char *dirName)
|
|||||||
return UPNP_E_INVALID_PARAM;
|
return UPNP_E_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
/* Handle the special case where the directory that we are */
|
/* Handle the special case where the directory that we are */
|
||||||
/* removing is the first and only one in the list. */
|
/* removing is the first in the list. */
|
||||||
if( ( pVirtualDirList->next == NULL ) &&
|
if (strcmp( pVirtualDirList->dirName, dirName ) == 0)
|
||||||
( strcmp( pVirtualDirList->dirName, dirName ) == 0 ) ) {
|
{
|
||||||
free( pVirtualDirList );
|
pPrev = pVirtualDirList;
|
||||||
pVirtualDirList = NULL;
|
pVirtualDirList = pVirtualDirList->next;
|
||||||
|
free( pPrev );
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
pCur = pVirtualDirList;
|
pCur = pVirtualDirList->next;
|
||||||
pPrev = pCur;
|
pPrev = pVirtualDirList;
|
||||||
|
|
||||||
while( pCur != NULL ) {
|
while( pCur != NULL ) {
|
||||||
if( strcmp( pCur->dirName, dirName ) == 0 ) {
|
if( strcmp( pCur->dirName, dirName ) == 0 ) {
|
||||||
|
|||||||
@@ -480,25 +480,20 @@ int genaInitNotify(
|
|||||||
}
|
}
|
||||||
*reference_count = 0;
|
*reference_count = 0;
|
||||||
|
|
||||||
UDN_copy = (char *)malloc(strlen(UDN) + 1);
|
UDN_copy = strdup(UDN);
|
||||||
if (UDN_copy == NULL) {
|
if (UDN_copy == NULL) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
servId_copy = (char *)malloc(strlen(servId) + 1);
|
servId_copy = strdup(servId);
|
||||||
if (servId_copy == NULL) {
|
if (servId_copy == NULL) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(UDN_copy, 0, strlen(UDN) + 1);
|
|
||||||
strncpy(UDN_copy, UDN, strlen(UDN));
|
|
||||||
memset(servId_copy, 0, strlen(servId) + 1);
|
|
||||||
strncpy(servId_copy, servId, strlen(servId));
|
|
||||||
|
|
||||||
HandleLock();
|
HandleLock();
|
||||||
|
|
||||||
if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
|
if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
|
||||||
@@ -639,25 +634,20 @@ int genaInitNotifyExt(
|
|||||||
}
|
}
|
||||||
*reference_count = 0;
|
*reference_count = 0;
|
||||||
|
|
||||||
UDN_copy = (char *)malloc(strlen(UDN) + 1);
|
UDN_copy = strdup(UDN);
|
||||||
if (UDN_copy == NULL) {
|
if (UDN_copy == NULL) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
servId_copy = (char *)malloc(strlen(servId) + 1);
|
servId_copy = strdup(servId);
|
||||||
if( servId_copy == NULL ) {
|
if( servId_copy == NULL ) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(UDN_copy, 0, strlen(UDN) + 1);
|
|
||||||
strncpy(UDN_copy, UDN, strlen(UDN));
|
|
||||||
memset(servId_copy, 0, strlen(servId) + 1);
|
|
||||||
strncpy(servId_copy, servId, strlen(servId));
|
|
||||||
|
|
||||||
HandleLock();
|
HandleLock();
|
||||||
|
|
||||||
if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
|
if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
|
||||||
@@ -798,25 +788,20 @@ int genaNotifyAllExt(
|
|||||||
}
|
}
|
||||||
*reference_count = 0;
|
*reference_count = 0;
|
||||||
|
|
||||||
UDN_copy = (char *)malloc(strlen(UDN) + 1);
|
UDN_copy = strdup(UDN);
|
||||||
if (UDN_copy == NULL) {
|
if (UDN_copy == NULL) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
servId_copy = (char *)malloc(strlen(servId) + 1);
|
servId_copy = strdup(servId);
|
||||||
if( servId_copy == NULL ) {
|
if( servId_copy == NULL ) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(UDN_copy, 0, strlen(UDN) + 1);
|
|
||||||
strncpy(UDN_copy, UDN, strlen(UDN));
|
|
||||||
memset(servId_copy, 0, strlen(servId) + 1);
|
|
||||||
strncpy(servId_copy, servId, strlen(servId));
|
|
||||||
|
|
||||||
propertySet = ixmlPrintNode((IXML_Node *)PropSet);
|
propertySet = ixmlPrintNode((IXML_Node *)PropSet);
|
||||||
if (propertySet == NULL) {
|
if (propertySet == NULL) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
@@ -944,25 +929,20 @@ int genaNotifyAll(
|
|||||||
}
|
}
|
||||||
*reference_count = 0;
|
*reference_count = 0;
|
||||||
|
|
||||||
UDN_copy = (char *)malloc(strlen(UDN) + 1);
|
UDN_copy = strdup(UDN);
|
||||||
if (UDN_copy == NULL) {
|
if (UDN_copy == NULL) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
servId_copy = (char *)malloc(strlen(servId) + 1);
|
servId_copy = strdup(servId);
|
||||||
if( servId_copy == NULL ) {
|
if( servId_copy == NULL ) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_OUTOF_MEMORY;
|
ret = UPNP_E_OUTOF_MEMORY;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(UDN_copy, 0, strlen(UDN) + 1);
|
|
||||||
strncpy(UDN_copy, UDN, strlen(UDN));
|
|
||||||
memset(servId_copy, 0, strlen(servId) + 1);
|
|
||||||
strncpy(servId_copy, servId, strlen(servId));
|
|
||||||
|
|
||||||
ret = GeneratePropertySet(VarNames, VarValues, var_count, &propertySet);
|
ret = GeneratePropertySet(VarNames, VarValues, var_count, &propertySet);
|
||||||
if (ret != XML_SUCCESS) {
|
if (ret != XML_SUCCESS) {
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
|
|||||||
@@ -910,6 +910,7 @@ int StartMiniServer(
|
|||||||
sock_close(miniSocket->ssdpReqSock4);
|
sock_close(miniSocket->ssdpReqSock4);
|
||||||
sock_close(miniSocket->ssdpReqSock6);
|
sock_close(miniSocket->ssdpReqSock6);
|
||||||
#endif /* INCLUDE_CLIENT_APIS */
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
free(miniSocket);
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
}
|
}
|
||||||
/* Wait for miniserver to start. */
|
/* Wait for miniserver to start. */
|
||||||
|
|||||||
@@ -138,12 +138,12 @@ static UPNP_INLINE void scanner_init(OUT scanner_t *scanner, IN membuffer *bufpt
|
|||||||
* Parameters :
|
* Parameters :
|
||||||
* IN char c ; character to be tested against used separator values
|
* IN char c ; character to be tested against used separator values
|
||||||
*
|
*
|
||||||
* Description : Finds the separator character.
|
* Description : Determines if the passed value is a separator
|
||||||
*
|
*
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int is_separator_char(IN char c)
|
static UPNP_INLINE int is_separator_char(IN int c)
|
||||||
{
|
{
|
||||||
return strchr(" \t()<>@,;:\\\"/[]?={}", (int)c) != NULL;
|
return strchr(" \t()<>@,;:\\\"/[]?={}", c) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -152,10 +152,10 @@ static UPNP_INLINE int is_separator_char(IN char c)
|
|||||||
* Parameters :
|
* Parameters :
|
||||||
* IN char c ; character to be tested for separator values
|
* IN char c ; character to be tested for separator values
|
||||||
*
|
*
|
||||||
* Description : Calls the function to indentify separator character
|
* Description : Determines if the passed value is permissible in token
|
||||||
*
|
*
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int is_identifier_char(IN char c)
|
static UPNP_INLINE int is_identifier_char(IN int c)
|
||||||
{
|
{
|
||||||
return c >= 32 && c <= 126 && !is_separator_char(c);
|
return c >= 32 && c <= 126 && !is_separator_char(c);
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ static UPNP_INLINE int is_identifier_char(IN char c)
|
|||||||
* Description : Determines if the passed value is a control character
|
* Description : Determines if the passed value is a control character
|
||||||
*
|
*
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int is_control_char(IN char c)
|
static UPNP_INLINE int is_control_char(IN int c)
|
||||||
{
|
{
|
||||||
return (c >= 0 && c <= 31) || c == 127;
|
return (c >= 0 && c <= 31) || c == 127;
|
||||||
}
|
}
|
||||||
@@ -180,23 +180,20 @@ static UPNP_INLINE int is_control_char(IN char c)
|
|||||||
* Parameters :
|
* Parameters :
|
||||||
* IN char cc ; character to be tested for CR/LF
|
* IN char cc ; character to be tested for CR/LF
|
||||||
*
|
*
|
||||||
* Description : Checks to see if the passed in value is CR/LF
|
* Description : Determines if the passed value is permissible in qdtext
|
||||||
*
|
*
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE int is_qdtext_char(IN char cc)
|
static UPNP_INLINE int is_qdtext_char(IN int c)
|
||||||
{
|
{
|
||||||
unsigned char c = ( unsigned char )cc;
|
/* we don't check for this; it's checked in get_token() */
|
||||||
|
assert( c != '"' );
|
||||||
|
|
||||||
/* we don't check for this; it's checked in get_token() */
|
return
|
||||||
assert( c != '"' );
|
(c >= 32 && c != 127) ||
|
||||||
|
c < 0 ||
|
||||||
if( ( c >= 32 && c != 127 ) ||
|
c == TOKCHAR_CR ||
|
||||||
( c == TOKCHAR_CR || c == TOKCHAR_LF || c == '\t' )
|
c == TOKCHAR_LF ||
|
||||||
) {
|
c == '\t';
|
||||||
return TRUE;
|
|
||||||
} else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -224,7 +221,7 @@ static parse_status_t scanner_get_token(
|
|||||||
{
|
{
|
||||||
char *cursor;
|
char *cursor;
|
||||||
char *null_terminator; /* point to null-terminator in buffer */
|
char *null_terminator; /* point to null-terminator in buffer */
|
||||||
char c;
|
int c;
|
||||||
token_type_t token_type;
|
token_type_t token_type;
|
||||||
int got_end_quote;
|
int got_end_quote;
|
||||||
|
|
||||||
@@ -243,7 +240,7 @@ static parse_status_t scanner_get_token(
|
|||||||
/* scan identifier */
|
/* scan identifier */
|
||||||
token->buf = cursor++;
|
token->buf = cursor++;
|
||||||
token_type = TT_IDENTIFIER;
|
token_type = TT_IDENTIFIER;
|
||||||
while (is_identifier_char(*cursor))
|
while (cursor < null_terminator && is_identifier_char(*cursor))
|
||||||
cursor++;
|
cursor++;
|
||||||
if (!scanner->entire_msg_loaded && cursor == null_terminator)
|
if (!scanner->entire_msg_loaded && cursor == null_terminator)
|
||||||
/* possibly more valid chars */
|
/* possibly more valid chars */
|
||||||
@@ -253,7 +250,7 @@ static parse_status_t scanner_get_token(
|
|||||||
} else if (c == ' ' || c == '\t') {
|
} else if (c == ' ' || c == '\t') {
|
||||||
token->buf = cursor++;
|
token->buf = cursor++;
|
||||||
token_type = TT_WHITESPACE;
|
token_type = TT_WHITESPACE;
|
||||||
while (*cursor == ' ' || *cursor == '\t')
|
while (cursor < null_terminator && (*cursor == ' ' || *cursor == '\t'))
|
||||||
cursor++;
|
cursor++;
|
||||||
if (!scanner->entire_msg_loaded && cursor == null_terminator)
|
if (!scanner->entire_msg_loaded && cursor == null_terminator)
|
||||||
/* possibly more chars */
|
/* possibly more chars */
|
||||||
@@ -292,9 +289,7 @@ static parse_status_t scanner_get_token(
|
|||||||
} else if (c == '\\') {
|
} else if (c == '\\') {
|
||||||
if (cursor < null_terminator) {
|
if (cursor < null_terminator) {
|
||||||
c = *cursor++;
|
c = *cursor++;
|
||||||
/*if ( !(c > 0 && c <= 127) ) */
|
/* the char after '\\' could be ANY octet */
|
||||||
if (c == 0)
|
|
||||||
return PARSE_FAILURE;
|
|
||||||
}
|
}
|
||||||
/* else, while loop handles incomplete buf */
|
/* else, while loop handles incomplete buf */
|
||||||
} else if (is_qdtext_char(c)) {
|
} else if (is_qdtext_char(c)) {
|
||||||
@@ -521,8 +516,9 @@ http_header_t *httpmsg_find_hdr(
|
|||||||
* Description : skips blank lines at the start of a msg.
|
* Description : skips blank lines at the start of a msg.
|
||||||
*
|
*
|
||||||
* Return : parse_status_t ;
|
* Return : parse_status_t ;
|
||||||
*
|
* PARSE_OK
|
||||||
* Note :
|
* PARSE_INCOMPLETE -- not enuf chars to get a token
|
||||||
|
* PARSE_FAILURE -- bad msg format
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t skip_blank_lines(INOUT scanner_t *scanner)
|
static UPNP_INLINE parse_status_t skip_blank_lines(INOUT scanner_t *scanner)
|
||||||
{
|
{
|
||||||
@@ -1132,6 +1128,7 @@ static parse_status_t vfmatch(
|
|||||||
* PARSE_OK
|
* PARSE_OK
|
||||||
* PARSE_NO_MATCH
|
* PARSE_NO_MATCH
|
||||||
* PARSE_INCOMPLETE
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_FAILURE - bad input
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static parse_status_t match(
|
static parse_status_t match(
|
||||||
INOUT scanner_t *scanner,
|
INOUT scanner_t *scanner,
|
||||||
@@ -1164,6 +1161,7 @@ static parse_status_t match(
|
|||||||
* PARSE_OK
|
* PARSE_OK
|
||||||
* PARSE_NO_MATCH -- failure to match pattern 'fmt'
|
* PARSE_NO_MATCH -- failure to match pattern 'fmt'
|
||||||
* PARSE_FAILURE -- 'str' is bad input
|
* PARSE_FAILURE -- 'str' is bad input
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
parse_status_t
|
parse_status_t
|
||||||
matchstr( IN char *str,
|
matchstr( IN char *str,
|
||||||
@@ -1238,6 +1236,8 @@ parser_init( OUT http_parser_t * parser )
|
|||||||
* PARSE_OK
|
* PARSE_OK
|
||||||
* PARSE_SUCCESS
|
* PARSE_SUCCESS
|
||||||
* PARSE_FAILURE
|
* PARSE_FAILURE
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_NO_MATCH
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static parse_status_t
|
static parse_status_t
|
||||||
parser_parse_requestline( INOUT http_parser_t * parser )
|
parser_parse_requestline( INOUT http_parser_t * parser )
|
||||||
@@ -1354,12 +1354,13 @@ parser_parse_requestline( INOUT http_parser_t * parser )
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* INOUT http_parser_t* parser ; HTTP Parser object
|
* INOUT http_parser_t* parser ; HTTP Parser object
|
||||||
*
|
*
|
||||||
* Description: Get HTTP Method, URL location and version information.
|
* Description: Get HTTP version information, status code and status msg.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_OK
|
* PARSE_OK
|
||||||
* PARSE_SUCCESS
|
|
||||||
* PARSE_FAILURE
|
* PARSE_FAILURE
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_NO_MATCH
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
parse_status_t parser_parse_responseline(INOUT http_parser_t *parser)
|
parse_status_t parser_parse_responseline(INOUT http_parser_t *parser)
|
||||||
{
|
{
|
||||||
@@ -1431,12 +1432,14 @@ parse_status_t parser_parse_responseline(INOUT http_parser_t *parser)
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* INOUT http_parser_t* parser ; HTTP Parser object
|
* INOUT http_parser_t* parser ; HTTP Parser object
|
||||||
*
|
*
|
||||||
* Description: Get HTTP Method, URL location and version information.
|
* Description: Read HTTP header fields.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_OK
|
* PARSE_OK
|
||||||
* PARSE_SUCCESS
|
* PARSE_SUCCESS
|
||||||
* PARSE_FAILURE
|
* PARSE_FAILURE
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_NO_MATCH
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
parse_status_t parser_parse_headers(INOUT http_parser_t *parser)
|
parse_status_t parser_parse_headers(INOUT http_parser_t *parser)
|
||||||
{
|
{
|
||||||
@@ -1462,6 +1465,8 @@ parse_status_t parser_parse_headers(INOUT http_parser_t *parser)
|
|||||||
/* check end of headers */
|
/* check end of headers */
|
||||||
status = scanner_get_token(scanner, &token, &tok_type);
|
status = scanner_get_token(scanner, &token, &tok_type);
|
||||||
if (status != (parse_status_t)PARSE_OK) {
|
if (status != (parse_status_t)PARSE_OK) {
|
||||||
|
/* pushback tokens; useful only on INCOMPLETE error */
|
||||||
|
scanner->cursor = save_pos;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
switch (tok_type) {
|
switch (tok_type) {
|
||||||
@@ -1529,6 +1534,8 @@ parse_status_t parser_parse_headers(INOUT http_parser_t *parser)
|
|||||||
if (membuffer_assign(&header->name_buf, token.buf, token.length) ||
|
if (membuffer_assign(&header->name_buf, token.buf, token.length) ||
|
||||||
membuffer_assign(&header->value, hdr_value.buf, hdr_value.length)) {
|
membuffer_assign(&header->value, hdr_value.buf, hdr_value.length)) {
|
||||||
/* not enough mem */
|
/* not enough mem */
|
||||||
|
membuffer_destroy(&header->value);
|
||||||
|
membuffer_destroy(&header->name_buf);
|
||||||
free(header);
|
free(header);
|
||||||
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
|
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
|
||||||
return PARSE_FAILURE;
|
return PARSE_FAILURE;
|
||||||
@@ -1536,15 +1543,13 @@ parse_status_t parser_parse_headers(INOUT http_parser_t *parser)
|
|||||||
header->name.buf = header->name_buf.buf;
|
header->name.buf = header->name_buf.buf;
|
||||||
header->name.length = header->name_buf.length;
|
header->name.length = header->name_buf.length;
|
||||||
header->name_id = header_id;
|
header->name_id = header_id;
|
||||||
ListAddTail(&parser->msg.headers, header);
|
if (!ListAddTail(&parser->msg.headers, header)) {
|
||||||
/*NNS: ret = dlist_append( &parser->msg.headers, header ); */
|
membuffer_destroy(&header->value);
|
||||||
/** TODO: remove that? Yes as ret is not set anymore
|
membuffer_destroy(&header->name_buf);
|
||||||
if (ret == UPNP_E_OUTOF_MEMORY) {
|
free(header);
|
||||||
parser->http_error_code =
|
parser->http_error_code = HTTP_INTERNAL_SERVER_ERROR;
|
||||||
HTTP_INTERNAL_SERVER_ERROR;
|
|
||||||
return PARSE_FAILURE;
|
return PARSE_FAILURE;
|
||||||
}
|
}
|
||||||
end of remove that? */
|
|
||||||
} else if (hdr_value.length > (size_t)0) {
|
} else if (hdr_value.length > (size_t)0) {
|
||||||
/* append value to existing header */
|
/* append value to existing header */
|
||||||
/* append space */
|
/* append space */
|
||||||
@@ -1575,7 +1580,6 @@ end of remove that? */
|
|||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_INCOMPLETE
|
* PARSE_INCOMPLETE
|
||||||
* PARSE_FAILURE -- entity length > content-length value
|
|
||||||
* PARSE_SUCCESS
|
* PARSE_SUCCESS
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t
|
static UPNP_INLINE parse_status_t
|
||||||
@@ -1622,9 +1626,10 @@ parser_parse_entity_using_clen( INOUT http_parser_t * parser )
|
|||||||
* Description: Read data in the chunks
|
* Description: Read data in the chunks
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
|
* PARSE_CONTINUE_1
|
||||||
* PARSE_INCOMPLETE
|
* PARSE_INCOMPLETE
|
||||||
* PARSE_FAILURE -- entity length > content-length value
|
* PARSE_FAILURE
|
||||||
* PARSE_SUCCESS
|
* PARSE_NO_MATCH
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t parser_parse_chunky_body(
|
static UPNP_INLINE parse_status_t parser_parse_chunky_body(
|
||||||
INOUT http_parser_t *parser)
|
INOUT http_parser_t *parser)
|
||||||
@@ -1666,8 +1671,9 @@ static UPNP_INLINE parse_status_t parser_parse_chunky_body(
|
|||||||
* Description: Read headers at the end of the chunked entity
|
* Description: Read headers at the end of the chunked entity
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
|
* PARSE_NO_MATCH
|
||||||
* PARSE_INCOMPLETE
|
* PARSE_INCOMPLETE
|
||||||
* PARSE_FAILURE -- entity length > content-length value
|
* PARSE_FAILURE
|
||||||
* PARSE_SUCCESS
|
* PARSE_SUCCESS
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t
|
static UPNP_INLINE parse_status_t
|
||||||
@@ -1702,12 +1708,12 @@ parser_parse_chunky_headers( INOUT http_parser_t * parser )
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* INOUT http_parser_t* parser - HTTP Parser Object
|
* INOUT http_parser_t* parser - HTTP Parser Object
|
||||||
*
|
*
|
||||||
* Description: Read headers at the end of the chunked entity
|
* Description: Read entity using chunked transfer encoding
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_INCOMPLETE
|
* PARSE_INCOMPLETE
|
||||||
* PARSE_FAILURE -- entity length > content-length value
|
* PARSE_FAILURE
|
||||||
* PARSE_SUCCESS
|
* PARSE_NO_MATCH
|
||||||
* PARSE_CONTINUE_1
|
* PARSE_CONTINUE_1
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
static UPNP_INLINE parse_status_t
|
static UPNP_INLINE parse_status_t
|
||||||
@@ -1756,7 +1762,7 @@ parser_parse_chunky_entity( INOUT http_parser_t * parser )
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* INOUT http_parser_t* parser ; HTTP Parser object
|
* INOUT http_parser_t* parser ; HTTP Parser object
|
||||||
*
|
*
|
||||||
* Description: Read headers at the end of the chunked entity
|
* Description: Keep reading entity until the connection is closed.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_INCOMPLETE_ENTITY
|
* PARSE_INCOMPLETE_ENTITY
|
||||||
@@ -1793,9 +1799,9 @@ parser_parse_entity_until_close( INOUT http_parser_t * parser )
|
|||||||
* Description: Determines method to read entity
|
* Description: Determines method to read entity
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_OK
|
* PARSE_CONTINUE_1
|
||||||
* PARSE_FAILURE
|
* PARSE_FAILURE
|
||||||
* PARSE_COMPLETE -- no more reading to do
|
* PARSE_SUCCESS -- no more reading to do
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
UPNP_INLINE parse_status_t
|
UPNP_INLINE parse_status_t
|
||||||
parser_get_entity_read_method( INOUT http_parser_t * parser )
|
parser_get_entity_read_method( INOUT http_parser_t * parser )
|
||||||
@@ -1891,17 +1897,19 @@ parser_get_entity_read_method( INOUT http_parser_t * parser )
|
|||||||
* Parameters:
|
* Parameters:
|
||||||
* INOUT http_parser_t* parser ; HTTP Parser object
|
* INOUT http_parser_t* parser ; HTTP Parser object
|
||||||
*
|
*
|
||||||
* Description: Determines method to read entity
|
* Description: Read HTTP entity body
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* PARSE_OK
|
|
||||||
* PARSE_FAILURE
|
* PARSE_FAILURE
|
||||||
* PARSE_COMPLETE -- no more reading to do
|
* PARSE_NO_MATCH
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_INCOMPLETE_ENTITY
|
||||||
|
* PARSE_SUCCESS -- no more reading to do
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
UPNP_INLINE parse_status_t
|
UPNP_INLINE parse_status_t
|
||||||
parser_parse_entity( INOUT http_parser_t * parser )
|
parser_parse_entity( INOUT http_parser_t * parser )
|
||||||
{
|
{
|
||||||
parse_status_t status = PARSE_OK;
|
parse_status_t status;
|
||||||
|
|
||||||
assert( parser->position == POS_ENTITY );
|
assert( parser->position == POS_ENTITY );
|
||||||
|
|
||||||
@@ -1932,6 +1940,7 @@ parser_parse_entity( INOUT http_parser_t * parser )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
status = PARSE_FAILURE;
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1992,7 +2001,11 @@ parser_response_init( OUT http_parser_t * parser,
|
|||||||
* parser object the actual parsing function is invoked
|
* parser object the actual parsing function is invoked
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* void
|
* PARSE_SUCCESS
|
||||||
|
* PARSE_FAILURE
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_INCOMPLETE_ENTITY
|
||||||
|
* PARSE_NO_MATCH
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
parse_status_t
|
parse_status_t
|
||||||
parser_parse( INOUT http_parser_t * parser )
|
parser_parse( INOUT http_parser_t * parser )
|
||||||
@@ -2047,11 +2060,14 @@ parser_parse( INOUT http_parser_t * parser )
|
|||||||
* buffer
|
* buffer
|
||||||
* IN size_t buf_length ; Size of the buffer
|
* IN size_t buf_length ; Size of the buffer
|
||||||
*
|
*
|
||||||
* Description: The parser function. Depending on the position of the
|
* Description: Append date to HTTP parser, and do the parsing.
|
||||||
* parser object the actual parsing function is invoked
|
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* void
|
* PARSE_SUCCESS
|
||||||
|
* PARSE_FAILURE
|
||||||
|
* PARSE_INCOMPLETE
|
||||||
|
* PARSE_INCOMPLETE_ENTITY
|
||||||
|
* PARSE_NO_MATCH
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
parse_status_t
|
parse_status_t
|
||||||
parser_append( INOUT http_parser_t * parser,
|
parser_append( INOUT http_parser_t * parser,
|
||||||
|
|||||||
@@ -322,6 +322,7 @@ int http_RecvMessage(
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
case PARSE_FAILURE:
|
case PARSE_FAILURE:
|
||||||
|
case PARSE_NO_MATCH:
|
||||||
*http_error_code = parser->http_error_code;
|
*http_error_code = parser->http_error_code;
|
||||||
line = __LINE__;
|
line = __LINE__;
|
||||||
ret = UPNP_E_BAD_HTTPMSG;
|
ret = UPNP_E_BAD_HTTPMSG;
|
||||||
@@ -480,13 +481,12 @@ int http_SendMessage(SOCKINFO *info, int *TimeOut, const char *fmt, ...)
|
|||||||
memset(Chunk_Header, 0,
|
memset(Chunk_Header, 0,
|
||||||
sizeof(Chunk_Header));
|
sizeof(Chunk_Header));
|
||||||
rc = snprintf(Chunk_Header,
|
rc = snprintf(Chunk_Header,
|
||||||
sizeof(Chunk_Header) - strlen ("\r\n"),
|
sizeof(Chunk_Header),
|
||||||
"%" PRIzx, num_read);
|
"%" PRIzx "\r\n", num_read);
|
||||||
if (rc < 0 || (unsigned int) rc >= sizeof(Chunk_Header) - strlen ("\r\n")) {
|
if (rc < 0 || (unsigned int) rc >= sizeof(Chunk_Header)) {
|
||||||
RetVal = UPNP_E_INTERNAL_ERROR;
|
RetVal = UPNP_E_INTERNAL_ERROR;
|
||||||
goto Cleanup_File;
|
goto Cleanup_File;
|
||||||
}
|
}
|
||||||
strncat(Chunk_Header, "\r\n", strlen ("\r\n"));
|
|
||||||
/* Copy the chunk size header */
|
/* Copy the chunk size header */
|
||||||
memcpy(file_buf - strlen(Chunk_Header),
|
memcpy(file_buf - strlen(Chunk_Header),
|
||||||
Chunk_Header,
|
Chunk_Header,
|
||||||
|
|||||||
@@ -88,14 +88,19 @@ static const char *Http4xxStr =
|
|||||||
"Unsupported Media Type\0"
|
"Unsupported Media Type\0"
|
||||||
"Requested Range Not Satisfiable\0" "Expectation Failed\0";
|
"Requested Range Not Satisfiable\0" "Expectation Failed\0";
|
||||||
|
|
||||||
#define NUM_5XX_CODES 6
|
#define NUM_5XX_CODES 11
|
||||||
static const char *Http5xxCodes[NUM_5XX_CODES];
|
static const char *Http5xxCodes[NUM_5XX_CODES];
|
||||||
static const char *Http5xxStr =
|
static const char *Http5xxStr =
|
||||||
"Internal Server Error\0"
|
"Internal Server Error\0"
|
||||||
"Not Implemented\0"
|
"Not Implemented\0"
|
||||||
"Bad Gateway\0"
|
"Bad Gateway\0"
|
||||||
"Service Unavailable\0"
|
"Service Unavailable\0"
|
||||||
"Gateway Timeout\0" "HTTP Version Not Supported\0";
|
"Gateway Timeout\0"
|
||||||
|
"HTTP Version Not Supported\0"
|
||||||
|
"Variant Also Negotiates\0"
|
||||||
|
"Insufficient Storage\0"
|
||||||
|
"Loop Detected\0"
|
||||||
|
"\0" "Not Extended\0";
|
||||||
|
|
||||||
static int gInitialized = FALSE;
|
static int gInitialized = FALSE;
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ static const char *gMediaTypes[] = {
|
|||||||
#define TEXT_INDEX 5
|
#define TEXT_INDEX 5
|
||||||
|
|
||||||
/* general */
|
/* general */
|
||||||
#define NUM_MEDIA_TYPES 69
|
#define NUM_MEDIA_TYPES 70
|
||||||
#define NUM_HTTP_HEADER_NAMES 33
|
#define NUM_HTTP_HEADER_NAMES 33
|
||||||
|
|
||||||
#define ASCTIME_R_BUFFER_SIZE 26
|
#define ASCTIME_R_BUFFER_SIZE 26
|
||||||
@@ -156,6 +156,7 @@ static const char *gEncodedMediaTypes =
|
|||||||
"au\0" AUDIO_STR "basic\0"
|
"au\0" AUDIO_STR "basic\0"
|
||||||
"avi\0" VIDEO_STR "msvideo\0"
|
"avi\0" VIDEO_STR "msvideo\0"
|
||||||
"bmp\0" IMAGE_STR "bmp\0"
|
"bmp\0" IMAGE_STR "bmp\0"
|
||||||
|
"css\0" TEXT_STR "css\0"
|
||||||
"dcr\0" APPLICATION_STR "x-director\0"
|
"dcr\0" APPLICATION_STR "x-director\0"
|
||||||
"dib\0" IMAGE_STR "bmp\0"
|
"dib\0" IMAGE_STR "bmp\0"
|
||||||
"dir\0" APPLICATION_STR "x-director\0"
|
"dir\0" APPLICATION_STR "x-director\0"
|
||||||
@@ -771,7 +772,7 @@ static int GetNextRange(
|
|||||||
*
|
*
|
||||||
* \return
|
* \return
|
||||||
* \li \c HTTP_BAD_REQUEST
|
* \li \c HTTP_BAD_REQUEST
|
||||||
* \li \c UPNP_E_OUTOF_MEMORY
|
* \li \c HTTP_INTERNAL_SERVER_ERROR
|
||||||
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
||||||
* \li \c HTTP_OK
|
* \li \c HTTP_OK
|
||||||
*/
|
*/
|
||||||
@@ -792,11 +793,9 @@ static int CreateHTTPRangeResponseHeader(
|
|||||||
Instr->ReadSendSize = FileLength;
|
Instr->ReadSendSize = FileLength;
|
||||||
if (!ByteRangeSpecifier)
|
if (!ByteRangeSpecifier)
|
||||||
return HTTP_BAD_REQUEST;
|
return HTTP_BAD_REQUEST;
|
||||||
RangeInput = malloc(strlen(ByteRangeSpecifier) + 1);
|
RangeInput = strdup(ByteRangeSpecifier);
|
||||||
if (!RangeInput)
|
if (!RangeInput)
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
memset(RangeInput, 0, strlen(ByteRangeSpecifier) + 1);
|
|
||||||
strncpy(RangeInput, ByteRangeSpecifier, strlen(ByteRangeSpecifier));
|
|
||||||
/* CONTENT-RANGE: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
/* CONTENT-RANGE: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
||||||
if (StrStr(RangeInput, "bytes") == NULL ||
|
if (StrStr(RangeInput, "bytes") == NULL ||
|
||||||
(Ptr = StrStr(RangeInput, "=")) == NULL) {
|
(Ptr = StrStr(RangeInput, "=")) == NULL) {
|
||||||
@@ -830,7 +829,7 @@ static int CreateHTTPRangeResponseHeader(
|
|||||||
(int64_t)FileLength);
|
(int64_t)FileLength);
|
||||||
if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
|
if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
|
||||||
free(RangeInput);
|
free(RangeInput);
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
} else if (FirstByte >= 0 && LastByte == -1
|
} else if (FirstByte >= 0 && LastByte == -1
|
||||||
&& FirstByte < FileLength) {
|
&& FirstByte < FileLength) {
|
||||||
@@ -845,7 +844,7 @@ static int CreateHTTPRangeResponseHeader(
|
|||||||
(int64_t)FileLength);
|
(int64_t)FileLength);
|
||||||
if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
|
if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
|
||||||
free(RangeInput);
|
free(RangeInput);
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
} else if (FirstByte == -1 && LastByte > 0) {
|
} else if (FirstByte == -1 && LastByte > 0) {
|
||||||
if (LastByte >= FileLength) {
|
if (LastByte >= FileLength) {
|
||||||
@@ -864,13 +863,13 @@ static int CreateHTTPRangeResponseHeader(
|
|||||||
sizeof(Instr->RangeHeader),
|
sizeof(Instr->RangeHeader),
|
||||||
"CONTENT-RANGE: bytes %" PRId64
|
"CONTENT-RANGE: bytes %" PRId64
|
||||||
"-%" PRId64 "/%" PRId64 "\r\n",
|
"-%" PRId64 "/%" PRId64 "\r\n",
|
||||||
(int64_t)(FileLength - LastByte + 1),
|
(int64_t)(FileLength - LastByte),
|
||||||
(int64_t)FileLength,
|
(int64_t)FileLength - 1,
|
||||||
(int64_t)FileLength);
|
(int64_t)FileLength);
|
||||||
}
|
}
|
||||||
if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
|
if (rc < 0 || (unsigned int) rc >= sizeof(Instr->RangeHeader)) {
|
||||||
free(RangeInput);
|
free(RangeInput);
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
free(RangeInput);
|
free(RangeInput);
|
||||||
@@ -891,7 +890,7 @@ static int CreateHTTPRangeResponseHeader(
|
|||||||
*
|
*
|
||||||
* \return
|
* \return
|
||||||
* \li \c HTTP_BAD_REQUEST
|
* \li \c HTTP_BAD_REQUEST
|
||||||
* \li \c UPNP_E_OUTOF_MEMORY
|
* \li \c HTTP_INTERNAL_SERVER_ERROR
|
||||||
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
||||||
* \li \c HTTP_OK
|
* \li \c HTTP_OK
|
||||||
*/
|
*/
|
||||||
@@ -912,7 +911,7 @@ static int CheckOtherHTTPHeaders(
|
|||||||
|
|
||||||
TmpBuf = (char *)malloc(TmpBufSize);
|
TmpBuf = (char *)malloc(TmpBufSize);
|
||||||
if (!TmpBuf)
|
if (!TmpBuf)
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
node = ListHead(&Req->headers);
|
node = ListHead(&Req->headers);
|
||||||
while (node != NULL) {
|
while (node != NULL) {
|
||||||
header = (http_header_t *) node->item;
|
header = (http_header_t *) node->item;
|
||||||
@@ -925,7 +924,7 @@ static int CheckOtherHTTPHeaders(
|
|||||||
TmpBufSize = header->value.length + 1;
|
TmpBufSize = header->value.length + 1;
|
||||||
TmpBuf = (char *)malloc(TmpBufSize);
|
TmpBuf = (char *)malloc(TmpBufSize);
|
||||||
if (!TmpBuf)
|
if (!TmpBuf)
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(TmpBuf, header->value.buf, header->value.length);
|
memcpy(TmpBuf, header->value.buf, header->value.length);
|
||||||
TmpBuf[header->value.length] = '\0';
|
TmpBuf[header->value.length] = '\0';
|
||||||
@@ -1014,8 +1013,11 @@ static int CheckOtherHTTPHeaders(
|
|||||||
*
|
*
|
||||||
* \return
|
* \return
|
||||||
* \li \c HTTP_BAD_REQUEST
|
* \li \c HTTP_BAD_REQUEST
|
||||||
* \li \c UPNP_E_OUTOF_MEMORY
|
* \li \c HTTP_INTERNAL_SERVER_ERROR
|
||||||
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
||||||
|
* \li \c HTTP_FORBIDDEN
|
||||||
|
* \li \c HTTP_NOT_FOUND
|
||||||
|
* \li \c HTTP_NOT_ACCEPTABLE
|
||||||
* \li \c HTTP_OK
|
* \li \c HTTP_OK
|
||||||
*/
|
*/
|
||||||
static int process_request(
|
static int process_request(
|
||||||
@@ -1202,14 +1204,15 @@ static int process_request(
|
|||||||
}
|
}
|
||||||
RespInstr->ReadSendSize = finfo.file_length;
|
RespInstr->ReadSendSize = finfo.file_length;
|
||||||
/* Check other header field. */
|
/* Check other header field. */
|
||||||
if ((err_code =
|
if ((code =
|
||||||
CheckOtherHTTPHeaders(req, RespInstr,
|
CheckOtherHTTPHeaders(req, RespInstr,
|
||||||
finfo.file_length)) != HTTP_OK) {
|
finfo.file_length)) != HTTP_OK) {
|
||||||
|
err_code = code;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
if (req->method == HTTPMETHOD_POST) {
|
if (req->method == HTTPMETHOD_POST) {
|
||||||
*rtype = RESP_POST;
|
*rtype = RESP_POST;
|
||||||
err_code = UPNP_E_SUCCESS;
|
err_code = HTTP_OK;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
/*extra_headers = UpnpFileInfo_get_ExtraHeaders(finfo); */
|
/*extra_headers = UpnpFileInfo_get_ExtraHeaders(finfo); */
|
||||||
@@ -1247,7 +1250,6 @@ static int process_request(
|
|||||||
}
|
}
|
||||||
} else if (RespInstr->IsRangeActive && !RespInstr->IsChunkActive) {
|
} else if (RespInstr->IsRangeActive && !RespInstr->IsChunkActive) {
|
||||||
/* Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
/* Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
||||||
/* Transfer-Encoding: chunked */
|
|
||||||
if (http_MakeMessage(headers, resp_major, resp_minor,
|
if (http_MakeMessage(headers, resp_major, resp_minor,
|
||||||
"R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc",
|
"R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc",
|
||||||
HTTP_PARTIAL_CONTENT, /* status code */
|
HTTP_PARTIAL_CONTENT, /* status code */
|
||||||
@@ -1261,7 +1263,6 @@ static int process_request(
|
|||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
} else if (!RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
|
} else if (!RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
|
||||||
/* Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
|
||||||
/* Transfer-Encoding: chunked */
|
/* Transfer-Encoding: chunked */
|
||||||
if (http_MakeMessage(headers, resp_major, resp_minor,
|
if (http_MakeMessage(headers, resp_major, resp_minor,
|
||||||
"RK" "TLD" "s" "tcS" "Xc" "sCc",
|
"RK" "TLD" "s" "tcS" "Xc" "sCc",
|
||||||
@@ -1276,8 +1277,6 @@ static int process_request(
|
|||||||
} else {
|
} else {
|
||||||
/* !RespInstr->IsRangeActive && !RespInstr->IsChunkActive */
|
/* !RespInstr->IsRangeActive && !RespInstr->IsChunkActive */
|
||||||
if (RespInstr->ReadSendSize >= 0) {
|
if (RespInstr->ReadSendSize >= 0) {
|
||||||
/* Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
|
||||||
/* Transfer-Encoding: chunked */
|
|
||||||
if (http_MakeMessage(headers, resp_major, resp_minor,
|
if (http_MakeMessage(headers, resp_major, resp_minor,
|
||||||
"R" "N" "TLD" "s" "tcS" "Xc" "sCc",
|
"R" "N" "TLD" "s" "tcS" "Xc" "sCc",
|
||||||
HTTP_OK, /* status code */
|
HTTP_OK, /* status code */
|
||||||
@@ -1291,8 +1290,6 @@ static int process_request(
|
|||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Content-Range: bytes 222-3333/4000 HTTP_PARTIAL_CONTENT */
|
|
||||||
/* Transfer-Encoding: chunked */
|
|
||||||
if (http_MakeMessage(headers, resp_major, resp_minor,
|
if (http_MakeMessage(headers, resp_major, resp_minor,
|
||||||
"R" "TLD" "s" "tcS" "Xc" "sCc",
|
"R" "TLD" "s" "tcS" "Xc" "sCc",
|
||||||
HTTP_OK, /* status code */
|
HTTP_OK, /* status code */
|
||||||
@@ -1322,12 +1319,12 @@ static int process_request(
|
|||||||
if (req->method == HTTPMETHOD_SIMPLEGET) {
|
if (req->method == HTTPMETHOD_SIMPLEGET) {
|
||||||
membuffer_destroy(headers);
|
membuffer_destroy(headers);
|
||||||
}
|
}
|
||||||
err_code = UPNP_E_SUCCESS;
|
err_code = HTTP_OK;
|
||||||
|
|
||||||
error_handler:
|
error_handler:
|
||||||
free(request_doc);
|
free(request_doc);
|
||||||
ixmlFreeDOMString(finfo.content_type);
|
ixmlFreeDOMString(finfo.content_type);
|
||||||
if (err_code != UPNP_E_SUCCESS && alias_grabbed) {
|
if (err_code != HTTP_OK && alias_grabbed) {
|
||||||
alias_release(alias);
|
alias_release(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1340,7 +1337,8 @@ static int process_request(
|
|||||||
* \return
|
* \return
|
||||||
* \li \c HTTP_INTERNAL_SERVER_ERROR
|
* \li \c HTTP_INTERNAL_SERVER_ERROR
|
||||||
* \li \c HTTP_UNAUTHORIZED
|
* \li \c HTTP_UNAUTHORIZED
|
||||||
* \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
|
* \li \c HTTP_BAD_REQUEST
|
||||||
|
* \li \c HTTP_SERVICE_UNAVAILABLE
|
||||||
* \li \c HTTP_OK
|
* \li \c HTTP_OK
|
||||||
*/
|
*/
|
||||||
static int http_RecvPostMessage(
|
static int http_RecvPostMessage(
|
||||||
@@ -1426,7 +1424,7 @@ static int http_RecvPostMessage(
|
|||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret_code = num_read;
|
ret_code = HTTP_SERVICE_UNAVAILABLE;
|
||||||
goto ExitFunction;
|
goto ExitFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1489,7 +1487,7 @@ void web_server_callback(http_parser_t *parser, INOUT http_message_t *req,
|
|||||||
/*the type of request. */
|
/*the type of request. */
|
||||||
ret = process_request(req, &rtype, &headers, &filename, &xmldoc,
|
ret = process_request(req, &rtype, &headers, &filename, &xmldoc,
|
||||||
&RespInstr);
|
&RespInstr);
|
||||||
if (ret != UPNP_E_SUCCESS) {
|
if (ret != HTTP_OK) {
|
||||||
/* send error code */
|
/* send error code */
|
||||||
http_SendStatusResponse(info, ret, req->major_version,
|
http_SendStatusResponse(info, ret, req->major_version,
|
||||||
req->minor_version);
|
req->minor_version);
|
||||||
@@ -1531,7 +1529,7 @@ void web_server_callback(http_parser_t *parser, INOUT http_message_t *req,
|
|||||||
/* Send response. */
|
/* Send response. */
|
||||||
http_MakeMessage(&headers, 1, 1,
|
http_MakeMessage(&headers, 1, 1,
|
||||||
"RTLSXcCc",
|
"RTLSXcCc",
|
||||||
ret, "text/html", X_USER_AGENT);
|
ret, "text/html", &RespInstr, X_USER_AGENT);
|
||||||
http_SendMessage(info, &timeout, "b",
|
http_SendMessage(info, &timeout, "b",
|
||||||
headers.buf, headers.length);
|
headers.buf, headers.length);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ static int parse_hostport(
|
|||||||
|
|
||||||
ret = getaddrinfo(srvname, NULL, &hints, &res0);
|
ret = getaddrinfo(srvname, NULL, &hints, &res0);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
for (res = res0; res && !ret; res = res->ai_next) {
|
for (res = res0; res; res = res->ai_next) {
|
||||||
switch (res->ai_family) {
|
switch (res->ai_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
@@ -395,12 +395,10 @@ static int parse_hostport(
|
|||||||
memcpy(&out->IPaddress,
|
memcpy(&out->IPaddress,
|
||||||
res->ai_addr,
|
res->ai_addr,
|
||||||
res->ai_addrlen);
|
res->ai_addrlen);
|
||||||
ret=1;
|
goto found;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
found:
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
/* Didn't find an AF_INET or AF_INET6 address. */
|
/* Didn't find an AF_INET or AF_INET6 address. */
|
||||||
@@ -512,68 +510,81 @@ int remove_escaped_chars(INOUT char *in, INOUT size_t *size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int remove_dots(char *in, size_t size)
|
static UPNP_INLINE int is_end_path(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case '?':
|
||||||
|
case '#':
|
||||||
|
case '\0':
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function directly implements the "Remove Dot Segments"
|
||||||
|
* algorithm described in RFC 3986 section 5.2.4. */
|
||||||
|
int remove_dots(char *buf, size_t size)
|
||||||
{
|
{
|
||||||
char *copyTo = in;
|
char *in = buf;
|
||||||
char *copyFrom = in;
|
char *out = buf;
|
||||||
char *max = in + size;
|
char *max = buf + size;
|
||||||
char **Segments = NULL;
|
|
||||||
int lastSegment = -1;
|
|
||||||
|
|
||||||
Segments = malloc( sizeof( char * ) * size );
|
while (!is_end_path(in[0])) {
|
||||||
|
assert (buf <= out);
|
||||||
|
assert (out <= in);
|
||||||
|
assert (in < max);
|
||||||
|
|
||||||
if( Segments == NULL )
|
/* case 2.A: */
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
if (strncmp(in, "./", 2) == 0) {
|
||||||
|
in += 2;
|
||||||
Segments[0] = NULL;
|
} else if (strncmp(in, "../", 3) == 0) {
|
||||||
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
|
in += 3;
|
||||||
"REMOVE_DOTS: before: %s\n", in );
|
/* case 2.B: */
|
||||||
while( ( copyFrom < max ) && ( *copyFrom != '?' )
|
} else if (strncmp(in, "/./", 3) == 0) {
|
||||||
&& ( *copyFrom != '#' ) ) {
|
in += 2;
|
||||||
|
} else if (strncmp(in, "/.", 2) == 0 && is_end_path(in[2])) {
|
||||||
if( ( ( *copyFrom ) == '.' )
|
in += 1;
|
||||||
&& ( ( copyFrom == in ) || ( *( copyFrom - 1 ) == '/' ) ) ) {
|
in[0] = '/';
|
||||||
if( ( copyFrom + 1 == max )
|
/* case 2.C: */
|
||||||
|| ( *( copyFrom + 1 ) == '/' ) ) {
|
} else if (strncmp(in, "/../", 4) == 0 || (strncmp(in, "/..", 3) == 0 && is_end_path(in[3]))) {
|
||||||
|
/* Make the next character in the input buffer a '/': */
|
||||||
copyFrom += 2;
|
if (is_end_path(in[3])) { /* terminating "/.." case */
|
||||||
continue;
|
in += 2;
|
||||||
} else if( ( *( copyFrom + 1 ) == '.' )
|
in[0] = '/';
|
||||||
&& ( ( copyFrom + 2 == max )
|
} else { /* "/../" prefix case */
|
||||||
|| ( *( copyFrom + 2 ) == '/' ) ) ) {
|
in += 3;
|
||||||
copyFrom += 3;
|
|
||||||
|
|
||||||
if( lastSegment > 0 ) {
|
|
||||||
copyTo = Segments[--lastSegment];
|
|
||||||
} else {
|
|
||||||
free( Segments );
|
|
||||||
/*TRACE("ERROR RESOLVING URL, ../ at ROOT"); */
|
|
||||||
return UPNP_E_INVALID_URL;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
/* Trim the last component from the output buffer, or empty it. */
|
||||||
|
while (buf < out)
|
||||||
if( ( *copyFrom ) == '/' ) {
|
if (*--out == '/')
|
||||||
|
break;
|
||||||
lastSegment++;
|
#ifdef DEBUG
|
||||||
Segments[lastSegment] = copyTo + 1;
|
if (out < in)
|
||||||
}
|
out[0] = '\0';
|
||||||
( *copyTo ) = ( *copyFrom );
|
#endif
|
||||||
copyTo++;
|
/* case 2.D: */
|
||||||
copyFrom++;
|
} else if (strncmp(in, ".", 1) == 0 && is_end_path(in[1])) {
|
||||||
}
|
in += 1;
|
||||||
if( copyFrom < max ) {
|
} else if (strncmp(in, "..", 2) == 0 && is_end_path(in[2])) {
|
||||||
while( copyFrom < max ) {
|
in += 2;
|
||||||
( *copyTo ) = ( *copyFrom );
|
/* case 2.E */
|
||||||
copyTo++;
|
} else {
|
||||||
copyFrom++;
|
/* move initial '/' character (if any) */
|
||||||
|
if (in[0] == '/')
|
||||||
|
*out++ = *in++;
|
||||||
|
/* move first segment up to, but not including, the next '/' character */
|
||||||
|
while (in < max && in[0] != '/' && !is_end_path(in[0]))
|
||||||
|
*out++ = *in++;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (out < in)
|
||||||
|
out[0] = '\0';
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
( *copyTo ) = 0;
|
while (in < max)
|
||||||
free( Segments );
|
*out++ = *in++;
|
||||||
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
|
if (out < max)
|
||||||
"REMOVE_DOTS: after: %s\n", in );
|
out[0] = '\0';
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,115 +593,113 @@ char *resolve_rel_url(char *base_url, char *rel_url)
|
|||||||
{
|
{
|
||||||
uri_type base;
|
uri_type base;
|
||||||
uri_type rel;
|
uri_type rel;
|
||||||
|
int rv;
|
||||||
|
|
||||||
size_t i = (size_t)0;
|
if (!base_url) {
|
||||||
char *finger = NULL;
|
if (!rel_url)
|
||||||
|
|
||||||
char *last_slash = NULL;
|
|
||||||
|
|
||||||
char *out = NULL;
|
|
||||||
|
|
||||||
if( base_url && rel_url ) {
|
|
||||||
out =
|
|
||||||
( char * )malloc( strlen( base_url ) + strlen( rel_url ) + (size_t)2 );
|
|
||||||
} else {
|
|
||||||
if( rel_url )
|
|
||||||
return strdup( rel_url );
|
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
return strdup(rel_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( out == NULL ) {
|
size_t len_rel = strlen(rel_url);
|
||||||
|
if (parse_uri(rel_url, len_rel, &rel) != HTTP_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (rel.type == (enum uriType)ABSOLUTE)
|
||||||
|
return strdup(rel_url);
|
||||||
|
|
||||||
|
size_t len_base = strlen(base_url);
|
||||||
|
if ((parse_uri(base_url, len_base, &base) != HTTP_SUCCESS)
|
||||||
|
|| (base.type != (enum uriType)ABSOLUTE))
|
||||||
|
return NULL;
|
||||||
|
if (len_rel == (size_t)0)
|
||||||
|
return strdup(base_url);
|
||||||
|
|
||||||
|
size_t len = len_base + len_rel + (size_t)2;
|
||||||
|
char *out = (char *)malloc(len);
|
||||||
|
if (out == NULL)
|
||||||
|
return NULL;
|
||||||
|
memset(out, 0, len);
|
||||||
|
char *out_finger = out;
|
||||||
|
|
||||||
|
/* scheme */
|
||||||
|
rv = snprintf(out_finger, len, "%.*s:", (int)base.scheme.size, base.scheme.buff);
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
|
|
||||||
|
/* authority */
|
||||||
|
if (rel.hostport.text.size > (size_t)0) {
|
||||||
|
rv = snprintf(out_finger, len, "%s", rel_url);
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
if (base.hostport.text.size > (size_t)0) {
|
||||||
|
rv = snprintf(out_finger, len, "//%.*s", (int)base.hostport.text.size, base.hostport.text.buff);
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
}
|
}
|
||||||
memset( out, 0, strlen( base_url ) + strlen( rel_url ) + (size_t)2 );
|
|
||||||
|
|
||||||
if( ( parse_uri( rel_url, strlen( rel_url ), &rel ) ) == HTTP_SUCCESS ) {
|
/* path */
|
||||||
|
char *path = out_finger;
|
||||||
if( rel.type == ( enum uriType) ABSOLUTE ) {
|
if (rel.path_type == (enum pathType)ABS_PATH) {
|
||||||
|
rv = snprintf(out_finger, len, "%s", rel_url);
|
||||||
strncpy( out, rel_url, strlen ( rel_url ) );
|
} else if (base.pathquery.size == (size_t)0) {
|
||||||
} else {
|
rv = snprintf(out_finger, len, "/%s", rel_url);
|
||||||
|
|
||||||
if( ( parse_uri( base_url, strlen( base_url ), &base ) ==
|
|
||||||
HTTP_SUCCESS )
|
|
||||||
&& ( base.type == ( enum uriType ) ABSOLUTE ) ) {
|
|
||||||
|
|
||||||
if( strlen( rel_url ) == (size_t)0 ) {
|
|
||||||
strncpy( out, base_url, strlen ( base_url ) );
|
|
||||||
} else {
|
|
||||||
char *out_finger = out;
|
|
||||||
assert( base.scheme.size + (size_t)1 /* ':' */ <= strlen ( base_url ) );
|
|
||||||
memcpy( out, base.scheme.buff, base.scheme.size );
|
|
||||||
out_finger += base.scheme.size;
|
|
||||||
( *out_finger ) = ':';
|
|
||||||
out_finger++;
|
|
||||||
|
|
||||||
if( rel.hostport.text.size > (size_t)0 ) {
|
|
||||||
snprintf( out_finger, strlen( rel_url ) + (size_t)1,
|
|
||||||
"%s", rel_url );
|
|
||||||
} else {
|
|
||||||
if( base.hostport.text.size > (size_t)0 ) {
|
|
||||||
assert( base.scheme.size + (size_t)1
|
|
||||||
+ base.hostport.text.size + (size_t)2 /* "//" */ <= strlen ( base_url ) );
|
|
||||||
memcpy( out_finger, "//", (size_t)2 );
|
|
||||||
out_finger += 2;
|
|
||||||
memcpy( out_finger, base.hostport.text.buff,
|
|
||||||
base.hostport.text.size );
|
|
||||||
out_finger += base.hostport.text.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rel.path_type == ( enum pathType ) ABS_PATH ) {
|
|
||||||
strncpy( out_finger, rel_url, strlen ( rel_url ) );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
char temp_path = '/';
|
|
||||||
|
|
||||||
if( base.pathquery.size == (size_t)0 ) {
|
|
||||||
base.pathquery.size = (size_t)1;
|
|
||||||
base.pathquery.buff = &temp_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( base.scheme.size + (size_t)1 + base.hostport.text.size + (size_t)2
|
|
||||||
+ base.pathquery.size <= strlen ( base_url ) + (size_t)1 /* temp_path */);
|
|
||||||
finger = out_finger;
|
|
||||||
last_slash = finger;
|
|
||||||
i = (size_t)0;
|
|
||||||
while( ( i < base.pathquery.size ) &&
|
|
||||||
( base.pathquery.buff[i] != '?' ) ) {
|
|
||||||
( *finger ) = base.pathquery.buff[i];
|
|
||||||
if( base.pathquery.buff[i] == '/' )
|
|
||||||
last_slash = finger + 1;
|
|
||||||
i++;
|
|
||||||
finger++;
|
|
||||||
|
|
||||||
}
|
|
||||||
strncpy( last_slash, rel_url, strlen ( rel_url ) );
|
|
||||||
if( remove_dots( out_finger,
|
|
||||||
strlen( out_finger ) ) !=
|
|
||||||
UPNP_E_SUCCESS ) {
|
|
||||||
free(out);
|
|
||||||
/* free(rel_url); */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
free(out);
|
|
||||||
/* free(rel_url); */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
free(out);
|
if (rel.pathquery.size == (size_t)0) {
|
||||||
/* free(rel_url); */
|
rv = snprintf(out_finger, len, "%.*s", (int)base.pathquery.size, base.pathquery.buff);
|
||||||
return NULL;
|
} else {
|
||||||
}
|
if (len < base.pathquery.size)
|
||||||
|
goto error;
|
||||||
|
size_t i = (size_t)0, prefix = (size_t)1;
|
||||||
|
while (i < base.pathquery.size) {
|
||||||
|
out_finger[i] = base.pathquery.buff[i];
|
||||||
|
switch (base.pathquery.buff[i++]) {
|
||||||
|
case '/':
|
||||||
|
prefix = i;
|
||||||
|
/* fall-through */
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
case '?': /* query */
|
||||||
|
if (rel.pathquery.buff[0] == '?')
|
||||||
|
prefix = --i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out_finger += prefix;
|
||||||
|
len -= prefix;
|
||||||
|
rv = snprintf(out_finger, len, "%.*s", (int)rel.pathquery.size, rel.pathquery.buff);
|
||||||
|
}
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
|
|
||||||
|
/* fragment */
|
||||||
|
if (rel.fragment.size > (size_t)0)
|
||||||
|
rv = snprintf(out_finger, len, "#%.*s", (int)rel.fragment.size, rel.fragment.buff);
|
||||||
|
else if (base.fragment.size > (size_t)0)
|
||||||
|
rv = snprintf(out_finger, len, "#%.*s", (int)base.fragment.size, base.fragment.buff);
|
||||||
|
else
|
||||||
|
rv = 0;
|
||||||
|
}
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
|
|
||||||
|
if (remove_dots(path, out_finger - path) != UPNP_E_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* free(rel_url); */
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -301,15 +301,16 @@ FindServiceEventURLPath( service_table * table,
|
|||||||
|
|
||||||
if( ( table )
|
if( ( table )
|
||||||
&&
|
&&
|
||||||
( parse_uri
|
( parse_uri( eventURLPath,
|
||||||
( eventURLPath, strlen( eventURLPath ), &parsed_url_in ) ) ) {
|
strlen( eventURLPath ),
|
||||||
|
&parsed_url_in ) == HTTP_SUCCESS ) ) {
|
||||||
|
|
||||||
finger = table->serviceList;
|
finger = table->serviceList;
|
||||||
while( finger ) {
|
while( finger ) {
|
||||||
if( finger->eventURL )
|
if( finger->eventURL )
|
||||||
if( ( parse_uri
|
if( ( parse_uri
|
||||||
( finger->eventURL, strlen( finger->eventURL ),
|
( finger->eventURL, strlen( finger->eventURL ),
|
||||||
&parsed_url ) ) ) {
|
&parsed_url ) == HTTP_SUCCESS ) ) {
|
||||||
|
|
||||||
if( !token_cmp
|
if( !token_cmp
|
||||||
( &parsed_url.pathquery,
|
( &parsed_url.pathquery,
|
||||||
@@ -354,13 +355,13 @@ FindServiceControlURLPath( service_table * table,
|
|||||||
&&
|
&&
|
||||||
( parse_uri
|
( parse_uri
|
||||||
( controlURLPath, strlen( controlURLPath ),
|
( controlURLPath, strlen( controlURLPath ),
|
||||||
&parsed_url_in ) ) ) {
|
&parsed_url_in ) == HTTP_SUCCESS ) ) {
|
||||||
finger = table->serviceList;
|
finger = table->serviceList;
|
||||||
while( finger ) {
|
while( finger ) {
|
||||||
if( finger->controlURL )
|
if( finger->controlURL )
|
||||||
if( ( parse_uri
|
if( ( parse_uri
|
||||||
( finger->controlURL, strlen( finger->controlURL ),
|
( finger->controlURL, strlen( finger->controlURL ),
|
||||||
&parsed_url ) ) ) {
|
&parsed_url ) == HTTP_SUCCESS) ) {
|
||||||
if( !token_cmp
|
if( !token_cmp
|
||||||
( &parsed_url.pathquery,
|
( &parsed_url.pathquery,
|
||||||
&parsed_url_in.pathquery ) )
|
&parsed_url_in.pathquery ) )
|
||||||
|
|||||||
@@ -79,6 +79,10 @@
|
|||||||
#define HTTP_SERVICE_UNAVAILABLE 503
|
#define HTTP_SERVICE_UNAVAILABLE 503
|
||||||
#define HTTP_GATEWAY_TIMEOUT 504
|
#define HTTP_GATEWAY_TIMEOUT 504
|
||||||
#define HTTP_HTTP_VERSION_NOT_SUPPORTED 505
|
#define HTTP_HTTP_VERSION_NOT_SUPPORTED 505
|
||||||
|
#define HTTP_VARIANT_ALSO_NEGOTIATES 506
|
||||||
|
#define HTTP_INSUFFICIENT_STORAGE 507
|
||||||
|
#define HTTP_LOOP_DETECTED 508
|
||||||
|
#define HTTP_NOT_EXTENDED 510
|
||||||
|
|
||||||
/* HTTP lib error codes */
|
/* HTTP lib error codes */
|
||||||
|
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ get_response_value( IN http_message_t * hmsg,
|
|||||||
if (!temp_str)
|
if (!temp_str)
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
*upnp_error_code = atoi(temp_str);
|
*upnp_error_code = atoi(temp_str);
|
||||||
if (*upnp_error_code < 400) {
|
if (*upnp_error_code > 400) {
|
||||||
err_code = *upnp_error_code;
|
err_code = *upnp_error_code;
|
||||||
goto error_handler; /* bad SOAP error code */
|
goto error_handler; /* bad SOAP error code */
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -291,8 +291,9 @@ void ssdp_handle_ctrlpt_msg(http_message_t *hmsg, struct sockaddr_storage *dest_
|
|||||||
TPJobSetFreeFunction(&job,
|
TPJobSetFreeFunction(&job,
|
||||||
(free_routine)
|
(free_routine)
|
||||||
free);
|
free);
|
||||||
ThreadPoolAdd(&gRecvThreadPool, &job,
|
if (ThreadPoolAdd(&gRecvThreadPool, &job, NULL) != 0) {
|
||||||
NULL);
|
free(threadData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node = ListNext(&ctrlpt_info->SsdpSearchList, node);
|
node = ListNext(&ctrlpt_info->SsdpSearchList, node);
|
||||||
|
|||||||
@@ -814,7 +814,7 @@ static int create_ssdp_sock_v4(
|
|||||||
ret = UPNP_E_SOCKET_ERROR;
|
ret = UPNP_E_SOCKET_ERROR;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
#if defined(BSD) || defined(__OSX__) || defined(__APPLE__)
|
#if (defined(BSD) && !defined(__GNU__)) || defined(__OSX__) || defined(__APPLE__)
|
||||||
onOff = 1;
|
onOff = 1;
|
||||||
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||||
(char *)&onOff, sizeof(onOff));
|
(char *)&onOff, sizeof(onOff));
|
||||||
@@ -956,7 +956,7 @@ static int create_ssdp_sock_v6(
|
|||||||
ret = UPNP_E_SOCKET_ERROR;
|
ret = UPNP_E_SOCKET_ERROR;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
#if defined(BSD) || defined(__OSX__) || defined(__APPLE__)
|
#if (defined(BSD) && !defined(__GNU__)) || defined(__OSX__) || defined(__APPLE__)
|
||||||
onOff = 1;
|
onOff = 1;
|
||||||
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||||
(char *)&onOff, sizeof(onOff));
|
(char *)&onOff, sizeof(onOff));
|
||||||
@@ -1069,7 +1069,7 @@ static int create_ssdp_sock_v6_ula_gua(
|
|||||||
ret = UPNP_E_SOCKET_ERROR;
|
ret = UPNP_E_SOCKET_ERROR;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
#if defined(BSD) || defined(__OSX__) || defined(__APPLE__)
|
#if (defined(BSD) && !defined(__GNU__)) || defined(__OSX__) || defined(__APPLE__)
|
||||||
onOff = 1;
|
onOff = 1;
|
||||||
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||||
(char *)&onOff, sizeof(onOff));
|
(char *)&onOff, sizeof(onOff));
|
||||||
|
|||||||
@@ -143,15 +143,12 @@ static UPNP_INLINE int calc_alias(
|
|||||||
aliasPtr = alias + 1;
|
aliasPtr = alias + 1;
|
||||||
else
|
else
|
||||||
aliasPtr = alias;
|
aliasPtr = alias;
|
||||||
new_alias_len = root_len + strlen(temp_str) + strlen(aliasPtr);
|
new_alias_len = root_len + strlen(temp_str) + strlen(aliasPtr) + (size_t)1;
|
||||||
alias_temp = malloc(new_alias_len + (size_t)1);
|
alias_temp = malloc(new_alias_len);
|
||||||
if (alias_temp == NULL)
|
if (alias_temp == NULL)
|
||||||
return UPNP_E_OUTOF_MEMORY;
|
return UPNP_E_OUTOF_MEMORY;
|
||||||
memset(alias_temp, 0, new_alias_len + (size_t)1);
|
memset(alias_temp, 0, new_alias_len);
|
||||||
strncpy(alias_temp, rootPath, root_len);
|
snprintf(alias_temp, new_alias_len, "%s%s%s", rootPath, temp_str, aliasPtr);
|
||||||
alias_temp[root_len] = '\0';
|
|
||||||
strncat(alias_temp, temp_str, strlen(temp_str));
|
|
||||||
strncat(alias_temp, aliasPtr, strlen(aliasPtr));
|
|
||||||
|
|
||||||
*newAlias = alias_temp;
|
*newAlias = alias_temp;
|
||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
@@ -186,14 +183,10 @@ static UPNP_INLINE int calc_descURL(
|
|||||||
assert(ipPortStr != NULL && strlen(ipPortStr) > 0);
|
assert(ipPortStr != NULL && strlen(ipPortStr) > 0);
|
||||||
assert(alias != NULL && strlen(alias) > 0);
|
assert(alias != NULL && strlen(alias) > 0);
|
||||||
|
|
||||||
len = strlen(http_scheme) + strlen(ipPortStr) + strlen(alias);
|
len = strlen(http_scheme) + strlen(ipPortStr) + strlen(alias) + (size_t)1;
|
||||||
if (len > ((size_t)LINE_SIZE - (size_t)1))
|
if (len > (size_t)LINE_SIZE)
|
||||||
return UPNP_E_URL_TOO_BIG;
|
return UPNP_E_URL_TOO_BIG;
|
||||||
strncpy(descURL, http_scheme, strlen(http_scheme));
|
snprintf(descURL, len, "%s%s%s", http_scheme, ipPortStr, alias);
|
||||||
descURL[strlen(http_scheme)] = '\0';
|
|
||||||
strncat(descURL, ipPortStr, strlen(ipPortStr));
|
|
||||||
strncat(descURL, alias, strlen(alias));
|
|
||||||
descURL[len] = '\0';
|
|
||||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
"desc url: %s\n", descURL);
|
"desc url: %s\n", descURL);
|
||||||
|
|
||||||
@@ -267,6 +260,7 @@ static int config_description_doc(
|
|||||||
err_code =
|
err_code =
|
||||||
ixmlNode_appendChild(rootNode, (IXML_Node *) element);
|
ixmlNode_appendChild(rootNode, (IXML_Node *) element);
|
||||||
if (err_code != IXML_SUCCESS) {
|
if (err_code != IXML_SUCCESS) {
|
||||||
|
err_code = UPNP_E_INVALID_DESC;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
textNode =
|
textNode =
|
||||||
@@ -277,6 +271,7 @@ static int config_description_doc(
|
|||||||
err_code =
|
err_code =
|
||||||
ixmlNode_appendChild((IXML_Node *) element, textNode);
|
ixmlNode_appendChild((IXML_Node *) element, textNode);
|
||||||
if (err_code != IXML_SUCCESS) {
|
if (err_code != IXML_SUCCESS) {
|
||||||
|
err_code = UPNP_E_INTERNAL_ERROR;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -327,6 +322,7 @@ static int config_description_doc(
|
|||||||
}
|
}
|
||||||
err_code = ixmlNode_setNodeValue(textNode, url_str.buf);
|
err_code = ixmlNode_setNodeValue(textNode, url_str.buf);
|
||||||
if (err_code != IXML_SUCCESS) {
|
if (err_code != IXML_SUCCESS) {
|
||||||
|
err_code = UPNP_E_OUTOF_MEMORY;
|
||||||
goto error_handler;
|
goto error_handler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
131
upnp/test/test_url.c
Normal file
131
upnp/test/test_url.c
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "upnp.h"
|
||||||
|
#include "upnptools.h"
|
||||||
|
|
||||||
|
struct test {
|
||||||
|
const char *base;
|
||||||
|
const char *rel;
|
||||||
|
const char *expect;
|
||||||
|
int line;
|
||||||
|
int error;
|
||||||
|
};
|
||||||
|
#define TEST(BaseURL, RelURL, expect, ...) {BaseURL, RelURL, expect, __LINE__, ##__VA_ARGS__}
|
||||||
|
|
||||||
|
static int
|
||||||
|
result(const struct test *test)
|
||||||
|
{
|
||||||
|
char *absurl = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = UpnpResolveURL2(test->base, test->rel, &absurl);
|
||||||
|
if (ret == test->error && (test->expect == NULL || strcmp(test->expect, absurl) == 0)) {
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
printf("%s:%d: '%s' | '%s' -> '%s' != '%s' (%d)\n", __FILE__, test->line, test->base, test->rel, absurl, test->expect, ret);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
free(absurl);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The URLs must be resolvale! */
|
||||||
|
static const char ABS_URL1[] = "http://www.libupnp.org/path1/";
|
||||||
|
static const char ABS_URL2[] = "http://www.libupnp.org/path1/path1";
|
||||||
|
static const char ABS_URL3[] = "http://localhost/path1/";
|
||||||
|
static const char ABS_URL4[] = "http://127.0.0.1/path1/";
|
||||||
|
static const char ABS_URL5[] = "http://127.0.0.1:6544/path1/";
|
||||||
|
static const char ABS_URL6[] = "http://[::1]:6544/path1/";
|
||||||
|
|
||||||
|
static const char REL_URL1[] = "//localhost/path2";
|
||||||
|
static const char REL_URL2[] = "/path3";
|
||||||
|
static const char REL_URL3[] = "path4";
|
||||||
|
static const char REL_URL4[] = "../path5";
|
||||||
|
static const char REL_URL5[] = "?query1";
|
||||||
|
static const char REL_URL6[] = "#frag1";
|
||||||
|
|
||||||
|
static const char ABS_RFC[] = "http://localhost/b/c/d;p?q";
|
||||||
|
// s,\<a\>,localhost,
|
||||||
|
// s,//g\>,//127.0.0.1,
|
||||||
|
|
||||||
|
static const struct test RFC3986[] = {
|
||||||
|
// Errors
|
||||||
|
TEST(NULL, NULL, NULL, UPNP_E_INVALID_PARAM),
|
||||||
|
TEST(ABS_URL1, NULL, NULL, UPNP_E_INVALID_PARAM),
|
||||||
|
TEST("foo", "bar", NULL, UPNP_E_INVALID_URL),
|
||||||
|
// Custom
|
||||||
|
TEST(NULL, ABS_URL1, ABS_URL1),
|
||||||
|
TEST(ABS_URL1, ABS_URL2, ABS_URL2),
|
||||||
|
TEST(ABS_URL1, "", ABS_URL1),
|
||||||
|
TEST(ABS_URL1, REL_URL1, "http://localhost/path2"),
|
||||||
|
TEST(ABS_URL2, REL_URL1, "http://localhost/path2"),
|
||||||
|
TEST(ABS_URL1, REL_URL2, "http://www.libupnp.org/path3"),
|
||||||
|
TEST(ABS_URL2, REL_URL2, "http://www.libupnp.org/path3"),
|
||||||
|
TEST(ABS_URL1, REL_URL3, "http://www.libupnp.org/path1/path4"),
|
||||||
|
TEST(ABS_URL2, REL_URL3, "http://www.libupnp.org/path1/path4"),
|
||||||
|
TEST(ABS_URL1, REL_URL4, "http://www.libupnp.org/path5"),
|
||||||
|
TEST(ABS_URL2, REL_URL4, "http://www.libupnp.org/path5"),
|
||||||
|
TEST(ABS_URL1, REL_URL6, "http://www.libupnp.org/path1/#frag1"),
|
||||||
|
TEST(ABS_URL2, REL_URL6, "http://www.libupnp.org/path1/path1#frag1"),
|
||||||
|
TEST("http://127.0.0.1:6544/getDeviceDesc", "CDS_Event", "http://127.0.0.1:6544/CDS_Event"),
|
||||||
|
// <http://tools.ietf.org/html/rfc3986#section-5.4.1> Normal Examples
|
||||||
|
TEST(ABS_RFC, "g:h", "g:h"),
|
||||||
|
TEST(ABS_RFC, "g", "http://localhost/b/c/g"),
|
||||||
|
TEST(ABS_RFC, "./g", "http://localhost/b/c/g"),
|
||||||
|
TEST(ABS_RFC, "g/", "http://localhost/b/c/g/"),
|
||||||
|
TEST(ABS_RFC, "/g", "http://localhost/g"),
|
||||||
|
TEST(ABS_RFC, "//127.0.0.1", "http://127.0.0.1"),
|
||||||
|
TEST(ABS_RFC, "?y", "http://localhost/b/c/d;p?y"),
|
||||||
|
TEST(ABS_RFC, "g?y", "http://localhost/b/c/g?y"),
|
||||||
|
TEST(ABS_RFC, "#s", "http://localhost/b/c/d;p?q#s"),
|
||||||
|
TEST(ABS_RFC, "g#s", "http://localhost/b/c/g#s"),
|
||||||
|
TEST(ABS_RFC, "g?y#s", "http://localhost/b/c/g?y#s"),
|
||||||
|
TEST(ABS_RFC, ";x", "http://localhost/b/c/;x"),
|
||||||
|
TEST(ABS_RFC, "g;x", "http://localhost/b/c/g;x"),
|
||||||
|
TEST(ABS_RFC, "g;x?y#s", "http://localhost/b/c/g;x?y#s"),
|
||||||
|
TEST(ABS_RFC, "", "http://localhost/b/c/d;p?q"),
|
||||||
|
TEST(ABS_RFC, ".", "http://localhost/b/c/"),
|
||||||
|
TEST(ABS_RFC, "./", "http://localhost/b/c/"),
|
||||||
|
TEST(ABS_RFC, "..", "http://localhost/b/"),
|
||||||
|
TEST(ABS_RFC, "../", "http://localhost/b/"),
|
||||||
|
TEST(ABS_RFC, "../g", "http://localhost/b/g"),
|
||||||
|
TEST(ABS_RFC, "../..", "http://localhost/"),
|
||||||
|
TEST(ABS_RFC, "../../", "http://localhost/"),
|
||||||
|
TEST(ABS_RFC, "../../g", "http://localhost/g"),
|
||||||
|
// <http://tools.ietf.org/html/rfc3986#section-5.4.2> Abnormal Examples
|
||||||
|
TEST(ABS_RFC, "../../../g", "http://localhost/g"),
|
||||||
|
TEST(ABS_RFC, "../../../../g", "http://localhost/g"),
|
||||||
|
TEST(ABS_RFC, "/./g", "http://localhost/g"),
|
||||||
|
TEST(ABS_RFC, "/../g", "http://localhost/g"),
|
||||||
|
TEST(ABS_RFC, "g.", "http://localhost/b/c/g."),
|
||||||
|
TEST(ABS_RFC, ".g", "http://localhost/b/c/.g"),
|
||||||
|
TEST(ABS_RFC, "g..", "http://localhost/b/c/g.."),
|
||||||
|
TEST(ABS_RFC, "..g", "http://localhost/b/c/..g"),
|
||||||
|
TEST(ABS_RFC, "./../g", "http://localhost/b/g"),
|
||||||
|
TEST(ABS_RFC, "./g/.", "http://localhost/b/c/g/"),
|
||||||
|
TEST(ABS_RFC, "g/./h", "http://localhost/b/c/g/h"),
|
||||||
|
TEST(ABS_RFC, "g/../h", "http://localhost/b/c/h"),
|
||||||
|
TEST(ABS_RFC, "g;x=1/./y", "http://localhost/b/c/g;x=1/y"),
|
||||||
|
TEST(ABS_RFC, "g;x=1/../y", "http://localhost/b/c/y"),
|
||||||
|
TEST(ABS_RFC, "g?y/./x", "http://localhost/b/c/g?y/./x"),
|
||||||
|
TEST(ABS_RFC, "g?y/../x", "http://localhost/b/c/g?y/../x"),
|
||||||
|
TEST(ABS_RFC, "g#s/./x", "http://localhost/b/c/g#s/./x"),
|
||||||
|
TEST(ABS_RFC, "g#s/../x", "http://localhost/b/c/g#s/../x"),
|
||||||
|
TEST(ABS_RFC, "http:g", "http:g"),
|
||||||
|
};
|
||||||
|
#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a))
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(RFC3986); i++)
|
||||||
|
ret += result(&RFC3986[i]);
|
||||||
|
|
||||||
|
exit (ret ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gcc -o url-test -g url-test.c -I ixml/inc -I threadutil/inc -I upnp/inc upnp/.libs/libupnp.a -L ixml/.libs -lixml -L threadutil/.libs -lthreadutil -lpthread
|
||||||
Reference in New Issue
Block a user