diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-11-03 00:00:56 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2012-11-03 00:00:56 +0000 |
commit | df77815b8b94d487809e1b2786bbe729de4bfbb8 (patch) | |
tree | 8d59aa4f455f6010a95272f5c31b76d7ea4cb806 /apps/netutils | |
parent | 23e8d5321a4de9c08a5f9c1e3a919aa740acca78 (diff) | |
download | px4-firmware-df77815b8b94d487809e1b2786bbe729de4bfbb8.tar.gz px4-firmware-df77815b8b94d487809e1b2786bbe729de4bfbb8.tar.bz2 px4-firmware-df77815b8b94d487809e1b2786bbe729de4bfbb8.zip |
Add support for wget POST interface; from Darcy Gong
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5301 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/netutils')
-rw-r--r-- | apps/netutils/codecs/urldecode.c | 67 | ||||
-rw-r--r-- | apps/netutils/webclient/Kconfig | 5 | ||||
-rw-r--r-- | apps/netutils/webclient/webclient.c | 245 |
3 files changed, 294 insertions, 23 deletions
diff --git a/apps/netutils/codecs/urldecode.c b/apps/netutils/codecs/urldecode.c index 9b3b60955..90cc3301b 100644 --- a/apps/netutils/codecs/urldecode.c +++ b/apps/netutils/codecs/urldecode.c @@ -351,6 +351,73 @@ char *urldecode(const char *src, const int src_len, char *dest, int *dest_len) #endif /**************************************************************************** + * Name: urlencode_len + ****************************************************************************/ + +#ifdef CONFIG_CODECS_URLCODE +int urlencode_len(const char *src, const int src_len) +{ + const unsigned char *pSrc; + const unsigned char *pEnd; + int len = 0; + + pEnd = (unsigned char *)src + src_len; + for (pSrc = (unsigned char *)src; pSrc < pEnd; pSrc++) + { + if ((*pSrc >= '0' && *pSrc <= '9') || + (*pSrc >= 'a' && *pSrc <= 'z') || + (*pSrc >= 'A' && *pSrc <= 'Z') || + (*pSrc == '_' || *pSrc == '-' || *pSrc == '.' || *pSrc == '~' || *pSrc == ' ')) + { + len++; + } + else + { + len+=3; + } + } + + return len; +} +#endif + +/**************************************************************************** + * Name: urldecode_len + ****************************************************************************/ + +#ifdef CONFIG_CODECS_URLCODE +int urldecode_len(const char *src, const int src_len) +{ + const unsigned char *pSrc; + const unsigned char *pEnd; + int len = 0; + unsigned char cHigh; + unsigned char cLow; + + pSrc = (unsigned char *)src; + pEnd = (unsigned char *)src + src_len; + while (pSrc < pEnd) + { + if (*pSrc == '%' && pSrc + 2 < pEnd) + { + cHigh = *(pSrc + 1); + cLow = *(pSrc + 2); + + if (IS_HEX_CHAR(cHigh) && IS_HEX_CHAR(cLow)) + { + pSrc += 2; + } + } + + len++; + pSrc++; + } + + return len; +} +#endif + +/**************************************************************************** * Name: urlrawdecode * * Description: diff --git a/apps/netutils/webclient/Kconfig b/apps/netutils/webclient/Kconfig index c53195d48..68b13ce92 100644 --- a/apps/netutils/webclient/Kconfig +++ b/apps/netutils/webclient/Kconfig @@ -10,4 +10,9 @@ config NETUTILS_WEBCLIENT Enable support for the uIP web client. if NETUTILS_WEBCLIENT + +config NSH_WGET_USERAGENT + string "wget Usert Agent" + default "NuttX/6.xx.x (; http://www.nuttx.org/)" + endif diff --git a/apps/netutils/webclient/webclient.c b/apps/netutils/webclient/webclient.c index 8ce7b93a0..4dbd130ec 100644 --- a/apps/netutils/webclient/webclient.c +++ b/apps/netutils/webclient/webclient.c @@ -69,9 +69,31 @@ #include <arpa/inet.h> #include <netinet/in.h> + +#include <nuttx/version.h> #include <apps/netutils/uiplib.h> #include <apps/netutils/webclient.h> +#if defined(CONFIG_NETUTILS_CODECS) +# if defined(CONFIG_CODECS_URLCODE) +# define WGET_USE_URLENCODE 1 +# include <apps/netutils/urldecode.h> +# endif +# if defined(CONFIG_CODECS_BASE64) +# include <apps/netutils/base64.h> +# endif +#endif + +#ifndef CONFIG_NSH_WGET_USERAGENT +# if CONFIG_VERSION_MAJOR != 0 || CONFIG_VERSION_MINOR != 0 +# define CONFIG_NSH_WGET_USERAGENT \ + "NuttX/" CONFIG_VERSION_STRING " (; http://www.nuttx.org/)" +# else +# define CONFIG_NSH_WGET_USERAGENT \ + "NuttX/6.xx.x (; http://www.nuttx.org/)" +# endif +#endif + /**************************************************************************** * Definitions ****************************************************************************/ @@ -92,6 +114,9 @@ #define ISO_cr 0x0d #define ISO_space 0x20 +#define WGET_MODE_GET 0 +#define WGET_MODE_POST 1 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -136,10 +161,13 @@ static const char g_httpcontenttype[] = "content-type: "; static const char g_httphost[] = "host: "; static const char g_httplocation[] = "location: "; static const char g_httpget[] = "GET "; +static const char g_httppost[] = "POST "; static const char g_httpuseragentfields[] = "Connection: close\r\n" - "User-Agent: NuttX/0.4.x (; http://www.nuttx.org/)\r\n\r\n"; + "User-Agent: " + CONFIG_NSH_WGET_USERAGENT + "\r\n\r\n"; static const char g_http200[] = "200 "; static const char g_http301[] = "301 "; @@ -147,6 +175,11 @@ static const char g_http302[] = "302 "; static const char g_httpcrnl[] = "\r\n"; +static const char g_httpform[] = "Content-Type: application/x-www-form-urlencoded"; +static const char g_httpcontsize[] = "Content-Length: "; +//static const char g_httpconn[] = "Connection: Keep-Alive"; +//static const char g_httpcache[] = "Cache-Control: no-cache"; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -162,12 +195,29 @@ static const char g_httpcrnl[] = "\r\n"; static char *wget_strcpy(char *dest, const char *src) { int len = strlen(src); + memcpy(dest, src, len); dest[len] = '\0'; return dest + len; } /**************************************************************************** + * Name: wget_urlencode_strcpy + ****************************************************************************/ + +#ifdef WGET_USE_URLENCODE +static char *wget_urlencode_strcpy(char *dest, const char *src) +{ + int len = strlen(src); + int d_len; + + d_len = urlencode_len(src, len); + urlencode(src, len, dest, &d_len); + return dest + d_len; +} +#endif + +/**************************************************************************** * Name: wget_parsestatus ****************************************************************************/ @@ -320,11 +370,7 @@ exit: } /**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: wget + * Name: wget_base * * Description: * Obtain the requested file from an HTTP server using the GET method. @@ -344,6 +390,7 @@ exit: * buflen - The size of the user provided buffer * callback - As data is obtained from the host, this function is * to dispose of each block of file data as it is received. + * mode - Indicates GET or POST modes * * Returned Value: * 0: if the GET operation completed successfully; @@ -351,15 +398,16 @@ exit: * ****************************************************************************/ -int wget(FAR const char *url, FAR char *buffer, int buflen, - wget_callback_t callback, FAR void *arg) +static int wget_base(FAR const char *url, FAR char *buffer, int buflen, + wget_callback_t callback, FAR void *arg, + FAR const char *posts, uint8_t mode) { struct sockaddr_in server; struct wget_s ws; bool redirected; - char *dest; + char *dest,post_size[8]; int sockfd; - int len; + int len,post_len; int ret = OK; /* Initialize the state structure */ @@ -380,6 +428,7 @@ int wget(FAR const char *url, FAR char *buffer, int buflen, set_errno(-ret); return ERROR; } + nvdbg("hostname='%s' filename='%s'\n", ws.hostname, ws.filename); /* The following sequence may repeat indefinitely if we are redirected */ @@ -435,19 +484,53 @@ int wget(FAR const char *url, FAR char *buffer, int buflen, /* Send the GET request */ - dest = ws.buffer; - dest = wget_strcpy(dest, g_httpget); - dest = wget_strcpy(dest, ws.filename); - *dest++ = ISO_space; - dest = wget_strcpy(dest, g_http10); - dest = wget_strcpy(dest, g_httpcrnl); - dest = wget_strcpy(dest, g_httphost); - dest = wget_strcpy(dest, ws.hostname); - dest = wget_strcpy(dest, g_httpcrnl); - dest = wget_strcpy(dest, g_httpuseragentfields); - len = dest - buffer; - - ret = send(sockfd, buffer, len, 0); + dest = ws.buffer; + if (mode == WGET_MODE_POST) + { + dest = wget_strcpy(dest, g_httppost); + } + else + { + dest = wget_strcpy(dest, g_httpget); + } + +#ifndef WGET_USE_URLENCODE + dest = wget_strcpy(dest, ws.filename); +#else + //dest = wget_urlencode_strcpy(dest, ws.filename); + dest = wget_strcpy(dest, ws.filename); +#endif + + *dest++ = ISO_space; + dest = wget_strcpy(dest, g_http10); + dest = wget_strcpy(dest, g_httpcrnl); + dest = wget_strcpy(dest, g_httphost); + dest = wget_strcpy(dest, ws.hostname); + dest = wget_strcpy(dest, g_httpcrnl); + + if (mode == WGET_MODE_POST) + { + dest = wget_strcpy(dest, g_httpform); + dest = wget_strcpy(dest, g_httpcrnl); + dest = wget_strcpy(dest, g_httpcontsize); + + /* Post content size */ + + post_len = strlen((char *)posts); + sprintf(post_size,"%d", post_len); + dest = wget_strcpy(dest, post_size); + dest = wget_strcpy(dest, g_httpcrnl); + } + + dest = wget_strcpy(dest, g_httpuseragentfields); + if (mode == WGET_MODE_POST) + { + dest = wget_strcpy(dest, (char *)posts); + } + + len = dest - buffer; + + ret = send(sockfd, buffer, len, 0); if (ret < 0) { ndbg("send failed: %d\n", errno); @@ -528,3 +611,119 @@ errout: close(sockfd); return ERROR; } + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: web_post_str + ****************************************************************************/ + +char *web_post_str(FAR char *buffer, int *size, FAR char *name, + FAR char *value) +{ + char *dst=buffer; + buffer = wget_strcpy(buffer,name); + buffer = wget_strcpy(buffer, "="); + buffer = wget_urlencode_strcpy(buffer,value); + *size = buffer - dst; + return dst; +} + +/**************************************************************************** + * Name: web_post_strlen + ****************************************************************************/ + +int web_post_strlen(FAR char *name, FAR char *value) +{ + return strlen(name) + urlencode_len(value,strlen(value)) + 1; +} + +/**************************************************************************** + * Name: web_posts_str + ****************************************************************************/ + +char *web_posts_str(FAR char *buffer, int *size, FAR char **name, + FAR char **value, int len) +{ + char *dst=buffer; + int wlen; + int i; + + for (i = 0; i < len; i++) + { + if (i > 0) + { + buffer = wget_strcpy(buffer,"&"); + } + + wlen = *size; + buffer = web_post_str(buffer, &wlen, name[i], value[i]); + buffer += wlen; + } + + *size=buffer-dst; + return dst; +} + +/**************************************************************************** + * Name: web_posts_strlen + ****************************************************************************/ + +int web_posts_strlen(FAR char **name, FAR char **value, int len) +{ + int wlen = 0; + int i; + + for (i = 0; i < len; i++) + { + wlen += web_post_strlen(name[i], value[i]); + } + + return wlen + len - 1; +} + +/**************************************************************************** + * Name: wget + * + * Description: + * Obtain the requested file from an HTTP server using the GET method. + * + * Note: If the function is passed a host name, it must already be in + * the resolver cache in order for the function to connect to the web + * server. It is therefore up to the calling module to implement the + * resolver calls and the signal handler used for reporting a resolv + * query answer. + * + * Input Parameters + * url - A pointer to a string containing either the full URL to + * the file to get (e.g., http://www.nutt.org/index.html, or + * http://192.168.23.1:80/index.html). + * buffer - A user provided buffer to receive the file data (also + * used for the outgoing GET request + * buflen - The size of the user provided buffer + * callback - As data is obtained from the host, this function is + * to dispose of each block of file data as it is received. + * + * Returned Value: + * 0: if the GET operation completed successfully; + * -1: On a failure with errno set appropriately + * + ****************************************************************************/ + +int wget(FAR const char *url, FAR char *buffer, int buflen, + wget_callback_t callback, FAR void *arg) +{ + return wget_base(url, buffer, buflen, callback, arg, NULL, WGET_MODE_GET); +} + +/**************************************************************************** + * Name: web_posts_strlen + ****************************************************************************/ + +int wget_post(FAR const char *url, FAR const char *posts, FAR char *buffer, + int buflen, wget_callback_t callback, FAR void *arg) +{ + return wget_base(url, buffer, buflen, callback, arg, posts, WGET_MODE_POST); +} |