diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7dfbf9f --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +MAKE=gmake + +DEFS= + +SRCS= tvdb.c + +HDRS= + +OBJS= $(SRCS:.c=.o) +CC=gcc +#CC=mipsel-linux-gcc +CFLAGS=-g +INCS= +LIBS=-lsqlite3 +WARN=-pedantic -Wall -W -Wnested-externs -Wpointer-arith -Wno-long-long + +all: tags tvdb + +tvdb: tvdb.o + ${CC} -static-libgcc \ + ${WARN} \ + ${DEFS} \ + ${CFLAGS} -o $@ \ + ${OBJS} \ + ${LIBS} + @echo "Done..." + +install: tvdb + strip tvdb + cp tvdb /mod/bin/tvdb + +clean: + @-touch core + rm -f tvdb tvdb~ core tags ${OBJS} + +tags: + @-ctags *.[ch] 2>> /dev/null + +.c.o: + @echo " $<" + @$(CC) $(CFLAGS) ${WARN} ${DEFS} ${INCS} -c $< -o $@ + +#${OBJS}: ${HDRS} + + diff --git a/tvdb.c b/tvdb.c new file mode 100644 index 0000000..881401a --- /dev/null +++ b/tvdb.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +#include + +#define EXEC(xx) if (sqlite3_exec(db, xx, NULL, NULL, &error) != SQLITE_OK) \ + do { \ + printf("Failed: %s - %s (%s)\n", xx, error, sqlite3_errmsg(db)); \ + sqlite3_free(error); \ + exit(0); \ + } while (0) + +struct episode { + unsigned long id; + char *name; + char *overview; + unsigned long series; + unsigned long episode; +}; + +#define HANDLE(str, c, n) \ + do { \ + if (!strncmp(p, str, (n + 1))) \ + { \ + *p = c; \ + memmove(p + 1, p + (n + 1), l - (p - txt) - (n + 1)); \ + l -= n; \ + txt[l] = '\0'; \ + } \ + } while (0) + +void +unescape(char *txt) +{ + char *p = txt; + int l = strlen(txt); + + //printf("PRE: [%s]\n", txt); + while ((p = strchr(p, '&'))) + { + HANDLE(""", '"', 5); + HANDLE("&", '&', 4); + p++; + } + if ((p = strpbrk(txt, "\n\r"))) + *p = '\0'; + //printf("PST: [%s]\n", txt); + //printf("\n"); +} + +int +main(int argc, char **argv) +{ + char buf[0x400], *p, *q; + struct episode e; + char *error; + sqlite3_stmt *stmt; + sqlite3 *db; + FILE *fp; + + if (argc != 3) + { + printf("Syntax: %s \n", argv[0]); + return 0; + } + + if (!(fp = fopen(argv[1], "r"))) + { + perror("open"); + return 0; + } + + sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); + + if (sqlite3_open_v2(argv[2], &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_PRIVATECACHE, NULL) + != SQLITE_OK) + { + printf("Failed to open database: %s\n", sqlite3_errmsg(db)); + return 0; + } + + EXEC("pragma journal_mode = off"); + EXEC("pragma synchronous = off"); + EXEC( + "create table if not exists episode(" + "[episode_id] integer primary key, " + "[series] integer, " + "[episode] integer, " + "[name] text, " + "[overview] text" + ")" + ); + + if (sqlite3_prepare_v2(db, + "insert or replace into episode " + "values(?,?,?,?,?)", + -1, &stmt, NULL) != SQLITE_OK) + { + fprintf(stderr, + "Problem preparing statement %s", sqlite3_errmsg(db)); + exit(1); + } + + while (fgets(buf, sizeof(buf), fp)) + { + p = buf; + while ((*p++) != '<') + ; + if (!strncmp(p, "Episode>", 8)) + { + /* New episode */ + memset(&e, '\0', sizeof(e)); + } + + if (!strncmp(p, "id>", 3)) + e.id = strtoul(p + 3, (char **)NULL, 10); + if (!strncmp(p, "Combined_episodenumber>", 23)) + e.episode = strtoul(p + 23, (char **)NULL, 10); + if (!strncmp(p, "Combined_season>", 16)) + e.series = strtoul(p + 16, (char **)NULL, 10); + if (!strncmp(p, "EpisodeName>", 12)) + { + e.name = strdup(p + 12); + if ((q = strstr(e.name, ""))) + *q = '\0'; + unescape(e.name); + } + if (!strncmp(p, "Overview>", 9)) + { + e.overview = strdup(p + 9); + if ((q = strstr(e.overview, ""))) + *q = '\0'; + unescape(e.overview); + } + + if (!strncmp(p, "/Episode>", 8)) + { + /* End of episode */ + if (e.id) + { + sqlite3_bind_int(stmt, 1, e.id); + sqlite3_bind_int(stmt, 2, e.series); + sqlite3_bind_int(stmt, 3, e.episode); + sqlite3_bind_text(stmt, 4, e.name, -1, NULL); + sqlite3_bind_text(stmt, 5, e.overview, + -1, NULL); + sqlite3_step(stmt); + sqlite3_reset(stmt); + sqlite3_clear_bindings(stmt); + } + if (e.name) free(e.name); + if (e.overview) free(e.overview); + } + } + + fclose(fp); + sqlite3_finalize(stmt); + sqlite3_close(db); + + return 0; +} +