00001
00002
00003
00004
00005
00006
00007
00008 #include "wvhttp.h"
00009 #include "strutils.h"
00010 #include <assert.h>
00011
00012
00013
00014 WvHTTPStream::WvHTTPStream(const WvURL &_url)
00015 : WvStreamClone(NULL), headers(7), client_headers(7),
00016 url(_url)
00017 {
00018 state = Resolving;
00019 num_received = 0;
00020 tcp = NULL;
00021
00022
00023
00024 url.resolve();
00025 }
00026
00027
00028 bool WvHTTPStream::isok() const
00029 {
00030 if (cloned)
00031 return WvStreamClone::isok();
00032 else
00033 return url.isok();
00034 }
00035
00036
00037 int WvHTTPStream::geterr() const
00038 {
00039 if (cloned)
00040 return WvStreamClone::geterr();
00041 else
00042 return -1;
00043 }
00044
00045
00046 WvString WvHTTPStream::errstr() const
00047 {
00048 if (cloned)
00049 return WvStreamClone::errstr();
00050 else if (!url.isok())
00051 return url.errstr();
00052 else
00053 return "Unknown error! (no stream yet)";
00054 }
00055
00056
00057 bool WvHTTPStream::pre_select(SelectInfo &si)
00058 {
00059 if (!isok()) return false;
00060
00061 switch (state)
00062 {
00063 case Resolving:
00064 if (!url.isok())
00065 seterr("Invalid URL");
00066 else if (url.resolve())
00067 {
00068 state = Connecting;
00069 cloned = tcp = new WvTCPConn(url.getaddr());
00070 }
00071 return false;
00072
00073 case Connecting:
00074 tcp->select(0, false, true, false);
00075 if (!tcp->isconnected())
00076 return false;
00077 if (tcp->geterr())
00078 return false;
00079
00080
00081 state = ReadHeader1;
00082 delay_output(true);
00083 print("GET %s HTTP/1.0\r\n", url.getfile());
00084 print("Host: %s:%s\r\n", url.gethost(), url.getport());
00085 {
00086 WvHTTPHeaderDict::Iter i(client_headers);
00087 for (i.rewind(); i.next(); )
00088 {
00089 print("%s: %s\r\n", i().name, i().value);
00090 }
00091 }
00092 print("\r\n");
00093 delay_output(false);
00094
00095
00096
00097 default:
00098 return WvStreamClone::isok()
00099 && WvStreamClone::pre_select(si);
00100 }
00101 }
00102
00103
00104 size_t WvHTTPStream::uread(void *buf, size_t count)
00105 {
00106 char *line;
00107 int retval;
00108 size_t len;
00109
00110 switch (state)
00111 {
00112 case Resolving:
00113 case Connecting:
00114 break;
00115
00116 case ReadHeader1:
00117 line = trim_string(tcp->getline(0));
00118 if (line)
00119 {
00120 if (strncmp(line, "HTTP/", 5))
00121 {
00122 seterr("Invalid HTTP response");
00123 return 0;
00124 }
00125
00126 retval = atoi(trim_string(line+9));
00127
00128 if (retval / 100 != 2)
00129 {
00130 seterr(WvString("HTTP error: %s", trim_string(line+9)));
00131 return 0;
00132 }
00133
00134 state = ReadHeader;
00135 }
00136 break;
00137
00138 case ReadHeader:
00139 line = trim_string(tcp->getline(0));
00140 if (line)
00141 {
00142 if (!line[0])
00143 state = ReadData;
00144 else
00145 {
00146 char *cptr = strchr(line, ':');
00147 if (!cptr)
00148 headers.add(new WvHTTPHeader(line, ""), true);
00149 else
00150 {
00151 *cptr++ = 0;
00152 line = trim_string(line);
00153 cptr = trim_string(cptr);
00154 headers.add(new WvHTTPHeader(line, cptr), true);
00155 }
00156 }
00157 }
00158 break;
00159
00160 case ReadData:
00161 len = tcp->read(buf, count);
00162 num_received += len;
00163 return len;
00164
00165 case Done:
00166 break;
00167 }
00168
00169 return 0;
00170 }