summaryrefslogtreecommitdiff
path: root/plugins/vfs_curl
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-10-25 21:16:35 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-10-25 21:16:35 +0100
commit1205684e301f998f26a1dc8828e1f628ef0160f6 (patch)
tree3347a4cfab6edd8432c91c4f33d96564078e887c /plugins/vfs_curl
parent3e5687aef0a52ee3e500741f4623145a351d41dd (diff)
added vfs filetype detection based on content-type
Diffstat (limited to 'plugins/vfs_curl')
-rw-r--r--plugins/vfs_curl/vfs_curl.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index f257600b..0a449824 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -52,6 +52,8 @@ typedef struct {
int32_t skipbytes;
intptr_t tid; // thread id which does http requests
intptr_t mutex;
+ int gotheader;
+ char *content_type;
uint8_t status;
} HTTP_FILE;
@@ -59,7 +61,6 @@ static DB_vfs_t plugin;
static char http_err[CURL_ERROR_SIZE];
-
static size_t
http_curl_write (void *ptr, size_t size, size_t nmemb, void *stream) {
// trace ("http_curl_write %d bytes\n", size * nmemb);
@@ -109,7 +110,7 @@ http_curl_write (void *ptr, size_t size, size_t nmemb, void *stream) {
}
static size_t
-http_size_request_handler (void *ptr, size_t size, size_t nmemb, void *stream) {
+http_size_header_handler (void *ptr, size_t size, size_t nmemb, void *stream) {
assert (stream);
HTTP_FILE *fp = (HTTP_FILE *)stream;
// don't copy/allocate mem, just grep for "Content-Length: "
@@ -122,6 +123,28 @@ http_size_request_handler (void *ptr, size_t size, size_t nmemb, void *stream) {
return size * nmemb;
}
+static size_t
+http_content_header_handler (void *ptr, size_t size, size_t nmemb, void *stream) {
+ assert (stream);
+ HTTP_FILE *fp = (HTTP_FILE *)stream;
+ const char c_type_str[] ="Content-Type: ";
+ const char *cl = strstr (ptr, c_type_str);
+ if (cl) {
+ cl += sizeof (c_type_str)-1;
+ const uint8_t *p = (const uint8_t *)cl;
+ while (*p >= 0x20) {
+ p++;
+ }
+ int len = (const char *)p-cl;
+ char str[len+1];
+ strncpy (str, cl, len);
+ str[len] = 0;
+ fp->content_type = strdup (str);
+ }
+ fp->gotheader = 1;
+ return size * nmemb;
+}
+
static void
http_thread_func (uintptr_t ctx) {
HTTP_FILE *fp = (HTTP_FILE *)ctx;
@@ -136,15 +159,12 @@ http_thread_func (uintptr_t ctx) {
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10);
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, http_size_request_handler);
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, http_size_header_handler);
curl_easy_setopt (curl, CURLOPT_HEADERDATA, ctx);
status = curl_easy_perform(curl);
if (status != 0) {
fp->length = -1;
trace ("vfs_curl: curl_easy_perform failed while getting filesize, status %d\n", status);
-// fp->status = STATUS_FINISHED;
-// fp->tid = 0;
-// return;
}
fp->status = STATUS_STARTING;
@@ -157,6 +177,8 @@ http_thread_func (uintptr_t ctx) {
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, http_err);
curl_easy_setopt (curl, CURLOPT_BUFFERSIZE, BUFFER_SIZE/2);
curl_easy_setopt (curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, http_content_header_handler);
+ curl_easy_setopt (curl, CURLOPT_HEADERDATA, ctx);
// enable up to 10 redirects
curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 10);
@@ -216,7 +238,12 @@ http_close (DB_FILE *stream) {
deadbeef->thread_join (fp->tid);
deadbeef->mutex_free (fp->mutex);
}
- free (fp->url);
+ if (fp->content_type) {
+ free (fp->content_type);
+ }
+ if (fp->url) {
+ free (fp->url);
+ }
free (stream);
}
@@ -372,6 +399,20 @@ http_getlength (DB_FILE *stream) {
return fp->length;
}
+static const char *
+http_get_content_type (DB_FILE *stream) {
+ trace ("http_get_content_type\n");
+ assert (stream);
+ HTTP_FILE *fp = (HTTP_FILE *)stream;
+ if (!fp->tid) {
+ http_start_streamer (fp);
+ }
+ while (fp->status != STATUS_FINISHED && fp->status != STATUS_ABORTED && !fp->gotheader) {
+ usleep (3000);
+ }
+ return fp->content_type;
+}
+
static const char *scheme_names[] = { "http://", "ftp://", NULL };
// standard stdio vfs
@@ -392,6 +433,7 @@ static DB_vfs_t plugin = {
.tell = http_tell,
.rewind = http_rewind,
.getlength = http_getlength,
+ .get_content_type = http_get_content_type,
.scheme_names = scheme_names,
.streaming = 1
};