| 88 | } |
| 89 | |
| 90 | UInt32 HTTPPacket::build(Exception& ex,UInt8* data,UInt32 size) { |
| 91 | if (_data) |
| 92 | return 0; |
| 93 | exception.set(Exception::NIL); |
| 94 | |
| 95 | /// read data |
| 96 | ReadingStep step(CMD); |
| 97 | UInt8* current(data); |
| 98 | const UInt8* end(current+size-4); // 4 == /r/n/r/n |
| 99 | const char* signifiant(NULL); |
| 100 | const char* key(NULL); |
| 101 | |
| 102 | // headers |
| 103 | |
| 104 | for (; current <= end;++current) { |
| 105 | |
| 106 | if (memcmp(current, EXPAND("\r\n")) == 0 || memcmp(current, EXPAND("\0\n")) == 0) { |
| 107 | |
| 108 | if (!ex && signifiant) { |
| 109 | // KEY = VALUE |
| 110 | UInt8* endValue(current); |
| 111 | while (isblank(*--endValue)); |
| 112 | *(endValue+1) = 0; |
| 113 | if (!key) { // version case! |
| 114 | String::ToNumber(signifiant+5, version); |
| 115 | } else { |
| 116 | headers[key] = signifiant; |
| 117 | parseHeader(ex,key,signifiant); |
| 118 | key = NULL; |
| 119 | } |
| 120 | } |
| 121 | step = LEFT; |
| 122 | current += 2; |
| 123 | signifiant = (const char*)current; |
| 124 | |
| 125 | if (memcmp(current, EXPAND("\r\n")) == 0) { |
| 126 | current += 2; |
| 127 | content = current; |
| 128 | current += contentLength; |
| 129 | if (ex || current > (end+4)) |
| 130 | break; // wait next |
| 131 | _data = data; |
| 132 | return _size = current - data; |
| 133 | } |
| 134 | |
| 135 | ++current; // here no continue, the "\r\n" check is not required again |
| 136 | } |
| 137 | |
| 138 | if (ex) |
| 139 | continue; // try to go to "\r\n\r\n" |
| 140 | |
| 141 | // http header, byte by byte |
| 142 | UInt8 byte = *current; |
| 143 | |
| 144 | if ((step == LEFT || step == CMD || step == PATH) && (isspace(byte) || byte==0)) { |
| 145 | if (step == CMD) { |
| 146 | if(!signifiant) // Space before signifiant |
| 147 | ex.set(Exception::PROTOCOL,"Unexpected space before command"); |