/[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 313 by twoaday, Sat Apr 7 11:07:20 2007 UTC revision 314 by twoaday, Sun May 13 09:44:03 2007 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 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;
# Line 208  wHTTP::findHeader (http_head_t root, Line 210  wHTTP::findHeader (http_head_t root,
210    
211    
212  int  int
213  wHTTP::connect (const char *_host, int _port)  NetHTTP::connect (const char *_host, int _port)
214  {  {
215      struct hostent *hp;      struct hostent *hp;
216      struct sockaddr_in srv;      struct sockaddr_in srv;
# Line 250  wHTTP::connect (const char *_host, int _ Line 252  wHTTP::connect (const char *_host, int _
252          return WPTERR_WINSOCK_SOCKET;          return WPTERR_WINSOCK_SOCKET;
253      }      }
254            
255      if (::connect (fd, (struct sockaddr *)&srv, sizeof srv)) {      if (::connect (fd, (struct sockaddr *)&srv, sizeof (srv))) {
256          closesocket (fd);          closesocket (fd);
257          fd = 0;          fd = 0;
258          this->error = (int)WSAGetLastError ();          this->error = (int)WSAGetLastError ();
# Line 261  wHTTP::connect (const char *_host, int _ Line 263  wHTTP::connect (const char *_host, int _
263  }  }
264    
265    
266    /* Return 0 if the next recv() call would be block. */
267  int  int
268  wHTTP::isDataAvailable (int _fd)  NetHTTP::isDataAvailable (int _fd)
269  {  {
270      struct timeval tv;      struct timeval tv;
271      fd_set inp;      fd_set inp;
# Line 280  wHTTP::isDataAvailable (int _fd) Line 283  wHTTP::isDataAvailable (int _fd)
283  }  }
284    
285    
286    /* Read a line from the open socket. A line means
287       a sequence of octets terminated with a \r\n.
288       Return value: 0 on success. */
289  int  int
290  wHTTP::readLine (char *buf, unsigned int nbuf,  NetHTTP::readLine (char *buf, unsigned int nbuf,
291                   int nonblock, int *nn, int *eof)                   int nonblock, int *nn, int *eof)
292  {  {
293      char c;      char c;
# Line 331  wHTTP::readLine (char *buf, unsigned int Line 337  wHTTP::readLine (char *buf, unsigned int
337  /* Extract the host from the given url @url. Return the host in  /* Extract the host from the given url @url. Return the host in
338     @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. */
339  int  int
340  wHTTP::extractHostInfo (const char *_url, char **_host, char **new_url)  NetHTTP::extractHostInfo (const char *_url, char **_host, char **new_url)
341  {    {  
342      char tmpbuf[2*MAX_PATH+1];      char tmpbuf[2*MAX_PATH+1];
343      char *p;      char *p;
# Line 344  wHTTP::extractHostInfo (const char *_url Line 350  wHTTP::extractHostInfo (const char *_url
350      strncpy (tmpbuf, _url, DIM (tmpbuf)-1);      strncpy (tmpbuf, _url, DIM (tmpbuf)-1);
351            
352      p = "http://";      p = "http://";
353      if (strlen (_url) < 10 || strncmp (_url, p, 7))      if (strlen (_url) < 10 || strncmp (_url, p, strlen (p)))
354          return WPTERR_GENERAL;          return WPTERR_GENERAL;
355      _url += strlen (p);      _url += strlen (p);
356      p = strtok (tmpbuf+7, "/");      p = strtok (tmpbuf+7, "/");
# Line 352  wHTTP::extractHostInfo (const char *_url Line 358  wHTTP::extractHostInfo (const char *_url
358          return WPTERR_GENERAL;          return WPTERR_GENERAL;
359      *_host = strdup (p);        *_host = strdup (p);  
360      p = strchr (_url, '/');      p = strchr (_url, '/');
361      if (!p) /* document were given so we assume the root '/'. */      /* if no document were given so we assume the root '/'. */
362          *new_url = strdup ("/");      *new_url = !p? strdup ("/") : strdup (p);  
363      else  
         *new_url = strdup (p);  
364      return 0;      return 0;
365  }  }
366    
367    
368  /* Add a request header. */  /* Add a request header. */
369  int  int
370  wHTTP::addRequestHeader (const char *name, const char *val)  NetHTTP::addRequestHeader (const char *name, const char *val)
371  {  {
372      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);  
373    
374        p = p + name + ": " + val;
375        addHeader (&req_headers, p.getBuffer ());
376      return 0;      return 0;
377  }  }
378    
379    
380  void  void
381  wHTTP::setVersion (int _ver)  NetHTTP::setVersion (int _ver)
382  {  {
383      if (_ver > 9)      if (_ver > 9)
384          _ver = 0;          _ver = 0;
# Line 386  wHTTP::setVersion (int _ver) Line 387  wHTTP::setVersion (int _ver)
387    
388    
389  int  int
390  wHTTP::addRequestHeader (const char *name, unsigned int val)  NetHTTP::addRequestHeader (const char *name, unsigned int val)
391  {  {
392      char buf[32];      char buf[32];
393    
# Line 398  wHTTP::addRequestHeader (const char *nam Line 399  wHTTP::addRequestHeader (const char *nam
399  /* Prepare the request resource @url and send  /* Prepare the request resource @url and send
400     it to host @host (port @port). */     it to host @host (port @port). */
401  int  int
402  wHTTP::sendRequest (const char *_host, int _port, const char *_url)  NetHTTP::sendRequest (const char *_host, int _port, const char *_url)
403  {  {
404      const char *id[] = {"GET", "HEAD", "PUT", "POST"};      const char *id[] = {"GET", "HEAD", "PUT", "POST"};
405      http_head_t h;      http_head_t h;
406      const char *h_head;      StringBuffer out;
     char *p;  
407      int n;      int n;
     int rc;  
408    
409      if (!this->fd) {      if (this->fd == 0) {
410          rc = connect (_host, _port);          int rc = connect (_host, _port);
411          if (rc)          if (rc)
412              return rc;              return rc;
413      }      }
# Line 422  wHTTP::sendRequest (const char *_host, i Line 421  wHTTP::sendRequest (const char *_host, i
421      if (ver < 1)      if (ver < 1)
422          addRequestHeader ("Connection", "close");          addRequestHeader ("Connection", "close");
423    
424      n = 0;      out = out + id[method] + " " + "/" + _url + " " + "HTTP/1." + (int)ver + "\r\n";
425      for (h = req_headers; h; h = h->next)      for (h = req_headers; h; h = h->next)
426          n += strlen (h->d) + 2 + 1;          out = out + h->d + "\r\n";
427      h_head = "%s /%s HTTP/1.%d\r\n";      out = out + "\r\n";
428      n += strlen (id[method]) + strlen (h_head)  
429           + strlen (_url) + n + 2 + 1 + 4;      n = write (out.getBuffer (), strlen (out.getBuffer ()));
430      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);  
431      return n > 0? 0 : WPTERR_GENERAL;      return n > 0? 0 : WPTERR_GENERAL;
432  }  }
433    
434    
435  /* Parse all response resp_headers. */  /* Parse all response resp_headers. */
436  int  int
437  wHTTP::parseHeaders (http_head_t *r_head)  NetHTTP::parseHeaders (http_head_t *r_head)
438  {  {
439      char buf[300];      char buf[300];
440      int nn;      int nn;
# Line 466  wHTTP::parseHeaders (http_head_t *r_head Line 455  wHTTP::parseHeaders (http_head_t *r_head
455  }  }
456    
457    
458    /* Default buffer size */
459    #define BUFSIZE 1024
460    
461    
462  /* Read data from the response and write it to @out. */  /* Read data from the response and write it to @out. */
463  int  int
464  wHTTP::readData (FILE *out)  NetHTTP::readData (FILE *out)
465  {  {
466      const char *val;      const char *val;
467      char buf[1024+1];      char buf[BUFSIZE+1];
468      int nlen = 0, nn = 0, n, eof=0;      int nlen, nn = 0, n, eof=0;
469      int rc = 0;      int rc = 0;
470            
471      if (this->fd == 0 || this->resp_headers == NULL)      if (this->fd == 0 || this->resp_headers == NULL)
# Line 490  wHTTP::readData (FILE *out) Line 483  wHTTP::readData (FILE *out)
483          return WPTERR_GENERAL;          return WPTERR_GENERAL;
484      if (strnicmp (val, "text", 4)) { /* binary */      if (strnicmp (val, "text", 4)) { /* binary */
485          do {          do {
486              n = recv (fd, buf, nlen > 1024? 1024 : nlen, 0);              n = recv (fd, buf, nlen > BUFSIZE? BUFSIZE : nlen, 0);
487              if (n == -1) {              if (n == -1) {
488                  this->error = (int)WSAGetLastError ();                  this->error = (int)WSAGetLastError ();
489                  return SOCKET_ERROR;                  return SOCKET_ERROR;
# Line 522  wHTTP::readData (FILE *out) Line 515  wHTTP::readData (FILE *out)
515    
516  /* Parse the HTTP response line. */  /* Parse the HTTP response line. */
517  int  int
518  wHTTP::parseResponse (int *_statcode)  NetHTTP::parseResponse (int *_statcode)
519  {  {
520      http_head_t n;      http_head_t n;
521      const char *tmp, *p;      const char *tmp, *p;
# Line 531  wHTTP::parseResponse (int *_statcode) Line 524  wHTTP::parseResponse (int *_statcode)
524      int rc;      int rc;
525    
526      *_statcode = 0;      *_statcode = 0;
527      rc = readLine (buf, 299, 1, &nn, NULL);      rc = readLine (buf, DIM (buf)-1, 1, &nn, NULL);
528      if (rc)      if (rc)
529          return rc;          return rc;
530    
# Line 557  wHTTP::parseResponse (int *_statcode) Line 550  wHTTP::parseResponse (int *_statcode)
550          resp_headers = n;          resp_headers = n;
551      }      }
552      resp_headers = NULL;      resp_headers = NULL;
553      return parseHeaders (&resp_headers);      rc = parseHeaders (&resp_headers);
554        if (rc)
555            return rc;
556        return 0;
557  }  }
558    
559    
560  /* Release all used structures. */  /* Destroy HTTP object. */
561  void  NetHTTP::~NetHTTP (void)
 wHTTP::releaseHeaders (void)  
562  {  {
563      http_head_t h;      http_head_t h;
564            
565      while (resp_headers != NULL) {      while (resp_headers) {
566          h = resp_headers->next;          h = resp_headers->next;
567          free (resp_headers);          free (resp_headers);
568          resp_headers = h;          resp_headers = h;
569      }      }
570      resp_headers = NULL;      while (req_headers) {
     while (req_headers != NULL) {  
571          h = req_headers->next;          h = req_headers->next;
572          free (req_headers);          free (req_headers);
573          req_headers = h;          req_headers = h;
574      }      }
     req_headers = NULL;  
 }  
   
   
 /* Destroy HTTP object. */  
 wHTTP::~wHTTP (void)  
 {  
     releaseHeaders();  
     safe_free (host);  
575      safe_free (url);      safe_free (url);
576        safe_free (host);
577      if (fd != 0) {      if (fd != 0) {
578          closesocket (fd);          closesocket (fd);
579          fd = 0;          fd = 0;
# Line 597  wHTTP::~wHTTP (void) Line 583  wHTTP::~wHTTP (void)
583    
584  /* Read @buflen bytes from the http stream into the buffer @buf. */  /* Read @buflen bytes from the http stream into the buffer @buf. */
585  int  int
586  wHTTP::read (void *buf, unsigned int buflen)  NetHTTP::read (void *buf, unsigned int buflen)
587  {  {
588      int n;      int n;
589    
# Line 616  wHTTP::read (void *buf, unsigned int buf Line 602  wHTTP::read (void *buf, unsigned int buf
602      n = recv (fd, (char*)buf, (int)buflen, 0);      n = recv (fd, (char*)buf, (int)buflen, 0);
603      if (n > 0) {      if (n > 0) {
604          nleft -= n;          nleft -= n;
605          if (nleft < 0) nleft = 0;          if (nleft < 0)
606                nleft = 0;
607      }      }
608      return n;      return n;
609  }  }
610    
611    
612  /* Write the buffer @buf to the http stream. */  /* Write the buffer @buf to the http stream.
613  int     The function should be considered general as a replacement
614  wHTTP::write (const void *buf, unsigned buflen)     for send() to make sure the entire buffer is written. */
615  {  int
616    NetHTTP::write (const void *buf, unsigned int buflen)
617    {
618        const char *buffer = (const char*)buf;
619        unsigned int bytesleft = buflen;
620        int nwritten;
621    
622      if (this->fd == 0)      if (this->fd == 0)
623          return -1;          return -1;
624      if (method == HTTP_GET || method == HTTP_HEAD)  
625          return -1;      while (bytesleft > 0) {
626      return send (fd, (const char*)buf, (int)buflen, 0);          nwritten = send (this->fd, buffer, bytesleft, 0);
627            if (nwritten == -1)
628                return -1;
629            bytesleft -= nwritten;
630            buffer += nwritten;
631        }
632        return buflen;
633  }  }
634    
635    
636  /* Return the Winsock specific error code. */  /* Return the Winsock specific error code. */
637  int wHTTP::getErrorCode (void)  int NetHTTP::getErrorCode (void)
638  {  {
639      return error;      return error;
640  }  }

Legend:
Removed from v.313  
changed lines
  Added in v.314

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26