blob: 13e70937ec6c82ea53f7f8b4d526dfe968b637c4 [file] [log] [blame]
/*
* Webif page translator
*
* Copyright (C) 2005 Felix Fietkau <nbd@openwrt.org>
*
* This program 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
* of the License, or (at your option) any later version.
*
* This program 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glob.h>
#include <ctype.h>
#ifdef NVRAM
#include <bcmnvram.h>
#endif
#define HASH_MAX 100
#define LINE_BUF 1024 /* max. buffer allocated for one line */
#define MAX_TR 32 /* max. translations done on one line */
#define TR_START "@TR<<"
#define TR_END ">>"
struct lstr {
char *name;
char *value;
struct lstr *next;
};
typedef struct lstr lstr;
static lstr *ltable[HASH_MAX];
static char buf[LINE_BUF], buf2[LINE_BUF];
/* djb2 hash function */
static inline unsigned long hash(char *str)
{
unsigned long hash = 5381;
int c;
while ((c = *str++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
static inline char *translate_lookup(char *str)
{
char *name, *def, *p, *res = NULL;
lstr *i;
int h;
def = name = str;
if (((p = strchr(str, '|')) != NULL)
|| ((p = strchr(str, '#')) != NULL)) {
def = p + 1;
*p = 0;
}
h = hash(name) % HASH_MAX;
i = ltable[h];
while ((res == NULL) && (i != NULL)) {
if (strcmp(name, i->name) == 0)
res = i->value;
i = i->next;
}
if (res == NULL)
res = def;
return res;
}
static inline void add_line(char *name, char *value)
{
int h = hash(name) % HASH_MAX;
lstr *s = malloc(sizeof(lstr));
lstr *p;
s->name = strdup(name);
s->value = strdup(value);
s->next = NULL;
if (ltable[h] == NULL)
ltable[h] = s;
else {
for(p = ltable[h]; p->next != NULL; p = p->next);
p->next = s;
}
}
static char *translate_line(char *line)
{
static char *tok[MAX_TR * 3];
char *l, *p, *p2, *res;
int len = 0, pos = 0, i;
l = line;
while (l != NULL) {
if ((p = strstr(l, TR_START)) == NULL) {
len += strlen((tok[pos++] = l));
break;
}
p2 = strstr(p, TR_END);
if (p2 == NULL)
break;
*p = 0;
*p2 = 0;
len += strlen((tok[pos++] = l));
len += strlen((tok[pos++] = translate_lookup(p + strlen(TR_START))));
l = p2;
l += strlen(TR_END);
}
len++;
if (len > LINE_BUF)
p = malloc(len);
else
p = buf2;
p[0] = 0;
res = p;
for (i = 0; i < pos; i++) {
strcat(p, tok[i]);
p += strlen(tok[i]);
}
return res;
}
/* load and parse language file */
static void load_lang(char *file)
{
FILE *f;
char *b, *name, *value;
f = fopen(file, "r");
while (!feof(f) && (fgets(buf, LINE_BUF - 1, f) != NULL)) {
b = buf;
while (isspace(*b))
b++; /* skip leading spaces */
if (!*b)
continue;
name = b;
if ((b = strstr(name, "=>")) == NULL)
continue; /* separator not found */
value = b + 2;
if (!*value)
continue;
*b = 0;
for (b--; isspace(*b); b--)
*b = 0; /* remove trailing spaces */
while (isspace(*value))
value++; /* skip leading spaces */
for (b = value + strlen(value) - 1; isspace(*b); b--)
*b = 0; /* remove trailing spaces */
if (!*value)
continue;
add_line(name, value);
}
}
int main (int argc, char **argv)
{
FILE *f;
int len, i, done;
char line[LINE_BUF], *tmp, *arg;
glob_t langfiles;
char *lang = NULL;
char *proc = "/usr/bin/haserl";
memset(ltable, 0, HASH_MAX * sizeof(lstr *));
#ifdef NVRAM
if ((lang = nvram_get("language")) != NULL) {
#else
if ((f = fopen("/etc/config/webif", "r")) != NULL) {
int n, i;
while (!feof(f) && (lang == NULL)) {
fgets(line, LINE_BUF - 1, f);
if (strncasecmp(line, "lang", 4) != 0)
goto nomatch;
lang = line + 4;
while (isspace(*lang))
lang++;
if (*lang != '=')
goto nomatch;
lang++;
while (isspace(*lang))
lang++;
for (i = 0; isalpha(lang[i]) && (i < 32); i++);
lang[i] = 0;
continue;
nomatch:
lang = NULL;
}
fclose(f);
#endif
sprintf(buf, "/usr/lib/webif/lang/%s/*.txt", lang);
i = glob(buf, GLOB_ERR | GLOB_MARK, NULL, &langfiles);
if (i == GLOB_NOSPACE || i == GLOB_ABORTED || i == GLOB_NOMATCH) {
// no language files found
} else {
for (i = 0; i < langfiles.gl_pathc; i++) {
load_lang(langfiles.gl_pathv[i]);
}
}
}
/*
* command line options for this parser are stored in argv[1] only.
* filename to be processed is in argv[2]
*/
done = 0;
i = 1;
while (!done) {
if (argv[1] == NULL) {
done = 1;
} else if (strncmp(argv[1], "-e", 2) == 0) {
argv[1] = strchr(argv[1], ' ');
argv[1]++;
if (argv[1] != NULL) {
arg = argv[1];
if ((tmp = strchr(argv[1], ' ')) != NULL) {
*tmp = 0;
argv[1] = &tmp[1];
} else {
argv[1] = NULL;
i++;
}
system(arg);
}
} else if (strncmp(argv[1], "-p", 2) == 0) {
argv[1] = strchr(argv[1], ' ');
argv[1]++;
if (argv[1] != NULL) {
arg = argv[1];
if ((tmp = strchr(argv[1], ' ')) != NULL) {
*tmp = 0;
argv[1] = &tmp[1];
} else {
argv[1] = NULL;
i++;
}
proc = strdup(arg);
}
} else {
done = 1;
}
}
strcpy(buf, proc);
while (argv[i]) {
sprintf(buf + strlen(buf), " %s", argv[i++]);
}
f = popen(buf, "r");
while (!feof(f) && (fgets(buf, LINE_BUF - 1, f)) != NULL) {
fprintf(stdout, "%s", translate_line(buf));
fflush(stdout);
}
return 0;
}