📄 ncbicgi.cpp
字号:
} if ( NStr::StartsWith(content_type, "multipart/form-data") ) { string start = "boundary="; SIZE_TYPE pos = content_type.find(start); if ( pos == NPOS ) NCBI_THROW2(CCgiParseException, eEntry, "CCgiRequest::ParsePostQuery(\"" + content_type + "\"): no boundary field", 0); s_ParseMultipartEntries("--" + content_type.substr(pos + start.size()), str, entries); return; } // The caller function thinks that s_ParsePostQuery() knows how to parse // this content type, but s_ParsePostQuery() apparently cannot do it... _TROUBLE;}CCgiRequest::~CCgiRequest(void){ SetInputStream(0);}CCgiRequest::CCgiRequest(const CNcbiArguments* args, const CNcbiEnvironment* env, CNcbiIstream* istr, TFlags flags, int ifd, size_t errbuf_size) : m_Env(0), m_ErrBufSize(errbuf_size){ x_Init(args, env, istr, flags, ifd);}CCgiRequest::CCgiRequest(int argc, const char* const* argv, const char* const* envp, CNcbiIstream* istr, TFlags flags, int ifd, size_t errbuf_size) : m_Env(0), m_ErrBufSize(errbuf_size){ CNcbiArguments args(argc, argv); CNcbiEnvironment* env = new CNcbiEnvironment(envp); flags |= fOwnEnvironment; x_Init(&args, env, istr, flags, ifd);}void CCgiRequest::x_Init(const CNcbiArguments* args, const CNcbiEnvironment* env, CNcbiIstream* istr, TFlags flags, int ifd){ // Setup environment variables _ASSERT( !m_Env ); m_Env = env; if ( !m_Env ) { // create a dummy environment, if is not specified m_OwnEnv.reset(new CNcbiEnvironment); m_Env = m_OwnEnv.get(); } else if ((flags & fOwnEnvironment) != 0) { // take ownership over the passed environment object m_OwnEnv.reset(const_cast<CNcbiEnvironment*>(m_Env)); } // Cache "standard" properties for (size_t prop = 0; prop < (size_t) eCgi_NProperties; prop++) { x_GetPropertyByName(GetPropertyName((ECgiProp) prop)); } // Compose cookies m_Cookies.Add(GetProperty(eCgi_HttpCookie)); // Parse entries or indexes from "$QUERY_STRING" or cmd.-line args {{ const string* query_string = 0; if ( GetProperty(eCgi_RequestMethod).empty() ) { // special case: "$REQUEST_METHOD" undefined, so use cmd.-line args if (args && args->Size() > 1) query_string = &(*args)[1]; } else if ( !(flags & fIgnoreQueryString) ) { // regular case -- read from "$QUERY_STRING" query_string = &GetProperty(eCgi_QueryString); } if ( query_string ) { s_ParseQuery(*query_string, m_Entries, m_Indexes, (flags & fIndexesNotEntries) == 0); } }} // POST method? if ( AStrEquiv(GetProperty(eCgi_RequestMethod), "POST", PNocase()) ) { if ( !istr ) { istr = &NcbiCin; // default input stream ifd = STDIN_FILENO; } const string& content_type = GetProperty(eCgi_ContentType); if ((flags & fDoNotParseContent) == 0 && (content_type.empty() || content_type == "application/x-www-form-urlencoded" || NStr::StartsWith(content_type, "multipart/form-data"))) { // Automagically retrieve and parse content into entries string str; size_t len = GetContentLength(); if (len == kContentLengthUnknown) { // read data until end of file for (;;) { char buffer[1024]; istr->read(buffer, sizeof(buffer)); size_t count = istr->gcount(); if ( count == 0 ) { if ( istr->eof() ) { break; // end of data } else { THROW1_TRACE(runtime_error, "\CCgiRequest::x_Init() -- error in reading POST content: read fault"); } } str.append(buffer, count); } } else { str.resize(len); for (size_t pos = 0; pos < len; ) { size_t rlen = len - pos; istr->read(&str[pos], rlen); size_t count = istr->gcount(); if ( count == 0 ) { str.resize(pos); if ( istr->eof() ) { string err = "\CCgiRequest::x_Init() -- error in reading POST content: unexpected EOF"; string pos_str("(pos="); pos_str.append(NStr::UIntToString(pos)); pos_str.append("; content_length="); pos_str.append(NStr::UIntToString(len)); pos_str.append("):\n"); if (m_ErrBufSize && pos) { pos_str.append(NStr::PrintableString(str), 0, min(m_ErrBufSize, pos)); if (m_ErrBufSize < pos) { pos_str.append("\n[truncated...]"); } } err.append(pos_str); THROW1_TRACE(runtime_error, err); } else { THROW1_TRACE(runtime_error, "\CCgiRequest::x_Init() -- error in reading POST content: read fault"); } } pos += count; } } // parse query from the POST content s_ParsePostQuery(content_type, str, m_Entries); m_Input = 0; m_InputFD = -1; } else { // Let the user to retrieve and parse the content m_Input = istr; m_InputFD = ifd; m_OwnInput = false; } } else { m_Input = 0; m_InputFD = -1; } // Check for an IMAGEMAP input entry like: "Command.x=5&Command.y=3" and // put them with empty string key for better access if (m_Entries.find(kEmptyStr) != m_Entries.end()) { // there is already empty name key ERR_POST("empty key name: we will not check for IMAGE names"); return; } string image_name; ITERATE (TCgiEntries, i, m_Entries) { const string& entry = i->first; // check for our case ("*.x") if ( !NStr::EndsWith(entry, ".x") ) continue; // get base name of IMAGE, check for the presence of ".y" part string name = entry.substr(0, entry.size() - 2); if (m_Entries.find(name + ".y") == m_Entries.end()) continue; // it is a correct IMAGE name if ( !image_name.empty() ) { ERR_POST("duplicated IMAGE name: \"" << image_name << "\" and \"" << name << "\""); return; } image_name = name; } s_AddEntry(m_Entries, kEmptyStr, image_name, 0);}const string& CCgiRequest::x_GetPropertyByName(const string& name) const{ return m_Env->Get(name);}const string& CCgiRequest::GetProperty(ECgiProp property) const{ return x_GetPropertyByName(GetPropertyName(property));}const string& CCgiRequest::GetRandomProperty(const string& key, bool http) const{ if ( http ) { return x_GetPropertyByName("HTTP_" + key); } else { return x_GetPropertyByName(key); }}const CCgiEntry& CCgiRequest::GetEntry(const string& name, bool* is_found) const{ static const CCgiEntry kEmptyEntry(kEmptyStr); TCgiEntriesCI it = GetEntries().find(name); bool x_found = (it != GetEntries().end()); if ( is_found ) { *is_found = x_found; } return x_found ? it->second : kEmptyEntry;}const size_t CCgiRequest::kContentLengthUnknown = (size_t)(-1);size_t CCgiRequest::GetContentLength(void) const{ const string& str = GetProperty(eCgi_ContentLength); if ( str.empty() ) { return kContentLengthUnknown; } return (size_t) NStr::StringToUInt(str);}void CCgiRequest::SetInputStream(CNcbiIstream* is, bool own, int fd){ if (m_Input && m_OwnInput && is != m_Input) { delete m_Input; } m_Input = is; m_InputFD = fd; m_OwnInput = own;}SIZE_TYPE CCgiRequest::ParseEntries(const string& str, TCgiEntries& entries){ SIZE_TYPE len = str.length(); if ( !len ) return 0; // If no '=' present in the parsed string then try to parse it as ISINDEX if (str.find_first_of("&=") == NPOS) return s_ParseIsIndex(str, 0, &entries); // No spaces are allowed 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 entries unsigned int num = 1; for (SIZE_TYPE beg = 0; beg < len; ) { // ignore 1st ampersand (it is just a temp. slack to some biz. clients) if (beg == 0 && str[0] == '&') { beg = 1; continue; } // kludge for the sake of some older browsers, which fail to decode // "&" within hrefs. if ( !NStr::CompareNocase(str, beg, 4, "amp;") ) { beg += 4; } // parse and URL-decode name SIZE_TYPE mid = str.find_first_of("=&", beg); if (mid == beg || (mid != NPOS && str[mid] == '&' && mid == len-1)) return mid + 1; // error if (mid == NPOS) mid = len; string name = str.substr(beg, mid - beg); if ((err_pos = s_URL_Decode(name)) != 0) return beg + err_pos; // error // parse and URL-decode value(if any) string value; if (str[mid] == '=') { // has a value mid++; SIZE_TYPE end = str.find_first_of(" &", mid); if (end != NPOS && (str[end] != '&' || end == len-1)) return end + 1; // error if (end == NPOS) end = len; value = str.substr(mid, end - mid); if ((err_pos = s_URL_Decode(value)) != 0) return mid + err_pos; // error beg = end + 1; } else { // has no value beg = mid + 1; } // store the name-value pair s_AddEntry(entries, name, value, num++); } return 0;}SIZE_TYPE CCgiRequest::ParseIndexes(const string& str, TCgiIndexes& indexes){ return s_ParseIsIndex(str, &indexes, 0);}extern string URL_DecodeString(const string& str){ string x_str = str; SIZE_TYPE err_pos = s_URL_Decode(x_str); if (err_pos != 0) NCBI_THROW2(CCgiParseException, eFormat, "URL_DecodeString(<badly_formatted_str>)",err_pos); return x_str;}extern string URL_EncodeString(const string& str, EUrlEncode encode_mark_chars){ static const char s_Encode[256][4] = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F", "+", "!", "%22", "%23", "$", "%25", "%26", "'", "(", ")", "*", "%2B", ",", "-", ".", "%2F",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -