googlefs: use libnetservices for HTTP requests
This allows us to do HTTPS more easily and removes a lot of the code. A file is converted to C++ to allow use of these APIs. Now Google replies to the query with… a page asking to accept cookies, and no results at all. They are definitely not cool anymore. Change-Id: I4bed3b1f8630b324b979d26fbb71c4f05165fbb5 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5494 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
d669317867
commit
31111d806f
@@ -4,20 +4,22 @@ local userlandFSTop = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems
|
|||||||
userlandfs ] ;
|
userlandfs ] ;
|
||||||
local userlandFSIncludes = [ PrivateHeaders userlandfs ] ;
|
local userlandFSIncludes = [ PrivateHeaders userlandfs ] ;
|
||||||
|
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
UsePrivateHeaders netservices ;
|
||||||
|
|
||||||
#SubDirCcFlags -DTRACK_FILENAME ;
|
#SubDirCcFlags -DTRACK_FILENAME ;
|
||||||
#SubDirCcFlags -DDEBUG_GOOGLEFS=1 ;
|
#SubDirCcFlags -DDEBUG_GOOGLEFS=1 ;
|
||||||
SubDirCcFlags -D_IMPEXP_KERNEL= ;
|
SubDirCcFlags -D_IMPEXP_KERNEL= ;
|
||||||
|
|
||||||
Addon googlefs :
|
Addon googlefs :
|
||||||
attrs.c
|
attrs.c
|
||||||
google_request.c
|
google_request.cpp
|
||||||
googlefs.c
|
googlefs.c
|
||||||
http_cnx.c
|
|
||||||
lists2.c
|
lists2.c
|
||||||
parse_google_html.c
|
parse_google_html.c
|
||||||
query.c
|
query.c
|
||||||
settings.c
|
settings.c
|
||||||
string_utils.c
|
string_utils.c
|
||||||
vnidpool.c
|
vnidpool.c
|
||||||
: libuserlandfs_haiku_kernel.so network
|
: libuserlandfs_haiku_kernel.so libnetservices.a bnetapi be network shared [ TargetLibstdc++ ]
|
||||||
;
|
;
|
||||||
|
|||||||
+26
-75
@@ -12,13 +12,18 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include "http_cnx.h"
|
|
||||||
#include "googlefs.h"
|
|
||||||
#include "google_request.h"
|
#include "google_request.h"
|
||||||
|
|
||||||
|
#include "googlefs.h"
|
||||||
#include "lists2.h"
|
#include "lists2.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
|
|
||||||
|
#include <UrlProtocolRoster.h>
|
||||||
|
#include <UrlRequest.h>
|
||||||
|
|
||||||
|
using namespace BPrivate::Network;
|
||||||
|
|
||||||
#define DO_PUBLISH
|
#define DO_PUBLISH
|
||||||
//#define FAKE_INPUT "/boot/home/devel/drivers/googlefs/log2.html"
|
//#define FAKE_INPUT "/boot/home/devel/drivers/googlefs/log2.html"
|
||||||
|
|
||||||
@@ -29,83 +34,34 @@
|
|||||||
//#define EXTRAURL "&num=50&hl=en&ie=ISO-8859-1&btnG=Google+Search&as_epq=frequently+asked&as_oq=help&as_eq=plop&lr=lang_en&as_ft=i&as_filetype=&as_qdr=m3&as_nlo=&as_nhi=&as_occt=any&as_dt=i&as_sitesearch="
|
//#define EXTRAURL "&num=50&hl=en&ie=ISO-8859-1&btnG=Google+Search&as_epq=frequently+asked&as_oq=help&as_eq=plop&lr=lang_en&as_ft=i&as_filetype=&as_qdr=m3&as_nlo=&as_nhi=&as_occt=any&as_dt=i&as_sitesearch="
|
||||||
|
|
||||||
#define TESTURL "http://www.google.com/search?hl=en&ie=UTF-8&num=50&q=beos"
|
#define TESTURL "http://www.google.com/search?hl=en&ie=UTF-8&num=50&q=beos"
|
||||||
//#define BASEURL "http://www.google.com/search?hl=en&ie=UTF-8&num=50&q="
|
#define BASEURL "https://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&gws_rd=cr"
|
||||||
#define BASEURL "/search?hl=en&ie=UTF-8&oe=UTF-8&gws_rd=cr"
|
|
||||||
#define FMT_NUM "&num=%u"
|
#define FMT_NUM "&num=%u"
|
||||||
#define FMT_Q "&q=%s"
|
#define FMT_Q "&q=%s"
|
||||||
|
|
||||||
/* parse_google_html.c */
|
/* parse_google_html.c */
|
||||||
extern int google_parse_results(const char *html, size_t htmlsize, long *nextid, struct google_result **results);
|
extern int google_parse_results(const char *html, size_t htmlsize, long *nextid, struct google_result **results);
|
||||||
|
|
||||||
// move that to ksocket inlined
|
|
||||||
static int kinet_aton(const char *in, struct in_addr *addr)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned long a;
|
|
||||||
uint32 inaddr = 0L;
|
|
||||||
const char *p = in;
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
a = strtoul(p, (char **)&p, 10);
|
|
||||||
if (!p)
|
|
||||||
return -1;
|
|
||||||
inaddr = (inaddr >> 8) | ((a & 0x0ff) << 24);
|
|
||||||
*(uint32 *)addr = inaddr;
|
|
||||||
if (!*p)
|
|
||||||
return 0;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t google_request_init(void)
|
|
||||||
{
|
|
||||||
status_t err;
|
|
||||||
err = http_init();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t google_request_uninit(void)
|
|
||||||
{
|
|
||||||
status_t err;
|
|
||||||
err = http_uninit();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t google_request_process(struct google_request *req)
|
status_t google_request_process(struct google_request *req)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin;
|
struct BUrlRequest *cnx = NULL;
|
||||||
struct http_cnx *cnx = NULL;
|
|
||||||
struct google_result *res;
|
struct google_result *res;
|
||||||
status_t err;
|
status_t err;
|
||||||
int count;
|
int count;
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
|
BMallocIO output;
|
||||||
|
thread_id t;
|
||||||
|
|
||||||
err = http_create(&cnx);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
req->cnx = cnx;
|
req->cnx = cnx;
|
||||||
#ifndef FAKE_INPUT
|
#ifndef FAKE_INPUT
|
||||||
sin.sin_len = sizeof(struct sockaddr_in);
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
||||||
if (kinet_aton(google_server, &sin.sin_addr) < 0)
|
|
||||||
goto err_cnx;
|
|
||||||
sin.sin_port = htons(google_server_port);
|
|
||||||
err = http_connect(cnx, &sin);
|
|
||||||
fprintf(stderr, "google_request: http_connect: error 0x%08" B_PRIx32 "\n", err);
|
|
||||||
if (err)
|
|
||||||
goto err_cnx;
|
|
||||||
|
|
||||||
err = ENOMEM;
|
|
||||||
p = urlify_string(req->query_string);
|
p = urlify_string(req->query_string);
|
||||||
if (!p)
|
if (!p)
|
||||||
goto err_con;
|
goto err_con;
|
||||||
|
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
url = malloc(strlen(BASEURL)+strlen(FMT_NUM)+10+strlen(FMT_Q)+strlen(p)+2);
|
url = (char*)malloc(strlen(BASEURL)+strlen(FMT_NUM)+10+strlen(FMT_Q)+strlen(p)+2);
|
||||||
if (!url)
|
if (!url)
|
||||||
goto err_url;
|
goto err_url;
|
||||||
strcpy(url, BASEURL);
|
strcpy(url, BASEURL);
|
||||||
@@ -114,19 +70,19 @@ status_t google_request_process(struct google_request *req)
|
|||||||
|
|
||||||
fprintf(stderr, "google_request: final URL: %s\n", url);
|
fprintf(stderr, "google_request: final URL: %s\n", url);
|
||||||
|
|
||||||
err = http_get(cnx, url);
|
cnx = BUrlProtocolRoster::MakeRequest(url, &output, NULL);
|
||||||
fprintf(stderr, "google_request: http_get: error 0x%08" B_PRIx32 "\n", err);
|
if (cnx == NULL)
|
||||||
if (err < 0)
|
return ENOMEM;
|
||||||
goto err_url2;
|
|
||||||
fprintf(stderr, "google_request: http_get: HEADERS %ld:%s\n", cnx->headerslen, cnx->headers);
|
t = cnx->Run();
|
||||||
//fprintf(stderr, "DATA: %d:%s\n", cnx->datalen, cnx->data);
|
wait_for_thread(t, &err);
|
||||||
|
|
||||||
fprintf(stderr, "google_request: buffer @ %p, len %ld\n", cnx->data, cnx->datalen);
|
fprintf(stderr, "google_request: buffer @ %p, len %ld\n", output.Buffer(), output.BufferLength());
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
// debug output
|
// debug output
|
||||||
fd = open("/tmp/google.html", O_CREAT|O_TRUNC|O_RDWR, 0644);
|
fd = open("/tmp/google.html", O_CREAT|O_TRUNC|O_RDWR, 0644);
|
||||||
write(fd, cnx->data, cnx->datalen);
|
write(fd, output.Buffer(), output.BufferLength());
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -150,7 +106,8 @@ status_t google_request_process(struct google_request *req)
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
#endif /* FAKE_INPUT */
|
#endif /* FAKE_INPUT */
|
||||||
err = count = google_parse_results(req->cnx->data, req->cnx->datalen, &req->nextid, &req->results);
|
err = count = google_parse_results((const char*)output.Buffer(), output.BufferLength(),
|
||||||
|
&req->nextid, &req->results);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_get;
|
goto err_get;
|
||||||
#ifdef DO_PUBLISH
|
#ifdef DO_PUBLISH
|
||||||
@@ -161,21 +118,16 @@ status_t google_request_process(struct google_request *req)
|
|||||||
#endif
|
#endif
|
||||||
free(url);
|
free(url);
|
||||||
free(p);
|
free(p);
|
||||||
/* close now */
|
// request is kept and deleted in google_request_close
|
||||||
http_close(cnx);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
|
||||||
err_get:
|
err_get:
|
||||||
err_url2:
|
|
||||||
free(url);
|
free(url);
|
||||||
err_url:
|
err_url:
|
||||||
free(p);
|
free(p);
|
||||||
err_con:
|
err_con:
|
||||||
http_close(cnx);
|
delete cnx;
|
||||||
err_cnx:
|
|
||||||
http_delete(cnx);
|
|
||||||
req->cnx = NULL;
|
req->cnx = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -191,8 +143,7 @@ status_t google_request_close(struct google_request *req)
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (!req->cnx)
|
if (!req->cnx)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
http_close(req->cnx);
|
delete(req->cnx);
|
||||||
http_delete(req->cnx);
|
|
||||||
req->cnx = NULL;
|
req->cnx = NULL;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -202,7 +153,7 @@ status_t google_request_open(const char *query_string, struct fs_volume *volume,
|
|||||||
struct google_request *r;
|
struct google_request *r;
|
||||||
if (!req)
|
if (!req)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
r = malloc(sizeof(struct google_request));
|
r = (google_request*)malloc(sizeof(struct google_request));
|
||||||
if (!r)
|
if (!r)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
memset(r, 0, sizeof(struct google_request));
|
memset(r, 0, sizeof(struct google_request));
|
||||||
@@ -5,12 +5,21 @@
|
|||||||
#ifndef _GOOGLE_REQUEST_H
|
#ifndef _GOOGLE_REQUEST_H
|
||||||
#define _GOOGLE_REQUEST_H
|
#define _GOOGLE_REQUEST_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <UrlRequest.h>
|
||||||
|
using namespace BPrivate::Network;
|
||||||
|
extern "C" {
|
||||||
|
#else
|
||||||
|
struct BUrlRequest;
|
||||||
|
typedef struct BUrlRequest BUrlRequest;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct google_request {
|
struct google_request {
|
||||||
struct google_request *next;
|
struct google_request *next;
|
||||||
struct fs_volume *volume;
|
struct fs_volume *volume;
|
||||||
struct fs_node *query_node; /* root folder for that query */
|
struct fs_node *query_node; /* root folder for that query */
|
||||||
char *query_string;
|
char *query_string;
|
||||||
struct http_cnx *cnx;
|
BUrlRequest *cnx;
|
||||||
struct google_result *results;
|
struct google_result *results;
|
||||||
long nextid;
|
long nextid;
|
||||||
};
|
};
|
||||||
@@ -31,8 +40,6 @@ struct google_result {
|
|||||||
char similar_url[GR_MAX_URL];
|
char similar_url[GR_MAX_URL];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern status_t google_request_init(void);
|
|
||||||
extern status_t google_request_uninit(void);
|
|
||||||
extern status_t google_request_process(struct google_request *req);
|
extern status_t google_request_process(struct google_request *req);
|
||||||
extern status_t google_request_process_async(struct google_request *req);
|
extern status_t google_request_process_async(struct google_request *req);
|
||||||
extern status_t google_request_close(struct google_request *req);
|
extern status_t google_request_close(struct google_request *req);
|
||||||
@@ -41,4 +48,8 @@ extern status_t google_request_free(struct google_request *req);
|
|||||||
|
|
||||||
extern int google_parse_results(const char *html, size_t htmlsize, long *nextid, struct google_result **results);
|
extern int google_parse_results(const char *html, size_t htmlsize, long *nextid, struct google_result **results);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _GOOGLE_REQUEST_H */
|
#endif /* _GOOGLE_REQUEST_H */
|
||||||
|
|||||||
@@ -133,10 +133,6 @@ static status_t googlefs_mount(fs_volume *_vol, const char *devname, uint32 flag
|
|||||||
|
|
||||||
err = load_settings();
|
err = load_settings();
|
||||||
|
|
||||||
err = google_request_init();
|
|
||||||
if (err)
|
|
||||||
goto err_http;
|
|
||||||
|
|
||||||
ns = malloc(sizeof(fs_nspace));
|
ns = malloc(sizeof(fs_nspace));
|
||||||
if (!ns)
|
if (!ns)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -184,7 +180,6 @@ static status_t googlefs_mount(fs_volume *_vol, const char *devname, uint32 flag
|
|||||||
}
|
}
|
||||||
free_lock(&ns->l);
|
free_lock(&ns->l);
|
||||||
free(ns);
|
free(ns);
|
||||||
err_http:
|
|
||||||
atomic_add(&refcount, -1);
|
atomic_add(&refcount, -1);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -211,8 +206,6 @@ static status_t googlefs_unmount(fs_volume *_volume)
|
|||||||
vnidpool_free(ns->vnids);
|
vnidpool_free(ns->vnids);
|
||||||
free(ns);
|
free(ns);
|
||||||
|
|
||||||
google_request_uninit();
|
|
||||||
|
|
||||||
atomic_add(&refcount, -1);
|
atomic_add(&refcount, -1);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ typedef dev_t nspace_id;
|
|||||||
|
|
||||||
#define MAX_VNIDS 5000
|
#define MAX_VNIDS 5000
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
struct attr_entry {
|
struct attr_entry {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -132,4 +135,8 @@ int googlefs_event(fs_nspace *ns, fs_node *node, int flags);
|
|||||||
*/
|
*/
|
||||||
extern int googlefs_push_result_to_query(struct google_request *request, struct google_result *result);
|
extern int googlefs_push_result_to_query(struct google_request *request, struct google_result *result);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,262 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-2008, François Revol, <[email protected]>.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "ksocket.h"
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include "http_cnx.h"
|
|
||||||
|
|
||||||
//#define TESTME
|
|
||||||
|
|
||||||
#ifdef _KERNEL_MODE
|
|
||||||
#include <KernelExport.h>
|
|
||||||
#define printf dprintf
|
|
||||||
#undef TESTME
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DBG "googlefs: http_cnx: "
|
|
||||||
|
|
||||||
#define HTTPVER "1.0"
|
|
||||||
|
|
||||||
//#define GOOGLEFS_UA "GoogleFS"
|
|
||||||
//Mozilla/3.0 (compatible; NetPositive/2.2.2; BeOS)
|
|
||||||
//Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.18) Gecko/20081114 BonEcho/2.0.0.18
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
#define GOOGLEFS_UA "Mozilla/5.0 (compatible; GoogleFS/0.1; Haiku)"
|
|
||||||
#else
|
|
||||||
#define GOOGLEFS_UA "Mozilla/5.0 (compatible; GoogleFS/0.1; BeOS)"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TESTME
|
|
||||||
#define BUFSZ (128*1024)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
KSOCKET_MODULE_DECL;
|
|
||||||
|
|
||||||
status_t http_init(void)
|
|
||||||
{
|
|
||||||
return ksocket_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t http_uninit(void)
|
|
||||||
{
|
|
||||||
return ksocket_cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t http_create(struct http_cnx **cnx)
|
|
||||||
{
|
|
||||||
struct http_cnx *c;
|
|
||||||
int err;
|
|
||||||
c = malloc(sizeof(struct http_cnx));
|
|
||||||
if (!c)
|
|
||||||
return ENOMEM;
|
|
||||||
memset(c, 0, sizeof(struct http_cnx));
|
|
||||||
err = c->sock = ksocket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (err < 0) {
|
|
||||||
free(c);
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
*cnx = c;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t http_delete(struct http_cnx *cnx)
|
|
||||||
{
|
|
||||||
if (!cnx)
|
|
||||||
return EINVAL;
|
|
||||||
if ((unsigned long)cnx < 0x40) {
|
|
||||||
fprintf(stderr, "http: WARNING: cnx ptr = %p\n", cnx);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
if (cnx->sock >= 0) {
|
|
||||||
kclosesocket(cnx->sock);
|
|
||||||
cnx->sock = -1;
|
|
||||||
}
|
|
||||||
if (cnx->buffer)
|
|
||||||
free(cnx->buffer);
|
|
||||||
cnx->buffer = (char *)0xaa55aa55;//XXX
|
|
||||||
free(cnx);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t http_connect(struct http_cnx *cnx, struct sockaddr_in *sin)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
uint32 ip;
|
|
||||||
uint16 port;
|
|
||||||
if (!sin) {
|
|
||||||
fprintf(stderr, "http_connect(, NULL)!!\n");
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
ip = sin->sin_addr.s_addr;
|
|
||||||
port = sin->sin_port;
|
|
||||||
fprintf(stderr, "http_connect(, %"B_PRId32".%"B_PRId32".%" B_PRId32 ".%" B_PRId32 ":%d), sock = %d\n", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff, ntohs(port), cnx->sock);
|
|
||||||
err = kconnect(cnx->sock, (struct sockaddr *)sin, sin->sin_len);
|
|
||||||
cnx->err = 0;
|
|
||||||
if (err == -1)
|
|
||||||
return errno;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t http_close(struct http_cnx *cnx)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
if (!cnx)
|
|
||||||
return EINVAL;
|
|
||||||
if (cnx->sock < 0)
|
|
||||||
return 0;
|
|
||||||
err = kclosesocket(cnx->sock);
|
|
||||||
cnx->sock = -1;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t http_get(struct http_cnx *cnx, const char *url)
|
|
||||||
{
|
|
||||||
char *req, *p;
|
|
||||||
int reqlen;
|
|
||||||
int len;
|
|
||||||
int err;
|
|
||||||
long headerslen = 0;
|
|
||||||
long contentlen = 0;
|
|
||||||
if (strlen(url) > 4096 - 128)
|
|
||||||
return EINVAL;
|
|
||||||
req = malloc(4096+1);
|
|
||||||
if (!req)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
req[4096] = '\0';
|
|
||||||
/* no snprintf in kernel :( */
|
|
||||||
sprintf(req, "GET %s HTTP/"HTTPVER"\r\nUser-Agent: " GOOGLEFS_UA "\r\nAccept: */*\r\n\r\n", url);
|
|
||||||
reqlen = strlen(req);
|
|
||||||
err = len = write(cnx->sock, req, reqlen);
|
|
||||||
if (len < 1)
|
|
||||||
goto err0;
|
|
||||||
reqlen = 4096;
|
|
||||||
err = len = read(cnx->sock, req, reqlen);
|
|
||||||
printf("read(sock) = %d\n", len);
|
|
||||||
if (err < 0)
|
|
||||||
goto err0;
|
|
||||||
//write(1, req, len);
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
// debug output
|
|
||||||
fd = open("/tmp/google.html_", O_CREAT|O_TRUNC|O_RDWR, 0644);
|
|
||||||
write(fd, req, len);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = EINVAL;
|
|
||||||
if (len < 10)
|
|
||||||
goto err0;
|
|
||||||
if (!strstr(req, "HTTP/1.0 200"))
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
err = B_NO_MEMORY;
|
|
||||||
if (!strstr(req, "\r\n\r\n")) {
|
|
||||||
if (!strstr(req, "\n\n")) /* shouldn't happen */
|
|
||||||
goto err0;
|
|
||||||
headerslen = strstr(req, "\n\n") - req + 2;
|
|
||||||
req[headerslen-1] = '\0';
|
|
||||||
req[headerslen-2] = '\0';
|
|
||||||
} else {
|
|
||||||
headerslen = strstr(req, "\r\n\r\n") - req + 4;
|
|
||||||
req[headerslen-3] = '\0';
|
|
||||||
req[headerslen-4] = '\0';
|
|
||||||
}
|
|
||||||
if (headerslen < 2 || headerslen > 4095)
|
|
||||||
goto err0;
|
|
||||||
p = strstr(req, "HTTP/1.");
|
|
||||||
if (!p)
|
|
||||||
goto err0;
|
|
||||||
p += strlen("HTTP/1.");
|
|
||||||
if (strlen(p) < 5)
|
|
||||||
goto err0;
|
|
||||||
p += strlen("1 ");
|
|
||||||
cnx->err = strtol(p, &p, 10);
|
|
||||||
if (cnx->err < 200 || cnx->err > 299)
|
|
||||||
goto err0;
|
|
||||||
printf("REQ: %" B_PRId32 "\n", cnx->err);
|
|
||||||
contentlen = len - headerslen;
|
|
||||||
// if (!strstr(req, "\n\n") && !strstr(req, "\r\n\r\n"))
|
|
||||||
// goto err0;
|
|
||||||
while (len > 0) {
|
|
||||||
long left = reqlen - headerslen - contentlen;
|
|
||||||
if (left < 128) {
|
|
||||||
reqlen += 4096;
|
|
||||||
p = realloc(req, reqlen);
|
|
||||||
left += 4096;
|
|
||||||
if (!p)
|
|
||||||
goto err0;
|
|
||||||
req = p;
|
|
||||||
}
|
|
||||||
err = len = read(cnx->sock, req + headerslen + contentlen, left);
|
|
||||||
if (len < 0)
|
|
||||||
goto err0;
|
|
||||||
contentlen += len;
|
|
||||||
}
|
|
||||||
cnx->buffer = req;
|
|
||||||
cnx->headers = req;
|
|
||||||
cnx->headerslen = headerslen;
|
|
||||||
cnx->data = req + headerslen;
|
|
||||||
cnx->datalen = contentlen;
|
|
||||||
cnx->data[contentlen] = '\0'; /* we have at least 128 bytes allocated ahead */
|
|
||||||
return B_OK;
|
|
||||||
err0:
|
|
||||||
if (err > -1)
|
|
||||||
err = -1;
|
|
||||||
free(req);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TESTME
|
|
||||||
//#define TESTURL "/"
|
|
||||||
//#define TESTURL "http://www.google.com/search?as_q=google+api+&num=50&hl=en&ie=ISO-8859-1&btnG=Google+Search&as_epq=frequently+asked&as_oq=help&as_eq=plop&lr=lang_en&as_ft=i&as_filetype=&as_qdr=m3&as_nlo=&as_nhi=&as_occt=any&as_dt=i&as_sitesearch="
|
|
||||||
#define TESTURL "http://www.google.com/search?hl=en&ie=UTF-8&num=50&q=beos"
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
struct http_cnx *cnx;
|
|
||||||
size_t len;
|
|
||||||
char *p;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
http_init();
|
|
||||||
err = http_create(&cnx);
|
|
||||||
printf("error 0x%08lx\n", err);
|
|
||||||
sin.sin_len = sizeof(struct sockaddr_in);
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
||||||
inet_aton("66.102.11.99", &sin.sin_addr);
|
|
||||||
sin.sin_port = htons(80);
|
|
||||||
err = http_connect(cnx, &sin);
|
|
||||||
printf("error 0x%08lx\n", err);
|
|
||||||
err = http_get(cnx, TESTURL);
|
|
||||||
printf("error 0x%08lx\n", err);
|
|
||||||
if (err < 0)
|
|
||||||
return 1;
|
|
||||||
printf("HEADERS %d:%s\n", cnx->headerslen, cnx->headers);
|
|
||||||
printf("DATA: %d:%s\n", cnx->datalen, cnx->data);
|
|
||||||
http_close(cnx);
|
|
||||||
http_delete(cnx);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2004-2008, François Revol, <[email protected]>.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef _HTTP_CNX_H
|
|
||||||
#define _HTTP_CNX_H
|
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
struct http_cnx {
|
|
||||||
int sock;
|
|
||||||
status_t err; /* 404, ... */
|
|
||||||
char *headers;
|
|
||||||
size_t headerslen;
|
|
||||||
char *data;
|
|
||||||
size_t datalen;
|
|
||||||
/* for bookkeeping */
|
|
||||||
char *buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sockaddr_in;
|
|
||||||
|
|
||||||
extern status_t http_init(void);
|
|
||||||
extern status_t http_uninit(void);
|
|
||||||
|
|
||||||
extern status_t http_create(struct http_cnx **);
|
|
||||||
extern status_t http_delete(struct http_cnx *cnx);
|
|
||||||
|
|
||||||
extern status_t http_connect(struct http_cnx *cnx, struct sockaddr_in *sin);
|
|
||||||
extern status_t http_close(struct http_cnx *cnx);
|
|
||||||
|
|
||||||
extern status_t http_get(struct http_cnx *cnx, const char *url);
|
|
||||||
//extern status_t http_post(struct http_cnx *cnx, const char *url);
|
|
||||||
/* read the actual data in the buffer */
|
|
||||||
//extern status_t http_fetch_data(struct http_cnx *cnx);
|
|
||||||
|
|
||||||
#endif /* _HTTP_CNX_H */
|
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
#ifndef _LISTS2_H
|
#ifndef _LISTS2_H
|
||||||
#define _LISTS2_H
|
#define _LISTS2_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef int (*sll_compare_func)(const void *item, void *id);
|
typedef int (*sll_compare_func)(const void *item, void *id);
|
||||||
|
|
||||||
extern void *sll_find(long nextoff, void *head, sll_compare_func func, void *id);
|
extern void *sll_find(long nextoff, void *head, sll_compare_func func, void *id);
|
||||||
@@ -27,4 +31,8 @@ extern void *sll_next(long nextoff, void *item);
|
|||||||
#define SLL_DEQUEUE(_head,_nextp) (typeof(_head))sll_dequeue_tail(offsetof(typeof(*_head),_nextp), (void **)&(_head))
|
#define SLL_DEQUEUE(_head,_nextp) (typeof(_head))sll_dequeue_tail(offsetof(typeof(*_head),_nextp), (void **)&(_head))
|
||||||
#define SLL_REMOVE(_head,_nextp,_item) sll_remove(offsetof(typeof(*_head),_nextp), (void **)&(_head), _item)
|
#define SLL_REMOVE(_head,_nextp,_item) sll_remove(offsetof(typeof(*_head),_nextp), (void **)&(_head), _item)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _LISTS2_H */
|
#endif /* _LISTS2_H */
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
#ifndef _SETTINGS_H
|
#ifndef _SETTINGS_H
|
||||||
#define _SETTINGS_H
|
#define _SETTINGS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* settings */
|
/* settings */
|
||||||
extern char google_server[20];
|
extern char google_server[20];
|
||||||
extern int google_server_port;
|
extern int google_server_port;
|
||||||
@@ -14,4 +18,8 @@ extern bool sync_unlink_queries;
|
|||||||
|
|
||||||
extern status_t load_settings(void);
|
extern status_t load_settings(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _SETTINGS_H */
|
#endif /* _SETTINGS_H */
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
#ifndef _STRING_UTILS_H
|
#ifndef _STRING_UTILS_H
|
||||||
#define _STRING_UTILS_H
|
#define _STRING_UTILS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* converts a string to a format suitable for use in urls
|
/* converts a string to a format suitable for use in urls
|
||||||
* ex: "foo bar+" -> "foo+bar%2D"
|
* ex: "foo bar+" -> "foo+bar%2D"
|
||||||
* caller must free() result
|
* caller must free() result
|
||||||
@@ -17,4 +21,8 @@ extern char *urlify_string(const char *str);
|
|||||||
*/
|
*/
|
||||||
extern char *unentitify_string(const char *str);
|
extern char *unentitify_string(const char *str);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _STRING_UTILS_H */
|
#endif /* _STRING_UTILS_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user