summaryrefslogtreecommitdiff
path: root/navit/file.c
diff options
context:
space:
mode:
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>2010-12-21 17:50:56 +0000
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>2010-12-21 17:50:56 +0000
commit267af2e52befc9dfad05d3b40ad136d07d4883d8 (patch)
tree1685ae4a9e3953b035c2ec935c6db2a807b38fb5 /navit/file.c
parent69c49c4ab0e7d02d8930d8a5c3412a02f11209f8 (diff)
downloadnavit-267af2e52befc9dfad05d3b40ad136d07d4883d8.tar.gz
Add:gui_internal:Initial work on map downloader
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@3808 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'navit/file.c')
-rw-r--r--navit/file.c130
1 files changed, 117 insertions, 13 deletions
diff --git a/navit/file.c b/navit/file.c
index 95f075b91..cb13ae530 100644
--- a/navit/file.c
+++ b/navit/file.c
@@ -35,6 +35,12 @@
#include "file.h"
#include "atom.h"
#include "config.h"
+#ifdef HAVE_SOCKET
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+
+extern char *version;
#ifdef HAVE_LIBCRYPTO
#include <openssl/sha.h>
@@ -69,6 +75,66 @@ struct file_cache_id {
int method;
} __attribute__ ((packed));
+#ifdef HAVE_SOCKET
+static int
+file_socket_connect(char *host, char *service)
+{
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+ int ret,fd,s;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = 0;
+ s = getaddrinfo(host, service, &hints, &result);
+ if (s != 0) {
+ dbg(0,"getaddrinfo error %s\n",gai_strerror(s));
+ return -1;
+ }
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (fd != -1) {
+ if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
+ break;
+ close(fd);
+ fd=-1;
+ }
+ }
+ freeaddrinfo(result);
+ return fd;
+}
+#endif
+
+static int
+file_http_request(struct file *file, char *host, char *path)
+{
+ char *request=g_strdup_printf("GET %s HTTP/1.0\r\nUser-Agent: navit %s\r\nHost: %s\r\n\r\n",path,version,host);
+ write(file->fd, request, strlen(request));
+ file->requests++;
+}
+
+static char *
+file_http_header_end(char *str, int len)
+{
+ int i;
+ for (i=0; i+1<len; i+=2) {
+ if (str[i+1]=='\n') {
+ if (str[i]=='\n')
+ return str+i+2;
+ else if (str[i]=='\r' && i+3<len && str[i+2]=='\r' && str[i+3]=='\n')
+ return str+i+4;
+ --i;
+ } else if (str[i+1]=='\r') {
+ if (i+4<len && str[i+2]=='\n' && str[i+3]=='\r' && str[i+4]=='\n')
+ return str+i+5;
+ --i;
+ }
+ }
+ return NULL;
+}
+
struct file *
file_create(char *name, enum file_flags flags)
{
@@ -84,12 +150,21 @@ file_create(char *name, enum file_flags flags)
file->name = g_strdup(name);
if (flags & file_flag_url) {
-#ifndef HAVE_API_WIN32_BASE
- char *cmd=g_strdup_printf("curl '%s'",name);
- file->stdfile=popen(cmd,"r");
- file->fd=fileno(file->stdfile);
- file->special=1;
- g_free(cmd);
+#ifdef HAVE_SOCKET
+ if (!strncmp(name,"http://",7)) {
+ char *host=g_strdup(name+7);
+ char *port=strchr(host,':');
+ char *path=strchr(name+7,'/');
+ if (path)
+ host[path-name-7]='\0';
+ if (port)
+ *port++='\0';
+ dbg(0,"host=%s path=%s\n",host,path);
+ file->fd=file_socket_connect(host,port?port:"80");
+ file_http_request(file,host,path);
+ file->special=1;
+ g_free(host);
+ }
#endif
} else {
file->fd=open(name, open_flags);
@@ -213,14 +288,47 @@ file_data_read(struct file *file, long long offset, int size)
}
+static void
+file_process_headers(struct file *file, char *headers)
+{
+ char *tok;
+ char *cl="Content-Length: ";
+ while (tok=strtok(headers, "\r\n")) {
+ if (!strncasecmp(tok,cl,strlen(cl))) {
+ file->size=atoll(tok+strlen(cl));
+ }
+ headers=NULL;
+ }
+}
+
unsigned char *
file_data_read_special(struct file *file, int size, int *size_ret)
{
- void *ret;
+ char *ret,*hdr;
+ int rets=0,rd;
if (!file->special)
return NULL;
ret=g_malloc(size);
- *size_ret=read(file->fd, ret, size);
+ while (size > 0) {
+ rd=read(file->fd, ret+rets, size);
+ if (rd <= 0)
+ break;
+ rets+=rd;
+ size-=rd;
+ if (file->requests) {
+ if (hdr=file_http_header_end(ret, rets)) {
+ hdr[-1]='\0';
+ file_process_headers(file, ret);
+ rets-=hdr-ret;
+ memmove(ret, hdr, rets);
+ file->requests--;
+ } else {
+ rets=0;
+ break;
+ }
+ }
+ }
+ *size_ret=rets;
return ret;
}
@@ -509,13 +617,9 @@ file_destroy(struct file *f)
{
switch (f->special) {
case 0:
- close(f->fd);
- break;
-#ifndef HAVE_API_WIN32_BASE
case 1:
- pclose(f->stdfile);
+ close(f->fd);
break;
-#endif
}
if ( f->begin != NULL )