worldi
wirrköpfiger Philosoph
Hi,
ich habe mir gestern 'ne shared lib gebastelt, mit der sich Operas User-Agent beliebig setzen lässt. Das Ding ist nicht gerade perfekt und sicherlich ein klein wenig bröselig, funktioniert aber tadellos (zumindest auf meiner Kiste).
-- w.
ich habe mir gestern 'ne shared lib gebastelt, mit der sich Operas User-Agent beliebig setzen lässt. Das Ding ist nicht gerade perfekt und sicherlich ein klein wenig bröselig, funktioniert aber tadellos (zumindest auf meiner Kiste).
-- w.
Code:
/* customua4opera.c
Description:
This is a shared library that - when preloaded - set Opera's "User-Agent"
string to the value of a specific environment variable.
Compilation & Linkage:
% $CC -c -std=c99 -O3 -Wall -Werror -Wextra -pedantic-errors -fPIC -o customua4opera.o customua4opera.c
% $CC -shared -o customua4opera.so customua4opera.o
Usage:
% export OPERA_CUSTOM_UA="Googlebot/2.1 (+http://www.google.com/bot.html)"
% LD_PRELOAD=./customua4opera.so /path/to/opera
Notes:
This code has been tested with Opera 11.61 on FreeBSD 8.2-RELEASE (amd64).
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char* env_ua = "OPERA_CUSTOM_UA";
static const char* part1 = "Opera/9.80 (%s; U; %s)";
static const char* part2 = " %s/%s";
static const char* part2_arg1 = "Presto";
static const char* part3 = " Version/%s";
static char* user_agent = NULL;
static int (*_snprintf) (char*, size_t, const char*, ...) = NULL;
// In order to assemble its User-Agent Opera calls snprintf(3) three times.
// This function identifies each of these three calls. It returns an empty
// string for the first two. For the last call it returns the value of the
// environment variable OPERA_CUSTOM_UA (or "unknown" in case it is unset).
int
snprintf(char *str, size_t size, const char* format, ...)
{
if (!_snprintf) {
_snprintf = (int(*)(char*, size_t, const char*, ...)) dlfunc(RTLD_NEXT, "snprintf");
}
if (!strcmp(format, part1)) {
return _snprintf(str, size, "%s", "");
}
if (!strcmp(format, part2)) {
va_list tmp;
va_start(tmp, format);
char* arg1 = va_arg(tmp, char*);
if (!strcmp(arg1, part2_arg1)) {
va_end(tmp);
return _snprintf(str, size, "%s", "");
}
va_end(tmp);
}
if (!strcmp(format, part3)) {
if (!user_agent) {
user_agent = getenv(env_ua) ? getenv(env_ua) : "unknown";
}
return _snprintf(str, size, "%s", user_agent);
}
va_list ap;
va_start(ap, format);
return vsnprintf(str, size, format, ap);
}