diff options
Diffstat (limited to 'oncology/dpfhack_display/lcd4linux/.svn/text-base/plugin_kvv.c.svn-base')
| -rw-r--r-- | oncology/dpfhack_display/lcd4linux/.svn/text-base/plugin_kvv.c.svn-base | 814 |
1 files changed, 0 insertions, 814 deletions
diff --git a/oncology/dpfhack_display/lcd4linux/.svn/text-base/plugin_kvv.c.svn-base b/oncology/dpfhack_display/lcd4linux/.svn/text-base/plugin_kvv.c.svn-base deleted file mode 100644 index 2291af14..00000000 --- a/oncology/dpfhack_display/lcd4linux/.svn/text-base/plugin_kvv.c.svn-base +++ /dev/null @@ -1,814 +0,0 @@ -/* $Id$ - * $URL$ - * - * plugin kvv (karlsruher verkehrsverbund) - * - * Copyright (C) 2006 Till Harbaum <till@harbaum.org> - * Copyright (C) 2006 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> - * - * This file is part of LCD4Linux. - * - * LCD4Linux is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * LCD4Linux is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * exported functions: - * - * int plugin_init_kvv (void) - * adds various functions - * void plugin_exit_kvv (void) - * - */ - -/* define the include files you need */ -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <signal.h> - -/* network specific includes */ -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> - -/* these should always be included */ -#include "debug.h" -#include "plugin.h" -#include "cfg.h" -#include "thread.h" - -/* these can't be configured as it doesn't make sense to change them */ -#define HTTP_SERVER "www.init-ka.de" -#define HTTP_REQUEST "/webfgi/StopInfoInplace.aspx?ID=%s" -#define USER_AGENT "lcd4linux - KVV plugin (http://ssl.bulix.org/projects/lcd4linux/wiki/plugin_kvv)" - -#define DEFAULT_STATION_ID "89" /* Hauptbahnhof */ - -/* example ids: - * 89 = Hauptbahnhof - * 12_701 = Berufsakademie - */ - -/* total max values to calculate shm size */ -#define MAX_LINES 4 -#define MAX_LINE_LENGTH 8 -#define MAX_STATION_LENGTH 40 - -typedef struct { - char line[MAX_LINE_LENGTH + 1]; - char station[MAX_STATION_LENGTH + 1]; - int time; -} kvv_entry_t; - -typedef struct { - int entries, error; - kvv_entry_t entry[MAX_LINES]; -} kvv_shm_t; - -static char *station_id = NULL; -static char *proxy_name = NULL; -static int port = 80; -static pid_t pid = -1; -static int refresh = 60; -static int abbreviate = 0; - -static int initialized = 0; -static int mutex = 0; -static int shmid = -1; -static kvv_shm_t *shm = NULL; - -#define SECTION "Plugin:KVV" - -#define TIMEOUT_SHORT 1 /* wait this long for additional data */ -#define TIMEOUT_LONG 10 /* wait this long for initial data */ - -/* search an element in the result string */ -static int get_element(char *input, char *name, char **data) -{ - int skip = 0; - int len = 0; - int state = 0; /* nothing found yet */ - - /* search entire string */ - while (*input) { - - if (skip == 0) { - switch (state) { - case 0: - if (*input == '<') - state = 1; - else - state = 0; - break; - - case 1: - /* ignore white spaces */ - if (*input != ' ') { - if (strncasecmp(input, name, strlen(name)) == 0) { - state = 2; - skip = strlen(name) - 1; - } else - state = 0; - } - break; - - case 2: - if (*input == ' ') { - *data = ++input; - while (*input && (*input++ != '>')) - len++; - - return len; - } else - state = 0; - break; - } - } else if (skip) - skip--; - - input++; - } - - return -1; -} - -/* serach an attribute within an element */ -static int get_attrib(char *input, char *name, char **data) -{ - int skip = 0; - int len = 0; - int state = 0; /* nothing found */ - - /* search in this element */ - while (*input != '>') { - /* ignore white spaces */ - if (((*input != ' ') && (*input != '\t')) && (skip == 0)) { - switch (state) { - case 0: - if (strncasecmp(input, name, strlen(name)) == 0) { - state = 1; - skip = strlen(name) - 1; - } - break; - - case 1: - if (*input == '=') - state = 2; - else - state = 0; - break; - - case 2: - if (*input == '\"') { - *data = ++input; - while (*input++ != '\"') - len++; - - return len; - } else - state = 0; - - break; - } - } else if (skip) - skip--; - - input++; - } - return -1; -} - -static int http_open(char *name) -{ - struct sockaddr_in server; - struct hostent *host_info; - unsigned long addr; - int sock; - - /* create socket */ - sock = socket(PF_INET, SOCK_STREAM, 0); - if (sock < 0) { - perror("failed to create socket"); - return -1; - } - - /* Erzeuge die Socketadresse des Servers - * Sie besteht aus Typ, IP-Adresse und Portnummer */ - memset(&server, 0, sizeof(server)); - if ((addr = inet_addr(name)) != INADDR_NONE) { - memcpy((char *) &server.sin_addr, &addr, sizeof(addr)); - } else { - /* Wandle den Servernamen in eine IP-Adresse um */ - host_info = gethostbyname(name); - if (NULL == host_info) { - error("[KVV] Unknown server: %s", name); - return -1; - } - memcpy((char *) &server.sin_addr, host_info->h_addr, host_info->h_length); - } - - server.sin_family = AF_INET; - server.sin_port = htons(port); - - /* Baue die Verbindung zum Server auf */ - if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { - perror("can't connect to server"); - return -1; - } - - return sock; -} - -static void get_text(char *input, char *end, char *dest, int dlen) -{ - int state = 0; /* nothing yet, outside any element */ - int cnt = 0; - - while (*input) { - switch (state) { - case 0: - if (*input == '<') - state = 1; - else { - if (cnt < (dlen - 1)) - dest[cnt++] = *input; - } - break; - - case 1: - if (*input == '/') - state = 2; - else if (*input == '>') - state = 0; - break; - - case 2: - if (strncasecmp(input, end, strlen(end)) == 0) { - dest[cnt++] = 0; - return; - } - break; - } - - input++; - } - -} - -static void process_station_string(char *str) -{ - char *p, *q; - int last, i; - - /* some strings to replace */ - char *repl[] = { - "Hauptbahnhof", "Hbf.", - "Bahnhof", "Bhf.", - "Karlsruhe", "KA", - "Schienenersatzverkehr", "Ersatzv.", - "Marktplatz", "Marktpl.", - }; - - /* decode utf8 */ - p = q = str; - last = 0; - while (*p) { - if (last) { - *q++ = (last << 6) | (*p & 0x3f); - last = 0; - } else if ((*p & 0xe0) == 0xc0) { - last = *p & 3; - } else - *q++ = *p; - - p++; - } - *q++ = 0; - - /* erase multiple spaces and replace umlauts */ - p = q = str; - last = 1; /* no leading spaces */ - while (*p) { - if ((!last) || (*p != ' ')) { - - /* translate from latin1 to hd44780 */ - if (*p == (char) 228) /* lower a umlaut */ - *q++ = (char) 0xe1; - else if (*p == (char) 223) /* sz ligature */ - *q++ = (char) 0xe2; - else if (*p == (char) 246) /* lower o umlaut */ - *q++ = (char) 0xef; - else if (*p == (char) 252) /* lower u umlaut */ - *q++ = (char) 0xf5; - else - *q++ = *p; - } - - last = (*p == ' '); - p++; - } - *q++ = 0; - - /* replace certain (long) words with e.g. abbreviations if enabled */ - if (abbreviate) { - - for (i = 0; i < (int) (sizeof(repl) / (2 * sizeof(char *))); i++) { - if ((p = strstr(str, repl[2 * i])) != NULL) { - - /* move new string */ - memcpy(p, repl[2 * i + 1], strlen(repl[2 * i + 1])); - /* move rest of string down */ - memmove(p + strlen(repl[2 * i + 1]), - p + strlen(repl[2 * i]), strlen(str) - (p - str) - strlen(repl[2 * i]) + 1); - } - } - } -} - -static void kvv_client( __attribute__ ((unused)) - void *dummy) -{ - char ibuffer[8192]; - char obuffer[1024]; - int count, i, sock; - - char server_name[] = HTTP_SERVER; - char *connect_to; - - /* connect to proxy if given, to server otherwise */ - if ((proxy_name != NULL) && (strlen(proxy_name) != 0)) - connect_to = proxy_name; - else - connect_to = server_name; - - info("[KVV] Connecting to %s", connect_to); - - while (1) { - - sock = http_open(connect_to); - if (sock < 0) { - error("[KVV] Error accessing server/proxy: %s", strerror(errno)); - return; - } - /* create and set get request */ - if (snprintf(obuffer, sizeof(obuffer), - "GET http://%s" HTTP_REQUEST " HTTP/1.1\n" - "Host: %s\n" "User-Agent: " USER_AGENT "\n\n", server_name, station_id, - server_name) >= (int) sizeof(obuffer)) { - - info("[KVV] Warning, request has been truncated!"); - } - - info("[KVV] Sending first (GET) request ..."); - send(sock, obuffer, strlen(obuffer), 0); - - count = 0; - do { - fd_set rfds; - struct timeval tv; - - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - - tv.tv_sec = count ? TIMEOUT_SHORT : TIMEOUT_LONG; - tv.tv_usec = 0; - - i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv); - if (i < 0) { - perror("select"); - exit(1); - } - - if (i != 0) { - i = recv(sock, ibuffer + count, sizeof(ibuffer) - count - 1, 0); - count += i; - } - } - while (i > 0); - - ibuffer[count] = 0; /* terminate string */ - close(sock); - - if (!count) - info("[KVV] empty/no reply"); - - if (count > 0) { - char *input, *cookie, *name = NULL, *value = NULL; - int input_len, cookie_len, name_len, value_len; - - /* buffer to html encode value */ - char value_enc[512]; - int value_enc_len; - - /* find cookie */ - cookie_len = 0; - cookie = strstr(ibuffer, "Set-Cookie:"); - if (cookie) { - cookie += strlen("Set-Cookie:"); - - while (*cookie == ' ') - cookie++; - - while (cookie[cookie_len] != ';') - cookie_len++; - } - /* find input element */ - input_len = get_element(ibuffer, "input", &input); - - - if (input_len > 0) { - char *input_end = input; - while (*input_end != '>') - input_end++; - while (*input_end != '\"') - input_end--; - *(input_end + 1) = 0; - - name_len = get_attrib(input, "name", &name); - value_len = get_attrib(input, "value", &value); - - for (value_enc_len = 0, i = 0; i < value_len; i++) { - if (isalnum(value[i])) - value_enc[value_enc_len++] = value[i]; - else { - sprintf(value_enc + value_enc_len, "%%%02X", 0xff & value[i]); - value_enc_len += 3; - } - } - - if (cookie_len >= 0) - cookie[cookie_len] = 0; - if (name_len >= 0) - name[name_len] = 0; - if (value_len >= 0) - value[value_len] = 0; - if (value_enc_len >= 0) - value_enc[value_enc_len] = 0; - - sock = http_open(connect_to); - - /* send POST */ - if (snprintf(obuffer, sizeof(obuffer), - "POST http://%s" HTTP_REQUEST " HTTP/1.1\n" - "Host: %s\n" - "User-Agent: " USER_AGENT "\n" - "Cookie: %s\n" - "Content-Type: application/x-www-form-urlencoded\n" - "Content-Length: %d\n" - "\n%s=%s", - server_name, station_id, server_name, cookie, name_len + value_enc_len + 1, name, - value_enc) >= (int) sizeof(obuffer)) { - - info("[KVV] Warning, request has been truncated!"); - } - - info("[KVV] Sending second (POST) request ..."); - send(sock, obuffer, strlen(obuffer), 0); - - count = 0; - do { - fd_set rfds; - struct timeval tv; - - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - - tv.tv_sec = count ? TIMEOUT_SHORT : TIMEOUT_LONG; - tv.tv_usec = 0; - - i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv); - if (i > 0) { - i = recv(sock, ibuffer + count, sizeof(ibuffer) - count - 1, 0); - count += i; - } - } - while (i > 0); /* leave on select or read error */ - - ibuffer[count] = 0; - - /* printf("Result (%d):\n%s\n", count, ibuffer); */ - - /* close connection */ - close(sock); - - if (!count) - info("[KVV] empty/no reply"); - - if (count > 0) { - int last_was_stop = 0; - char *td = ibuffer; - char str[32]; - int td_len, i, overflow = 0; - - /* lock shared memory */ - mutex_lock(mutex); - - /* free allocated memory */ - shm->entries = 0; - - if (strstr(ibuffer, "Die Daten konnten nicht abgefragt werden.") != NULL) { - info("[KVV] Server returned error!"); - /* printf("%s\n", ibuffer); */ - shm->error = 1; - } else - shm->error = 0; - - /* scan through all <td> entries and search the line nums */ - do { - if ((td_len = get_element(td, "td", &td)) > 0) { - char *attr, *p; - int attr_len; - - /* time does not have a class but comes immediately after stop :-( */ - if (last_was_stop) { - td += td_len + 1; - get_text(td, "td", str, sizeof(str)); - - /* time needs special treatment */ - if (strncasecmp(str, "sofort", strlen("sofort")) == 0) - i = 0; - else { - /* skip everything that is not a number */ - p = str; - while (!isdigit(*p)) - p++; - - /* and convert remaining to number */ - i = atoi(p); - } - - /* save time */ - if (!overflow) - shm->entry[shm->entries - 1].time = i; - - last_was_stop = 0; - } - - /* linenum and stopname fields have proper classes */ - if ((attr_len = get_attrib(td, "class", &attr)) > 0) { - - if (strncasecmp(attr, "lineNum", strlen("lineNum")) == 0) { - td += td_len + 1; - get_text(td, "td", str, sizeof(str)); - - if (shm->entries < MAX_LINES) { - /* allocate a new slot */ - shm->entries++; - shm->entry[shm->entries - 1].time = -1; - memset(shm->entry[shm->entries - 1].line, 0, MAX_LINE_LENGTH + 1); - memset(shm->entry[shm->entries - 1].station, 0, MAX_STATION_LENGTH + 1); - - /* add new lines entry */ - strncpy(shm->entry[shm->entries - 1].line, str, MAX_LINE_LENGTH); - } else - overflow = 1; /* don't add further entries */ - } - - if (strncasecmp(attr, "stopname", strlen("stopname")) == 0) { - td += td_len + 1; - get_text(td, "td", str, sizeof(str)); - - - /* stopname may need further tuning */ - process_station_string(str); - - if (!overflow) - strncpy(shm->entry[shm->entries - 1].station, str, MAX_STATION_LENGTH); - - last_was_stop = 1; - } - } - } - } while (td_len >= 0); - - mutex_unlock(mutex); - } - } - } - - sleep(refresh); - } -} - -static int kvv_fork(void) -{ - if (initialized) - return 0; - - info("[KVV] creating client thread"); - - /* set this here to prevent continous retries if init fails */ - initialized = 1; - - /* create communication buffer */ - shmid = shm_create((void **) &shm, sizeof(kvv_shm_t)); - - /* catch error */ - if (shmid < 0) { - error("[KVV] Shared memory allocation failed!"); - return -1; - } - - /* attach client thread */ - mutex = mutex_create(); - pid = thread_create("plugin_kvv", kvv_client, NULL); - - if (pid < 0) { - error("[KVV] Unable to fork client: %s", strerror(errno)); - return -1; - } - - info("[KVV] forked client with pid %d", pid); - return 0; -} - -static void kvv_start(void) -{ - static int started = 0; - int val; - char *p; - - - if (started) - return; - - started = 1; - - /* parse parameter */ - if ((p = cfg_get(SECTION, "StationID", DEFAULT_STATION_ID)) != NULL) { - station_id = malloc(strlen(p) + 1); - strcpy(station_id, p); - } - info("[KVV] Using station %s", station_id); - - if ((p = cfg_get(SECTION, "Proxy", NULL)) != NULL) { - proxy_name = malloc(strlen(p) + 1); - strcpy(proxy_name, p); - info("[KVV] Using proxy \"%s\"", proxy_name); - } - - if (cfg_number(SECTION, "Port", 0, 0, 65535, &val) > 0) { - port = val; - info("[KVV] Using port %d", port); - } else { - info("[KVV] Using default port %d", port); - } - - if (cfg_number(SECTION, "Refresh", 0, 0, 65535, &val) > 0) { - refresh = val; - info("[KVV] Using %d seconds refresh interval", refresh); - } else { - info("[KVV] Using default refresh interval of %d seconds", refresh); - } - - if (cfg_number(SECTION, "Abbreviate", 0, 0, 65535, &val) > 0) { - abbreviate = val; - info("[KVV] Abbreviation enabled: %s", abbreviate ? "on" : "off"); - } else { - info("[KVV] Default abbreviation setting: %s", abbreviate ? "on" : "off"); - } - -} - -static void kvv_line(RESULT * result, RESULT * arg1) -{ - int index = (int) R2N(arg1); - - kvv_start(); - - if (kvv_fork() != 0) { - SetResult(&result, R_STRING, ""); - return; - } - - mutex_lock(mutex); - - if (index < shm->entries) { - SetResult(&result, R_STRING, shm->entry[index].line); - } else - SetResult(&result, R_STRING, ""); - - mutex_unlock(mutex); -} - -static void kvv_station(RESULT * result, RESULT * arg1) -{ - int index = (int) R2N(arg1); - - kvv_start(); - - if (kvv_fork() != 0) { - SetResult(&result, R_STRING, ""); - return; - } - - mutex_lock(mutex); - - if (shm->error && index == 0) - SetResult(&result, R_STRING, "Server Err"); - else { - if (index < shm->entries) - SetResult(&result, R_STRING, shm->entry[index].station); - else - SetResult(&result, R_STRING, ""); - } - - mutex_unlock(mutex); -} - -static void kvv_time(RESULT * result, RESULT * arg1) -{ - int index = (int) R2N(arg1); - double value = -1.0; - - kvv_start(); - - if (kvv_fork() != 0) { - SetResult(&result, R_STRING, ""); - return; - } - - mutex_lock(mutex); - - if (index < shm->entries) - value = shm->entry[index].time; - - SetResult(&result, R_NUMBER, &value); - - mutex_unlock(mutex); -} - -static void kvv_time_str(RESULT * result, RESULT * arg1) -{ - int index = (int) R2N(arg1); - - kvv_start(); - - if (kvv_fork() != 0) { - SetResult(&result, R_STRING, ""); - return; - } - - mutex_lock(mutex); - - if (index < shm->entries) { - char str[8]; - sprintf(str, "%d", shm->entry[index].time); - SetResult(&result, R_STRING, str); - } else - SetResult(&result, R_STRING, ""); - - mutex_unlock(mutex); -} - -/* plugin initialization */ -int plugin_init_kvv(void) -{ - /* register all our cool functions */ - AddFunction("kvv::line", 1, kvv_line); - AddFunction("kvv::station", 1, kvv_station); - AddFunction("kvv::time", 1, kvv_time); - AddFunction("kvv::time_str", 1, kvv_time_str); - return 0; -} - -void plugin_exit_kvv(void) -{ - /* kill client thread if it's running */ - if (initialized) { - /* kill client */ - if (pid != -1) - thread_destroy(pid); - - /* free shared mem and its mutex */ - if (shm) { - shm_destroy(shmid, shm); - mutex_destroy(mutex); - } - } - - if (station_id) - free(station_id); - if (proxy_name) - free(proxy_name); -} |
