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 201 by douglas, 2003-07-15T01:01:00-07:00 vs.
Revision 334 by Douglas Thrift, 2004-04-05T16:37:41-07:00

# Line 1 | Line 1
1   /* ============================================================================
2   * Douglas Thrift's Search Engine License
3   *
4 < * Copyright (C) 2002-2003, Douglas Thrift. All Rights Reserved.
4 > * Copyright (C) 2002-2004, Douglas Thrift. All Rights Reserved.
5   * Redistribution and use in source and binary forms, with or without
6   * modification, are permitted provided that the following conditions are met:
7   *
# Line 46 | Line 46
46   //
47   // Douglas Thrift
48   //
49 < // $Id: HttpHandler.cpp,v 1.19 2003/07/15 08:01:00 douglas Exp $
49 > // $Id$
50  
51 < #include "HttpHandler.h"
51 > #include "HttpHandler.hpp"
52  
53   // Lovely C Sockets!
54   #ifndef _WIN32
# Line 59 | Line 59
59   #include <netinet/in.h>
60   #include <netdb.h>
61  
62 #define INVALID_SOCKET -1
63 #define SOCKET_ERROR -1
64
62   inline int closesocket(SOCKET s) { return close(s); }
63   #endif
64  
# Line 77 | Line 74 | HttpHandler::HttpHandler()
74          }
75   #endif // _WIN32
76  
77 +        binary = false;
78          length = 0;
79          chunked = false;
80   #ifdef _OpenSSL_
# Line 124 | Line 122 | bool HttpHandler::handle(URL &url, const
122                  return answer;
123          }
124  
125 + #ifdef _OpenSSL_
126 +        if (url.getTls())
127 +        {
128 +                tls = true;
129 +
130 +                if (!starttls()) return answer;
131 +        }
132 + #endif
133 +
134          if (head)
135          {
136                  putline("HEAD " + url.getPath() + " HTTP/1.1");
# Line 136 | Line 143 | bool HttpHandler::handle(URL &url, const
143          putline("Accept: text/html; text/plain");
144   #ifndef _OpenSSL_
145          putline("User-Agent: " + agent(true) + ' ' + platform());
146 +
147 +        if (url.getPort() == 80)
148   #else
149          putline("User-Agent: " + agent(true) + ' ' + platform() + ' '
150                  + openssl(true));
142 #endif
151  
152 <        if (url.getPort() == 80)
152 >        if (url.getPort() == 80 && tls || url.getPort() == 443 && tls)
153 > #endif
154          {
155                  putline("Host: " + url.getAddress());
156          }
157          else
158          {
159 <                char* port = new char[1024];
151 <                sprintf(port, "%u", url.getPort());
159 >                ostringstream port;
160  
161 <                putline("Host: " + url.getAddress() + ':' + port);
161 >                port << url.getPort();
162  
163 <                delete [] port;
163 >                putline("Host: " + url.getAddress() + ':' + port.str());
164          }
165  
166          if (referer != "")
# Line 178 | Line 186 | bool HttpHandler::handle(URL &url, const
186                  unsigned dot = line.find('.');
187                  unsigned space = line.find(' ');
188  
189 <                unsigned major = strtoul(line.substr(5, dot - 5).c_str(), 0, 10);
190 <                unsigned minor = strtoul(line.substr(dot + 1, space - dot - 1).c_str(),
191 <                        0, 10);
189 >                unsigned major;
190 >                unsigned minor;
191 >
192 >                istringstream number(line.substr(5, dot - 5) + " " + line.substr(dot
193 >                        + 1, space - dot - 1));
194 >
195 >                number >> major;
196 >                number >> minor;
197  
198                  if (major > 1)
199                  {
# Line 190 | Line 203 | bool HttpHandler::handle(URL &url, const
203                          return answer;
204                  }
205  
206 <                response = code(strtoul(line.substr(space + 1).c_str(), 0, 10));
206 >                number.clear();
207 >                number.str(line.substr(space + 1, 3));
208 >                number >> response;
209  
210                  if (response < ok) do line = getline(); while (line != "");
211          }
# Line 215 | Line 230 | bool HttpHandler::handle(URL &url, const
230                          }
231                          else if (field == "Content-Length")
232                          {
233 <                                length = strtoul(value.c_str(), 0, 10);
233 >                                istringstream number(value);
234 >
235 >                                number >> length;
236                          }
237                          else if (field == "Location")
238                          {
# Line 264 | Line 281 | bool HttpHandler::handle(URL &url, const
281          return answer;
282   }
283  
284 < HttpHandler& HttpHandler::getline(string& line, char endline)
284 > void HttpHandler::clear()
285   {
286 <        unsigned end = page.find(endline);
287 <        unsigned newline = page.find('\n');
271 <
272 <        if (newline < end || end == string::npos)
286 > #ifdef _OpenSSL_
287 >        if (tls)
288          {
289 <                end = newline;
289 >                SSL_shutdown(ssl);
290 >                SSL_free(ssl);
291 >                SSL_CTX_free(ctx);
292          }
293 + #endif
294  
277        line = page.substr(0, end);
278        page.erase(0, (end == string::npos ? end : end + 1));
279
280        return *this;
281 }
282
283 void HttpHandler::clear()
284 {
295          closesocket(http);
296  
297          type = "";
298          length = 0;
299          location = "";
300 <        page = "";
300 >        page.clear();
301 >        page.str("");
302          chunked = false;
303   #ifdef _OpenSSL_
304          tls = false;
# Line 305 | Line 316 | void HttpHandler::populate()
316                          memset(buffer, 0, BUFSIZ + 1);
317  
318                          unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
319 <                        unsigned received;
319 >                        long received;
320  
321                          while (true)
322                          {
323 + #ifndef _OpenSSL_
324                                  if ((received = recv(http, buffer, bytes, 0)) == SOCKET_ERROR)
325                                  {
326                                          error(program + ": Recv");
327                                          exit(1);
328                                  }
329 + #else
330 +                                if ((received = !tls ? recv(http, buffer, bytes, 0) :
331 +                                        SSL_read(ssl, buffer, bytes)) <= 0)
332 +                                {
333 +                                        !tls ? error(program + ": Recv") : error(program +
334 +                                                ": SSL Read", int(received));
335 +                                }
336 + #endif
337                                  else if (received != bytes)
338                                  {
339                                          left -= received;
340 <                                        page += buffer;
340 >                                        page << buffer;
341  
342                                          memset(buffer, 0, BUFSIZ + 1);
343  
# Line 329 | Line 349 | void HttpHandler::populate()
349                                  }
350                          }
351  
352 <                        page += buffer;
352 >                        page << buffer;
353                          left -= bytes;
354                  }
355          }
# Line 339 | Line 359 | void HttpHandler::populate()
359  
360                  do
361                  {
362 <                        chunk = strtoul(getline().c_str(), 0, 16);
362 >                        istringstream number(getline());
363 >
364 >                        number.setf(ios_base::hex, ios_base::basefield);
365 >                        number >> chunk;
366  
367                          unsigned left = chunk;
368  
# Line 348 | Line 371 | void HttpHandler::populate()
371                                  memset(buffer, 0, BUFSIZ + 1);
372  
373                                  unsigned bytes = left > BUFSIZ ? BUFSIZ : left;
374 <                                unsigned received;
374 >                                long received;
375  
376                                  while (true)
377                                  {
378 + #ifndef _OpenSSL_
379                                          if ((received = recv(http, buffer, bytes, 0)) ==
380                                                  SOCKET_ERROR)
381                                          {
382                                                  error(program + ": Recv");
383                                                  exit(1);
384                                          }
385 + #else
386 +                                        if ((received = !tls ? recv(http, buffer, bytes, 0) :
387 +                                                SSL_read(ssl, buffer, bytes)) <= 0)
388 +                                        {
389 +                                                !tls ? error(program + ": Recv") : error(program +
390 +                                                        ": SSL Read", int(received));
391 +                                                exit(1);
392 +                                        }
393 + #endif
394                                          else if (received != bytes)
395                                          {
396                                                  left -= received;
397 <                                                page += buffer;
397 >                                                page << buffer;
398  
399                                                  memset(buffer, 0, BUFSIZ + 1);
400  
# Line 373 | Line 406 | void HttpHandler::populate()
406                                          }
407                                  }
408  
409 <                                page += buffer;
409 >                                page << buffer;
410                                  left -= bytes;
411                          }
412  
# Line 383 | Line 416 | void HttpHandler::populate()
416                  while (chunk > 0);
417          }
418  
419 <        for (unsigned index = 0; index < page.length(); index++)
419 >        if (!binary)
420          {
421 <                if (page[index] == '\r' && (index + 1 < page.length()) ? page[index +
422 <                        1] == '\n' : false)
423 <                {
391 <                        page.erase(index, 1);
392 <                }
393 <                else if (page[index] == '\r')
421 >                string page = this->page.str();
422 >
423 >                for (unsigned index = 0; index < page.length(); index++)
424                  {
425 <                        page[index] = '\n';
425 >                        if (page[index] == '\r' && (index + 1 < page.length()) ? page[index +
426 >                                1] == '\n' : false)
427 >                        {
428 >                                page.erase(index, 1);
429 >                        }
430 >                        else if (page[index] == '\r')
431 >                        {
432 >                                page[index] = '\n';
433 >                        }
434                  }
435 +
436 +                this->page.str(page);
437          }
438   }
439  
440   void HttpHandler::putline(const string line)
441   {
442          sprintf(buffer, "%s\r\n", line.c_str());
443 +
444 + #ifndef _OpenSSL_
445          if (send(http, buffer, strlen(buffer), 0) == SOCKET_ERROR)
446          {
447                  error(program + ": Send");
448                  exit(1);
449          }
450 + #else
451 +        if (!tls)
452 +        {
453 +                if (send(http, buffer, strlen(buffer), 0) == SOCKET_ERROR)
454 +                {
455 +                        error(program + ": Send");
456 +                        exit(1);
457 +                }
458 +        }
459 +        else
460 +        {
461 +                int number;
462 +
463 +                if ((number = SSL_write(ssl, buffer, strlen(buffer))) <= 0)
464 +                {
465 +                        error(program + ": SSL Write", number);
466 +                        exit(1);
467 +                }
468 +        }
469 + #endif
470   }
471  
472   string HttpHandler::getline()
# Line 414 | Line 476 | string HttpHandler::getline()
476  
477          do
478          {
479 + #ifndef _OpenSSL_
480                  if (recv(http, &byte, 1, 0) == SOCKET_ERROR)
481                  {
482                          error(program + ": Recv");
483                  }
484 + #else
485 +                if (!tls)
486 +                {
487 +                        if (recv(http, &byte, 1, 0) == SOCKET_ERROR)
488 +                        {
489 +                                error(program + ": Recv");
490 +                        }
491 +                }
492 +                else
493 +                {
494 +                        int number;
495 +
496 +                        if ((number = SSL_read(ssl, &byte, 1)) <= 0)
497 +                        {
498 +                                error(program + ": SSL Read", number);
499 +                        }
500 +                }
501 + #endif
502  
503                  if (byte != '\r' && byte != '\n')
504                  {
# Line 633 | Line 714 | void HttpHandler::error(const string& pr
714          }
715   #endif // _WIN32
716   }
717 +
718 + #ifdef _OpenSSL_
719 + void HttpHandler::error(const string& prefix, int number)
720 + {
721 +        string error;
722 +
723 +        switch (SSL_get_error(ssl, number))
724 +        {
725 +        case SSL_ERROR_NONE:
726 +                error = "The TLS/SSL I/O operation completed";
727 +                break;
728 +        case SSL_ERROR_ZERO_RETURN:
729 +                error = "The TLS/SSL connection has been closed";
730 +                break;
731 +        case SSL_ERROR_WANT_READ:
732 +        case SSL_ERROR_WANT_WRITE:
733 +        case SSL_ERROR_WANT_CONNECT:
734 + //      case SSL_ERROR_WANT_ACCEPT:
735 +        case SSL_ERROR_WANT_X509_LOOKUP:
736 +                error = "The operation did not complete";
737 +                break;
738 +        case SSL_ERROR_SYSCALL:
739 +                if (int err = ERR_get_error() != 0)
740 +                {
741 +                        error = ERR_reason_error_string(err);
742 +                }
743 +                else
744 +                {
745 +                        switch (number)
746 +                        {
747 +                        case 0:
748 +                                error = "An EOF was observed that violates the protocol";
749 +                                break;
750 +                        case -1:
751 +                                this->error(prefix);
752 +                                return;
753 +                        default:
754 +                                error = "Unknown error";
755 +                                break;
756 +                        }
757 +                }
758 +                break;
759 +        case SSL_ERROR_SSL:
760 +                error = ERR_reason_error_string(ERR_get_error());
761 +                break;
762 +        default:
763 +                error = "Unknown error";
764 +                break;
765 +        }
766 +
767 +        cerr << prefix << ": " << error << "\n";
768 + }
769 +
770 + bool HttpHandler::starttls()
771 + {
772 +        SSL_load_error_strings();
773 +        SSL_library_init();
774 +
775 + #ifndef _urandomdev_
776 +        int pid = getpid();
777 +        int now = time(NULL);
778 +
779 +        unsigned seed = now > pid ? now - pid : pid - now;
780 +
781 +        char* junk = new char[seed % 30 + 2];
782 +        junk[0] = pid;
783 +        junk[seed % 30 + 1] = now;
784 +
785 +        srand(seed);
786 +
787 +        for (int index = 1; index < seed % 30 + 1; index++)
788 +        {
789 +                junk[index] = rand();
790 +        }
791 +
792 +        if (debug)
793 +        {
794 +                cerr << "junk = {\n";
795 +
796 +                for (int index = 1; index < seed % 30 + 2; index++)
797 +                {
798 +                        cerr << "   [" << index << "] = " << int(junk[index]) << "\n";
799 +                }
800 +
801 +                cerr << "}\n";
802 +        }
803 +
804 +        RAND_seed(junk, seed % 30 + 2);
805 +
806 +        delete junk;
807 + #else
808 +        if (debug) cerr << "junk = /dev/urandom\n";
809 + #endif
810 +
811 +        ctx = SSL_CTX_new(TLSv1_client_method());
812 +
813 +        if (ctx == NULL)
814 +        {
815 +                cerr << program << ": SSL CTX New: "
816 +                        << ERR_reason_error_string(ERR_get_error()) << "\n";
817 +                return false;
818 +        }
819 +
820 +        ssl = SSL_new(ctx);
821 +
822 +        if (SSL_set_fd(ssl, http) == 0)
823 +        {
824 +                cerr << program << ": SSL Set FD: "
825 +                        << ERR_reason_error_string(ERR_get_error()) << "\n";
826 +                return false;
827 +        }
828 +
829 +        int number;
830 +
831 +        if ((number = SSL_connect(ssl)) <= 0)
832 +        {
833 +                error(program + ": SSL Connect", number);
834 +                return false;
835 +        }
836 +
837 +        return true;
838 + }
839 + #endif

Comparing trunk/Search/HttpHandler.cpp (property svn:eol-style):
Revision 201 by douglas, 2003-07-15T01:01:00-07:00 vs.
Revision 334 by Douglas Thrift, 2004-04-05T16:37:41-07:00

# Line 0 | Line 1
1 + native

Comparing trunk/Search/HttpHandler.cpp (property svn:keywords):
Revision 201 by douglas, 2003-07-15T01:01:00-07:00 vs.
Revision 334 by Douglas Thrift, 2004-04-05T16:37:41-07:00

# Line 0 | Line 1
1 + Id

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines