diff --git a/HISTORY b/HISTORY index 385180c..951a57d 100644 --- a/HISTORY +++ b/HISTORY @@ -21,7 +21,7 @@ Version 1.06 2014-08-11 * replace INT64_PRINTF_FORMAT with PRId64 * support OS Darwin * socket send and recv ignore erno EINTR - * http_parse_query set both lengths of key and name + * http_parse_query_ex support binary buffer, and set both lengths of key and name Version 1.05 2012-07-08 * update source code from FastDFS V3.09 diff --git a/src/common_define.h b/src/common_define.h index 657a2fb..860bc22 100644 --- a/src/common_define.h +++ b/src/common_define.h @@ -132,13 +132,19 @@ typedef struct char minor; } Version; +typedef struct +{ + char *key; + char *value; +} KeyValuePair; + typedef struct { char *key; char *value; int key_len; int value_len; -} KeyValuePair; +} KeyValuePairEx; typedef struct { diff --git a/src/http_func.c b/src/http_func.c index 3dd0ad6..81780d7 100644 --- a/src/http_func.c +++ b/src/http_func.c @@ -277,6 +277,7 @@ int http_parse_query(char *url, KeyValuePair *params, const int max_count) char *p; char *pKeyEnd; char *pValueEnd; + int value_len; pParamStart = strchr(url, '?'); if (pParamStart == NULL) @@ -316,6 +317,70 @@ int http_parse_query(char *url, KeyValuePair *params, const int max_count) } *pKeyEnd = '\0'; + if (*pCurrent->key == '\0') //empty key + { + continue; + } + + pCurrent->value = pKeyEnd + 1; + urldecode(pCurrent->value, (int)(pValueEnd - pCurrent->value), + pCurrent->value, &value_len); + pCurrent++; + } + + return pCurrent - params; +} + +int http_parse_query_ex(char *url, const int url_len, + int *uri_len, KeyValuePairEx *params, const int max_count) +{ + KeyValuePairEx *pCurrent; + KeyValuePairEx *pEnd; + char *pParamStart; + char *p; + char *pStrEnd; + char *pKeyEnd; + char *pValueEnd; + + pParamStart = (char *)memchr(url, '?', url_len); + if (pParamStart == NULL) + { + *uri_len = url_len; + return 0; + } + + *uri_len = pParamStart - url; + pStrEnd = url + url_len; + + pEnd = params + max_count; + pCurrent = params; + p = pParamStart + 1; + while (p < pStrEnd) + { + if (pCurrent >= pEnd) + { + return pCurrent - params; + } + + pCurrent->key = p; + pValueEnd = (char *)memchr(p, '&', pStrEnd - p); + if (pValueEnd == NULL) + { + pValueEnd = pStrEnd; + p = pStrEnd; + } + else + { + p = pValueEnd + 1; + } + + pKeyEnd = (char *)memchr(pCurrent->key, '=', + pStrEnd - pCurrent->key); + if (pKeyEnd == NULL) //no = + { + continue; + } + pCurrent->key_len = (int)(pKeyEnd - pCurrent->key); if (pCurrent->key_len == 0) //empty key { @@ -323,7 +388,7 @@ int http_parse_query(char *url, KeyValuePair *params, const int max_count) } pCurrent->value = pKeyEnd + 1; - urldecode(pCurrent->value, (int)(pValueEnd - pCurrent->value), + urldecode_ex(pCurrent->value, (int)(pValueEnd - pCurrent->value), pCurrent->value, &pCurrent->value_len); pCurrent++; } diff --git a/src/http_func.h b/src/http_func.h index 95edc88..ae20b09 100644 --- a/src/http_func.h +++ b/src/http_func.h @@ -64,6 +64,19 @@ return: param count **/ int http_parse_query(char *url, KeyValuePair *params, const int max_count); +/** +parse url ex +params: + url: the url to parse, the url be modified after parse + url_len: the length of url + uri_len: return the uri length (not including ? and parameters) + params: params array to store param and it's value + max_count: max param count +return: param count +**/ +int http_parse_query_ex(char *url, const int url_len, + int *uri_len, KeyValuePairEx *params, const int max_count); + #ifdef __cplusplus } #endif diff --git a/src/shared_func.c b/src/shared_func.c index 814e346..f6f08fa 100644 --- a/src/shared_func.c +++ b/src/shared_func.c @@ -1887,6 +1887,13 @@ char *urlencode(const char *src, const int src_len, char *dest, int *dest_len) } char *urldecode(const char *src, const int src_len, char *dest, int *dest_len) +{ + (void)urldecode_ex(src, src_len, dest, dest_len); + *(dest + *dest_len) = '\0'; + return dest; +} + +char *urldecode_ex(const char *src, const int src_len, char *dest, int *dest_len) { #define IS_HEX_CHAR(ch) \ ((ch >= '0' && ch <= '9') || \ @@ -1950,9 +1957,7 @@ char *urldecode(const char *src, const int src_len, char *dest, int *dest_len) } } - *pDest = '\0'; *dest_len = pDest - dest; - return dest; } diff --git a/src/shared_func.h b/src/shared_func.h index 6ea8342..212d20c 100644 --- a/src/shared_func.h +++ b/src/shared_func.h @@ -240,7 +240,7 @@ int buffer_memcpy(BufferInfo *pBuff, const char *buff, const int len); */ char *urlencode(const char *src, const int src_len, char *dest, int *dest_len); -/** url decode +/** url decode, terminated with \0 * parameters: * src: the source string to decode * src_len: source string length @@ -250,6 +250,16 @@ char *urlencode(const char *src, const int src_len, char *dest, int *dest_len); */ char *urldecode(const char *src, const int src_len, char *dest, int *dest_len); +/** url decode, no terminate with \0 + * parameters: + * src: the source string to decode + * src_len: source string length + * dest: store dest string + * dest_len: store the dest string length + * return: error no, 0 success, != 0 fail +*/ +char *urldecode_ex(const char *src, const int src_len, char *dest, int *dest_len); + /** get char occurs count * parameters: * src: the source string