Skip to content
This repository
Newer
Older
100644 161 lines (137 sloc) 4.716 kb
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
1 #include <string.h>
4497f346 » Flast
2011-09-15 Refactoring.
2 #include <stdbool.h>
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
3 #include <stdlib.h>
4 #include <ctype.h>
5
6 #include <glib.h>
7 #include <gdk-pixbuf/gdk-pixbuf.h>
8
9 #ifdef _WIN32
10 # include <windows.h>
11 #endif
12
a573bd9a » Flast
2011-09-14 Add memfile_from_url function for getting resources from URL using CURL.
13 #include <curl/curl.h>
14
15 #include "memfile.h"
16 #include "from_url.h"
17
18 #define REQUEST_TIMEOUT (5)
19
20 CURLcode
21 memfile_from_url(const memfile_from_url_info info) {
22 CURL* curl = curl_easy_init();
23 if (!curl) return CURLE_FAILED_INIT;
24
4497f346 » Flast
2011-09-15 Refactoring.
25 MEMFILE* body = memfopen();
a4d93bad » yibe
2011-10-31 Ignore icons with non-200 response codes (as Growl for Windows does)
26 long code = 0;
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
27 double csize = -1;
28 char* ctype = NULL;
a573bd9a » Flast
2011-09-14 Add memfile_from_url function for getting resources from URL using CURL.
29
30 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
31 curl_easy_setopt(curl, CURLOPT_URL, info.url);
32 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, REQUEST_TIMEOUT);
33 curl_easy_setopt(curl, CURLOPT_TIMEOUT, REQUEST_TIMEOUT);
34 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, info.body_writer);
4497f346 » Flast
2011-09-15 Refactoring.
35 curl_easy_setopt(curl, CURLOPT_WRITEDATA, body);
a573bd9a » Flast
2011-09-14 Add memfile_from_url function for getting resources from URL using CURL.
36 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
37 const CURLcode res = curl_easy_perform(curl);
4497f346 » Flast
2011-09-15 Refactoring.
38
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
39 if (res == CURLE_OK) {
a4d93bad » yibe
2011-10-31 Ignore icons with non-200 response codes (as Growl for Windows does)
40 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
41
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
42 if (curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &csize) != CURLE_OK)
43 csize = -1;
44 curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ctype);
45 }
46
a4d93bad » yibe
2011-10-31 Ignore icons with non-200 response codes (as Growl for Windows does)
47 if (info.code) *info.code = code;
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
48 if (info.csize) *info.csize = csize;
49 if (info.ctype) *info.ctype = ctype ? strdup(ctype) : NULL;
50 if (info.body) *info.body = memfrelease(&body);
4497f346 » Flast
2011-09-15 Refactoring.
51 memfclose(body);
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
52
53 curl_easy_cleanup(curl);
4497f346 » Flast
2011-09-15 Refactoring.
54
a573bd9a » Flast
2011-09-14 Add memfile_from_url function for getting resources from URL using CURL.
55 return res;
56 }
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
57
4497f346 » Flast
2011-09-15 Refactoring.
58 // Some error happened only if returns true.
59 static bool
60 gerror_set_or_free(GError** dest, GError* val) {
61 if (!val) return false;
62
63 if (dest) *dest = val;
64 else g_error_free(val);
65 return true;
66 }
67
68 // FIXME: More refactor this function.
69 static GdkPixbuf*
70 pixbuf_from_url_impl(const char* ctype, const MEMFILE* raw, GError** error) {
71 GdkPixbuf* pixbuf = NULL;
72 #ifdef _WIN32
73 if (ctype && (!strcmp(ctype, "image/jpeg") || !strcmp(ctype, "image/gif"))) {
74 char temp_path[MAX_PATH];
75 char temp_filename[MAX_PATH];
76 GetTempPath(sizeof(temp_path), temp_path);
77 GetTempFileName(temp_path, "growl-for-linux-", 0, temp_filename);
78 FILE* const fp = fopen(temp_filename, "wb");
79 if (fp) {
80 fwrite(memfdata(raw), memfsize(raw), 1, fp);
81 fclose(fp);
82 }
83 pixbuf = gdk_pixbuf_new_from_file(temp_filename, NULL);
84 DeleteFile(temp_filename);
85 } else
86 #endif
87 {
88 GError* _error = NULL;
89 GdkPixbufLoader* const loader =
90 ctype ? gdk_pixbuf_loader_new_with_mime_type(ctype, &_error)
91 : gdk_pixbuf_loader_new();
92 if (!gerror_set_or_free(error, _error)) {
93 if (gdk_pixbuf_loader_write(loader, (const guchar*) memfcdata(raw), memfsize(raw), &_error))
94 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
95 else
96 gerror_set_or_free(error, _error);
97
98 gdk_pixbuf_loader_close(loader, NULL);
99 }
100 }
101 return pixbuf;
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
102 }
103
104 GdkPixbuf*
105 pixbuf_from_url(const char* url, GError** error) {
72c18320 » Flast
2011-09-30 Fixes null pointer deref.
106 if (!url) return NULL;
34da4b16 »
2012-03-13 support x-growl-resource://[identifier].
107 if (!strncmp(url, "x-growl-resource://", 19)) {
108 const gchar* const confdir = (const gchar*) g_get_user_config_dir();
109 gchar* const resourcedir = g_build_path(G_DIR_SEPARATOR_S, confdir, "gol", "resource", NULL);
110 const gchar* const newurl = g_build_filename(resourcedir, url + 19, NULL);
111 GdkPixbuf* pixbuf = pixbuf_from_url_as_file(newurl, error);
112 g_free(resourcedir);
113 return pixbuf;
114 }
72c18320 » Flast
2011-09-30 Fixes null pointer deref.
115
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
116 MEMFILE* mbody;
a4d93bad » yibe
2011-10-31 Ignore icons with non-200 response codes (as Growl for Windows does)
117 long code;
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
118 double csize;
119 char* ctype;
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
120 const CURLcode res = memfile_from_url((memfile_from_url_info){
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
121 .url = url,
122 .body = &mbody,
123 .body_writer = memfwrite,
a4d93bad » yibe
2011-10-31 Ignore icons with non-200 response codes (as Growl for Windows does)
124 .code = &code,
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
125 .csize = &csize,
126 .ctype = &ctype,
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
127 });
a4d93bad » yibe
2011-10-31 Ignore icons with non-200 response codes (as Growl for Windows does)
128 if (res != CURLE_OK || code != 200 || !mbody) {
4497f346 » Flast
2011-09-15 Refactoring.
129 if (error) *error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
130 free(ctype);
4497f346 » Flast
2011-09-15 Refactoring.
131 memfclose(mbody);
132 return NULL;
133 }
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
134
34391e3d » yibe
2011-10-31 Leave HTTP response header parsing up to libcurl
135 memfresize(mbody, csize >= 0 ? (size_t) csize : memfsize(mbody));
0e75481e » Flast
2011-09-14 Refactoring.
136
4497f346 » Flast
2011-09-15 Refactoring.
137 GdkPixbuf* const pixbuf = pixbuf_from_url_impl(ctype, mbody, error);
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
138
4497f346 » Flast
2011-09-15 Refactoring.
139 free(ctype);
140 memfclose(mbody);
7b1b29b9 » Flast
2011-09-14 Add pixbuf_from_url function.
141
142 return pixbuf;
143 }
144
62899613 » Flast
2011-09-18 Aggregate pixbuf creator.
145 GdkPixbuf*
146 pixbuf_from_url_as_file(const char* url, GError** error) {
34da4b16 »
2012-03-13 support x-growl-resource://[identifier].
147 if (!url) return NULL;
148 gchar* newurl;
149 if (!strncmp(url, "x-growl-resource://", 19)) {
150 const gchar* const confdir = (const gchar*) g_get_user_config_dir();
151 gchar* const resourcedir = g_build_path(G_DIR_SEPARATOR_S, confdir, "gol", "resource", NULL);
152 newurl = g_build_filename(resourcedir, url + 19, NULL);
153 g_free(resourcedir);
154 } else
155 newurl = g_filename_from_uri(url, NULL, NULL);
62899613 » Flast
2011-09-18 Aggregate pixbuf creator.
156 GError* _error = NULL;
157 GdkPixbuf* const pixbuf = gdk_pixbuf_new_from_file(newurl ? newurl : url, &_error);
158 if (!pixbuf) gerror_set_or_free(error, _error);
159 g_free(newurl);
160 return pixbuf;
161 }
162
Something went wrong with that request. Please try again.