Súbor: [Platon] / dead / mail2sms / http.c (stiahnutie)
Revízia 1.16, Thu May 9 16:10:49 2002 UTC (21 years, 10 months ago) by host8
Zmeny od 1.15: +18 -1
[lines]
* Test of cvs commit (loginfo.sh changed).
* New implementation of HTTP protocol, doesn't work yet.
|
/*
* Author: Lubomir Host 'rajo' <host8@kepler.fmph.uniba.sk>
* $Log: http.c,v $
* Revision 1.16 2002/05/09 16:10:49 host8
* * Test of cvs commit (loginfo.sh changed).
* * New implementation of HTTP protocol, doesn't work yet.
*
* Revision 1.15 2001/11/19 20:15:07 host8
* Http protocol probably works fine.
*
* Revision 1.14 2001/11/16 19:30:01 host8
* Patched bug in declaration/definition of global variable debug.
*
* Revision 1.13 2001/11/14 16:00:07 host8
* Changed some debug messages.
* Improvements in cookies (still not works fine).
*
* Revision 1.12 2001/11/12 20:19:10 host8
* http_connect() probably works fine.
* Some problems with http_requests for www.mtnsms.com.
*
* Revision 1.11 2001/11/12 16:08:00 host8
* Big improvements in http. connect() doesn't work correctly yet.
*
* Revision 1.10 2001/10/30 18:18:12 jombik9
* Improvements.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "mail2sms.h"
#include "strings.h"
#include "strdyn.h"
#include "http.h"
static void free_cookie(COOKIE *c);
static COOKIE *new_cookie(void);
static COOKIE *duplicate_cookie(COOKIE *c);
static COOKIE **add_to_cookies(COOKIE **coo, COOKIE *c);
static char * get_cookie(HTTP_REQUEST *r);
static int get_size_cookies(COOKIE **coo);
static void http_set_cookie(char *str);
static void free_request(HTTP_REQUEST *r);
static int get_size_requests(HTTP_REQUEST **req);
static HTTP_REQUEST **create_requests(void);
static HTTP_REQUEST *new_request(void);
static HTTP_REQUEST *duplicate_request(HTTP_REQUEST *r);
static HTTP_REQUEST **add_to_requests(HTTP_REQUEST **req, HTTP_REQUEST *r);
static char *get_http_referer(HTTP_REQUEST **req);
HTTP_REQUEST **requests;
COOKIE **cookies;
/*
// static struct addrinfo *GetAddrInfo(const char *str, int port) {{{
static struct addrinfo *GetAddrInfo(const char *host, int port)
{
struct addrinfo hints, *res;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host, "80", &hints, &res);
if (error || !res) {
fprintf(stderr, "GetAddrInfo: getaddrinfo(%s, %d): %s\n", host, port,
strerror(error));
res = NULL;
}
return res;
} // }}}
*/
// static void free_cookie(COOKIE *c) {{{
static void free_cookie(COOKIE *c)
{
free(c->domain);
free(c->text);
free(c);
}
// }}}
// static COOKIE **create_cookies(void) {{{
static COOKIE **create_cookies(void)
{
register COOKIE **coo;
if ((coo = (COOKIE **) malloc(1 * sizeof(COOKIE *))) == NULL)
return NULL;
coo[0] = NULL;
return (coo);
} // }}}
// static COOKIE *new_cookie(void) {{{
static COOKIE *new_cookie(void)
{
COOKIE *new;
new = (COOKIE *) malloc(1*sizeof(COOKIE));
new->domain = NULL;
new->text = NULL;
return (new);
} // }}}
// static COOKIE *duplicate_cookie(COOKIE *c) {{{
static COOKIE *duplicate_cookie(COOKIE *c)
{
COOKIE *new;
if (c == NULL)
return (NULL);
if ((new = new_cookie()) == NULL)
return (NULL);
if (c->domain != NULL)
new->domain = strdup(c->domain);
if (c->text != NULL)
new->text = strdup(c->text);
return (new);
} // }}}
// static COOKIE **add_to_cookies(COOKIE **coo, COOKIE *r) {{{
static COOKIE **add_to_cookies(COOKIE **coo, COOKIE *c)
{
register int count;
if (coo == NULL)
if ((coo = create_cookies()) == NULL)
return NULL;
if (c == NULL)
return (coo);
count = get_size_cookies(coo);
coo = (COOKIE **) realloc(coo, (count + 2) * sizeof(COOKIE *));
if (coo == NULL)
return NULL;
coo[count] = c;
coo[count + 1] = NULL;
return coo;
} // }}}
// static COOKIE *parse_cookie(char *str) {{{
static COOKIE *parse_cookie(char *str)
{
COOKIE *c = NULL;
char **array;
int i, j;
char *tmp;
/* Cookies {{{
read(4, "HTTP/1.1 302 Object moved\r\n
Server: Microsoft-IIS/5.0\r\n
Date: Mon, 22 Oct 2001 16:43:36 GMT\r\n
Location: http://www4.mtnsms.com/members/contacts/contacts.asp\r\n
Connection: Keep-Alive\r\n
Content-Length: 173\r\n
Content-Type: text/html\r\n
Expires: Mon, 22 Oct 2001 16:43:36 GMT\r\n
Set-Cookie: mtnsms%2Ep%2E2=color=0&cn=rajo%40host%2Esk&akey=; expires=Sat, 22-Oct-2011 16:43:36 GMT; domain=.mtnsms.com; path=/\r\n
Set-Cookie: mtnsms%2Et%2E2=skey=178A2593%2D5FA7%2D406B%2D8DE9%2D5EA0B8A4BB15; domain=.mtnsms.com; path=/\r\n
Cache-control: private\r\n\r\n
Accept-Language: en\r\nUser-Agent: Lynx/2.8.4dev.7 libwww-FM/2.14\r\n
Referer: http://www.mtnsms.com/\r\n
Cookie2: $Version=\"1\"\r\n
Cookie: mtnsms%2Ep%2E2=color=0&cn=rajo%40host%2Esk&akey=; mtnsms%2Et%2E2=skey=178A2593%2D5FA7%2D406B%2D8DE9%2D5EA0B8A4BB15\r\n\r\n", 747) = 747
* }}} Cookies */
array = strdyn_explode_chr(str, ';');
/* search for cookies with same domain,
* if found, not alloc new cookie.
*/
for (i=0; array[i] != NULL; i++) {
tmp = array[i];
if (tmp == strstr(tmp, " domain=")) {
int count;
count = get_size_cookies(cookies);
for (j=(count-1); j >= 0; j--) {
if (cookies[j] != NULL &&
cookies[j]->domain != NULL &&
strstr(tmp, cookies[j]->domain)
!= NULL) {
/* same domain found, set c to these */
c = cookies[j];
break;
}
}
}
}
if (c == NULL) { // domain not found
c = new_cookie();
}
for (i=0; array[i] != NULL; i++) {
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "COOKIES: parsed_cookie[%d] = '%s'\n", i,
array[i]);
#endif
tmp = array[i];
if (tmp == strstr(tmp, " domain=")) {
c->domain = strdup(tmp+8);
}
else if (tmp == strstr(tmp, " expires=")) {
/* ignored */
}
else if (tmp == strstr(tmp, " path=")) {
/* ignored */
}
else {
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "COOKIES: cookies->text-old = '%s'\n",
c->text);
#endif
if (c->text == NULL)
c->text = strdup(tmp);
else {
char *ar[3];
ar[0] = c->text, ar[1] = tmp, ar[2] = NULL;
c->text = strdyn_implode2_str(ar, "; ");
}
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "COOKIES: cookies->text-new = '%s'\n",
c->text);
#endif
}
}
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "COOKIES: returning cookie, "
"c->domain = '%s' c->text ='%s'\n",
c->domain, c->text);
#endif
return (c);
} // }}}
// static char * get_cookie(HTTP_REQUEST *r) {{{
static char *get_cookie(HTTP_REQUEST *r)
{
int i;
int count;
char *str = NULL;
if (r == NULL || r->host == NULL)
return (NULL);
count = get_size_cookies(cookies);
for (i=(count-1); i >= 0; i--) {
if (cookies[i] != NULL &&
cookies[i]->domain != NULL &&
strstr(r->host, cookies[i]->domain)
!= NULL) {
str = cookies[i]->text;
break;
}
}
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "COOKIES: get_cookie() = '%s'\n", str);
#endif
return (str);
}
// }}}
// static int get_size_cookies(COOKIE **coo) {{{
static int get_size_cookies(COOKIE **coo)
{
register int i;
for (i = 0; coo[i] != NULL; i++)
;
return i;
} // }}}
// static void http_set_cookie(char *str) {{{
static void http_set_cookie(char *str)
{
if (str != NULL) {
if (str == strstr(str, "Set-Cookie: ")) {
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "COOKIES: adding cookie '%s'\n", str);
#endif
cookies = add_to_cookies(cookies, parse_cookie(str + 12));
}
}
} // }}}
// static void free_request(HTTP_REQUEST *r) {{{
static void free_request(HTTP_REQUEST *r)
{
if (r->ret_val != NULL)
free(r->ret_val);
if (r->host != NULL)
free(r->host);
if (r->file != NULL)
free(r->file);
free(r);
}
// }}}
// static int get_size_requests(HTTP_REQUEST **req) {{{
static int get_size_requests(HTTP_REQUEST **req)
{
register int i;
for (i = 0; req[i] != NULL; i++)
;
return i;
} // }}}
// static HTTP_REQUEST **create_requests(void) {{{
static HTTP_REQUEST **create_requests(void)
{
register HTTP_REQUEST **req;
if ((req = (HTTP_REQUEST **) malloc(1 * sizeof(HTTP_REQUEST *))) == NULL)
return NULL;
req[0] = NULL;
return (req);
} // }}}
// static HTTP_REQUEST *new_request(void) {{{
static HTTP_REQUEST *new_request(void)
{
HTTP_REQUEST *new;
new = (HTTP_REQUEST *) malloc(1*sizeof(HTTP_REQUEST));
return (new);
} // }}}
// static HTTP_REQUEST *duplicate_request(HTTP_REQUEST *r) {{{
static HTTP_REQUEST *duplicate_request(HTTP_REQUEST *r)
{
HTTP_REQUEST *new;
if (r == NULL)
return (NULL);
if ((new = new_request()) == NULL)
return (NULL);
new->frw = r->frw;
new->method = r->method;
new->port = r->port;
fprintf(stderr, "%d - OK\n", __LINE__);
if (r->ret_val != NULL)
new->ret_val = strdup(r->ret_val);
else
new->ret_val = NULL;
fprintf(stderr, "%d - OK\n", __LINE__);
if (r->host != NULL)
new->host = strdup(r->host);
else
new->host = NULL;
fprintf(stderr, "%d - OK\n", __LINE__);
if (r->file != NULL)
new->file = strdup(r->file);
else
new->file = NULL;
fprintf(stderr, "%d - OK\n", __LINE__);
return (new);
} // }}}
// static HTTP_REQUEST **add_to_requests(HTTP_REQUEST **req, HTTP_REQUEST *r) {{{
static HTTP_REQUEST **add_to_requests(HTTP_REQUEST **req, HTTP_REQUEST *r)
{
register int count;
if (req == NULL)
if ((req = create_requests()) == NULL)
return NULL;
count = get_size_requests(req);
req = (HTTP_REQUEST **) realloc(req, (count + 2) * sizeof(HTTP_REQUEST *));
if (req == NULL)
return NULL;
// req[count] = duplicate_request(r);
req[count] = r;
req[count + 1] = NULL;
return req;
} // }}}
// static char * get_http_referer(HTTP_REQUEST **req) {{{
static char *get_http_referer(HTTP_REQUEST **req)
{
int count;
count = get_size_requests(req);
if (count > 0) {
return (req[count - 1]->referer);
}
return (NULL);
}
// }}}
// static char * http_clean_referer(HTTP_REQUEST **req) {{{
void http_clean_referer(HTTP_REQUEST **req)
{
int i;
for (i=0; req[i] != NULL; i++) {
if (req[i]->referer != NULL)
free(req[i]->referer);
}
return ;
}
// }}}
// static http_connect(HTTP_REQUEST *r) {{{
static FILE *http_connect(HTTP_REQUEST *r)
{
int s = 0;
int i, idx = -1;
struct sockaddr_in serv_addr;
// struct addrinfo *res0;
if (r == NULL || r->host == NULL)
return (NULL);
for (i=0; servers[i].desc != NULL; i++) {
if (servers[i].id == id) {
idx = i;
break;
}
}
if (idx == -1) {
fprintf(stderr, "Id %d not found in servers[] !\n", id);
exit(1);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(r->host);
if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
struct hostent *pent = gethostbyname(r->host);
if (pent != NULL)
serv_addr.sin_addr.s_addr = *((u_long *) (pent->h_addr));
}
if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
#ifdef DEBUG
if (debug > 8) {
fprintf(stderr, "%s: %d - catched error\n",
__FILE__, __LINE__);
}
#endif
fprintf(stderr, "Can't connect to %s[%s:%hd] - %s\n",
servers[idx].desc,
servers[idx].ip,
r->port, strerror(errno));
return (NULL);
}
if (r->port != 0) {
serv_addr.sin_port = htons((u_short) r->port);
if (serv_addr.sin_port == 0) {
struct servent *pent;
char str_port[10];
#ifdef DEBUG
if (debug > 6) {
fprintf(stderr, "(u_short) r->port = %hd\n", r->port);
}
#endif
if (snprintf(str_port, 9, "%hd", r->port) == -1) {
fprintf(stderr, "Can't connect to %s[%s:%s] - %s\n",
servers[idx].desc,
servers[idx].ip,
str_port, strerror(errno));
return (NULL);
}
pent = getservbyname(str_port, "tcp");
if (pent != NULL)
serv_addr.sin_port = pent->s_port;
}
if (serv_addr.sin_port == 0) {
#ifdef DEBUG
if (debug > 8) {
fprintf(stderr, "%s: %d - catched error\n",
__FILE__, __LINE__);
}
#endif
fprintf(stderr, "Can't connect to %s[%s:%hd] - %s\n",
servers[idx].desc,
servers[idx].ip,
r->port, strerror(errno));
return (NULL);
}
}
else {
// No port specified ... use telnet port. //
struct servent *pent;
pent = getservbyname ("www", "tcp");
if (pent == NULL)
serv_addr.sin_port = htons(80);
else
serv_addr.sin_port = pent->s_port;
}
s = socket(PF_INET, SOCK_STREAM, 0);
if (s != -1) {
for (i=0; i<MAX_CONNECTS; i++) {
if (connect(s, (struct sockaddr *)&serv_addr,
sizeof(serv_addr)) != -1) {
if ((r->frw = fdopen(s, "w+b")) != NULL)
return (r->frw);
}
}
}
else {
#ifdef DEBUG
if (debug > 8) {
fprintf(stderr, "%s: %d - catched error\n",
__FILE__, __LINE__);
}
#endif
fprintf(stderr, "Can't connect to %s[%s:%hd] - %s\n",
servers[idx].desc,
servers[idx].ip,
r->port, strerror(errno));
return (NULL);
}
#ifdef DEBUG
if (debug > 8) {
fprintf(stderr, "%s: %d - catched error\n",
__FILE__, __LINE__);
}
#endif
fprintf(stderr, "Can't connect to %s[%s:%hd] - %s\n",
servers[idx].desc,
servers[idx].ip,
r->port, strerror(errno));
return (NULL);
} // }}}
// static void http_read_source(HTTP_REQUEST *r) {{{
static void http_read_source(HTTP_REQUEST *r)
{
int search_for_link = 0;
#ifdef DEBUG
int info = debug;
#else
int info = 1;
#endif
int bad_request = 0;
char *buf;
char *new_host = NULL;
char *new_file = NULL;
#define BUF_SIZE 1024
if ((buf = (char *) malloc((BUF_SIZE)*sizeof(char))) == NULL) {
fprintf(stderr, "Memory aloocation failed!\n");
exit(1);
}
while (1) {
memset(buf, 0, BUF_SIZE);
if (fgets(buf, ((BUF_SIZE) -1), r->frw) == NULL)
break;
buf[BUF_SIZE -1] = '\0';
strrmeol(buf);
if (r->ret_val == NULL)
r->ret_val = strdup(buf);
if (buf == strstr(buf, "Set-Cookie: "))
http_set_cookie(buf);
if (search_for_link == 1) { /* Handling " 302 Object Moved" {{{ */
if (buf == strstr(buf, "Location: ")) {
char *str;
char *tmp;
if ((str = strdup(buf)) == NULL) {
fprintf(stderr, "strdup(%s) failed!\n", buf);
exit(1);
}
strrmeol(str);
if ((tmp = strstr((str + 17), "/")) != NULL) {
new_file = strdup(tmp);
new_host = (char *)
malloc ((tmp - str - 16)*sizeof(char));
strncpy(new_host, (str + 17), (tmp - str - 17));
new_host[tmp - str - 17] = '\0';
#ifdef DEBUG
fprintf(stderr, "FILENAME = '%s', HOST = '%s'\n",
new_file,
new_host);
#endif
}
#ifdef DEBUG
else {
fprintf(stderr, "Invalid link '%s'!\n", str);
}
fprintf(stderr, "Object Moved = '%s'\n", str);
#endif
free(str);
search_for_link = 0;
}
} /* }}} End of Handling '302 Object Moved' */
if (info) {
fprintf(stderr, "\t%.*s\n", (int)(strlen(buf)), buf);
info=0;
if (strstr(buf, "HTTP/1.") != NULL) {
if ((buf+8) == strstr(buf, " 200 OK")) {
// TODO: test this:
r->referer = strdup(r->host);
//http_set_referer(host, file);
}
if ((buf+8) == strstr(buf, " 302 Object moved")) {
#ifdef DEBUG
fprintf(stderr, "Searching for 'Location: '...\n");
#endif
search_for_link = 1 ;
}
if ((buf+8) == strstr(buf, " 400 Bad Request")) {
bad_request = 1;
}
if ((buf+8) == strstr(buf, " 404 Object Not Found")) {
bad_request = 1;
}
if ((buf+8) == strstr(buf, " 500 Server Error")) {
bad_request = 1;
}
}
}
#ifdef DEBUG
if (debug > 10) {
fprintf(stderr, "HTTP_SOURCE: '%s'\n", buf);
}
else if (debug > 8 ) {
fputs(buf, stderr);
}
#endif
}
#ifdef DEBUG
if (search_for_link == 1) {
fprintf(stderr, "Link NOT FOUND!\n");
}
#endif
fclose (r->frw);
if (bad_request)
exit(1);
if (new_host != NULL && new_file != NULL) {
http_request(HTTP_GET, new_file, new_host, NULL);
free(new_host);
free(new_file);
}
free(buf);
} // }}}
// int http_request_by_request(HTTP_REQUEST *r) {{{
int http_request_by_request(HTTP_REQUEST *r)
{
return (http_request(r->method, r->file, r->host, NULL));
} // }}}
// int http_request(int method, char *file, char *host, char *fmt, ...) {{{
int http_request(int method, char *file, char *host, char *fmt, ...)
{
va_list ap;
HTTP_REQUEST *r;
#ifdef DEBUG
if (debug) { // Debug code STAHUJEM/POSIELAM {{{
if (method == HTTP_GET) {
fprintf(stderr, "GET: %s%s\n", host, file);
}
else if (method == HTTP_POST) {
fprintf(stderr, "POST: %s%s\n", host, file);
}
} // }}}
#endif
r = new_request();
r->port = (u_short) 80;
r->method = method;
r->host = strdup(host);
r->file = strdup(file);
requests = add_to_requests(requests, r);
if ((r->frw = http_connect(r)) == NULL) {
exit(errno);
}
switch (r->method) {
case HTTP_GET:
fprintf(r->frw, "GET %s HTTP/1.0\r\n", file);
break;
case HTTP_POST:
fprintf(r->frw, "POST %s HTTP/1.0\r\n", file);
break;
default:
fprintf(stderr, "Unknown http method %d\n", method);
break;
}
fprintf(r->frw, "Host: %s\r\n", host);
fprintf(r->frw, "Accept: text/html, text/plain, application/applefile, ");
fprintf(r->frw, "application/x-metamail-patch, sun-deskset-message, ");
fprintf(r->frw, "mail-file, default, postscript-file, audio-file, ");
fprintf(r->frw, "x-sun-attachment, text/enriched, text/richtext, ");
fprintf(r->frw, "application/andrew-inset, x-be2\r\n");
fprintf(r->frw, "Accept: application/postscript, message/external-body, ");
fprintf(r->frw, "message/partial, image/g3fax, application/pdf, ");
fprintf(r->frw, "application/pgp, application/pgp, video/mpeg, video/*, ");
fprintf(r->frw, "image/*, audio/mod, text/sgml, */*;q=0.01\r\n");
fprintf(r->frw, "Accept-Encoding: gzip, compress\r\n");
fprintf(r->frw, "Accept-Language: en\r\n");
if (method == HTTP_POST) {
fprintf(r->frw, "Pragma: no-cache\r\n");
fprintf(r->frw, "Cache-Control: no-cache\r\n");
}
fprintf(r->frw, "%s", USER_AGENT);
if (get_http_referer(requests) != NULL)
fprintf(r->frw, "Referer: %s\r\n", get_http_referer(requests));
if (get_cookie(r) != NULL) {
#ifdef DEBUG
if (debug > 4)
fprintf(stderr, "HTTP: sending cookies:\r\n"
"Cookie2: $Version=\"1\"\r\n"
"Cookie: %s\r\n",
get_cookie(r));
#endif
fprintf(r->frw, "Cookie2: $Version=\"1\"\r\nCookie: %s\r\n",
get_cookie(r));
}
if (fmt != NULL) {
va_start(ap, fmt);
vfprintf(r->frw, fmt, ap);
va_end(ap);
}
fprintf(r->frw, "\r\n");
http_read_source(r);
#ifdef DEBUG
if (debug) {
fprintf(stderr, "HTTP request sent, reply OK...\n");
}
#endif
return 0;
} // }}}
// char *get_last_hostname(void) {{{
char *get_last_hostname(void)
{
int count;
count = get_size_requests(requests);
#ifdef DEBUG
if (debug > 6) {
fprintf(stderr, "get_last_hostname() = '%s'\n",
requests[count-1]->host);
}
#endif
return (requests[count-1]->host);
}
// }}}
// void http_init(void) {{{
void http_init(void)
{
if ((requests = create_requests()) == NULL) {
fprintf(stderr, "Failed creation of internal structures!\n");
exit(1);
}
if ((cookies = create_cookies()) == NULL) {
fprintf(stderr, "Failed creation of internal structures!\n");
exit(1);
}
return;
}
// }}}
// void free_requests(HTTP_REQUEST **req) {{{
void free_requests(HTTP_REQUEST **req)
{
register int i;
for (i = 0; req[i] != NULL; i++)
free_request(req[i]);
free(req);
}
// }}}
/* Modeline for ViM {{{1
* vim:set ts=4:
* vim600:fdm=marker fdl=0 fdc=3:
* }}}1 */
Platon Group <platon@platon.sk> http://platon.sk/
|