ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/Search/HttpHandler.cpp
(Generate patch)

Comparing trunk/Search/HttpHandler.cpp (file contents):
Revision 13 by douglas, 2002-12-06T19:56:56-08:00 vs.
Revision 20 by douglas, 2002-12-10T14:04:39-08:00

# Line 52 | Line 52
52  
53   HttpHandler::HttpHandler()
54   {
55 +        buffer = new char[BUFSIZ + 1];
56 +
57   #ifdef _WIN32
58 <        WSADATA data;
57 <        if (WSAStartup(MAKEWORD(2, 0) != 0, &data))
58 >        if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
59          {
60 <                error(program + ": WSAStartup()");
60 >                error(program + ": WSAStartup");
61                  exit(1);
62          }
63   #endif // _WIN32
64  
65 <        begin = 0;
65 >        length = 0;
66 >        chunked = false;
67   }
68  
69   HttpHandler::~HttpHandler()
70   {
71 +        delete [] buffer;
72 +
73   #ifdef _WIN32
74          WSACleanup();
75   #endif // _WIN32
76   }
77  
78 < bool HttpHandler::connect(URL &url, bool head)
78 > bool HttpHandler::handle(URL &url, bool head)
79   {
80          bool answer = false;
81  
82 < //      if (status != JNI_ERR)
83 < //      {
84 < //              if (cls != 0)
85 < //              {
86 < //                      if (mid != 0)
87 < //                      {
88 < //                              jstring addressJ = env->NewStringUTF(url.getAddress().c_str());
89 < //                              jint portJ = url.getPort();
90 < //                              jstring pathJ = env->NewStringUTF(url.getPath().c_str());
91 < //                              jstring programNameJ = env->NewStringUTF(programName.c_str());
92 < //                              jstring programVersionJ =
93 < //                                      env->NewStringUTF(programVersion.c_str());
94 <
95 < //                              jstring pageJ = (jstring)env->CallStaticObjectMethod(cls, mid,
96 < //                                      addressJ, portJ, pathJ, programNameJ, programVersionJ);
97 <
98 < //                              const char* pageC = env->GetStringUTFChars(pageJ, 0);
99 < //                              page = pageC;
100 < //                              env->ReleaseStringUTFChars(pageJ, pageC);
101 <
102 < //                              if (page != "unknown host\n" && page != "io exception\n" &&
103 < //                                      page != "bad headers\n") answer = true;
104 < //                      }
105 < //              }
106 < //      }
82 >        if ((http = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
83 >        {
84 >                error(program + ": Socket");
85 >                exit(1);
86 >        }
87 >
88 >        sockaddr_in address;
89 >        hostent* host;
90 >
91 >        address.sin_family = AF_INET;
92 >
93 >        if ((host = gethostbyname(url.getAddress().c_str())) == NULL)
94 >        {
95 >                error(program + ": Host: " + url.getAddress(), true);
96 >                return answer;
97 >        }
98 >
99 >        address.sin_addr = *((in_addr*)*host->h_addr_list);
100 >        address.sin_port = htons(url.getPort());
101 >
102 >        if (connect(http, (sockaddr*)&address, sizeof(sockaddr_in)) ==
103 >                SOCKET_ERROR)
104 >        {
105 >                error(program + ": Connect");
106 >                return answer;
107 >        }
108 >
109 >        if (head)
110 >        {
111 >                putline("HEAD " + url.getPath() + " HTTP/1.1");
112 >        }
113 >        else
114 >        {
115 >                putline("GET " + url.getPath() + " HTTP/1.1");
116 >        }
117 >
118 >        putline("Accept: text/html; text/plain");
119 >        putline("User-Agent: " + agent(true) + ' ' + platform());
120 >
121 >        if (url.getPort() == 80)
122 >        {
123 >                putline("Host: " + url.getAddress());
124 >        }
125 >        else
126 >        {
127 >                char* port = new char[1024];
128 >                sprintf(port, "%u", url.getPort());
129 >
130 >                putline("Host: " + url.getAddress() + ':' + port);
131 >
132 >                delete [] port;
133 >        }
134 >
135 > //      putline("Referer: " + ?referer?);
136 >        putline("Connection: close");
137 >        putline();
138 >
139 >        code response;
140 >        string line;
141 >
142 >        do
143 >        {
144 >                line = getline();
145 >
146 >                if (line.find("HTTP/") != 0)
147 >                {
148 >                        return answer;
149 >                }
150 >
151 >                unsigned dot = line.find('.');
152 >                unsigned space = line.find(' ');
153 >
154 >                unsigned major = strtoul(line.substr(5, dot - 5).c_str(), 0, 10);
155 >                unsigned minor = strtoul(line.substr(dot + 1, space - dot - 1).c_str(),
156 >                        0, 10);
157 >
158 >                if (major > 1 || minor < 1)
159 >                {
160 >                        cerr << program << ": Potentially Incompatible Server: HTTP/" <<
161 >                                major << "." << minor << "\n";
162 >
163 >                        return answer;
164 >                }
165 >
166 >                response = code(strtoul(line.substr(space + 1).c_str(), 0, 10));
167 >
168 >                if (response < ok) do line = getline(); while (line != "");
169 >        }
170 >        while (response < ok);
171 >
172 >        do
173 >        {
174 >                line = getline();
175 >
176 >                if (line != "")
177 >                {
178 >                        unsigned colon = line.find(':');
179 >
180 >                        string field = line.substr(0, colon);
181 >                        string value = line.substr(colon + 1);
182 >
183 >                        while (isspace(value[0])) value.erase(0, 1);
184 >
185 >                        if (field == "Content-Type")
186 >                        {
187 >                                type = value;
188 >                        }
189 >                        else if (field == "Content-Length")
190 >                        {
191 >                                length = strtoul(value.c_str(), 0, 10);
192 >                        }
193 >                        else if (field == "Location")
194 >                        {
195 >                                location = value;
196 >                        }
197 >                        else if (field == "Transfer-Encoding")
198 >                        {
199 >                                chunked = value == "chunked";
200 >                        }
201 >                }
202 >        }
203 >        while (line != "");
204 >
205 >        switch (response)
206 >        {
207 >        case ok:
208 >                if (debug) cerr << "response = " << response << "\n";
209 >                answer = true;
210 >                break;
211 >        case choices:
212 >        case moved:
213 >        case found:
214 >                if (debug) cerr << "response = " << response << "\n"
215 >                        << "location = " << location << "\n";
216 >                location = getLink(location, url);
217 >                break;
218 >        case notfound:
219 >        case internal:
220 >                if (debug) cerr << "response = " << response << "\n";
221 >                break;
222 >        default:
223 >                if (debug) cerr << "response = " << response << "\n";
224 >                if (response <= 299)
225 >                {
226 >                        answer = true;
227 >                }
228 >                else if (response <= 399)
229 >                {
230 >                        location = getLink(location, url);
231 >                }
232 >                break;
233 >        }
234 >
235 >        if (!head && answer) populate();
236  
237          return answer;
238   }
239  
240   HttpHandler& HttpHandler::getline(string& line, char endline)
241   {
242 <        int end = page.find(endline, begin);
243 <        int newline = page.find('\n', begin);
242 >        int end = page.find(endline);
243 >        int newline = page.find('\n');
244  
245          if (newline < end || end == string::npos)
246          {
247                  end = newline;
248          }
249  
250 <        line = page.substr(begin, end - begin);
250 >        line = page.substr(0, end);
251 >        page.erase(0, (end == string::npos ? end : end + 1));
252  
253 <        if (end == string::npos)
254 <        {
121 <                begin = end;
122 <        }
123 <        else
124 <        {
125 <                begin = end + 1;
126 <        }
253 > //      if (line == "") cerr << "line = [" << line << "]\npage = [" << page
254 > //              << "]" << (good() ? "true" : "false") << "\n";
255  
256          return *this;
257   }
258  
259 < bool HttpHandler::good()
259 > void HttpHandler::clear()
260 > {
261 >        closesocket(http);
262 >
263 >        type = "";
264 >        length = 0;
265 >        location = "";
266 >        page = "";
267 >        chunked = false;
268 > }
269 >
270 > void HttpHandler::populate()
271   {
272 <        bool answer = true;
272 >        if (!chunked)
273 >        {
274 >                unsigned left = length;
275  
276 <        if (begin >= page.length())
276 >                while (left > 0)
277 >                {
278 >                        memset(buffer, 0, BUFSIZ + 1);
279 >
280 >                        unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
281 >
282 >                        if (recv(http, buffer, bytes, 0) == SOCKET_ERROR)
283 >                        {
284 >                                error(program + ": Recv");
285 >                                exit(1);
286 >                        }
287 >
288 >                        page += buffer;
289 >                        left -= bytes;
290 >                }
291 >        }
292 >        else
293          {
294 <                answer = false;
294 >                unsigned chunk;
295 >
296 >                do
297 >                {
298 >                        chunk = strtoul(getline().c_str(), 0, 16);
299 >
300 >                        unsigned left = chunk;
301 >
302 >                        while (left > 0)
303 >                        {
304 >                                memset(buffer, 0, BUFSIZ + 1);
305 >
306 >                                unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
307 >
308 >                                if (recv(http, buffer, bytes, 0) == SOCKET_ERROR)
309 >                                {
310 >                                        error(program + ": Recv");
311 >                                        exit(1);
312 >                                }
313 >
314 >                                page += buffer;
315 >                                left -= bytes;
316 >                        }
317 >
318 >                        getline();
319 >                        length += chunk;
320 >                }
321 >                while (chunk > 0);
322          }
323 <        else if (begin == string::npos)
323 >
324 >        for (unsigned index = 0; index < page.length(); index++)
325          {
326 <                answer = false;
326 >                if (page[index] == '\r' && (index + 1 < page.length()) ? page[index +
327 >                        1] == '\n' : false)
328 >                {
329 >                        page.erase(index, 1);
330 >                }
331 >                else if (page[index] == '\r')
332 >                {
333 >                        page[index] = '\n';
334 >                }
335          }
336 + }
337  
338 <        return answer;
338 > void HttpHandler::putline(const string line)
339 > {
340 >        sprintf(buffer, "%s\r\n", line.c_str());
341 >        if (send(http, buffer, strlen(buffer), 0) == SOCKET_ERROR)
342 >        {
343 >                error(program + ": Send");
344 >                exit(1);
345 >        }
346   }
347  
348 < void HttpHandler::clear()
348 > string HttpHandler::getline()
349   {
350 <        begin = 0;
351 <        page = "";
350 >        string line;
351 >        char byte;
352 >
353 >        do
354 >        {
355 >                if (recv(http, &byte, 1, 0) == SOCKET_ERROR)
356 >                {
357 >                        error(program + ": Recv");
358 >                }
359 >
360 >                if (byte != '\r' && byte != '\n')
361 >                {
362 >                        line += byte;
363 >                }
364 >        }
365 >        while (byte != '\n');
366 >
367 >        return line;
368   }
369  
370 < void HttpHandler::error(const string prefix, bool host)
370 > void HttpHandler::error(const string& prefix, bool host)
371   {
372   #ifdef _WIN32
373          string error;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines