Jelajahi Sumber

Added urlDecode urlDecode CivetServer methods

Thomas Davis 12 tahun lalu
induk
melakukan
466f3982fe
5 mengubah file dengan 182 tambahan dan 30 penghapusan
  1. 2 0
      RELEASE_NOTES.md
  2. 99 19
      include/CivetServer.h
  3. 3 0
      include/civetweb.h
  4. 77 10
      src/CivetServer.cpp
  5. 1 1
      src/civetweb.c

+ 2 - 0
RELEASE_NOTES.md

@@ -2,6 +2,8 @@ Release Notes v1.4 (UNDER DEVELOPMENT)
 ===
 ### Objectives: *???*
 
+- Added CivetServer::getParam methods
+- Added CivetServer::urlDecode methods
 - Dealt with compiler warnings and some static analysis hits.
 - Added mg_get_var2() to parse repeated query variables
 - Externalized logging function cry() as mg_cry()

+ 99 - 19
include/CivetServer.h

@@ -140,7 +140,7 @@ public:
      * @returns the handler that matches the requested URI or 0 if none were found.
      */
     CivetHandler *getHandler(const std::string &uri) const {
-        return getHandler(uri.data(), uri.length());
+        return getHandler(uri.data(), (unsigned int)uri.length());
     }
 
     /**
@@ -151,24 +151,104 @@ public:
      * @returns the handler that matches the requested URI or 0 if none were found.
      */
     CivetHandler *getHandler(const char *uri, unsigned urilen) const;
-	
-	/**
-	 * getCookie(struct mg_connection *conn, const std::string &cookieName, std::string &cookieValue)
-	 * @param conn - the connection information 
-	 * @param cookieName - cookie name to get the value from
-	 * @param cookieValue - cookie value is returned using thiis reference
-	 * @puts the cookie value string that matches the cookie name in the _cookieValue string.
-	 * @returns the size of the cookie value string read.
-	*/
-	int getCookie(struct mg_connection *conn, const std::string &cookieName, std::string &cookieValue);
-
-	/**
-	 * getHeader(struct mg_connection *conn, const std::string &headerName)
-	 * @param conn - the connection information 
-	 * @param headerName - header name to get the value from
-	 * @returns a char array whcih contains the header value as string
-	*/
-	const char* getHeader(struct mg_connection *conn, const std::string &headerName);
+    
+    /**
+     * getCookie(struct mg_connection *conn, const std::string &cookieName, std::string &cookieValue)
+     * @param conn - the connection information 
+     * @param cookieName - cookie name to get the value from
+     * @param cookieValue - cookie value is returned using thiis reference
+     * @puts the cookie value string that matches the cookie name in the _cookieValue string.
+     * @returns the size of the cookie value string read.
+    */
+    static int getCookie(struct mg_connection *conn, const std::string &cookieName, std::string &cookieValue);
+
+    /**
+     * getHeader(struct mg_connection *conn, const std::string &headerName)
+     * @param conn - the connection information 
+     * @param headerName - header name to get the value from
+     * @returns a char array whcih contains the header value as string
+    */
+    static const char* getHeader(struct mg_connection *conn, const std::string &headerName);
+
+    /**
+     * getParam(struct mg_connection *conn, const char *, std::string &, size_t)
+     *
+     * Returns a query paramter contained in the supplied buffer.  The
+     * occurance value is a zero-based index of a particular key name.  This
+     * should nto be confused with the index over all of the keys.
+     *
+     * @param data the query string
+     * @param name the key to search for
+     * @param the destination string
+     * @param occurrence the occurrence of the selected name in the query (0 based).
+     * @return true of key was found
+     */
+    static bool getParam(struct mg_connection *conn, const char *name,
+               std::string &dst, size_t occurrence=0);
+
+    /**
+     * getParam(const std::string &, const char *, std::string &, size_t)
+     *
+     * Returns a query paramter contained in the supplied buffer.  The
+     * occurance value is a zero-based index of a particular key name.  This
+     * should nto be confused with the index over all of the keys.
+     *
+     * @param data the query string
+     * @param name the key to search for
+     * @param the destination string
+     * @param occurrence the occurrence of the selected name in the query (0 based).
+     * @return true of key was found
+     */
+    static bool getParam(const std::string &data, const char *name,
+               std::string &dst, size_t occurrence=0) {
+        return getParam(data.c_str(), data.length(), name, dst, occurrence);
+    }
+
+    /**
+     * getParam(const char *, size_t, const char *, std::string &, size_t)
+     *
+     * Returns a query paramter contained in the supplied buffer.  The
+     * occurance value is a zero-based index of a particular key name.  This
+     * should nto be confused with the index over all of the keys.
+     *
+     * @param data the query string
+     * @param length length of the query string
+     * @param name the key to search for
+     * @param the destination string
+     * @param occurrence the occurrence of the selected name in the query (0 based).
+     * @return true of key was found
+     */
+    static bool getParam(const char *data, size_t data_len, const char *name,
+               std::string &dst, size_t occurrence=0);
+
+
+    /**
+     * urlDecode(const char *, int, std::string &, bool)
+     *
+     * @param src string to be decoded
+     * @param dst destination string
+     * @is_form_url_encoded true if form url encoded
+     *       form-url-encoded data differs from URI encoding in a way that it
+     *       uses '+' as character for space, see RFC 1866 section 8.2.1
+     *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
+     */
+    static void urlDecode(const std::string &src, std::string &dst, bool is_form_url_encoded=true) {
+        urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
+    }
+
+    /**
+     * urlDecode(const char *, int, std::string &, bool)
+     *
+     * @param src buffer to be decoded
+     * @param src_len length of buffer to be decoded
+     * @param dst destination string
+     * @is_form_url_encoded true if form url encoded
+     *       form-url-encoded data differs from URI encoding in a way that it
+     *       uses '+' as character for space, see RFC 1866 section 8.2.1
+     *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
+     */
+    static void urlDecode(const char *src, size_t src_len, std::string &dst, bool is_form_url_encoded=true);
+
 protected:
 
     /**

+ 3 - 0
include/civetweb.h

@@ -428,6 +428,9 @@ char *mg_md5(char buf[33], ...);
 void mg_cry(struct mg_connection *conn,
                 PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
 
+// utility method to compare two buffers, case incensitive.
+int mg_strncasecmp(const char *s1, const char *s2, size_t len);
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus

+ 77 - 10
src/CivetServer.cpp

@@ -7,6 +7,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #ifndef UNUSED_PARAMETER
  #define UNUSED_PARAMETER(x) (void)(x)
@@ -146,7 +147,7 @@ void CivetServer::close() {
         mg_stop (context);
         context = 0;
     }
-    for (int i = handlers.size() - 1; i >= 0; i--) {
+    for (int i = (int) handlers.size() - 1; i >= 0; i--) {
         delete handlers[i];
     }
     handlers.clear();
@@ -156,16 +157,82 @@ void CivetServer::close() {
 
 int CivetServer::getCookie(struct mg_connection *conn, const std::string &cookieName, std::string &cookieValue)
 {
-	//Maximum cookie length as per microsoft is 4096. http://msdn.microsoft.com/en-us/library/ms178194.aspx
-	char _cookieValue[4096];
-	const char *cookie = mg_get_header(conn, "Cookie");
-	int lRead = mg_get_cookie(cookie, cookieName.c_str(), _cookieValue, sizeof(_cookieValue));
-	cookieValue.clear();
-	cookieValue.append(_cookieValue);
-	return lRead;
+    //Maximum cookie length as per microsoft is 4096. http://msdn.microsoft.com/en-us/library/ms178194.aspx
+    char _cookieValue[4096];
+    const char *cookie = mg_get_header(conn, "Cookie");
+    int lRead = mg_get_cookie(cookie, cookieName.c_str(), _cookieValue, sizeof(_cookieValue));
+    cookieValue.clear();
+    cookieValue.append(_cookieValue);
+    return lRead;
 }
 
 const char* CivetServer::getHeader(struct mg_connection *conn, const std::string &headerName)
 {
-	return mg_get_header(conn, headerName.c_str());
-}
+    return mg_get_header(conn, headerName.c_str());
+}
+
+void
+CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst, bool is_form_url_encoded) {
+  int i, j, a, b;
+#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
+
+  dst.clear();
+  for (i = j = 0; i < (int)src_len; i++, j++) {
+    if (src[i] == '%' && i < (int)src_len - 2 &&
+        isxdigit(* (const unsigned char *) (src + i + 1)) &&
+        isxdigit(* (const unsigned char *) (src + i + 2))) {
+      a = tolower(* (const unsigned char *) (src + i + 1));
+      b = tolower(* (const unsigned char *) (src + i + 2));
+      dst.push_back((char) ((HEXTOI(a) << 4) | HEXTOI(b)));
+      i += 2;
+    } else if (is_form_url_encoded && src[i] == '+') {
+      dst.push_back(' ');
+    } else {
+      dst.push_back(src[i]);
+    }
+  }
+}
+
+bool
+CivetServer::getParam(struct mg_connection *conn, const char *name,
+               std::string &dst, size_t occurrence) {
+        const char *query = mg_get_request_info(conn)->query_string;
+        return getParam(query, strlen(query), name, dst, occurrence);
+}
+
+bool
+CivetServer::getParam(const char *data, size_t data_len, const char *name,
+               std::string &dst, size_t occurrence) {
+  const char *p, *e, *s;
+  size_t name_len;
+
+  dst.clear();
+  if (data == NULL || name == NULL || data_len == 0) {
+      return false;
+  }
+  name_len = strlen(name);
+  e = data + data_len;
+
+  // data is "var1=val1&var2=val2...". Find variable first
+  for (p = data; p + name_len < e; p++) {
+    if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
+        !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
+
+      // Point p to variable value
+      p += name_len + 1;
+
+      // Point s to the end of the value
+      s = (const char *) memchr(p, '&', (size_t)(e - p));
+      if (s == NULL) {
+        s = e;
+      }
+      assert(s >= p);
+
+      // Decode variable into destination buffer
+      urlDecode(p, (int)(s - p), dst, true);
+      return true;
+    }
+  }
+  return false;
+}
+

+ 1 - 1
src/civetweb.c

@@ -691,7 +691,7 @@ static int lowercase(const char *s) {
   return tolower(* (const unsigned char *) s);
 }
 
-static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
+int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
   int diff = 0;
 
   if (len > 0)