summaryrefslogtreecommitdiff
path: root/src/imlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/imlib.c')
-rw-r--r--src/imlib.c307
1 files changed, 67 insertions, 240 deletions
diff --git a/src/imlib.c b/src/imlib.c
index 89271bf..dcf3c5c 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -1,6 +1,7 @@
/* imlib.c
Copyright (C) 1999-2003 Tom Gilbert.
+Copyright (C) 2010-2011 Daniel Friesel.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
@@ -33,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <curl/curl.h>
Display *disp = NULL;
Visual *vis = NULL;
@@ -231,8 +233,16 @@ int feh_load_image(Imlib_Image * im, feh_file * file)
return(1);
}
+#ifdef HAVE_LIBCURL
+
char *feh_http_load_image(char *url)
{
+ CURL *curl;
+ CURLcode res;
+ char *sfn;
+ FILE *sfp;
+ int fd = -1;
+ char *ebuff;
char *tmpname;
char *basename;
char *path = NULL;
@@ -248,252 +258,64 @@ char *feh_http_load_image(char *url)
basename = strrchr(url, '/') + 1;
tmpname = feh_unique_filename(path, basename);
- if (opt.builtin_http) {
- /* state for HTTP header parser */
-#define SAW_NONE 1
-#define SAW_ONE_CM 2
-#define SAW_ONE_CJ 3
-#define SAW_TWO_CM 4
-#define IN_BODY 5
-
-#define OUR_BUF_SIZE 1024
-#define EOL "\015\012"
-
- int sockno = 0;
- int size;
- int body = SAW_NONE;
- struct addrinfo hints;
- struct addrinfo *result, *rp;
- char *hostname;
- char *get_string;
- char *host_string;
- char *query_string;
- char *get_url;
- static char buf[OUR_BUF_SIZE];
- char ua_string[] = "User-Agent: feh image viewer";
- char accept_string[] = "Accept: image/*";
- FILE *fp;
-
- D(("using builtin http collection\n"));
- fp = fopen(tmpname, "w");
- if (!fp) {
- weprintf("couldn't write to file %s:", tmpname);
- free(tmpname);
- return(NULL);
- }
-
- hostname = feh_strip_hostname(url);
- if (!hostname) {
- weprintf("couldn't work out hostname from %s:", url);
- fclose(fp);
- unlink(tmpname);
- free(tmpname);
- return(NULL);
- }
-
- D(("trying hostname %s\n", hostname));
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_NUMERICSERV;
- hints.ai_protocol = 0;
- if (getaddrinfo(hostname, "80", &hints, &result) != 0) {
- weprintf("error resolving host %s:", hostname);
- fclose(fp);
- unlink(tmpname);
- free(hostname);
- free(tmpname);
- return(NULL);
- }
- for (rp = result; rp != NULL; rp = rp->ai_next) {
- sockno = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if (sockno == -1) {
- continue;
- }
- if (connect(sockno, rp->ai_addr, rp->ai_addrlen) != -1) {
- break;
- }
- close(sockno);
- }
- if (rp == NULL) {
- weprintf("error connecting socket:");
- freeaddrinfo(result);
- fclose(fp);
- unlink(tmpname);
- free(tmpname);
- free(hostname);
- return(NULL);
- }
- freeaddrinfo(result);
-
- get_url = strchr(url, '/') + 2;
- get_url = strchr(get_url, '/');
-
- get_string = estrjoin(" ", "GET", get_url, "HTTP/1.0", NULL);
- host_string = estrjoin(" ", "Host:", hostname, NULL);
- query_string = estrjoin(EOL, get_string, host_string, accept_string, ua_string, "", "", NULL);
- /* At this point query_string looks something like
- **
- ** GET /dir/foo.jpg?123456 HTTP/1.0^M^J
- ** Host: www.example.com^M^J
- ** Accept: image/ *^M^J
- ** User-Agent: feh image viewer^M^J
- ** ^M^J
- **
- ** Host: is required by HTTP/1.1 and very important for some sites,
- ** even with HTTP/1.0
- **
- ** -- BEG
- */
- if ((send(sockno, query_string, strlen(query_string), 0)) == -1) {
- free(get_string);
- free(host_string);
- free(query_string);
- free(tmpname);
- free(hostname);
- weprintf("error sending over socket:");
- return(NULL);
- }
- free(get_string);
- free(host_string);
- free(query_string);
- free(hostname);
-
- while ((size = read(sockno, &buf, OUR_BUF_SIZE))) {
- if (body == IN_BODY) {
- fwrite(buf, 1, size, fp);
- } else {
- int i;
-
- for (i = 0; i < size; i++) {
- /* We are looking for ^M^J^M^J, but will accept
- ** ^J^J from broken servers. Stray ^Ms will be
- ** ignored.
- **
- ** TODO:
- ** Checking the headers for a
- ** Content-Type: image/ *
- ** header would help detect problems with results.
- ** Maybe look at the response code too? But there is
- ** no fundamental reason why a 4xx or 5xx response
- ** could not return an image, it is just the 3xx
- ** series we need to worry about.
- **
- ** Also, grabbing the size from the Content-Length
- ** header and killing the connection after that
- ** many bytes where read would speed up closing the
- ** socket.
- ** -- BEG
- */
-
- switch (body) {
-
- case IN_BODY:
- fwrite(buf + i, 1, size - i, fp);
- i = size;
- break;
-
- case SAW_ONE_CM:
- if (buf[i] == '\012') {
- body = SAW_ONE_CJ;
- } else {
- body = SAW_NONE;
- }
- break;
-
- case SAW_ONE_CJ:
- if (buf[i] == '\015') {
- body = SAW_TWO_CM;
- } else {
- if (buf[i] == '\012') {
- body = IN_BODY;
- } else {
- body = SAW_NONE;
- }
- }
- break;
-
- case SAW_TWO_CM:
- if (buf[i] == '\012') {
- body = IN_BODY;
- } else {
- body = SAW_NONE;
- }
- break;
-
- case SAW_NONE:
- if (buf[i] == '\015') {
- body = SAW_ONE_CM;
- } else {
- if (buf[i] == '\012') {
- body = SAW_ONE_CJ;
- }
- }
- break;
-
- } /* switch */
- } /* for i */
+ curl = curl_easy_init();
+ if (!curl) {
+ weprintf("open url: libcurl initialization failure");
+ return NULL;
+ }
+
+ sfn = estrjoin("_", tmpname, "XXXXXX", NULL);
+ free(tmpname);
+ fd = mkstemp(sfn);
+ if (fd != -1) {
+ sfp = fdopen(fd, "w+");
+ if (sfp != NULL) {
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, sfp);
+ ebuff = emalloc(CURL_ERROR_SIZE);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, ebuff);
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
+
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ if (res != CURLE_OK) {
+ weprintf("open url: %s", ebuff);
+ unlink(sfn);
+ close(fd);
+ free(sfn);
+ sfn = NULL;
}
- } /* while read */
- close(sockno);
- fclose(fp);
- } else {
- int pid;
- int status;
-
- if ((pid = fork()) < 0) {
- weprintf("open url: fork failed:");
- free(tmpname);
- return(NULL);
- } else if (pid == 0) {
- char *quiet = NULL;
- if (!opt.verbose)
- quiet = estrdup("-q");
-
- execlp("wget", "wget", "--cache=off", "-O", tmpname, url, quiet, NULL);
- eprintf("url: Is 'wget' installed? Failed to exec wget:");
+ free(ebuff);
+ fclose(sfp);
+ return sfn;
} else {
- waitpid(pid, &status, 0);
-
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- weprintf("url: wget failed to load URL %s\n", url);
- unlink(tmpname);
- free(tmpname);
- return(NULL);
- }
+ weprintf("open url: fdopen failed:");
+ free(sfn);
+ unlink(sfn);
+ close(fd);
}
+ } else {
+ weprintf("open url: mkstemp failed:");
+ free(sfn);
}
-
- return(tmpname);
+ curl_easy_cleanup(curl);
+ return NULL;
}
-char *feh_strip_hostname(char *url)
-{
- char *ret;
- char *start;
- char *finish;
- int len;
-
- start = strchr(url, '/');
- if (!start)
- return(NULL);
-
- start += 2;
-
- finish = strchr(start, '/');
- if (!finish)
- return(NULL);
+#else /* HAVE_LIBCURL */
- len = finish - start;
-
- ret = emalloc(len + 1);
- strncpy(ret, start, len);
- ret[len] = '\0';
- return(ret);
+char *feh_http_load_image(char *url)
+{
+ weprintf(
+ "Cannot load image %s\n Please recompile with libcurl support",
+ url
+ );
+ return NULL;
}
+#endif /* HAVE_LIBCURL */
+
void feh_draw_zoom(winwidget w)
{
static Imlib_Font fn = NULL;
@@ -683,7 +505,7 @@ void feh_draw_info(winwidget w)
return;
}
-char *build_caption_filename(feh_file * file)
+char *build_caption_filename(feh_file * file, short create_dir)
{
char *caption_filename;
char *s, *dir, *caption_dir;
@@ -702,6 +524,8 @@ char *build_caption_filename(feh_file * file)
D(("dir %s, cp %s, cdir %s\n", dir, opt.caption_path, caption_dir))
if (stat(caption_dir, &cdir_stat) == -1) {
+ if (!create_dir)
+ return NULL;
if (mkdir(caption_dir, 0755) == -1)
eprintf("Failed to create caption directory %s:", caption_dir);
} else if (!S_ISDIR(cdir_stat.st_mode))
@@ -737,9 +561,12 @@ void feh_draw_caption(winwidget w)
if (!file->caption) {
char *caption_filename;
- caption_filename = build_caption_filename(file);
- /* read caption from file */
- file->caption = ereadfile(caption_filename);
+ caption_filename = build_caption_filename(file, 0);
+ if (caption_filename)
+ /* read caption from file */
+ file->caption = ereadfile(caption_filename);
+ else
+ file->caption = estrdup("");
free(caption_filename);
}