From 854459cb11d29093bf8dc6e98c3cfb6ba208ec6c Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Tue, 31 Oct 2017 13:23:59 +0100 Subject: Initial commit --- .gitignore | 2 ++ Makefile | 3 +++ README.rst | 15 +++++++++++++++ curlfilter.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.rst create mode 100644 curlfilter.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a7d3377 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.sw? +curlfilter.so diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4e1fac1 --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ +curlfilter.so: curlfilter.c + gcc -Wl,-init=init -o $@ -std=c11 -shared -fPIC -ldl -lpcre $< + diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..9ef00ce --- /dev/null +++ b/README.rst @@ -0,0 +1,15 @@ +curlfilter +========== + +Filter URLs passed to libcurl’s easy interface by regular expression. Can be +used to implement per-application ad-blocking. + +Compile with:: + + make + +For Spotify run:: + + export CURLFILTER_PATTERN="spclient.wg.spotify.com/ad[-s]" + LD_PRELOAD=/path/to/curlfilter.so spotify + diff --git a/curlfilter.c b/curlfilter.c new file mode 100644 index 0000000..5984edc --- /dev/null +++ b/curlfilter.c @@ -0,0 +1,46 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +/* the function is actually a macro, which prevents us from redefining it + * properly */ +#undef curl_easy_setopt + +typedef CURLcode (*orig_curl_easy_setopt) (CURL *handle, CURLoption option, ...); + +static pcre *re = NULL; + +CURL_EXTERN CURLcode curl_easy_setopt (CURL *handle, CURLoption option, ...) { + va_list args; + va_start (args, option); + void *parameter = va_arg (args, void *); + + if (re != NULL && option == CURLOPT_URL) { + int matches[3]; + if (pcre_exec (re, NULL, parameter, strlen (parameter), 0, 0, matches, 3) >= 0) { + /* not allowed */ + return CURLE_URL_MALFORMAT; + } + } + + orig_curl_easy_setopt orig_setopt; + orig_setopt = (orig_curl_easy_setopt) dlsym (RTLD_NEXT, "curl_easy_setopt"); + return orig_setopt (handle, option, parameter); +} + +void init () { + const char * const pattern = getenv ("CURLFILTER_PATTERN"); + const char *errmsg = NULL; + int errpos; + if (pattern == NULL) { + fprintf (stderr, "Environment variable CURLFILTER_PATTERN is not set\n"); + return; + } + if ((re = pcre_compile (pattern, 0, &errmsg, &errpos, NULL)) == NULL) { + fprintf (stderr, "Cannot compile regex %s: %s\n", pattern, errmsg); + return; + } +} -- cgit v1.2.3