/** UrlEncode **/ String* UrlEncode::Encode(const char* src, const int64_t len){ if(!src){ return 0; } // prepare BinaryCoder<1024> coder; int64_t real_len =len; if(len < 0){ real_len =strlen(src); } // encode for(int64_t i=0; i<real_len; ++i){ const char ch =src[i]; if(isalnum(ch) || ch=='.' || ch=='-' || ch=='_' || ch=='~'){ coder.append(&ch, 1); } else{ char sz[3]; sprintf(sz, "%%%02X", (unsigned char)ch); coder.append(sz, sizeof(sz)); } } // return if(coder.size() == 0){ return String::New(); } else{ return String::New(coder.c_str(), coder.size()); } }
String* HttpCookie::build(const bool client){ if(!m_Name || m_Name->empty() || !m_Value || m_Value->empty()){ WARN("build cookie failed, name or value is invalid"); return 0; } BinaryCoder<1024> coder; if(client){ coder.append("Cookie: ", 8); } else{ coder.append("Set-Cookie: ", 12); } // name = value coder.append(m_Name); coder.append("=", 1); coder.append(m_Value); if(!client){ // domain if(m_Domain){ coder.append("; domain=", 9); coder.append(m_Domain); } // path if(m_Domain){ coder.append("; path=", 7); coder.append(m_Path); } // secure if(m_Secure){ coder.append("; secure", 8); } // HttpOnly if(m_HttpOnly){ coder.append("; HttpOnly", 10); } // max age if(m_MaxAge > 0){ coder.append("; max-age=", 10); coder.append(String::Format("%lld", (long long)m_MaxAge)); } // expires if(m_ExpireTime){ coder.append("; expires=", 10); coder.append(m_ExpireTime); } } return String::New(coder.c_str(), coder.size()); }
String* UrlEncode::Decode(const char* code, const int64_t len){ if(!code){ return 0; } // prepare BinaryCoder<1024> coder; int64_t real_len =len; if(len < 0){ real_len =strlen(code); } // encode for(int64_t i=0; i<real_len; ++i){ int ch =code[i]; if(isalnum(ch) || ch=='.' || ch=='-' || ch=='_' || ch=='~'){ const uint8_t x =static_cast<uint8_t>(ch); coder.append(&x, 1); } else if(ch == '%'){ if(1 != sscanf(code+i, "%%%2X", &ch)){ ERROR("invalid url code"); return 0; } const uint8_t x =static_cast<uint8_t>(ch); coder.append(&x, sizeof(x)); i+=2; } else{ puts(code); ERROR("invalid url code"); return 0; } } // return if(coder.size() == 0){ return String::New(); } else{ return String::New(coder.c_str(), coder.size()); } }
bool HttpRespond::flush(){ // check if(m_requestor == 0){ WARN("http flush failed, requestor is null"); return false; } //// build data BinaryCoder<4096> coder; /// head line // version if(m_version){ coder.append(m_version); } else{ coder.append("HTTP/1.1"); } coder.append(" "); // code coder.append(String::Format("%lld", (long long)m_code)); coder.append(" "); // msg coder.append(_code_to_msg(m_code)); coder.append("\r\n"); /// header if(!m_header_tb->has("Content-Type")){ coder.append("Content-Type: text/html\r\n"); } if(!m_header_tb->has("Content-Length")){ coder.append(String::Format("Content-Length: %lld\r\n", (long long)m_content->size())); } HashIterator* it =static_cast< HashIterator* >(m_header_tb->iterator()); while(it->next()){ if(String* name =dynamic_cast< String* >(it->getKey())){ if(String* value =dynamic_cast< String* >(it->getValue())){ coder.append(name); coder.append(": "); coder.append(value); coder.append("\r\n"); } } } it =static_cast< HashIterator* >(m_cookie_tb->iterator()); while(it->next()){ if(dynamic_cast< String* >(it->getKey())){ if(HttpCookie* cookie =dynamic_cast< HttpCookie* >(it->getValue())){ if(String* str =cookie->build(false)){ coder.append(str); coder.append("\r\n"); } } } } coder.append("\r\n"); /// content if(m_content->size() > 0){ coder.append(m_content->c_str(), m_content->size()); } //// send const bool ok =m_requestor->send(coder.c_str(), coder.size()); //// clear CLEAN_POINTER(m_version); m_code =200; CLEAN_POINTER(m_msg); m_header_tb->clear(); m_cookie_tb->clear(); m_content->clear(); //// post process if(!ok){ close(); } m_auto_flush =false; return ok; }
bool Url::_build(String* protocol, String* auth, String* host, String* path, String* query_string, Hash* query, String* fragment){ // clean clean(); // check if(path && path->size() && !path->hasPrefix("/")){ return false; } // make url BinaryCoder<1024> coder; if(protocol && protocol->size()){ ASSIGN_POINTER(m_protocol, protocol); coder.append(protocol); coder.append("://", 3); } if(auth && auth->size()){ ASSIGN_POINTER(m_auth, auth); coder.append(auth); coder.append("@", 1); } if(host && host->size()){ ASSIGN_POINTER(m_host, host); coder.append(host); } if(path && path->size()){ ASSIGN_POINTER(m_path, path); coder.append(path); } if(query_string && query_string->size()){ ASSIGN_POINTER(m_query_string, query_string); ASSIGN_POINTER(m_query, SafeNew<Hash>()); if(!ParseQuery(m_query_string, m_query)){ clean(); return false; } coder.append("?", 1); coder.append(m_query_string); } else if(query && query->size()){ ASSIGN_POINTER(m_query, query); // make query string BinaryCoder<1024> sub_coder; HashIterator* it =static_cast< HashIterator* >(query->iterator()); while(it->next()){ String* key =static_cast< String* >(it->getKey()); String* val =static_cast< String* >(it->getValue()); if(sub_coder.size() > 0){ sub_coder.append("&", 1); } sub_coder.append(UrlEncode::Encode(key)); sub_coder.append("=", 1); sub_coder.append(UrlEncode::Encode(val)); } // set ASSERT(sub_coder.size()); ASSIGN_POINTER(m_query_string, String::New(sub_coder.c_str(), sub_coder.size())); coder.append("?", 1); coder.append(m_query_string); } if(fragment && fragment->size()){ ASSIGN_POINTER(m_fragment, fragment); coder.append("#", 1); coder.append(fragment); } ASSIGN_POINTER(m_url, String::New(coder.c_str(), coder.size())); return true; }