00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stlib/net/URL.h>
00025
00026 #include <stlib/ByteArray.h>
00027 #include <stlib/Integer.h>
00028 #include <stlib/String.h>
00029 #include <stlib/WriteStream.h>
00030 #include <stlib/net/IPSocketAddress.h>
00031
00032 #include <stlib/Error.h>
00033
00034 using namespace Net;
00035
00036 URL::URL(String *protocol)
00037 {
00038 _proto = protocol;
00039 }
00040
00041
00042 String *URL::className(void) const
00043 {
00044 return new String("URL");
00045 }
00046
00047
00048 URL *URL::fromString(String *urlString)
00049 {
00050 URL *url;
00051 String *proto;
00052 long protoIdx;
00053
00054 if (!urlString->includesSubcollection("://")) {
00055 (new Error(new String("Protocol expected in url string."),
00056 new String(__PRETTY_FUNCTION__), urlString))->raise();
00057 }
00058 protoIdx = urlString->indexOf(':');
00059 proto = dynamic_cast<String *>(urlString->copy(0, protoIdx));
00060 urlString = dynamic_cast<String *>(urlString->copy(proto->size() + 3, urlString->size()));
00061 url = new URL(proto);
00062 url->parseHost(urlString);
00063
00064 return url;
00065 }
00066
00067
00068 void URL::parseHost(String *urlWithPath)
00069 {
00070 long portIdx = urlWithPath->indexOf(':');
00071 long pathIdx = urlWithPath->indexOf('/');
00072 long fragmentIdx = urlWithPath->indexOf('#');
00073 long queryIdx = urlWithPath->indexOf('?');
00074
00075 if (queryIdx > 0) {
00076 _query = dynamic_cast<String *>(urlWithPath->copy(queryIdx + 1,
00077 urlWithPath->size()));
00078 } else queryIdx = urlWithPath->size();
00079
00080 if (fragmentIdx > 0) {
00081 _fragment = dynamic_cast<String *>(urlWithPath->copy(fragmentIdx + 1,
00082 queryIdx));
00083 } else fragmentIdx = queryIdx;
00084
00085 if (pathIdx > 0) {
00086 _path = dynamic_cast<String *>(urlWithPath->copy(pathIdx + 1, fragmentIdx));
00087 } else pathIdx = fragmentIdx;
00088
00089 if (portIdx > 0) {
00090 String *portStr = dynamic_cast<String *>(urlWithPath->copy(portIdx + 1,
00091 pathIdx));
00092 _port = portStr->asNumber()->asLong() & 0xffff;
00093 } else {
00094 _port = 0;
00095 portIdx = pathIdx;
00096 }
00097
00098 _host = dynamic_cast<String *>(urlWithPath->copy(0, portIdx));
00099 }
00100
00101
00102 String *URL::protocol(void)
00103 {
00104 return _proto;
00105 }
00106
00107 String *URL::host(void)
00108 {
00109 return _host;
00110 }
00111
00112 ByteArray *URL::hostAddress(void)
00113 {
00114 return socketAddress()->hostAddress();
00115 }
00116
00117 String *URL::hostAndPort(void)
00118 {
00119 if (_port <= 0)
00120 return _host;
00121 return dynamic_cast<String *>(&(*_host + *(String::format(":%u", _port))));
00122 }
00123
00124 String *URL::pathString(void)
00125 {
00126 Stream *stream = (new String(64))->writeStream();
00127 stream->nextPut('/');
00128 stream->nextPutAll(_path);
00129 if (_query != nil) {
00130 stream->nextPut('?');
00131 stream->nextPutAll(_query);
00132 }
00133 return dynamic_cast<String *>(stream->contents());
00134 }
00135
00136 unsigned short URL::port(void)
00137 {
00138 return _port;
00139 }
00140
00141 IPSocketAddress *URL::socketAddress(void)
00142 {
00143 return IPSocketAddress::hostName(_host, _port);
00144 }
00145
00146
00147 String *URL::asString(void) const
00148 {
00149 Stream *stream = (new String(64))->writeStream();
00150 printContentOn(stream);
00151 return dynamic_cast<String *>(stream->contents());
00152 }
00153
00154
00155 void URL::printOn(Stream *stream) const
00156 {
00157 stream->nextPut('<');
00158 printContentOn(stream);
00159 stream->nextPut('>');
00160 }
00161
00162 void URL::printContentOn(Stream *stream) const
00163 {
00164 stream->nextPutAll(_proto);
00165 stream->nextPutAll("://");
00166 stream->nextPutAll(_host);
00167 if (_port > 0) {
00168 stream->nextPut(':');
00169 stream->print((long int) _port);
00170 }
00171 stream->nextPut('/');
00172 stream->nextPutAll(_path);
00173 if (_query != nil) {
00174 stream->nextPut('?');
00175 stream->nextPutAll(_query);
00176 }
00177 }