diff options
Diffstat (limited to 'ACE/protocols/ace/INet/URLBase.cpp')
-rw-r--r-- | ACE/protocols/ace/INet/URLBase.cpp | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/ACE/protocols/ace/INet/URLBase.cpp b/ACE/protocols/ace/INet/URLBase.cpp new file mode 100644 index 00000000000..9ba4641ead3 --- /dev/null +++ b/ACE/protocols/ace/INet/URLBase.cpp @@ -0,0 +1,452 @@ +// $Id$ + +#include "ace/INet/URLBase.h" +#include "ace/INet/IOS_util.h" + +#if !defined (__ACE_INLINE__) +#include "ace/INet/URLBase.inl" +#endif + +#include "ace/INet/String_IOStream.h" + +#include "ace/INet/ClientRequestHandler.h" +#include <istream> + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +namespace ACE +{ + namespace INet + { + + URLStream::URLStream (const URLStream& url_stream) + : request_handler_ref_ (url_stream.request_handler_ref_), + request_handler_ (url_stream.request_handler_) + { + } + + URLStream::~URLStream () + { + } + + bool URLStream::operator ! () + { + return this->request_handler_ == 0 || !this->request_handler_->is_response_ok (); + } + + URLStream::operator bool () + { + return this->request_handler_ != 0 && this->request_handler_->is_response_ok (); + } + + std::istream& URLStream::operator * () + { + return this->request_handler_ ? + this->request_handler_->response_stream () : + ACE::IOS::Null::in_stream_; + } + + std::istream* URLStream::operator -> () + { + return this->request_handler_ ? + &this->request_handler_->response_stream () : + &ACE::IOS::Null::in_stream_; + } + + URLStream::URLStream (ClientRequestHandler& rh) + : request_handler_ (&rh) + { + } + + URLStream::URLStream (ClientRequestHandler* rh) + : request_handler_ref_ (rh), + request_handler_ (rh) + { + } + + const ACE_CString URL_Base::empty_; + + URL_Base::URL_Base () + { + } + + URL_Base::~URL_Base () {} + + bool URL_Base::parse (const ACE_CString& url_string) + { + static const int eof = + std::char_traits<ACE::IOS::CString_OStream::char_type>::eof (); + + ACE_CString uri = url_string; + if (this->strip_scheme (uri)) + { + ACE::IOS::CString_OStream sos; + ACE::IOS::CString_IStream sis (uri); + + int ch; + + // parse authority part (if any) + if ((ch = this->parse_authority (sis)) == '/' || + !this->has_authority ()) // relative paths allowed if no authority + { + // parse path part + sos.put (ch); + for (ch = sis.get (); ch != '?' && ch != '#' && ch != eof ;ch = sis.get ()) + sos.put (ch); + this->set_path (sos.str ()); + sos.clear (); + } + else + { + // empty path + this->set_path (empty_); + } + + if (ch == '?') + { + // parse query part + for (ch = sis.get (); ch != '#' && ch != eof ;ch = sis.get ()) + sos.put (ch); + this->set_query (sos.str ()); + sos.clear (); + } + + if (ch == '#') + { + // get fragment + sos << sis.rdbuf (); + this->set_fragment (sos.str ()); + } + else if (ch != eof) + { + // should not happen + return false; + } + + // check for (minimum) correctness + return this->validate (); + } + return false; + } + + int URL_Base::parse_authority(std::istream& is) + { + return is.get (); + } + + bool URL_Base::has_authority () + { + return false; + } + + bool URL_Base::validate () + { + return true; + } + + URLStream URL_Base::open () const + { + ClientRequestHandler* rh = this->create_default_request_handler (); + if (rh) + { + rh->handle_open_request (*this); + return URLStream (rh); + } + else + return URLStream (0); + } + + URLStream URL_Base::open (ClientRequestHandler& rh) const + { + rh.handle_open_request (*this); + return URLStream (rh); + } + + URL_Base* URL_Base::create_from_string (const ACE_CString& url_string) + { + ACE_CString::size_type pos = url_string.find (':'); + if (pos >0 ) + { + Factory* url_factory = 0; + if (factories_->find (url_string.substr (0, pos), url_factory) == 0) + { + return url_factory->create_from_string (url_string); + } + } + + return 0; + } + +#if defined (ACE_HAS_WCHAR) + bool URL_Base::parse (const ACE_WString& url_string) + { + return this->parse (ACE_Wide_To_Ascii (url_string.c_str ()).char_rep ()); + } + + ACE_WString URL_Base::to_wstring () const + { + return ACE_Ascii_To_Wide (this->to_string().c_str ()).wchar_rep (); + } + + URL_Base* URL_Base::create_from_wstring (const ACE_WString& url_string) + { + return create_from_string (ACE_Wide_To_Ascii (url_string.c_str ()).char_rep ()); + } +#endif + + bool URL_Base::strip_scheme (ACE_CString& url_string) + { + // since this will be called at a point where the + // actual URL class is already known (and with that + // the protocol prefix) we allow for the fact we + // may get a url passed without the actual prefix + + ACE_CString::size_type pos = url_string.find (':'); + if (pos > 0 && url_string[pos+1] == '/' && url_string[pos+1] == '/') + { + // in case we find a scheme check for the right protocol + if (this->get_protocol () != url_string.substr (0, pos)) + { + return false; + } + url_string = url_string.substr (pos+3); // skip '<protocol>://' + } + return true; + } + + void URL_Base::register_factory (Factory* url_factory) + { + if (factories_ == 0) + { + factories_ = URL_Base::TURLFactorySingleton::instance (); + } + if (url_factory) + factories_->bind (url_factory->protocol (), url_factory); + } + + void URL_Base::deregister_factory (Factory* url_factory) + { + if (factories_ && url_factory) + { + factories_->unbind (url_factory->protocol ()); + }; + } + + URL_Base::TURLFactoryMap* URL_Base::factories_ = 0; + + URL_Base::Factory::Factory () + {} + + URL_Base::Factory::~Factory () + {} + + URL_INetBase::URL_INetBase (u_short port) + : URL_Base (), port_ (port) + { + } + + URL_INetBase::~URL_INetBase () {} + + int URL_INetBase::parse_authority (std::istream& is) + { + ACE::IOS::CString_OStream sos; + return this->parse_authority_i (is, sos, 0); + } + + int URL_INetBase::parse_authority_i (std::istream& is, + std::ostream& os, + int lastch) + { + static const int eof = + std::char_traits<ACE::IOS::CString_OStream::char_type>::eof (); + + ACE::IOS::CString_OStream& sos = + dynamic_cast<ACE::IOS::CString_OStream&> (os); + + int ch = lastch; + if (ch == 0) + { + // parse host part + for (ch = is.get (); +#if defined (ACE_HAS_IPV6) + ch != '[' && ch != '/' && ch != ':' && ch != '@' && ch != '?' && ch != '#' && ch != eof ; +#else + ch != '/' && ch != ':' && ch != '@' && ch != '?' && ch != '#' && ch != eof ; +#endif + ch = is.get ()) + sos.put (ch); + } + +#if defined (ACE_HAS_IPV6) + if (ch == '[') + { + sos.clear (); + for (ch = is.get (); ch != ']' && ch != eof ;ch = is.get ()) + sos.put (ch); + if (ch != eof) + ch = is.get (); // skip ']' + if (ch != '/' && ch != ':' && ch != '?' && ch != '#' && ch != eof) + { + this->set_host (empty_); // invalid URL, clear host field + ch = eof; // stop parsing + } + else + { + this->set_host (sos.str ()); + } + } + else + { +#endif + this->set_host (sos.str ()); +#if defined (ACE_HAS_IPV6) + } +#endif + sos.clear (); + + if (ch == ':') + { + u_short port = 0; + is >> port; // should stop at '/' or '?' or '#' or eof + ch = is.get (); + if (ch == '/' || ch == '?' || ch == '#' || ch == eof) + this->set_port (port); + else + this->set_port (0); + } + else + { + this->set_port (this->default_port ()); + } + + return ch; + } + + bool URL_INetBase::has_authority () + { + return true; + } + + bool URL_INetBase::validate () + { + return !this->host_.empty () && this->port_>0; + } + + ACE_CString URL_INetBase::get_authority () const + { + ACE::IOS::CString_OStream sos; + sos << this->get_host().c_str (); + if (this->get_port () != this->default_port ()) + sos << ':' << this->get_port (); + return sos.str (); + } + + URL_INetAuthBase::authenticator_map URL_INetAuthBase::authenticators_; + + URL_INetAuthBase::URL_INetAuthBase (u_short port) + : URL_INetBase (port) + { + } + + URL_INetAuthBase::~URL_INetAuthBase () {} + + ACE_CString URL_INetAuthBase::get_authority () const + { + ACE::IOS::CString_OStream sos; + if (!this->get_user_info ().empty ()) + sos << this->get_user_info ().c_str () << "@"; + sos << this->get_host().c_str (); + if (this->get_port () != this->default_port ()) + sos << ':' << this->get_port (); + return sos.str (); + } + + int URL_INetAuthBase::parse_authority (std::istream& is) + { + static const int eof = + std::char_traits<ACE::IOS::CString_OStream::char_type>::eof (); + + ACE::IOS::CString_OStream sos; + + int ch; + // parse userinfo (if any) + for (ch = is.get (); +#if defined (ACE_HAS_IPV6) + ch != '[' && ch != '/' && ch != ':' && ch != '@' && ch != '?' && ch != '#' && ch != eof ; +#else + ch != '/' && ch != ':' && ch != '@' && ch != '?' && ch != '#' && ch != eof ; +#endif + ch = is.get ()) + sos.put (ch); + + if (ch == '@') + { + this->set_user_info (sos.str ()); + sos.clear (); + ch = URL_INetBase::parse_authority_i (is, sos, 0); + } + else + { + ch = URL_INetBase::parse_authority_i (is, sos, ch); + } + + return ch; + } + + bool URL_INetAuthBase::add_authenticator (const ACE_CString& auth_id, + AuthenticatorBase* authenticator) + { + if (URL_INetAuthBase::authenticators_.find (auth_id) == -1) + { + return URL_INetAuthBase::authenticators_.bind (auth_id, + authenticator_ptr (authenticator)) == 0; + } + return false; + } + + bool URL_INetAuthBase::has_authenticator (const ACE_CString& auth_id) + { + return (URL_INetAuthBase::authenticators_.find (auth_id) == 0); + } + + AuthenticatorBase* URL_INetAuthBase::remove_authenticator (const ACE_CString& auth_id) + { + authenticator_ptr auth; + if (URL_INetAuthBase::authenticators_.unbind (auth_id, auth) == 0) + { + auth.release (); + } + return 0; + } + + bool URL_INetAuthBase::authenticate (AuthenticationBase& authentication) + { + ACE_GUARD_RETURN (ACE_SYNCH::RECURSIVE_MUTEX, + _guard, + URL_INetAuthBase::authenticators_.mutex (), + false); + + authenticator_map::iterator it = URL_INetAuthBase::authenticators_.begin (); + for (; it != URL_INetAuthBase::authenticators_.end (); + ++it) + { + authenticator_ptr auth_ptr = (*it).int_id_; + + // release lock before calling user code + if (URL_INetAuthBase::authenticators_.mutex ().release () != 0) + return false; + + if (auth_ptr->authenticate (authentication)) + return true; + + // re-acquire lock + if (URL_INetAuthBase::authenticators_.mutex ().acquire () != 0) + return false; + } + + return false; + } + } +} + +ACE_END_VERSIONED_NAMESPACE_DECL |