📄 ncbicgi.cpp
字号:
end++; range->first = beg; range->second = end; return (beg == end) ? 0 : *beg;}const CCgiCookie* CCgiCookies::Find(const string& name, TCRange* range) const{ CCgiCookies& nonconst_This = const_cast<CCgiCookies&>(*this); if ( range ) { TRange x_range; const CCgiCookie* ck = nonconst_This.Find(name, &x_range); range->first = x_range.first; range->second = x_range.second; return ck; } else { return nonconst_This.Find(name, 0); }}bool CCgiCookies::Remove(CCgiCookie* cookie, bool destroy){ if (!cookie || m_Cookies.erase(cookie) == 0) return false; if ( destroy ) delete cookie; return true;}size_t CCgiCookies::Remove(TRange& range, bool destroy){ size_t count = 0; for (TIter iter = range.first; iter != range.second; iter++, count++) { if ( destroy ) delete *iter; } m_Cookies.erase(range.first, range.second); return count;}void CCgiCookies::Clear(void){ ITERATE (TSet, cookie, m_Cookies) { delete *cookie; } m_Cookies.clear();}///////////////////////////////////////////////////////// CCgiRequest//// Standard property namesstatic const string s_PropName[eCgi_NProperties + 1] = { "SERVER_SOFTWARE", "SERVER_NAME", "GATEWAY_INTERFACE", "SERVER_PROTOCOL", "SERVER_PORT", "REMOTE_HOST", "REMOTE_ADDR", "CONTENT_TYPE", "CONTENT_LENGTH", "REQUEST_METHOD", "PATH_INFO", "PATH_TRANSLATED", "SCRIPT_NAME", "QUERY_STRING", "AUTH_TYPE", "REMOTE_USER", "REMOTE_IDENT", "HTTP_ACCEPT", "HTTP_COOKIE", "HTTP_IF_MODIFIED_SINCE", "HTTP_REFERER", "HTTP_USER_AGENT", "" // eCgi_NProperties};const string& CCgiRequest::GetPropertyName(ECgiProp prop){ if ((long) prop < 0 || (long) eCgi_NProperties <= (long) prop) { _TROUBLE; throw logic_error("CCgiRequest::GetPropertyName(BadPropIdx)"); } return s_PropName[prop];}// Return integer (0..15) corresponding to the "ch" as a hex digit// Return -1 on errorstatic int s_HexChar(char ch) THROWS_NONE{ if ('0' <= ch && ch <= '9') return ch - '0'; if ('a' <= ch && ch <= 'f') return 10 + (ch - 'a'); if ('A' <= ch && ch <= 'F') return 10 + (ch - 'A'); return -1;}// URL-decode string "str" into itself// Return 0 on success; otherwise, return 1-based error positionstatic SIZE_TYPE s_URL_Decode(string& str){ SIZE_TYPE len = str.length(); if ( !len ) return 0; SIZE_TYPE p = 0; for (SIZE_TYPE pos = 0; pos < len; p++) { switch ( str[pos] ) { case '%': { if (pos + 2 > len) return (pos + 1); int i1 = s_HexChar(str[pos+1]); if (i1 < 0 || 15 < i1) return (pos + 2); int i2 = s_HexChar(str[pos+2]); if (i2 < 0 || 15 < i2) return (pos + 3); str[p] = s_HexChar(str[pos+1]) * 16 + s_HexChar(str[pos+2]); pos += 3; break; } case '+': { str[p] = ' '; pos++; break; } default: str[p] = str[pos++]; } } if (p < len) { str[p] = '\0'; str.resize(p); } return 0;}// Add another entry to the container of entriesvoid s_AddEntry(TCgiEntries& entries, const string& name, const string& value, unsigned int position, const string& filename = kEmptyStr){ entries.insert(TCgiEntries::value_type (name, CCgiEntry(value, filename, position)));}// Parse ISINDEX-like query string into "indexes" XOR "entries" --// whichever is not null// Return 0 on success; return 1-based error position otherwisestatic SIZE_TYPE s_ParseIsIndex(const string& str, TCgiIndexes* indexes, TCgiEntries* entries){ _ASSERT( !indexes != !entries ); SIZE_TYPE len = str.length(); if ( !len ) return 0; // No '=' and spaces must present in the parsed string SIZE_TYPE err_pos = str.find_first_of("=& \t\r\n"); if (err_pos != NPOS) return err_pos + 1; // Parse into indexes unsigned int num = 1; for (SIZE_TYPE beg = 0; beg < len; ) { // parse and URL-decode ISINDEX name SIZE_TYPE end = str.find_first_of('+', beg); if (end == beg || end == len-1) return end + 1; // error if (end == NPOS) end = len; string name = str.substr(beg, end - beg); if ((err_pos = s_URL_Decode(name)) != 0) return beg + err_pos; // error // store if ( indexes ) { indexes->push_back(name); } else { s_AddEntry(*entries, name, kEmptyStr, num++); } // continue beg = end + 1; } return 0;}// Guess if "str" is ISINDEX- or FORM-like, then fill out// "entries" XOR "indexes"; if "indexes_as_entries" is "true" then// interprete indexes as FORM-like entries(with empty value) and so// put them to "entries"static void s_ParseQuery(const string& str, TCgiEntries& entries, TCgiIndexes& indexes, bool indexes_as_entries){ if (str.find_first_of("=&") == NPOS) { // ISINDEX SIZE_TYPE err_pos = indexes_as_entries ? s_ParseIsIndex(str, 0, &entries) : s_ParseIsIndex(str, &indexes, 0); if (err_pos != 0) NCBI_THROW2(CCgiParseException, eIndex, "Init CCgiRequest::ParseISINDEX(\"" + str + "\"", err_pos); } else { // regular(FORM) entries SIZE_TYPE err_pos = CCgiRequest::ParseEntries(str, entries); if (err_pos != 0) NCBI_THROW2(CCgiParseException, eEntry, "Init CCgiRequest::ParseFORM(\"" + str + "\")", err_pos); }}static string s_FindAttribute(const string& str, const string& name, SIZE_TYPE start, SIZE_TYPE end, bool required){ SIZE_TYPE att_pos = str.find("; " + name + "=\"", start); if (att_pos == NPOS || att_pos >= end) { if (required) { NCBI_THROW2(CCgiParseException, eAttribute, "s_FindAttribute: missing " + name + " in " + str.substr(start, end - start), start); } else { return kEmptyStr; } } SIZE_TYPE att_start = att_pos + name.size() + 4; SIZE_TYPE att_end = str.find('\"', att_start); if (att_end == NPOS || att_end >= end) { NCBI_THROW2(CCgiParseException, eFormat, "s_FindAttribute: malformatted " + name + " in " + str.substr(att_pos, end - att_pos), att_start); } return str.substr(att_start, att_end - att_start);}static void s_ParseMultipartEntries(const string& boundary, const string& str, TCgiEntries& entries){ const string s_Me("s_ParseMultipartEntries"); const string s_Eol(HTTP_EOL); const SIZE_TYPE eol_size = s_Eol.size(); SIZE_TYPE pos = 0; SIZE_TYPE boundary_size = boundary.size(); SIZE_TYPE end_pos; unsigned int num = 1; if (NStr::Compare(str, 0, boundary_size + eol_size, boundary + s_Eol) != 0) { if (NStr::StartsWith(str, boundary + "--")) { // potential corner case: no actual data return; } NCBI_THROW2(CCgiParseException, eEntry, s_Me + ": input does not start with boundary line " + boundary, 0); } {{ SIZE_TYPE tail_size = boundary_size + eol_size + 2; SIZE_TYPE tail_start = str.find(s_Eol + boundary + "--"); if (tail_start == NPOS) { NCBI_THROW2(CCgiParseException, eEntry, s_Me + ": input does not contain trailing boundary " + boundary + "--", 0); } end_pos = tail_start + tail_size; }} pos += boundary_size + eol_size; while (pos < end_pos) { SIZE_TYPE next_boundary = str.find(s_Eol + boundary, pos); _ASSERT(next_boundary != NPOS); string name, filename; bool found = false; for (;;) { SIZE_TYPE bol_pos = pos, eol_pos = str.find(s_Eol, pos); _ASSERT(eol_pos != NPOS); if (pos == eol_pos) { // blank -- end of headers pos += eol_size; break; } pos = str.find(':', bol_pos); if (pos == NPOS || pos >= eol_pos) { NCBI_THROW2(CCgiParseException, eEntry, s_Me + ": no colon in header " + str.substr(bol_pos, eol_pos - bol_pos), bol_pos); } if (NStr::CompareNocase(str, bol_pos, pos - bol_pos, "Content-Disposition") != 0) { ERR_POST(Warning << s_Me << ": ignoring unrecognized header " + str.substr(bol_pos, eol_pos - bol_pos)); pos = eol_pos + eol_size; continue; } if (NStr::CompareNocase(str, pos, 13, ": form-data; ") != 0) { NCBI_THROW2(CCgiParseException, eEntry, s_Me + ": bad Content-Disposition header " + str.substr(bol_pos, eol_pos - bol_pos), pos); } pos += 11; name = s_FindAttribute(str, "name", pos, eol_pos, true); filename = s_FindAttribute(str, "filename", pos, eol_pos, false); found = true; pos = eol_pos + eol_size; } if (!found) { NCBI_THROW2(CCgiParseException, eEntry, s_Me + ": missing Content-Disposition header", pos); } s_AddEntry(entries, name, str.substr(pos, next_boundary - pos), num++, filename); pos = next_boundary + 2*eol_size + boundary_size; }}static void s_ParsePostQuery(const string& content_type, const string& str, TCgiEntries& entries){ if (content_type.empty() || content_type == "application/x-www-form-urlencoded") { // remove trailing end of line '\r' and/or '\n' // (this can happen if Content-Length: was not specified) SIZE_TYPE err_pos; SIZE_TYPE eol = str.find_first_of("\r\n"); if (eol != NPOS) { err_pos = CCgiRequest::ParseEntries(str.substr(0, eol), entries); } else { err_pos = CCgiRequest::ParseEntries(str, entries); } if ( err_pos != 0 ) { NCBI_THROW2(CCgiParseException, eEntry, "Init CCgiRequest::ParseFORM(\"" + str + "\")", err_pos); } return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -