]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
YaHTTP upstream update 1495/head
authorAki Tuomi <cmouse@desteem.org>
Mon, 30 Jun 2014 20:56:26 +0000 (23:56 +0300)
committerAki Tuomi <cmouse@desteem.org>
Mon, 30 Jun 2014 20:56:26 +0000 (23:56 +0300)
Fixes:
  - Chunked responses and requests are parsed properly even when
    the headers and body come in separately.

pdns/ext/yahttp/yahttp/reqresp.cpp
pdns/ext/yahttp/yahttp/reqresp.hpp
pdns/ext/yahttp/yahttp/url.hpp

index d9d15ef096e746017265abf99755b56004c73610..9b94a2720a0d2e04ac3ce9ce6f0e0515a935752d 100644 (file)
@@ -96,25 +96,28 @@ namespace YaHTTP {
     if (buffer.size() == 0) return ready();
 
     while(buffer.size() > 0) {
-      char buf[1024] = {0};
-
       if (chunked) {
         if (chunk_size == 0) {
+          char buf[100];
           // read chunk length
           if ((pos = buffer.find('\n')) == std::string::npos) return false;
-          if (pos > 1023)
+          if (pos > 99)
             throw ParseError("Impossible chunk_size");
           buffer.copy(buf, pos);
           buf[pos]=0; // just in case...
           buffer.erase(buffer.begin(), buffer.begin()+pos+1); // remove line from buffer
           sscanf(buf, "%x", &chunk_size);
-          if (!chunk_size) break; // last chunk
+          if (!chunk_size) { state = 3; break; } // last chunk
         } else {
+          int crlf=1;
           if (buffer.size() < static_cast<size_t>(chunk_size+1)) return false; // expect newline
-          if (buffer.at(chunk_size) != '\n') return false; // there should be newline.
-          buffer.copy(buf, chunk_size);
-          buffer.erase(buffer.begin(), buffer.begin()+chunk_size+1);
-          bodybuf << buf;
+          if (buffer.at(chunk_size) == '\r') {
+            if (buffer.size() < static_cast<size_t>(chunk_size+2) || buffer.at(chunk_size+1) != '\n') return false; // expect newline after carriage return
+            crlf=2;
+          } else if (buffer.at(chunk_size) != '\n') return false; 
+          std::string tmp = buffer.substr(0, chunk_size);
+          buffer.erase(buffer.begin(), buffer.begin()+chunk_size+crlf);
+          bodybuf << tmp;
           chunk_size = 0;
           if (buffer.size() == 0) break; // just in case
         }
index 3c31e63138027f1e39cd32a4e8356d0f2d61ca4a..44be27a563c30de948af9c1f5b7c1b1169845359 100644 (file)
@@ -237,12 +237,15 @@ public:
       hasBody = false;
     }; //<! Initialize the parser for target and clear state
     int feed(const std::string& somedata); //<! Feed data to the parser
-    bool ready() {  return state > 1 && 
-                      (!hasBody || 
-                         (bodybuf.str().size() <= maxbody && 
-                          bodybuf.str().size() >= minbody)
-                      ); 
-                 }; //<! whether we have received enough data
+    bool ready() {
+     return (chunked == true && state == 3) || // if it's chunked we get end of data indication
+             (chunked == false && state > 1 &&  
+               (!hasBody || 
+                 (bodybuf.str().size() <= maxbody && 
+                  bodybuf.str().size() >= minbody)
+               )
+             ); 
+    }; //<! whether we have received enough data
     void finalize() {
       bodybuf.flush();
       if (ready()) {
index 73b8d2342cb18943f944f493ff73acc5f69816c5..8d46276791a1e501fde7baa928371c343d066ba0 100644 (file)
@@ -155,37 +155,37 @@ namespace YaHTTP {
 
       URL() { initialize(); }; //<! construct empty url
       URL(const std::string& url) {
-          parse(url);
+        parse(url);
       }; //<! calls parse with url 
 
       URL(const char *url) {
-          parse(std::string(url));
+        parse(std::string(url));
       }; //<! calls parse with url
 
       bool parse(const std::string& url) {
-          // setup
-          initialize();
-
-          if (url.size() > YAHTTP_MAX_URL_LENGTH) return false;
-          size_t pos = 0;
-          if (*(url.begin()) != '/') { // full url?
-             if (parseSchema(url, pos) == false) return false;
-             if (pathless) {
-                parameters = url.substr(pos);
-                return true;
-             }
-             if (parseUserPass(url, pos) == false) return false;
-             if (parseHost(url, pos) == false) return false;
+        // setup
+        initialize();
+
+        if (url.size() > YAHTTP_MAX_URL_LENGTH) return false;
+        size_t pos = 0;
+        if (*(url.begin()) != '/') { // full url?
+          if (parseSchema(url, pos) == false) return false;
+          if (pathless) {
+            parameters = url.substr(pos);
+            return true;
           }
-          if (parsePath(url, pos) == false) return false;
-          if (parseParameters(url, pos) == false) return false;
-          return parseAnchor(url, pos);
-      }; /*! parse various formats of urls ranging from http://example.com/foo?bar=baz into data:base64:d089swt64wt... */
-
-      friend std::ostream & operator<<(std::ostream& os, const URL& url) {
-         os<<url.to_string();
-         return os;
-      };
+          if (parseUserPass(url, pos) == false) return false;
+          if (parseHost(url, pos) == false) return false;
+        }
+        if (parsePath(url, pos) == false) return false;
+        if (parseParameters(url, pos) == false) return false;
+        return parseAnchor(url, pos);
+    }; //<! parse various formats of urls ranging from http://example.com/foo?bar=baz into data:base64:d089swt64wt... 
+
+    friend std::ostream & operator<<(std::ostream& os, const URL& url) {
+      os<<url.to_string();
+      return os;
+    };
   };
 };
 #endif