Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

URL.cc

Go to the documentation of this file.
00001 /*
00002  * URL.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Unified resource locator.
00006  *
00007  * Copyright (c) 2004 Milan Cermak
00008  */
00009 /*
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /* Class-accessing protocol */
00042 String *URL::className(void) const
00043 {
00044     return new String("URL");
00045 }
00046 
00047 /* Instance creation protocol */
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 /* Initialize protocol */
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 /* Accessing protocol */
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 /* Converting protocol */
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 /* Printing protocol */
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 }

Generated on Mon Nov 27 09:47:56 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2