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 1 by douglas, 2002-12-04T20:22:59-08:00 vs.
Revision 19 by douglas, 2002-12-10T00:02:22-08:00

# Line 50 | Line 50
50  
51   #include "HttpHandler.h"
52  
53 #ifdef _WIN32
54 #define PATH_SEPARATOR "\\"
55 #define ENV_SEPARATOR ';'
56 #else
57 #define PATH_SEPARATOR "/"
58 #define ENV_SEPARATOR ':'
59 #endif
60
53   HttpHandler::HttpHandler()
54   {
55 <        string arguments = "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/Strin"
64 <                + string("g;Ljava/lang/String;)Ljava/lang/String;");
65 <
66 <        begin = 0;
55 >        buffer = new char[BUFSIZ + 1];
56  
57 <        setJarPath();
57 > #ifdef _WIN32
58 >        if (WSAStartup(MAKEWORD(2, 0), &data) != 0)
59 >        {
60 >                error(program + ": WSAStartup");
61 >                exit(1);
62 >        }
63 > #endif // _WIN32
64  
65 < //      options[0].optionString = jarPath;
66 < //      memset(&vm_args, 0, sizeof (vm_args));
67 < //      vm_args.version = JNI_VERSION_1_4;
73 < //      vm_args.nOptions = 1;
74 < //      vm_args.options = options;
75 <
76 < //      status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
77 <
78 < //      if (status != JNI_ERR)
79 < //      {
80 < //              cls = env->FindClass("HttpConnector");
81 <
82 < //              if (cls != 0)
83 < //              {
84 < //                      mid = env->GetStaticMethodID(cls, "connect", arguments.c_str());
85 < //              }
86 < //      }
65 >        begin = 0;
66 >        length = 0;
67 >        chunked = false;
68   }
69  
70   HttpHandler::~HttpHandler()
71   {
72 < //      if (status != JNI_ERR)
92 < //      {
93 < //              jvm->DestroyJavaVM();
94 < //      }
72 >        delete [] buffer;
73  
74 < //      delete [] jarPath;
74 > #ifdef _WIN32
75 >        WSACleanup();
76 > #endif // _WIN32
77   }
78  
79 < bool HttpHandler::connect(URL& url)
79 > bool HttpHandler::handle(URL &url, bool head)
80   {
81          bool answer = false;
82  
83 < //      if (status != JNI_ERR)
84 < //      {
85 < //              if (cls != 0)
86 < //              {
87 < //                      if (mid != 0)
88 < //                      {
89 < //                              jstring addressJ = env->NewStringUTF(url.getAddress().c_str());
90 < //                              jint portJ = url.getPort();
91 < //                              jstring pathJ = env->NewStringUTF(url.getPath().c_str());
92 < //                              jstring programNameJ = env->NewStringUTF(programName.c_str());
93 < //                              jstring programVersionJ =
94 < //                                      env->NewStringUTF(programVersion.c_str());
95 <
96 < //                              jstring pageJ = (jstring)env->CallStaticObjectMethod(cls, mid,
97 < //                                      addressJ, portJ, pathJ, programNameJ, programVersionJ);
98 <
99 < //                              const char* pageC = env->GetStringUTFChars(pageJ, 0);
100 < //                              page = pageC;
101 < //                              env->ReleaseStringUTFChars(pageJ, pageC);
102 <
103 < //                              if (page != "unknown host\n" && page != "io exception\n" &&
104 < //                                      page != "bad headers\n") answer = true;
105 < //                      }
106 < //              }
107 < //      }
83 >        if ((http = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
84 >        {
85 >                error(program + ": Socket");
86 >                exit(1);
87 >        }
88 >
89 >        sockaddr_in address;
90 >        hostent* host;
91 >
92 >        address.sin_family = AF_INET;
93 >
94 >        if ((host = gethostbyname(url.getAddress().c_str())) == NULL)
95 >        {
96 >                error(program + ": Host: " + url.getAddress(), true);
97 >                return answer;
98 >        }
99 >
100 >        address.sin_addr = *((in_addr*)*host->h_addr_list);
101 >        address.sin_port = htons(url.getPort());
102 >
103 >        if (connect(http, (sockaddr*)&address, sizeof(sockaddr_in)) ==
104 >                SOCKET_ERROR)
105 >        {
106 >                error(program + ": Connect");
107 >                return answer;
108 >        }
109 >
110 >        if (head)
111 >        {
112 >                putline("HEAD " + url.getPath() + " HTTP/1.1");
113 >        }
114 >        else
115 >        {
116 >                putline("GET " + url.getPath() + " HTTP/1.1");
117 >        }
118 >
119 >        putline("Accept: text/html; text/plain");
120 >        putline("User-Agent: " + agent(true) + ' ' + platform());
121 >
122 >        if (url.getPort() == 80)
123 >        {
124 >                putline("Host: " + url.getAddress());
125 >        }
126 >        else
127 >        {
128 >                char* port = new char[1024];
129 >                sprintf(port, "%u", url.getPort());
130 >
131 >                putline("Host: " + url.getAddress() + ':' + port);
132 >
133 >                delete [] port;
134 >        }
135 >
136 > //      putline("Referer: " + ?referer?);
137 >        putline("Connection: close");
138 >        putline();
139 >
140 >        code response;
141 >        string line;
142 >
143 >        do
144 >        {
145 >                line = getline();
146 >
147 >                if (line.find("HTTP/") != 0)
148 >                {
149 >                        return answer;
150 >                }
151 >
152 >                unsigned dot = line.find('.');
153 >                unsigned space = line.find(' ');
154 >
155 >                unsigned major = strtoul(line.substr(5, dot - 5).c_str(), 0, 10);
156 >                unsigned minor = strtoul(line.substr(dot + 1, space - dot - 1).c_str(),
157 >                        0, 10);
158 >
159 >                if (major > 1 || minor < 1)
160 >                {
161 >                        cerr << program << ": Potentially Incompatible Server: HTTP/" <<
162 >                                major << "." << minor << "\n";
163 >
164 >                        return answer;
165 >                }
166 >
167 >                response = code(strtoul(line.substr(space + 1).c_str(), 0, 10));
168 >
169 >                if (response < ok) do line = getline(); while (line != "");
170 >        }
171 >        while (response < ok);
172 >
173 >        do
174 >        {
175 >                line = getline();
176 >
177 >                if (line != "")
178 >                {
179 >                        unsigned colon = line.find(':');
180 >
181 >                        string field = line.substr(0, colon);
182 >                        string value = line.substr(colon + 1);
183 >
184 >                        while (isspace(value[0])) value.erase(0, 1);
185 >
186 >                        if (field == "Content-Type")
187 >                        {
188 >                                type = value;
189 >                        }
190 >                        else if (field == "Content-Length")
191 >                        {
192 >                                length = strtoul(value.c_str(), 0, 10);
193 >                        }
194 >                        else if (field == "Location")
195 >                        {
196 >                                location = value;
197 >                        }
198 >                        else if (field == "Transfer-Encoding")
199 >                        {
200 >                                chunked = value == "chunked";
201 >                        }
202 >                }
203 >        }
204 >        while (line != "");
205 >
206 >        switch (response)
207 >        {
208 >        case ok:
209 >                if (debug) cerr << "response = " << response << "\n";
210 >                answer = true;
211 >                break;
212 >        case choices:
213 >        case moved:
214 >        case found:
215 >                if (debug) cerr << "response = " << response << "\n"
216 >                        << "location = " << location << "\n";
217 >                location = getLink(location, url);
218 >                break;
219 >        case notfound:
220 >        case internal:
221 >                if (debug) cerr << "response = " << response << "\n";
222 >                break;
223 >        default:
224 >                if (debug) cerr << "response = " << response << "\n";
225 >                if (response <= 299)
226 >                {
227 >                        answer = true;
228 >                }
229 >                else if (response <= 399)
230 >                {
231 >                        location = getLink(location, url);
232 >                }
233 >                break;
234 >        }
235 >
236 >        if (!head && answer) populate();
237  
238          return answer;
239   }
# Line 171 | Line 280 | bool HttpHandler::good()
280  
281   void HttpHandler::clear()
282   {
283 +        closesocket(http);
284 +
285 +        type = "";
286 +        length = 0;
287 +        location = "";
288          begin = 0;
289          page = "";
290 +        chunked = false;
291   }
292  
293 < void HttpHandler::setJarPath()
293 > void HttpHandler::populate()
294   {
295 <        const string jarFile = "HttpConnector.jar";
181 <        string jarFilePath = jarFile;
182 <
183 <        ifstream fin(jarFilePath.c_str());
184 <        if (!fin.is_open())
295 >        if (!chunked)
296          {
297 <                unsigned end = program.rfind(PATH_SEPARATOR);
298 <                if (end != string::npos)
297 >                unsigned left = length;
298 >
299 >                while (left > 0)
300                  {
301 <                        string path = program.substr(0, end);
301 >                        memset(buffer, 0, BUFSIZ + 1);
302  
303 <                        jarFilePath = path + PATH_SEPARATOR + jarFile;
303 >                        unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
304  
305 <                        fin.open(jarFilePath.c_str());
194 <                        if (!fin.is_open())
305 >                        if (recv(http, buffer, bytes, 0) == SOCKET_ERROR)
306                          {
307 <                                cerr << program << ": Could not find required file: "
197 <                                        << jarFile << "\n";
307 >                                error(program + ": Revc");
308                                  exit(1);
309                          }
310 <                        else
311 <                        {
312 <                                fin.close();
203 <                        }
310 >
311 >                        page += buffer;
312 >                        left -= bytes;
313                  }
314 <                else
315 <                {
316 <                        string envPath = getenv("PATH");
314 >        }
315 >        else
316 >        {
317 >                //
318 >        }
319  
320 <                        if (debug) cerr << "envPath = " << envPath << "\n";
320 >        cerr << "\n[" << page << "]\n";
321 > }
322  
323 <                        unsigned begin = 0;
324 <                        do
325 <                        {
326 <                                unsigned end = envPath.find(ENV_SEPARATOR, begin);
327 <                                string path = envPath.substr(begin, end);
323 > void HttpHandler::putline(const string line)
324 > {
325 >        sprintf(buffer, "%s\r\n", line.c_str());
326 >        if (send(http, buffer, strlen(buffer), 0) == SOCKET_ERROR)
327 >        {
328 >                error(program + ": Send");
329 >                exit(1);
330 >        }
331 > }
332  
333 <                                if (debug) cerr << "path = " << path << "\n";
333 > string HttpHandler::getline()
334 > {
335 >        string line;
336 >        char byte;
337  
338 <                                jarFilePath = path + PATH_SEPARATOR + jarFile;
338 >        do
339 >        {
340 >                if (recv(http, &byte, 1, 0) == SOCKET_ERROR)
341 >                {
342 >                        error(program + ": Recv");
343 >                }
344  
345 <                                fin.open(jarFilePath.c_str());
346 <                                if (fin.is_open())
347 <                                {
348 <                                        fin.close();
349 <                                        break;
350 <                                }
345 >                if (byte != '\r' && byte != '\n')
346 >                {
347 >                        line += byte;
348 >                }
349 >        }
350 >        while (byte != '\n');
351  
352 <                                begin = end != string::npos ? end + 1 : string::npos;
353 <                        }
230 <                        while (begin < envPath.length());
352 >        return line;
353 > }
354  
355 <                        if (begin == string::npos)
356 <                        {
357 <                                cerr << program << ": Could not find required file: "
358 <                                        << jarFile << "\n";
359 <                                exit(1);
360 <                        }
361 <                }
355 > void HttpHandler::error(const string& prefix, bool host)
356 > {
357 > #ifdef _WIN32
358 >        string error;
359 >
360 >        switch (WSAGetLastError())
361 >        {
362 >        case WSAEACCES:
363 >                error = "Permission denied.";
364 >                break;
365 >        case WSAEADDRINUSE:
366 >                error = "Address already in use.";
367 >                break;
368 >        case WSAEADDRNOTAVAIL:
369 >                error = "Cannot assign requested address.";
370 >                break;
371 >        case WSAEAFNOSUPPORT:
372 >                error = "Address family not supported by protocol family.";
373 >                break;
374 >        case WSAEALREADY:
375 >                error = "Operation already in progress.";
376 >                break;
377 >        case WSAECONNABORTED:
378 >                error = "Software caused connection abort.";
379 >                break;
380 >        case WSAECONNREFUSED:
381 >                error = "Connection refused.";
382 >                break;
383 >        case WSAECONNRESET:
384 >                error = "Connection reset by peer.";
385 >                break;
386 >        case WSAEDESTADDRREQ:
387 >                error = "Destination address required.";
388 >                break;
389 >        case WSAEFAULT:
390 >                error = "Bad address.";
391 >                break;
392 >        case WSAEHOSTDOWN:
393 >                error = "Host is down.";
394 >                break;
395 >        case WSAEHOSTUNREACH:
396 >                error = "No route to host.";
397 >                break;
398 >        case WSAEINPROGRESS:
399 >                error = "Operation now in progress.";
400 >                break;
401 >        case WSAEINTR:
402 >                error = "Interrupted function call.";
403 >                break;
404 >        case WSAEINVAL:
405 >                error = "Invalid argument.";
406 >                break;
407 >        case WSAEISCONN:
408 >                error = "Socket is already connected.";
409 >                break;
410 >        case WSAEMFILE:
411 >                error = "Too many open files.";
412 >                break;
413 >        case WSAEMSGSIZE:
414 >                error = "Message too long.";
415 >                break;
416 >        case WSAENETDOWN:
417 >                error = "Network is down.";
418 >                break;
419 >        case WSAENETRESET:
420 >                error = "Network dropped connection on reset.";
421 >                break;
422 >        case WSAENETUNREACH:
423 >                error = "Network is unreachable.";
424 >                break;
425 >        case WSAENOBUFS:
426 >                error = "No buffer space available.";
427 >                break;
428 >        case WSAENOPROTOOPT:
429 >                error = "Bad protocol option.";
430 >                break;
431 >        case WSAENOTCONN:
432 >                error = "Socket is not connected.";
433 >                break;
434 >        case WSAENOTSOCK:
435 >                error = "Socket operation on non-socket.";
436 >                break;
437 >        case WSAEOPNOTSUPP:
438 >                error = "Operation not supported.";
439 >                break;
440 >        case WSAEPFNOSUPPORT:
441 >                error = "Protocol family not supported.";
442 >                break;
443 >        case WSAEPROCLIM:
444 >                error = "Too many processes.";
445 >                break;
446 >        case WSAEPROTONOSUPPORT:
447 >                error = "Protocol not supported.";
448 >                break;
449 >        case WSAEPROTOTYPE:
450 >                error = "Protocol wrong type for socket.";
451 >                break;
452 >        case WSAESHUTDOWN:
453 >                error = "Cannot send after socket shutdown.";
454 >                break;
455 >        case WSAESOCKTNOSUPPORT:
456 >                error = "Socket type not supported.";
457 >                break;
458 >        case WSAETIMEDOUT:
459 >                error = "Connection timed out.";
460 >                break;
461 >        case WSATYPE_NOT_FOUND:
462 >                error = "Class type not found.";
463 >                break;
464 >        case WSAEWOULDBLOCK:
465 >                error = "Resource temporarily unavailable.";
466 >                break;
467 >        case WSAHOST_NOT_FOUND:
468 >                error = "Host not found.";
469 >                break;
470 >        case WSA_INVALID_HANDLE:
471 >                error = "Specified event object handle is invalid.";
472 >                break;
473 >        case WSA_INVALID_PARAMETER:
474 >                error = "One or more parameters are invalid.";
475 >                break;
476 > //      case WSAINVALIDPROCTABLE:
477 > //              error = "Invalid procedure table from service provider.";
478 > //              break;
479 > //      case WSAINVALIDPROVIDER:
480 > //              error = "Invalid service provider version number.";
481 > //              break;
482 >        case WSA_IO_INCOMPLETE:
483 >                error = "Overlapped I/O event object not in signaled state.";
484 >                break;
485 >        case WSA_IO_PENDING:
486 >                error = "Overlapped operations will complete later.";
487 >                break;
488 >        case WSA_NOT_ENOUGH_MEMORY:
489 >                error = "Insufficient memory available.";
490 >                break;
491 >        case WSANOTINITIALISED:
492 >                error = "Successful WSAStartup not yet performed.";
493 >                break;
494 >        case WSANO_DATA:
495 >                error = "Valid name, no data record of requested type.";
496 >                break;
497 >        case WSANO_RECOVERY:
498 >                error = "This is a non-recoverable error.";
499 >                break;
500 > //      case WSAPROVIDERFAILEDINIT:
501 > //              error = "Unable to initialize a service provider.";
502 > //              break;
503 >        case WSASYSCALLFAILURE:
504 >                error = "System call failure.";
505 >                break;
506 >        case WSASYSNOTREADY:
507 >                error = "Network subsystem is unavailable.";
508 >                break;
509 >        case WSATRY_AGAIN:
510 >                error = "Non-authoritative host not found.";
511 >                break;
512 >        case WSAVERNOTSUPPORTED:
513 >                error = "WINSOCK.DLL version out of range.";
514 >                break;
515 >        case WSAEDISCON:
516 >                error = "Graceful shutdown in progress.";
517 >                break;
518 >        case WSA_OPERATION_ABORTED:
519 >                error = "Overlapped operation aborted.";
520 >                break;
521 >        default:
522 >                error = "Unknown error.";
523 >                break;
524 >        }
525 >
526 >        cerr << prefix << ": " << error << "\n";
527 > #else
528 >        if (host)
529 >        {
530 >                herror(prefix.c_str());
531          }
532          else
533          {
534 <                fin.close();
534 >                perror(prefix.c_str());
535          }
536 <
245 <        string jarPath = "-Djava.class.path=" + jarFilePath;
246 <
247 < //      this->jarPath = new char[jarPath.length()];
248 < //      strcpy(this->jarPath, jarPath.c_str());
536 > #endif // _WIN32
537   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines