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
}
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()) {
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