From 8e7c3d9a4676c5ec1b6b3e9f243af474420ea9fb Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 3 Nov 2012 00:00:56 +0000 Subject: Add support for wget POST interface; from Darcy Gong git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5301 42af7a65-404d-4744-a932-0658087f49c3 --- apps/netutils/webclient/webclient.c | 245 ++++++++++++++++++++++++++++++++---- 1 file changed, 222 insertions(+), 23 deletions(-) (limited to 'apps/netutils/webclient/webclient.c') 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 #include + +#include #include #include +#if defined(CONFIG_NETUTILS_CODECS) +# if defined(CONFIG_CODECS_URLCODE) +# define WGET_USE_URLENCODE 1 +# include +# endif +# if defined(CONFIG_CODECS_BASE64) +# include +# 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,11 +195,28 @@ 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); +} -- cgit v1.2.3