/[winpt]/trunk/Src/wptHTTP.cpp
ViewVC logotype

Diff of /trunk/Src/wptHTTP.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 310 by twoaday, Sat Apr 7 11:07:20 2007 UTC revision 351 by twoaday, Thu Dec 1 20:10:25 2011 UTC
# Line 1  Line 1 
1  /* wptHTTP.cpp - Generic HTTP support  /* wptHTTP.cpp - Generic HTTP support
2   *      Copyright (C) 2004, 2005, 2006, 2007 Timo Schulz   *      Copyright (C) 2004-2007, 2009 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 28  Line 28 
28  #include "wptHTTP.h"  #include "wptHTTP.h"
29  #include "wptTypes.h"  #include "wptTypes.h"
30  #include "wptErrors.h"  #include "wptErrors.h"
31    #include "StringBuffer.h"
32    
33    
34  /* Empty constructur to allow advanced requests. */  /* Empty constructur to allow advanced requests. */
35  wHTTP::wHTTP (void)  NetHTTP::NetHTTP (void)
36  {  {
37      reset ();      reset ();
38  }  }
39    
40    
41  /* Constructur to allow alternative syntax. */  /* Constructur to allow alternative syntax. */
42  wHTTP::wHTTP (const char *_host, int _port, const char *_url)  NetHTTP::NetHTTP (const char *_host, int _port, const char *_url)
43  {  {
44      reset ();      reset ();
45      this->host = strdup (_host);      this->host = strdup (_host);
# Line 51  wHTTP::wHTTP (const char *_host, int _po Line 52  wHTTP::wHTTP (const char *_host, int _po
52    
53    
54  /* Standard constructur. */  /* Standard constructur. */
55  wHTTP::wHTTP (const char *_url)  NetHTTP::NetHTTP (const char *_url)
56  {  {
57      reset ();      reset ();
58      open (_url);      open (_url);
59  }  }
60    
61    /* Open a connection to the given URL @_url. */
 /* Open a connection to the given URL. */  
62  int  int
63  wHTTP::open (const char *_url)  NetHTTP::open (const char *_url)
64  {  {
65      /* In case the function is used more than once, we      int err;
66         need to release the old structures first. */  
67      releaseHeaders ();      /* A connection were privously established. */
68            if (this->fd != 0)
69            return 0;
70    
71      safe_free (this->host);      safe_free (this->host);
72      safe_free (this->url);      safe_free (this->url);
73        
74      if (extractHostInfo (_url, &this->host, &this->url))      err = extractHostInfo (_url, &this->host, &this->url);
75          return -1;      if (err)
76                return err;
77      if (!sendRequest (this->host, this->port, this->url))      err = sendRequest (this->host, this->port, this->url);
78          return parseResponse (&statcode);      if (err)
79                return err;
80      return 0;      return parseResponse (&statcode);
81  }  }
82    
83    
84  /* Reset object contents for first use. */  /* Reset object contents for first use. */
85  void  void
86  wHTTP::reset (void)  NetHTTP::reset (void)
87  {  {
88      ver = 1;      ver = 1;
89      port = 80;      port = 80;
# Line 96  wHTTP::reset (void) Line 98  wHTTP::reset (void)
98    
99  /* Perform a HTTP 'HEAD' request. */  /* Perform a HTTP 'HEAD' request. */
100  int  int
101  wHTTP::head (const char *_url)  NetHTTP::head (const char *_url)
102  {  {
103      int err;      int err;
104    
# Line 106  wHTTP::head (const char *_url) Line 108  wHTTP::head (const char *_url)
108      err = extractHostInfo (_url, &this->host, &this->url);      err = extractHostInfo (_url, &this->host, &this->url);
109      if (err)      if (err)
110          return err;          return err;
111        
112      method = HTTP_HEAD;      method = HTTP_HEAD;
113      if (!sendRequest (this->host, this->port, this->url))      if (!sendRequest (host, port, url))
114          parseResponse (&statcode);          err = parseResponse (&statcode);
115    
116      return 0;      return err;
117  }  }
118    
119    
120  /* Perform a HTTP 'GET' request. */  /* Perform a HTTP 'GET' request. */
121  int  int
122  wHTTP::get (const char *_url)  NetHTTP::get (const char *_url)
123  {  {
124      int err;      int err;
125    
126      safe_free (this->host);      safe_free (host);
127      safe_free (this->url);      safe_free (url);
128    
129      err = extractHostInfo (_url, &this->host, &this->url);      err = extractHostInfo (_url, &this->host, &this->url);
130      if (err)      if (err)
# Line 130  wHTTP::get (const char *_url) Line 132  wHTTP::get (const char *_url)
132    
133      method = HTTP_GET;      method = HTTP_GET;
134      if (!sendRequest (this->host, this->port, this->url))      if (!sendRequest (this->host, this->port, this->url))
135          parseResponse (&statcode);          err = parseResponse (&statcode);
136    
137      return 0;      return err;
138  }  }
139    
140    
141  /* Return HTTP status code. */  /* Return HTTP status code. */
142  int  int
143  wHTTP::getStatusCode (void)  NetHTTP::getStatusCode (void)
144  {  {
145      return statcode;      return statcode;
146  }  }
# Line 146  wHTTP::getStatusCode (void) Line 148  wHTTP::getStatusCode (void)
148    
149  /* Return MIME content type. */  /* Return MIME content type. */
150  const char*  const char*
151  wHTTP::getContentType (void)  NetHTTP::getContentType (void)
152  {  {
153      const char *type = NULL;      const char *type = NULL;
154    
# Line 157  wHTTP::getContentType (void) Line 159  wHTTP::getContentType (void)
159    
160  /* Return content length. */  /* Return content length. */
161  unsigned int  unsigned int
162  wHTTP::getContentLength (void)  NetHTTP::getContentLength (void)
163  {  {
164      const char *len = NULL;      const char *len = NULL;
165    
# Line 168  wHTTP::getContentLength (void) Line 170  wHTTP::getContentLength (void)
170    
171    
172  void  void
173  wHTTP::addHeader (http_head_t *root, const char *val)  NetHTTP::addHeader (http_head_t *root, const char *val)
174  {  {
175      http_head_t n, t;      http_head_t n, t;
176            
# Line 188  wHTTP::addHeader (http_head_t *root, con Line 190  wHTTP::addHeader (http_head_t *root, con
190    
191    
192  bool  bool
193  wHTTP::findHeader (http_head_t root,  NetHTTP::findHeader (http_head_t root,
194                     const char *name, const char **val)                       const char *name, const char **val)
195  {  {
196      http_head_t n;      http_head_t n;
197      char *p;      char *p;
198            
199      *val = NULL;      *val = NULL;
200      for (n = root; n; n = n->next) {      for (n = root; n; n = n->next) {
201          if (strlen (n->d) >= strlen (name) &&          if (strlen (n->d) >= strlen (name) && strstr (n->d, name)) {
             strstr (n->d, name)) {  
202              p = strchr (n->d, ':');              p = strchr (n->d, ':');
203              *val = p? n->d + (p - n->d + 1 + 1) : NULL;              *val = p? n->d + (p - n->d + 1 + 1) : NULL;
204              return true;              return true;
# Line 208  wHTTP::findHeader (http_head_t root, Line 209  wHTTP::findHeader (http_head_t root,
209    
210    
211  int  int
212  wHTTP::connect (const char *_host, int _port)  NetHTTP::connect (const char *_host, int _port)
213  {  {
214      struct hostent *hp;      struct hostent *hp;
215      struct sockaddr_in srv;      struct sockaddr_in srv;
# Line 250  wHTTP::connect (const char *_host, int _ Line 251  wHTTP::connect (const char *_host, int _
251          return WPTERR_WINSOCK_SOCKET;          return WPTERR_WINSOCK_SOCKET;
252      }      }
253            
254      if (::connect (fd, (struct sockaddr *)&srv, sizeof srv)) {      if (::connect (fd, (struct sockaddr *)&srv, sizeof (srv))) {
255          closesocket (fd);          closesocket (fd);
256          fd = 0;          fd = 0;
257          this->error = (int)WSAGetLastError ();          this->error = (int)WSAGetLastError ();
# Line 261  wHTTP::connect (const char *_host, int _ Line 262  wHTTP::connect (const char *_host, int _
262  }  }
263    
264    
265    /* Return 0 if the next recv() call would be block. */
266  int  int
267  wHTTP::isDataAvailable (int _fd)  NetHTTP::isDataAvailable (int _fd)
268  {  {
269      struct timeval tv;      struct timeval tv;    
270      fd_set inp;      fd_set inp;
271      int n;      
   
272      FD_ZERO (&inp);      FD_ZERO (&inp);
273      FD_SET (_fd, &inp);      FD_SET (_fd, &inp);
274      tv.tv_sec = 1;      tv.tv_sec = 1;
275      tv.tv_usec = 0;      tv.tv_usec = 0;
276    
277      n = select (_fd+1, &inp, NULL, NULL, &tv);      int n = select (_fd+1, &inp, NULL, NULL, &tv);
278      if (n && FD_ISSET (_fd, &inp))      if (n && FD_ISSET (_fd, &inp))
279          return n;          return n;
280      return 0;      return 0;
281  }  }
282    
283    
284    /* Read a line from the open socket. A line means
285       a sequence of octets terminated with a \r\n.
286       Return value: 0 on success. */
287  int  int
288  wHTTP::readLine (char *buf, unsigned int nbuf,  NetHTTP::readLine (char *buf, unsigned int nbuf,
289                   int nonblock, int *nn, int *eof)                     int nonblock, int *nn, int *eof)
290  {  {
291      char c;      char c;
292      int n, i;      int n, i;
# Line 331  wHTTP::readLine (char *buf, unsigned int Line 335  wHTTP::readLine (char *buf, unsigned int
335  /* Extract the host from the given url @url. Return the host in  /* Extract the host from the given url @url. Return the host in
336     @host and also return the resource part of the url in @new_url. */     @host and also return the resource part of the url in @new_url. */
337  int  int
338  wHTTP::extractHostInfo (const char *_url, char **_host, char **new_url)  NetHTTP::extractHostInfo (const char *_url, char **_host, char **new_url)
339  {    {  
340      char tmpbuf[2*MAX_PATH+1];      char tmpbuf[2*MAX_PATH+1];
341      char *p;      char *p;
# Line 343  wHTTP::extractHostInfo (const char *_url Line 347  wHTTP::extractHostInfo (const char *_url
347      memset (tmpbuf, 0, sizeof (tmpbuf));      memset (tmpbuf, 0, sizeof (tmpbuf));
348      strncpy (tmpbuf, _url, DIM (tmpbuf)-1);      strncpy (tmpbuf, _url, DIM (tmpbuf)-1);
349            
350      p = "http://";      p = (char*)"http://";
351      if (strlen (_url) < 10 || strncmp (_url, p, 7))      if (strlen (_url) < 10 || strncmp (_url, p, strlen (p)))
352          return WPTERR_GENERAL;          return WPTERR_GENERAL;
353      _url += strlen (p);      _url += strlen (p);
354      p = strtok (tmpbuf+7, "/");      p = strtok (tmpbuf+7, "/");
# Line 352  wHTTP::extractHostInfo (const char *_url Line 356  wHTTP::extractHostInfo (const char *_url
356          return WPTERR_GENERAL;          return WPTERR_GENERAL;
357      *_host = strdup (p);        *_host = strdup (p);  
358      p = strchr (_url, '/');      p = strchr (_url, '/');
359      if (!p) /* document were given so we assume the root '/'. */      /* if no document were given so we assume the root '/'. */
360          *new_url = strdup ("/");      *new_url = !p? strdup ("/") : strdup (p);  
361      else  
         *new_url = strdup (p);  
362      return 0;      return 0;
363  }  }
364    
365    
366  /* Add a request header. */  /* Add a request header. */
367  int  int
368  wHTTP::addRequestHeader (const char *name, const char *val)  NetHTTP::addRequestHeader (const char *name, const char *val)
369  {  {
370      char *p;      StringBuffer p;
     char *fmt = "%s: %s";  
   
     p = (char*) malloc (strlen (name)+strlen (val)+strlen (fmt)+4);  
     sprintf (p, fmt, name, val);  
     addHeader (&req_headers, p);  
     safe_free (p);  
371    
372        p = p + name + ": " + val;
373        addHeader (&req_headers, p.getBuffer ());
374      return 0;      return 0;
375  }  }
376    
377    
378  void  void
379  wHTTP::setVersion (int _ver)  NetHTTP::setVersion (int _ver)
380  {  {
381      if (_ver > 9)      if (_ver > 9)
382          _ver = 0;          _ver = 0;
# Line 386  wHTTP::setVersion (int _ver) Line 385  wHTTP::setVersion (int _ver)
385    
386    
387  int  int
388  wHTTP::addRequestHeader (const char *name, unsigned int val)  NetHTTP::addRequestHeader (const char *name, unsigned int val)
389  {  {
390      char buf[32];      char buf[32];
391    
# Line 398  wHTTP::addRequestHeader (const char *nam Line 397  wHTTP::addRequestHeader (const char *nam
397  /* Prepare the request resource @url and send  /* Prepare the request resource @url and send
398     it to host @host (port @port). */     it to host @host (port @port). */
399  int  int
400  wHTTP::sendRequest (const char *_host, int _port, const char *_url)  NetHTTP::sendRequest (const char *_host, int _port, const char *_url)
401  {  {
402      const char *id[] = {"GET", "HEAD", "PUT", "POST"};      const char *id[] = {"GET", "HEAD", "PUT", "POST"};
403      http_head_t h;      http_head_t h;
404      const char *h_head;      StringBuffer out;
     char *p;  
405      int n;      int n;
     int rc;  
406    
407      if (!this->fd) {      if (this->fd == 0) {
408          rc = connect (_host, _port);          int rc = connect (_host, _port);
409          if (rc)          if (rc)
410              return rc;              return rc;
411      }      }
# Line 422  wHTTP::sendRequest (const char *_host, i Line 419  wHTTP::sendRequest (const char *_host, i
419      if (ver < 1)      if (ver < 1)
420          addRequestHeader ("Connection", "close");          addRequestHeader ("Connection", "close");
421    
422      n = 0;      out = out + id[method] + " " + "/" + _url + " " + "HTTP/1." + (int)ver + "\r\n";
423      for (h = req_headers; h; h = h->next)      for (h = req_headers; h; h = h->next)
424          n += strlen (h->d) + 2 + 1;          out = out + h->d + "\r\n";
425      h_head = "%s /%s HTTP/1.%d\r\n";      out = out + "\r\n";
426      n += strlen (id[method]) + strlen (h_head)  
427           + strlen (_url) + n + 2 + 1 + 4;      n = write (out.getBuffer (), strlen (out.getBuffer ()));
428      p = (char*)calloc (1, n+1);      //log_box ("debug", 0, "%d", n);
     if (!p)  
         BUG (0);  
     sprintf (p, h_head, id[method], _url, ver);  
     for (h = req_headers; h; h = h->next) {  
         strcat (p, h->d);  
         strcat (p, "\r\n");  
     }  
     strcat (p, "\r\n");  
     n = send (fd, p, strlen (p), 0);  
     safe_free (p);  
429      return n > 0? 0 : WPTERR_GENERAL;      return n > 0? 0 : WPTERR_GENERAL;
430  }  }
431    
432    
433  /* Parse all response resp_headers. */  /* Parse all response resp_headers. */
434  int  int
435  wHTTP::parseHeaders (http_head_t *r_head)  NetHTTP::parseHeaders (http_head_t *r_head)
436  {  {
437      char buf[300];      char buf[300];
438      int nn;      int nn;
# Line 466  wHTTP::parseHeaders (http_head_t *r_head Line 453  wHTTP::parseHeaders (http_head_t *r_head
453  }  }
454    
455    
456    /* Default buffer size */
457    #define BUFSIZE 1024
458    
459    
460  /* Read data from the response and write it to @out. */  /* Read data from the response and write it to @out. */
461  int  int
462  wHTTP::readData (FILE *out)  NetHTTP::readData (FILE *out)
463  {  {
464      const char *val;      const char *val;
465      char buf[1024+1];      char buf[BUFSIZE+1];
466      int nlen = 0, nn = 0, n, eof=0;      int nlen, nn = 0, n, eof=0;
467      int rc = 0;      int rc = 0;
468            
469      if (this->fd == 0 || this->resp_headers == NULL)      if (this->fd == 0 || this->resp_headers == NULL)
# Line 490  wHTTP::readData (FILE *out) Line 481  wHTTP::readData (FILE *out)
481          return WPTERR_GENERAL;          return WPTERR_GENERAL;
482      if (strnicmp (val, "text", 4)) { /* binary */      if (strnicmp (val, "text", 4)) { /* binary */
483          do {          do {
484              n = recv (fd, buf, nlen > 1024? 1024 : nlen, 0);              n = recv (fd, buf, nlen > BUFSIZE? BUFSIZE : nlen, 0);
485              if (n == -1) {              if (n == -1) {
486                  this->error = (int)WSAGetLastError ();                  this->error = (int)WSAGetLastError ();
487                  return SOCKET_ERROR;                  return SOCKET_ERROR;
# Line 522  wHTTP::readData (FILE *out) Line 513  wHTTP::readData (FILE *out)
513    
514  /* Parse the HTTP response line. */  /* Parse the HTTP response line. */
515  int  int
516  wHTTP::parseResponse (int *_statcode)  NetHTTP::parseResponse (int *_statcode)
517  {  {
518      http_head_t n;      http_head_t n;
519      const char *tmp, *p;      const char *tmp, *p;
# Line 531  wHTTP::parseResponse (int *_statcode) Line 522  wHTTP::parseResponse (int *_statcode)
522      int rc;      int rc;
523    
524      *_statcode = 0;      *_statcode = 0;
525      rc = readLine (buf, 299, 1, &nn, NULL);      rc = readLine (buf, DIM (buf)-1, 1, &nn, NULL);
526      if (rc)      if (rc)
527          return rc;          return rc;
528    
# Line 557  wHTTP::parseResponse (int *_statcode) Line 548  wHTTP::parseResponse (int *_statcode)
548          resp_headers = n;          resp_headers = n;
549      }      }
550      resp_headers = NULL;      resp_headers = NULL;
551      return parseHeaders (&resp_headers);      rc = parseHeaders (&resp_headers);
552        if (rc)
553            return rc;
554        return 0;
555  }  }
556    
557    
558  /* Release all used structures. */  /* Destroy HTTP object. */
559  void  NetHTTP::~NetHTTP (void)
 wHTTP::releaseHeaders (void)  
560  {  {
561      http_head_t h;      http_head_t h;
562            
563      while (resp_headers != NULL) {      while (resp_headers) {
564          h = resp_headers->next;          h = resp_headers->next;
565          free (resp_headers);          free (resp_headers);
566          resp_headers = h;          resp_headers = h;
567      }      }
568      resp_headers = NULL;      while (req_headers) {
     while (req_headers != NULL) {  
569          h = req_headers->next;          h = req_headers->next;
570          free (req_headers);          free (req_headers);
571          req_headers = h;          req_headers = h;
572      }      }
     req_headers = NULL;  
 }  
   
   
 /* Destroy HTTP object. */  
 wHTTP::~wHTTP (void)  
 {  
     releaseHeaders();  
     safe_free (host);  
573      safe_free (url);      safe_free (url);
574        safe_free (host);
575      if (fd != 0) {      if (fd != 0) {
576          closesocket (fd);          closesocket (fd);
577          fd = 0;          fd = 0;
# Line 597  wHTTP::~wHTTP (void) Line 581  wHTTP::~wHTTP (void)
581    
582  /* Read @buflen bytes from the http stream into the buffer @buf. */  /* Read @buflen bytes from the http stream into the buffer @buf. */
583  int  int
584  wHTTP::read (void *buf, unsigned int buflen)  NetHTTP::read (void *buf, unsigned int buflen)
585  {  {
586      int n;      int n;
587    
# Line 616  wHTTP::read (void *buf, unsigned int buf Line 600  wHTTP::read (void *buf, unsigned int buf
600      n = recv (fd, (char*)buf, (int)buflen, 0);      n = recv (fd, (char*)buf, (int)buflen, 0);
601      if (n > 0) {      if (n > 0) {
602          nleft -= n;          nleft -= n;
603          if (nleft < 0) nleft = 0;          if (nleft < 0)
604                nleft = 0;
605      }      }
606      return n;      return n;
607  }  }
608    
609    
610  /* Write the buffer @buf to the http stream. */  /* Write the buffer @buf to the http stream.
611  int     The function should be considered general as a replacement
612  wHTTP::write (const void *buf, unsigned buflen)     for send() to make sure the entire buffer is written. */
613  {  int
614    NetHTTP::write (const void *buf, unsigned int buflen)
615    {
616        const char *buffer = (const char*)buf;
617        unsigned int bytesleft = buflen;
618        int nwritten;
619    
620      if (this->fd == 0)      if (this->fd == 0)
621          return -1;          return -1;
622      if (method == HTTP_GET || method == HTTP_HEAD)  
623          return -1;      while (bytesleft > 0) {
624      return send (fd, (const char*)buf, (int)buflen, 0);          nwritten = send (this->fd, buffer, bytesleft, 0);
625            if (nwritten == -1)
626                return -1;
627            bytesleft -= nwritten;
628            buffer += nwritten;
629        }
630        return buflen;
631  }  }
632    
633    
634  /* Return the Winsock specific error code. */  /* Return the Winsock specific error code. */
635  int wHTTP::getErrorCode (void)  int NetHTTP::getErrorCode (void)
636  {  {
637      return error;      return error;
638  }  }

Legend:
Removed from v.310  
changed lines
  Added in v.351

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26