#include "ace/OS_NS_string.h" #include "ace/OS_NS_stdlib.h" #include "ace/Log_Msg.h" #include "HTTPU/parse_url.h" HTTP_Parse_URL::HTTP_Parse_URL (const char *url) : url_ (0), scheme_ (0), user_ (0), passwd_ (0), host_ (0), port_ (-1), url_path_ (0), error_ (URL_ERROR_NONE), is_cgi_ (0) { this->init (url); } HTTP_Parse_URL::~HTTP_Parse_URL () { if (this->url_) ACE_OS::free (this->url_); this->url_ = 0; this->scheme_ = 0; this->user_ = 0; this->passwd_ = 0; this->host_ = 0; this->port_ = -1; this->url_path_ = 0; } void HTTP_Parse_URL::init( const char *url ) { // Should really reset completely and cleanly here before // doing anything else! if ( url == 0 ) return; if ( url_ ) ACE_OS::free( url_ ); url_ = ACE_OS::strdup( url ); if ( url_ == 0 ) { error_ = URL_ERROR_STRDUP; return; } if (ACE_OS::strlen (this->url_) > 3 && ACE_OS::strstr ("://", this->url_)) { // Parse it out completely. Figure out what it is later. parse_url(); } else { this->url_path_ = this->url_; this->is_cgi (this->url_path_); } } void HTTP_Parse_URL::parse_url () { char *p = this->url_; char *q; if ((q = ACE_OS::strchr (this->url_, '\r')) || (q = ACE_OS::strchr (this->url_, '\n'))) *q = '\0'; this->parse_scheme (p); if (*p == '\0') { this->error_ = URL_ERROR_SCHEME; return; } // Parse past "//" if (*p != '/' || *(p+1) != '/') { this->error_ = URL_ERROR_SLASHSLASH; return; } p += 2; this->parse_host (p); while (*p == '/') p++; if (*p == '\0') return; this->url_path_ = p; this->is_cgi (this->url_path_); } void HTTP_Parse_URL::parse_scheme (char *&p) { // Parse the scheme. The scheme is delimited by a ':'. if (*p != '\0') { this->scheme_ = p++; for (;;) { switch (*p) { case '\0': break; case ':': *p++ = '\0'; break; default: p++; continue; } break; } } } void HTTP_Parse_URL::parse_host (char *&p) { // Parse user, password, host, port if (*p == '/' || *p == '\0') { this->set_port_from_scheme (); return; } char *at = 0; char *colon1 = 0; char *colon2 = 0; char *q = p; while (*q != '\0') { if (*q == '/') { *q = '\0'; q++; break; } if (*q == ':') { if (colon1 == 0) { if (at != 0 && colon2 == 0) colon2 = q; else colon1 = q; } else { if (at != 0 && colon2 == 0) colon2 = q; } } if (*q == '@') { if (at == 0) at = q; } q++; } // no user, no port if (at == 0 && colon1 == 0) { if (*p != '\0' && *p != '/') this->host_ = p; } // no user, port else if (at == 0 && colon1 != 0) { if (p != colon1) this->host_ = p; *colon1++ = '\0'; this->port_ = ACE_OS::atoi (colon1); } // user, no passwd, no port else if (at != 0 && colon1 == 0 && colon2 == 0) { this->user_ = p; *at++ = '\0'; if (*at != '\0' && *at != '/') this->host_ = at; } // user, no passwd, port else if (at != 0 && colon1 == 0 && colon2 != 0) { this->user_ = p; *at++ = '\0'; if (at != colon2) this->host_ = at; *colon2++ = '\0'; this->port_ = ACE_OS::atoi (colon2); } // user, passwd, no port else if (at != 0 && colon1 != 0 && colon2 == 0) { this->user_ = p; *colon1++ = '\0'; this->passwd_ = colon1; *at++ = '\0'; if (*at != '\0') this->host_ = at; } // user, passwd, and port else if (at != 0 && colon1 != 0 && colon2 != 0) { this->user_ = p; *colon1++ = '\0'; this->passwd_ = colon1; *at++ = '\0'; if (at != colon2) this->host_ = at; *colon2++ = '\0'; this->port_ = ACE_OS::atoi (colon2); } // impossible! else { ACE_ERROR ((LM_ERROR, "uh oh!\n")); p = q; return; } this->set_port_from_scheme (); p = q; } void HTTP_Parse_URL::set_port_from_scheme () { if (ACE_OS::strcmp (this->scheme_, "ftp") == 0) { if (this->port_ == -1) this->port_ = 21; if (this->user_ == 0) { this->user_ = "anonymous"; // *** need something better here this->passwd_ = "a@b.c"; } } else if (ACE_OS::strcmp (this->scheme_, "http") == 0) { if (this->port_ == -1) this->port_ = 80; } } const char * HTTP_Parse_URL::scheme () const { return this->scheme_; } const char * HTTP_Parse_URL::user () const { return this->user_; } const char * HTTP_Parse_URL::passwd () const { return this->passwd_; } const char * HTTP_Parse_URL::host () const { return this->host_; } int HTTP_Parse_URL::port () const { return this->port_; } const char * HTTP_Parse_URL::url_path () const { return this->url_path_ ? this->url_path_ : ""; } void HTTP_Parse_URL::is_cgi (const char *path) { int yes; yes = (ACE_OS::strchr (path, '?') != 0); if (!yes && (ACE_OS::strlen (path) >= 3)) yes = (ACE_OS::strstr (path, "cgi") != 0); if (!yes) yes = (ACE_OS::strstr (path, "asp") != 0); this->is_cgi_ = yes; } int HTTP_Parse_URL::is_cgi () const { return this->is_cgi_; }